3
0
Mirror von https://github.com/IntellectualSites/FastAsyncWorldEdit.git synchronisiert 2024-12-24 18:10:08 +01:00

WIP on 1.13 CFI

Dieser Commit ist enthalten in:
Jesse Boyd 2019-04-10 18:32:21 +10:00
Ursprung 435a8ad6f2
Commit 31797d4231
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 59F1DE6293AF6E1F
9 geänderte Dateien mit 895 neuen und 447 gelöschten Zeilen

Datei anzeigen

@ -293,11 +293,6 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
return result; return result;
} }
@Override
public IntFaweChunk getPrevious(IntFaweChunk fs, CHUNKSECTIONS sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> createdEntities, boolean all) throws Exception {
return fs;
}
@Override @Override
public boolean hasSky() { public boolean hasSky() {
World world = getWorld(); World world = getWorld();

Datei anzeigen

@ -349,8 +349,6 @@ public class BukkitQueue_All extends BukkitQueue_0<ChunkSnapshot, ChunkSnapshot,
return super.supports(capability); return super.supports(capability);
} }
private int skip;
@Override @Override
public void startSet(boolean parallel) { public void startSet(boolean parallel) {
super.startSet(true); super.startSet(true);

Datei anzeigen

@ -222,6 +222,4 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
public abstract void setBlockLight(SECTION section, int x, int y, int z, int value); public abstract void setBlockLight(SECTION section, int x, int y, int z, int value);
public abstract void refreshChunk(FaweChunk fs); public abstract void refreshChunk(FaweChunk fs);
public abstract IntFaweChunk getPrevious(IntFaweChunk fs, CHUNKSECTION sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> createdEntities, boolean all) throws Exception;
} }

Datei anzeigen

@ -0,0 +1,163 @@
package com.boydti.fawe.jnbt.anvil;
public final class BitArray4096 {
private final int bitsPerEntry;
private final int maxSeqLocIndex;
private final int maxEntryValue;
private final long[] data;
private final int longLen;
public BitArray4096(long[] buffer, int bitsPerEntry) {
this.bitsPerEntry = bitsPerEntry;
this.maxSeqLocIndex = 64 - bitsPerEntry;
maxEntryValue = (1 << bitsPerEntry) - 1;
this.longLen = (this.bitsPerEntry * 4096) >> 6;
if (buffer.length < longLen) {
System.out.println("Invalid buffer " + buffer.length + " | " + longLen);
this.data = new long[longLen];
} else {
this.data = buffer;
}
}
public BitArray4096(int bitsPerEntry) {
this.bitsPerEntry = bitsPerEntry;
this.maxSeqLocIndex = 64 - bitsPerEntry;
maxEntryValue = (1 << bitsPerEntry) - 1;
this.longLen = (this.bitsPerEntry * 4096) >> 6;
this.data = new long[longLen];
}
public final void setAt(int index, int value) {
if (longLen == 0) return;
int bitIndexStart = index * bitsPerEntry;
int longIndexStart = bitIndexStart >> 6;
int localBitIndexStart = bitIndexStart & 63;
this.data[longIndexStart] = this.data[longIndexStart] & ~((long) maxEntryValue << localBitIndexStart) | ((long) value) << localBitIndexStart;
if(localBitIndexStart > maxSeqLocIndex) {
int longIndexEnd = longIndexStart + 1;
int localShiftStart = 64 - localBitIndexStart;
int localShiftEnd = bitsPerEntry - localShiftStart;
this.data[longIndexEnd] = this.data[longIndexEnd] >>> localShiftEnd << localShiftEnd | (((long) value) >> localShiftStart);
}
}
public final int getAt(int index) {
if (longLen == 0) return 0;
int bitIndexStart = index * bitsPerEntry;
int longIndexStart = bitIndexStart >> 6;
int localBitIndexStart = bitIndexStart & 63;
if(localBitIndexStart <= maxSeqLocIndex) {
return (int)(this.data[longIndexStart] >>> localBitIndexStart & maxEntryValue);
} else {
int localShift = 64 - localBitIndexStart;
return (int) ((this.data[longIndexStart] >>> localBitIndexStart | this.data[longIndexStart + 1] << localShift) & maxEntryValue);
}
}
public int getLength() {
return longLen;
}
public final void fromRawSlow(char[] arr) {
for (int i = 0; i < arr.length; i++) {
setAt(i, arr[i]);
}
}
public final void fromRaw(int[] arr, int offset) {
final long[] data = this.data;
final int bitsPerEntry = this.bitsPerEntry;
final int maxEntryValue = this.maxEntryValue;
final int maxSeqLocIndex = this.maxSeqLocIndex;
int localStart = 0;
int lastVal;
int arrI = offset;
long l = 0;
long nextVal;
for (int i = 0; i < longLen; i++) {
for (; localStart <= maxSeqLocIndex; localStart += bitsPerEntry) {
lastVal = arr[arrI++];
l |= ((long) lastVal << localStart);
}
if (localStart < 64) {
if (i != longLen - 1) {
lastVal = arr[arrI++];
int shift = 64 - localStart;
nextVal = lastVal >> shift;
l |= ((lastVal - (nextVal << shift)) << localStart);
data[i] = l;
data[i + 1] = l = nextVal;
localStart -= maxSeqLocIndex;
}
} else {
localStart = 0;
data[i] = l;
l = 0;
}
}
}
public BitArray4096 growSlow(int bitsPerEntry) {
BitArray4096 newBitArray = new BitArray4096(bitsPerEntry);
for (int i = 0; i < 4096; i++) {
newBitArray.setAt(i, getAt(i));
}
return newBitArray;
}
public final char[] toRawSlow() {
char[] arr = new char[4096];
for (int i = 0; i < arr.length; i++) {
arr[i] = (char) getAt(i);
}
return arr;
}
public final char[] toRaw() {
return toRaw(new char[4096]);
}
protected final char[] toRaw(char[] buffer) {
final long[] data = this.data;
final int dataLength = longLen;
final int bitsPerEntry = this.bitsPerEntry;
final int maxEntryValue = this.maxEntryValue;
final int maxSeqLocIndex = this.maxSeqLocIndex;
int localStart = 0;
char lastVal;
int arrI = 0;
long l;
for (int i = 0; i < dataLength; i++) {
l = data[i];
for (; localStart <= maxSeqLocIndex; localStart += bitsPerEntry) {
lastVal = (char) (l >>> localStart & maxEntryValue);
buffer[arrI++] = lastVal;
}
if (localStart < 64) {
if (i != dataLength - 1) {
lastVal = (char) (l >>> localStart);
localStart -= maxSeqLocIndex;
l = data[i + 1];
int localShift = bitsPerEntry - localStart;
lastVal |= l << localShift;
lastVal &= maxEntryValue;
buffer[arrI++] = lastVal;
}
} else {
localStart = 0;
}
}
return buffer;
}
}

Datei anzeigen

