Crafting Calculator mostly works now - is missing features however.
This commit is contained in:
@@ -16,6 +16,7 @@ import appeng.core.AELog;
|
|||||||
import appeng.core.localization.GuiText;
|
import appeng.core.localization.GuiText;
|
||||||
import appeng.core.sync.GuiBridge;
|
import appeng.core.sync.GuiBridge;
|
||||||
import appeng.core.sync.network.NetworkHandler;
|
import appeng.core.sync.network.NetworkHandler;
|
||||||
|
import appeng.core.sync.packets.PacketCraftRequest;
|
||||||
import appeng.core.sync.packets.PacketSwitchGuis;
|
import appeng.core.sync.packets.PacketSwitchGuis;
|
||||||
import appeng.helpers.WirelessTerminalGuiObject;
|
import appeng.helpers.WirelessTerminalGuiObject;
|
||||||
import appeng.parts.reporting.PartCraftingTerminal;
|
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 )
|
if ( btn == plus1 )
|
||||||
addQty( 1 );
|
addQty( 1 );
|
||||||
if ( btn == plus10 )
|
if ( btn == plus10 )
|
||||||
|
|||||||
@@ -2,14 +2,20 @@ package appeng.container.implementations;
|
|||||||
|
|
||||||
import net.minecraft.entity.player.InventoryPlayer;
|
import net.minecraft.entity.player.InventoryPlayer;
|
||||||
import net.minecraft.inventory.Slot;
|
import net.minecraft.inventory.Slot;
|
||||||
|
import net.minecraft.world.World;
|
||||||
import appeng.api.config.SecurityPermissions;
|
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.ITerminalHost;
|
||||||
import appeng.api.storage.data.IAEItemStack;
|
import appeng.api.storage.data.IAEItemStack;
|
||||||
import appeng.container.AEBaseContainer;
|
import appeng.container.AEBaseContainer;
|
||||||
import appeng.container.slot.SlotInaccessable;
|
import appeng.container.slot.SlotInaccessable;
|
||||||
|
import appeng.crafting.ICraftingHost;
|
||||||
import appeng.tile.inventory.AppEngInternalInventory;
|
import appeng.tile.inventory.AppEngInternalInventory;
|
||||||
|
|
||||||
public class ContainerCraftAmount extends AEBaseContainer
|
public class ContainerCraftAmount extends AEBaseContainer implements ICraftingHost
|
||||||
{
|
{
|
||||||
|
|
||||||
ITerminalHost priHost;
|
ITerminalHost priHost;
|
||||||
@@ -32,4 +38,23 @@ public class ContainerCraftAmount extends AEBaseContainer
|
|||||||
verifyPermissions( SecurityPermissions.CRAFT, false );
|
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() );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import appeng.core.sync.packets.PacketClick;
|
|||||||
import appeng.core.sync.packets.PacketCompassRequest;
|
import appeng.core.sync.packets.PacketCompassRequest;
|
||||||
import appeng.core.sync.packets.PacketCompassResponse;
|
import appeng.core.sync.packets.PacketCompassResponse;
|
||||||
import appeng.core.sync.packets.PacketConfigButton;
|
import appeng.core.sync.packets.PacketConfigButton;
|
||||||
|
import appeng.core.sync.packets.PacketCraftRequest;
|
||||||
import appeng.core.sync.packets.PacketInventoryAction;
|
import appeng.core.sync.packets.PacketInventoryAction;
|
||||||
import appeng.core.sync.packets.PacketLightning;
|
import appeng.core.sync.packets.PacketLightning;
|
||||||
import appeng.core.sync.packets.PacketMEInventoryUpdate;
|
import appeng.core.sync.packets.PacketMEInventoryUpdate;
|
||||||
@@ -73,7 +74,9 @@ public class AppEngPacketHandlerBase
|
|||||||
|
|
||||||
PACKET_RECIPE_NEI(PacketNEIRecipe.class),
|
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 Class pc;
|
||||||
final public Constructor con;
|
final public Constructor con;
|
||||||
|
|||||||
@@ -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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
-136
@@ -1,25 +1,22 @@
|
|||||||
package appeng.crafting;
|
package appeng.crafting;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import appeng.api.AEApi;
|
import appeng.api.AEApi;
|
||||||
import appeng.api.config.Actionable;
|
import appeng.api.config.Actionable;
|
||||||
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
||||||
import appeng.api.networking.storage.IStorageGrid;
|
import appeng.api.networking.storage.IStorageGrid;
|
||||||
import appeng.api.storage.IMEInventory;
|
|
||||||
import appeng.api.storage.data.IAEItemStack;
|
import appeng.api.storage.data.IAEItemStack;
|
||||||
import appeng.api.storage.data.IItemList;
|
import appeng.api.storage.data.IItemList;
|
||||||
|
import appeng.core.AELog;
|
||||||
import appeng.me.cache.CraftingCache;
|
import appeng.me.cache.CraftingCache;
|
||||||
|
import appeng.util.Platform;
|
||||||
|
|
||||||
import com.google.common.collect.ArrayListMultimap;
|
import com.google.common.base.Stopwatch;
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
|
|
||||||
public class CraftingJob implements ICraftingParent
|
public class CraftingJob
|
||||||
{
|
{
|
||||||
|
|
||||||
IAEItemStack output;
|
IAEItemStack output;
|
||||||
@@ -28,170 +25,71 @@ public class CraftingJob implements ICraftingParent
|
|||||||
|
|
||||||
HashSet<IAEItemStack> prophecies;
|
HashSet<IAEItemStack> prophecies;
|
||||||
|
|
||||||
Multimap<IAEItemStack, CraftingTask> bottom;
|
|
||||||
CraftingTask top;
|
|
||||||
|
|
||||||
ICraftingHost jobHost;
|
ICraftingHost jobHost;
|
||||||
|
|
||||||
public CraftingJob(ICraftingHost host, NBTTagCompound data) {
|
public CraftingJob(ICraftingHost host, NBTTagCompound data) {
|
||||||
jobHost = host;
|
jobHost = host;
|
||||||
storage = AEApi.instance().storage().createItemList();
|
storage = AEApi.instance().storage().createItemList();
|
||||||
prophecies = new HashSet();
|
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;
|
jobHost = host;
|
||||||
output = what.copy();
|
output = what.copy();
|
||||||
storage = AEApi.instance().storage().createItemList();
|
storage = AEApi.instance().storage().createItemList();
|
||||||
prophecies = new HashSet();
|
prophecies = new HashSet();
|
||||||
bottom = ArrayListMultimap.create();
|
|
||||||
|
|
||||||
CraftingCache cc = host.getGrid().getCache( CraftingCache.class );
|
CraftingCache cc = host.getGrid().getCache( CraftingCache.class );
|
||||||
IStorageGrid sg = host.getGrid().getCache( IStorageGrid.class );
|
IStorageGrid sg = host.getGrid().getCache( IStorageGrid.class );
|
||||||
|
|
||||||
IItemList<IAEItemStack> missing = AEApi.instance().storage().createItemList();
|
IItemList<IAEItemStack> 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 )
|
Stopwatch timer = Stopwatch.createStarted();
|
||||||
{
|
tree.request( meci, what.getStackSize(), host.getActionSrc() );
|
||||||
IMEInventory<IAEItemStack> netStorage = sg.getItemInventory();
|
tree.dive( this );
|
||||||
|
AELog.info( "-------------" + timer.elapsed( TimeUnit.MILLISECONDS ) + "ms" );
|
||||||
Iterator<IAEItemStack> i = storage.iterator();
|
// if ( mode == Actionable.MODULATE )
|
||||||
while (i.hasNext())
|
// meci.moveItemsToStorage( storage );
|
||||||
{
|
}
|
||||||
IAEItemStack item = i.next();
|
catch (CraftBranchFailure e)
|
||||||
netStorage.injectItems( item, mode, host.getActionSrc() );
|
{
|
||||||
}
|
AELog.error( e );
|
||||||
}
|
}
|
||||||
|
catch (CraftingCalculationFailure f)
|
||||||
throw new CraftingMissingItemsException( missing );
|
{
|
||||||
|
AELog.error( f );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( mode == Actionable.MODULATE )
|
|
||||||
meci.moveItemsToStorage( storage );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void calculateCrafting(CraftingCache cc, ICraftingParent parent, IMEInventory<IAEItemStack> inv, IItemList<IAEItemStack> missing, IAEItemStack what,
|
private CraftingTreeNode getCraftingTree(CraftingCache cc, IAEItemStack what)
|
||||||
Actionable mode)
|
|
||||||
{
|
{
|
||||||
Set<ICraftingPatternDetails> patterns = cc.getCraftingFor( what );
|
return new CraftingTreeNode( cc, this, what, null, 0 );
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void extractItems(IAEItemStack[] requirements, IMEInventory<IAEItemStack> inv, IItemList<IAEItemStack> dest, IItemList<IAEItemStack> 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<IAEItemStack> 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<CraftingTask> getBottom()
|
|
||||||
{
|
|
||||||
return bottom.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IAEItemStack addProgress(IAEItemStack progress)
|
|
||||||
{
|
|
||||||
Collection<CraftingTask> task = bottom.get( progress );
|
|
||||||
|
|
||||||
if ( task == null )
|
|
||||||
return progress;
|
|
||||||
|
|
||||||
Iterator<CraftingTask> 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)
|
public void writeToNBT(NBTTagCompound out)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void addTask(IAEItemStack what, int crafts, ICraftingPatternDetails details, int depth)
|
||||||
public void removeChild(CraftingTask craftingTask)
|
|
||||||
{
|
{
|
||||||
// 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
|
AELog.info( "required material: " + Platform.getItemDisplayName( what ) + " x " + what.getStackSize() );
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<? extends ICraftingParent> getSubJobs()
|
|
||||||
{
|
|
||||||
return Collections.singleton( top );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<IAEItemStack> missingItems;
|
|
||||||
|
|
||||||
public CraftingMissingItemsException( IItemList<IAEItemStack> missing )
|
|
||||||
{
|
|
||||||
missingItems = missing;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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<CraftingTask> 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<? extends ICraftingParent> getSubJobs()
|
|
||||||
{
|
|
||||||
return subtasks;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToNBT(NBTTagCompound out)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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<CraftingTreeProcess> 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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<CraftingTreeNode, Long> 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<CraftingTreeNode, Long> 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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package appeng.crafting;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
|
||||||
|
|
||||||
public interface ICraftingParent
|
|
||||||
{
|
|
||||||
|
|
||||||
Collection<? extends ICraftingParent> getSubJobs();
|
|
||||||
|
|
||||||
void writeToNBT(NBTTagCompound out);
|
|
||||||
|
|
||||||
void removeChild(CraftingTask craftingTask);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -11,14 +11,44 @@ import appeng.api.storage.data.IItemList;
|
|||||||
public class MECraftingInventory implements IMEInventory<IAEItemStack>
|
public class MECraftingInventory implements IMEInventory<IAEItemStack>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
final MECraftingInventory par;
|
||||||
|
|
||||||
final IMEInventory<IAEItemStack> target;
|
final IMEInventory<IAEItemStack> target;
|
||||||
final IItemList<IAEItemStack> localCache;
|
final IItemList<IAEItemStack> localCache;
|
||||||
|
|
||||||
|
final boolean logExtracted;
|
||||||
final IItemList<IAEItemStack> extractedCache;
|
final IItemList<IAEItemStack> extractedCache;
|
||||||
|
|
||||||
public MECraftingInventory(IMEInventory<IAEItemStack> target) {
|
final boolean logInjections;
|
||||||
this.target = target;
|
final IItemList<IAEItemStack> injectedCache;
|
||||||
|
|
||||||
|
final boolean logMissing;
|
||||||
|
final IItemList<IAEItemStack> 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();
|
extractedCache = AEApi.instance().storage().createItemList();
|
||||||
|
injectedCache = AEApi.instance().storage().createItemList();
|
||||||
localCache = target.getAvailableItems( AEApi.instance().storage().createItemList() );
|
localCache = target.getAvailableItems( AEApi.instance().storage().createItemList() );
|
||||||
|
|
||||||
|
par = parrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MECraftingInventory(IMEInventory<IAEItemStack> 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
|
@Override
|
||||||
@@ -27,8 +57,14 @@ public class MECraftingInventory implements IMEInventory<IAEItemStack>
|
|||||||
if ( input == null )
|
if ( input == null )
|
||||||
return 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 );
|
localCache.add( input );
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -39,11 +75,13 @@ public class MECraftingInventory implements IMEInventory<IAEItemStack>
|
|||||||
if ( request == null )
|
if ( request == null )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
// AELog.info( mode.toString() + "Extract: " + request.toString() );
|
||||||
|
|
||||||
IAEItemStack list = localCache.findPrecise( request );
|
IAEItemStack list = localCache.findPrecise( request );
|
||||||
if ( list == null || list.getStackSize() == 0 )
|
if ( list == null || list.getStackSize() == 0 )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if ( mode == Actionable.MODULATE )
|
if ( mode == Actionable.MODULATE && logExtracted )
|
||||||
extractedCache.add( request );
|
extractedCache.add( request );
|
||||||
|
|
||||||
if ( list.getStackSize() >= request.getStackSize() )
|
if ( list.getStackSize() >= request.getStackSize() )
|
||||||
@@ -88,4 +126,34 @@ public class MECraftingInventory implements IMEInventory<IAEItemStack>
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
final IRecipe standardRecipe;
|
final IRecipe standardRecipe;
|
||||||
|
|
||||||
final IAEItemStack condencedInputs[];
|
final IAEItemStack condencedInputs[];
|
||||||
|
final IAEItemStack condencedOutputs[];
|
||||||
final IAEItemStack inputs[];
|
final IAEItemStack inputs[];
|
||||||
final IAEItemStack outputs[];
|
final IAEItemStack outputs[];
|
||||||
|
|
||||||
@@ -129,9 +130,9 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
if ( gs != null && (!isCrafting || !gs.hasTagCompound()) )
|
if ( gs != null && (!isCrafting || !gs.hasTagCompound()) )
|
||||||
{
|
{
|
||||||
markItemAs( x, gs, TestStatus.ACCEPT );
|
markItemAs( x, gs, TestStatus.ACCEPT );
|
||||||
in.add( AEApi.instance().storage().createItemStack( gs ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
in.add( AEApi.instance().storage().createItemStack( gs ) );
|
||||||
testFrame.setInventorySlotContents( x, gs );
|
testFrame.setInventorySlotContents( x, gs );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,21 +158,41 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
outputs = out.toArray( new IAEItemStack[out.size()] );
|
outputs = out.toArray( new IAEItemStack[out.size()] );
|
||||||
inputs = in.toArray( new IAEItemStack[in.size()] );
|
inputs = in.toArray( new IAEItemStack[in.size()] );
|
||||||
|
|
||||||
HashMap<IAEItemStack, IAEItemStack> o = new HashMap<IAEItemStack, IAEItemStack>();
|
HashMap<IAEItemStack, IAEItemStack> tmpOutputs = new HashMap<IAEItemStack, IAEItemStack>();
|
||||||
|
for (IAEItemStack io : outputs)
|
||||||
for (IAEItemStack io : inputs)
|
|
||||||
{
|
{
|
||||||
IAEItemStack g = o.get( io );
|
if ( io == null )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
IAEItemStack g = tmpOutputs.get( io );
|
||||||
if ( g == null )
|
if ( g == null )
|
||||||
o.put( io, io.copy() );
|
tmpOutputs.put( io, io.copy() );
|
||||||
|
else
|
||||||
|
g.add( io );
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMap<IAEItemStack, IAEItemStack> tmpInputs = new HashMap<IAEItemStack, IAEItemStack>();
|
||||||
|
for (IAEItemStack io : inputs)
|
||||||
|
{
|
||||||
|
if ( io == null )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
IAEItemStack g = tmpInputs.get( io );
|
||||||
|
if ( g == null )
|
||||||
|
tmpInputs.put( io, io.copy() );
|
||||||
else
|
else
|
||||||
g.add( io );
|
g.add( io );
|
||||||
}
|
}
|
||||||
|
|
||||||
condencedInputs = new IAEItemStack[o.size()];
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for (IAEItemStack io : o.values())
|
condencedInputs = new IAEItemStack[tmpInputs.size()];
|
||||||
|
for (IAEItemStack io : tmpInputs.values())
|
||||||
condencedInputs[offset++] = io;
|
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)
|
public boolean isValidItemForSlot(int slotIndex, ItemStack i, World w)
|
||||||
@@ -282,9 +303,16 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
return condencedInputs;
|
return condencedInputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IAEItemStack[] getCondencedOutputs()
|
||||||
|
{
|
||||||
|
return condencedOutputs;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(PatternHelper o)
|
public int compareTo(PatternHelper o)
|
||||||
{
|
{
|
||||||
return ItemSorters.compareInt( o.priority, priority );
|
return ItemSorters.compareInt( o.priority, priority );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+6
-1
@@ -34,6 +34,8 @@ import appeng.me.cluster.implementations.CraftingCPUCluster;
|
|||||||
import appeng.tile.crafting.TileCraftingStorageTile;
|
import appeng.tile.crafting.TileCraftingStorageTile;
|
||||||
import appeng.tile.crafting.TileCraftingTile;
|
import appeng.tile.crafting.TileCraftingTile;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
public class CraftingCache implements IGridCache, ICraftingProviderHelper, ICellProvider, IMEInventoryHandler
|
public class CraftingCache implements IGridCache, ICraftingProviderHelper, ICellProvider, IMEInventoryHandler
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -257,7 +259,10 @@ public class CraftingCache implements IGridCache, ICraftingProviderHelper, ICell
|
|||||||
|
|
||||||
public Set<ICraftingPatternDetails> getCraftingFor(IAEItemStack what)
|
public Set<ICraftingPatternDetails> getCraftingFor(IAEItemStack what)
|
||||||
{
|
{
|
||||||
return craftableItems.get( what );
|
Set<ICraftingPatternDetails> res = craftableItems.get( what );
|
||||||
|
if ( res == null )
|
||||||
|
return ImmutableSet.of();
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
|
|||||||
Fluid fluid;
|
Fluid fluid;
|
||||||
protected IAETagCompound tagCompound;
|
protected IAETagCompound tagCompound;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getFluidStack().toString();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IAETagCompound getTagCompound()
|
public IAETagCompound getTagCompound()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
|
|||||||
|
|
||||||
AEItemDef def;
|
AEItemDef def;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return getItemStack().toString();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(IAEItemStack option)
|
public void add(IAEItemStack option)
|
||||||
{
|
{
|
||||||
@@ -53,10 +59,10 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
|
|||||||
|
|
||||||
def = new AEItemDef();
|
def = new AEItemDef();
|
||||||
def.item = is.getItem();
|
def.item = is.getItem();
|
||||||
|
|
||||||
if ( def.item == null )
|
if ( def.item == null )
|
||||||
throw new RuntimeException( "This ItemStack is bad, it has a null item." );
|
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.
|
* Prevent an Item from changing the damage value on me... Either, this or a core mod.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user