Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lDEVinux
GitHub Repository: lDEVinux/eaglercraft
Path: blob/main/sp-server/src_aux/AnvilChunkLoader.java
8641 views
1
package net.minecraft.src;
2
3
import java.io.DataInputStream;
4
import java.io.DataOutputStream;
5
import java.io.File;
6
import java.io.IOException;
7
import java.util.ArrayList;
8
import java.util.HashSet;
9
import java.util.Iterator;
10
import java.util.List;
11
import java.util.Set;
12
13
public class AnvilChunkLoader implements IChunkLoader, IThreadedFileIO {
14
private List chunksToRemove = new ArrayList();
15
private Set pendingAnvilChunksCoordinates = new HashSet();
16
private Object syncLockObject = new Object();
17
18
/** Save directory for chunks using the Anvil format */
19
private final File chunkSaveLocation;
20
21
public AnvilChunkLoader(File par1File) {
22
this.chunkSaveLocation = par1File;
23
}
24
25
/**
26
* Loads the specified(XZ) chunk into the specified world.
27
*/
28
public Chunk loadChunk(World par1World, int par2, int par3) throws IOException {
29
NBTTagCompound var4 = null;
30
ChunkCoordIntPair var5 = new ChunkCoordIntPair(par2, par3);
31
Object var6 = this.syncLockObject;
32
33
synchronized (this.syncLockObject) {
34
if (this.pendingAnvilChunksCoordinates.contains(var5)) {
35
for (int var7 = 0; var7 < this.chunksToRemove.size(); ++var7) {
36
if (((AnvilChunkLoaderPending) this.chunksToRemove.get(var7)).chunkCoordinate.equals(var5)) {
37
var4 = ((AnvilChunkLoaderPending) this.chunksToRemove.get(var7)).nbtTags;
38
break;
39
}
40
}
41
}
42
}
43
44
if (var4 == null) {
45
DataInputStream var10 = RegionFileCache.getChunkInputStream(this.chunkSaveLocation, par2, par3);
46
47
if (var10 == null) {
48
return null;
49
}
50
51
var4 = CompressedStreamTools.read(var10);
52
}
53
54
return this.checkedReadChunkFromNBT(par1World, par2, par3, var4);
55
}
56
57
/**
58
* Wraps readChunkFromNBT. Checks the coordinates and several NBT tags.
59
*/
60
protected Chunk checkedReadChunkFromNBT(World par1World, int par2, int par3, NBTTagCompound par4NBTTagCompound) {
61
if (!par4NBTTagCompound.hasKey("Level")) {
62
par1World.getWorldLogAgent()
63
.logSevere("Chunk file at " + par2 + "," + par3 + " is missing level data, skipping");
64
return null;
65
} else if (!par4NBTTagCompound.getCompoundTag("Level").hasKey("Sections")) {
66
par1World.getWorldLogAgent()
67
.logSevere("Chunk file at " + par2 + "," + par3 + " is missing block data, skipping");
68
return null;
69
} else {
70
Chunk var5 = this.readChunkFromNBT(par1World, par4NBTTagCompound.getCompoundTag("Level"));
71
72
if (!var5.isAtLocation(par2, par3)) {
73
par1World.getWorldLogAgent()
74
.logSevere("Chunk file at " + par2 + "," + par3
75
+ " is in the wrong location; relocating. (Expected " + par2 + ", " + par3 + ", got "
76
+ var5.xPosition + ", " + var5.zPosition + ")");
77
par4NBTTagCompound.setInteger("xPos", par2);
78
par4NBTTagCompound.setInteger("zPos", par3);
79
var5 = this.readChunkFromNBT(par1World, par4NBTTagCompound.getCompoundTag("Level"));
80
}
81
82
return var5;
83
}
84
}
85
86
public void saveChunk(World par1World, Chunk par2Chunk) throws MinecraftException, IOException {
87
par1World.checkSessionLock();
88
89
try {
90
NBTTagCompound var3 = new NBTTagCompound();
91
NBTTagCompound var4 = new NBTTagCompound();
92
var3.setTag("Level", var4);
93
this.writeChunkToNBT(par2Chunk, par1World, var4);
94
this.addChunkToPending(par2Chunk.getChunkCoordIntPair(), var3);
95
} catch (Exception var5) {
96
var5.printStackTrace();
97
}
98
}
99
100
protected void addChunkToPending(ChunkCoordIntPair par1ChunkCoordIntPair, NBTTagCompound par2NBTTagCompound) {
101
Object var3 = this.syncLockObject;
102
103
synchronized (this.syncLockObject) {
104
if (this.pendingAnvilChunksCoordinates.contains(par1ChunkCoordIntPair)) {
105
for (int var4 = 0; var4 < this.chunksToRemove.size(); ++var4) {
106
if (((AnvilChunkLoaderPending) this.chunksToRemove.get(var4)).chunkCoordinate
107
.equals(par1ChunkCoordIntPair)) {
108
this.chunksToRemove.set(var4,
109
new AnvilChunkLoaderPending(par1ChunkCoordIntPair, par2NBTTagCompound));
110
return;
111
}
112
}
113
}
114
115
this.chunksToRemove.add(new AnvilChunkLoaderPending(par1ChunkCoordIntPair, par2NBTTagCompound));
116
this.pendingAnvilChunksCoordinates.add(par1ChunkCoordIntPair);
117
ThreadedFileIOBase.threadedIOInstance.queueIO(this);
118
}
119
}
120
121
/**
122
* Returns a boolean stating if the write was unsuccessful.
123
*/
124
public boolean writeNextIO() {
125
AnvilChunkLoaderPending var1 = null;
126
Object var2 = this.syncLockObject;
127
128
synchronized (this.syncLockObject) {
129
if (this.chunksToRemove.isEmpty()) {
130
return false;
131
}
132
133
var1 = (AnvilChunkLoaderPending) this.chunksToRemove.remove(0);
134
this.pendingAnvilChunksCoordinates.remove(var1.chunkCoordinate);
135
}
136
137
if (var1 != null) {
138
try {
139
this.writeChunkNBTTags(var1);
140
} catch (Exception var4) {
141
var4.printStackTrace();
142
}
143
}
144
145
return true;
146
}
147
148
private void writeChunkNBTTags(AnvilChunkLoaderPending par1AnvilChunkLoaderPending) throws IOException {
149
DataOutputStream var2 = RegionFileCache.getChunkOutputStream(this.chunkSaveLocation,
150
par1AnvilChunkLoaderPending.chunkCoordinate.chunkXPos,
151
par1AnvilChunkLoaderPending.chunkCoordinate.chunkZPos);
152
CompressedStreamTools.write(par1AnvilChunkLoaderPending.nbtTags, var2);
153
var2.close();
154
}
155
156
/**
157
* Save extra data associated with this Chunk not normally saved during
158
* autosave, only during chunk unload. Currently unused.
159
*/
160
public void saveExtraChunkData(World par1World, Chunk par2Chunk) {
161
}
162
163
/**
164
* Called every World.tick()
165
*/
166
public void chunkTick() {
167
}
168
169
/**
170
* Save extra data not associated with any Chunk. Not saved during autosave,
171
* only during world unload. Currently unused.
172
*/
173
public void saveExtraData() {
174
while (this.writeNextIO()) {
175
;
176
}
177
}
178
179
/**
180
* Writes the Chunk passed as an argument to the NBTTagCompound also passed,
181
* using the World argument to retrieve the Chunk's last update time.
182
*/
183
private void writeChunkToNBT(Chunk par1Chunk, World par2World, NBTTagCompound par3NBTTagCompound) {
184
par3NBTTagCompound.setInteger("xPos", par1Chunk.xPosition);
185
par3NBTTagCompound.setInteger("zPos", par1Chunk.zPosition);
186
par3NBTTagCompound.setLong("LastUpdate", par2World.getTotalWorldTime());
187
par3NBTTagCompound.setIntArray("HeightMap", par1Chunk.heightMap);
188
par3NBTTagCompound.setBoolean("TerrainPopulated", par1Chunk.isTerrainPopulated);
189
ExtendedBlockStorage[] var4 = par1Chunk.getBlockStorageArray();
190
NBTTagList var5 = new NBTTagList("Sections");
191
boolean var6 = !par2World.provider.hasNoSky;
192
ExtendedBlockStorage[] var7 = var4;
193
int var8 = var4.length;
194
NBTTagCompound var11;
195
196
for (int var9 = 0; var9 < var8; ++var9) {
197
ExtendedBlockStorage var10 = var7[var9];
198
199
if (var10 != null) {
200
var11 = new NBTTagCompound();
201
var11.setByte("Y", (byte) (var10.getYLocation() >> 4 & 255));
202
var11.setByteArray("Blocks", var10.getBlockLSBArray());
203
204
if (var10.getBlockMSBArray() != null) {
205
var11.setByteArray("Add", var10.getBlockMSBArray().data);
206
}
207
208
var11.setByteArray("Data", var10.getMetadataArray().data);
209
var11.setByteArray("BlockLight", var10.getBlocklightArray().data);
210
211
if (var6) {
212
var11.setByteArray("SkyLight", var10.getSkylightArray().data);
213
} else {
214
var11.setByteArray("SkyLight", new byte[var10.getBlocklightArray().data.length]);
215
}
216
217
var5.appendTag(var11);
218
}
219
}
220
221
par3NBTTagCompound.setTag("Sections", var5);
222
par3NBTTagCompound.setByteArray("Biomes", par1Chunk.getBiomeArray());
223
par1Chunk.hasEntities = false;
224
NBTTagList var16 = new NBTTagList();
225
Iterator var18;
226
227
for (var8 = 0; var8 < par1Chunk.entityLists.length; ++var8) {
228
var18 = par1Chunk.entityLists[var8].iterator();
229
230
while (var18.hasNext()) {
231
Entity var20 = (Entity) var18.next();
232
var11 = new NBTTagCompound();
233
234
if (var20.addEntityID(var11)) {
235
par1Chunk.hasEntities = true;
236
var16.appendTag(var11);
237
}
238
}
239
}
240
241
par3NBTTagCompound.setTag("Entities", var16);
242
NBTTagList var17 = new NBTTagList();
243
var18 = par1Chunk.chunkTileEntityMap.values().iterator();
244
245
while (var18.hasNext()) {
246
TileEntity var21 = (TileEntity) var18.next();
247
var11 = new NBTTagCompound();
248
var21.writeToNBT(var11);
249
var17.appendTag(var11);
250
}
251
252
par3NBTTagCompound.setTag("TileEntities", var17);
253
List var19 = par2World.getPendingBlockUpdates(par1Chunk, false);
254
255
if (var19 != null) {
256
long var22 = par2World.getTotalWorldTime();
257
NBTTagList var12 = new NBTTagList();
258
Iterator var13 = var19.iterator();
259
260
while (var13.hasNext()) {
261
NextTickListEntry var14 = (NextTickListEntry) var13.next();
262
NBTTagCompound var15 = new NBTTagCompound();
263
var15.setInteger("i", var14.blockID);
264
var15.setInteger("x", var14.xCoord);
265
var15.setInteger("y", var14.yCoord);
266
var15.setInteger("z", var14.zCoord);
267
var15.setInteger("t", (int) (var14.scheduledTime - var22));
268
var15.setInteger("p", var14.field_82754_f);
269
var12.appendTag(var15);
270
}
271
272
par3NBTTagCompound.setTag("TileTicks", var12);
273
}
274
}
275
276
/**
277
* Reads the data stored in the passed NBTTagCompound and creates a Chunk with
278
* that data in the passed World. Returns the created Chunk.
279
*/
280
private Chunk readChunkFromNBT(World par1World, NBTTagCompound par2NBTTagCompound) {
281
int var3 = par2NBTTagCompound.getInteger("xPos");
282
int var4 = par2NBTTagCompound.getInteger("zPos");
283
Chunk var5 = new Chunk(par1World, var3, var4);
284
var5.heightMap = par2NBTTagCompound.getIntArray("HeightMap");
285
var5.isTerrainPopulated = par2NBTTagCompound.getBoolean("TerrainPopulated");
286
NBTTagList var6 = par2NBTTagCompound.getTagList("Sections");
287
byte var7 = 16;
288
ExtendedBlockStorage[] var8 = new ExtendedBlockStorage[var7];
289
boolean var9 = !par1World.provider.hasNoSky;
290
291
for (int var10 = 0; var10 < var6.tagCount(); ++var10) {
292
NBTTagCompound var11 = (NBTTagCompound) var6.tagAt(var10);
293
byte var12 = var11.getByte("Y");
294
ExtendedBlockStorage var13 = new ExtendedBlockStorage(var12 << 4, var9);
295
var13.setBlockLSBArray(var11.getByteArray("Blocks"));
296
297
if (var11.hasKey("Add")) {
298
var13.setBlockMSBArray(new NibbleArray(var11.getByteArray("Add"), 4));
299
}
300
301
var13.setBlockMetadataArray(new NibbleArray(var11.getByteArray("Data"), 4));
302
var13.setBlocklightArray(new NibbleArray(var11.getByteArray("BlockLight"), 4));
303
304
if (var9) {
305
var13.setSkylightArray(new NibbleArray(var11.getByteArray("SkyLight"), 4));
306
}
307
308
var13.removeInvalidBlocks();
309
var8[var12] = var13;
310
}
311
312
var5.setStorageArrays(var8);
313
314
if (par2NBTTagCompound.hasKey("Biomes")) {
315
var5.setBiomeArray(par2NBTTagCompound.getByteArray("Biomes"));
316
}
317
318
NBTTagList var17 = par2NBTTagCompound.getTagList("Entities");
319
320
if (var17 != null) {
321
for (int var18 = 0; var18 < var17.tagCount(); ++var18) {
322
NBTTagCompound var20 = (NBTTagCompound) var17.tagAt(var18);
323
Entity var22 = EntityList.createEntityFromNBT(var20, par1World);
324
var5.hasEntities = true;
325
326
if (var22 != null) {
327
var5.addEntity(var22);
328
Entity var14 = var22;
329
330
for (NBTTagCompound var15 = var20; var15.hasKey("Riding"); var15 = var15.getCompoundTag("Riding")) {
331
Entity var16 = EntityList.createEntityFromNBT(var15.getCompoundTag("Riding"), par1World);
332
333
if (var16 != null) {
334
var5.addEntity(var16);
335
var14.mountEntity(var16);
336
}
337
338
var14 = var16;
339
}
340
}
341
}
342
}
343
344
NBTTagList var19 = par2NBTTagCompound.getTagList("TileEntities");
345
346
if (var19 != null) {
347
for (int var21 = 0; var21 < var19.tagCount(); ++var21) {
348
NBTTagCompound var24 = (NBTTagCompound) var19.tagAt(var21);
349
TileEntity var26 = TileEntity.createAndLoadEntity(var24);
350
351
if (var26 != null) {
352
var5.addTileEntity(var26);
353
}
354
}
355
}
356
357
if (par2NBTTagCompound.hasKey("TileTicks")) {
358
NBTTagList var23 = par2NBTTagCompound.getTagList("TileTicks");
359
360
if (var23 != null) {
361
for (int var25 = 0; var25 < var23.tagCount(); ++var25) {
362
NBTTagCompound var27 = (NBTTagCompound) var23.tagAt(var25);
363
par1World.scheduleBlockUpdateFromLoad(var27.getInteger("x"), var27.getInteger("y"),
364
var27.getInteger("z"), var27.getInteger("i"), var27.getInteger("t"), var27.getInteger("p"));
365
}
366
}
367
}
368
369
return var5;
370
}
371
}
372
373