-
Notifications
You must be signed in to change notification settings - Fork 214
Expand file tree
/
Copy pathNeighborCacheTileEntityBase.java
More file actions
121 lines (101 loc) · 4.08 KB
/
NeighborCacheTileEntityBase.java
File metadata and controls
121 lines (101 loc) · 4.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package gregtech.api.metatileentity;
import gregtech.api.metatileentity.interfaces.INeighborCache;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.jetbrains.annotations.MustBeInvokedByOverriders;
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 static final WeakReference<TileEntity> NULL = new WeakReference<>(null);
private static final WeakReference<TileEntity> INVALID = new WeakReference<>(null);
private final List<WeakReference<TileEntity>> neighbors = Arrays.asList(
INVALID, INVALID, INVALID, INVALID, INVALID, INVALID);
private boolean neighborsInvalidated = false;
public NeighborCacheTileEntityBase() {
invalidateNeighbors(false);
}
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;
}
}
@MustBeInvokedByOverriders
@Override
public void setWorld(@NotNull World worldIn) {
super.setWorld(worldIn);
invalidateNeighbors(false);
}
@MustBeInvokedByOverriders
@Override
public void setPos(@NotNull BlockPos posIn) {
super.setPos(posIn);
invalidateNeighbors(false);
}
@MustBeInvokedByOverriders
@Override
public void invalidate() {
super.invalidate();
invalidateNeighbors(false);
}
@MustBeInvokedByOverriders
@Override
public void onChunkUnload() {
super.onChunkUnload();
invalidateNeighbors(true);
}
@Override
public @Nullable TileEntity getNeighbor(@NotNull EnumFacing facing) {
if (world == null || pos == null) return null;
// if the ref is INVALID, compute neighbor, otherwise, return TE or null
WeakReference<TileEntity> ref = invalidRef(facing) ? computeNeighbor(facing) : getRef(facing);
return ref.get();
}
private boolean invalidRef(EnumFacing facing) {
WeakReference<TileEntity> ref = getRef(facing);
if (ref == INVALID || crossesUnloadedChunk(facing)) return true;
TileEntity te = ref.get();
return te != null && te.isInvalid();
}
private boolean crossesUnloadedChunk(EnumFacing facing) {
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<TileEntity> computeNeighbor(EnumFacing facing) {
TileEntity te = super.getNeighbor(facing);
// avoid making new references to null TEs
WeakReference<TileEntity> ref = te == null ? NULL : new WeakReference<>(te);
this.neighbors.set(facing.getIndex(), ref);
this.neighborsInvalidated = false;
return ref;
}
@NotNull
private WeakReference<TileEntity> getRef(EnumFacing facing) {
return this.neighbors.get(facing.getIndex());
}
public void onNeighborChanged(@NotNull EnumFacing facing) {
this.neighbors.set(facing.getIndex(), INVALID);
}
}