diff --git a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java index 97200ab8518..dac9672978a 100644 --- a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java +++ b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java @@ -11,11 +11,17 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.lang.ref.WeakReference; import java.util.Arrays; +import java.util.List; public abstract class NeighborCacheTileEntityBase extends SyncedTileEntityBase implements INeighborCache { - private final TileEntity[] neighbors = new TileEntity[6]; + private static final WeakReference NULL = new WeakReference<>(null); + private static final WeakReference INVALID = new WeakReference<>(null); + + private final List> neighbors = Arrays.asList( + INVALID, INVALID, INVALID, INVALID, INVALID, INVALID); private boolean neighborsInvalidated = false; public NeighborCacheTileEntityBase() { @@ -24,7 +30,9 @@ public NeighborCacheTileEntityBase() { protected void invalidateNeighbors() { if (!this.neighborsInvalidated) { - Arrays.fill(this.neighbors, this); + for (EnumFacing value : EnumFacing.VALUES) { + this.neighbors.set(value.getIndex(), INVALID); + } this.neighborsInvalidated = true; } } @@ -60,17 +68,34 @@ public void onChunkUnload() { @Override public @Nullable TileEntity getNeighbor(@NotNull EnumFacing facing) { if (world == null || pos == null) return null; - int i = facing.getIndex(); - TileEntity neighbor = this.neighbors[i]; - if (neighbor == this || (neighbor != null && neighbor.isInvalid())) { - neighbor = world.getTileEntity(pos.offset(facing)); - this.neighbors[i] = neighbor; - this.neighborsInvalidated = false; - } - return neighbor; + // if the ref is INVALID, compute neighbor, otherwise, return TE or null + WeakReference ref = invalidRef(facing) ? computeNeighbor(facing) : getRef(facing); + return ref.get(); + } + + private boolean invalidRef(EnumFacing facing) { + WeakReference ref = getRef(facing); + if (ref == INVALID) return true; + TileEntity te = ref.get(); + return te != null && te.isInvalid(); + } + + @NotNull + private WeakReference computeNeighbor(EnumFacing facing) { + TileEntity te = super.getNeighbor(facing); + // avoid making new references to null TEs + WeakReference ref = te == null ? NULL : new WeakReference<>(te); + this.neighbors.set(facing.getIndex(), ref); + this.neighborsInvalidated = false; + return ref; + } + + @NotNull + private WeakReference getRef(EnumFacing facing) { + return this.neighbors.get(facing.getIndex()); } public void onNeighborChanged(@NotNull EnumFacing facing) { - this.neighbors[facing.getIndex()] = this; + this.neighbors.set(facing.getIndex(), INVALID); } }