From 0d1e32efcb83622f9c295f556c1141f605aaa222 Mon Sep 17 00:00:00 2001 From: MattBDev <4009945+MattBDev@users.noreply.github.com> Date: Thu, 2 Jan 2020 16:30:44 -0500 Subject: [PATCH] Upstream and debugging changes. --- .../cli/schematic/ClipboardWorld.java | 18 +-- .../src/main/java/com/boydti/fawe/Fawe.java | 1 - .../com/boydti/fawe/beta/IQueueChunk.java | 2 +- .../plotquared/PlotSquaredFeature.java | 7 +- .../java/com/boydti/fawe/util/WEManager.java | 4 + .../worldedit/function/factory/Deform.java | 20 +-- .../function/operation/Operation.java | 12 +- .../com/sk89q/worldedit/util/io/Closer.java | 21 ++++ .../util/translation/TranslationManager.java | 12 +- .../worldedit/world/chunk/AnvilChunk.java | 6 +- .../worldedit/world/chunk/AnvilChunk13.java | 2 +- .../sk89q/worldedit/world/chunk/OldChunk.java | 7 +- .../worldedit/world/storage/ChunkStore.java | 56 +-------- .../world/storage/ChunkStoreHelper.java | 117 ++++++++++++++++++ .../world/storage/LegacyChunkStore.java | 18 +-- .../src/main/resources/lang/strings.json | 10 +- 16 files changed, 196 insertions(+), 117 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStoreHelper.java diff --git a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/schematic/ClipboardWorld.java b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/schematic/ClipboardWorld.java index 5e1a26b96..69d1cb1c9 100644 --- a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/schematic/ClipboardWorld.java +++ b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/schematic/ClipboardWorld.java @@ -108,11 +108,6 @@ public class ClipboardWorld extends AbstractWorld implements Clipboard, CLIWorld return false; } - @Override - public List getEntities(Region region) { - return clipboard.getEntities(region); - } - @Override public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 position) throws MaxChangedBlocksException { @@ -120,13 +115,18 @@ public class ClipboardWorld extends AbstractWorld implements Clipboard, CLIWorld } @Override - public List getEntities() { - return clipboard.getEntities(); + public BlockVector3 getSpawnPosition() { + return clipboard.getOrigin(); } @Override - public BlockVector3 getSpawnPosition() { - return clipboard.getOrigin(); + public List getEntities(Region region) { + return clipboard.getEntities(region); + } + + @Override + public List getEntities() { + return clipboard.getEntities(); } @Nullable diff --git a/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java b/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java index 8e8ba17c6..492c2362a 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java @@ -1,7 +1,6 @@ package com.boydti.fawe; import com.boydti.fawe.beta.implementation.queue.QueueHandler; -import com.boydti.fawe.config.Caption; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.brush.visualization.VisualQueue; import com.boydti.fawe.regions.general.integrations.plotquared.PlotSquaredFeature; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueChunk.java index f60556029..c512edd9e 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueChunk.java @@ -10,7 +10,7 @@ public interface IQueueChunk> extends IChunk, Callable { * @return */ @Override - default IQueueChunk reset() { + default IQueueChunk reset() { init(null, getX(), getZ()); return this; } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/regions/general/integrations/plotquared/PlotSquaredFeature.java b/worldedit-core/src/main/java/com/boydti/fawe/regions/general/integrations/plotquared/PlotSquaredFeature.java index 0d3f11a0b..c0d24887c 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/regions/general/integrations/plotquared/PlotSquaredFeature.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/regions/general/integrations/plotquared/PlotSquaredFeature.java @@ -97,7 +97,12 @@ public class PlotSquaredFeature extends FaweMaskManager { return false; } UUID uid = player.getUniqueId(); - return !Flags.NO_WORLDEDIT.isTrue(plot) && ((plot.isOwner(uid) || (type == MaskType.MEMBER && (plot.getTrusted().contains(uid) || plot.getTrusted().contains(DBFunc.EVERYONE) || ((plot.getMembers().contains(uid) || plot.getMembers().contains(DBFunc.EVERYONE)) && player.hasPermission("fawe.plotsquared.member"))))) || player.hasPermission("fawe.plotsquared.admin")); + return !Flags.NO_WORLDEDIT.isTrue(plot) && (plot.isOwner(uid) + || type == MaskType.MEMBER && (plot.getTrusted().contains(uid) || plot.getTrusted() + .contains(DBFunc.EVERYONE) + || (plot.getMembers().contains(uid) || plot.getMembers().contains(DBFunc.EVERYONE)) + && player.hasPermission("fawe.plotsquared.member")) || player + .hasPermission("fawe.plotsquared.admin")); } @Override diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/WEManager.java b/worldedit-core/src/main/java/com/boydti/fawe/util/WEManager.java index 6183518f3..82f01dcfc 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/WEManager.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/util/WEManager.java @@ -13,6 +13,7 @@ import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TextComponent; import java.lang.reflect.Field; import java.util.ArrayDeque; import java.util.HashSet; @@ -92,6 +93,7 @@ public class WEManager { backupRegions.add(region); } } else { + player.printDebug(TextComponent.of("Invalid Mask")); removed = true; iterator.remove(); } @@ -115,6 +117,8 @@ public class WEManager { } catch (Throwable e) { e.printStackTrace(); } + } else { + player.printError(TextComponent.of("Missing permission " + "fawe." + manager.getKey())); } } regions.addAll(backupRegions); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java index 9bb608bba..aab9adb8d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java @@ -19,6 +19,9 @@ package com.sk89q.worldedit.function.factory; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.util.GuavaUtil.firstNonNull; + import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; @@ -39,9 +42,6 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.worldedit.util.GuavaUtil.firstNonNull; - public class Deform implements Contextual { private Extent destination; @@ -157,12 +157,6 @@ public class Deform implements Contextual { session == null ? WorldEdit.getInstance().getConfiguration().calculationTimeout : session.getTimeout()); } - public enum Mode { - RAW_COORD, - OFFSET, - UNIT_CUBE - } - private static final class DeformOperation implements Operation { private final Extent destination; private final Region region; @@ -199,9 +193,15 @@ public class Deform implements Contextual { @Override public Iterable getStatusMessages() { return ImmutableList.of(TranslatableComponent.of("worldedit.operation.deform.expression", - TextComponent.of(expression).color(TextColor.GRAY))); + TextComponent.of(expression).color(TextColor.LIGHT_PURPLE))); } } + public enum Mode { + RAW_COORD, + OFFSET, + UNIT_CUBE + } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/Operation.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/Operation.java index c21f2a6f7..85b0631f3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/Operation.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/Operation.java @@ -38,11 +38,6 @@ import java.util.stream.Collectors; */ public interface Operation { - /** - * This is an internal field, and should not be touched. - */ - Set warnedDeprecatedClasses = new HashSet<>(); - /** * Complete the next step. If this method returns true, then the method may * be called again in the future, or possibly never. If this method @@ -74,6 +69,11 @@ public interface Operation { default void addStatusMessages(List messages) { } + /** + * This is an internal field, and should not be touched. + */ + Set warnedDeprecatedClasses = new HashSet<>(); + /** * Gets an iterable of messages that describe the current status of the * operation. @@ -87,7 +87,7 @@ public interface Operation { if (oldMessages.size() > 0) { String className = getClass().getName(); if (!warnedDeprecatedClasses.contains(className)) { - WorldEdit.logger.warn("An operation is using the old status message API. This will be removed in further versions. Class: " + className); + WorldEdit.logger.warn("An operation is using the old status message API. This will be removed in WorldEdit 8. Class: " + className); warnedDeprecatedClasses.add(className); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/Closer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/Closer.java index 1b7aceda3..85e3f10a5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/Closer.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/Closer.java @@ -86,6 +86,27 @@ public final class Closer implements Closeable { return zipFile; } + /** + * Call {@link #rethrow(Throwable)} with the given exception, but before throwing the exception, + * also close this Closer. Exceptions from closing are added to {@code t} as suppressed + * exceptions. + * + * @param t the throwable that should be re-thrown + * @throws IOException if {@code t} is an IOException, or one occurs + */ + public RuntimeException rethrowAndClose(Throwable t) throws IOException { + // bit of a hack here + try { + throw rethrow(t); + } finally { + try { + close(); + } catch (Throwable closeThrown) { + t.addSuppressed(closeThrown); + } + } + } + /** * Stores the given throwable and rethrows it. It will be rethrown as is if it is an * {@code IOException}, {@code RuntimeException} or {@code Error}. Otherwise, it will be rethrown diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/translation/TranslationManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/translation/TranslationManager.java index 46a582736..79ad5d6b2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/translation/TranslationManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/translation/TranslationManager.java @@ -19,6 +19,9 @@ package com.sk89q.worldedit.util.translation; +import static java.util.stream.Collectors.toMap; + +import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; @@ -26,7 +29,6 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.renderer.FriendlyComponentRenderer; import com.sk89q.worldedit.util.io.ResourceLoader; - import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -76,8 +78,10 @@ public class TranslationManager { } private Map filterTranslations(Map translations) { - translations.entrySet().removeIf(entry -> entry.getValue().isEmpty()); - return translations; + return translations.entrySet().stream() + .filter(e -> !e.getValue().isEmpty()) + .map(e -> Maps.immutableEntry(e.getKey(), e.getValue().replace("'", "''"))) + .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); } private Map parseTranslationFile(InputStream inputStream) { @@ -156,4 +160,4 @@ public class TranslationManager { public Locale getDefaultLocale() { return defaultLocale; } -} \ No newline at end of file +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk.java index 3a2336754..f42997187 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/AnvilChunk.java @@ -29,7 +29,6 @@ import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.DataException; -import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; @@ -55,11 +54,10 @@ public class AnvilChunk implements Chunk { /** * Construct the chunk with a compound tag. * - * @param world the world to construct the chunk for * @param tag the tag to read * @throws DataException on a data error */ - public AnvilChunk(World world, CompoundTag tag) throws DataException { + public AnvilChunk(CompoundTag tag) throws DataException { rootTag = tag; rootX = NBTUtils.getChildTag(rootTag.getValue(), "xPos", IntTag.class).getValue(); @@ -261,13 +259,11 @@ public class AnvilChunk implements Chunk { WorldEdit.logger.warn("Unknown legacy block " + id + ":" + data + " found when loading legacy anvil chunk."); return BlockTypes.AIR.getDefaultState().toBaseBlock(); } - if (state.getMaterial().hasContainer()) { CompoundTag tileEntity = getBlockTileEntity(position); if (tileEntity != null) { return state.toBaseBlock(tileEntity); } - } return state.toBaseBlock(); } 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 daf291e8c..e0717c0e2 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 @@ -226,9 +226,9 @@ public class AnvilChunk13 implements Chunk { BlockState[] sectionBlocks = blocks[section]; BlockState state = sectionBlocks != null ? sectionBlocks[(yIndex << 8) | (z << 4) | x] : BlockTypes.AIR.getDefaultState(); - if (state.getMaterial().hasContainer()) { CompoundTag tileEntity = getBlockTileEntity(position); + if (tileEntity != null) { return state.toBaseBlock(tileEntity); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/OldChunk.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/OldChunk.java index 3cc7e002d..540197cee 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/OldChunk.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/chunk/OldChunk.java @@ -28,7 +28,6 @@ import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.DataException; -import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; @@ -55,11 +54,10 @@ public class OldChunk implements Chunk { /** * Construct the chunk with a compound tag. * - * @param world the world * @param tag the tag * @throws DataException */ - public OldChunk(World world, CompoundTag tag) throws DataException { + public OldChunk(CompoundTag tag) throws DataException { rootTag = tag; blocks = NBTUtils.getChildTag(rootTag.getValue(), "Blocks", ByteArrayTag.class).getValue(); @@ -185,13 +183,12 @@ public class OldChunk implements Chunk { WorldEdit.logger.warn("Unknown legacy block " + id + ":" + dataVal + " found when loading legacy anvil chunk."); return BlockTypes.AIR.getDefaultState().toBaseBlock(); } - if (state.getBlockType().getMaterial().hasContainer()) { + CompoundTag tileEntity = getBlockTileEntity(position); if (tileEntity != null) { return state.toBaseBlock(tileEntity); } - } return state.toBaseBlock(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStore.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStore.java index 1b89c8b09..e975a200f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStore.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStore.java @@ -20,34 +20,19 @@ package com.sk89q.worldedit.world.storage; import com.sk89q.jnbt.CompoundTag; -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.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.DataException; -import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.World; -import com.sk89q.worldedit.world.chunk.AnvilChunk; -import com.sk89q.worldedit.world.chunk.AnvilChunk13; import com.sk89q.worldedit.world.chunk.Chunk; -import com.sk89q.worldedit.world.chunk.OldChunk; - import java.io.Closeable; import java.io.IOException; -import java.util.Map; /** * Represents chunk storage mechanisms. */ public abstract class ChunkStore implements Closeable { - /** - * The DataVersion for Minecraft 1.13 - */ - private static final int DATA_VERSION_MC_1_13 = 1519; - /** * {@code >>} - to chunk * {@code <<} - from chunk @@ -85,46 +70,7 @@ public abstract class ChunkStore implements Closeable { */ public Chunk getChunk(BlockVector2 position, World world) throws DataException, IOException { CompoundTag rootTag = getChunkTag(position, world); - - Map children = rootTag.getValue(); - CompoundTag tag = null; - - // Find Level tag - for (Map.Entry entry : children.entrySet()) { - if (entry.getKey().equals("Level")) { - if (entry.getValue() instanceof CompoundTag) { - tag = (CompoundTag) entry.getValue(); - break; - } else { - throw new ChunkStoreException("CompoundTag expected for 'Level'; got " + entry.getValue().getClass().getName()); - } - } - } - - if (tag == null) { - throw new ChunkStoreException("Missing root 'Level' tag"); - } - - int dataVersion = rootTag.getInt("DataVersion"); - 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 - final DataFixer dataFixer = platform.getDataFixer(); - if (dataFixer != null) { - return new AnvilChunk13((CompoundTag) dataFixer.fixUp(DataFixer.FixTypes.CHUNK, rootTag, dataVersion).getValue().get("Level")); - } - } - if (dataVersion >= DATA_VERSION_MC_1_13) { - return new AnvilChunk13(tag); - } - - Map tags = tag.getValue(); - if (tags.containsKey("Sections")) { - return new AnvilChunk(world, tag); - } - - return new OldChunk(world, tag); + return ChunkStoreHelper.getChunk(rootTag); } @Override 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 new file mode 100644 index 000000000..083f868b2 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/ChunkStoreHelper.java @@ -0,0 +1,117 @@ +/* + * 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 Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.world.storage; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.NBTInputStream; +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.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.Chunk; +import com.sk89q.worldedit.world.chunk.OldChunk; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +public class ChunkStoreHelper { + + @FunctionalInterface + public interface ChunkDataInputSupplier { + + InputStream openInputStream() throws DataException, IOException; + + } + + public static CompoundTag readCompoundTag(ChunkDataInputSupplier input) throws DataException, IOException { + try (InputStream stream = input.openInputStream(); + NBTInputStream nbt = new NBTInputStream(stream)) { + Tag tag = nbt.readNamedTag().getTag(); + if (!(tag instanceof CompoundTag)) { + throw new ChunkStoreException("CompoundTag expected for chunk; got " + + tag.getClass().getName()); + } + + return (CompoundTag) tag; + } + } + + /** + * 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. + * + * @param rootTag the root tag of the chunk + * @return a Chunk implementation + * @throws DataException if the rootTag is not valid chunk data + */ + public static Chunk getChunk(CompoundTag rootTag) throws DataException { + Map children = rootTag.getValue(); + CompoundTag tag = null; + + // Find Level tag + for (Map.Entry entry : children.entrySet()) { + if (entry.getKey().equals("Level")) { + if (entry.getValue() instanceof CompoundTag) { + tag = (CompoundTag) entry.getValue(); + break; + } else { + throw new ChunkStoreException("CompoundTag expected for 'Level'; got " + entry.getValue().getClass().getName()); + } + } + } + + if (tag == null) { + throw new ChunkStoreException("Missing root 'Level' tag"); + } + + int dataVersion = rootTag.getInt("DataVersion"); + 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 + final DataFixer dataFixer = platform.getDataFixer(); + if (dataFixer != null) { + return new AnvilChunk13((CompoundTag) dataFixer.fixUp(DataFixer.FixTypes.CHUNK, rootTag, dataVersion).getValue().get("Level")); + } + } + if (dataVersion >= DATA_VERSION_MC_1_13) { + return new AnvilChunk13(tag); + } + + Map tags = tag.getValue(); + if (tags.containsKey("Sections")) { + return new AnvilChunk(tag); + } + + return new OldChunk(tag); + } + + private ChunkStoreHelper() { + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/LegacyChunkStore.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/LegacyChunkStore.java index b3b5728fe..af302ff62 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/LegacyChunkStore.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/storage/LegacyChunkStore.java @@ -20,12 +20,9 @@ package com.sk89q.worldedit.world.storage; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.NBTInputStream; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.world.DataException; import com.sk89q.worldedit.world.World; - import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -78,18 +75,9 @@ public abstract class LegacyChunkStore extends ChunkStore { String filename = "c." + Integer.toString(x, 36) + "." + Integer.toString(z, 36) + ".dat"; - InputStream stream = getInputStream(folder1, folder2, filename); - Tag tag; - - try (NBTInputStream nbt = new NBTInputStream(new GZIPInputStream(stream))) { - tag = nbt.readNamedTag().getTag(); - if (!(tag instanceof CompoundTag)) { - throw new ChunkStoreException("CompoundTag expected for chunk; got " - + tag.getClass().getName()); - } - - return (CompoundTag) tag; - } + return ChunkStoreHelper.readCompoundTag(() -> + new GZIPInputStream(getInputStream(folder1, folder2, filename)) + ); } private static int divisorMod(int a, int n) { diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index deb5d268a..85a9d8dbf 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -6,11 +6,11 @@ "fawe.worldedit.history.find.element": "&8 - &2{0}: {1} &7ago &3{2}m &6{3} &c/{4}", "fawe.worldedit.history.find.hover": "{0} blocks changed, click for more info", - + "fawe.info.lighting.propagate.selection": "Lighting has been propogated in {0} chunks. (Note: To remove light use //removelight)", "fawe.info.updated.lighting.selection": "Lighting has been updated in {0} chunks. (It may take a second for the packets to send)", "fawe.info.set.region": "Selection set to your current allowed region", - + "fawe.info.worldedit.command.limit": "Please wait until your current action completes", "fawe.info.worldedit.delayed": "Please wait while we process your FAWE action...", "fawe.info.worldedit.run": "Apologies for the delay. Now executing: {0}", @@ -331,7 +331,7 @@ "fawe.tips.tip.regen.1": "Tip: Use a seed with /regen [biome] [seed]", "fawe.tips.tip.biome.pattern": "Tip: The #biome[forest] pattern can be used in any command", "fawe.tips.tip.biome.mask": "Tip: Restrict to a biome with the `$jungle` mask", - + "worldedit.expand.description.vert": "Vertically expand the selection to world limits.", "worldedit.expand.expanded": "Region expanded {0} blocks", "worldedit.expand.expanded.vert": "Region expanded {0} blocks (top-to-bottom).", @@ -408,6 +408,7 @@ "worldedit.restore.failed": "Failed to load snapshot: {0}", "worldedit.restore.loaded": "Snapshot '{0}' loaded; now restoring...", "worldedit.restore.restored": "Restored; {0} missing chunks and {1} other errors.", + "worldedit.restore.none-for-specific-world": "No snapshots were found for world '{0}'.", "worldedit.restore.none-for-world": "No snapshots were found for this world.", "worldedit.restore.none-found": "No snapshots were found.", "worldedit.restore.none-found-console": "No snapshots were found. See console for details.", @@ -502,7 +503,7 @@ "worldedit.paste.pasted": "The clipboard has been pasted at {0}", "worldedit.paste.selected": "Selected clipboard paste region.", - + "worldedit.rotate.no-interpolation": "Note: Interpolation is not yet supported, so angles that are multiples of 90 is recommended.", "worldedit.rotate.rotated": "The clipboard copy has been rotated.", "worldedit.flip.flipped": "The clipboard copy has been flipped.", @@ -517,6 +518,7 @@ "worldedit.replace.replaced": "{0} blocks have been replaced.", "worldedit.stack.changed": "{0} blocks changed. Undo with //undo", "worldedit.regen.regenerated": "Region regenerated.", + "worldedit.regen.failed": "Unable to regenerate chunks. Check console for details.", "worldedit.walls.changed": "{0} blocks have been changed.", "worldedit.faces.changed": "{0} blocks have been changed.", "worldedit.overlay.overlaid": "{0} blocks have been overlaid.",