Path: blob/main/sp-server/src_aux/RegionFile.java
11173 views
package net.minecraft.src;12import java.io.BufferedInputStream;3import java.io.ByteArrayInputStream;4import java.io.DataInputStream;5import java.io.DataOutputStream;6import java.io.File;7import java.io.IOException;8import java.io.RandomAccessFile;9import java.util.ArrayList;10import java.util.zip.DeflaterOutputStream;11import java.util.zip.GZIPInputStream;12import java.util.zip.InflaterInputStream;1314public class RegionFile {15private static final byte[] emptySector = new byte[4096];16private final File fileName;17private RandomAccessFile dataFile;18private final int[] offsets = new int[1024];19private final int[] chunkTimestamps = new int[1024];20private ArrayList sectorFree;2122/** McRegion sizeDelta */23private int sizeDelta;24private long lastModified = 0L;2526public RegionFile(File par1File) {27this.fileName = par1File;28this.sizeDelta = 0;2930try {31if (par1File.exists()) {32this.lastModified = par1File.lastModified();33}3435this.dataFile = new RandomAccessFile(par1File, "rw");36int var2;3738if (this.dataFile.length() < 4096L) {39for (var2 = 0; var2 < 1024; ++var2) {40this.dataFile.writeInt(0);41}4243for (var2 = 0; var2 < 1024; ++var2) {44this.dataFile.writeInt(0);45}4647this.sizeDelta += 8192;48}4950if ((this.dataFile.length() & 4095L) != 0L) {51for (var2 = 0; (long) var2 < (this.dataFile.length() & 4095L); ++var2) {52this.dataFile.write(0);53}54}5556var2 = (int) this.dataFile.length() / 4096;57this.sectorFree = new ArrayList(var2);58int var3;5960for (var3 = 0; var3 < var2; ++var3) {61this.sectorFree.add(Boolean.valueOf(true));62}6364this.sectorFree.set(0, Boolean.valueOf(false));65this.sectorFree.set(1, Boolean.valueOf(false));66this.dataFile.seek(0L);67int var4;6869for (var3 = 0; var3 < 1024; ++var3) {70var4 = this.dataFile.readInt();71this.offsets[var3] = var4;7273if (var4 != 0 && (var4 >> 8) + (var4 & 255) <= this.sectorFree.size()) {74for (int var5 = 0; var5 < (var4 & 255); ++var5) {75this.sectorFree.set((var4 >> 8) + var5, Boolean.valueOf(false));76}77}78}7980for (var3 = 0; var3 < 1024; ++var3) {81var4 = this.dataFile.readInt();82this.chunkTimestamps[var3] = var4;83}84} catch (IOException var6) {85var6.printStackTrace();86}87}8889/**90* args: x, y - get uncompressed chunk stream from the region file91*/92public synchronized DataInputStream getChunkDataInputStream(int par1, int par2) {93if (this.outOfBounds(par1, par2)) {94return null;95} else {96try {97int var3 = this.getOffset(par1, par2);9899if (var3 == 0) {100return null;101} else {102int var4 = var3 >> 8;103int var5 = var3 & 255;104105if (var4 + var5 > this.sectorFree.size()) {106return null;107} else {108this.dataFile.seek((long) (var4 * 4096));109int var6 = this.dataFile.readInt();110111if (var6 > 4096 * var5) {112return null;113} else if (var6 <= 0) {114return null;115} else {116byte var7 = this.dataFile.readByte();117byte[] var8;118119if (var7 == 1) {120var8 = new byte[var6 - 1];121this.dataFile.read(var8);122return new DataInputStream(123new BufferedInputStream(new GZIPInputStream(new ByteArrayInputStream(var8))));124} else if (var7 == 2) {125var8 = new byte[var6 - 1];126this.dataFile.read(var8);127return new DataInputStream(new BufferedInputStream(128new InflaterInputStream(new ByteArrayInputStream(var8))));129} else {130return null;131}132}133}134}135} catch (IOException var9) {136return null;137}138}139}140141/**142* args: x, z - get an output stream used to write chunk data, data is on disk143* when the returned stream is closed144*/145public DataOutputStream getChunkDataOutputStream(int par1, int par2) {146return this.outOfBounds(par1, par2) ? null147: new DataOutputStream(new DeflaterOutputStream(new RegionFileChunkBuffer(this, par1, par2)));148}149150/**151* args: x, z, data, length - write chunk data at (x, z) to disk152*/153protected synchronized void write(int par1, int par2, byte[] par3ArrayOfByte, int par4) {154try {155int var5 = this.getOffset(par1, par2);156int var6 = var5 >> 8;157int var7 = var5 & 255;158int var8 = (par4 + 5) / 4096 + 1;159160if (var8 >= 256) {161return;162}163164if (var6 != 0 && var7 == var8) {165this.write(var6, par3ArrayOfByte, par4);166} else {167int var9;168169for (var9 = 0; var9 < var7; ++var9) {170this.sectorFree.set(var6 + var9, Boolean.valueOf(true));171}172173var9 = this.sectorFree.indexOf(Boolean.valueOf(true));174int var10 = 0;175int var11;176177if (var9 != -1) {178for (var11 = var9; var11 < this.sectorFree.size(); ++var11) {179if (var10 != 0) {180if (((Boolean) this.sectorFree.get(var11)).booleanValue()) {181++var10;182} else {183var10 = 0;184}185} else if (((Boolean) this.sectorFree.get(var11)).booleanValue()) {186var9 = var11;187var10 = 1;188}189190if (var10 >= var8) {191break;192}193}194}195196if (var10 >= var8) {197var6 = var9;198this.setOffset(par1, par2, var9 << 8 | var8);199200for (var11 = 0; var11 < var8; ++var11) {201this.sectorFree.set(var6 + var11, Boolean.valueOf(false));202}203204this.write(var6, par3ArrayOfByte, par4);205} else {206this.dataFile.seek(this.dataFile.length());207var6 = this.sectorFree.size();208209for (var11 = 0; var11 < var8; ++var11) {210this.dataFile.write(emptySector);211this.sectorFree.add(Boolean.valueOf(false));212}213214this.sizeDelta += 4096 * var8;215this.write(var6, par3ArrayOfByte, par4);216this.setOffset(par1, par2, var6 << 8 | var8);217}218}219220this.setChunkTimestamp(par1, par2, (int) (System.currentTimeMillis() / 1000L));221} catch (IOException var12) {222var12.printStackTrace();223}224}225226/**227* args: sectorNumber, data, length - write the chunk data to this RegionFile228*/229private void write(int par1, byte[] par2ArrayOfByte, int par3) throws IOException {230this.dataFile.seek((long) (par1 * 4096));231this.dataFile.writeInt(par3 + 1);232this.dataFile.writeByte(2);233this.dataFile.write(par2ArrayOfByte, 0, par3);234}235236/**237* args: x, z - check region bounds238*/239private boolean outOfBounds(int par1, int par2) {240return par1 < 0 || par1 >= 32 || par2 < 0 || par2 >= 32;241}242243/**244* args: x, y - get chunk's offset in region file245*/246private int getOffset(int par1, int par2) {247return this.offsets[par1 + par2 * 32];248}249250/**251* args: x, z, - true if chunk has been saved / converted252*/253public boolean isChunkSaved(int par1, int par2) {254return this.getOffset(par1, par2) != 0;255}256257/**258* args: x, z, offset - sets the chunk's offset in the region file259*/260private void setOffset(int par1, int par2, int par3) throws IOException {261this.offsets[par1 + par2 * 32] = par3;262this.dataFile.seek((long) ((par1 + par2 * 32) * 4));263this.dataFile.writeInt(par3);264}265266/**267* args: x, z, timestamp - sets the chunk's write timestamp268*/269private void setChunkTimestamp(int par1, int par2, int par3) throws IOException {270this.chunkTimestamps[par1 + par2 * 32] = par3;271this.dataFile.seek((long) (4096 + (par1 + par2 * 32) * 4));272this.dataFile.writeInt(par3);273}274275/**276* close this RegionFile and prevent further writes277*/278public void close() throws IOException {279if (this.dataFile != null) {280this.dataFile.close();281}282}283}284285286