Skip to content

Commit 41f3711

Browse files
authored
Rework Neighbor Cache to use Weak References (#2828)
1 parent 62f148a commit 41f3711

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,17 @@
1111
import org.jetbrains.annotations.NotNull;
1212
import org.jetbrains.annotations.Nullable;
1313

14+
import java.lang.ref.WeakReference;
1415
import java.util.Arrays;
16+
import java.util.List;
1517

1618
public abstract class NeighborCacheTileEntityBase extends SyncedTileEntityBase implements INeighborCache {
1719

18-
private final TileEntity[] neighbors = new TileEntity[6];
20+
private static final WeakReference<TileEntity> NULL = new WeakReference<>(null);
21+
private static final WeakReference<TileEntity> INVALID = new WeakReference<>(null);
22+
23+
private final List<WeakReference<TileEntity>> neighbors = Arrays.asList(
24+
INVALID, INVALID, INVALID, INVALID, INVALID, INVALID);
1925
private boolean neighborsInvalidated = false;
2026

2127
public NeighborCacheTileEntityBase() {
@@ -24,7 +30,9 @@ public NeighborCacheTileEntityBase() {
2430

2531
protected void invalidateNeighbors() {
2632
if (!this.neighborsInvalidated) {
27-
Arrays.fill(this.neighbors, this);
33+
for (EnumFacing value : EnumFacing.VALUES) {
34+
this.neighbors.set(value.getIndex(), INVALID);
35+
}
2836
this.neighborsInvalidated = true;
2937
}
3038
}
@@ -60,17 +68,34 @@ public void onChunkUnload() {
6068
@Override
6169
public @Nullable TileEntity getNeighbor(@NotNull EnumFacing facing) {
6270
if (world == null || pos == null) return null;
63-
int i = facing.getIndex();
64-
TileEntity neighbor = this.neighbors[i];
65-
if (neighbor == this || (neighbor != null && neighbor.isInvalid())) {
66-
neighbor = world.getTileEntity(pos.offset(facing));
67-
this.neighbors[i] = neighbor;
68-
this.neighborsInvalidated = false;
69-
}
70-
return neighbor;
71+
// if the ref is INVALID, compute neighbor, otherwise, return TE or null
72+
WeakReference<TileEntity> ref = invalidRef(facing) ? computeNeighbor(facing) : getRef(facing);
73+
return ref.get();
74+
}
75+
76+
private boolean invalidRef(EnumFacing facing) {
77+
WeakReference<TileEntity> ref = getRef(facing);
78+
if (ref == INVALID) return true;
79+
TileEntity te = ref.get();
80+
return te != null && te.isInvalid();
81+
}
82+
83+
@NotNull
84+
private WeakReference<TileEntity> computeNeighbor(EnumFacing facing) {
85+
TileEntity te = super.getNeighbor(facing);
86+
// avoid making new references to null TEs
87+
WeakReference<TileEntity> ref = te == null ? NULL : new WeakReference<>(te);
88+
this.neighbors.set(facing.getIndex(), ref);
89+
this.neighborsInvalidated = false;
90+
return ref;
91+
}
92+
93+
@NotNull
94+
private WeakReference<TileEntity> getRef(EnumFacing facing) {
95+
return this.neighbors.get(facing.getIndex());
7196
}
7297

7398
public void onNeighborChanged(@NotNull EnumFacing facing) {
74-
this.neighbors[facing.getIndex()] = this;
99+
this.neighbors.set(facing.getIndex(), INVALID);
75100
}
76101
}

0 commit comments

Comments
 (0)