From e03a43a1abc5bf61dd8db7f877cb4d5ef9fb389a Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Wed, 10 Apr 2019 22:04:22 +1000 Subject: [PATCH] finish MCAWriter --- .../fawe/bukkit/wrapper/AsyncBlockState.java | 4 +- .../jnbt/anvil/HeightMapMCAGenerator.java | 8 +- .../com/boydti/fawe/jnbt/anvil/MCAQueue.java | 5 - .../com/boydti/fawe/jnbt/anvil/MCAWriter.java | 2 + .../fawe/jnbt/anvil/WritableMCAChunk.java | 93 ++++++++++++------- 5 files changed, 65 insertions(+), 47 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlockState.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlockState.java index 4d36f64bf..39b469c29 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlockState.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlockState.java @@ -39,7 +39,7 @@ public class AsyncBlockState implements BlockState { } public int getTypeId() { - return combinedId & BlockTypes.BIT_MASK; + return BlockTypes.getFromStateId(combinedId).getInternalId(); } public int getPropertyId() { @@ -160,7 +160,7 @@ public class AsyncBlockState implements BlockState { @Override public void setRawData(byte data) { - this.combinedId = (combinedId & BlockTypes.BIT_MASK) + (data << BlockTypes.BIT_OFFSET); + this.combinedId = getTypeId() + (data << BlockTypes.BIT_OFFSET); this.blockData = BukkitAdapter.getBlockData(this.combinedId); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java index 2d176d0f2..bf05415a3 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java @@ -20,6 +20,7 @@ import com.boydti.fawe.util.image.ImageViewer; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.*; import com.sk89q.worldedit.math.MutableBlockVector3; +import com.sk89q.worldedit.registry.state.PropertyKey; import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BlockID; import com.sk89q.worldedit.world.block.BlockState; @@ -80,7 +81,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr protected int worldThickness = 0; protected boolean randomVariation = true; protected int biomePriority = 0; - protected int waterId = BlockTypes.WATER.getInternalId(); + protected int waterId = BlockID.WATER; protected int bedrockId = BlockID.BEDROCK; protected boolean modifiedMain = false; @@ -221,8 +222,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr floor = new DifferentialArray(new int[getArea()]); main = new DifferentialArray(new int[getArea()]); - int stone = BlockTypes.STONE.getInternalId(); - int grass = BlockTypes.GRASS_BLOCK.getInternalId(); + int stone = BlockID.STONE; + int grass = BlockTypes.GRASS_BLOCK.getDefaultState().with(PropertyKey.SNOWY, false).getInternalId(); Arrays.fill(main.getIntArray(), stone); Arrays.fill(floor.getIntArray(), grass); } @@ -1684,7 +1685,6 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr chunk.hasSections[layer] = true; } if (primtives.waterHeight != 0) { - maxY = Math.max(maxY, primtives.waterHeight); int maxIndex = (primtives.waterHeight) << 8; Arrays.fill(chunk.blocks, 0, maxIndex, primtives.waterId); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java index 5a96a16cf..b54dac7cf 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java @@ -647,11 +647,6 @@ public class MCAQueue extends NMSMappedFaweQueue tiles, Collection[] entities, Set createdEntities, boolean all) throws Exception { - throw new UnsupportedOperationException("Not supported"); - } - @Override public FaweQueue getImpWorld() { return parent; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWriter.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWriter.java index 5d4421d12..51f523a53 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWriter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWriter.java @@ -3,6 +3,7 @@ package com.boydti.fawe.jnbt.anvil; import com.boydti.fawe.object.collection.IterableThreadLocal; import com.boydti.fawe.object.io.BufferedRandomAccessFile; import com.boydti.fawe.util.MainUtil; +import com.sk89q.worldedit.world.block.BlockID; import java.io.File; import java.io.IOException; @@ -82,6 +83,7 @@ public abstract class MCAWriter { @Override protected WritableMCAChunk initialValue() { WritableMCAChunk chunk = new WritableMCAChunk(); + Arrays.fill(chunk.blocks, BlockID.AIR); Arrays.fill(chunk.skyLight, (byte) 255); return chunk; } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/WritableMCAChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/WritableMCAChunk.java index 8283145c1..76359d3a8 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/WritableMCAChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/WritableMCAChunk.java @@ -7,8 +7,10 @@ import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.NBTConstants; import com.sk89q.jnbt.NBTOutputStream; +import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BlockID; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; @@ -73,11 +75,17 @@ public class WritableMCAChunk extends FaweChunk { modified = 0; deleted = false; hasBiomes = false; + // TODO optimize + for (int i = 0; i < 65536; i++) { + blocks[i] = BlockID.AIR; + } Arrays.fill(hasSections, false); } private transient final int[] blockToPalette = new int[BlockTypes.states.length]; - private transient final boolean[] hasBlock = new boolean[BlockTypes.states.length]; + { + Arrays.fill(blockToPalette, Integer.MAX_VALUE); + } private transient final int[] paletteToBlock = new int[Character.MAX_VALUE]; private transient final long[] blockstates = new long[2048]; @@ -105,51 +113,52 @@ public class WritableMCAChunk extends FaweChunk { 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++; } - + out.writeNamedTagName("Sections", NBTConstants.TYPE_LIST); + nbtOut.writeByte(NBTConstants.TYPE_COMPOUND); nbtOut.writeInt(len); for (int layer = 0; layer < hasSections.length; layer++) { - if (hasSections[layer]) { - continue; - } + 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 blockIndexStart = layer << 12; + int blockIndexEnd = blockIndexStart + 4096; int num_palette = 0; try { + for (int i = blockIndexStart; i < blockIndexEnd; i++) { + int stateId = blocks[i]; + int ordinal = BlockState.getFromInternalId(stateId).getOrdinal(); // TODO fixme Remove all use of BlockTypes.BIT_OFFSET so that this conversion isn't necessary + int palette = blockToPalette[ordinal]; + if (palette == Integer.MAX_VALUE) { + BlockState state = BlockTypes.states[ordinal]; + blockToPalette[ordinal] = palette = num_palette; + paletteToBlock[num_palette] = ordinal; + num_palette++; + } + blocks[i] = palette; + } + + for (int i = 0; i < num_palette; i++) { + blockToPalette[paletteToBlock[i]] = Integer.MAX_VALUE; + } + 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; + for (int i = 0; i < num_palette; i++) { + int ordinal = paletteToBlock[i]; + BlockState state = BlockTypes.states[ordinal]; + BlockType type = state.getBlockType(); + out.writeNamedTag("Name", type.getId()); + // Has no properties + if (type.getDefaultState() != state) { + // Write properties out.writeNamedTagName("Properties", NBTConstants.TYPE_COMPOUND); for (Property property : type.getProperties()) { String key = property.getName(); @@ -161,30 +170,42 @@ public class WritableMCAChunk extends FaweChunk { } out.writeNamedTag(key, valueStr); } - out.writeByte(NBTConstants.TYPE_END); + out.writeEndTag(); } + out.writeEndTag(); } + // BlockStates int bitsPerEntry = MathMan.log2nlz(num_palette - 1); int blockBitArrayEnd = (bitsPerEntry * 4096) >> 6; if (num_palette == 1) { Arrays.fill(blockstates, 0, blockBitArrayEnd, 0); + } else { + BitArray4096 bitArray = new BitArray4096(blockstates, bitsPerEntry); + bitArray.fromRaw(blocks, blockIndexStart); } - 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.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); + + out.writeEndTag(); // cleanup } catch (Throwable e) { - for (int i = 0; i < num_palette; i++) { - hasBlock[i] = false; - } + Arrays.fill(blockToPalette, Integer.MAX_VALUE); + System.out.println("======================== exception e"); throw e; } }