diff --git a/changelog b/changelog index bc7c1f902..16660da9d 100644 --- a/changelog +++ b/changelog @@ -27,4 +27,5 @@ * Fixed state change in RoR controllers not allowing repeat commands * Fixed blast furnace NEI handler not cycling through all valid material shapes * Fixed RoR transmitter sending empty signals when unused mappings apply -* Fixed hopper IO for battery sockets being entirely broken \ No newline at end of file +* Fixed hopper IO for battery sockets being entirely broken +* Fixed cargo elevators not dropping the correct amount of segments \ No newline at end of file diff --git a/src/main/java/api/hbm/ntl/ISlotMonitorProvider.java b/src/main/java/api/hbm/ntl/ISlotMonitorProvider.java index 19de13029..fb549fee8 100644 --- a/src/main/java/api/hbm/ntl/ISlotMonitorProvider.java +++ b/src/main/java/api/hbm/ntl/ISlotMonitorProvider.java @@ -1,8 +1,15 @@ package api.hbm.ntl; +import com.hbm.uninos.networkproviders.PneumaticNetwork; + import net.minecraft.item.ItemStack; -/** Interface for storage tile entities which provides the access terminals with slot monitors, and slot monitors with ways of accessing the underlying stacks */ +/** + * Interface for storage tile entities which provides the access terminals with slot monitors, + * and slot monitors with ways of accessing the underlying stacks + * + * @author hbm + */ public interface ISlotMonitorProvider { /** Returns an array of available slot monitors, which should ideally mirror the available slots of that container */ @@ -14,6 +21,13 @@ public interface ISlotMonitorProvider { /** Returns the amount of that slot at that index. Some storages may use int64 datatypes so we have to account for those too somehow, since ItemStacks cannot handle that. */ public long getAmountAt(int index); - /** Whether this storage unit is reachable by the access point on the provided location */ - public boolean isAvailableToTerminal(int termX, int termY, int termZ); + /** Whether this storage unit is reachable by the access point */ + public boolean isAvailableToCache(StackCache cache); + + /** This allows slot monitors to find the network, and by extension all cached slots */ + public PneumaticNetwork getRelevantNetwork(); + + public default void updateMonitors() { + for(SlotMonitor monitor : getMonitors()) monitor.checkUpdate(); + } } diff --git a/src/main/java/api/hbm/ntl/SlotMonitor.java b/src/main/java/api/hbm/ntl/SlotMonitor.java index 81284d08d..84b15d402 100644 --- a/src/main/java/api/hbm/ntl/SlotMonitor.java +++ b/src/main/java/api/hbm/ntl/SlotMonitor.java @@ -1,11 +1,21 @@ package api.hbm.ntl; -import java.util.HashSet; +import java.util.LinkedHashSet; import api.hbm.ntl.StackCache.CacheSlot; import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +/** + * Slot monitors are the access points of the system to the actual items stacks. + * Each storage unit needs to provide all its stacks in the form of slot monitors + * to the storage system. The slot monitor's main functionality is to detect changes + * in the underlying stack, so that it can notify and update the system's wider + * data structures. + * + * @author hbm + */ public class SlotMonitor { /** The index of the slot in the inventory this monitor....monitors */ @@ -14,7 +24,7 @@ public class SlotMonitor { public final ISlotMonitorProvider parent; /** If this monitor detects a change, all cache slots need to be notified */ - public HashSet viewedBy = new HashSet(); + public LinkedHashSet viewedBy = new LinkedHashSet(); public Item item; public long stacksize; @@ -28,5 +38,30 @@ public class SlotMonitor { public void checkUpdate() { + for(CacheSlot slot : viewedBy) { // we're gonna need an iterator for that + if(!parent.isAvailableToCache(slot.getStackCache())) { + // TODO: kill from that cache + } + } + + ItemStack stack = parent.getSlotAt(index); + long amount = parent.getAmountAt(index); + + boolean hasTypeChanged = false; + if(item != stack.getItem() || meta != stack.getItemDamage()) hasTypeChanged = true; + else if(nbt == null && stack.hasTagCompound()) hasTypeChanged = true; + else if(nbt != null && !stack.hasTagCompound()) hasTypeChanged = true; + else if(nbt != null && stack.hasTagCompound() && !nbt.equals(stack.stackTagCompound)) hasTypeChanged = true; + + if(hasTypeChanged) { + // TODO: find a bridge to the other CacheSlots, ideally over the pneumo network + // all viewing cache slots need their reference removed and a new cache slot needs to be found/created + return; + } + + if(stacksize != amount) { + long delta = amount - stacksize; + for(CacheSlot slot : viewedBy) slot.changeAmounts(delta); + } } } diff --git a/src/main/java/api/hbm/ntl/StackCache.java b/src/main/java/api/hbm/ntl/StackCache.java index bb67d9933..0f376ebb1 100644 --- a/src/main/java/api/hbm/ntl/StackCache.java +++ b/src/main/java/api/hbm/ntl/StackCache.java @@ -4,18 +4,73 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +/** + * The stack cache represents all combined slots that are available to this endpoint. + * I.e. each endpoint, like an access terminal or an automation output has one stack cache + * which gets regularly updated so it knows what stacks it can access. + * + * @author hbm + */ public class StackCache { + public int x; + public int y; + public int z; + + /** Maps an identity number to the actual cache slot */ public LinkedHashMap cacheSlots = new LinkedHashMap(); + public StackCache(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + /** + * A cache slot represents multiple accessible slots combined into one by type, + * in essence it's a single slot with an uncapped max stack size, which references + * multiple slot monitor instances in order to figure out how many items it has in total. + * + * @author hbm + */ public class CacheSlot { - public Item item; + public final ItemStack displayStack; + public final int itemId; + public final int meta; + public final NBTTagCompound nbt; + public long stacksize; - public int meta; - public NBTTagCompound nbt; + + public CacheSlot(ItemStack stack) { + this.displayStack = stack.copy(); + this.displayStack.stackSize = 1; + this.itemId = Item.getIdFromItem(stack.getItem()); + this.stacksize = stack.stackSize; + this.meta = stack.getItemDamage(); + if(stack.hasTagCompound()) + this.nbt = (NBTTagCompound) stack.stackTagCompound.copy(); + else + this.nbt = null; + } + + public void changeAmounts(long delta) { + this.stacksize += delta; + } + + public StackCache getStackCache() { + return StackCache.this; + } + + public void reCount() { + this.stacksize = 0; + for(SlotMonitor monitor : monitors) { + this.stacksize += monitor.stacksize; + } + } public LinkedHashSet monitors = new LinkedHashSet(); } diff --git a/src/main/java/com/hbm/blocks/machine/BlockCargoElevator.java b/src/main/java/com/hbm/blocks/machine/BlockCargoElevator.java index 73687ebf6..bcf88c618 100644 --- a/src/main/java/com/hbm/blocks/machine/BlockCargoElevator.java +++ b/src/main/java/com/hbm/blocks/machine/BlockCargoElevator.java @@ -1,5 +1,6 @@ package com.hbm.blocks.machine; +import java.util.ArrayList; import java.util.List; import com.hbm.blocks.BlockDummyable; @@ -14,6 +15,7 @@ import net.minecraft.client.renderer.RenderGlobal; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.MovingObjectPosition; @@ -80,6 +82,23 @@ public class BlockCargoElevator extends BlockDummyable { } return true; } + + @Override + public ArrayList getDrops(World world, int x, int y, int z, int metadata, int fortune) { + int[] pos = ((BlockDummyable) ModBlocks.cargo_elevator).findCore(world, x, y, z); + if(pos != null) { + TileEntityCargoElevator elevator = (TileEntityCargoElevator) world.getTileEntity(pos[0], pos[1], pos[2]); + int toDrop = elevator.height + 1; + ArrayList drops = new ArrayList(); + while(toDrop > 0) { + int perStack = Math.min(toDrop, 64); + toDrop -= perStack; + drops.add(new ItemStack(this, perStack)); + } + return drops; + } + return super.getDrops(world, x, y, z, metadata, fortune); + } @Override public void setBlockBoundsBasedOnState(IBlockAccess world, int x, int y, int z) { diff --git a/src/main/java/com/hbm/inventory/container/ContainerPneumoStorageAccess.java b/src/main/java/com/hbm/inventory/container/ContainerPneumoStorageAccess.java index 728769312..dfa738a37 100644 --- a/src/main/java/com/hbm/inventory/container/ContainerPneumoStorageAccess.java +++ b/src/main/java/com/hbm/inventory/container/ContainerPneumoStorageAccess.java @@ -1,8 +1,15 @@ package com.hbm.inventory.container; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + import com.hbm.inventory.SlotNonRetarded; import com.hbm.tileentity.network.pneumatic.TileEntityPneumoStorageAccess; +import api.hbm.ntl.StackCache; +import api.hbm.ntl.StackCache.CacheSlot; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Container; @@ -16,6 +23,7 @@ public class ContainerPneumoStorageAccess extends Container { public ContainerPneumoStorageAccess(InventoryPlayer invPlayer, TileEntityPneumoStorageAccess access) { this.access = access; + this.inventory = new InventoryPneumoStorageAccess(access); for(int i = 0; i < 6; i++) { for(int j = 0; j < 8; j++) { @@ -44,21 +52,47 @@ public class ContainerPneumoStorageAccess extends Container { return null; } + /** This inventory instance only exists to prepare the contents of a StackCache in such a way that we can use it in a container. */ public static class InventoryPneumoStorageAccess implements IInventory { + public StackCache cache; public ItemStack[] slots; - public InventoryPneumoStorageAccess() { - slots = new ItemStack[getSizeInventory()]; + public InventoryPneumoStorageAccess(TileEntityPneumoStorageAccess access) { + this.slots = new ItemStack[getSizeInventory()]; + this.cache = access.cache; } + + public void updateListing() { // DEMO + List cacheSlots = new ArrayList(cache.cacheSlots.size()); + cacheSlots.addAll(cache.cacheSlots.values()); + Collections.sort(cacheSlots, SORT_BY_STACK_SIZE); + int size = cacheSlots.size(); + + for(int i = 0; i < slots.length; i++) { + if(i < size) { + CacheSlot cache = cacheSlots.get(i); + slots[i] = cache.displayStack; + } + } + } + + public static final Comparator SORT_BY_STACK_SIZE = new Comparator() { + @Override + public int compare(CacheSlot o1, CacheSlot o2) { + if(o1.stacksize > o2.stacksize) return 1; if(o1.stacksize < o2.stacksize) return -1; + if(o1.itemId < o2.itemId) return 1; if(o1.itemId > o2.itemId) return -1; + if(o1.meta < o2.meta) return 1; if(o1.meta > o2.meta) return -1; + if(o1.nbt == null && o2.nbt != null) return 1; if(o1.nbt != null && o2.nbt == null) return -1; + return 0; + } + }; @Override public int getSizeInventory() { return 6 * 9; } @Override public ItemStack getStackInSlot(int slot) { return slots[slot]; } + @Override public int getInventoryStackLimit() { return 64; } - @Override - public ItemStack decrStackSize(int slot, int amount) { - return null; - } + @Override public ItemStack decrStackSize(int slot, int amount) { return null; } @Override public ItemStack getStackInSlotOnClosing(int slot) { @@ -77,11 +111,7 @@ public class ContainerPneumoStorageAccess extends Container { @Override public String getInventoryName() { return "null"; } @Override public boolean hasCustomInventoryName() { return false; } - - @Override - public int getInventoryStackLimit() { - return 64; - } + @Override public boolean isItemValidForSlot(int slot, ItemStack stack) { return false; } @Override public void markDirty() { @@ -92,10 +122,5 @@ public class ContainerPneumoStorageAccess extends Container { @Override public void openInventory() { } @Override public void closeInventory() { } - - @Override - public boolean isItemValidForSlot(int slot, ItemStack stack) { - return false; - } } } diff --git a/src/main/java/com/hbm/inventory/recipes/AssemblyMachineRecipes.java b/src/main/java/com/hbm/inventory/recipes/AssemblyMachineRecipes.java index df7b54b9d..ed0d4c536 100644 --- a/src/main/java/com/hbm/inventory/recipes/AssemblyMachineRecipes.java +++ b/src/main/java/com/hbm/inventory/recipes/AssemblyMachineRecipes.java @@ -423,9 +423,9 @@ public class AssemblyMachineRecipes extends GenericRecipes { this.register(new GenericRecipe("ass.tank").setup(200, 100).outputItems(new ItemStack(ModBlocks.machine_fluidtank, 1)) .inputItems(new OreDictStack(STEEL.plate(), 8), new OreDictStack(STEEL.shell(), 4)) .inputItemsEx(new ComparableStack(ModItems.item_expensive, 4, EnumExpensiveType.STEEL_PLATING), new OreDictStack(ANY_TAR.any(), 16))); - this.register(new GenericRecipe("ass.bat9k").setup(200, 100).outputItems(new ItemStack(ModBlocks.machine_bat9000, 1)) - .inputItems(new OreDictStack(STEEL.plate(), 16), new OreDictStack(ANY_RESISTANTALLOY.plateWelded(), 2), new ComparableStack(ModBlocks.steel_scaffold, 16), new OreDictStack(ANY_TAR.any(), 16)) - .inputItemsEx(new ComparableStack(ModItems.item_expensive, 4, EnumExpensiveType.FERRO_PLATING), new ComparableStack(ModBlocks.steel_scaffold, 16), new OreDictStack(ANY_TAR.any(), 16))); + this.register(new GenericRecipe("ass.bigasstank").setup(200, 100).outputItems(new ItemStack(ModBlocks.machine_bigasstank, 1)) + .inputItems(new OreDictStack(STEEL.plate(), 16), new OreDictStack(ANY_RESISTANTALLOY.plateWelded(), 4), new ComparableStack(ModBlocks.steel_scaffold, 16)) + .inputItemsEx(new ComparableStack(ModItems.item_expensive, 6, EnumExpensiveType.FERRO_PLATING), new ComparableStack(ModBlocks.steel_scaffold, 16), new OreDictStack(ANY_TAR.any(), 16))); this.register(new GenericRecipe("ass.orbus").setup(300, 100).outputItems(new ItemStack(ModBlocks.machine_orbus, 1)) .inputItems(new OreDictStack(ANY_RESISTANTALLOY.plateWelded(), 8), new OreDictStack(BIGMT.plateCast(), 4), new OreDictStack(BSCCO.wireDense(), 8), new ComparableStack(ModItems.battery_sc, 1, EnumBatterySC.PO210)) .inputItemsEx(new ComparableStack(ModItems.item_expensive, 8, EnumExpensiveType.FERRO_PLATING), new OreDictStack(BIGMT.plateCast(), 16), new ComparableStack(ModItems.coil_advanced_alloy, 24), new ComparableStack(ModItems.battery_sc, 1, EnumBatterySC.PO210))); diff --git a/src/main/java/com/hbm/tileentity/network/pneumatic/TileEntityPneumoStorageAccess.java b/src/main/java/com/hbm/tileentity/network/pneumatic/TileEntityPneumoStorageAccess.java index 785e4302e..e6396ed89 100644 --- a/src/main/java/com/hbm/tileentity/network/pneumatic/TileEntityPneumoStorageAccess.java +++ b/src/main/java/com/hbm/tileentity/network/pneumatic/TileEntityPneumoStorageAccess.java @@ -22,14 +22,12 @@ public class TileEntityPneumoStorageAccess extends TileEntity implements IPneuma protected PneumaticNode node; public StackCache cache; - - public TileEntityPneumoStorageAccess() { - this.cache = new StackCache(); - } @Override public void updateEntity() { + if(this.cache == null) this.cache = new StackCache(xCoord, yCoord, zCoord); + if(!worldObj.isRemote) { if(this.node == null || this.node.expired) { diff --git a/src/main/java/com/hbm/tileentity/network/pneumatic/TileEntityPneumoStorageClutter.java b/src/main/java/com/hbm/tileentity/network/pneumatic/TileEntityPneumoStorageClutter.java index 156aa6ca8..4b907b83f 100644 --- a/src/main/java/com/hbm/tileentity/network/pneumatic/TileEntityPneumoStorageClutter.java +++ b/src/main/java/com/hbm/tileentity/network/pneumatic/TileEntityPneumoStorageClutter.java @@ -9,6 +9,7 @@ import com.hbm.tileentity.IGUIProvider; import com.hbm.tileentity.TileEntityMachineBase; import com.hbm.tileentity.network.pneumatic.TileEntityPneumoTube.PneumaticNode; import com.hbm.uninos.UniNodespace; +import com.hbm.uninos.networkproviders.PneumaticNetwork; import com.hbm.uninos.networkproviders.PneumaticNetworkProvider; import com.hbm.util.fauxpointtwelve.BlockPos; import com.hbm.util.fauxpointtwelve.DirPos; @@ -16,6 +17,7 @@ import com.hbm.util.fauxpointtwelve.DirPos; import api.hbm.fluidmk2.IFluidStandardReceiverMK2; import api.hbm.ntl.ISlotMonitorProvider; import api.hbm.ntl.SlotMonitor; +import api.hbm.ntl.StackCache; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.item.ItemStack; @@ -65,7 +67,8 @@ public class TileEntityPneumoStorageClutter extends TileEntityMachineBase implem if(node != null && !node.expired && node.hasValidNet()) { this.node.net.storages.put(this, worldObj.getTotalWorldTime()); } - + + this.updateMonitors(); this.networkPackNT(15); } } @@ -109,7 +112,13 @@ public class TileEntityPneumoStorageClutter extends TileEntityMachineBase implem @Override public long getAmountAt(int index) { ItemStack stack = getSlotAt(index); return stack != null ? stack.stackSize : 0; } @Override - public boolean isAvailableToTerminal(int termX, int termY, int termZ) { + public PneumaticNetwork getRelevantNetwork() { + if(this.node == null || this.node.expired || !this.node.hasValidNet()) return null; + return this.node.net; + } + + @Override + public boolean isAvailableToCache(StackCache cache) { return true; } }