Path: blob/main/sp-server/src_aux/AnvilChunkLoader.java
8641 views
package net.minecraft.src;12import java.io.DataInputStream;3import java.io.DataOutputStream;4import java.io.File;5import java.io.IOException;6import java.util.ArrayList;7import java.util.HashSet;8import java.util.Iterator;9import java.util.List;10import java.util.Set;1112public class AnvilChunkLoader implements IChunkLoader, IThreadedFileIO {13private List chunksToRemove = new ArrayList();14private Set pendingAnvilChunksCoordinates = new HashSet();15private Object syncLockObject = new Object();1617/** Save directory for chunks using the Anvil format */18private final File chunkSaveLocation;1920public AnvilChunkLoader(File par1File) {21this.chunkSaveLocation = par1File;22}2324/**25* Loads the specified(XZ) chunk into the specified world.26*/27public Chunk loadChunk(World par1World, int par2, int par3) throws IOException {28NBTTagCompound var4 = null;29ChunkCoordIntPair var5 = new ChunkCoordIntPair(par2, par3);30Object var6 = this.syncLockObject;3132synchronized (this.syncLockObject) {33if (this.pendingAnvilChunksCoordinates.contains(var5)) {34for (int var7 = 0; var7 < this.chunksToRemove.size(); ++var7) {35if (((AnvilChunkLoaderPending) this.chunksToRemove.get(var7)).chunkCoordinate.equals(var5)) {36var4 = ((AnvilChunkLoaderPending) this.chunksToRemove.get(var7)).nbtTags;37break;38}39}40}41}4243if (var4 == null) {44DataInputStream var10 = RegionFileCache.getChunkInputStream(this.chunkSaveLocation, par2, par3);4546if (var10 == null) {47return null;48}4950var4 = CompressedStreamTools.read(var10);51}5253return this.checkedReadChunkFromNBT(par1World, par2, par3, var4);54}5556/**57* Wraps readChunkFromNBT. Checks the coordinates and several NBT tags.58*/59protected Chunk checkedReadChunkFromNBT(World par1World, int par2, int par3, NBTTagCompound par4NBTTagCompound) {60if (!par4NBTTagCompound.hasKey("Level")) {61par1World.getWorldLogAgent()62.logSevere("Chunk file at " + par2 + "," + par3 + " is missing level data, skipping");63return null;64} else if (!par4NBTTagCompound.getCompoundTag("Level").hasKey("Sections")) {65par1World.getWorldLogAgent()66.logSevere("Chunk file at " + par2 + "," + par3 + " is missing block data, skipping");67return null;68} else {69Chunk var5 = this.readChunkFromNBT(par1World, par4NBTTagCompound.getCompoundTag("Level"));7071if (!var5.isAtLocation(par2, par3)) {72par1World.getWorldLogAgent()73.logSevere("Chunk file at " + par2 + "," + par374+ " is in the wrong location; relocating. (Expected " + par2 + ", " + par3 + ", got "75+ var5.xPosition + ", " + var5.zPosition + ")");76par4NBTTagCompound.setInteger("xPos", par2);77par4NBTTagCompound.setInteger("zPos", par3);78var5 = this.readChunkFromNBT(par1World, par4NBTTagCompound.getCompoundTag("Level"));79}8081return var5;82}83}8485public void saveChunk(World par1World, Chunk par2Chunk) throws MinecraftException, IOException {86par1World.checkSessionLock();8788try {89NBTTagCompound var3 = new NBTTagCompound();90NBTTagCompound var4 = new NBTTagCompound();91var3.setTag("Level", var4);92this.writeChunkToNBT(par2Chunk, par1World, var4);93this.addChunkToPending(par2Chunk.getChunkCoordIntPair(), var3);94} catch (Exception var5) {95var5.printStackTrace();96}97}9899protected void addChunkToPending(ChunkCoordIntPair par1ChunkCoordIntPair, NBTTagCompound par2NBTTagCompound) {100Object var3 = this.syncLockObject;101102synchronized (this.syncLockObject) {103if (this.pendingAnvilChunksCoordinates.contains(par1ChunkCoordIntPair)) {104for (int var4 = 0; var4 < this.chunksToRemove.size(); ++var4) {105if (((AnvilChunkLoaderPending) this.chunksToRemove.get(var4)).chunkCoordinate106.equals(par1ChunkCoordIntPair)) {107this.chunksToRemove.set(var4,108new AnvilChunkLoaderPending(par1ChunkCoordIntPair, par2NBTTagCompound));109return;110}111}112}113114this.chunksToRemove.add(new AnvilChunkLoaderPending(par1ChunkCoordIntPair, par2NBTTagCompound));115this.pendingAnvilChunksCoordinates.add(par1ChunkCoordIntPair);116ThreadedFileIOBase.threadedIOInstance.queueIO(this);117}118}119120/**121* Returns a boolean stating if the write was unsuccessful.122*/123public boolean writeNextIO() {124AnvilChunkLoaderPending var1 = null;125Object var2 = this.syncLockObject;126127synchronized (this.syncLockObject) {128if (this.chunksToRemove.isEmpty()) {129return false;130}131132var1 = (AnvilChunkLoaderPending) this.chunksToRemove.remove(0);133this.pendingAnvilChunksCoordinates.remove(var1.chunkCoordinate);134}135136if (var1 != null) {137try {138this.writeChunkNBTTags(var1);139} catch (Exception var4) {140var4.printStackTrace();141}142}143144return true;145}146147private void writeChunkNBTTags(AnvilChunkLoaderPending par1AnvilChunkLoaderPending) throws IOException {148DataOutputStream var2 = RegionFileCache.getChunkOutputStream(this.chunkSaveLocation,149par1AnvilChunkLoaderPending.chunkCoordinate.chunkXPos,150par1AnvilChunkLoaderPending.chunkCoordinate.chunkZPos);151CompressedStreamTools.write(par1AnvilChunkLoaderPending.nbtTags, var2);152var2.close();153}154155/**156* Save extra data associated with this Chunk not normally saved during157* autosave, only during chunk unload. Currently unused.158*/159public void saveExtraChunkData(World par1World, Chunk par2Chunk) {160}161162/**163* Called every World.tick()164*/165public void chunkTick() {166}167168/**169* Save extra data not associated with any Chunk. Not saved during autosave,170* only during world unload. Currently unused.171*/172public void saveExtraData() {173while (this.writeNextIO()) {174;175}176}177178/**179* Writes the Chunk passed as an argument to the NBTTagCompound also passed,180* using the World argument to retrieve the Chunk's last update time.181*/182private void writeChunkToNBT(Chunk par1Chunk, World par2World, NBTTagCompound par3NBTTagCompound) {183par3NBTTagCompound.setInteger("xPos", par1Chunk.xPosition);184par3NBTTagCompound.setInteger("zPos", par1Chunk.zPosition);185par3NBTTagCompound.setLong("LastUpdate", par2World.getTotalWorldTime());186par3NBTTagCompound.setIntArray("HeightMap", par1Chunk.heightMap);187par3NBTTagCompound.setBoolean("TerrainPopulated", par1Chunk.isTerrainPopulated);188ExtendedBlockStorage[] var4 = par1Chunk.getBlockStorageArray();189NBTTagList var5 = new NBTTagList("Sections");190boolean var6 = !par2World.provider.hasNoSky;191ExtendedBlockStorage[] var7 = var4;192int var8 = var4.length;193NBTTagCompound var11;194195for (int var9 = 0; var9 < var8; ++var9) {196ExtendedBlockStorage var10 = var7[var9];197198if (var10 != null) {199var11 = new NBTTagCompound();200var11.setByte("Y", (byte) (var10.getYLocation() >> 4 & 255));201var11.setByteArray("Blocks", var10.getBlockLSBArray());202203if (var10.getBlockMSBArray() != null) {204var11.setByteArray("Add", var10.getBlockMSBArray().data);205}206207var11.setByteArray("Data", var10.getMetadataArray().data);208var11.setByteArray("BlockLight", var10.getBlocklightArray().data);209210if (var6) {211var11.setByteArray("SkyLight", var10.getSkylightArray().data);212} else {213var11.setByteArray("SkyLight", new byte[var10.getBlocklightArray().data.length]);214}215216var5.appendTag(var11);217}218}219220par3NBTTagCompound.setTag("Sections", var5);221par3NBTTagCompound.setByteArray("Biomes", par1Chunk.getBiomeArray());222par1Chunk.hasEntities = false;223NBTTagList var16 = new NBTTagList();224Iterator var18;225226for (var8 = 0; var8 < par1Chunk.entityLists.length; ++var8) {227var18 = par1Chunk.entityLists[var8].iterator();228229while (var18.hasNext()) {230Entity var20 = (Entity) var18.next();231var11 = new NBTTagCompound();232233if (var20.addEntityID(var11)) {234par1Chunk.hasEntities = true;235var16.appendTag(var11);236}237}238}239240par3NBTTagCompound.setTag("Entities", var16);241NBTTagList var17 = new NBTTagList();242var18 = par1Chunk.chunkTileEntityMap.values().iterator();243244while (var18.hasNext()) {245TileEntity var21 = (TileEntity) var18.next();246var11 = new NBTTagCompound();247var21.writeToNBT(var11);248var17.appendTag(var11);249}250251par3NBTTagCompound.setTag("TileEntities", var17);252List var19 = par2World.getPendingBlockUpdates(par1Chunk, false);253254if (var19 != null) {255long var22 = par2World.getTotalWorldTime();256NBTTagList var12 = new NBTTagList();257Iterator var13 = var19.iterator();258259while (var13.hasNext()) {260NextTickListEntry var14 = (NextTickListEntry) var13.next();261NBTTagCompound var15 = new NBTTagCompound();262var15.setInteger("i", var14.blockID);263var15.setInteger("x", var14.xCoord);264var15.setInteger("y", var14.yCoord);265var15.setInteger("z", var14.zCoord);266var15.setInteger("t", (int) (var14.scheduledTime - var22));267var15.setInteger("p", var14.field_82754_f);268var12.appendTag(var15);269}270271par3NBTTagCompound.setTag("TileTicks", var12);272}273}274275/**276* Reads the data stored in the passed NBTTagCompound and creates a Chunk with277* that data in the passed World. Returns the created Chunk.278*/279private Chunk readChunkFromNBT(World par1World, NBTTagCompound par2NBTTagCompound) {280int var3 = par2NBTTagCompound.getInteger("xPos");281int var4 = par2NBTTagCompound.getInteger("zPos");282Chunk var5 = new Chunk(par1World, var3, var4);283var5.heightMap = par2NBTTagCompound.getIntArray("HeightMap");284var5.isTerrainPopulated = par2NBTTagCompound.getBoolean("TerrainPopulated");285NBTTagList var6 = par2NBTTagCompound.getTagList("Sections");286byte var7 = 16;287ExtendedBlockStorage[] var8 = new ExtendedBlockStorage[var7];288boolean var9 = !par1World.provider.hasNoSky;289290for (int var10 = 0; var10 < var6.tagCount(); ++var10) {291NBTTagCompound var11 = (NBTTagCompound) var6.tagAt(var10);292byte var12 = var11.getByte("Y");293ExtendedBlockStorage var13 = new ExtendedBlockStorage(var12 << 4, var9);294var13.setBlockLSBArray(var11.getByteArray("Blocks"));295296if (var11.hasKey("Add")) {297var13.setBlockMSBArray(new NibbleArray(var11.getByteArray("Add"), 4));298}299300var13.setBlockMetadataArray(new NibbleArray(var11.getByteArray("Data"), 4));301var13.setBlocklightArray(new NibbleArray(var11.getByteArray("BlockLight"), 4));302303if (var9) {304var13.setSkylightArray(new NibbleArray(var11.getByteArray("SkyLight"), 4));305}306307var13.removeInvalidBlocks();308var8[var12] = var13;309}310311var5.setStorageArrays(var8);312313if (par2NBTTagCompound.hasKey("Biomes")) {314var5.setBiomeArray(par2NBTTagCompound.getByteArray("Biomes"));315}316317NBTTagList var17 = par2NBTTagCompound.getTagList("Entities");318319if (var17 != null) {320for (int var18 = 0; var18 < var17.tagCount(); ++var18) {321NBTTagCompound var20 = (NBTTagCompound) var17.tagAt(var18);322Entity var22 = EntityList.createEntityFromNBT(var20, par1World);323var5.hasEntities = true;324325if (var22 != null) {326var5.addEntity(var22);327Entity var14 = var22;328329for (NBTTagCompound var15 = var20; var15.hasKey("Riding"); var15 = var15.getCompoundTag("Riding")) {330Entity var16 = EntityList.createEntityFromNBT(var15.getCompoundTag("Riding"), par1World);331332if (var16 != null) {333var5.addEntity(var16);334var14.mountEntity(var16);335}336337var14 = var16;338}339}340}341}342343NBTTagList var19 = par2NBTTagCompound.getTagList("TileEntities");344345if (var19 != null) {346for (int var21 = 0; var21 < var19.tagCount(); ++var21) {347NBTTagCompound var24 = (NBTTagCompound) var19.tagAt(var21);348TileEntity var26 = TileEntity.createAndLoadEntity(var24);349350if (var26 != null) {351var5.addTileEntity(var26);352}353}354}355356if (par2NBTTagCompound.hasKey("TileTicks")) {357NBTTagList var23 = par2NBTTagCompound.getTagList("TileTicks");358359if (var23 != null) {360for (int var25 = 0; var25 < var23.tagCount(); ++var25) {361NBTTagCompound var27 = (NBTTagCompound) var23.tagAt(var25);362par1World.scheduleBlockUpdateFromLoad(var27.getInteger("x"), var27.getInteger("y"),363var27.getInteger("z"), var27.getInteger("i"), var27.getInteger("t"), var27.getInteger("p"));364}365}366}367368return var5;369}370}371372373