@ -1,7 +1,11 @@
package com.boydti.fawe.jnbt.anvil; package com.boydti.fawe.jnbt.anvil;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.example.SimpleIntFaweChunk; import com.boydti.fawe.example.SimpleIntFaweChunk;
import com.boydti.fawe.jnbt.anvil.HeightMapMCADrawer;
import com.boydti.fawe.jnbt.anvil.MCAChunk;
import com.boydti.fawe.jnbt.anvil.MCAWriter;
import com.boydti.fawe.object.*; import com.boydti.fawe.object.*;
import com.boydti.fawe.object.brush.visualization.VirtualWorld; import com.boydti.fawe.object.brush.visualization.VirtualWorld;
import com.boydti.fawe.object.change.StreamChange; import com.boydti.fawe.object.change.StreamChange;
@ -77,7 +81,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
protected boolean randomVariation = true; protected boolean randomVariation = true;
protected int biomePriority = 0; protected int biomePriority = 0;
protected int waterId = BlockTypes.WATER.getInternalId(); protected int waterId = BlockTypes.WATER.getInternalId();
protected int bedrockId = 7; protected int bedrockId = BlockID.BEDROCK;
protected boolean modifiedMain = false; protected boolean modifiedMain = false;
@Override @Override
@ -210,7 +214,6 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
public HeightMapMCAGenerator(int width, int length, File regionFolder) { public HeightMapMCAGenerator(int width, int length, File regionFolder) {
super(width, length, regionFolder); super(width, length, regionFolder);
int area = getArea();
blocks = new DifferentialBlockBuffer(width, length); blocks = new DifferentialBlockBuffer(width, length);
heights = new DifferentialArray(new byte[getArea()]); heights = new DifferentialArray(new byte[getArea()]);
@ -296,7 +299,6 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
int ecx = Math.min(lenCX - 1, pcx + 15); int ecx = Math.min(lenCX - 1, pcx + 15);
int ecz = Math.min(lenCZ - 1, pcz + 15); int ecz = Math.min(lenCZ - 1, pcz + 15);
MCAChunk chunk = new MCAChunk(this, 0, 0);
for (int cz = scz; cz <= ecz; cz++) { for (int cz = scz; cz <= ecz; cz++) {
for (int cx = scx; cx <= ecx; cx++) { for (int cx = scx; cx <= ecx; cx++) {
final int finalCX = cx; final int finalCX = cx;
@ -517,7 +519,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
for (int x = 0; x < getWidth(); x++, index++) { for (int x = 0; x < getWidth(); x++, index++) {
int height = img.getRGB(x, z) & 0xFF; int height = img.getRGB(x, z) & 0xFF;
if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() if (height == 255 || height > 0 && !white && ThreadLocalRandom.current()
.nextInt(256) <= height) { .nextInt(256) <= height) {
int newHeight = table.average(x, z, index); int newHeight = table.average(x, z, index);
setLayerHeightRaw(index, newHeight); setLayerHeightRaw(index, newHeight);
} }
@ -767,16 +769,15 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
return getSnapshot(null, chunkX, chunkZ); return getSnapshot(null, chunkX, chunkZ);
} }
private FaweChunk getSnapshot(final MCAChunk chunk, int chunkX, int chunkZ) { private FaweChunk getSnapshot(final WritableMCAChunk chunk, int chunkX, int chunkZ) {
return new LazyFaweChunk<MCAChunk>(this, chunkX, chunkZ) { return new LazyFaweChunk<WritableMCAChunk>(this, chunkX, chunkZ) {
@Override @Override
public MCAChunk getChunk() { public WritableMCAChunk getChunk() {
MCAChunk tmp = chunk; WritableMCAChunk tmp = chunk;
if (tmp == null) { if (tmp == null) {
tmp = new MCAChunk(HeightMapMCAGenerator.this, chunkX, chunkZ); tmp = new WritableMCAChunk();
} else {
tmp.setLoc(HeightMapMCAGenerator.this, chunkX, chunkZ);
} }
tmp.setLoc(HeightMapMCAGenerator.this, chunkX, chunkZ);
int cbx = chunkX << 4; int cbx = chunkX << 4;
int cbz = chunkZ << 4; int cbz = chunkZ << 4;
int csx = Math.max(0, cbx); int csx = Math.max(0, cbx);
@ -790,7 +791,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
@Override @Override
public void addToQueue() { public void addToQueue() {
MCAChunk cached = getCachedChunk(); WritableMCAChunk cached = getCachedChunk();
if (cached != null) setChunk(cached); if (cached != null) setChunk(cached);
} }
}; };
@ -1091,7 +1092,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
for (int x = 0; x < getWidth(); x++, index++) { for (int x = 0; x < getWidth(); x++, index++) {
int height = img.getRGB(x, z) & 0xFF; int height = img.getRGB(x, z) & 0xFF;
if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() if (height == 255 || height > 0 && !white && ThreadLocalRandom.current()
.nextInt(256) <= height) { .nextInt(256) <= height) {
biomeArr[index] = biomeByte; biomeArr[index] = biomeByte;
} }
} }
@ -1143,7 +1144,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
if (imgMask != null) { if (imgMask != null) {
int height = imgMask.getRGB(x, z) & 0xFF; int height = imgMask.getRGB(x, z) & 0xFF;
if (height != 255 && (height <= 0 || !whiteOnly || ThreadLocalRandom if (height != 255 && (height <= 0 || !whiteOnly || ThreadLocalRandom
.current().nextInt(256) > height)) continue; .current().nextInt(256) > height)) continue;
} }
int color = img.getRGB(x, z); int color = img.getRGB(x, z);
if (textureUtil.getIsBlockCloserThanBiome(buffer, color, primtives.biomePriority)) { if (textureUtil.getIsBlockCloserThanBiome(buffer, color, primtives.biomePriority)) {
@ -1228,7 +1229,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
for (int x = 0; x < getWidth(); x++, index++) { for (int x = 0; x < getWidth(); x++, index++) {
int height = mask.getRGB(x, z) & 0xFF; int height = mask.getRGB(x, z) & 0xFF;
if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() if (height == 255 || height > 0 && !white && ThreadLocalRandom.current()
.nextInt(256) <= height) { .nextInt(256) <= height) {
int color = img.getRGB(x, z); int color = img.getRGB(x, z);
BlockType block = textureUtil.getNearestBlock(color); BlockType block = textureUtil.getNearestBlock(color);
if (block != null) { if (block != null) {
@ -1347,7 +1348,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
if (pattern instanceof BlockStateHolder) { if (pattern instanceof BlockStateHolder) {
setOverlay(img, ((BlockStateHolder) pattern).getInternalId(), white); setOverlay(img, ((BlockStateHolder) pattern).getInternalId(), white);
} else if (pattern instanceof BlockType) { } else if (pattern instanceof BlockType) {
setOverlay(img, ((BlockType) pattern).getInternalId(), white); setOverlay(img, ((BlockType) pattern).getInternalId(), white);
} else { } else {
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) if (img.getWidth() != getWidth() || img.getHeight() != getLength())
throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
@ -1363,7 +1364,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
for (int x = 0; x < getWidth(); x++, index++) { for (int x = 0; x < getWidth(); x++, index++) {
int height = img.getRGB(x, z) & 0xFF; int height = img.getRGB(x, z) & 0xFF;
if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() if (height == 255 || height > 0 && !white && ThreadLocalRandom.current()
.nextInt(256) <= height) { .nextInt(256) <= height) {
mutable.mutX(x); mutable.mutX(x);
mutable.mutY(height); mutable.mutY(height);
overlayArr[index] = pattern.apply(mutable).getInternalId(); overlayArr[index] = pattern.apply(mutable).getInternalId();
@ -1391,7 +1392,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
for (int x = 0; x < getWidth(); x++, index++) { for (int x = 0; x < getWidth(); x++, index++) {
int height = img.getRGB(x, z) & 0xFF; int height = img.getRGB(x, z) & 0xFF;
if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() if (height == 255 || height > 0 && !white && ThreadLocalRandom.current()
.nextInt(256) <= height) { .nextInt(256) <= height) {
mutable.mutX(x); mutable.mutX(x);
mutable.mutY(height); mutable.mutY(height);
mainArr[index] = pattern.apply(mutable).getInternalId(); mainArr[index] = pattern.apply(mutable).getInternalId();
@ -1417,7 +1418,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
for (int x = 0; x < getWidth(); x++, index++) { for (int x = 0; x < getWidth(); x++, index++) {
int height = img.getRGB(x, z) & 0xFF; int height = img.getRGB(x, z) & 0xFF;
if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() if (height == 255 || height > 0 && !white && ThreadLocalRandom.current()
.nextInt(256) <= height) { .nextInt(256) <= height) {
mutable.mutX(x); mutable.mutX(x);
mutable.mutY(height); mutable.mutY(height);
floorArr[index] = pattern.apply(mutable).getInternalId(); floorArr[index] = pattern.apply(mutable).getInternalId();
@ -1445,7 +1446,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
for (int x = 0; x < getWidth(); x++, index++) { for (int x = 0; x < getWidth(); x++, index++) {
int height = img.getRGB(x, z) & 0xFF; int height = img.getRGB(x, z) & 0xFF;
if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() if (height == 255 || height > 0 && !white && ThreadLocalRandom.current()
.nextInt(256) <= height) { .nextInt(256) <= height) {
mutable.mutX(x); mutable.mutX(x);
mutable.mutY(height); mutable.mutY(height);
int combined = pattern.apply(mutable).getInternalId(); int combined = pattern.apply(mutable).getInternalId();
@ -1649,328 +1650,159 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
} }
@Override @Override
public MCAChunk write(MCAChunk chunk, int csx, int cex, int csz, int cez) { public WritableMCAChunk write(WritableMCAChunk chunk, int csx, int cex, int csz, int cez) {
// TODO FIXME byte[] heights = this.heights.get();
// byte[] heights = this.heights.get(); byte[] biomes = this.biomes.get();
// byte[] biomes = this.biomes.get(); int[] main = this.main.get();
// int[] main = this.main.get(); int[] floor = this.floor.get();
// int[] floor = this.floor.get(); int[] overlay = this.overlay != null ? this.overlay.get() : null;
// int[] overlay = this.overlay != null ? this.overlay.get() : null; try {
// try { int[] indexes = indexStore.get();
// int[] indexes = indexStore.get();
// for (int i = 0; i < chunk.ids.length; i++) { int index;
// byte[] idsArray = chunk.ids[i]; int maxY = 0;
// if (idsArray != null) { int minY = Integer.MAX_VALUE;
// Arrays.fill(idsArray, (byte) 0); int[] heightMap = chunk.biomes;
// Arrays.fill(chunk.data[i], (byte) 0); int globalIndex;
// } for (int z = csz; z <= cez; z++) {
// } globalIndex = z * getWidth() + csx;
// int index; index = (z & 15) << 4;
// int maxY = 0; for (int x = csx; x <= cex; x++, index++, globalIndex++) {
// int minY = Integer.MAX_VALUE; indexes[index] = globalIndex;
// int[] heightMap = chunk.getHeightMapArray(); int height = heights[globalIndex] & 0xFF;
// int globalIndex; heightMap[index] = height;
// for (int z = csz; z <= cez; z++) { maxY = Math.max(maxY, height);
// globalIndex = z * getWidth() + csx; minY = Math.min(minY, height);
// index = (z & 15) << 4; }
// for (int x = csx; x <= cex; x++, index++, globalIndex++) { }
// indexes[index] = globalIndex; boolean hasOverlay = this.overlay != null;
// int height = heights[globalIndex] & 0xFF; if (hasOverlay) {
// heightMap[index] = height; maxY++;
// maxY = Math.max(maxY, height); }
// minY = Math.min(minY, height); int maxLayer = maxY >> 4;
// } for (int layer = 0; layer <= maxLayer; layer++) {
// } chunk.hasSections[layer] = true;
// boolean hasOverlay = this.overlay != null; }
// if (hasOverlay) { if (primtives.waterHeight != 0) {
// maxY++; maxY = Math.max(maxY, primtives.waterHeight);
// } int maxIndex = (primtives.waterHeight) << 8;
// int maxLayer = maxY >> 4; Arrays.fill(chunk.blocks, 0, maxIndex, primtives.waterId);
// int fillLayers = Math.max(0, (minY - 1)) >> 4; }
// for (int layer = 0; layer <= maxLayer; layer++) {
// if (chunk.ids[layer] == null) { if (primtives.modifiedMain) { // If the main block is modified, we can't short circuit this
// chunk.ids[layer] = new byte[4096]; for (int z = csz; z <= cez; z++) {
// chunk.data[layer] = new byte[2048]; index = (z & 15) << 4;
// chunk.skyLight[layer] = new byte[2048]; for (int x = csx; x <= cex; x++, index++) {
// chunk.blockLight[layer] = new byte[2048]; globalIndex = indexes[index];
// } int mainCombined = main[globalIndex];
// } for (int y = 0; y < minY; y++) {
// if (primtives.waterHeight != 0) { chunk.blocks[index + (y << 8)] = mainCombined;
// maxY = Math.max(maxY, primtives.waterHeight); }
// int maxWaterLayer = ((primtives.waterHeight + 15) >> 4); }
// for (int layer = 0; layer < maxWaterLayer; layer++) { }
// boolean fillAll = (layer << 4) + 15 <= primtives.waterHeight; } else {
// byte[] ids = chunk.ids[layer]; int maxIndex = minY << 8;
// if (ids == null) { Arrays.fill(chunk.blocks, 0, maxIndex, BlockID.STONE);
// chunk.ids[layer] = ids = new byte[4096]; }
// chunk.data[layer] = new byte[2048];
// chunk.skyLight[layer] = new byte[2048]; final boolean hasFloorThickness = primtives.floorThickness != 0 || primtives.worldThickness != 0;
// chunk.blockLight[layer] = new byte[2048]; if (primtives.worldThickness != 0) {
// Arrays.fill(chunk.skyLight[layer], (byte) 255); int endLayer = ((minY - primtives.worldThickness + 1) >> 4);
// } for (int layer = 0; layer < endLayer; layer++) {
// if (fillAll) { chunk.hasSections[layer] = false;
// Arrays.fill(ids, primtives.waterId); }
// } else { }
// int maxIndex = (primtives.waterHeight & 15) << 8;
// Arrays.fill(ids, 0, maxIndex, primtives.waterId); for (int z = csz; z <= cez; z++) {
// } index = (z & 15) << 4;
// } for (int x = csx; x <= cex; x++, index++) {
// } globalIndex = indexes[index];
// int height = heightMap[index];
// if (primtives.modifiedMain) { // If the main block is modified, we can't short circuit this int maxMainY = height;
// for (int layer = 0; layer < fillLayers; layer++) { int minMainY = minY;
// byte[] layerIds = chunk.ids[layer];
// byte[] layerDatas = chunk.data[layer]; int mainCombined = main[globalIndex];
// for (int z = csz; z <= cez; z++) {
// index = (z & 15) << 4; int floorCombined = floor[globalIndex];
// for (int x = csx; x <= cex; x++, index++) { if (hasFloorThickness) {
// globalIndex = indexes[index]; if (x > 0) maxMainY = Math.min(heights[globalIndex - 1] & 0xFF, maxMainY);
// char mainCombined = main[globalIndex]; if (x < getWidth() - 1) maxMainY = Math.min(heights[globalIndex + 1] & 0xFF, maxMainY);
// byte id = (byte) FaweCache.getId(mainCombined); if (z > 0) maxMainY = Math.min(heights[globalIndex - getWidth()] & 0xFF, maxMainY);
// int data = FaweCache.getData(mainCombined); if (z < getLength() - 1) maxMainY = Math.min(heights[globalIndex + getWidth()] & 0xFF, maxMainY);
// if (data != 0) {
// for (int y = 0; y < 16; y++) { int min = maxMainY;
// int mainIndex = index + (y << 8);
// chunk.setNibble(mainIndex, layerDatas, data); if (primtives.floorThickness != 0) {
// } maxMainY = Math.max(0, maxMainY - (primtives.floorThickness - 1));
// } for (int y = maxMainY; y <= height; y++) {
// for (int y = 0; y < 16; y++) { chunk.blocks[index + (y << 8)] = floorCombined;
// layerIds[index + (y << 8)] = id; }
// } }
// } else {
// } chunk.blocks[index + ((height) << 8)] = floorCombined;
// } }
// } else {
// for (int layer = 0; layer < fillLayers; layer++) { if (primtives.worldThickness != 0) {
// Arrays.fill(chunk.ids[layer], (byte) 1); minMainY = Math.max(minY, min - primtives.worldThickness + 1);
// } for (int y = minY; y < minMainY; y++) {
// } chunk.blocks[index + (y << 8)] = BlockID.AIR;
// }
// for (int layer = fillLayers; layer <= maxLayer; layer++) { }
// Arrays.fill(chunk.skyLight[layer], (byte) 255);
// byte[] layerIds = chunk.ids[layer]; } else {
// byte[] layerDatas = chunk.data[layer]; chunk.blocks[index + ((height) << 8)] = floorCombined;
// int startY = layer << 4; }
// int endY = startY + 15;
// for (int z = csz; z <= cez; z++) { for (int y = minMainY; y < maxMainY; y++) {
// index = (z & 15) << 4; chunk.blocks[index + (y << 8)] = mainCombined;
// for (int x = csx; x <= cex; x++, index++) { }
// globalIndex = indexes[index];
// int height = heightMap[index]; if (hasOverlay) {
// int diff; int overlayCombined = overlay[globalIndex];
// if (height > endY) { int overlayIndex = index + ((height + 1) << 8);
// diff = 16; chunk.blocks[overlayIndex] = overlayCombined;
// } else if (height >= startY) { }
// diff = height - startY;
// char floorCombined = floor[globalIndex]; if (primtives.bedrockId != 0) {
// int id = FaweCache.getId(floorCombined); chunk.blocks[index] = primtives.bedrockId;
// int floorIndex = index + ((height & 15) << 8); }
// layerIds[floorIndex] = (byte) id; }
// int data = FaweCache.getData(floorCombined); }
// if (data != 0) {
// chunk.setNibble(floorIndex, layerDatas, data); int[][][] localBlocks = getChunkArray(chunk.getX(), chunk.getZ());
// } if (localBlocks != null) {
// if (hasOverlay && height >= startY - 1 && height < endY) { index = 0;
// char overlayCombined = overlay[globalIndex]; for (int layer = 0; layer < 16; layer++) {
// id = FaweCache.getId(overlayCombined); int by = layer << 4;
// int overlayIndex = index + (((height + 1) & 15) << 8); int ty = by + 15;
// layerIds[overlayIndex] = (byte) id; for (int y = by; y <= ty; y++, index += 256) {
// data = FaweCache.getData(overlayCombined); int[][] yBlocks = localBlocks[y];
// if (data != 0) { if (yBlocks != null) {
// chunk.setNibble(overlayIndex, layerDatas, data); chunk.hasSections[layer] = true;
// } for (int z = 0; z < yBlocks.length; z++) {
// } int[] zBlocks = yBlocks[z];
// } else if (hasOverlay && height == startY - 1) { if (zBlocks != null) {
// char overlayCombined = overlay[globalIndex]; int zIndex = index + (z << 4);
// int id = FaweCache.getId(overlayCombined); for (int x = 0; x < zBlocks.length; x++, zIndex++) {
// int overlayIndex = index + (((height + 1) & 15) << 8); int combined = zBlocks[x];
// layerIds[overlayIndex] = (byte) id; if (combined == 0) continue;
// int data = FaweCache.getData(overlayCombined); chunk.blocks[zIndex] = combined;
// if (data != 0) { }
// chunk.setNibble(overlayIndex, layerDatas, data); }
// } }
// continue; }
// } else { }
// continue; }
// } }
// char mainCombined = main[globalIndex];
// byte id = (byte) FaweCache.getId(mainCombined); for (int i = 0; i < 256; i++) {
// int data = FaweCache.getData(mainCombined); chunk.biomes[i] = biomes[indexes[i]];
// if (data != 0) { }
// for (int y = 0; y < diff; y++) {
// int mainIndex = index + (y << 8);
// chunk.setNibble(mainIndex, layerDatas, data); } catch (Throwable e) {
// } e.printStackTrace();
// } }
// for (int y = 0; y < diff; y++) {
// layerIds[index + (y << 8)] = id;
// }
// }
// }
// }
//
// int maxYMod = 15 + (maxLayer << 4);
// for (int layer = (maxY >> 4) + 1; layer < 16; layer++) {
// chunk.ids[layer] = null;
// chunk.data[layer] = null;
// }
//
// if (primtives.bedrockId != 0) { // Bedrock
// byte[] layerIds = chunk.ids[0];
// for (int z = csz; z <= cez; z++) {
// index = (z & 15) << 4;
// for (int x = csx; x <= cex; x++) {
// layerIds[index++] = primtives.bedrockId;
// }
// }
// }
//
// char[][][] localBlocks = getChunkArray(chunk.getX(), chunk.getZ());
// if (localBlocks != null) {
// for (int layer = 0; layer < 16; layer++) {
// int by = layer << 4;
// int ty = by + 15;
// index = 0;
// for (int y = by; y <= ty; y++, index += 256) {
// char[][] yBlocks = localBlocks[y];
// if (yBlocks != null) {
// if (chunk.ids[layer] == null) {
// chunk.ids[layer] = new byte[4096];
// chunk.data[layer] = new byte[2048];
// chunk.skyLight[layer] = new byte[2048];
// chunk.blockLight[layer] = new byte[2048];
// Arrays.fill(chunk.skyLight[layer], (byte) 255);
// }
// byte[] idsLayer = chunk.ids[layer];
// byte[] dataLayer = chunk.data[layer];
// for (int z = 0; z < yBlocks.length; z++) {
// char[] zBlocks = yBlocks[z];
// if (zBlocks != null) {
// int zIndex = index + (z << 4);
// for (int x = 0; x < zBlocks.length; x++, zIndex++) {
// char combined = zBlocks[x];
// if (combined == 0) continue;
// int id = FaweCache.getId(combined);
// int data = FaweCache.getData(combined);
// if (data == 0) {
// chunk.setIdUnsafe(idsLayer, zIndex, (byte) id);
// } else {
// chunk.setBlockUnsafe(idsLayer, dataLayer, zIndex, (byte) id, FaweCache.getData(combined));
// }
// }
// }
// }
// }
// }
// }
// }
//
// if (primtives.floorThickness != 0 || primtives.worldThickness != 0) {
// // Use biomes array as temporary buffer
// byte[] minArr = chunk.biomes;
// for (int z = csz; z <= cez; z++) {
// index = (z & 15) << 4;
// for (int x = csx; x <= cex; x++, index++) {
// int gi = indexes[index];
// int height = heightMap[index];
// int min = height;
// if (x > 0) min = Math.min(heights[gi - 1] & 0xFF, min);
// if (x < getWidth() - 1) min = Math.min(heights[gi + 1] & 0xFF, min);
// if (z > 0) min = Math.min(heights[gi - getWidth()] & 0xFF, min);
// if (z < getLength() - 1) min = Math.min(heights[gi + getWidth()] & 0xFF, min);
// minArr[index] = (byte) min;
// }
// }
//
// int minLayer = Math.max(0, (minY - primtives.floorThickness) >> 4);
//
// if (primtives.floorThickness != 0) {
// for (int layer = minLayer; layer <= maxLayer; layer++) {
// byte[] layerIds = chunk.ids[layer];
// byte[] layerDatas = chunk.data[layer];
// int startY = layer << 4;
// int endY = startY + 15;
// for (int z = csz; z <= cez; z++) {
// index = (z & 15) << 4;
// for (int x = csx; x <= cex; x++, index++) {
// globalIndex = indexes[index];
// int height = heightMap[index];
//
// int min = (minArr[index] & 0xFF) - primtives.floorThickness;
// int localMin = min - startY;
//
// int max = height + 1;
// if (min < startY) min = startY;
// if (max > endY) max = endY + 1;
//
//
// if (min < max) {
// char floorCombined = floor[globalIndex];
// final byte id = (byte) FaweCache.getId(floorCombined);
// final int data = FaweCache.getData(floorCombined);
// for (int y = min; y < max; y++) {
// int floorIndex = index + ((y & 15) << 8);
// layerIds[floorIndex] = id;
// if (data != 0) {
// chunk.setNibble(floorIndex, layerDatas, data);
// }
// }
// }
//
// }
// }
// }
// }
// if (primtives.worldThickness != 0) {
// for (int layer = 0; layer < minLayer; layer++) {
// chunk.ids[layer] = null;
// chunk.data[layer] = null;
// }
// for (int layer = minLayer; layer <= maxLayer; layer++) {
// byte[] layerIds = chunk.ids[layer];
// byte[] layerDatas = chunk.data[layer];
// int startY = layer << 4;
// int endY = startY + 15;
// for (int z = csz; z <= cez; z++) {
// index = (z & 15) << 4;
// for (int x = csx; x <= cex; x++, index++) {
// globalIndex = indexes[index];
// int height = heightMap[index];
//
// int min = (minArr[index] & 0xFF) - primtives.worldThickness;
// int localMin = min - startY;
// if (localMin > 0) {
// char floorCombined = floor[globalIndex];
// final byte id = (byte) FaweCache.getId(floorCombined);
// final int data = FaweCache.getData(floorCombined);
//
// for (int y = 0; y < localMin; y++) {
// int floorIndex = index + ((y & 15) << 8);
// layerIds[floorIndex] = 0;
// if (data != 0) {
// chunk.setNibble(floorIndex, layerDatas, 0);
// }
// }
// }
// }
// }
// }
// }
//
// for (int layer = fillLayers; layer <= maxLayer; layer++) {
// Arrays.fill(chunk.skyLight[layer], (byte) 255);
//
// }
// }
//
// for (int i = 0; i < 256; i++) {
// chunk.biomes[i] = biomes[indexes[i]];
// }
//
//
// } catch (Throwable e) {
// e.printStackTrace();
// }
return chunk; return chunk;
} }
@ -2092,7 +1924,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
for (int x = 0; x < getWidth(); x++, index++) { for (int x = 0; x < getWidth(); x++, index++) {
int height = img.getRGB(x, z) & 0xFF; int height = img.getRGB(x, z) & 0xFF;
if (height == 255 || height > 0 && white && ThreadLocalRandom.current() if (height == 255 || height > 0 && white && ThreadLocalRandom.current()
.nextInt(256) <= height) { .nextInt(256) <= height) {
overlay.get()[index] = combined; overlay.get()[index] = combined;
} }
} }
@ -2111,7 +1943,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
for (int x = 0; x < getWidth(); x++, index++) { for (int x = 0; x < getWidth(); x++, index++) {
int height = img.getRGB(x, z) & 0xFF; int height = img.getRGB(x, z) & 0xFF;
if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() if (height == 255 || height > 0 && !white && ThreadLocalRandom.current()
.nextInt(256) <= height) { .nextInt(256) <= height) {
main.get()[index] = combined; main.get()[index] = combined;
} }
} }
@ -2129,7 +1961,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
for (int x = 0; x < getWidth(); x++, index++) { for (int x = 0; x < getWidth(); x++, index++) {
int height = img.getRGB(x, z) & 0xFF; int height = img.getRGB(x, z) & 0xFF;
if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() if (height == 255 || height > 0 && !white && ThreadLocalRandom.current()
.nextInt(256) <= height) { .nextInt(256) <= height) {
floor.get()[index] = combined; floor.get()[index] = combined;
} }
} }
@ -2148,7 +1980,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
for (int x = 0; x < getWidth(); x++, index++) { for (int x = 0; x < getWidth(); x++, index++) {
int height = img.getRGB(x, z) & 0xFF; int height = img.getRGB(x, z) & 0xFF;
if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() if (height == 255 || height > 0 && !white && ThreadLocalRandom.current()
.nextInt(256) <= height) { .nextInt(256) <= height) {
main.get()[index] = combined; main.get()[index] = combined;
floor.get()[index] = combined; floor.get()[index] = combined;
} }
@ -2286,27 +2118,27 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
return false; return false;
} }
@Override @Override
public void dropItem(Vector3 position, BaseItemStack item) { public void dropItem(Vector3 position, BaseItemStack item) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
}
@Override }
public boolean playEffect(Vector3 position, int type, int data) {
// TODO Auto-generated method stub
return false;
}
@Override @Override
public boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException { public boolean playEffect(Vector3 position, int type, int data) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return false; return false;
} }
@Override @Override
public BlockVector3 getSpawnPosition() { public boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return false;
} }
@Override
public BlockVector3 getSpawnPosition() {
// TODO Auto-generated method stub
return null;
}
} }

Datei anzeigen

@ -3,8 +3,10 @@ package com.boydti.fawe.jnbt.anvil;
import com.boydti.fawe.object.collection.IterableThreadLocal; import com.boydti.fawe.object.collection.IterableThreadLocal;
import com.boydti.fawe.object.io.BufferedRandomAccessFile; import com.boydti.fawe.object.io.BufferedRandomAccessFile;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.zip.Deflater; import java.util.zip.Deflater;
@ -67,22 +69,20 @@ public abstract class MCAWriter {
public abstract boolean shouldWrite(int chunkX, int chunkZ); public abstract boolean shouldWrite(int chunkX, int chunkZ);
public abstract MCAChunk write(MCAChunk input, int startX, int endX, int startZ, int endZ); public abstract WritableMCAChunk write(WritableMCAChunk input, int startX, int endX, int startZ, int endZ);
public void generate() throws IOException { public void generate() throws IOException {
if (!folder.exists()) { if (!folder.exists()) {
folder.mkdirs(); folder.mkdirs();
} }
final ForkJoinPool pool = new ForkJoinPool(); final ForkJoinPool pool = new ForkJoinPool();
int bcx = 0;
int bcz = 0;
int tcx = (width - 1) >> 4; int tcx = (width - 1) >> 4;
int tcz = (length - 1) >> 4; int tcz = (length - 1) >> 4;
final ThreadLocal<MCAChunk> chunkStore = new ThreadLocal<MCAChunk>() { final ThreadLocal<WritableMCAChunk> chunkStore = new ThreadLocal<WritableMCAChunk>() {
@Override @Override
protected MCAChunk initialValue() { protected WritableMCAChunk initialValue() {
MCAChunk chunk = new MCAChunk(null, 0, 0); WritableMCAChunk chunk = new WritableMCAChunk();
chunk.biomes = new byte[256]; Arrays.fill(chunk.skyLight, (byte) 255);
return chunk; return chunk;
} }
}; };
@ -111,16 +111,15 @@ public abstract class MCAWriter {
int mcaXMax = mcaXMin + ((width - 1) >> 9); int mcaXMax = mcaXMin + ((width - 1) >> 9);
int mcaZMax = mcaZMin + ((length - 1) >> 9); int mcaZMax = mcaZMin + ((length - 1) >> 9);
final byte[] header = new byte[4096];
for (int mcaZ = mcaXMin; mcaZ <= mcaZMax; mcaZ++) { for (int mcaZ = mcaXMin; mcaZ <= mcaZMax; mcaZ++) {
for (int mcaX = mcaXMin; mcaX <= mcaXMax; mcaX++) { for (int mcaX = mcaXMin; mcaX <= mcaXMax; mcaX++) {
final int fmcaX = mcaX;
final int fmcaZ = mcaZ;
File file = new File(folder, "r." + (mcaX + (getOffsetX() >> 9)) + "." + (mcaZ + (getOffsetZ() >> 9)) + ".mca"); File file = new File(folder, "r." + (mcaX + (getOffsetX() >> 9)) + "." + (mcaZ + (getOffsetZ() >> 9)) + ".mca");
if (!file.exists()) { if (!file.exists()) {
file.createNewFile(); file.createNewFile();
} }
final BufferedRandomAccessFile raf = new BufferedRandomAccessFile(file, "rw", fileBuf); final BufferedRandomAccessFile raf = new BufferedRandomAccessFile(file, "rw", fileBuf);
final byte[] header = new byte[4096];
final byte[][] compressed = new byte[1024][]; final byte[][] compressed = new byte[1024][];
int bx = mcaX << 9; int bx = mcaX << 9;
int bz = mcaZ << 9; int bz = mcaZ << 9;
@ -137,76 +136,70 @@ public abstract class MCAWriter {
final int fcx = cx; final int fcx = cx;
final int fcz = cz; final int fcz = cz;
if (shouldWrite(cx, cz)) { if (shouldWrite(cx, cz)) {
pool.submit(new Runnable() { pool.submit(() -> {
@Override try {
public void run() { WritableMCAChunk chunk = chunkStore.get();
try { chunk.clear(fcx, fcz);
MCAChunk chunk = chunkStore.get(); chunk = write(chunk, csx, cex, csz, cez);
chunk.setLoc(null, fcx, fcz); if (chunk != null) {
chunk = write(chunk, csx, cex, csz, cez); // Generation offset
if (chunk != null) { chunk.setLoc( fcx + (getOffsetX() >> 4), fcz + (getOffsetZ() >> 4));
// Generation offset
chunk.setLoc(null, fcx + (getOffsetX() >> 4), fcz + (getOffsetZ() >> 4)); // Compress
// Compress byte[] bytes = chunk.toBytes(byteStore1.get());
byte[] bytes = chunk.toBytes(byteStore1.get()); byte[] compressedBytes = MainUtil.compress(bytes, byteStore2.get(), deflateStore.get());
byte[] compressedBytes = MainUtil.compress(bytes, byteStore2.get(), deflateStore.get());
int blocks = (compressed.length + 4095) >> 12; // TODO optimize (avoid cloning) by add a synchronized block and write to the RAF here instead of below
compressed[((fcx & 31)) + ((fcz & 31) << 5)] = compressedBytes.clone(); compressed[((fcx & 31)) + ((fcz & 31) << 5)] = compressedBytes.clone();
}
} catch (Throwable e) {
e.printStackTrace();
} }
} catch (Throwable e) {
e.printStackTrace();
} }
}); });
} }
} }
} }
pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
pool.submit(new Runnable() { pool.submit(() -> {
@Override try {
public void run() { int totalLength = 8192;
for (int i = 0; i < compressed.length; i++) {
byte[] compressedBytes = compressed[i];
if (compressedBytes != null) {
int blocks = ((4095 + compressedBytes.length + 5) / 4096) * 4096;
totalLength += blocks;
}
}
raf.setLength(totalLength);
int offset = 8192;
for (int i = 0; i < compressed.length; i++) {
byte[] compressedBytes = compressed[i];
if (compressedBytes != null) {
// Set header
int index = i << 2;
int offsetMedium = offset >> 12;
int blocks = ((4095 + compressedBytes.length + 5) / 4096);
header[index] = (byte) (offsetMedium >> 16);
header[index + 1] = (byte) ((offsetMedium >> 8));
header[index + 2] = (byte) ((offsetMedium >> 0));
header[index + 3] = (byte) (blocks);
// Write bytes
raf.seek(offset);
raf.writeInt(compressedBytes.length + 1);
raf.write(2);
raf.write(compressedBytes);
offset += blocks * 4096;
}
}
raf.seek(0);
raf.write(header);
} catch (IOException e) {
e.printStackTrace();
} finally {
try { try {
int totalLength = 8192; raf.close();
for (int i = 0; i < compressed.length; i++) {
byte[] compressedBytes = compressed[i];
if (compressedBytes != null) {
int blocks = ((4095 + compressedBytes.length + 5) / 4096) * 4096;
totalLength += blocks;
}
}
raf.setLength(totalLength);
int offset = 8192;
for (int i = 0; i < compressed.length; i++) {
byte[] compressedBytes = compressed[i];
if (compressedBytes != null) {
// Set header
int index = i << 2;
int offsetMedium = offset >> 12;
int blocks = ((4095 + compressedBytes.length + 5) / 4096);
header[index] = (byte) (offsetMedium >> 16);
header[index + 1] = (byte) ((offsetMedium >> 8));
header[index + 2] = (byte) ((offsetMedium >> 0));
header[index + 3] = (byte) (blocks);
// Write bytes
int cx = (fmcaX << 5) + (i & 31);
int cz = (fmcaZ << 5) + (i >> 5);
raf.seek(offset);
raf.writeInt(compressedBytes.length + 1);
raf.write(2);
raf.write(compressedBytes);
offset += blocks * 4096;
}
}
raf.seek(0);
raf.write(header);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
} }
} }
}); });

Datei anzeigen

@ -0,0 +1,398 @@
package com.boydti.fawe.jnbt.anvil;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.util.MathMan;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
public class WritableMCAChunk extends FaweChunk<Void> {
public final boolean[] hasSections = new boolean[16];
public final byte[] skyLight = new byte[65536];
public final byte[] blockLight = new byte[65536];
public boolean hasBiomes = false;
public final int[] biomes = new int[256];
public final int[] blocks = new int[65536];
public Map<Short, CompoundTag> tiles = new HashMap<>();
public Map<UUID, CompoundTag> entities = new HashMap<>();
public long inhabitedTime = System.currentTimeMillis();
public long lastUpdate;
public int modified;
public boolean deleted;
public int chunkX, chunkZ;
protected WritableMCAChunk() {
super(null, 0, 0);
}
public int getX() {
return chunkX;
}
public int getZ() {
return chunkZ;
}
public void setLoc(int X, int Z) {
this.chunkX = X;
this.chunkZ = Z;
}
public void clear(int X, int Z) {
this.chunkX = X;
this.chunkZ = Z;
if (!tiles.isEmpty()) {
tiles.clear();
}
if (!entities.isEmpty()) {
entities.clear();
}
modified = 0;
deleted = false;
hasBiomes = false;
Arrays.fill(hasSections, false);
}
private transient final int[] blockToPalette = new int[BlockTypes.states.length];
private transient final boolean[] hasBlock = new boolean[BlockTypes.states.length];
private transient final int[] paletteToBlock = new int[Character.MAX_VALUE];
private transient final long[] blockstates = new long[2048];
public void write(NBTOutputStream nbtOut) throws IOException {
nbtOut.writeNamedTagName("", NBTConstants.TYPE_COMPOUND);
nbtOut.writeLazyCompoundTag("Level", out -> {
out.writeNamedTag("V", (byte) 1);
out.writeNamedTag("xPos", getX());
out.writeNamedTag("zPos", getZ());
out.writeNamedTag("LightPopulated", (byte) 0);
out.writeNamedTag("TerrainPopulated", (byte) 1);
if (entities.isEmpty()) {
out.writeNamedEmptyList("Entities");
} else {
out.writeNamedTag("Entities", new ListTag(CompoundTag.class, new ArrayList<>(entities.values())));
}
if (tiles.isEmpty()) {
out.writeNamedEmptyList("TileEntities");
} else {
out.writeNamedTag("TileEntities", new ListTag(CompoundTag.class,
new ArrayList<>(tiles.values())));
}
out.writeNamedTag("InhabitedTime", inhabitedTime);
out.writeNamedTag("LastUpdate", lastUpdate);
if (biomes != null) {
out.writeNamedTag("Biomes", biomes);
}
out.writeNamedTagName("Sections", NBTConstants.TYPE_LIST);
nbtOut.writeByte(NBTConstants.TYPE_COMPOUND);
int len = 0;
for (int layer = 0; layer < hasSections.length; layer++) {
if (hasSections[layer]) len++;
}
nbtOut.writeInt(len);
for (int layer = 0; layer < hasSections.length; layer++) {
if (hasSections[layer]) {
continue;
}
out.writeNamedTag("Y", (byte) layer);
out.writeNamedTagName("BlockLight", NBTConstants.TYPE_BYTE_ARRAY);
out.writeInt(2048);
out.write(blockLight, layer << 11, 1 << 11);
out.writeNamedTagName("SkyLight", NBTConstants.TYPE_BYTE_ARRAY);
out.writeInt(2048);
out.write(skyLight, layer << 11, 1 << 11);
int blockIndexStart = layer << 8;
int blockIndexEnd = blockIndexStart << 1;
int num_palette = 0;
try {
out.writeNamedTagName("Palette", NBTConstants.TYPE_LIST);
out.writeByte(NBTConstants.TYPE_COMPOUND);
out.writeInt(num_palette);
for (int i = blockIndexStart; i < blockIndexEnd; i++) {
int stateId = blocks[i];
if (!hasBlock[stateId]) {
hasBlock[stateId] = true;
blockToPalette[stateId] = num_palette;
paletteToBlock[num_palette++] = stateId;
BlockState state = BlockTypes.states[stateId];
BlockType type = state.getBlockType();
out.writeNamedTag("Name", type.getId());
// Properties
if (type.getDefaultState() == state) continue;
out.writeNamedTagName("Properties", NBTConstants.TYPE_COMPOUND);
for (Property<?> property : type.getProperties()) {
String key = property.getName();
Object value = state.getState(property);
String valueStr = value.toString();
if (Character.isUpperCase(valueStr.charAt(0))) {
System.out.println("Invalid uppercase value " + value);
valueStr = valueStr.toLowerCase();
}
out.writeNamedTag(key, valueStr);
}
out.writeByte(NBTConstants.TYPE_END);
}
}
// BlockStates
int bitsPerEntry = MathMan.log2nlz(num_palette - 1);
int blockBitArrayEnd = (bitsPerEntry * 4096) >> 6;
if (num_palette == 1) {
Arrays.fill(blockstates, 0, blockBitArrayEnd, 0);
}
BitArray4096 bitArray = new BitArray4096(blockstates, bitsPerEntry);
bitArray.fromRaw(blocks, blockIndexStart);
out.writeNamedTagName("BlockStates", NBTConstants.TYPE_LONG_ARRAY);
out.writeInt(blockBitArrayEnd);
for (int i = 0; i < blockBitArrayEnd; i++) out.writeLong(blockstates[i]);
out.writeEndTag();
// cleanup
} catch (Throwable e) {
for (int i = 0; i < num_palette; i++) {
hasBlock[i] = false;
}
throw e;
}
}
});
nbtOut.writeEndTag();
}
public byte[] toBytes(byte[] buffer) throws IOException {
if (buffer == null) {
buffer = new byte[8192];
}
FastByteArrayOutputStream buffered = new FastByteArrayOutputStream(buffer);
DataOutputStream dataOut = new DataOutputStream(buffered);
try (NBTOutputStream nbtOut = new NBTOutputStream((DataOutput) dataOut)) {
write(nbtOut);
}
return buffered.toByteArray();
}
public long getInhabitedTime() {
return inhabitedTime;
}
public long getLastUpdate() {
return lastUpdate;
}
public void setInhabitedTime(long inhabitedTime) {
this.inhabitedTime = inhabitedTime;
}
public void setLastUpdate(long lastUpdate) {
this.lastUpdate = lastUpdate;
}
public void setDeleted(boolean deleted) {
setModified();
this.deleted = deleted;
}
public boolean isDeleted() {
return deleted;
}
public boolean isModified() {
return modified != 0;
}
public int getModified() {
return modified;
}
public final void setModified() {
this.modified++;
}
public int getBitMask() {
int bitMask = 0;
for (int section = 0; section < hasSections.length; section++) {
if (hasSections[section]) {
bitMask += 1 << section;
}
}
return bitMask;
}
public void setTile(int x, int y, int z, CompoundTag tile) {
setModified();
short pair = MathMan.tripleBlockCoord(x, y, z);
if (tile != null) {
tiles.put(pair, tile);
} else {
tiles.remove(pair);
}
}
public void setEntity(CompoundTag entityTag) {
setModified();
long least = entityTag.getLong("UUIDLeast");
long most = entityTag.getLong("UUIDMost");
entities.put(new UUID(most, least), entityTag);
}
public void setBiome(int x, int z, BiomeType biome) {
setModified();
biomes[x + (z << 4)] = biome.getInternalId();
}
public Set<CompoundTag> getEntities() {
return new HashSet<>(entities.values());
}
public Map<Short, CompoundTag> getTiles() {
return tiles == null ? new HashMap<>() : tiles;
}
public CompoundTag getTile(int x, int y, int z) {
if (tiles == null || tiles.isEmpty()) {
return null;
}
short pair = MathMan.tripleBlockCoord(x, y, z);
return tiles.get(pair);
}
public boolean doesSectionExist(int cy) {
return hasSections[cy];
}
private final int getIndex(int x, int y, int z) {
return x | (z << 4) | (y << 8);
}
public int getBlockCombinedId(int x, int y, int z) {
return blocks[x | (z << 4) | (y << 8)];
}
public BiomeType[] getBiomeArray() {
return null;
}
public Set<UUID> getEntityRemoves() {
return new HashSet<>();
}
public void setSkyLight(int x, int y, int z, int value) {
setNibble(getIndex(x, y, z), skyLight, value);
}
public void setBlockLight(int x, int y, int z, int value) {
setNibble(getIndex(x, y, z), blockLight, value);
}
public int getSkyLight(int x, int y, int z) {
if (!hasSections[y >> 4]) return 0;
return getNibble(getIndex(x, y, z), skyLight);
}
public int getBlockLight(int x, int y, int z) {
if (!hasSections[y >> 4]) return 0;
return getNibble(getIndex(x, y, z), blockLight);
}
public void setFullbright() {
for (int layer = 0; layer < 16; layer++) {
if (hasSections[layer]) {
Arrays.fill(skyLight, layer << 7, ((layer + 1) << 7), (byte) 255);
}
}
}
public void removeLight() {
for (int i = 0; i < skyLight.length; i++) {
removeLight(i);
}
}
public void removeLight(int i) {
if (hasSections[i]) {
Arrays.fill(skyLight, i << 7, ((i + 1) << 7), (byte) 0);
Arrays.fill(blockLight, i << 7, ((i + 1) << 7), (byte) 0);
}
}
public int getNibble(int index, byte[] array) {
int indexShift = index >> 1;
if ((index & 1) == 0) {
return array[indexShift] & 15;
} else {
return array[indexShift] >> 4 & 15;
}
}
public void setNibble(int index, byte[] array, int value) {
int indexShift = index >> 1;
byte existing = array[indexShift];
int valueShift = value << 4;
if (existing == value + valueShift) {
return;
}
if ((index & 1) == 0) {
array[indexShift] = (byte) (existing & 240 | value);
} else {
array[indexShift] = (byte) (existing & 15 | valueShift);
}
}
public void setBlock(int x, int y, int z, int combinedId) {
blocks[getIndex(x, y, z)] = combinedId;
}
public void setBiome(BiomeType biome) {
Arrays.fill(biomes, (byte) biome.getInternalId());
}
@Override
public FaweChunk<Void> copy(boolean shallow) {
throw new UnsupportedOperationException("Unsupported");
}
public void removeEntity(UUID uuid) {
entities.remove(uuid);
}
public Void getChunk() {
throw new UnsupportedOperationException("Not applicable for this");
}
public FaweChunk call() {
throw new UnsupportedOperationException("Not supported");
}
}

Datei anzeigen

@ -39,7 +39,7 @@ import java.util.Map;
* found at <a href="http://www.minecraft.net/docs/NBT.txt"> * found at <a href="http://www.minecraft.net/docs/NBT.txt">
* http://www.minecraft.net/docs/NBT.txt</a>.</p> * http://www.minecraft.net/docs/NBT.txt</a>.</p>
*/ */
public final class NBTOutputStream implements Closeable { public final class NBTOutputStream extends OutputStream implements Closeable, DataOutput {
/** /**
* The output stream. * The output stream.
@ -426,11 +426,82 @@ public final class NBTOutputStream implements Closeable {
if (os instanceof Closeable) ((Closeable) os).close(); if (os instanceof Closeable) ((Closeable) os).close();
} }
@Override
public void write(int b) throws IOException {
os.write(b);
}
@Override
public void write(byte[] b) throws IOException {
os.write(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
os.write(b, off, len);
}
@Override
public void writeBoolean(boolean v) throws IOException {
os.writeBoolean(v);
}
@Override
public void writeByte(int v) throws IOException {
os.writeByte(v);
}
@Override
public void writeShort(int v) throws IOException {
os.writeShort(v);
}
@Override
public void writeChar(int v) throws IOException {
os.writeChar(v);
}
@Override
public void writeInt(int v) throws IOException {
os.writeInt(v);
}
@Override
public void writeLong(long v) throws IOException {
os.writeLong(v);
}
@Override
public void writeFloat(float v) throws IOException {
os.writeFloat(v);
}
@Override
public void writeDouble(double v) throws IOException {
os.writeDouble(v);
}
@Override
public void writeBytes(String s) throws IOException {
os.writeBytes(s);
}
@Override
public void writeChars(String s) throws IOException {
os.writeChars(s);
}
@Override
public void writeUTF(String s) throws IOException {
os.writeUTF(s);
}
/** /**
* Flush output. * Flush output.
* *
* @throws IOException * @throws IOException
*/ */
@Override
public void flush() throws IOException { public void flush() throws IOException {
if (os instanceof Flushable) ((Flushable) os).flush(); if (os instanceof Flushable) ((Flushable) os).flush();
} }

Datei anzeigen

@ -974,7 +974,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
BBC.WORLDEDIT_SOME_FAILS_BLOCKBAG.send(player, str.toString()); BBC.WORLDEDIT_SOME_FAILS_BLOCKBAG.send(player, str.toString());
} }
} }
return new HashMap<>(); return Collections.emptyMap();
} }
/** /**