From f7e1f70e1913969d12416f443f13ddf924ad2de0 Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Fri, 3 Jul 2020 21:44:19 -0400 Subject: [PATCH] Replace BlockStates reading with new 1.16 logic (#1413) * Replace BlockStates reading with new 1.16 logic * Account for running on older platforms Splits out the new reading to AnvilChunk16, uses data version to detect the appropriate version. * Move data versions to Constants Also fixes some logic hiccups that become obvious with the new names. * Fix LegacyMapper DFU handling * Fix factor indexing (cherry picked from commit 8c171f0929e8530aab1731d122649adc58c5161f) --- .../fawe/bukkit/wrapper/AsyncBlock.java | 9 ++ .../sk89q/worldedit/EditSessionBuilder.java | 145 ------------------ .../clipboard/io/SpongeSchematicReader.java | 14 +- .../extent/world/BiomeQuirkExtent.java | 50 ------ .../worldedit/world/chunk/AnvilChunk13.java | 66 ++++---- .../world/storage/ChunkStoreHelper.java | 17 +- 6 files changed, 61 insertions(+), 240 deletions(-) delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/BiomeQuirkExtent.java diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java index dc7bfd742..a2c38dce8 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java @@ -393,6 +393,15 @@ public class AsyncBlock implements Block { return this.getUnsafeBlock().rayTrace(arg0, arg1, arg2, arg3); } + public boolean applyBoneMeal(@NotNull BlockFace face) { + throw new UnsupportedOperationException("FAWE does not support this method"); + } + + public String getTranslationKey() { + throw new UnsupportedOperationException("FAWE does not support this yet"); + } + + @NotNull @Override public BoundingBox getBoundingBox() { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java deleted file mode 100644 index 57b768648..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit; - -import com.google.common.base.Preconditions; -import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.extension.platform.Locatable; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.extent.inventory.BlockBag; -import com.sk89q.worldedit.util.eventbus.EventBus; -import com.sk89q.worldedit.world.World; - -import javax.annotation.Nullable; - -/** - * A builder-style factory for {@link EditSession EditSessions}. - */ -public final class EditSessionBuilder { - - private final EventBus eventBus; - private @Nullable World world; - private int maxBlocks = -1; - private @Nullable Actor actor; - private @Nullable BlockBag blockBag; - private boolean tracing; - - EditSessionBuilder(EventBus eventBus) { - this.eventBus = eventBus; - } - - public @Nullable World getWorld() { - return world; - } - - /** - * Set the world for the {@link EditSession}. - * - * @param world the world - * @return this builder - */ - public EditSessionBuilder world(@Nullable World world) { - this.world = world; - return this; - } - - public int getMaxBlocks() { - return maxBlocks; - } - - /** - * Set the maximum blocks to change for the {@link EditSession}. - * - * @param maxBlocks the maximum blocks to change - * @return this builder - */ - public EditSessionBuilder maxBlocks(int maxBlocks) { - this.maxBlocks = maxBlocks; - return this; - } - - public @Nullable Actor getActor() { - return actor; - } - - /** - * Set the actor who owns the {@link EditSession}. - * - * @param actor the actor - * @return this builder - */ - public EditSessionBuilder actor(@Nullable Actor actor) { - this.actor = actor; - return this; - } - - public @Nullable BlockBag getBlockBag() { - return blockBag; - } - - /** - * Set the block bag for the {@link EditSession}. - * - * @param blockBag the block bag - * @return this builder - */ - public EditSessionBuilder blockBag(@Nullable BlockBag blockBag) { - this.blockBag = blockBag; - return this; - } - - /** - * Check if tracing is enabled. - * - * Internal use only. - */ - public boolean isTracing() { - return tracing; - } - - /** - * Set tracing enabled/disabled. - * - * Internal use only. - */ - public EditSessionBuilder tracing(boolean tracing) { - this.tracing = tracing; - return this; - } - - // Extended methods - public EditSessionBuilder locatableActor(A locatable) { - Extent extent = locatable.getExtent(); - Preconditions.checkArgument(extent instanceof World, "%s is not located in a World", locatable); - return world(((World) extent)).actor(locatable); - } - - /** - * Build the {@link EditSession} using properties described in this builder. - * - * @return the new EditSession - */ - public EditSession build() { - if (WorldEdit.getInstance().getConfiguration().traceUnflushedSessions) { - return new TracedEditSession(eventBus, world, maxBlocks, blockBag, actor, tracing); - } - return new EditSession(eventBus, world, maxBlocks, blockBag, actor, tracing); - } -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java index fe768992c..53e05567c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java @@ -39,7 +39,7 @@ import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; -import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; @@ -97,7 +97,7 @@ public class SpongeSchematicReader extends NBTSchematicReader { int liveDataVersion = platform.getDataVersion(); if (schematicVersion == 1) { - dataVersion = 1631; // this is a relatively safe assumption unless someone imports a schematic from 1.12, e.g. sponge 7.1- + dataVersion = Constants.DATA_VERSION_MC_1_13_2; // this is a relatively safe assumption unless someone imports a schematic from 1.12, e.g. sponge 7.1- fixer = platform.getDataFixer(); return readVersion1(schematicTag); } else if (schematicVersion == 2) { @@ -128,7 +128,7 @@ public class SpongeSchematicReader extends NBTSchematicReader { CompoundTag schematicTag = getBaseTag(); Map schematic = schematicTag.getValue(); if (schematicVersion == 1) { - return OptionalInt.of(1631); + return OptionalInt.of(Constants.DATA_VERSION_MC_1_13_2); } else if (schematicVersion == 2) { return OptionalInt.of(requireTag(schematic, "DataVersion", IntTag.class).getValue()); } @@ -322,7 +322,7 @@ public class SpongeSchematicReader extends NBTSchematicReader { BiomeType biome = BiomeTypes.get(key); if (biome == null) { log.warn("Unknown biome type :" + key + - " in palette. Are you missing a mod or using a schematic made in a newer version of Minecraft?"); + " in palette. Are you missing a mod or using a schematic made in a newer version of Minecraft?"); } Tag idTag = palettePart.getValue(); if (!(idTag instanceof IntTag)) { @@ -338,7 +338,7 @@ public class SpongeSchematicReader extends NBTSchematicReader { int biomeJ = 0; int bVal; int varIntLength; - BlockVector2 min = clipboard.getMinimumPoint().toBlockVector2(); + BlockVector3 min = clipboard.getMinimumPoint(); while (biomeJ < biomes.length) { bVal = 0; varIntLength = 0; @@ -357,7 +357,9 @@ public class SpongeSchematicReader extends NBTSchematicReader { int z = biomeIndex / width; int x = biomeIndex % width; BiomeType type = palette.get(bVal); - clipboard.setBiome(min.add(x, z), type); + for (int y = 0; y < clipboard.getRegion().getHeight(); y++) { + clipboard.setBiome(min.add(x, y, z), type); + } biomeIndex++; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/BiomeQuirkExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/BiomeQuirkExtent.java deleted file mode 100644 index 1abdccfa7..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/BiomeQuirkExtent.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.extent.world; - -import com.sk89q.worldedit.extent.AbstractDelegateExtent; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.world.biome.BiomeType; - -/** - * Handles quirks when placing biomes. - */ -public class BiomeQuirkExtent extends AbstractDelegateExtent { - - /** - * Create a new instance. - * - * @param extent the extent - */ - public BiomeQuirkExtent(Extent extent) { - super(extent); - } - - @Override - public boolean setBiome(BlockVector3 position, BiomeType biome) { - boolean success = false; - if (!fullySupports3DBiomes()) { - // Also place at Y = 0 for proper handling - success = super.setBiome(position.withY(0), biome); - } - return super.setBiome(position, biome) || success; - } -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java index 527f3cc9a..aa7fe471d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk13.java @@ -41,7 +41,7 @@ import java.util.Map; import javax.annotation.Nullable; /** - * The chunk format for Minecraft 1.13 and newer + * The chunk format for Minecraft 1.13 to 1.15 */ public class AnvilChunk13 implements Chunk { @@ -112,44 +112,48 @@ public class AnvilChunk13 implements Chunk { } palette[paletteEntryId] = blockState; } - int paletteBits = 4; - while ((1 << paletteBits) < paletteSize) { - ++paletteBits; - } - int paletteMask = (1 << paletteBits) - 1; // parse block states long[] blockStatesSerialized = NBTUtils.getChildTag(sectionTag.getValue(), "BlockStates", LongArrayTag.class).getValue(); - int blocksPerChunkSection = 16 * 16 * 16; - BlockState[] chunkSectionBlocks = new BlockState[blocksPerChunkSection]; + BlockState[] chunkSectionBlocks = new BlockState[16 * 16 * 16]; blocks[y] = chunkSectionBlocks; - long currentSerializedValue = 0; - int nextSerializedItem = 0; - int remainingBits = 0; - for (int blockPos = 0; blockPos < blocksPerChunkSection; blockPos++) { - int localBlockId; - if (remainingBits < paletteBits) { - int bitsNextLong = paletteBits - remainingBits; - localBlockId = (int) currentSerializedValue; - if (nextSerializedItem >= blockStatesSerialized.length) { - throw new InvalidFormatException("Too short block state table"); - } - currentSerializedValue = blockStatesSerialized[nextSerializedItem++]; - localBlockId |= (currentSerializedValue & ((1 << bitsNextLong) - 1)) << remainingBits; - currentSerializedValue >>>= bitsNextLong; - remainingBits = 64 - bitsNextLong; - } else { - localBlockId = (int) (currentSerializedValue & paletteMask); - currentSerializedValue >>>= paletteBits; - remainingBits -= paletteBits; + readBlockStates(palette, blockStatesSerialized, chunkSectionBlocks); + } + } + + protected void readBlockStates(BlockState[] palette, long[] blockStatesSerialized, BlockState[] chunkSectionBlocks) throws InvalidFormatException { + int paletteBits = 4; + while ((1 << paletteBits) < palette.length) { + ++paletteBits; + } + int paletteMask = (1 << paletteBits) - 1; + + long currentSerializedValue = 0; + int nextSerializedItem = 0; + int remainingBits = 0; + for (int blockPos = 0; blockPos < chunkSectionBlocks.length; blockPos++) { + int localBlockId; + if (remainingBits < paletteBits) { + int bitsNextLong = paletteBits - remainingBits; + localBlockId = (int) currentSerializedValue; + if (nextSerializedItem >= blockStatesSerialized.length) { + throw new InvalidFormatException("Too short block state table"); } - if (localBlockId >= palette.length) { - throw new InvalidFormatException("Invalid block state table entry: " + localBlockId); - } - chunkSectionBlocks[blockPos] = palette[localBlockId]; + currentSerializedValue = blockStatesSerialized[nextSerializedItem++]; + localBlockId |= (currentSerializedValue & ((1 << bitsNextLong) - 1)) << remainingBits; + currentSerializedValue >>>= bitsNextLong; + remainingBits = 64 - bitsNextLong; + } else { + localBlockId = (int) (currentSerializedValue & paletteMask); + currentSerializedValue >>>= paletteBits; + remainingBits -= paletteBits; } + if (localBlockId >= palette.length) { + throw new InvalidFormatException("Invalid block state table entry: " + localBlockId); + } + chunkSectionBlocks[blockPos] = palette[localBlockId]; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStoreHelper.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStoreHelper.java index 1f577c455..6928964ae 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStoreHelper.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStoreHelper.java @@ -25,10 +25,12 @@ import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.chunk.AnvilChunk; import com.sk89q.worldedit.world.chunk.AnvilChunk13; +import com.sk89q.worldedit.world.chunk.AnvilChunk16; import com.sk89q.worldedit.world.chunk.Chunk; import com.sk89q.worldedit.world.chunk.OldChunk; @@ -58,11 +60,6 @@ public class ChunkStoreHelper { } } - /** - * The DataVersion for Minecraft 1.13 - */ - private static final int DATA_VERSION_MC_1_13 = 1519; - /** * Convert a chunk NBT tag into a {@link Chunk} implementation. * @@ -94,13 +91,17 @@ public class ChunkStoreHelper { if (dataVersion == 0) dataVersion = -1; final Platform platform = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING); final int currentDataVersion = platform.getDataVersion(); - if (tag.getValue().containsKey("Sections") && dataVersion < currentDataVersion) { // only fix up MCA format, DFU doesn't support MCR chunks + if (tag.getValue().containsKey("Sections") && dataVersion < currentDataVersion) { // only fix up MCA format, DFU doesn't support MCR chunks final DataFixer dataFixer = platform.getDataFixer(); if (dataFixer != null) { - return new AnvilChunk13((CompoundTag) dataFixer.fixUp(DataFixer.FixTypes.CHUNK, rootTag, dataVersion).getValue().get("Level")); + tag = (CompoundTag) dataFixer.fixUp(DataFixer.FixTypes.CHUNK, rootTag, dataVersion).getValue().get("Level"); + dataVersion = currentDataVersion; } } - if (dataVersion >= DATA_VERSION_MC_1_13) { + if (dataVersion >= Constants.DATA_VERSION_MC_1_16) { + return new AnvilChunk16(tag); + } + if (dataVersion >= Constants.DATA_VERSION_MC_1_13) { return new AnvilChunk13(tag); }