-
-
Notifications
You must be signed in to change notification settings - Fork 44
/
TickRegion.java
132 lines (116 loc) · 3.73 KB
/
TickRegion.java
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
122
123
124
125
126
127
128
129
130
131
132
package me.nallar.tickthreading.minecraft.tickregion;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import me.nallar.tickthreading.minecraft.TickManager;
import net.minecraft.world.World;
public abstract class TickRegion implements Runnable {
protected final Object tickStateLock = new Object();
protected volatile boolean ticking = false;
protected final Set toRemove = new LinkedHashSet();
protected final Set toAdd = new LinkedHashSet();
volatile Lock thisLock = new ReentrantLock();
volatile Lock xPlusLock = null;
volatile Lock xMinusLock = null;
volatile Lock zPlusLock = null;
volatile Lock zMinusLock = null;
final World world;
final TickManager manager;
public final int hashCode;
private final int regionX;
private final int regionZ;
private float averageTickTime = 1;
TickRegion(World world, TickManager manager, int regionX, int regionZ) {
super();
this.world = world;
this.manager = manager;
this.hashCode = TickManager.getHashCodeFromRegionCoords(regionX, regionZ);
this.regionX = regionX;
this.regionZ = regionZ;
setupLocks();
}
private void setupLocks() {
TickRegion tickRegion = getCallable(regionX + 1, regionZ);
if (tickRegion != null) {
tickRegion.xMinusLock = thisLock;
this.xPlusLock = tickRegion.thisLock;
}
tickRegion = getCallable(regionX - 1, regionZ);
if (tickRegion != null) {
tickRegion.xPlusLock = thisLock;
this.xMinusLock = tickRegion.thisLock;
}
tickRegion = getCallable(regionX, regionZ + 1);
if (tickRegion != null) {
tickRegion.zMinusLock = thisLock;
this.zPlusLock = tickRegion.thisLock;
}
tickRegion = getCallable(regionX, regionZ - 1);
if (tickRegion != null) {
tickRegion.zPlusLock = thisLock;
this.zMinusLock = tickRegion.thisLock;
}
}
public void die() {
thisLock = null;
TickRegion tickRegion = getCallable(regionX + 1, regionZ);
if (tickRegion != null) {
tickRegion.xMinusLock = null;
}
tickRegion = getCallable(regionX - 1, regionZ);
if (tickRegion != null) {
tickRegion.xPlusLock = null;
}
tickRegion = getCallable(regionX, regionZ + 1);
if (tickRegion != null) {
tickRegion.zMinusLock = null;
}
tickRegion = getCallable(regionX, regionZ - 1);
if (tickRegion != null) {
tickRegion.zPlusLock = null;
}
}
@Override
public void run() {
if (shouldTick()) {
long startTime = System.currentTimeMillis();
synchronized (tickStateLock) {
ticking = true;
}
doTick();
synchronized (tickStateLock) {
ticking = false;
}
averageTickTime = ((averageTickTime * 127) + (System.currentTimeMillis() - startTime)) / 128;
}
}
boolean shouldTick() {
return !manager.variableTickRate || averageTickTime < 55 || Math.random() < ((float) 55) / averageTickTime;
}
protected abstract void doTick();
public float getAverageTickTime() {
return averageTickTime;
}
public String getStats() {
return "X: " + regionX * manager.regionSize + ", Z: " + regionZ * manager.regionSize + ", time: " + getAverageTickTime() + "ms";
}
@Override
public String toString() {
return "rX: " + regionX + ", rZ: " + regionZ + ", hashCode: " + hashCode;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof TickRegion)) {
return false;
}
TickRegion otherTickRegion = (TickRegion) other;
return otherTickRegion.hashCode == this.hashCode && this.getClass().isInstance(other);
}
protected abstract TickRegion getCallable(int regionX, int regionZ);
public abstract boolean isEmpty();
public abstract void processChanges();
}