1111import org .jetbrains .annotations .NotNull ;
1212import org .jetbrains .annotations .Nullable ;
1313
14+ import java .lang .ref .WeakReference ;
1415import java .util .Arrays ;
16+ import java .util .List ;
1517
1618public 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