From 8634d6362564f3903b54a8a01a9cb832c685cfb8 Mon Sep 17 00:00:00 2001 From: George Paton Date: Sun, 26 Jan 2025 12:31:35 +1100 Subject: [PATCH 1/2] Prevent contiguous foundry channels from accepting different materials until fully emptied, preventing clogs --- .../machine/TileEntityFoundryChannel.java | 98 ++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntityFoundryChannel.java b/src/main/java/com/hbm/tileentity/machine/TileEntityFoundryChannel.java index 3156aada3..a3d50cc76 100644 --- a/src/main/java/com/hbm/tileentity/machine/TileEntityFoundryChannel.java +++ b/src/main/java/com/hbm/tileentity/machine/TileEntityFoundryChannel.java @@ -6,23 +6,38 @@ import java.util.List; import com.hbm.blocks.ModBlocks; import com.hbm.inventory.material.MaterialShapes; +import com.hbm.inventory.material.Mats; import com.hbm.inventory.material.Mats.MaterialStack; +import com.hbm.inventory.material.NTMMaterial; import api.hbm.block.ICrucibleAcceptor; import net.minecraft.block.Block; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; public class TileEntityFoundryChannel extends TileEntityFoundryBase { public int nextUpdate; public int lastFlow = 0; + + protected NTMMaterial neighborType; + protected boolean hasCheckedNeighbors; @Override public void updateEntity() { if(!worldObj.isRemote) { + + // Initialise before allowing pours, so newly added channels will avoid causing clog feeds + if(!hasCheckedNeighbors) { + List visited = new ArrayList(); + visited.add(this); + + neighborType = checkNeighbors(visited); + hasCheckedNeighbors = true; + } if(this.type == null && this.amount != 0) { this.amount = 0; @@ -35,7 +50,7 @@ public class TileEntityFoundryChannel extends TileEntityFoundryBase { boolean hasOp = false; nextUpdate = 5; - List ints = new ArrayList() {{ add(2); add(3); add(4); add(5); }}; + List ints = new ArrayList() {{ add(2); add(3); add(4); add(5); }}; Collections.shuffle(ints); if(lastFlow > 0) { ints.remove((Integer) this.lastFlow); @@ -54,6 +69,8 @@ public class TileEntityFoundryChannel extends TileEntityFoundryBase { if(left == null) { this.type = null; this.amount = 0; + + propagateMaterial(null); } else { this.amount = left.amount; } @@ -117,11 +134,90 @@ public class TileEntityFoundryChannel extends TileEntityFoundryBase { public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); this.lastFlow = nbt.getByte("flow"); + this.neighborType = Mats.matById.get(nbt.getInteger("nType")); + this.hasCheckedNeighbors = nbt.getBoolean("init"); } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); nbt.setByte("flow", (byte) this.lastFlow); + nbt.setInteger("nType", this.neighborType != null ? this.neighborType.id : -1); + nbt.setBoolean("init", hasCheckedNeighbors); } + + /** + * Channels accept pouring as normal, except when neighbor channels already have material. + * This prevents a contiguous channel from having multiple different types of material in it, causing clogs. + * If you connect two channels that have different materials already in them, god help you (nah jokes it'll just be clogged until you fix manually) + */ + @Override + public boolean canAcceptPartialPour(World world, int x, int y, int z, double dX, double dY, double dZ, ForgeDirection side, MaterialStack stack) { + if(!hasCheckedNeighbors || (neighborType != null && neighborType != stack.material)) return false; + return super.canAcceptPartialPour(world, x, y, z, dX, dY, dZ, side, stack); + } + + /** Upon pouring, propagate the current material type along contiguous channels */ + @Override + public MaterialStack pour(World world, int x, int y, int z, double dX, double dY, double dZ, ForgeDirection side, MaterialStack stack) { + propagateMaterial(stack.material); + return super.pour(world, x, y, z, dX, dY, dZ, side, stack); + } + + protected void propagateMaterial(NTMMaterial propType) { + if(propType != null && neighborType != null) return; // optimise away any pours that change nothing + + List visited = new ArrayList(); + visited.add(this); + + boolean hasMaterial = propagateMaterial(propType, visited, false); + + // since we are now fully clear, it's safe to unassign the contiguous channel type + if(propType == null && !hasMaterial) { + for(TileEntityFoundryChannel acc : visited) { + acc.neighborType = null; + } + } + } + + protected boolean propagateMaterial(NTMMaterial propType, List visited, boolean hasMaterial) { + // if emptying, don't allow the channel to be marked as ready for a new material until it is entirely clear + if(propType != null) neighborType = propType; + + for(ForgeDirection dir : new ForgeDirection[] { ForgeDirection.NORTH, ForgeDirection.SOUTH, ForgeDirection.WEST, ForgeDirection.EAST }) { + TileEntity b = worldObj.getTileEntity(xCoord + dir.offsetX, yCoord, zCoord + dir.offsetZ); + + if(b instanceof TileEntityFoundryChannel && !visited.contains(b)) { + TileEntityFoundryChannel acc = (TileEntityFoundryChannel) b; + visited.add(acc); + + if(acc.amount > 0) hasMaterial = true; + + hasMaterial = acc.propagateMaterial(propType, visited, hasMaterial); + } + } + + return hasMaterial; + } + + protected NTMMaterial checkNeighbors(List visited) { + if(neighborType != null) return neighborType; + + for(ForgeDirection dir : new ForgeDirection[] { ForgeDirection.NORTH, ForgeDirection.SOUTH, ForgeDirection.WEST, ForgeDirection.EAST }) { + TileEntity b = worldObj.getTileEntity(xCoord + dir.offsetX, yCoord, zCoord + dir.offsetZ); + + if(b instanceof TileEntityFoundryChannel && !visited.contains(b)) { + TileEntityFoundryChannel acc = (TileEntityFoundryChannel) b; + visited.add(acc); + + NTMMaterial neighborMaterial = acc.checkNeighbors(visited); + + // immediately propagate backwards if a material is found + if(neighborMaterial != null) return neighborMaterial; + } + } + + return null; + } + } From e65a98421fbfb3ddcb456c9345ba0e5d35170403 Mon Sep 17 00:00:00 2001 From: George Paton Date: Mon, 27 Jan 2025 10:13:11 +1100 Subject: [PATCH 2/2] handle shovels and prevent any unforeseen issues (like if a channel gets separated by breaking/explosion) --- .../hbm/blocks/machine/FoundryChannel.java | 1 + .../machine/TileEntityFoundryChannel.java | 21 ++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/hbm/blocks/machine/FoundryChannel.java b/src/main/java/com/hbm/blocks/machine/FoundryChannel.java index 8866bfd0f..84faf6dee 100644 --- a/src/main/java/com/hbm/blocks/machine/FoundryChannel.java +++ b/src/main/java/com/hbm/blocks/machine/FoundryChannel.java @@ -176,6 +176,7 @@ public class FoundryChannel extends BlockContainer implements ICrucibleAcceptor } cast.amount = 0; cast.type = null; + cast.propagateMaterial(null); cast.markDirty(); world.markBlockForUpdate(x, y, z); } diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntityFoundryChannel.java b/src/main/java/com/hbm/tileentity/machine/TileEntityFoundryChannel.java index a3d50cc76..d20e8acb0 100644 --- a/src/main/java/com/hbm/tileentity/machine/TileEntityFoundryChannel.java +++ b/src/main/java/com/hbm/tileentity/machine/TileEntityFoundryChannel.java @@ -24,6 +24,7 @@ public class TileEntityFoundryChannel extends TileEntityFoundryBase { protected NTMMaterial neighborType; protected boolean hasCheckedNeighbors; + protected int unpropagateTime; @Override public void updateEntity() { @@ -115,10 +116,19 @@ public class TileEntityFoundryChannel extends TileEntityFoundryBase { } } } + + if(neighborType != null && amount == 0) unpropagateTime++; + + // every 5 seconds do a unprop test, will only occur once per contiguous channel per 5 seconds due to the timer getting updated in all channels from the prop + if(unpropagateTime > 100) { + propagateMaterial(null); + } if(this.amount == 0) { this.lastFlow = 0; this.nextUpdate = 5; + } else { + unpropagateTime = 0; } } @@ -164,7 +174,7 @@ public class TileEntityFoundryChannel extends TileEntityFoundryBase { return super.pour(world, x, y, z, dX, dY, dZ, side, stack); } - protected void propagateMaterial(NTMMaterial propType) { + public void propagateMaterial(NTMMaterial propType) { if(propType != null && neighborType != null) return; // optimise away any pours that change nothing List visited = new ArrayList(); @@ -181,8 +191,13 @@ public class TileEntityFoundryChannel extends TileEntityFoundryBase { } protected boolean propagateMaterial(NTMMaterial propType, List visited, boolean hasMaterial) { - // if emptying, don't allow the channel to be marked as ready for a new material until it is entirely clear - if(propType != null) neighborType = propType; + // if emptying, don't mark the channel as ready for a new material until it is entirely clear + if(propType != null) { + neighborType = propType; + } else { + // and when empty testing, update the last unpropagate time + unpropagateTime = 0; + } for(ForgeDirection dir : new ForgeDirection[] { ForgeDirection.NORTH, ForgeDirection.SOUTH, ForgeDirection.WEST, ForgeDirection.EAST }) { TileEntity b = worldObj.getTileEntity(xCoord + dir.offsetX, yCoord, zCoord + dir.offsetZ);