diff --git a/client/gui/implementations/GuiCraftAmount.java b/client/gui/implementations/GuiCraftAmount.java index f66ffc89..9993e9b0 100644 --- a/client/gui/implementations/GuiCraftAmount.java +++ b/client/gui/implementations/GuiCraftAmount.java @@ -16,6 +16,7 @@ import appeng.core.AELog; import appeng.core.localization.GuiText; import appeng.core.sync.GuiBridge; import appeng.core.sync.network.NetworkHandler; +import appeng.core.sync.packets.PacketCraftRequest; import appeng.core.sync.packets.PacketSwitchGuis; import appeng.helpers.WirelessTerminalGuiObject; import appeng.parts.reporting.PartCraftingTerminal; @@ -112,6 +113,19 @@ public class GuiCraftAmount extends AEBaseGui } } + if ( btn == next ) + { + try + { + NetworkHandler.instance.sendToServer( new PacketCraftRequest( inventorySlots.getSlot( 0 ).getStack(), Integer.parseInt( this.amountToCraft + .getText() ) ) ); + } + catch (Throwable e) + { + AELog.error( e ); + } + } + if ( btn == plus1 ) addQty( 1 ); if ( btn == plus10 ) diff --git a/container/implementations/ContainerCraftAmount.java b/container/implementations/ContainerCraftAmount.java index 9d33cefa..c113faa6 100644 --- a/container/implementations/ContainerCraftAmount.java +++ b/container/implementations/ContainerCraftAmount.java @@ -2,14 +2,20 @@ package appeng.container.implementations; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Slot; +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.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 +public class ContainerCraftAmount extends AEBaseContainer implements ICraftingHost { ITerminalHost priHost; @@ -32,4 +38,23 @@ public class ContainerCraftAmount extends AEBaseContainer verifyPermissions( SecurityPermissions.CRAFT, false ); } + @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() ); + } + } diff --git a/core/sync/AppEngPacketHandlerBase.java b/core/sync/AppEngPacketHandlerBase.java index ca4a7b0d..0b4ff7df 100644 --- a/core/sync/AppEngPacketHandlerBase.java +++ b/core/sync/AppEngPacketHandlerBase.java @@ -11,6 +11,7 @@ import appeng.core.sync.packets.PacketClick; import appeng.core.sync.packets.PacketCompassRequest; import appeng.core.sync.packets.PacketCompassResponse; import appeng.core.sync.packets.PacketConfigButton; +import appeng.core.sync.packets.PacketCraftRequest; import appeng.core.sync.packets.PacketInventoryAction; import appeng.core.sync.packets.PacketLightning; import appeng.core.sync.packets.PacketMEInventoryUpdate; @@ -73,7 +74,9 @@ public class AppEngPacketHandlerBase PACKET_RECIPE_NEI(PacketNEIRecipe.class), - PACKET_PARTIAL_ITEM(PacketPartialItem.class); + PACKET_PARTIAL_ITEM(PacketPartialItem.class), + + PAKCET_CRAFTING_REQUEST(PacketCraftRequest.class); final public Class pc; final public Constructor con; diff --git a/crafting/CraftBranchFailure.java b/crafting/CraftBranchFailure.java new file mode 100644 index 00000000..04c4f535 --- /dev/null +++ b/crafting/CraftBranchFailure.java @@ -0,0 +1,17 @@ +package appeng.crafting; + +import appeng.api.storage.data.IAEItemStack; + +public class CraftBranchFailure extends Exception +{ + + private static final long serialVersionUID = 654603652836724823L; + + IAEItemStack missing; + + public CraftBranchFailure(IAEItemStack what, long howMany) { + super( "this should have been caught!" ); + missing = what.copy(); + missing.setStackSize( howMany ); + } +} diff --git a/crafting/CraftingCalculationFailure.java b/crafting/CraftingCalculationFailure.java new file mode 100644 index 00000000..3048e610 --- /dev/null +++ b/crafting/CraftingCalculationFailure.java @@ -0,0 +1,17 @@ +package appeng.crafting; + +import appeng.api.storage.data.IAEItemStack; + +public class CraftingCalculationFailure extends RuntimeException +{ + + private static final long serialVersionUID = 654603652836724823L; + + IAEItemStack missing; + + public CraftingCalculationFailure(IAEItemStack what, long howMany) { + super( "this should have been caught!" ); + missing = what.copy(); + missing.setStackSize( howMany ); + } +} diff --git a/crafting/CraftingJob.java b/crafting/CraftingJob.java index f317f382..f1a7a584 100644 --- a/crafting/CraftingJob.java +++ b/crafting/CraftingJob.java @@ -1,25 +1,22 @@ package appeng.crafting; -import java.util.Collection; -import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; +import java.util.concurrent.TimeUnit; import net.minecraft.nbt.NBTTagCompound; import appeng.api.AEApi; import appeng.api.config.Actionable; import appeng.api.networking.crafting.ICraftingPatternDetails; import appeng.api.networking.storage.IStorageGrid; -import appeng.api.storage.IMEInventory; import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IItemList; +import appeng.core.AELog; import appeng.me.cache.CraftingCache; +import appeng.util.Platform; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; +import com.google.common.base.Stopwatch; -public class CraftingJob implements ICraftingParent +public class CraftingJob { IAEItemStack output; @@ -28,170 +25,71 @@ public class CraftingJob implements ICraftingParent HashSet prophecies; - Multimap bottom; - CraftingTask top; - ICraftingHost jobHost; public CraftingJob(ICraftingHost host, NBTTagCompound data) { jobHost = host; storage = AEApi.instance().storage().createItemList(); prophecies = new HashSet(); - bottom = ArrayListMultimap.create(); } - public CraftingJob(ICraftingHost host, IAEItemStack what, Actionable mode) throws CraftingMissingItemsException { + public CraftingJob(ICraftingHost host, IAEItemStack what, Actionable mode) { jobHost = host; output = what.copy(); storage = AEApi.instance().storage().createItemList(); prophecies = new HashSet(); - bottom = ArrayListMultimap.create(); CraftingCache cc = host.getGrid().getCache( CraftingCache.class ); IStorageGrid sg = host.getGrid().getCache( IStorageGrid.class ); IItemList missing = AEApi.instance().storage().createItemList(); - MECraftingInventory meci = new MECraftingInventory( sg.getItemInventory() ); + MECraftingInventory meci = new MECraftingInventory( sg.getItemInventory(), true, false, true ); + meci.ignore( what ); - calculateCrafting( cc, this, meci, missing, what, mode ); + CraftingTreeNode tree = getCraftingTree( cc, what ); - if ( !missing.isEmpty() ) + try { - if ( mode == Actionable.MODULATE ) - { - IMEInventory netStorage = sg.getItemInventory(); - - Iterator i = storage.iterator(); - while (i.hasNext()) - { - IAEItemStack item = i.next(); - netStorage.injectItems( item, mode, host.getActionSrc() ); - } - } - - throw new CraftingMissingItemsException( missing ); + Stopwatch timer = Stopwatch.createStarted(); + tree.request( meci, what.getStackSize(), host.getActionSrc() ); + tree.dive( this ); + 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 ); } - - if ( mode == Actionable.MODULATE ) - meci.moveItemsToStorage( storage ); } - public void calculateCrafting(CraftingCache cc, ICraftingParent parent, IMEInventory inv, IItemList missing, IAEItemStack what, - Actionable mode) + private CraftingTreeNode getCraftingTree(CraftingCache cc, IAEItemStack what) { - Set patterns = cc.getCraftingFor( what ); - - for (ICraftingPatternDetails details : patterns) - { - IAEItemStack[] requirements = details.getCondencedInputs(); - if ( canMake( requirements, inv ) ) - { - extractItems( requirements, inv, storage, missing ); - return; - } - } - - for (ICraftingPatternDetails details : patterns) - { - IAEItemStack[] requirements = details.getCondencedInputs(); - extractItems( requirements, inv, storage, missing ); - return; - } + return new CraftingTreeNode( cc, this, what, null, 0 ); } - private void extractItems(IAEItemStack[] requirements, IMEInventory inv, IItemList dest, IItemList missing) - { - for (IAEItemStack is : requirements) - { - IAEItemStack avail = inv.extractItems( is, Actionable.MODULATE, jobHost.getActionSrc() ); - - if ( avail == null ) - { - missing.add( is ); - continue; - } - - if ( avail.getStackSize() != is.getStackSize() ) - { - IAEItemStack ais = avail.copy(); - ais.setStackSize( is.getStackSize() - avail.getStackSize() ); - missing.add( ais ); - } - - dest.add( avail ); - } - } - - private boolean canMake(IAEItemStack[] requirements, IMEInventory inv) - { - - for (IAEItemStack is : requirements) - { - IAEItemStack avail = inv.extractItems( is, Actionable.SIMULATE, jobHost.getActionSrc() ); - - if ( avail == null ) - return false; - - if ( avail.getStackSize() != is.getStackSize() ) - return false; - } - - return true; - } - - public Collection getBottom() - { - return bottom.values(); - } - - public IAEItemStack addProgress(IAEItemStack progress) - { - Collection task = bottom.get( progress ); - - if ( task == null ) - return progress; - - Iterator i = task.iterator(); - - while (i.hasNext()) - { - // adding to the first item.. - progress = i.next().addProgress( progress ); - - // if nothing remains return - if ( progress == null ) - return null; - - // if something remains continue.. - i = task.iterator(); - } - - return null; - } - - @Override public void writeToNBT(NBTTagCompound out) { } - @Override - public void removeChild(CraftingTask craftingTask) + public void addTask(IAEItemStack what, int crafts, ICraftingPatternDetails details, int depth) { - // TODO Auto-generated method stub + if ( crafts > 0 ) + { + AELog.info( "new task: " + Platform.getItemDisplayName( what ) + " x " + what.getStackSize() + " * " + crafts + " = " + + (what.getStackSize() * crafts) + " @ " + depth ); + } } - public ICraftingHost getHost() + public void addMissing(IAEItemStack what) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Collection getSubJobs() - { - return Collections.singleton( top ); + AELog.info( "required material: " + Platform.getItemDisplayName( what ) + " x " + what.getStackSize() ); } } diff --git a/crafting/CraftingMissingItemsException.java b/crafting/CraftingMissingItemsException.java deleted file mode 100644 index f1461fa0..00000000 --- a/crafting/CraftingMissingItemsException.java +++ /dev/null @@ -1,17 +0,0 @@ -package appeng.crafting; - -import appeng.api.storage.data.IAEItemStack; -import appeng.api.storage.data.IItemList; - -public class CraftingMissingItemsException extends Exception { - - private static final long serialVersionUID = -7517510681369528425L; - - final public IItemList missingItems; - - public CraftingMissingItemsException( IItemList missing ) - { - missingItems = missing; - } - -} diff --git a/crafting/CraftingTask.java b/crafting/CraftingTask.java deleted file mode 100644 index 19997f3e..00000000 --- a/crafting/CraftingTask.java +++ /dev/null @@ -1,106 +0,0 @@ -package appeng.crafting; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import appeng.api.networking.crafting.ICraftingPatternDetails; -import appeng.api.storage.data.IAEItemStack; -import appeng.items.misc.ItemEncodedPattern; -import appeng.util.item.AEItemStack; - -public class CraftingTask implements ICraftingParent -{ - - final IAEItemStack task; - - final ICraftingPatternDetails process; - - final List subtasks; - final ICraftingParent parenttask; - - final CraftingJob job; - - public CraftingTask(IAEItemStack myTask, ICraftingPatternDetails pattern, ICraftingParent parent, CraftingJob craftingJob) { - task = myTask; - process = pattern; - parenttask = parent; - job = craftingJob; - subtasks = new ArrayList(); - - // register as part of the bottom. - job.bottom.put( task.copy(), this ); - } - - public CraftingTask(NBTTagCompound c, ICraftingParent parent, CraftingJob craftingJob) { - task = AEItemStack.loadItemStackFromNBT( c.getCompoundTag( "task" ) ); - ItemStack pattern = ItemStack.loadItemStackFromNBT( c.getCompoundTag( "pattern" ) ); - - if ( pattern == null || !(pattern.getItem() instanceof ItemEncodedPattern) ) - throw new RuntimeException( "Failed to load crafting job" ); - - ItemEncodedPattern iep = (ItemEncodedPattern) pattern.getItem(); - process = iep.getPatternForItem( pattern, craftingJob.getHost().getWorld() ); - - subtasks = new ArrayList(); - parenttask = parent; - job = craftingJob; - } - - public IAEItemStack addProgress(IAEItemStack progress) - { - long amt = progress.getStackSize(); - long mine = task.getStackSize(); - - if ( amt >= mine ) - { - parenttask.removeChild( this ); - - task.reset(); - job.bottom.remove( task, this ); - - progress = progress.copy(); - progress.decStackSize( mine ); - return progress; - } - else - { - task.decStackSize( amt ); - return null; - } - } - - public void addSubTask(CraftingTask task) - { - boolean wasEmpty = subtasks.isEmpty(); - - subtasks.add( task ); - - if ( wasEmpty ) - job.bottom.remove( task, this ); - } - - public void removeChild(CraftingTask craftingTask) - { - subtasks.remove( craftingTask ); - if ( subtasks.isEmpty() ) - { - job.bottom.put( task.copy(), this ); - } - } - - @Override - public Collection getSubJobs() - { - return subtasks; - } - - @Override - public void writeToNBT(NBTTagCompound out) - { - - } - -} diff --git a/crafting/CraftingTreeNode.java b/crafting/CraftingTreeNode.java new file mode 100644 index 00000000..40ade6fe --- /dev/null +++ b/crafting/CraftingTreeNode.java @@ -0,0 +1,141 @@ +package appeng.crafting; + +import java.util.ArrayList; + +import appeng.api.config.Actionable; +import appeng.api.networking.crafting.ICraftingPatternDetails; +import appeng.api.networking.security.BaseActionSource; +import appeng.api.storage.data.IAEItemStack; +import appeng.me.cache.CraftingCache; + +public class CraftingTreeNode +{ + + // parent node. + private CraftingTreeProcess parent; + + // what item is this? + private IAEItemStack what; + + // what are the crafting patterns for this? + private ArrayList nodes = new ArrayList(); + + boolean cannotUse = false; + int missing = 0; + + public CraftingTreeNode(CraftingCache cc, CraftingJob job, IAEItemStack wat, CraftingTreeProcess par, int depth) { + what = wat; + parent = par; + + for (ICraftingPatternDetails details : cc.getCraftingFor( what ))// in order. + { + if ( notRecurive( details ) ) + nodes.add( new CraftingTreeProcess( cc, job, details, this, depth + 1 ) ); + } + } + + public IAEItemStack getStack(long size) + { + IAEItemStack is = what.copy(); + is.setStackSize( size ); + return is; + } + + boolean notRecurive(ICraftingPatternDetails details) + { + IAEItemStack[] o = details.getOutputs(); + for (IAEItemStack i : o) + if ( i.equals( what ) ) + return true; + + if ( parent == null ) + return false; + + return parent.notRecurive( details ); + } + + private long getTimes(long remaining, long stackSize) + { + return (remaining / stackSize) + (remaining % stackSize != 0 ? 1 : 0); + } + + public void request(MECraftingInventory inv, long l, BaseActionSource src) throws CraftBranchFailure + { + what.setStackSize( l ); + IAEItemStack available = inv.extractItems( what, Actionable.MODULATE, src ); + + if ( available != null ) + l -= available.getStackSize(); + + if ( l == 0 ) + return; + + if ( nodes.size() == 1 ) + { + CraftingTreeProcess pro = nodes.get( 0 ); + + while (pro.possible && l > 0) + { + pro.request( inv, getTimes( l, pro.getAmountCrafted( what ).getStackSize() ), src ); + + what.setStackSize( l ); + available = inv.extractItems( what, Actionable.MODULATE, src ); + + if ( available != null ) + { + l -= available.getStackSize(); + + if ( l <= 0 ) + return; + } + else + pro.possible = false; // ;P + } + } + else if ( nodes.size() > 1 ) + { + for (CraftingTreeProcess pro : nodes) + { + try + { + while (pro.possible && l > 0) + { + MECraftingInventory subInv = new MECraftingInventory( inv ); + pro.request( subInv, 1, src ); + subInv.commit( src ); + + what.setStackSize( l ); + available = inv.extractItems( what, Actionable.MODULATE, src ); + + if ( available != null ) + { + l -= available.getStackSize(); + + if ( l <= 0 ) + return; + } + else + pro.possible = false; // ;P + } + } + catch (CraftBranchFailure fail) + { + pro.possible = true; + } + } + } + + missing += l; + // throw new CraftBranchFailure( what, l ); + } + + public void dive(CraftingJob job) + { + if ( missing > 0 ) + job.addMissing( getStack( missing ) ); + missing = 0; + + for (CraftingTreeProcess pro : nodes) + pro.dive( job ); + } +} diff --git a/crafting/CraftingTreeProcess.java b/crafting/CraftingTreeProcess.java new file mode 100644 index 00000000..5e0f9501 --- /dev/null +++ b/crafting/CraftingTreeProcess.java @@ -0,0 +1,84 @@ +package appeng.crafting; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import appeng.api.config.Actionable; +import appeng.api.networking.crafting.ICraftingPatternDetails; +import appeng.api.networking.security.BaseActionSource; +import appeng.api.storage.data.IAEItemStack; +import appeng.me.cache.CraftingCache; + +public class CraftingTreeProcess +{ + + CraftingTreeNode parent; + ICraftingPatternDetails details; + CraftingJob job; + + int crafts = 0; + final private int depth; + + Map nodes = new HashMap(); + public boolean possible = true; + + public CraftingTreeProcess(CraftingCache cc, CraftingJob job, ICraftingPatternDetails details, CraftingTreeNode craftingTreeNode, int depth) { + parent = craftingTreeNode; + this.details = details; + this.job = job; + this.depth = depth; + + for (IAEItemStack part : details.getCondencedInputs()) + nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, depth + 1 ), part.getStackSize() ); + } + + public boolean notRecurive(ICraftingPatternDetails details) + { + return parent.notRecurive( details ); + } + + IAEItemStack getAmountCrafted(IAEItemStack what2) + { + for (IAEItemStack is : details.getCondencedOutputs()) + { + if ( is.equals( what2 ) ) + { + what2 = what2.copy(); + what2.setStackSize( is.getStackSize() ); + return what2; + } + } + + throw new RuntimeException( "Crafting Tree construction failed." ); + } + + public void request(MECraftingInventory inv, long i, BaseActionSource src) throws CraftBranchFailure + { + // request and remove inputs... + for (Entry entry : nodes.entrySet()) + { + IAEItemStack item = entry.getKey().getStack( entry.getValue() ); + entry.getKey().request( inv, item.getStackSize() * i, src ); + } + + // assume its possible. + + // add crafting results.. + for (IAEItemStack out : details.getCondencedOutputs()) + { + IAEItemStack o = out.copy(); + o.setStackSize( o.getStackSize() * i ); + inv.injectItems( o, Actionable.MODULATE, src ); + } + + crafts += i; + } + + public void dive(CraftingJob job) + { + job.addTask( getAmountCrafted( parent.getStack( 1 ) ), crafts, details, depth ); + for (CraftingTreeNode pro : nodes.keySet()) + pro.dive( job ); + } +} diff --git a/crafting/ICraftingParent.java b/crafting/ICraftingParent.java deleted file mode 100644 index cf51a4a7..00000000 --- a/crafting/ICraftingParent.java +++ /dev/null @@ -1,16 +0,0 @@ -package appeng.crafting; - -import java.util.Collection; - -import net.minecraft.nbt.NBTTagCompound; - -public interface ICraftingParent -{ - - Collection getSubJobs(); - - void writeToNBT(NBTTagCompound out); - - void removeChild(CraftingTask craftingTask); - -} diff --git a/crafting/MECraftingInventory.java b/crafting/MECraftingInventory.java index 69a15fc1..d4d352dc 100644 --- a/crafting/MECraftingInventory.java +++ b/crafting/MECraftingInventory.java @@ -11,14 +11,44 @@ import appeng.api.storage.data.IItemList; public class MECraftingInventory implements IMEInventory { + final MECraftingInventory par; + final IMEInventory target; final IItemList localCache; + + final boolean logExtracted; final IItemList extractedCache; - public MECraftingInventory(IMEInventory target) { - this.target = target; + final boolean logInjections; + final IItemList injectedCache; + + final boolean logMissing; + final IItemList missingCache; + + public MECraftingInventory(MECraftingInventory parrent) { + this.target = parrent; + this.logExtracted = parrent.logExtracted; + this.logInjections = parrent.logInjections; + this.logMissing = parrent.logMissing; + + missingCache = AEApi.instance().storage().createItemList(); extractedCache = AEApi.instance().storage().createItemList(); + injectedCache = AEApi.instance().storage().createItemList(); localCache = target.getAvailableItems( AEApi.instance().storage().createItemList() ); + + par = parrent; + } + + public MECraftingInventory(IMEInventory target, boolean logExtracted, boolean logInjections, boolean logMissing) { + this.target = target; + this.logExtracted = logExtracted; + this.logInjections = logInjections; + this.logMissing = logMissing; + missingCache = AEApi.instance().storage().createItemList(); + extractedCache = AEApi.instance().storage().createItemList(); + injectedCache = AEApi.instance().storage().createItemList(); + localCache = target.getAvailableItems( AEApi.instance().storage().createItemList() ); + par = null; } @Override @@ -27,8 +57,14 @@ public class MECraftingInventory implements IMEInventory if ( input == null ) return null; - if ( mode == Actionable.SIMULATE ) + // AELog.info( mode.toString() + "Inject: " + input.toString() ); + + if ( mode == Actionable.MODULATE ) + { + if ( logInjections ) + injectedCache.add( input ); localCache.add( input ); + } return null; } @@ -39,11 +75,13 @@ public class MECraftingInventory implements IMEInventory if ( request == null ) return null; + // AELog.info( mode.toString() + "Extract: " + request.toString() ); + IAEItemStack list = localCache.findPrecise( request ); if ( list == null || list.getStackSize() == 0 ) return null; - if ( mode == Actionable.MODULATE ) + if ( mode == Actionable.MODULATE && logExtracted ) extractedCache.add( request ); if ( list.getStackSize() >= request.getStackSize() ) @@ -88,4 +126,34 @@ public class MECraftingInventory implements IMEInventory } + public void commit(BaseActionSource src) + { + if ( logInjections ) + { + for (IAEItemStack injec : injectedCache) + target.injectItems( injec, Actionable.MODULATE, src ); + } + + if ( logExtracted ) + { + for (IAEItemStack extra : extractedCache) + target.extractItems( extra, Actionable.MODULATE, src ); + } + + if ( logMissing && par != null ) + { + for (IAEItemStack extra : missingCache) + par.addMissing( extra ); + } + } + + public void addMissing(IAEItemStack extra) + { + missingCache.add( extra ); + } + + public void ignore(IAEItemStack what) + { + + } } diff --git a/helpers/PatternHelper.java b/helpers/PatternHelper.java index 81b35ff0..9abff908 100644 --- a/helpers/PatternHelper.java +++ b/helpers/PatternHelper.java @@ -32,6 +32,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable o = new HashMap(); - - for (IAEItemStack io : inputs) + HashMap tmpOutputs = new HashMap(); + for (IAEItemStack io : outputs) { - IAEItemStack g = o.get( io ); + if ( io == null ) + continue; + + IAEItemStack g = tmpOutputs.get( io ); if ( g == null ) - o.put( io, io.copy() ); + tmpOutputs.put( io, io.copy() ); + else + g.add( io ); + } + + HashMap tmpInputs = new HashMap(); + for (IAEItemStack io : inputs) + { + if ( io == null ) + continue; + + IAEItemStack g = tmpInputs.get( io ); + if ( g == null ) + tmpInputs.put( io, io.copy() ); else g.add( io ); } - condencedInputs = new IAEItemStack[o.size()]; int offset = 0; - for (IAEItemStack io : o.values()) + condencedInputs = new IAEItemStack[tmpInputs.size()]; + for (IAEItemStack io : tmpInputs.values()) condencedInputs[offset++] = io; + + offset = 0; + condencedOutputs = new IAEItemStack[tmpOutputs.size()]; + for (IAEItemStack io : tmpOutputs.values()) + condencedOutputs[offset++] = io; } public boolean isValidItemForSlot(int slotIndex, ItemStack i, World w) @@ -282,9 +303,16 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable getCraftingFor(IAEItemStack what) { - return craftableItems.get( what ); + Set res = craftableItems.get( what ); + if ( res == null ) + return ImmutableSet.of(); + return res; } } diff --git a/util/item/AEFluidStack.java b/util/item/AEFluidStack.java index f511f6e9..ca860539 100644 --- a/util/item/AEFluidStack.java +++ b/util/item/AEFluidStack.java @@ -27,6 +27,12 @@ public final class AEFluidStack extends AEStack implements IAEFlu Fluid fluid; protected IAETagCompound tagCompound; + @Override + public String toString() + { + return getFluidStack().toString(); + } + @Override public IAETagCompound getTagCompound() { diff --git a/util/item/AEItemStack.java b/util/item/AEItemStack.java index 1af8d3ce..3f7dce11 100644 --- a/util/item/AEItemStack.java +++ b/util/item/AEItemStack.java @@ -26,6 +26,12 @@ public final class AEItemStack extends AEStack implements IAEItemS AEItemDef def; + @Override + public String toString() + { + return getItemStack().toString(); + } + @Override public void add(IAEItemStack option) { @@ -53,10 +59,10 @@ public final class AEItemStack extends AEStack implements IAEItemS def = new AEItemDef(); def.item = is.getItem(); - + if ( def.item == null ) throw new RuntimeException( "This ItemStack is bad, it has a null item." ); - + /* * Prevent an Item from changing the damage value on me... Either, this or a core mod. */