forked from daveyliam/mapwriter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathChunkManager.java
167 lines (141 loc) · 4.68 KB
/
ChunkManager.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package mapwriter;
import java.util.Map;
import mapwriter.map.MapTexture;
import mapwriter.region.MwChunk;
import mapwriter.region.RegionManager;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
public class ChunkManager {
public Mw mw;
private boolean closed = false;
private CircularHashMap<Chunk, Integer> chunkMap = new CircularHashMap<Chunk, Integer>();
private static final int VISIBLE_FLAG = 0x01;
private static final int VIEWED_FLAG = 0x02;
public ChunkManager(Mw mw) {
this.mw = mw;
}
public synchronized void close() {
this.closed = true;
this.saveChunks();
this.chunkMap.clear();
}
// create MwChunk from Minecraft chunk.
// only MwChunk's should be used in the background thread.
// TODO: make this a full copy of chunk data
public static MwChunk copyToMwChunk(Chunk chunk) {
byte[][] msbArray = new byte[16][];
byte[][] lsbArray = new byte[16][];
byte[][] metaArray = new byte[16][];
ExtendedBlockStorage[] storageArrays = chunk.getBlockStorageArray();
if (storageArrays != null) {
for (ExtendedBlockStorage storage : storageArrays) {
if (storage != null) {
int y = (storage.getYLocation() >> 4) & 0xf;
lsbArray[y] = storage.getBlockLSBArray();
msbArray[y] = (storage.getBlockMSBArray() != null) ? storage.getBlockMSBArray().data : null;
metaArray[y] = (storage.getMetadataArray() != null) ? storage.getMetadataArray().data : null;
}
}
}
return new MwChunk(chunk.xPosition, chunk.zPosition, chunk.worldObj.provider.dimensionId,
msbArray, lsbArray, metaArray, chunk.getBiomeArray());
}
public synchronized void addChunk(Chunk chunk) {
if (!this.closed && (chunk != null)) {
this.chunkMap.put(chunk, 0);
}
}
public synchronized void removeChunk(Chunk chunk) {
if (!this.closed && (chunk != null)) {
int flags = this.chunkMap.get(chunk);
if ((flags & VIEWED_FLAG) != 0) {
this.addSaveChunkTask(chunk);
}
this.chunkMap.remove(chunk);
}
}
public synchronized void saveChunks() {
for (Map.Entry<Chunk, Integer> entry : this.chunkMap.entrySet()) {
int flags = entry.getValue();
if ((flags & VIEWED_FLAG) != 0) {
this.addSaveChunkTask(entry.getKey());
}
}
}
public class MapUpdateChunksTask extends Task {
MwChunk[] chunkArray;
RegionManager regionManager;
MapTexture mapTexture;
public MapUpdateChunksTask(MapTexture mapTexture, RegionManager regionManager, MwChunk[] chunkArray) {
this.mapTexture = mapTexture;
this.regionManager = regionManager;
this.chunkArray = chunkArray;
}
@Override
public void run() {
for (MwChunk chunk : this.chunkArray) {
if (chunk != null) {
// update the chunk in the region pixels
this.regionManager.updateChunk(chunk);
// copy updated region pixels to maptexture
this.mapTexture.updateChunk(this.regionManager, chunk);
}
}
// unload least accessed regions
this.regionManager.pruneRegions();
}
@Override
public void onComplete() {
}
}
public void onTick() {
if (!this.closed) {
int chunksToUpdate = Math.min(this.chunkMap.size(), this.mw.chunksPerTick);
MwChunk[] chunkArray = new MwChunk[chunksToUpdate];
for (int i = 0; i < chunksToUpdate; i++) {
Map.Entry<Chunk, Integer> entry = this.chunkMap.getNextEntry();
if (entry != null) {
// if this chunk is within a certain distance to the player then
// add it to the viewed set
Chunk chunk = entry.getKey();
int flags = entry.getValue();
if (MwUtil.distToChunkSq(this.mw.playerXInt, this.mw.playerZInt, chunk) <= this.mw.maxChunkSaveDistSq) {
flags |= (VISIBLE_FLAG | VIEWED_FLAG);
} else {
flags &= ~VISIBLE_FLAG;
}
entry.setValue(flags);
if ((flags & VISIBLE_FLAG) != 0) {
chunkArray[i] = copyToMwChunk(chunk);
} else {
chunkArray[i] = null;
}
}
}
this.mw.executor.addTask(new MapUpdateChunksTask(this.mw.mapTexture, this.mw.regionManager, chunkArray));
}
}
public void forceChunks(MwChunk[] chunks){
this.mw.executor.addTask(new MapUpdateChunksTask(this.mw.mapTexture, this.mw.regionManager, chunks));
}
private class SaveChunkTask extends Task {
private final RegionManager regionManager;
private final MwChunk mwChunk;
public SaveChunkTask(RegionManager regionManager, MwChunk mwChunk) {
this.regionManager = regionManager;
this.mwChunk = mwChunk;
}
@Override
public void run() {
this.regionManager.saveChunk(this.mwChunk);
}
@Override
public void onComplete() {
}
}
private void addSaveChunkTask(Chunk chunk) {
if (!chunk.isEmpty()) {
this.mw.executor.addTask(new SaveChunkTask(this.mw.regionManager, copyToMwChunk(chunk)));
}
}
}