diff --git a/container/implementations/ContainerCraftAmount.java b/container/implementations/ContainerCraftAmount.java index 2115b1d06..c4585b812 100644 --- a/container/implementations/ContainerCraftAmount.java +++ b/container/implementations/ContainerCraftAmount.java @@ -12,10 +12,9 @@ import appeng.api.storage.ITerminalHost; import appeng.api.storage.data.IAEItemStack; import appeng.container.AEBaseContainer; import appeng.container.slot.SlotInaccessable; -import appeng.crafting.ICraftingHost; import appeng.tile.inventory.AppEngInternalInventory; -public class ContainerCraftAmount extends AEBaseContainer implements ICraftingHost +public class ContainerCraftAmount extends AEBaseContainer { ITerminalHost priHost; @@ -38,7 +37,6 @@ public class ContainerCraftAmount extends AEBaseContainer implements ICraftingHo verifyPermissions( SecurityPermissions.CRAFT, false ); } - @Override public IGrid getGrid() { IActionHost h = ((IActionHost) this.getTarget()); @@ -50,7 +48,6 @@ public class ContainerCraftAmount extends AEBaseContainer implements ICraftingHo return getPlayerInv().player.worldObj; } - @Override public BaseActionSource getActionSrc() { return new PlayerSource( getPlayerInv().player, (IActionHost) getTarget() ); diff --git a/container/implementations/ContainerCraftConfirm.java b/container/implementations/ContainerCraftConfirm.java index 1d8c923a3..94a4d10b9 100644 --- a/container/implementations/ContainerCraftConfirm.java +++ b/container/implementations/ContainerCraftConfirm.java @@ -13,6 +13,8 @@ import appeng.api.AEApi; import appeng.api.config.Actionable; import appeng.api.config.SecurityPermissions; import appeng.api.networking.IGrid; +import appeng.api.networking.crafting.ICraftingGrid; +import appeng.api.networking.crafting.ICraftingJob; import appeng.api.networking.security.BaseActionSource; import appeng.api.networking.security.IActionHost; import appeng.api.networking.security.PlayerSource; @@ -26,16 +28,13 @@ import appeng.container.guisync.GuiSync; import appeng.core.AELog; import appeng.core.sync.network.NetworkHandler; import appeng.core.sync.packets.PacketMEInventoryUpdate; -import appeng.crafting.CraftingJob; -import appeng.crafting.ICraftingHost; -import appeng.me.cache.CraftingCache; -public class ContainerCraftConfirm extends AEBaseContainer implements ICraftingHost +public class ContainerCraftConfirm extends AEBaseContainer { ITerminalHost priHost; - public Future job; - public CraftingJob result; + public Future job; + public ICraftingJob result; @GuiSync(0) public long bytesUsed; @@ -86,7 +85,7 @@ public class ContainerCraftConfirm extends AEBaseContainer implements ICraftingH PacketMEInventoryUpdate c = result.isSimulation() ? new PacketMEInventoryUpdate( (byte) 2 ) : null; IItemList plan = AEApi.instance().storage().createItemList(); - result.tree.getPlan( plan ); + result.populatePlan( plan ); bytesUsed = result.getByteTotal(); @@ -162,7 +161,7 @@ public class ContainerCraftConfirm extends AEBaseContainer implements ICraftingH { if ( result != null && simulation == false ) { - CraftingCache cc = getGrid().getCache( CraftingCache.class ); + ICraftingGrid cc = getGrid().getCache( ICraftingGrid.class ); cc.submitJob( result, null, getActionSrc() ); this.isContainerValid = false; } @@ -190,7 +189,6 @@ public class ContainerCraftConfirm extends AEBaseContainer implements ICraftingH } } - @Override public IGrid getGrid() { IActionHost h = ((IActionHost) this.getTarget()); @@ -202,7 +200,6 @@ public class ContainerCraftConfirm extends AEBaseContainer implements ICraftingH return getPlayerInv().player.worldObj; } - @Override public BaseActionSource getActionSrc() { return new PlayerSource( getPlayerInv().player, (IActionHost) getTarget() ); diff --git a/core/Registration.java b/core/Registration.java index 0a74a52d5..7f527086e 100644 --- a/core/Registration.java +++ b/core/Registration.java @@ -21,6 +21,7 @@ import appeng.api.features.IRecipeHandlerRegistry; import appeng.api.features.IWirelessTermHandler; import appeng.api.movable.IMovableRegistry; import appeng.api.networking.IGridCacheRegistry; +import appeng.api.networking.crafting.ICraftingGrid; import appeng.api.networking.energy.IEnergyGrid; import appeng.api.networking.pathing.IPathingGrid; import appeng.api.networking.security.ISecurityGrid; @@ -123,7 +124,7 @@ import appeng.items.tools.quartz.ToolQuartzPickaxe; import appeng.items.tools.quartz.ToolQuartzSpade; import appeng.items.tools.quartz.ToolQuartzSword; import appeng.items.tools.quartz.ToolQuartzWrench; -import appeng.me.cache.CraftingCache; +import appeng.me.cache.CraftingGridCache; import appeng.me.cache.EnergyGridCache; import appeng.me.cache.GridStorageCache; import appeng.me.cache.P2PCache; @@ -523,7 +524,7 @@ public class Registration gcr.registerGridCache( P2PCache.class, P2PCache.class ); gcr.registerGridCache( ISpatialCache.class, SpatialPylonCache.class ); gcr.registerGridCache( ISecurityGrid.class, SecurityCache.class ); - gcr.registerGridCache( CraftingCache.class, CraftingCache.class ); + gcr.registerGridCache( ICraftingGrid.class, CraftingGridCache.class ); AEApi.instance().registries().externalStorage().addExternalStorageInterface( new AEExternalHandler() ); @@ -664,9 +665,9 @@ public class Registration private void registerSpatial(boolean force) { - if ( ! AEConfig.instance.isFeatureEnabled( AEFeature.SpatialIO ) ) + if ( !AEConfig.instance.isFeatureEnabled( AEFeature.SpatialIO ) ) return; - + AEConfig config = AEConfig.instance; if ( storageBiome == null ) @@ -675,8 +676,8 @@ public class Registration { config.storageBiomeID = Platform.findEmpty( BiomeGenBase.getBiomeGenArray() ); if ( config.storageBiomeID == -1 ) - throw new RuntimeException("Biome Array is full, please free up some Biome ID's or disable spatial."); - + throw new RuntimeException( "Biome Array is full, please free up some Biome ID's or disable spatial." ); + storageBiome = new BiomeGenStorage( config.storageBiomeID ); config.save(); } diff --git a/core/sync/packets/PacketCraftRequest.java b/core/sync/packets/PacketCraftRequest.java index fc098c34e..f53da5c7b 100644 --- a/core/sync/packets/PacketCraftRequest.java +++ b/core/sync/packets/PacketCraftRequest.java @@ -4,19 +4,18 @@ 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 java.util.concurrent.Future; 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; import appeng.api.networking.IGrid; import appeng.api.networking.IGridHost; import appeng.api.networking.IGridNode; +import appeng.api.networking.crafting.ICraftingGrid; +import appeng.api.networking.crafting.ICraftingJob; import appeng.api.storage.data.IAEItemStack; import appeng.container.ContainerOpenContext; import appeng.container.implementations.ContainerCraftAmount; @@ -25,7 +24,6 @@ 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.util.Platform; import appeng.util.item.AEItemStack; @@ -34,22 +32,6 @@ public class PacketCraftRequest extends AppEngPacket final public IAEItemStack slotItem; final public boolean heldShift; - 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 { @@ -75,9 +57,12 @@ public class PacketCraftRequest extends AppEngPacket if ( g == null ) return; + Future futureJob = null; + try { - CraftingJob cj = new CraftingJob( cca.getWorld(), cca, slotItem, Actionable.SIMULATE ); + ICraftingGrid cg = g.getCache( ICraftingGrid.class ); + futureJob = cg.beginCraftingJob( cca.getWorld(), cca.getGrid(), cca.getActionSrc(), slotItem, null ); ContainerOpenContext context = cca.openContext; if ( context != null ) @@ -89,7 +74,7 @@ public class PacketCraftRequest extends AppEngPacket { ContainerCraftConfirm ccc = (ContainerCraftConfirm) player.openContainer; ccc.autoStart = heldShift; - ccc.job = craftingPool.submit( cj, cj ); + ccc.job = futureJob; cca.detectAndSendChanges(); } } @@ -97,6 +82,8 @@ public class PacketCraftRequest extends AppEngPacket } catch (Throwable e) { + if ( futureJob != null ) + futureJob.cancel( true ); AELog.error( e ); } } diff --git a/crafting/CraftingJob.java b/crafting/CraftingJob.java index 86d2a4623..6e21999d4 100644 --- a/crafting/CraftingJob.java +++ b/crafting/CraftingJob.java @@ -8,6 +8,10 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import appeng.api.AEApi; import appeng.api.config.Actionable; +import appeng.api.networking.IGrid; +import appeng.api.networking.crafting.ICraftingCallback; +import appeng.api.networking.crafting.ICraftingGrid; +import appeng.api.networking.crafting.ICraftingJob; import appeng.api.networking.crafting.ICraftingPatternDetails; import appeng.api.networking.security.BaseActionSource; import appeng.api.networking.storage.IStorageGrid; @@ -15,12 +19,11 @@ import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IItemList; import appeng.core.AELog; import appeng.hooks.TickHandler; -import appeng.me.cache.CraftingCache; import appeng.util.Platform; import com.google.common.base.Stopwatch; -public class CraftingJob implements Runnable +public class CraftingJob implements Runnable, ICraftingJob { IAEItemStack output; @@ -29,14 +32,14 @@ public class CraftingJob implements Runnable HashSet prophecies; - ICraftingHost jobHost; - boolean simulate = false; final MECraftingInventory original; final MECraftingInventory availableCheck; public CraftingTreeNode tree; private BaseActionSource actionSrc; + private ICraftingCallback callback; + long bytes = 0; World world; @@ -45,8 +48,7 @@ public class CraftingJob implements Runnable return output; } - public CraftingJob(World w, ICraftingHost host, NBTTagCompound data) { - jobHost = host; + public CraftingJob(World w, NBTTagCompound data) { world = wrapWorld( w ); storage = AEApi.instance().storage().createItemList(); prophecies = new HashSet(); @@ -59,16 +61,16 @@ public class CraftingJob implements Runnable return availableCheck.extractItems( available, Actionable.MODULATE, this.actionSrc ); } - public CraftingJob(World w, ICraftingHost host, IAEItemStack what, Actionable mode) { - jobHost = host; + public CraftingJob(World w, IGrid grid, BaseActionSource actionSrc, IAEItemStack what, ICraftingCallback callback) { world = wrapWorld( w ); output = what.copy(); storage = AEApi.instance().storage().createItemList(); prophecies = new HashSet(); - actionSrc = host.getActionSrc(); + this.actionSrc = actionSrc; - CraftingCache cc = host.getGrid().getCache( CraftingCache.class ); - IStorageGrid sg = host.getGrid().getCache( IStorageGrid.class ); + this.callback = callback; + ICraftingGrid cc = grid.getCache( ICraftingGrid.class ); + IStorageGrid sg = grid.getCache( IStorageGrid.class ); original = new MECraftingInventory( sg.getItemInventory(), false, false, false ); availableCheck = new MECraftingInventory( sg.getItemInventory(), false, false, false ); tree = getCraftingTree( cc, what ); @@ -79,7 +81,7 @@ public class CraftingJob implements Runnable return w; } - private CraftingTreeNode getCraftingTree(CraftingCache cc, IAEItemStack what) + private CraftingTreeNode getCraftingTree(ICraftingGrid cc, IAEItemStack what) { return new CraftingTreeNode( cc, this, what, null, -1, 0 ); } @@ -225,6 +227,9 @@ public class CraftingJob implements Runnable public void finish() { + if ( callback != null ) + callback.calculationComplete( this ); + synchronized (monitor) { running = false; @@ -339,4 +344,11 @@ public class CraftingJob implements Runnable bytes += crafts; } + @Override + public void populatePlan(IItemList plan) + { + if ( tree != null ) + tree.getPlan( plan ); + } + } diff --git a/crafting/CraftingTreeNode.java b/crafting/CraftingTreeNode.java index 242b3f92b..e745088d3 100644 --- a/crafting/CraftingTreeNode.java +++ b/crafting/CraftingTreeNode.java @@ -6,11 +6,11 @@ import net.minecraft.world.World; import appeng.api.AEApi; import appeng.api.config.Actionable; import appeng.api.config.FuzzyMode; +import appeng.api.networking.crafting.ICraftingGrid; import appeng.api.networking.crafting.ICraftingPatternDetails; import appeng.api.networking.security.BaseActionSource; import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IItemList; -import appeng.me.cache.CraftingCache; import appeng.me.cluster.implementations.CraftingCPUCluster; public class CraftingTreeNode @@ -39,7 +39,7 @@ public class CraftingTreeNode boolean sim; - public CraftingTreeNode(CraftingCache cc, CraftingJob job, IAEItemStack wat, CraftingTreeProcess par, int slot, int depth) { + public CraftingTreeNode(ICraftingGrid cc, CraftingJob job, IAEItemStack wat, CraftingTreeProcess par, int slot, int depth) { what = wat; parent = par; this.slot = slot; diff --git a/crafting/CraftingTreeProcess.java b/crafting/CraftingTreeProcess.java index 2b6a39f5a..9bebe1c8a 100644 --- a/crafting/CraftingTreeProcess.java +++ b/crafting/CraftingTreeProcess.java @@ -10,12 +10,12 @@ import net.minecraft.world.World; import net.minecraft.world.WorldServer; import appeng.api.AEApi; import appeng.api.config.Actionable; +import appeng.api.networking.crafting.ICraftingGrid; import appeng.api.networking.crafting.ICraftingPatternDetails; import appeng.api.networking.security.BaseActionSource; import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IItemList; import appeng.container.ContainerNull; -import appeng.me.cache.CraftingCache; import appeng.me.cluster.implementations.CraftingCPUCluster; import appeng.util.Platform; import cpw.mods.fml.common.FMLCommonHandler; @@ -38,7 +38,7 @@ public class CraftingTreeProcess Map nodes = new HashMap(); public boolean possible = true; - public CraftingTreeProcess(CraftingCache cc, CraftingJob job, ICraftingPatternDetails details, CraftingTreeNode craftingTreeNode, int depth, World world) { + public CraftingTreeProcess(ICraftingGrid cc, CraftingJob job, ICraftingPatternDetails details, CraftingTreeNode craftingTreeNode, int depth, World world) { parent = craftingTreeNode; this.details = details; this.job = job; diff --git a/crafting/ICraftingHost.java b/crafting/ICraftingHost.java deleted file mode 100644 index 015286a81..000000000 --- a/crafting/ICraftingHost.java +++ /dev/null @@ -1,21 +0,0 @@ -package appeng.crafting; - -import appeng.api.networking.IGrid; -import appeng.api.networking.security.BaseActionSource; - -public interface ICraftingHost -{ - - /** - * Get Crafting cache for the host. - */ - IGrid getGrid(); - - /** - * get source of moving items around. - * - * @return {@link BaseActionSource} of host. - */ - BaseActionSource getActionSrc(); - -} diff --git a/me/cache/CraftingCache.java b/me/cache/CraftingGridCache.java similarity index 75% rename from me/cache/CraftingCache.java rename to me/cache/CraftingGridCache.java index f1c2fc39b..c46ea0d42 100644 --- a/me/cache/CraftingCache.java +++ b/me/cache/CraftingGridCache.java @@ -4,16 +4,25 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; +import net.minecraft.world.World; import appeng.api.config.AccessRestriction; import appeng.api.config.Actionable; import appeng.api.networking.IGrid; -import appeng.api.networking.IGridCache; import appeng.api.networking.IGridHost; import appeng.api.networking.IGridNode; import appeng.api.networking.IGridStorage; +import appeng.api.networking.crafting.ICraftingCPU; +import appeng.api.networking.crafting.ICraftingCallback; +import appeng.api.networking.crafting.ICraftingGrid; +import appeng.api.networking.crafting.ICraftingJob; import appeng.api.networking.crafting.ICraftingMedium; import appeng.api.networking.crafting.ICraftingPatternDetails; import appeng.api.networking.crafting.ICraftingProvider; @@ -36,10 +45,11 @@ import appeng.me.cluster.implementations.CraftingCPUCluster; import appeng.tile.crafting.TileCraftingStorageTile; import appeng.tile.crafting.TileCraftingTile; +import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; -public class CraftingCache implements IGridCache, ICraftingProviderHelper, ICellProvider, IMEInventoryHandler +public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper, ICellProvider, IMEInventoryHandler { HashSet cpuClusters = new HashSet(); @@ -50,11 +60,11 @@ public class CraftingCache implements IGridCache, ICraftingProviderHelper, ICell IEnergyGrid eg; HashMap> craftingMethods = new HashMap(); - HashMap> craftableItems = new HashMap(); + HashMap> craftableItems = new HashMap(); boolean updateList = false; - public CraftingCache(IGrid g) { + public CraftingGridCache(IGrid g) { grid = g; } @@ -159,22 +169,32 @@ public class CraftingCache implements IGridCache, ICraftingProviderHelper, ICell for (ICraftingProvider cp : providers) cp.provideCrafting( this ); + HashMap> tmpCraft = new HashMap(); + // new craftables! for (ICraftingPatternDetails details : craftingMethods.keySet()) + { for (IAEItemStack out : details.getOutputs()) { out = out.copy(); out.reset(); out.setCraftable( true ); - Set methods = craftableItems.get( out ); + Set methods = tmpCraft.get( out ); if ( methods == null ) - craftableItems.put( out, methods = new TreeSet() ); + tmpCraft.put( out, methods = new TreeSet() ); methods.add( details ); sg.postAlterationOfStoredItems( StorageChannel.ITEMS, out, new BaseActionSource() ); } + } + + // make them immutable + for (Entry> e : tmpCraft.entrySet()) + { + craftableItems.put( e.getKey(), ImmutableSet.copyOf( e.getValue() ) ); + } } @Override @@ -263,11 +283,16 @@ public class CraftingCache implements IGridCache, ICraftingProviderHelper, ICell return false; } - public boolean submitJob(CraftingJob job, CraftingCPUCluster target, BaseActionSource src) + public boolean submitJob(ICraftingJob job, ICraftingCPU target, BaseActionSource src) { if ( job.isSimulation() ) return false; + CraftingCPUCluster cpuClust = null; + + if ( target instanceof CraftingCPUCluster ) + cpuClust = (CraftingCPUCluster) target; + if ( target == null ) { // TODO real stuff... @@ -275,13 +300,13 @@ public class CraftingCache implements IGridCache, ICraftingProviderHelper, ICell { if ( !cpu.isBusy() ) { - target = cpu; + cpuClust = cpu; break; } } } - if ( target != null && target.submitJob( grid, job, src ) ) + if ( cpuClust != null && cpuClust.submitJob( grid, job, src ) ) return true; return false; @@ -293,9 +318,9 @@ public class CraftingCache implements IGridCache, ICraftingProviderHelper, ICell return 0; } - public Set getCraftingFor(IAEItemStack what) + public ImmutableCollection getCraftingFor(IAEItemStack what) { - Set res = craftableItems.get( what ); + ImmutableSet res = craftableItems.get( what ); if ( res == null ) return ImmutableSet.of(); return res; @@ -317,4 +342,28 @@ public class CraftingCache implements IGridCache, ICraftingProviderHelper, ICell return i == 1; } + 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 ); + } + + @Override + public Future beginCraftingJob(World world, IGrid grid, BaseActionSource actionSrc, IAEItemStack slotItem, ICraftingCallback cb) + { + CraftingJob cj = new CraftingJob( world, grid, actionSrc, slotItem, cb ); + return craftingPool.submit( cj, (ICraftingJob) cj ); + } + } diff --git a/me/cluster/implementations/CraftingCPUCluster.java b/me/cluster/implementations/CraftingCPUCluster.java index 8cbe1a7d3..dc87ab70e 100644 --- a/me/cluster/implementations/CraftingCPUCluster.java +++ b/me/cluster/implementations/CraftingCPUCluster.java @@ -21,13 +21,14 @@ import appeng.api.networking.IGrid; import appeng.api.networking.IGridHost; import appeng.api.networking.IGridNode; import appeng.api.networking.crafting.CraftingItemList; +import appeng.api.networking.crafting.ICraftingCPU; +import appeng.api.networking.crafting.ICraftingJob; import appeng.api.networking.crafting.ICraftingMedium; import appeng.api.networking.crafting.ICraftingPatternDetails; import appeng.api.networking.energy.IEnergyGrid; import appeng.api.networking.events.MENetworkCraftingCpuChange; import appeng.api.networking.security.BaseActionSource; import appeng.api.networking.security.MachineSource; -import appeng.api.networking.storage.IBaseMonitor; import appeng.api.networking.storage.IStorageGrid; import appeng.api.storage.IMEInventory; import appeng.api.storage.IMEMonitorHandlerReceiver; @@ -40,14 +41,14 @@ import appeng.core.AELog; import appeng.crafting.CraftBranchFailure; import appeng.crafting.CraftingJob; import appeng.crafting.MECraftingInventory; -import appeng.me.cache.CraftingCache; +import appeng.me.cache.CraftingGridCache; import appeng.me.cluster.IAECluster; import appeng.tile.crafting.TileCraftingTile; import appeng.util.Platform; import appeng.util.item.AEItemStack; import cpw.mods.fml.common.FMLCommonHandler; -public class CraftingCPUCluster implements IAECluster, IBaseMonitor +public class CraftingCPUCluster implements IAECluster, ICraftingCPU { class TaskProgress @@ -73,6 +74,8 @@ public class CraftingCPUCluster implements IAECluster, IBaseMonitor storage = new LinkedList(); private LinkedList status = new LinkedList(); + long availableStorage = 0; + MachineSource machineSrc = null; int accelerator = 0; @@ -182,9 +185,7 @@ public class CraftingCPUCluster implements IAECluster, IBaseMonitor storage = sg.getItemInventory(); MECraftingInventory ci = new MECraftingInventory( storage, true, false, false ); @@ -578,7 +597,7 @@ public class CraftingCPUCluster implements IAECluster, IBaseMonitor> i = tasks.entrySet().iterator(); @@ -768,6 +788,7 @@ public class CraftingCPUCluster implements IAECluster, IBaseMonitor