the closer we get to completion, the more likely is the catastrophe

This commit is contained in:
Boblet 2026-05-12 15:48:36 +02:00
parent eb9f8d8cb5
commit b8c71e2a80
9 changed files with 190 additions and 34 deletions

View File

@ -28,3 +28,4 @@
* 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
* Fixed cargo elevators not dropping the correct amount of segments

View File

@ -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();
}
}

View File

@ -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<CacheSlot> viewedBy = new HashSet();
public LinkedHashSet<CacheSlot> 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);
}
}
}

View File

@ -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<Integer, CacheSlot> 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<SlotMonitor> monitors = new LinkedHashSet();
}

View File

@ -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;
@ -81,6 +83,23 @@ public class BlockCargoElevator extends BlockDummyable {
return true;
}
@Override
public ArrayList<ItemStack> 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<ItemStack> 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) {
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.999F, 1.0F); //for some fucking reason setting maxY to something that isn't 1 magically fixes item collisions

View File

@ -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<CacheSlot> 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<CacheSlot> SORT_BY_STACK_SIZE = new Comparator<CacheSlot>() {
@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;
}
}
}

View File

@ -423,9 +423,9 @@ public class AssemblyMachineRecipes extends GenericRecipes<GenericRecipe> {
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)));

View File

@ -23,13 +23,11 @@ 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) {

View File

@ -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;
@ -66,6 +68,7 @@ public class TileEntityPneumoStorageClutter extends TileEntityMachineBase implem
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;
}
}