From eccd6ec18c32d8773371e99c919fce7314535856 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Wed, 12 Nov 2025 23:20:28 -0700 Subject: [PATCH 1/5] implement chunk boundary check --- .../api/metatileentity/NeighborCacheTileEntityBase.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java index dac9672978a..fccce8595dc 100644 --- a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java +++ b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java @@ -75,11 +75,18 @@ public void onChunkUnload() { private boolean invalidRef(EnumFacing facing) { WeakReference ref = getRef(facing); - if (ref == INVALID) return true; + if (ref == INVALID || crossesChunk(facing)) return true; TileEntity te = ref.get(); return te != null && te.isInvalid(); } + private boolean crossesChunk(EnumFacing facing) { + BlockPos pos = getPos(); + BlockPos offset = getPos().offset(facing); + return pos.getX() >> 4 != offset.getX() >> 4 || + pos.getZ() >> 4 != offset.getZ() >> 4; + } + @NotNull private WeakReference computeNeighbor(EnumFacing facing) { TileEntity te = super.getNeighbor(facing); From 2a863513874e586004ed89a5dabbc21718cbc5f4 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Wed, 12 Nov 2025 23:28:22 -0700 Subject: [PATCH 2/5] actually check if chunk is unloaded --- .../NeighborCacheTileEntityBase.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java index fccce8595dc..442dbd6d05b 100644 --- a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java +++ b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java @@ -75,16 +75,20 @@ public void onChunkUnload() { private boolean invalidRef(EnumFacing facing) { WeakReference ref = getRef(facing); - if (ref == INVALID || crossesChunk(facing)) return true; + if (ref == INVALID || crossesUnloadedChunk(facing)) return true; TileEntity te = ref.get(); return te != null && te.isInvalid(); } - private boolean crossesChunk(EnumFacing facing) { - BlockPos pos = getPos(); + private boolean crossesUnloadedChunk(EnumFacing facing) { + int cx = getPos().getX() >> 4, cz = getPos().getZ() >> 4; BlockPos offset = getPos().offset(facing); - return pos.getX() >> 4 != offset.getX() >> 4 || - pos.getZ() >> 4 != offset.getZ() >> 4; + int ncx = offset.getX() >> 4, ncz = offset.getZ() >> 4; + + if (cx != ncx || cz != ncz) { + return getWorld().getChunkProvider().getLoadedChunk(ncx, ncz) == null; + } + return false; } @NotNull From e88b75d930ec45716e315518e6640a4815c8a455 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Fri, 14 Nov 2025 18:23:34 -0700 Subject: [PATCH 3/5] on chunk unload, notify neighbors if crossing a chunk to invalidate us --- .../NeighborCacheTileEntityBase.java | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java index 442dbd6d05b..8d5d077250e 100644 --- a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java +++ b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java @@ -25,12 +25,16 @@ public abstract class NeighborCacheTileEntityBase extends SyncedTileEntityBase i private boolean neighborsInvalidated = false; public NeighborCacheTileEntityBase() { - invalidateNeighbors(); + invalidateNeighbors(false); } - protected void invalidateNeighbors() { + protected void invalidateNeighbors(boolean notify) { if (!this.neighborsInvalidated) { for (EnumFacing value : EnumFacing.VALUES) { + if (notify && crossesChunk(value) && getNeighbor(value) instanceof INeighborCache neighborCache) { + // notify neighbor on a different chunk to invalidate us + neighborCache.onNeighborChanged(value.getOpposite()); + } this.neighbors.set(value.getIndex(), INVALID); } this.neighborsInvalidated = true; @@ -41,28 +45,28 @@ protected void invalidateNeighbors() { @Override public void setWorld(@NotNull World worldIn) { super.setWorld(worldIn); - invalidateNeighbors(); + invalidateNeighbors(false); } @MustBeInvokedByOverriders @Override public void setPos(@NotNull BlockPos posIn) { super.setPos(posIn); - invalidateNeighbors(); + invalidateNeighbors(false); } @MustBeInvokedByOverriders @Override public void invalidate() { super.invalidate(); - invalidateNeighbors(); + invalidateNeighbors(false); } @MustBeInvokedByOverriders @Override public void onChunkUnload() { super.onChunkUnload(); - invalidateNeighbors(); + invalidateNeighbors(true); } @Override @@ -81,16 +85,21 @@ private boolean invalidRef(EnumFacing facing) { } private boolean crossesUnloadedChunk(EnumFacing facing) { - int cx = getPos().getX() >> 4, cz = getPos().getZ() >> 4; - BlockPos offset = getPos().offset(facing); - int ncx = offset.getX() >> 4, ncz = offset.getZ() >> 4; - - if (cx != ncx || cz != ncz) { + if (crossesChunk(facing)) { + int ncx = getPos().offset(facing).getX() >> 4; + int ncz = getPos().offset(facing).getZ() >> 4; return getWorld().getChunkProvider().getLoadedChunk(ncx, ncz) == null; } return false; } + private boolean crossesChunk(EnumFacing facing) { + int cx = getPos().getX() >> 4, cz = getPos().getZ() >> 4; + BlockPos offset = getPos().offset(facing); + int ncx = offset.getX() >> 4, ncz = offset.getZ() >> 4; + return cx != ncx || cz != ncz; + } + @NotNull private WeakReference computeNeighbor(EnumFacing facing) { TileEntity te = super.getNeighbor(facing); From 93c5d3c7aaa46ce7385732d97b40410dedb925cd Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 15 Nov 2025 02:11:23 -0700 Subject: [PATCH 4/5] expand and notify all tile entities --- .../api/metatileentity/NeighborCacheTileEntityBase.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java index 8d5d077250e..6d6e893802b 100644 --- a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java +++ b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java @@ -2,6 +2,7 @@ import gregtech.api.metatileentity.interfaces.INeighborCache; +import net.minecraft.block.state.IBlockState; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; @@ -31,9 +32,13 @@ public NeighborCacheTileEntityBase() { protected void invalidateNeighbors(boolean notify) { if (!this.neighborsInvalidated) { for (EnumFacing value : EnumFacing.VALUES) { - if (notify && crossesChunk(value) && getNeighbor(value) instanceof INeighborCache neighborCache) { + if (notify && crossesChunk(value)) { // notify neighbor on a different chunk to invalidate us - neighborCache.onNeighborChanged(value.getOpposite()); + TileEntity neighbor = getNeighbor(value); + if (neighbor != null) { + IBlockState state = getWorld().getBlockState(neighbor.getPos()); + state.neighborChanged(getWorld(), neighbor.getPos(), getBlockType(), getPos()); + } } this.neighbors.set(value.getIndex(), INVALID); } From 3679bc71f4aa69e0de8a9ac9170d96db5eaa56c3 Mon Sep 17 00:00:00 2001 From: Ghzdude <44148655+ghzdude@users.noreply.github.com> Date: Sat, 15 Nov 2025 02:54:37 -0700 Subject: [PATCH 5/5] no need to actually notify other TEs in this way --- .../NeighborCacheTileEntityBase.java | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java index 6d6e893802b..9972e817b1c 100644 --- a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java +++ b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java @@ -2,7 +2,6 @@ import gregtech.api.metatileentity.interfaces.INeighborCache; -import net.minecraft.block.state.IBlockState; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; @@ -26,20 +25,12 @@ public abstract class NeighborCacheTileEntityBase extends SyncedTileEntityBase i private boolean neighborsInvalidated = false; public NeighborCacheTileEntityBase() { - invalidateNeighbors(false); + invalidateNeighbors(); } - protected void invalidateNeighbors(boolean notify) { + protected void invalidateNeighbors() { if (!this.neighborsInvalidated) { for (EnumFacing value : EnumFacing.VALUES) { - if (notify && crossesChunk(value)) { - // notify neighbor on a different chunk to invalidate us - TileEntity neighbor = getNeighbor(value); - if (neighbor != null) { - IBlockState state = getWorld().getBlockState(neighbor.getPos()); - state.neighborChanged(getWorld(), neighbor.getPos(), getBlockType(), getPos()); - } - } this.neighbors.set(value.getIndex(), INVALID); } this.neighborsInvalidated = true; @@ -50,28 +41,28 @@ protected void invalidateNeighbors(boolean notify) { @Override public void setWorld(@NotNull World worldIn) { super.setWorld(worldIn); - invalidateNeighbors(false); + invalidateNeighbors(); } @MustBeInvokedByOverriders @Override public void setPos(@NotNull BlockPos posIn) { super.setPos(posIn); - invalidateNeighbors(false); + invalidateNeighbors(); } @MustBeInvokedByOverriders @Override public void invalidate() { super.invalidate(); - invalidateNeighbors(false); + invalidateNeighbors(); } @MustBeInvokedByOverriders @Override public void onChunkUnload() { super.onChunkUnload(); - invalidateNeighbors(true); + invalidateNeighbors(); } @Override