Separated Crafting job into a worker thread.
Crafting calculation can be canceled. Hooked up a crafting calculation launch and the confirmation GUI.
This commit is contained in:
parent
0a18f2d926
commit
32ee57c3a9
11 changed files with 320 additions and 44 deletions
46
client/gui/implementations/GuiCraftConfirm.java
Normal file
46
client/gui/implementations/GuiCraftConfirm.java
Normal file
|
@ -0,0 +1,46 @@
|
|||
package appeng.client.gui.implementations;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import appeng.api.storage.ITerminalHost;
|
||||
import appeng.client.gui.AEBaseGui;
|
||||
import appeng.container.implementations.ContainerCraftConfirm;
|
||||
import appeng.core.localization.GuiText;
|
||||
|
||||
public class GuiCraftConfirm extends AEBaseGui
|
||||
{
|
||||
|
||||
public GuiCraftConfirm(InventoryPlayer inventoryPlayer, ITerminalHost te) {
|
||||
super( new ContainerCraftConfirm( inventoryPlayer, te ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui()
|
||||
{
|
||||
super.initGui();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton btn)
|
||||
{
|
||||
super.actionPerformed( btn );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBG(int offsetX, int offsetY, int mouseX, int mouseY)
|
||||
{
|
||||
bindTexture( "guis/craftingreport.png" );
|
||||
this.drawTexturedModalRect( offsetX, offsetY, 0, 0, xSize, ySize );
|
||||
}
|
||||
|
||||
protected String getBackground()
|
||||
{
|
||||
return "guis/craftingreport.png";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawFG(int offsetX, int offsetY, int mouseX, int mouseY)
|
||||
{
|
||||
fontRendererObj.drawString( GuiText.ConfirmCrafting.getLocal(), 8, 6, 4210752 );
|
||||
}
|
||||
}
|
98
container/implementations/ContainerCraftConfirm.java
Normal file
98
container/implementations/ContainerCraftConfirm.java
Normal file
|
@ -0,0 +1,98 @@
|
|||
package appeng.container.implementations;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.inventory.ICrafting;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.world.World;
|
||||
import appeng.api.config.SecurityPermissions;
|
||||
import appeng.api.networking.IGrid;
|
||||
import appeng.api.networking.security.BaseActionSource;
|
||||
import appeng.api.networking.security.IActionHost;
|
||||
import appeng.api.networking.security.PlayerSource;
|
||||
import appeng.api.storage.ITerminalHost;
|
||||
import appeng.container.AEBaseContainer;
|
||||
import appeng.core.AELog;
|
||||
import appeng.crafting.CraftingJob;
|
||||
import appeng.crafting.ICraftingHost;
|
||||
|
||||
public class ContainerCraftConfirm extends AEBaseContainer implements ICraftingHost
|
||||
{
|
||||
|
||||
ITerminalHost priHost;
|
||||
public Future<CraftingJob> job;
|
||||
public CraftingJob result;
|
||||
|
||||
public ContainerCraftConfirm(InventoryPlayer ip, ITerminalHost te) {
|
||||
super( ip, te );
|
||||
priHost = te;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detectAndSendChanges()
|
||||
{
|
||||
super.detectAndSendChanges();
|
||||
if ( job != null && job.isDone() )
|
||||
{
|
||||
try
|
||||
{
|
||||
result = job.get();
|
||||
AELog.info( "Job info is ready!" );
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
getPlayerInv().player.addChatMessage( new ChatComponentText( "Error: " + e.toString() ) );
|
||||
AELog.error( e );
|
||||
this.isContainerValid = false;
|
||||
result = null;
|
||||
}
|
||||
|
||||
job = null;
|
||||
}
|
||||
verifyPermissions( SecurityPermissions.CRAFT, false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContainerClosed(EntityPlayer par1EntityPlayer)
|
||||
{
|
||||
super.onContainerClosed( par1EntityPlayer );
|
||||
if ( job != null )
|
||||
{
|
||||
job.cancel( true );
|
||||
job = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCraftingFromCrafters(ICrafting c)
|
||||
{
|
||||
super.removeCraftingFromCrafters( c );
|
||||
if ( job != null )
|
||||
{
|
||||
job.cancel( true );
|
||||
job = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGrid getGrid()
|
||||
{
|
||||
IActionHost h = ((IActionHost) this.getTarget());
|
||||
return h.getActionableNode().getGrid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld()
|
||||
{
|
||||
return getPlayerInv().player.worldObj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseActionSource getActionSrc()
|
||||
{
|
||||
return new PlayerSource( getPlayerInv().player, (IActionHost) getTarget() );
|
||||
}
|
||||
|
||||
}
|
|
@ -30,7 +30,7 @@ public enum GuiText
|
|||
|
||||
StoredPower, MaxPower, RequiredPower, Efficiency, InWorldCrafting, inWorldFluix, inWorldPurificationCertus, inWorldPurificationNether, inWorldPurificationFluix, inWorldSingularity, ChargedQuartz,
|
||||
|
||||
OfSecondOutput, NoSecondOutput, RFTunnel, Stores, Next, SelectAmount, Lumen, Empty;
|
||||
OfSecondOutput, NoSecondOutput, RFTunnel, Stores, Next, SelectAmount, Lumen, Empty, ConfirmCrafting;
|
||||
|
||||
String root;
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import appeng.container.implementations.ContainerCellWorkbench;
|
|||
import appeng.container.implementations.ContainerChest;
|
||||
import appeng.container.implementations.ContainerCondenser;
|
||||
import appeng.container.implementations.ContainerCraftAmount;
|
||||
import appeng.container.implementations.ContainerCraftConfirm;
|
||||
import appeng.container.implementations.ContainerCraftingTerm;
|
||||
import appeng.container.implementations.ContainerDrive;
|
||||
import appeng.container.implementations.ContainerFormationPlane;
|
||||
|
@ -150,7 +151,9 @@ public enum GuiBridge implements IGuiHandler
|
|||
|
||||
GUI_MAC(ContainerMAC.class, TileMolecularAssembler.class, WORLD, null),
|
||||
|
||||
GUI_CRAFTING_AMOUNT(ContainerCraftAmount.class, ITerminalHost.class, ITEM_OR_WORLD, SecurityPermissions.CRAFT);
|
||||
GUI_CRAFTING_AMOUNT(ContainerCraftAmount.class, ITerminalHost.class, ITEM_OR_WORLD, SecurityPermissions.CRAFT),
|
||||
|
||||
GUI_CRAFTING_CONFIRM(ContainerCraftConfirm.class, ITerminalHost.class, ITEM_OR_WORLD, SecurityPermissions.CRAFT);
|
||||
|
||||
private Class Tile;
|
||||
private Class Gui;
|
||||
|
|
|
@ -4,9 +4,13 @@ import io.netty.buffer.ByteBuf;
|
|||
import io.netty.buffer.Unpooled;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
|
@ -14,18 +18,38 @@ import appeng.api.networking.IGrid;
|
|||
import appeng.api.networking.IGridHost;
|
||||
import appeng.api.networking.IGridNode;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.container.ContainerOpenContext;
|
||||
import appeng.container.implementations.ContainerCraftAmount;
|
||||
import appeng.container.implementations.ContainerCraftConfirm;
|
||||
import appeng.core.AELog;
|
||||
import appeng.core.sync.AppEngPacket;
|
||||
import appeng.core.sync.GuiBridge;
|
||||
import appeng.core.sync.network.INetworkInfo;
|
||||
import appeng.crafting.CraftingJob;
|
||||
import appeng.me.cache.CraftingCache;
|
||||
import appeng.util.Platform;
|
||||
import appeng.util.item.AEItemStack;
|
||||
|
||||
public class PacketCraftRequest extends AppEngPacket
|
||||
{
|
||||
|
||||
final public IAEItemStack slotItem;
|
||||
final public static ExecutorService craftingPool;
|
||||
|
||||
static
|
||||
{
|
||||
ThreadFactory factory = new ThreadFactory() {
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable ar)
|
||||
{
|
||||
return new Thread( ar, "AE Crafting Calculator" );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
craftingPool = Executors.newCachedThreadPool( factory );
|
||||
}
|
||||
|
||||
// automatic.
|
||||
public PacketCraftRequest(ByteBuf stream) throws IOException {
|
||||
|
@ -56,6 +80,20 @@ public class PacketCraftRequest extends AppEngPacket
|
|||
{
|
||||
CraftingJob cj = new CraftingJob( cca, slotItem, Actionable.SIMULATE );
|
||||
|
||||
ContainerOpenContext context = cca.openContext;
|
||||
if ( context != null )
|
||||
{
|
||||
TileEntity te = context.w.getTileEntity( context.x, context.y, context.z );
|
||||
Platform.openGUI( player, te, cca.openContext.side, GuiBridge.GUI_CRAFTING_CONFIRM );
|
||||
|
||||
if ( player.openContainer instanceof ContainerCraftConfirm )
|
||||
{
|
||||
ContainerCraftConfirm ccc = (ContainerCraftConfirm) player.openContainer;
|
||||
ccc.job = craftingPool.submit( cj, cj );
|
||||
cca.detectAndSendChanges();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
|
|
|
@ -8,6 +8,7 @@ import net.minecraft.nbt.NBTTagCompound;
|
|||
import appeng.api.AEApi;
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
||||
import appeng.api.networking.security.BaseActionSource;
|
||||
import appeng.api.networking.storage.IStorageGrid;
|
||||
import appeng.api.storage.data.IAEItemStack;
|
||||
import appeng.api.storage.data.IItemList;
|
||||
|
@ -17,7 +18,7 @@ import appeng.util.Platform;
|
|||
|
||||
import com.google.common.base.Stopwatch;
|
||||
|
||||
public class CraftingJob
|
||||
public class CraftingJob implements Runnable
|
||||
{
|
||||
|
||||
IAEItemStack output;
|
||||
|
@ -28,10 +29,17 @@ public class CraftingJob
|
|||
|
||||
ICraftingHost jobHost;
|
||||
|
||||
boolean simulate = false;
|
||||
final MECraftingInventory original;
|
||||
|
||||
public CraftingTreeNode tree;
|
||||
private BaseActionSource actionSrc;
|
||||
|
||||
public CraftingJob(ICraftingHost host, NBTTagCompound data) {
|
||||
jobHost = host;
|
||||
storage = AEApi.instance().storage().createItemList();
|
||||
prophecies = new HashSet();
|
||||
original = null;
|
||||
}
|
||||
|
||||
public CraftingJob(ICraftingHost host, IAEItemStack what, Actionable mode) {
|
||||
|
@ -39,41 +47,13 @@ public class CraftingJob
|
|||
output = what.copy();
|
||||
storage = AEApi.instance().storage().createItemList();
|
||||
prophecies = new HashSet();
|
||||
actionSrc = host.getActionSrc();
|
||||
|
||||
CraftingCache cc = host.getGrid().getCache( CraftingCache.class );
|
||||
IStorageGrid sg = host.getGrid().getCache( IStorageGrid.class );
|
||||
original = new MECraftingInventory( sg.getItemInventory(), false, false, false );
|
||||
|
||||
IItemList<IAEItemStack> missing = AEApi.instance().storage().createItemList();
|
||||
|
||||
MECraftingInventory meci = new MECraftingInventory( sg.getItemInventory(), true, false, true );
|
||||
meci.ignore( what );
|
||||
|
||||
CraftingTreeNode tree = getCraftingTree( cc, what );
|
||||
|
||||
try
|
||||
{
|
||||
Stopwatch timer = Stopwatch.createStarted();
|
||||
tree.request( meci, what.getStackSize(), host.getActionSrc() );
|
||||
tree.dive( this );
|
||||
|
||||
for (String s : opsAndMultiplier.keySet())
|
||||
{
|
||||
twoIntegers ti = opsAndMultiplier.get( s );
|
||||
AELog.info( s + " * " + ti.times + " = " + (ti.perOp * ti.times) );
|
||||
}
|
||||
|
||||
AELog.info( "-------------" + timer.elapsed( TimeUnit.MILLISECONDS ) + "ms" );
|
||||
// if ( mode == Actionable.MODULATE )
|
||||
// meci.moveItemsToStorage( storage );
|
||||
}
|
||||
catch (CraftBranchFailure e)
|
||||
{
|
||||
AELog.error( e );
|
||||
}
|
||||
catch (CraftingCalculationFailure f)
|
||||
{
|
||||
AELog.error( f );
|
||||
}
|
||||
tree = getCraftingTree( cc, what );
|
||||
}
|
||||
|
||||
private CraftingTreeNode getCraftingTree(CraftingCache cc, IAEItemStack what)
|
||||
|
@ -86,16 +66,25 @@ public class CraftingJob
|
|||
|
||||
}
|
||||
|
||||
IItemList<IAEItemStack> crafting = AEApi.instance().storage().createItemList();
|
||||
IItemList<IAEItemStack> missing = AEApi.instance().storage().createItemList();
|
||||
|
||||
public void addTask(IAEItemStack what, long crafts, ICraftingPatternDetails details, int depth)
|
||||
{
|
||||
if ( crafts > 0 )
|
||||
{
|
||||
postOp( "new task: " + Platform.getItemDisplayName( what ) + " x " + what.getStackSize(), what.getStackSize(), crafts );
|
||||
what = what.copy();
|
||||
what.setStackSize( what.getStackSize() * crafts );
|
||||
crafting.add( what );
|
||||
}
|
||||
}
|
||||
|
||||
public void addMissing(IAEItemStack what)
|
||||
{
|
||||
what = what.copy();
|
||||
missing.add( what );
|
||||
|
||||
postOp( "required material: " + Platform.getItemDisplayName( what ), 1, what.getStackSize() );
|
||||
}
|
||||
|
||||
|
@ -117,4 +106,76 @@ public class CraftingJob
|
|||
ti.perOp = stackSize;
|
||||
ti.times += crafts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
Stopwatch timer = Stopwatch.createStarted();
|
||||
|
||||
MECraftingInventory meci = new MECraftingInventory( original, true, false, true );
|
||||
meci.ignore( output );
|
||||
|
||||
tree.request( meci, output.getStackSize(), actionSrc );
|
||||
tree.dive( this );
|
||||
|
||||
for (String s : opsAndMultiplier.keySet())
|
||||
{
|
||||
twoIntegers ti = opsAndMultiplier.get( s );
|
||||
AELog.info( s + " * " + ti.times + " = " + (ti.perOp * ti.times) );
|
||||
}
|
||||
|
||||
AELog.info( "------------- real" + timer.elapsed( TimeUnit.MILLISECONDS ) + "ms" );
|
||||
// if ( mode == Actionable.MODULATE )
|
||||
// meci.moveItemsToStorage( storage );
|
||||
}
|
||||
catch (CraftBranchFailure e)
|
||||
{
|
||||
simulate = true;
|
||||
|
||||
try
|
||||
{
|
||||
Stopwatch timer = Stopwatch.createStarted();
|
||||
MECraftingInventory meci = new MECraftingInventory( original, true, false, true );
|
||||
meci.ignore( output );
|
||||
|
||||
tree.setSimulate();
|
||||
tree.request( meci, output.getStackSize(), actionSrc );
|
||||
tree.dive( this );
|
||||
|
||||
for (String s : opsAndMultiplier.keySet())
|
||||
{
|
||||
twoIntegers ti = opsAndMultiplier.get( s );
|
||||
AELog.info( s + " * " + ti.times + " = " + (ti.perOp * ti.times) );
|
||||
}
|
||||
|
||||
AELog.info( "------------- simulate" + timer.elapsed( TimeUnit.MILLISECONDS ) + "ms" );
|
||||
}
|
||||
catch (CraftBranchFailure e1)
|
||||
{
|
||||
AELog.error( e1 );
|
||||
}
|
||||
catch (CraftingCalculationFailure f)
|
||||
{
|
||||
AELog.error( f );
|
||||
}
|
||||
catch (InterruptedException e1)
|
||||
{
|
||||
AELog.info( "Crafting calculation canceled." );
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (CraftingCalculationFailure f)
|
||||
{
|
||||
AELog.error( f );
|
||||
}
|
||||
catch (InterruptedException e1)
|
||||
{
|
||||
AELog.info( "Crafting calculation canceled." );
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,14 @@ public class CraftingTreeNode
|
|||
boolean cannotUse = false;
|
||||
long missing = 0;
|
||||
|
||||
boolean sim;
|
||||
|
||||
public CraftingTreeNode(CraftingCache cc, CraftingJob job, IAEItemStack wat, CraftingTreeProcess par, int slot, int depth) {
|
||||
what = wat;
|
||||
parent = par;
|
||||
this.slot = slot;
|
||||
this.world = job.jobHost.getWorld();
|
||||
sim = false;
|
||||
|
||||
for (ICraftingPatternDetails details : cc.getCraftingFor( what ))// in order.
|
||||
{
|
||||
|
@ -62,8 +65,11 @@ public class CraftingTreeNode
|
|||
return parent.notRecurive( details );
|
||||
}
|
||||
|
||||
public IAEItemStack request(MECraftingInventory inv, long l, BaseActionSource src) throws CraftBranchFailure
|
||||
public IAEItemStack request(MECraftingInventory inv, long l, BaseActionSource src) throws CraftBranchFailure, InterruptedException
|
||||
{
|
||||
if ( Thread.interrupted() )
|
||||
throw new InterruptedException();
|
||||
|
||||
what.setStackSize( l );
|
||||
if ( slot >= 0 && parent != null && parent.details.isCraftable() )
|
||||
{
|
||||
|
@ -153,9 +159,13 @@ public class CraftingTreeNode
|
|||
}
|
||||
}
|
||||
|
||||
missing += l;
|
||||
return what;
|
||||
// throw new CraftBranchFailure( what, l );
|
||||
if ( sim )
|
||||
{
|
||||
missing += l;
|
||||
return what;
|
||||
}
|
||||
|
||||
throw new CraftBranchFailure( what, l );
|
||||
}
|
||||
|
||||
public void dive(CraftingJob job)
|
||||
|
@ -167,4 +177,13 @@ public class CraftingTreeNode
|
|||
for (CraftingTreeProcess pro : nodes)
|
||||
pro.dive( job );
|
||||
}
|
||||
|
||||
public void setSimulate()
|
||||
{
|
||||
sim = true;
|
||||
missing = 0;
|
||||
|
||||
for (CraftingTreeProcess pro : nodes)
|
||||
pro.setSimulate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,8 +86,11 @@ public class CraftingTreeProcess
|
|||
throw new RuntimeException( "Crafting Tree construction failed." );
|
||||
}
|
||||
|
||||
public void request(MECraftingInventory inv, long i, BaseActionSource src) throws CraftBranchFailure
|
||||
public void request(MECraftingInventory inv, long i, BaseActionSource src) throws CraftBranchFailure, InterruptedException
|
||||
{
|
||||
if ( Thread.interrupted() )
|
||||
throw new InterruptedException();
|
||||
|
||||
// request and remove inputs...
|
||||
for (Entry<CraftingTreeNode, Long> entry : nodes.entrySet())
|
||||
{
|
||||
|
@ -129,4 +132,12 @@ public class CraftingTreeProcess
|
|||
for (CraftingTreeNode pro : nodes.keySet())
|
||||
pro.dive( job );
|
||||
}
|
||||
|
||||
public void setSimulate()
|
||||
{
|
||||
crafts = 0;
|
||||
|
||||
for (CraftingTreeNode pro : nodes.keySet())
|
||||
pro.setSimulate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,11 +195,10 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||
condencedOutputs[offset++] = io;
|
||||
}
|
||||
|
||||
public boolean isValidItemForSlot(int slotIndex, ItemStack i, World w)
|
||||
synchronized public boolean isValidItemForSlot(int slotIndex, ItemStack i, World w)
|
||||
{
|
||||
if ( isCrafting == false )
|
||||
{
|
||||
|
||||
throw new RuntimeException( "Only crafting recipes supported." );
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ public class CraftingCPUCalculator extends MBCalculator
|
|||
@Override
|
||||
public void disconnect()
|
||||
{
|
||||
tqb.disconnect();
|
||||
tqb.disconnect( true );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -62,12 +62,13 @@ public class TileCraftingTile extends AENetworkTile implements IAEMultiBlock, IP
|
|||
}
|
||||
|
||||
@Override
|
||||
public void disconnect()
|
||||
public void disconnect(boolean update)
|
||||
{
|
||||
if ( clust != null )
|
||||
{
|
||||
clust.destroy();
|
||||
updateMeta();
|
||||
if ( update )
|
||||
updateMeta();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue