From 2517aca66fb91cd4127c60ca92ab4537924f3397 Mon Sep 17 00:00:00 2001 From: MattBDev <4009945+MattBDev@users.noreply.github.com> Date: Sun, 28 Jun 2020 17:31:13 -0400 Subject: [PATCH 01/18] Removed some unnecessary code. --- .../main/java/com/boydti/fawe/FaweAPI.java | 26 ------------------- .../com/boydti/fawe/object/HistoryExtent.java | 2 +- .../object/changeset/AbstractChangeSet.java | 1 + .../fawe/object/regions/FuzzyRegion.java | 13 +++------- 4 files changed, 5 insertions(+), 37 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/FaweAPI.java b/worldedit-core/src/main/java/com/boydti/fawe/FaweAPI.java index f725f7e39..66c0f0978 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/FaweAPI.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/FaweAPI.java @@ -78,32 +78,6 @@ public class FaweAPI { return TaskManager.IMP; } -// /** -// * Add a custom mask for use in e.g {@literal //mask #id:} -// * -// * @param methods The class with a bunch of mask methods -// * @return true if the mask was registered -// * @see com.sk89q.worldedit.command.MaskCommands -// */ -// public static boolean registerMasks(Object methods) { -// DefaultMaskParser parser = getParser(DefaultMaskParser.class); -// if (parser != null) parser.register(methods); -// return parser != null; -// } -// -// /** -// * Add a custom material for use in e.g {@literal //material #id:} -// * -// * @param methods The class with a bunch of pattern methods -// * @return true if the mask was registered -// * @see com.sk89q.worldedit.command.PatternCommands -// */ -// public static boolean registerPatterns(Object methods) { -// DefaultPatternParser parser = getParser(DefaultPatternParser.class); -// if (parser != null) parser.register(methods); -// return parser != null; -// } -// // /** // * Add a custom transform for use in // * diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/HistoryExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/HistoryExtent.java index e6ae99514..4ae2da1aa 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/HistoryExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/HistoryExtent.java @@ -30,7 +30,7 @@ public class HistoryExtent extends AbstractDelegateExtent { /** * Create a new instance. * - * @param extent the extent + * @param extent the extent * @param changeSet the change set */ public HistoryExtent(Extent extent, AbstractChangeSet changeSet) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractChangeSet.java index 4fa22d579..ad5f0ca79 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractChangeSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/AbstractChangeSet.java @@ -46,6 +46,7 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { private final World world; protected AtomicInteger waitingCombined = new AtomicInteger(0); protected AtomicInteger waitingAsync = new AtomicInteger(0); + protected boolean closed; public AbstractChangeSet(World world) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/regions/FuzzyRegion.java b/worldedit-core/src/main/java/com/boydti/fawe/object/regions/FuzzyRegion.java index d710bd92b..ff1ad748a 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/regions/FuzzyRegion.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/regions/FuzzyRegion.java @@ -2,11 +2,7 @@ package com.boydti.fawe.object.regions; import com.boydti.fawe.object.collection.BlockVectorSet; import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.RegionFunction; -import com.sk89q.worldedit.function.mask.AbstractExtentMask; -import com.sk89q.worldedit.function.mask.DelegateExtentMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.visitor.RecursiveVisitor; @@ -45,12 +41,9 @@ public class FuzzyRegion extends AbstractRegion { } public void select(int x, int y, int z) { - RecursiveVisitor search = new RecursiveVisitor(mask.withExtent(extent), new RegionFunction() { - @Override - public boolean apply(BlockVector3 p) throws WorldEditException { - setMinMax(p.getBlockX(), p.getBlockY(), p.getBlockZ()); - return true; - } + RecursiveVisitor search = new RecursiveVisitor(mask.withExtent(extent), p -> { + setMinMax(p.getBlockX(), p.getBlockY(), p.getBlockZ()); + return true; }, 256); search.setVisited(set); search.visit(BlockVector3.at(x, y, z)); From 68679e007ed7bbc18ed312b1c28b679cba6ee35a Mon Sep 17 00:00:00 2001 From: IronApollo Date: Fri, 26 Jun 2020 19:08:45 -0400 Subject: [PATCH 02/18] Work towards 1.16 compatibility This commit will allow the branch to build properly but the plugin will not function properly due to the lack of a proper adapter implementation. Proceeding will require the implementation of the SideEffects system from upstream (https://github.com/EngineHub/WorldEdit/commit/865c3a24d25156cbffbf44630506a08d2ff4755a#diff-8fd33296e427c87d0296ad7f3ccc050a). --- .../mc1_16_1/BukkitAdapter_1_16_1.java | 5 + .../mc1_16_1/BukkitGetBlocks_1_16_1.java | 4 +- .../worldedit/bukkit/WorldEditPlugin.java | 2 + .../adapter/impl/FAWE_Spigot_v1_16_R1.java | 165 +++++++++--------- 4 files changed, 94 insertions(+), 82 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitAdapter_1_16_1.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitAdapter_1_16_1.java index 74ae46eb2..7b1549d65 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitAdapter_1_16_1.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitAdapter_1_16_1.java @@ -38,6 +38,8 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter { public final static Field fieldPalette; public final static Field fieldSize; + public final static Field fieldBitsPerEntry; + public final static Field fieldFluidCount; public final static Field fieldTickingBlockCount; public final static Field fieldNonEmptyBlockCount; @@ -61,6 +63,9 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter { fieldPalette = DataPaletteBlock.class.getDeclaredField("h"); fieldPalette.setAccessible(true); + fieldBitsPerEntry = DataBits.class.getDeclaredField("c"); + fieldBitsPerEntry.setAccessible(true); + fieldFluidCount = ChunkSection.class.getDeclaredField("e"); fieldFluidCount.setAccessible(true); fieldTickingBlockCount = ChunkSection.class.getDeclaredField("tickingBlockCount"); diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java index 110a47298..b07589339 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java @@ -465,7 +465,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks { tag.set("x", NBTTagInt.a(x)); tag.set("y", NBTTagInt.a(y)); tag.set("z", NBTTagInt.a(z)); - tileEntity.load(tag); + tileEntity.load(tileEntity.getBlock(), tag); } } } @@ -550,7 +550,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks { final DataBits bits = (DataBits) BukkitAdapter_1_16_1.fieldBits.get(blocks); final DataPalette palette = (DataPalette) BukkitAdapter_1_16_1.fieldPalette.get(blocks); - final int bitsPerEntry = bits.c(); + final int bitsPerEntry = (int) BukkitAdapter_1_16_1.fieldBitsPerEntry.get(bits); final long[] blockStates = bits.a(); new BitArray(bitsPerEntry, 4096, blockStates).toRaw(data); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java index ae66a73af..3124b04f6 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java @@ -34,6 +34,7 @@ import com.sk89q.worldedit.bukkit.adapter.AdapterLoadException; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplLoader; import com.sk89q.worldedit.bukkit.adapter.impl.FAWE_Spigot_v1_15_R2; +import com.sk89q.worldedit.bukkit.adapter.impl.FAWE_Spigot_v1_16_R1; import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.event.platform.PlatformReadyEvent; @@ -371,6 +372,7 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter try { adapterLoader.addClass(FAWE_Spigot_v1_14_R4.class); adapterLoader.addClass(FAWE_Spigot_v1_15_R2.class); + adapterLoader.addClass(FAWE_Spigot_v1_16_R1.class); } catch (Throwable throwable) { throwable.printStackTrace(); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java index 5cf63b4d3..695aeca79 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java @@ -27,6 +27,9 @@ import com.boydti.fawe.beta.IQueueExtent; import com.boydti.fawe.beta.implementation.packet.ChunkPacket; import com.boydti.fawe.beta.implementation.queue.SingleThreadQueueExtent; import com.boydti.fawe.bukkit.adapter.mc1_16_1.BlockMaterial_1_16_1; +import com.boydti.fawe.bukkit.adapter.mc1_16_1.BukkitAdapter_1_16_1; +import com.boydti.fawe.bukkit.adapter.mc1_16_1.BukkitGetBlocks_1_16_1; +import com.boydti.fawe.bukkit.adapter.mc1_16_1.MapChunkUtil_1_16_1; import com.boydti.fawe.bukkit.adapter.mc1_16_1.nbt.LazyCompoundTag_1_16_1; import com.google.common.io.Files; import com.sk89q.jnbt.CompoundTag; @@ -49,18 +52,18 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.*; import com.sk89q.worldedit.world.entity.EntityType; import com.sk89q.worldedit.world.registry.BlockMaterial; -import net.minecraft.server.v1_15_R1.*; +import net.minecraft.server.v1_16_R1.*; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World.Environment; import org.bukkit.block.data.BlockData; -import org.bukkit.craftbukkit.v1_15_R1.CraftChunk; -import org.bukkit.craftbukkit.v1_15_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_15_R1.block.CraftBlock; -import org.bukkit.craftbukkit.v1_15_R1.block.data.CraftBlockData; -import org.bukkit.craftbukkit.v1_15_R1.entity.CraftEntity; -import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_16_R1.CraftChunk; +import org.bukkit.craftbukkit.v1_16_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_16_R1.block.CraftBlock; +import org.bukkit.craftbukkit.v1_16_R1.block.data.CraftBlockData; +import org.bukkit.craftbukkit.v1_16_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_16_R1.inventory.CraftItemStack; import org.bukkit.entity.Player; import org.bukkit.generator.ChunkGenerator; @@ -192,7 +195,7 @@ public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements I tag.set("x", NBTTagInt.a(x)); tag.set("y", NBTTagInt.a(y)); tag.set("z", NBTTagInt.a(z)); - tileEntity.load(tag); // readTagIntoTileEntity - load data + tileEntity.load(tileEntity.getBlock(), tag); // readTagIntoTileEntity - load data } } } else { @@ -368,78 +371,80 @@ public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements I @Override public boolean regenerate(org.bukkit.World world, Region region, EditSession editSession) { - WorldServer originalWorld = ((CraftWorld) world).getHandle(); - ChunkProviderServer provider = originalWorld.getChunkProvider(); - if (!(provider instanceof ChunkProviderServer)) { - return false; - } +// WorldServer originalWorld = ((CraftWorld) world).getHandle(); +// ChunkProviderServer provider = originalWorld.getChunkProvider(); +// if (!(provider instanceof ChunkProviderServer)) { +// return false; +// } +// +// File saveFolder = Files.createTempDir(); +// // register this just in case something goes wrong +// // normally it should be deleted at the end of this method +// saveFolder.deleteOnExit(); +// try { +// MinecraftServer server = originalWorld.getServer().getServer(); +// Convertable.ConversionSession originalDataManager = server.convertable; +//// Convertable.ConversionSession saveHandler = new Convertable.ConversionSession(world.getName(), world.); +// WorldData newWorldData = new WorldData(originalWorld.worldData.a((NBTTagCompound) null), +// server.dataConverterManager, getDataVersion(), null); +// newWorldData.setName(UUID.randomUUID().toString()); +// +// ChunkGenerator gen = world.getGenerator(); +// Environment env = world.getEnvironment(); +// try (WorldServer freshWorld = new WorldServer(server, +// server.executorService, originalDataManager, +// newWorldData, +// originalWorld.worldProvider.getDimensionManager(), +// originalWorld.getMethodProfiler(), +// server.worldLoadListenerFactory.create(11), +// env, +// gen){ +// @Override +// public boolean addEntityChunk(Entity entity) { +// //Fixes #320; Prevent adding entities so we aren't attempting to spawn them asynchronously +// return false; +// } +// }) { +// +// // Pre-gen all the chunks +// // We need to also pull one more chunk in every direction +// Fawe.get().getQueueHandler().startSet(true); +// try { +// IQueueExtent extent = new SingleThreadQueueExtent(); +// extent.init(null, (x, z) -> new BukkitGetBlocks_1_16_1(freshWorld, x, z) { +// @Override +// public Chunk ensureLoaded(World nmsWorld, int X, int Z) { +// Chunk cached = nmsWorld.getChunkIfLoaded(X, Z); +// if (cached != null) return cached; +// Future future = Fawe.get().getQueueHandler().sync((Supplier) () -> freshWorld.getChunkAt(X, Z)); +// while (!future.isDone()) { +// // this feels so dirty +// freshWorld.getChunkProvider().runTasks(); +// } +// try { +// return future.get(); +// } catch (InterruptedException | ExecutionException e) { +// throw new RuntimeException(e); +// } +// } +// }, null); +// for (BlockVector3 vec : region) { +// editSession.setBlock(vec, extent.getFullBlock(vec)); +// } +// } finally { +// Fawe.get().getQueueHandler().endSet(true); +// } +// } catch (IOException e) { +// throw new RuntimeException(e); +// } +// } catch (MaxChangedBlocksException e) { +// throw new RuntimeException(e); +// } finally { +// saveFolder.delete(); +// } +// return true; - File saveFolder = Files.createTempDir(); - // register this just in case something goes wrong - // normally it should be deleted at the end of this method - saveFolder.deleteOnExit(); - try { - MinecraftServer server = originalWorld.getServer().getServer(); - WorldNBTStorage originalDataManager = originalWorld.getDataManager(); - WorldNBTStorage saveHandler = new WorldNBTStorage(saveFolder, originalDataManager.getDirectory().getName(), server, originalDataManager.getDataFixer()); - WorldData newWorldData = new WorldData(originalWorld.worldData.a((NBTTagCompound) null), - server.dataConverterManager, getDataVersion(), null); - newWorldData.setName(UUID.randomUUID().toString()); - - ChunkGenerator gen = world.getGenerator(); - Environment env = world.getEnvironment(); - try (WorldServer freshWorld = new WorldServer(server, - server.executorService, saveHandler, - newWorldData, - originalWorld.worldProvider.getDimensionManager(), - originalWorld.getMethodProfiler(), - server.worldLoadListenerFactory.create(11), - env, - gen){ - @Override - public boolean addEntityChunk(Entity entity) { - //Fixes #320; Prevent adding entities so we aren't attempting to spawn them asynchronously - return false; - } - }) { - - // Pre-gen all the chunks - // We need to also pull one more chunk in every direction - Fawe.get().getQueueHandler().startSet(true); - try { - IQueueExtent extent = new SingleThreadQueueExtent(); - extent.init(null, (x, z) -> new BukkitGetBlocks_1_16_1(freshWorld, x, z) { - @Override - public Chunk ensureLoaded(World nmsWorld, int X, int Z) { - Chunk cached = nmsWorld.getChunkIfLoaded(X, Z); - if (cached != null) return cached; - Future future = Fawe.get().getQueueHandler().sync((Supplier) () -> freshWorld.getChunkAt(X, Z)); - while (!future.isDone()) { - // this feels so dirty - freshWorld.getChunkProvider().runTasks(); - } - try { - return future.get(); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException(e); - } - } - }, null); - for (BlockVector3 vec : region) { - editSession.setBlock(vec, extent.getFullBlock(vec)); - } - } finally { - Fawe.get().getQueueHandler().endSet(true); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } catch (MaxChangedBlocksException e) { - throw new RuntimeException(e); - } finally { - saveFolder.delete(); - } - return true; + return false; //TODO: rework or remove for 1.16 } @Override From 4604aa59203f8b870e4b4fed29934a9cf54a284a Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Sun, 8 Mar 2020 16:09:36 +1000 Subject: [PATCH 03/18] Additional work towards 1.16 compatibility - Very basic implementation of the SideEffects system. Will definitely need fine tuning for it to be functional, but is not considered a priority in my opinion. - Minor changes to the World interface and World implementations related to the SideEffects system. Shouldn't be the cause of any new bugs but be on the lookout. - Included debug in BukkitImplLoader.java to assist contributors in understanding what needs to be implemented for the adapter to load properly. Still very WIP but we're a few steps closer. So far, this is coming along better than I anticipated. Hopefully we can keep the momentum. --- config/checkstyle/checkstyle.xml | 2 +- .../bukkit/BukkitServerInterface.java | 16 +++- .../sk89q/worldedit/bukkit/BukkitWorld.java | 32 ++++--- .../bukkit/adapter/BukkitImplAdapter.java | 20 +++- .../bukkit/adapter/BukkitImplLoader.java | 13 ++- .../adapter/IDelegateBukkitImplAdapter.java | 8 +- .../adapter/impl/FAWE_Spigot_v1_14_R4.java | 23 ++++- .../adapter/impl/FAWE_Spigot_v1_15_R2.java | 25 +++-- .../adapter/impl/FAWE_Spigot_v1_16_R1.java | 25 +++-- .../com/sk89q/worldedit/cli/CLIPlatform.java | 8 ++ .../cli/schematic/ClipboardWorld.java | 11 ++- .../com/boydti/fawe/jnbt/anvil/MCAWorld.java | 14 +++ .../cfi/HeightMapMCAGenerator.java | 22 +++-- .../boydti/fawe/wrappers/WorldWrapper.java | 16 +++- .../java/com/sk89q/worldedit/EditSession.java | 15 +++ .../com/sk89q/worldedit/LocalSession.java | 31 +++++- .../worldedit/command/GeneralCommands.java | 69 +++++++++++--- .../command/argument/EnumConverter.java | 7 ++ .../command/argument/SideEffectConverter.java | 75 +++++++++++++++ .../extension/platform/Platform.java | 4 + .../platform/PlatformCommandManager.java | 2 + .../extension/platform/PlatformManager.java | 6 ++ .../worldedit/extent/buffer/ExtentBuffer.java | 5 +- .../extent/reorder/ChunkBatchingExtent.java | 1 - ...tModeExtent.java => SideEffectExtent.java} | 86 ++++++----------- .../com/sk89q/worldedit/util/SideEffect.java | 68 ++++++++++++++ .../sk89q/worldedit/util/SideEffectSet.java | 94 +++++++++++++++++++ .../formatting/component/SideEffectBox.java | 88 +++++++++++++++++ .../sk89q/worldedit/world/AbstractWorld.java | 3 +- .../com/sk89q/worldedit/world/NullWorld.java | 11 ++- .../java/com/sk89q/worldedit/world/World.java | 41 +++++++- .../src/main/resources/lang/strings.json | 20 ++++ worldedit-fabric/build.gradle.kts | 4 - .../worldedit/fabric/FabricPlatform.java | 15 ++- .../sk89q/worldedit/fabric/FabricWorld.java | 71 +++++++++++--- worldedit-forge/build.gradle.kts | 7 +- .../sk89q/worldedit/forge/ForgePlatform.java | 13 +++ .../com/sk89q/worldedit/forge/ForgeWorld.java | 73 ++++++++++++-- .../worldedit/sponge/SpongePlatform.java | 9 ++ 39 files changed, 877 insertions(+), 176 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/SideEffectConverter.java rename worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/{FastModeExtent.java => SideEffectExtent.java} (63%) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffect.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffectSet.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/SideEffectBox.java diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index ab1c6d499..8dbf07f8f 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -68,6 +68,6 @@ - + diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java index d948d0e0a..99a4b183b 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.bukkit; +import com.google.common.collect.Sets; import com.sk89q.bukkit.util.CommandInfo; import com.sk89q.bukkit.util.CommandRegistration; import com.sk89q.worldedit.LocalConfiguration; @@ -30,6 +31,7 @@ import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.MultiUserPlatform; import com.sk89q.worldedit.extension.platform.Preference; import com.sk89q.worldedit.extension.platform.Watchdog; +import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.registry.Registries; @@ -44,8 +46,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.EnumMap; import java.util.List; -import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -218,6 +220,18 @@ public class BukkitServerInterface implements MultiUserPlatform { return capabilities; } + private static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( + SideEffect.NEIGHBORS + ); + + @Override + public Set getSupportedSideEffects() { + if (plugin.getBukkitImplAdapter() != null) { + return plugin.getBukkitImplAdapter().getSupportedSideEffects(); + } + return SUPPORTED_SIDE_EFFECTS; + } + public void unregisterCommands() { dynamicCommands.unregisterCommands(); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index 2818a8434..f11fc13d3 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -25,6 +25,7 @@ import com.boydti.fawe.Fawe; import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.implementation.packet.ChunkPacket; import com.sk89q.jnbt.CompoundTag; +import com.google.common.collect.Sets; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; @@ -38,6 +39,8 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.biome.BiomeType; @@ -48,12 +51,7 @@ import com.sk89q.worldedit.world.weather.WeatherTypes; import io.papermc.lib.PaperLib; import java.lang.ref.WeakReference; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.util.*; import javax.annotation.Nullable; import org.bukkit.Effect; import org.bukkit.TreeType; @@ -466,11 +464,11 @@ public class BukkitWorld extends AbstractWorld { } @Override - public > boolean setBlock(BlockVector3 position, B block, boolean notifyAndLight) throws WorldEditException { + public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); if (adapter != null) { try { - return adapter.setBlock(BukkitAdapter.adapt(getWorld(), position), block, notifyAndLight); + return adapter.setBlock(BukkitAdapter.adapt(getWorld(), position), block, sideEffects); } catch (Exception e) { if (block instanceof BaseBlock && ((BaseBlock) block).getNbtData() != null) { logger.warn("Tried to set a corrupt tile entity at " + position.toString()); @@ -478,12 +476,12 @@ public class BukkitWorld extends AbstractWorld { } e.printStackTrace(); Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - bukkitBlock.setBlockData(BukkitAdapter.adapt(block), notifyAndLight); + bukkitBlock.setBlockData(BukkitAdapter.adapt(block), sideEffects.doesApplyAny()); return true; } } else { Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - bukkitBlock.setBlockData(BukkitAdapter.adapt(block), false); + bukkitBlock.setBlockData(BukkitAdapter.adapt(block), sideEffects.doesApplyAny()); return true; } } @@ -499,14 +497,20 @@ public class BukkitWorld extends AbstractWorld { } @Override - public boolean notifyAndLightBlock(BlockVector3 position, com.sk89q.worldedit.world.block.BlockState previousType) throws WorldEditException { + public Set applySideEffects(BlockVector3 position, com.sk89q.worldedit.world.block.BlockState previousType, SideEffectSet sideEffectSet) throws WorldEditException { BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); if (adapter != null) { - adapter.notifyAndLightBlock(BukkitAdapter.adapt(getWorld(), position), previousType); - return true; + adapter.applySideEffects(BukkitAdapter.adapt(getWorld(), position), previousType, sideEffectSet); + return Sets.intersection( + adapter.getSupportedSideEffects(), + sideEffectSet.getSideEffectsToApply() + ); } - return false; + return Sets.intersection( + WorldEditPlugin.getInstance().getInternalPlatform().getSupportedSideEffects(), + sideEffectSet.getSideEffectsToApply() + ); } @Override diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java index 591626f0f..416b4b621 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java @@ -34,6 +34,8 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; @@ -43,6 +45,7 @@ import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.registry.BlockMaterial; import java.util.Map; import java.util.OptionalInt; +import java.util.Set; import javax.annotation.Nullable; import org.bukkit.Location; import org.bukkit.World; @@ -99,19 +102,19 @@ public interface BukkitImplAdapter extends IBukkitAdapter { * * @param location the location * @param state the block - * @param notifyAndLight notify and light if set + * @param sideEffectSet side effects to apply * @return true if a block was likely changed */ - > boolean setBlock(Location location, B state, boolean notifyAndLight); + boolean setBlock(Location location, BlockStateHolder state, SideEffectSet sideEffectSet); /** - * Notifies the simulation that the block at the given location has - * been changed and it must be re-lighted (and issue other events). + * Applies side effects on the given block. * * @param position position of the block * @param previousType the type of the previous block that was there + * @param sideEffectSet side effects to apply */ - void notifyAndLightBlock(Location position, BlockState previousType); + void applySideEffects(Location position, BlockState previousType, SideEffectSet sideEffectSet); /** * Get the state for the given entity. @@ -186,6 +189,13 @@ public interface BukkitImplAdapter extends IBukkitAdapter { */ BaseItemStack adapt(ItemStack itemStack); + /** + * Get the {@link SideEffect}s that this adapter supports. + * + * @return The side effects that are supported + */ + Set getSupportedSideEffects(); + default OptionalInt getInternalBlockStateId(BlockData data) { // return OptionalInt.empty(); return getInternalBlockStateId(BukkitAdapter.adapt(data)); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java index 172aaa2e7..00807b4b5 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java @@ -155,11 +155,20 @@ public class BukkitImplLoader { */ public BukkitImplAdapter loadAdapter() throws AdapterLoadException { for (String className : adapterCandidates) { + System.out.println("Candidate: " + className); try { Class cls = Class.forName(className); - if (cls.isSynthetic()) continue; + if (cls.isSynthetic()){ + System.out.println(className + " is synthetic, continuing"); + continue; + }else{ + System.out.println(className + " is not synthetic"); + } if (BukkitImplAdapter.class.isAssignableFrom(cls)) { + System.out.println(className + " is assignable from BukkitImplAdapter, returning"); return (BukkitImplAdapter) cls.newInstance(); + }else{ + System.out.println(className + " is NOT assignable from BukkitImplAdapter, returning"); } } catch (ClassNotFoundException e) { log.warn("Failed to load the Bukkit adapter class '" + className + @@ -170,6 +179,8 @@ public class BukkitImplLoader { } catch (Throwable e) { if (className.equals(customCandidate)) { log.warn("Failed to load the Bukkit adapter class '" + className + "'", e); + }else{ + log.warn(className + " is not custom candidate.", e); } } } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/IDelegateBukkitImplAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/IDelegateBukkitImplAdapter.java index 6656c032f..9f5499dcd 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/IDelegateBukkitImplAdapter.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/IDelegateBukkitImplAdapter.java @@ -12,6 +12,7 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; @@ -66,12 +67,7 @@ public interface IDelegateBukkitImplAdapter extends BukkitImplAdapter { } default > boolean setBlock(Location location, B state, boolean notifyAndLight) { - return getParent().setBlock(location, state, notifyAndLight); - } - - @Override - default void notifyAndLightBlock(Location position, BlockState previousType) { - getParent().notifyAndLightBlock(position, previousType); + return getParent().setBlock(location, state, SideEffectSet.none()); } @Override diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_14_R4.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_14_R4.java index b5094f0db..21bcf1718 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_14_R4.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_14_R4.java @@ -45,6 +45,8 @@ import com.sk89q.worldedit.entity.LazyBaseEntity; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BlockState; @@ -71,6 +73,7 @@ import java.io.File; import java.io.IOException; import java.util.Map; import java.util.OptionalInt; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.function.Supplier; @@ -148,6 +151,21 @@ public final class FAWE_Spigot_v1_14_R4 extends CachedBukkitAdapter implements I return state.toBaseBlock(); } + @Override + public boolean setBlock(Location location, BlockStateHolder state, SideEffectSet sideEffectSet) { + return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, sideEffectSet.shouldApply(SideEffect.LIGHTING)); + } + + @Override + public void applySideEffects(Location position, BlockState previousType, SideEffectSet sideEffectSet) { + return; //TODO: properly implement SideEffects into FAWE + } + + @Override + public Set getSupportedSideEffects() { + return SideEffectSet.defaults().getSideEffectsToApply(); + } + @Override public > boolean setBlock(Location location, B state, boolean notifyAndLight) { return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, notifyAndLight); @@ -292,11 +310,6 @@ public final class FAWE_Spigot_v1_14_R4 extends CachedBukkitAdapter implements I return material.getCraftBlockData(); } - @Override - public void notifyAndLightBlock(Location position, BlockState previousType) { - this.setBlock(position.getChunk(), position.getBlockX(), position.getBlockY(), position.getBlockZ(), previousType, true); - } - private MapChunkUtil_1_14 mapUtil = new MapChunkUtil_1_14(); @Override diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_15_R2.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_15_R2.java index 3ee354bd6..ffbe28f1d 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_15_R2.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_15_R2.java @@ -47,6 +47,8 @@ import com.sk89q.worldedit.entity.LazyBaseEntity; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BlockState; @@ -73,6 +75,7 @@ import java.io.File; import java.io.IOException; import java.util.Map; import java.util.OptionalInt; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -157,12 +160,27 @@ public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements I return state.toBaseBlock(); } + @Override + public boolean setBlock(Location location, BlockStateHolder state, SideEffectSet sideEffectSet) { + return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, sideEffectSet.shouldApply(SideEffect.LIGHTING)); + } + + @Override + public void applySideEffects(Location position, BlockState previousType, SideEffectSet sideEffectSet) { + return; //TODO: properly implement SideEffects into FAWE + } + + @Override + public Set getSupportedSideEffects() { + return SideEffectSet.defaults().getSideEffectsToApply(); + } + @Override public > boolean setBlock(Location location, B state, boolean notifyAndLight) { return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, notifyAndLight); } - public > boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, B state, boolean update) { + public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) { CraftChunk craftChunk = (CraftChunk) chunk; Chunk nmsChunk = craftChunk.getHandle(); World nmsWorld = nmsChunk.getWorld(); @@ -301,11 +319,6 @@ public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements I return material.getCraftBlockData(); } - @Override - public void notifyAndLightBlock(Location position, BlockState previousType) { - this.setBlock(position.getChunk(), position.getBlockX(), position.getBlockY(), position.getBlockZ(), previousType, true); - } - private MapChunkUtil_1_15_2 mapUtil = new MapChunkUtil_1_15_2(); @Override diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java index 695aeca79..a97372095 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java @@ -47,6 +47,8 @@ import com.sk89q.worldedit.entity.LazyBaseEntity; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.registry.state.Property; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.*; @@ -72,6 +74,7 @@ import java.io.File; import java.io.IOException; import java.util.Map; import java.util.OptionalInt; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -156,12 +159,27 @@ public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements I return state.toBaseBlock(); } + @Override + public boolean setBlock(Location location, BlockStateHolder state, SideEffectSet sideEffectSet) { + return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, sideEffectSet.shouldApply(SideEffect.LIGHTING)); + } + + @Override + public void applySideEffects(Location position, BlockState previousType, SideEffectSet sideEffectSet) { + return; //TODO: properly implement SideEffects into FAWE + } + + @Override + public Set getSupportedSideEffects() { + return SideEffectSet.defaults().getSideEffectsToApply(); + } + @Override public > boolean setBlock(Location location, B state, boolean notifyAndLight) { return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, notifyAndLight); } - public > boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, B state, boolean update) { + public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) { CraftChunk craftChunk = (CraftChunk) chunk; Chunk nmsChunk = craftChunk.getHandle(); World nmsWorld = nmsChunk.getWorld(); @@ -300,11 +318,6 @@ public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements I return material.getCraftBlockData(); } - @Override - public void notifyAndLightBlock(Location position, BlockState previousType) { - this.setBlock(position.getChunk(), position.getBlockX(), position.getBlockY(), position.getBlockZ(), previousType, true); - } - private MapChunkUtil_1_16_1 mapUtil = new MapChunkUtil_1_16_1(); @Override diff --git a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLIPlatform.java b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLIPlatform.java index c2e9eaba9..7dcfa2daf 100644 --- a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLIPlatform.java +++ b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/CLIPlatform.java @@ -19,10 +19,12 @@ package com.sk89q.worldedit.cli; +import com.google.common.collect.ImmutableSet; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.AbstractPlatform; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Preference; +import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.entity.EntityTypes; @@ -33,6 +35,7 @@ import java.util.ArrayList; import java.util.EnumMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.Timer; import java.util.TimerTask; @@ -153,6 +156,11 @@ class CLIPlatform extends AbstractPlatform { return capabilities; } + @Override + public Set getSupportedSideEffects() { + return ImmutableSet.of(); + } + public void addWorld(World world) { worlds.add(world); } 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 69d1cb1c9..6be24d545 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 @@ -19,6 +19,7 @@ package com.sk89q.worldedit.cli.schematic; +import com.google.common.collect.ImmutableSet; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; @@ -34,6 +35,8 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.biome.BiomeType; @@ -46,6 +49,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import java.util.Locale; +import java.util.Set; import javax.annotation.Nullable; @@ -74,15 +78,14 @@ public class ClipboardWorld extends AbstractWorld implements Clipboard, CLIWorld } @Override - public > boolean setBlock(BlockVector3 position, B block, boolean notifyAndLight) - throws WorldEditException { + public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { dirty = true; return clipboard.setBlock(position, block); } @Override - public boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException { - return false; + public Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) throws WorldEditException { + return ImmutableSet.of(); } @Override diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWorld.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWorld.java index a13cd75b6..6046c5928 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWorld.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWorld.java @@ -13,12 +13,16 @@ import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; import javax.annotation.Nullable; import java.io.File; +import java.util.Set; import static com.google.common.base.Preconditions.checkArgument; @@ -35,6 +39,11 @@ public class MCAWorld extends AbstractWorld { return path.getName(); } + @Override + public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { + return false; + } + @Override public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { @@ -46,6 +55,11 @@ public class MCAWorld extends AbstractWorld { return false; } + @Override + public Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) throws WorldEditException { + return SideEffectSet.none().getSideEffectsToApply(); + } + @Override public boolean clearContainerBlockContents(BlockVector3 position) { return false; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/HeightMapMCAGenerator.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/HeightMapMCAGenerator.java index 1e90346c4..b50bce169 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/HeightMapMCAGenerator.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/HeightMapMCAGenerator.java @@ -29,10 +29,7 @@ import com.boydti.fawe.util.TextureUtil; import com.boydti.fawe.util.image.Drawable; import com.boydti.fawe.util.image.ImageViewer; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.MaxChangedBlocksException; -import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.*; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extent.clipboard.Clipboard; @@ -48,9 +45,7 @@ import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.ClipboardHolder; -import com.sk89q.worldedit.util.Identifiable; -import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.TreeGenerator; +import com.sk89q.worldedit.util.*; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; @@ -68,6 +63,7 @@ import java.lang.reflect.Field; import java.nio.file.Path; import java.util.Arrays; import java.util.List; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; import java.util.function.Supplier; @@ -750,12 +746,24 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr return BlockVector3.at(getWidth() - 1, 255, getLength() - 1); } + @Override + public Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) + throws WorldEditException{ + return SideEffectSet.none().getSideEffectsToApply(); + } + @Override public > boolean setBlock(BlockVector3 position, B block) throws WorldEditException { return setBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ(), block); } + @Override + public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) + throws WorldEditException { + return setBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ(), block); + } + private boolean setBlock(int x, int y, int z, char combined) { int index = z * getWidth() + x; if (index < 0 || index >= getArea()) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java b/worldedit-core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java index 771262350..812b440dc 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java @@ -24,9 +24,7 @@ import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.Direction; -import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.TreeGenerator; +import com.sk89q.worldedit.util.*; import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; @@ -38,6 +36,7 @@ import com.sk89q.worldedit.world.weather.WeatherType; import javax.annotation.Nullable; import java.util.List; +import java.util.Set; public class WorldWrapper extends AbstractWorld { @@ -88,6 +87,12 @@ public class WorldWrapper extends AbstractWorld { return parent.useItem(position, item, face); } + @Override + public Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) + throws WorldEditException{ + return parent.applySideEffects(position, previousType, sideEffectSet); + } + @Override public > boolean setBlock(BlockVector3 position, B block, boolean notifyAndLight) throws WorldEditException { return parent.setBlock(position, block, notifyAndLight); @@ -99,6 +104,11 @@ public class WorldWrapper extends AbstractWorld { return parent.setBlock(x, y, z, block); } + @Override + public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { + return parent.setBlock(position, block, sideEffects); + } + @Override public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { return parent.setTile(x, y, z, tile); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index efc4eaa51..e3e38757c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -117,6 +117,7 @@ import com.sk89q.worldedit.regions.shape.RegionShape; import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment; import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.eventbus.EventBus; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; @@ -572,6 +573,20 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { disableHistory(enabled); } + /** + * Set which block updates should occur. + * + * @param sideEffectSet side effects to enable + */ + public void setSideEffectApplier(SideEffectSet sideEffectSet) { + //Do nothing; TODO: SideEffects currently not fully implemented in FAWE. + } + + public SideEffectSet getSideEffectApplier() { + //Do nothing; TODO: SideEffects currently not fully implemented in FAWE. + return SideEffectSet.defaults(); + } + /** * Disable history (or re-enable) * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index cc22a2972..eeb297713 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -72,6 +72,7 @@ import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.Identifiable; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -145,7 +146,7 @@ public class LocalSession implements TextureHolder { private transient Snapshot snapshotExperimental; private transient boolean hasCUISupport = false; private transient int cuiVersion = -1; - private transient boolean fastMode = false; + private transient SideEffectSet sideEffectSet = SideEffectSet.defaults(); private transient Mask mask; private transient Mask sourceMask; private transient TextureUtil texture; @@ -1494,7 +1495,7 @@ public class LocalSession implements TextureHolder { builder.blockBag(blockBag); } builder.command(command); - builder.fastmode(fastMode); + builder.fastmode(!this.sideEffectSet.doesApplyAny()); editSession = builder.build(); @@ -1513,7 +1514,7 @@ public class LocalSession implements TextureHolder { } private void prepareEditingExtents(EditSession editSession, Actor actor) { - editSession.setFastMode(fastMode); + editSession.setSideEffectApplier(sideEffectSet); editSession.setReorderMode(reorderMode); if (editSession.getSurvivalExtent() != null) { editSession.getSurvivalExtent().setStripNbt(!actor.hasPermission("worldedit.setnbt")); @@ -1521,13 +1522,32 @@ public class LocalSession implements TextureHolder { editSession.setTickingWatchdog(tickingWatchdog); } + /** + * Gets the side effect applier of this session. + * + * @return the side effect applier + */ + public SideEffectSet getSideEffectSet() { + return this.sideEffectSet; + } + + /** + * Sets the side effect applier for this session + * + * @param sideEffectSet the side effect applier + */ + public void setSideEffectSet(SideEffectSet sideEffectSet) { + this.sideEffectSet = sideEffectSet; + } + /** * Checks if the session has fast mode enabled. * * @return true if fast mode is enabled */ + @Deprecated public boolean hasFastMode() { - return fastMode; + return !this.sideEffectSet.doesApplyAny(); } /** @@ -1535,8 +1555,9 @@ public class LocalSession implements TextureHolder { * * @param fastMode true if fast mode is enabled */ + @Deprecated public void setFastMode(boolean fastMode) { - this.fastMode = fastMode; + this.sideEffectSet = fastMode ? SideEffectSet.none() : SideEffectSet.defaults(); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java index 91e6c76b4..923add56e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java @@ -49,10 +49,13 @@ import java.util.ArrayList; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.formatting.component.PaginationBox; +import com.sk89q.worldedit.util.formatting.component.SideEffectBox; +import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; -import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.item.ItemType; import java.io.FileNotFoundException; @@ -142,24 +145,62 @@ public class GeneralCommands { @Command( name = "/fast", - desc = "Toggle fast mode" + desc = "Toggle fast mode side effects" ) @CommandPermissions("worldedit.fast") public void fast(Actor actor, LocalSession session, - @Arg(desc = "The new fast mode state", def = "") - Boolean fastMode) { - boolean hasFastMode = session.hasFastMode(); - if (fastMode != null && fastMode == hasFastMode) { - actor.printError(TranslatableComponent.of(fastMode ? "worldedit.fast.enabled.already" : "worldedit.fast.disabled.already")); - return; + @Arg(desc = "The side effect", def = "") + SideEffect sideEffect, + @Arg(desc = "The new side effect state", def = "") + SideEffect.State newState, + @Switch(name = 'h', desc = "Show the info box") + boolean showInfoBox) throws WorldEditException { + if (sideEffect != null) { + SideEffect.State currentState = session.getSideEffectSet().getState(sideEffect); + if (newState != null && newState == currentState) { + if (!showInfoBox) { + actor.printError(TranslatableComponent.of( + "worldedit.fast.sideeffect.already-set", + TranslatableComponent.of(sideEffect.getDisplayName()), + TranslatableComponent.of(newState.getDisplayName()) + )); + } + return; + } + + if (newState != null) { + session.setSideEffectSet(session.getSideEffectSet().with(sideEffect, newState)); + if (!showInfoBox) { + actor.printInfo(TranslatableComponent.of( + "worldedit.fast.sideeffect.set", + TranslatableComponent.of(sideEffect.getDisplayName()), + TranslatableComponent.of(newState.getDisplayName()) + )); + } + } else { + actor.printInfo(TranslatableComponent.of( + "worldedit.fast.sideeffect.get", + TranslatableComponent.of(sideEffect.getDisplayName()), + TranslatableComponent.of(currentState.getDisplayName()) + )); + } + } else if (newState != null) { + SideEffectSet applier = session.getSideEffectSet(); + for (SideEffect sideEffectEntry : SideEffect.values()) { + applier = applier.with(sideEffectEntry, newState); + } + session.setSideEffectSet(applier); + if (!showInfoBox) { + actor.printInfo(TranslatableComponent.of( + "worldedit.fast.sideeffect.set-all", + TranslatableComponent.of(newState.getDisplayName()) + )); + } } - if (hasFastMode) { - session.setFastMode(false); - actor.printInfo(TranslatableComponent.of("worldedit.fast.disabled")); - } else { - session.setFastMode(true); - actor.printInfo(TranslatableComponent.of("worldedit.fast.enabled")); + if (sideEffect == null || showInfoBox) { + SideEffectBox sideEffectBox = new SideEffectBox(session.getSideEffectSet()); + actor.print(sideEffectBox.create(1)); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java index 7dc2192c7..f0f8e8ddd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java @@ -23,6 +23,7 @@ import com.boydti.fawe.object.brush.scroll.Scroll; import com.google.common.collect.ImmutableSet; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.command.util.HookMode; +import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.TreeGenerator; import org.enginehub.piston.CommandManager; import org.enginehub.piston.converter.ArgumentConverter; @@ -30,6 +31,7 @@ import org.enginehub.piston.converter.MultiKeyConverter; import org.enginehub.piston.inject.Key; import javax.annotation.Nullable; + import java.util.EnumSet; import java.util.Locale; import java.util.Set; @@ -48,6 +50,11 @@ public final class EnumConverter { full(EditSession.ReorderMode.class, r -> ImmutableSet.of(r.getDisplayName()), null)); + commandManager.registerConverter(Key.of(SideEffect.State.class), + MultiKeyConverter.from( + EnumSet.of(SideEffect.State.OFF, SideEffect.State.ON), + r -> ImmutableSet.of(r.name().toLowerCase(Locale.US)), + null)); commandManager.registerConverter(Key.of(HookMode.class), basic(HookMode.class)); commandManager.registerConverter(Key.of(Scroll.Action.class), diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/SideEffectConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/SideEffectConverter.java new file mode 100644 index 000000000..fd0ab684f --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/SideEffectConverter.java @@ -0,0 +1,75 @@ +/* + * 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.command.argument; + +import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix; + +import com.google.common.collect.ImmutableList; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.EntityRemover; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; + +import java.util.Collection; +import java.util.List; +import java.util.Locale; + +public class SideEffectConverter implements ArgumentConverter { + + public static void register(CommandManager commandManager) { + commandManager.registerConverter(Key.of(SideEffect.class), new SideEffectConverter()); + } + + private final TextComponent choices = TextComponent.of("any side effect"); + + private SideEffectConverter() { + } + + private Collection getSideEffects() { + return WorldEdit.getInstance().getPlatformManager().getSupportedSideEffects(); + } + + @Override + public Component describeAcceptableArguments() { + return choices; + } + + @Override + public List getSuggestions(String input, InjectedValueAccess context) { + return limitByPrefix(getSideEffects().stream().map(sideEffect -> sideEffect.name().toLowerCase(Locale.US)), input); + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess context) { + try { + return SuccessfulConversion.fromSingle(SideEffect.valueOf(argument.toUpperCase(Locale.US))); + } catch (Exception e) { + return FailedConversion.from(e); + } + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java index d82ed52c1..1f92543aa 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java @@ -21,14 +21,17 @@ package com.sk89q.worldedit.extension.platform; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.registry.Registries; import org.enginehub.piston.CommandManager; import javax.annotation.Nullable; + import java.util.List; import java.util.Map; +import java.util.Set; /** * Represents a platform that WorldEdit has been implemented for. @@ -174,4 +177,5 @@ public interface Platform { */ Map getCapabilities(); + Set getSupportedSideEffects(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java index 305c7f540..2b533f170 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java @@ -94,6 +94,7 @@ import com.sk89q.worldedit.command.argument.ExpressionConverter; import com.sk89q.worldedit.command.argument.FactoryConverter; import com.sk89q.worldedit.command.argument.RegionFactoryConverter; import com.sk89q.worldedit.command.argument.RegistryConverter; +import com.sk89q.worldedit.command.argument.SideEffectConverter; import com.sk89q.worldedit.command.argument.VectorConverter; import com.sk89q.worldedit.command.argument.WorldConverter; import com.sk89q.worldedit.command.argument.ZonedDateTimeConverter; @@ -255,6 +256,7 @@ public final class PlatformCommandManager { RegionFactoryConverter.register(commandManager); WorldConverter.register(commandManager); ExpressionConverter.register(commandManager); + SideEffectConverter.register(commandManager); registerBindings(new ConsumeBindings(worldEdit, this)); registerBindings(new PrimitiveBindings(worldEdit)); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index 9422a9abf..6ce088ac3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -48,9 +48,11 @@ import com.sk89q.worldedit.event.platform.PlayerInputEvent; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.eventbus.Subscribe; import com.sk89q.worldedit.world.World; import java.util.ArrayList; +import java.util.Collection; import java.util.EnumMap; import java.util.Iterator; import java.util.List; @@ -304,6 +306,10 @@ public class PlatformManager { return queryCapability(Capability.CONFIGURATION).getConfiguration(); } + public Collection getSupportedSideEffects() { + return queryCapability(Capability.WORLD_EDITING).getSupportedSideEffects(); + } + @Subscribe public void handlePlatformReady(PlatformReadyEvent event) { choosePreferred(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/buffer/ExtentBuffer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/buffer/ExtentBuffer.java index 4ae9a3ad5..699b73d43 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/buffer/ExtentBuffer.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/buffer/ExtentBuffer.java @@ -21,17 +21,16 @@ package com.sk89q.worldedit.extent.buffer; import static com.google.common.base.Preconditions.checkNotNull; -import com.google.common.collect.Maps; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.AbstractBufferingExtent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Masks; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.collection.BlockMap; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; import java.util.Map; -import java.util.Optional; /** * Buffers changes to an {@link Extent} and allows retrieval of the changed blocks, @@ -39,7 +38,7 @@ import java.util.Optional; */ public class ExtentBuffer extends AbstractBufferingExtent { - private final Map buffer = Maps.newHashMap(); + private final Map buffer = BlockMap.create(); private final Mask mask; /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java index 60cc68cf7..8b34e4778 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.extent.reorder; -import com.google.common.collect.ImmutableSortedSet; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.AbstractBufferingExtent; import com.sk89q.worldedit.extent.Extent; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SideEffectExtent.java similarity index 63% rename from worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SideEffectExtent.java index a29eff306..1a6b78505 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/FastModeExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SideEffectExtent.java @@ -27,67 +27,38 @@ import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.RunContext; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.util.collection.BlockMap; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockTypes; import java.util.HashSet; import java.util.Iterator; -import java.util.List; +import java.util.Map; import java.util.Set; /** - * Implements "fast mode" which may skip physics, lighting, etc. + * An extent that sets blocks in the world, with a {@link SideEffectSet}. */ -public class FastModeExtent extends AbstractDelegateExtent { +public class SideEffectExtent extends AbstractDelegateExtent { private final World world; - private final Set positions = new HashSet<>(); + private final Map positions = BlockMap.create(); private final Set dirtyChunks = new HashSet<>(); - private boolean enabled = true; + private SideEffectSet sideEffectSet = SideEffectSet.defaults(); private boolean postEditSimulation; - /** - * Create a new instance with fast mode enabled. - * - * @param world the world - */ - public FastModeExtent(World world) { - this(world, true); - } - /** * Create a new instance. * * @param world the world - * @param enabled true to enable fast mode */ - public FastModeExtent(World world, boolean enabled) { + public SideEffectExtent(World world) { super(world); checkNotNull(world); this.world = world; - this.enabled = enabled; - if (enabled) { - this.postEditSimulation = true; - } - } - - /** - * Return whether fast mode is enabled. - * - * @return true if fast mode is enabled - */ - public boolean isEnabled() { - return enabled; - } - - /** - * Set fast mode enable status. - * - * @param enabled true to enable fast mode - */ - public void setEnabled(boolean enabled) { - this.enabled = enabled; } public boolean isPostEditSimulationEnabled() { @@ -98,26 +69,28 @@ public class FastModeExtent extends AbstractDelegateExtent { this.postEditSimulation = enabled; } + public SideEffectSet getSideEffectSet() { + return this.sideEffectSet; + } + + public void setSideEffectSet(SideEffectSet sideEffectSet) { + this.sideEffectSet = sideEffectSet; + } + @Override public > boolean setBlock(BlockVector3 location, B block) throws WorldEditException { - if (enabled || postEditSimulation) { + if (sideEffectSet.getState(SideEffect.LIGHTING) == SideEffect.State.DELAYED) { dirtyChunks.add(BlockVector2.at(location.getBlockX() >> 4, location.getBlockZ() >> 4)); - - if (world.setBlock(location, block, false)) { - if (!enabled && postEditSimulation) { - positions.add(location); - } - return true; - } - - return false; - } else { - return world.setBlock(location, block, true); } + if (postEditSimulation) { + positions.put(location, world.getBlock(location)); + } + + return world.setBlock(location, block, postEditSimulation ? SideEffectSet.none() : sideEffectSet); } public boolean commitRequired() { - return enabled || postEditSimulation; + return postEditSimulation || !dirtyChunks.isEmpty(); } @Override @@ -132,11 +105,11 @@ public class FastModeExtent extends AbstractDelegateExtent { world.fixAfterFastMode(dirtyChunks); } - if (!enabled && postEditSimulation) { - Iterator positionIterator = positions.iterator(); + if (postEditSimulation) { + Iterator> positionIterator = positions.entrySet().iterator(); while (run.shouldContinue() && positionIterator.hasNext()) { - BlockVector3 position = positionIterator.next(); - world.notifyAndLightBlock(position, BlockTypes.AIR.getDefaultState()); + Map.Entry position = positionIterator.next(); + world.applySideEffects(position.getKey(), position.getValue(), sideEffectSet); positionIterator.remove(); } @@ -151,5 +124,4 @@ public class FastModeExtent extends AbstractDelegateExtent { } }; } - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffect.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffect.java new file mode 100644 index 000000000..c4c814fcb --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffect.java @@ -0,0 +1,68 @@ +/* + * 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.util; + +import java.util.Locale; + +public enum SideEffect { + LIGHTING(State.ON), + NEIGHBORS(State.ON), + CONNECTIONS(State.ON), + ENTITY_AI(State.OFF), + PLUGIN_EVENTS(State.OFF); + + private final String displayName; + private final String description; + private final State defaultValue; + + SideEffect(State defaultValue) { + this.displayName = "worldedit.sideeffect." + this.name().toLowerCase(Locale.US); + this.description = "worldedit.sideeffect." + this.name().toLowerCase(Locale.US) + ".description"; + this.defaultValue = defaultValue; + } + + public String getDisplayName() { + return this.displayName; + } + + public String getDescription() { + return this.description; + } + + public State getDefaultValue() { + return this.defaultValue; + } + + public enum State { + OFF, + ON, + DELAYED; + + private final String displayName; + + State() { + this.displayName = "worldedit.sideeffect.state." + this.name().toLowerCase(Locale.US); + } + + public String getDisplayName() { + return this.displayName; + } + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffectSet.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffectSet.java new file mode 100644 index 000000000..d88b37097 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffectSet.java @@ -0,0 +1,94 @@ +/* + * 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.util; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; + +import java.util.Arrays; +import java.util.EnumMap; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class SideEffectSet { + private static final SideEffectSet DEFAULT = new SideEffectSet( + Arrays.stream(SideEffect.values()).collect(Collectors.toMap(Function.identity(), SideEffect::getDefaultValue)) + ); + private static final SideEffectSet NONE = new SideEffectSet(); + + private final Map sideEffects; + private final Set appliedSideEffects; + private final boolean appliesAny; + + private SideEffectSet() { + this(ImmutableMap.of()); + } + + public SideEffectSet(Map sideEffects) { + this.sideEffects = Maps.immutableEnumMap(sideEffects); + + appliedSideEffects = sideEffects.entrySet() + .stream() + .filter(entry -> entry.getValue() != SideEffect.State.OFF) + .map(Map.Entry::getKey) + .collect(Collectors.toSet()); + appliesAny = !appliedSideEffects.isEmpty(); + } + + public SideEffectSet with(SideEffect sideEffect, SideEffect.State state) { + Map entries = this.sideEffects.isEmpty() ? Maps.newEnumMap(SideEffect.class) : new EnumMap<>(this.sideEffects); + entries.put(sideEffect, state); + return new SideEffectSet(entries); + } + + public boolean doesApplyAny() { + return this.appliesAny; + } + + public SideEffect.State getState(SideEffect effect) { + return sideEffects.getOrDefault(effect, effect.getDefaultValue()); + } + + /** + * Gets whether this side effect is not off. + * + * This returns whether it is either delayed or on. + * + * @param effect The side effect + * @return Whether it should apply + */ + public boolean shouldApply(SideEffect effect) { + return getState(effect) != SideEffect.State.OFF; + } + + public Set getSideEffectsToApply() { + return this.appliedSideEffects; + } + + public static SideEffectSet defaults() { + return DEFAULT; + } + + public static SideEffectSet none() { + return NONE; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/SideEffectBox.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/SideEffectBox.java new file mode 100644 index 000000000..14403313e --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/SideEffectBox.java @@ -0,0 +1,88 @@ +/* + * 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.util.formatting.component; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.event.ClickEvent; +import com.sk89q.worldedit.util.formatting.text.event.HoverEvent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; + +import java.util.Comparator; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; + +public class SideEffectBox extends PaginationBox { + + private static List sideEffects; + + private SideEffectSet sideEffectSet; + + private static List getSideEffects() { + if (sideEffects == null) { + sideEffects = WorldEdit.getInstance().getPlatformManager().getSupportedSideEffects() + .stream() + .sorted(Comparator.comparing(Enum::name)) + .collect(Collectors.toList()); + } + + return sideEffects; + } + + public SideEffectBox(SideEffectSet sideEffectSet) { + super("Side Effects"); + + this.sideEffectSet = sideEffectSet; + } + + private static final SideEffect.State[] SHOWN_VALUES = {SideEffect.State.OFF, SideEffect.State.ON}; + + @Override + public Component getComponent(int number) { + SideEffect effect = getSideEffects().get(number); + SideEffect.State state = this.sideEffectSet.getState(effect); + + TextComponent.Builder builder = TextComponent.builder(); + builder = builder.append(TranslatableComponent.of(effect.getDisplayName(), TextColor.YELLOW) + .hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TranslatableComponent.of(effect.getDescription())))); + for (SideEffect.State uiState : SHOWN_VALUES) { + builder = builder.append(TextComponent.space()); + builder = builder.append(TranslatableComponent.of(uiState.getDisplayName(), uiState == state ? TextColor.WHITE : TextColor.GRAY) + .clickEvent(ClickEvent.runCommand("//fast -h " + effect.name().toLowerCase(Locale.US) + " " + uiState.name().toLowerCase(Locale.US))) + .hoverEvent(HoverEvent.showText(uiState == state + ? TranslatableComponent.of("worldedit.sideeffect.box.current") + : TranslatableComponent.of("worldedit.sideeffect.box.change-to", TranslatableComponent.of(uiState.getDisplayName())) + )) + ); + } + + return builder.build(); + } + + @Override + public int getComponentsSize() { + return getSideEffects().size(); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/AbstractWorld.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/AbstractWorld.java index c333f1269..34e7179b0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/AbstractWorld.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/AbstractWorld.java @@ -32,6 +32,7 @@ import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.weather.WeatherType; import com.sk89q.worldedit.world.block.BlockType; @@ -57,7 +58,7 @@ public abstract class AbstractWorld implements World { @Override public final > boolean setBlock(BlockVector3 pt, B block) throws WorldEditException { - return setBlock(pt, block, true); + return setBlock(pt, block, SideEffectSet.defaults()); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java index f37665232..f3d6dd18a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java @@ -23,6 +23,7 @@ import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.implementation.packet.ChunkPacket; import com.boydti.fawe.beta.implementation.blocks.NullChunkGet; import com.sk89q.jnbt.CompoundTag; +import com.google.common.collect.ImmutableSet; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; @@ -35,6 +36,8 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.TreeGenerator.TreeType; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; @@ -48,6 +51,7 @@ import com.sk89q.worldedit.world.weather.WeatherTypes; import javax.annotation.Nullable; import java.util.Collections; import java.util.List; +import java.util.Set; /** * A null implementation of {@link World} that drops all changes and @@ -71,13 +75,14 @@ public class NullWorld extends AbstractWorld { } @Override - public > boolean setBlock(BlockVector3 position, B block, boolean notifyAndLight) throws WorldEditException { + public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { return false; } @Override - public boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException { - return false; + public Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) + throws WorldEditException { + return ImmutableSet.of(); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java index 5c6ba7df3..9388dcace 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/World.java @@ -37,15 +37,19 @@ import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.registry.Keyed; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.weather.WeatherType; -import javax.annotation.Nullable; import java.nio.file.Path; import java.util.Locale; +import java.util.Set; + +import javax.annotation.Nullable; /** * Represents a world (dimension). @@ -112,10 +116,28 @@ public interface World extends Extent, Keyed, IChunkCache { * @param notifyAndLight true to to notify and light * @return true if the block was successfully set (return value may not be accurate) */ + @Deprecated default > boolean setBlock(BlockVector3 position, B block, boolean notifyAndLight) throws WorldEditException { - return setBlock(position, block); + return setBlock(position, block, notifyAndLight ? SideEffectSet.defaults() : SideEffectSet.none()); } + /** + * Similar to {@link Extent#setBlock(BlockVector3, BlockStateHolder)} but a + * {@code sideEffects} parameter indicates which side effects should be applied + * to the block. This includes block updates, lighting, and others. See {@link SideEffect} + * for a full list. + * + *

Not all implementations support all side effects. Use + * {@link Platform#getSupportedSideEffects()} for a list of supported side effects. + * Non-supported side effects will be ignored.

+ * + * @param position position of the block + * @param block block to set + * @param sideEffects which side effects to perform + * @return true if the block was successfully set (return value may not be accurate) + */ + > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException; + /** * Notifies the simulation that the block at the given location has * been changed and it must be re-lighted (and issue other events). @@ -124,7 +146,20 @@ public interface World extends Extent, Keyed, IChunkCache { * @param previousType the type of the previous block that was there * @return true if the block was successfully notified */ - boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException; + @Deprecated + default boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException { + return !applySideEffects(position, previousType, SideEffectSet.defaults()).isEmpty(); + } + + /** + * Applies a set of side effects on the given block. + * + * @param position position of the block + * @param previousType the type of the previous block that was there + * @param sideEffectSet which side effects to perform + * @return a set of side effects that were applied + */ + Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) throws WorldEditException; /** * Get the light level at the given block. diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index fe79f060d..4708d4596 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -210,6 +210,10 @@ "worldedit.fast.enabled": "Fast mode enabled. Lighting in the affected chunks may be wrong and/or you may need to rejoin to see changes.", "worldedit.fast.disabled.already": "Fast mode already disabled.", "worldedit.fast.enabled.already": "Fast mode already enabled.", + "worldedit.fast.sideeffect.set": "Side effect \"{0}\" set to {1}", + "worldedit.fast.sideeffect.get": "Side effect \"{0}\" is set to {1}", + "worldedit.fast.sideeffect.already-set": "Side effect \"{0}\" is already {1}", + "worldedit.fast.sideeffect.set-all": "All side effects set to {0}", "worldedit.reorder.current": "The reorder mode is {0}", "worldedit.reorder.set": "The reorder mode is now {0}", "worldedit.gmask.disabled": "Global mask disabled.", @@ -494,6 +498,22 @@ "worldedit.selection.sphere.explain.secondary": "Radius set to {0}.", "worldedit.selection.sphere.explain.secondary-defined": "Radius set to {0} ({1}).", + "worldedit.sideeffect.lighting": "Lighting", + "worldedit.sideeffect.lighting.description": "Updates block lighting", + "worldedit.sideeffect.neighbors": "Neighbors", + "worldedit.sideeffect.neighbors.description": "Notifies nearby blocks of changes", + "worldedit.sideeffect.connections": "Connections", + "worldedit.sideeffect.connections.description": "Updates connections for blocks like fences", + "worldedit.sideeffect.entity_ai": "Entity AI", + "worldedit.sideeffect.entity_ai.description": "Updates Entity AI paths for the block changes", + "worldedit.sideeffect.plugin_events": "Plugin Events", + "worldedit.sideeffect.plugin_events.description": "Tells other plugins/mods about these changes when applicable", + "worldedit.sideeffect.state.on": "On", + "worldedit.sideeffect.state.delayed": "Delayed", + "worldedit.sideeffect.state.off": "Off", + "worldedit.sideeffect.box.current": "Current", + "worldedit.sideeffect.box.change-to": "Click to set to {0}", + "worldedit.help.command-not-found": "The command '{0}' could not be found.", "worldedit.help.no-subcommands": "'{0}' has no sub-commands. (Maybe '{1}' is for a parameter?)", "worldedit.help.subcommand-not-found": "The sub-command '{0}' under '{1}' could not be found.", diff --git a/worldedit-fabric/build.gradle.kts b/worldedit-fabric/build.gradle.kts index be85099fa..1cf6df8dd 100644 --- a/worldedit-fabric/build.gradle.kts +++ b/worldedit-fabric/build.gradle.kts @@ -61,16 +61,12 @@ tasks.named("processResources") { } } -<<<<<<< HEAD -addJarManifest(includeClasspath = true) -======= tasks.named("jar") { manifest { attributes("Class-Path" to CLASSPATH, "WorldEdit-Version" to project.version) } } ->>>>>>> 18a55bc14... Add new experimental snapshot API (#524) tasks.named("shadowJar") { archiveClassifier.set("dist-dev") diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java index beb6d5208..7fb18b0e7 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.fabric; +import com.google.common.collect.Sets; import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.AbstractPlatform; @@ -27,13 +28,13 @@ import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.MultiUserPlatform; import com.sk89q.worldedit.extension.platform.Preference; import com.sk89q.worldedit.extension.platform.Watchdog; +import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.registry.Registries; import net.minecraft.SharedConstants; import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerManager; -import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.dedicated.MinecraftDedicatedServer; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; @@ -200,6 +201,18 @@ class FabricPlatform extends AbstractPlatform implements MultiUserPlatform { return capabilities; } + private static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( + SideEffect.CONNECTIONS, + SideEffect.ENTITY_AI, + SideEffect.LIGHTING, + SideEffect.NEIGHBORS + ); + + @Override + public Set getSupportedSideEffects() { + return SUPPORTED_SIDE_EFFECTS; + } + @Override public Collection getConnectedUsers() { List users = new ArrayList<>(); diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java index 886523df5..e085d2326 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java @@ -24,6 +24,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; +import com.google.common.collect.Sets; import com.google.common.io.Files; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; @@ -42,6 +43,8 @@ import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.TreeGenerator.TreeType; import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.biome.BiomeType; @@ -61,6 +64,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUsageContext; import net.minecraft.server.MinecraftServer; import net.minecraft.server.WorldGenerationProgressListener; +import net.minecraft.server.world.ChunkHolder; import net.minecraft.server.world.ServerChunkManager; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.ActionResult; @@ -71,6 +75,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; import net.minecraft.world.WorldSaveHandler; +import net.minecraft.world.biome.DefaultBiomeFeatures; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.ChunkManager; import net.minecraft.world.chunk.ChunkStatus; @@ -104,6 +109,7 @@ import java.util.Locale; import java.util.Optional; import java.util.OptionalInt; import java.util.Random; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; @@ -185,8 +191,44 @@ public class FabricWorld extends AbstractWorld { return null; } + public void markAndNotifyBlock(World world, BlockPos pos, @Nullable WorldChunk worldChunk, net.minecraft.block.BlockState blockState, + net.minecraft.block.BlockState state, SideEffectSet sideEffectSet) { + Block block = state.getBlock(); + net.minecraft.block.BlockState blockState2 = world.getBlockState(pos); + if (blockState2 == state) { + if (blockState != blockState2) { + world.checkBlockRerender(pos, blockState, blockState2); + } + + if (world.isClient || worldChunk.getLevelType() != null && worldChunk.getLevelType().isAfter(ChunkHolder.LevelType.TICKING)) { + if (sideEffectSet.shouldApply(SideEffect.ENTITY_AI)) { + world.updateListeners(pos, blockState, state, UPDATE | NOTIFY); + } else { + // If we want to skip entity AI, just call the chunk dirty flag. + ((ServerChunkManager) world.getChunkManager()).markForUpdate(pos); + } + } + + if (!world.isClient && sideEffectSet.shouldApply(SideEffect.NEIGHBORS)) { + world.updateNeighbors(pos, blockState.getBlock()); + if (state.hasComparatorOutput()) { + world.updateHorizontalAdjacent(pos, block); + } + } + + if (sideEffectSet.shouldApply(SideEffect.CONNECTIONS)) { + blockState.method_11637(world, pos, 2); + state.updateNeighborStates(world, pos, 2); + state.method_11637(world, pos, 2); + } + + // This is disabled for other platforms, but keep it for mods. + world.onBlockChanged(pos, blockState, blockState2); + } + } + @Override - public > boolean setBlock(BlockVector3 position, B block, boolean notifyAndLight) throws WorldEditException { + public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { checkNotNull(position); checkNotNull(block); @@ -196,7 +238,7 @@ public class FabricWorld extends AbstractWorld { int z = position.getBlockZ(); // First set the block - Chunk chunk = world.getChunk(x >> 4, z >> 4); + WorldChunk chunk = world.getChunk(x >> 4, z >> 4); BlockPos pos = new BlockPos(x, y, z); net.minecraft.block.BlockState old = chunk.getBlockState(pos); OptionalInt stateId = BlockStateIdAccess.getBlockStateId(block.toImmutableState()); @@ -221,26 +263,27 @@ public class FabricWorld extends AbstractWorld { } } - if (successful && notifyAndLight) { - world.getChunkManager().getLightingProvider().enqueueLightUpdate(pos); - world.scheduleBlockRender(pos, old, newState); - world.updateListeners(pos, old, newState, UPDATE | NOTIFY); - world.updateNeighbors(pos, newState.getBlock()); - if (old.hasComparatorOutput()) { - world.updateHorizontalAdjacent(pos, newState.getBlock()); + if (successful) { + if (sideEffects.getState(SideEffect.LIGHTING) == SideEffect.State.ON) { + world.getChunkManager().getLightingProvider().checkBlock(pos); } + markAndNotifyBlock(world, pos, chunk, old, newState, sideEffects); } return successful; } @Override - public boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException { + public Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) throws WorldEditException { BlockPos pos = new BlockPos(position.getX(), position.getY(), position.getZ()); - net.minecraft.block.BlockState state = getWorld().getBlockState(pos); - getWorld().updateListeners(pos, FabricAdapter.adapt(previousType), state, 1 | 2); - getWorld().updateNeighbors(pos, state.getBlock()); - return true; + net.minecraft.block.BlockState oldData = FabricAdapter.adapt(previousType); + net.minecraft.block.BlockState newData = getWorld().getBlockState(pos); + + if (sideEffectSet.getState(SideEffect.LIGHTING) == SideEffect.State.ON) { + getWorld().getChunkManager().getLightingProvider().checkBlock(pos); + } + markAndNotifyBlock(getWorld(), pos, null, oldData, newData, sideEffectSet); // Update + return Sets.intersection(FabricWorldEdit.inst.getPlatform().getSupportedSideEffects(), sideEffectSet.getSideEffectsToApply()); } @Override diff --git a/worldedit-forge/build.gradle.kts b/worldedit-forge/build.gradle.kts index 23d52162d..f3b938ca7 100644 --- a/worldedit-forge/build.gradle.kts +++ b/worldedit-forge/build.gradle.kts @@ -77,7 +77,12 @@ tasks.named("processResources") { } } -addJarManifest(includeClasspath = false) +tasks.named("jar") { + manifest { + attributes("Class-Path" to CLASSPATH, + "WorldEdit-Version" to project.version) + } +} tasks.named("shadowJar") { dependencies { diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java index e1af09064..b844425eb 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.MultiUserPlatform; import com.sk89q.worldedit.extension.platform.Preference; +import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.registry.Registries; @@ -206,6 +207,18 @@ class ForgePlatform extends AbstractPlatform implements MultiUserPlatform { return capabilities; } + private static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( + SideEffect.CONNECTIONS, + SideEffect.ENTITY_AI, + SideEffect.LIGHTING, + SideEffect.NEIGHBORS + ); + + @Override + public Set getSupportedSideEffects() { + return SUPPORTED_SIDE_EFFECTS; + } + @Override public Collection getConnectedUsers() { List users = new ArrayList<>(); diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java index f9096578b..5d69754a6 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -19,6 +19,8 @@ package com.sk89q.worldedit.forge; +import static com.google.common.base.Preconditions.checkNotNull; + import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -96,13 +98,13 @@ import net.minecraft.world.gen.feature.SwampTreeFeature; import net.minecraft.world.gen.feature.TallTaigaTreeFeature; import net.minecraft.world.gen.feature.TreeFeature; +import net.minecraft.world.server.ChunkHolder; import net.minecraft.world.server.ServerChunkProvider; import net.minecraft.world.server.ServerWorld; import net.minecraft.world.storage.SaveHandler; import net.minecraft.world.storage.WorldInfo; import net.minecraftforge.common.DimensionManager; -import javax.annotation.Nullable; import java.io.File; import java.io.IOException; import java.lang.ref.WeakReference; @@ -117,7 +119,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; -import static com.google.common.base.Preconditions.checkNotNull; +import javax.annotation.Nullable; /** * An adapter to Minecraft worlds for WorldEdit. @@ -130,7 +132,7 @@ public class ForgeWorld extends AbstractWorld { private static final net.minecraft.block.BlockState JUNGLE_LOG = Blocks.JUNGLE_LOG.getDefaultState(); private static final net.minecraft.block.BlockState JUNGLE_LEAF = Blocks.JUNGLE_LEAVES.getDefaultState().with(LeavesBlock.PERSISTENT, Boolean.TRUE); private static final net.minecraft.block.BlockState JUNGLE_SHRUB = Blocks.OAK_LEAVES.getDefaultState().with(LeavesBlock.PERSISTENT, Boolean.TRUE); - + private final WeakReference worldRef; /** @@ -192,8 +194,51 @@ public class ForgeWorld extends AbstractWorld { return null; } + /** + * This is a heavily modified function stripped from MC to apply worldedit-modifications. + * + * @see World#markAndNotifyBlock + */ + public void markAndNotifyBlock(World world, BlockPos pos, @Nullable Chunk chunk, net.minecraft.block.BlockState blockstate, + net.minecraft.block.BlockState newState, SideEffectSet sideEffectSet) { + Block block = newState.getBlock(); + net.minecraft.block.BlockState blockstate1 = world.getBlockState(pos); + if (blockstate1 == newState) { + if (blockstate != blockstate1) { + world.markBlockRangeForRenderUpdate(pos, blockstate, blockstate1); + } + + // Remove redundant branches + if (world.isRemote || chunk == null || chunk.getLocationType().isAtLeast(ChunkHolder.LocationType.TICKING)) { + if (sideEffectSet.shouldApply(SideEffect.ENTITY_AI)) { + world.notifyBlockUpdate(pos, blockstate, newState, UPDATE | NOTIFY); + } else { + // If we want to skip entity AI, just call the chunk dirty flag. + ((ServerChunkProvider) world.getChunkProvider()).markBlockChanged(pos); + } + } + + if (!world.isRemote && sideEffectSet.shouldApply(SideEffect.NEIGHBORS)) { + world.notifyNeighbors(pos, blockstate.getBlock()); + if (newState.hasComparatorInputOverride()) { + world.updateComparatorOutputLevel(pos, block); + } + } + + // Make connection updates optional + if (sideEffectSet.shouldApply(SideEffect.CONNECTIONS)) { + blockstate.updateDiagonalNeighbors(world, pos, 2); + newState.updateNeighbors(world, pos, 2); + newState.updateDiagonalNeighbors(world, pos, 2); + } + + // This is disabled for other platforms, but keep it for mods. + world.onBlockStateChange(pos, blockstate, blockstate1); + } + } + @Override - public > boolean setBlock(BlockVector3 position, B block, boolean notifyAndLight) throws WorldEditException { + public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { checkNotNull(position); checkNotNull(block); @@ -224,19 +269,27 @@ public class ForgeWorld extends AbstractWorld { } } - if (successful && notifyAndLight) { - world.getChunkProvider().getLightManager().checkBlock(pos); - world.markAndNotifyBlock(pos, chunk, old, newState, UPDATE | NOTIFY); + if (successful) { + if (sideEffects.getState(SideEffect.LIGHTING) == SideEffect.State.ON) { + world.getChunkProvider().getLightManager().checkBlock(pos); + } + markAndNotifyBlock(world, pos, chunk, old, newState, sideEffects); } return successful; } @Override - public boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException { + public Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) throws WorldEditException { BlockPos pos = new BlockPos(position.getX(), position.getY(), position.getZ()); - getWorld().notifyBlockUpdate(pos, ForgeAdapter.adapt(previousType), getWorld().getBlockState(pos), 1 | 2); - return true; + net.minecraft.block.BlockState oldData = ForgeAdapter.adapt(previousType); + net.minecraft.block.BlockState newData = getWorld().getBlockState(pos); + + if (sideEffectSet.getState(SideEffect.LIGHTING) == SideEffect.State.ON) { + getWorld().getChunkProvider().getLightManager().checkBlock(pos); + } + markAndNotifyBlock(getWorld(), pos, null, oldData, newData, sideEffectSet); // Update + return Sets.intersection(ForgeWorldEdit.inst.getPlatform().getSupportedSideEffects(), sideEffectSet.getSideEffectsToApply()); } @Override diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java index 33849e915..ddfaad17b 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java @@ -20,6 +20,8 @@ package com.sk89q.worldedit.sponge; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.event.platform.CommandEvent; @@ -31,6 +33,7 @@ import com.sk89q.worldedit.extension.platform.MultiUserPlatform; import com.sk89q.worldedit.extension.platform.Preference; import com.sk89q.worldedit.internal.command.CommandUtil; import com.sk89q.worldedit.sponge.config.SpongeConfiguration; +import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.registry.Registries; import org.enginehub.piston.Command; @@ -50,6 +53,7 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import static java.util.stream.Collectors.toList; @@ -192,6 +196,11 @@ class SpongePlatform extends AbstractPlatform implements MultiUserPlatform { return capabilities; } + @Override + public Set getSupportedSideEffects() { + return ImmutableSet.of(); + } + @Override public Collection getConnectedUsers() { List users = new ArrayList<>(); From d232dc28e3f2ce091450745eb7827c57bd7bce5b Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Sun, 22 Mar 2020 21:02:04 -0700 Subject: [PATCH 04/18] Cherry-pick WNA, minor changes. 1.16 VERY WIP First noticed incident of operations ruining ChunkSections. Do not build and use this unless you're testing. Rushed some of the changes, gotta sleep. Would be nice to get a review of this one from @mattbdev and @dordsor21 --- .../mc1_14/FAWEWorldNativeAccess_1_14.java | 176 +++++++++++++++++ .../FAWEWorldNativeAccess_1_15_2.java | 173 ++++++++++++++++ .../mc1_16_1/BlockMaterial_1_16_1.java | 2 +- .../mc1_16_1/FAWEWorldNativeAccess_1_16.java | 174 +++++++++++++++++ .../fawe/bukkit/wrapper/AsyncWorld.java | 28 ++- .../wrapper/state/AsyncDataContainer.java | 22 ++- .../sk89q/worldedit/bukkit/BukkitWorld.java | 50 ++--- .../bukkit/adapter/BukkitImplAdapter.java | 22 +-- .../adapter/IDelegateBukkitImplAdapter.java | 4 - .../adapter/impl/FAWE_Spigot_v1_14_R4.java | 29 +-- .../adapter/impl/FAWE_Spigot_v1_15_R2.java | 28 +-- .../adapter/impl/FAWE_Spigot_v1_16_R1.java | 28 +-- .../internal/wna/WorldNativeAccess.java | 184 ++++++++++++++++++ .../worldedit/internal/wna/package-info.java | 25 +++ .../com/sk89q/worldedit/util/SideEffect.java | 4 +- .../src/main/resources/lang/strings.json | 8 +- worldedit-fabric/build.gradle.kts | 4 +- .../sk89q/worldedit/fabric/FabricAdapter.java | 1 + .../worldedit/fabric/FabricDataFixer.java | 7 +- .../sk89q/worldedit/fabric/FabricEntity.java | 1 + .../worldedit/fabric/FabricPlatform.java | 2 +- .../sk89q/worldedit/fabric/FabricPlayer.java | 7 +- .../sk89q/worldedit/fabric/FabricWorld.java | 93 +-------- .../internal/FabricWorldNativeAccess.java | 139 +++++++++++++ .../fabric/{ => internal}/NBTConverter.java | 4 +- .../net/handler/WECUIPacketHandler.java | 8 +- .../sk89q/worldedit/forge/ForgeEntity.java | 1 + .../sk89q/worldedit/forge/ForgePlatform.java | 2 +- .../com/sk89q/worldedit/forge/ForgeWorld.java | 102 +--------- .../internal/ForgeWorldNativeAccess.java | 152 +++++++++++++++ .../forge/internal/TileEntityUtils.java | 35 +--- 31 files changed, 1170 insertions(+), 345 deletions(-) create mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/FAWEWorldNativeAccess_1_14.java create mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/FAWEWorldNativeAccess_1_15_2.java create mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/FAWEWorldNativeAccess_1_16.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/WorldNativeAccess.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/package-info.java create mode 100644 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java rename worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/{ => internal}/NBTConverter.java (99%) create mode 100644 worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/ForgeWorldNativeAccess.java diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/FAWEWorldNativeAccess_1_14.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/FAWEWorldNativeAccess_1_14.java new file mode 100644 index 000000000..9bcfc1ddd --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/FAWEWorldNativeAccess_1_14.java @@ -0,0 +1,176 @@ +package com.boydti.fawe.bukkit.adapter.mc1_14; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.adapter.impl.FAWE_Spigot_v1_14_R4; +import com.sk89q.worldedit.internal.block.BlockStateIdAccess; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import net.minecraft.server.v1_14_R1.Block; +import net.minecraft.server.v1_14_R1.BlockPosition; +import net.minecraft.server.v1_14_R1.Chunk; +import net.minecraft.server.v1_14_R1.ChunkProviderServer; +import net.minecraft.server.v1_14_R1.EnumDirection; +import net.minecraft.server.v1_14_R1.IBlockData; +import net.minecraft.server.v1_14_R1.NBTBase; +import net.minecraft.server.v1_14_R1.NBTTagCompound; +import net.minecraft.server.v1_14_R1.PlayerChunk; +import net.minecraft.server.v1_14_R1.TileEntity; +import net.minecraft.server.v1_14_R1.World; +import org.bukkit.craftbukkit.v1_14_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_14_R1.block.data.CraftBlockData; +import org.bukkit.event.block.BlockPhysicsEvent; + +import javax.annotation.Nullable; +import java.lang.ref.WeakReference; +import java.util.Objects; + +public class FAWEWorldNativeAccess_1_14 implements WorldNativeAccess { + private static final int UPDATE = 1, NOTIFY = 2; + + private final FAWE_Spigot_v1_14_R4 adapter; + private final WeakReference world; + private SideEffectSet sideEffectSet; + + public FAWEWorldNativeAccess_1_14(FAWE_Spigot_v1_14_R4 adapter, WeakReference world) { + this.adapter = adapter; + this.world = world; + } + + private World getWorld() { + return Objects.requireNonNull(world.get(), "The reference to the world was lost"); + } + + @Override + public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { + this.sideEffectSet = sideEffectSet; + } + + @Override + public Chunk getChunk(int x, int z) { + return getWorld().getChunkAt(x, z); + } + + @Override + public IBlockData toNative(com.sk89q.worldedit.world.block.BlockState state) { + int stateId = BlockStateIdAccess.getBlockStateId(state); + return BlockStateIdAccess.isValidInternalId(stateId) + ? Block.getByCombinedId(stateId) + : ((CraftBlockData) BukkitAdapter.adapt(state)).getState(); + } + + @Override + public IBlockData getBlockState(Chunk chunk, BlockPosition position) { + return chunk.getType(position); + } + + @Nullable + @Override + public IBlockData setBlockState(Chunk chunk, BlockPosition position, IBlockData state) { + return chunk.setType(position, state, false); + } + + @Override + public IBlockData getValidBlockForPosition(IBlockData block, BlockPosition position) { + return Block.b(block, getWorld(), position); + } + + @Override + public BlockPosition getPosition(int x, int y, int z) { + return new BlockPosition(x, y, z); + } + + @Override + public void updateLightingForBlock(BlockPosition position) { + getWorld().getChunkProvider().getLightEngine().a(position); + } + + @Override + public boolean updateTileEntity(BlockPosition position, CompoundTag tag) { + // We will assume that the tile entity was created for us, + // though we do not do this on the other versions + TileEntity tileEntity = getWorld().getTileEntity(position); + if (tileEntity == null) { + return false; + } + NBTBase nativeTag = adapter.fromNative(tag); + tileEntity.load((NBTTagCompound) nativeTag); + return true; + } + + @Override + public void notifyBlockUpdate(BlockPosition position, IBlockData oldState, IBlockData newState) { + getWorld().notify(position, oldState, newState, UPDATE | NOTIFY); + } + + @Override + public boolean isChunkTicking(Chunk chunk) { + return chunk.getState().isAtLeast(PlayerChunk.State.TICKING); + } + + @Override + public void markBlockChanged(BlockPosition position) { + ((ChunkProviderServer) getWorld().getChunkProvider()).flagDirty(position); + } + + private static final EnumDirection[] NEIGHBOUR_ORDER = { + EnumDirection.WEST, EnumDirection.EAST, + EnumDirection.DOWN, EnumDirection.UP, + EnumDirection.NORTH, EnumDirection.SOUTH + }; + + @Override + public void notifyNeighbors(BlockPosition pos, IBlockData oldState, IBlockData newState) { + World world = getWorld(); + if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { + world.update(pos, oldState.getBlock()); + } else { + // When we don't want events, manually run the physics without them. + // Un-nest neighbour updating + for (EnumDirection direction : NEIGHBOUR_ORDER) { + BlockPosition shifted = pos.shift(direction); + world.getType(shifted).doPhysics(world, shifted, oldState.getBlock(), pos, false); + } + } + if (newState.isComplexRedstone()) { + world.updateAdjacentComparators(pos, newState.getBlock()); + } + } + + @Override + public void updateNeighbors(BlockPosition pos, IBlockData oldState, IBlockData newState, int recursionLimit) { + World world = getWorld(); + // a == updateNeighbors + // b == updateDiagonalNeighbors + oldState.b(world, pos, NOTIFY); + if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { + CraftWorld craftWorld = world.getWorld(); + if (craftWorld != null) { + BlockPhysicsEvent event = new BlockPhysicsEvent( + craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), + CraftBlockData.fromData(newState)); + world.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + } + } + newState.a(world, pos, NOTIFY); + newState.b(world, pos, NOTIFY); + } + + @Override + public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) { + getWorld().a(pos, oldState, newState); + } + + + @Override + public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { + return this.adapter.setBlock(this.getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4).bukkitChunk, position.getBlockX(), position.getBlockY(), position.getBlockZ(), block, sideEffectSet.shouldApply(SideEffect.LIGHTING)); + } +} \ No newline at end of file diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/FAWEWorldNativeAccess_1_15_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/FAWEWorldNativeAccess_1_15_2.java new file mode 100644 index 000000000..9ce24d789 --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/FAWEWorldNativeAccess_1_15_2.java @@ -0,0 +1,173 @@ +package com.boydti.fawe.bukkit.adapter.mc1_15_2; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.adapter.impl.FAWE_Spigot_v1_15_R2; +import com.sk89q.worldedit.internal.block.BlockStateIdAccess; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import net.minecraft.server.v1_15_R1.Block; +import net.minecraft.server.v1_15_R1.BlockPosition; +import net.minecraft.server.v1_15_R1.Chunk; +import net.minecraft.server.v1_15_R1.ChunkProviderServer; +import net.minecraft.server.v1_15_R1.EnumDirection; +import net.minecraft.server.v1_15_R1.IBlockData; +import net.minecraft.server.v1_15_R1.NBTBase; +import net.minecraft.server.v1_15_R1.NBTTagCompound; +import net.minecraft.server.v1_15_R1.PlayerChunk; +import net.minecraft.server.v1_15_R1.TileEntity; +import net.minecraft.server.v1_15_R1.World; +import org.bukkit.craftbukkit.v1_15_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_15_R1.block.data.CraftBlockData; +import org.bukkit.event.block.BlockPhysicsEvent; + +import javax.annotation.Nullable; +import java.lang.ref.WeakReference; +import java.util.Objects; + +public class FAWEWorldNativeAccess_1_15_2 implements WorldNativeAccess { + private static final int UPDATE = 1, NOTIFY = 2; + + private final FAWE_Spigot_v1_15_R2 adapter; + private final WeakReference world; + private SideEffectSet sideEffectSet; + + public FAWEWorldNativeAccess_1_15_2(FAWE_Spigot_v1_15_R2 adapter, WeakReference world) { + this.adapter = adapter; + this.world = world; + } + + private World getWorld() { + return Objects.requireNonNull(world.get(), "The reference to the world was lost"); + } + + @Override + public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { + this.sideEffectSet = sideEffectSet; + } + + @Override + public Chunk getChunk(int x, int z) { + return getWorld().getChunkAt(x, z); + } + + @Override + public IBlockData toNative(com.sk89q.worldedit.world.block.BlockState state) { + int stateId = BlockStateIdAccess.getBlockStateId(state); + return BlockStateIdAccess.isValidInternalId(stateId) + ? Block.getByCombinedId(stateId) + : ((CraftBlockData) BukkitAdapter.adapt(state)).getState(); + } + + @Override + public IBlockData getBlockState(Chunk chunk, BlockPosition position) { + return chunk.getType(position); + } + + @Nullable + @Override + public IBlockData setBlockState(Chunk chunk, BlockPosition position, IBlockData state) { + return chunk.setType(position, state, false); + } + + @Override + public IBlockData getValidBlockForPosition(IBlockData block, BlockPosition position) { + return Block.b(block, getWorld(), position); + } + + @Override + public BlockPosition getPosition(int x, int y, int z) { + return new BlockPosition(x, y, z); + } + + @Override + public void updateLightingForBlock(BlockPosition position) { + getWorld().getChunkProvider().getLightEngine().a(position); + } + + @Override + public boolean updateTileEntity(BlockPosition position, CompoundTag tag) { + // We will assume that the tile entity was created for us, + // though we do not do this on the other versions + TileEntity tileEntity = getWorld().getTileEntity(position); + if (tileEntity == null) { + return false; + } + NBTBase nativeTag = adapter.fromNative(tag); + tileEntity.load((NBTTagCompound) nativeTag); + return true; + } + + @Override + public void notifyBlockUpdate(BlockPosition position, IBlockData oldState, IBlockData newState) { + getWorld().notify(position, oldState, newState, UPDATE | NOTIFY); + } + + @Override + public boolean isChunkTicking(Chunk chunk) { + return chunk.getState().isAtLeast(PlayerChunk.State.TICKING); + } + + @Override + public void markBlockChanged(BlockPosition position) { + ((ChunkProviderServer) getWorld().getChunkProvider()).flagDirty(position); + } + + private static final EnumDirection[] NEIGHBOUR_ORDER = { + EnumDirection.WEST, EnumDirection.EAST, + EnumDirection.DOWN, EnumDirection.UP, + EnumDirection.NORTH, EnumDirection.SOUTH + }; + + @Override + public void notifyNeighbors(BlockPosition pos, IBlockData oldState, IBlockData newState) { + World world = getWorld(); + if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { + world.update(pos, oldState.getBlock()); + } else { + // When we don't want events, manually run the physics without them. + // Un-nest neighbour updating + for (EnumDirection direction : NEIGHBOUR_ORDER) { + BlockPosition shifted = pos.shift(direction); + world.getType(shifted).doPhysics(world, shifted, oldState.getBlock(), pos, false); + } + } + if (newState.isComplexRedstone()) { + world.updateAdjacentComparators(pos, newState.getBlock()); + } + } + + @Override + public void updateNeighbors(BlockPosition pos, IBlockData oldState, IBlockData newState, int recursionLimit) { + World world = getWorld(); + // a == updateNeighbors + // b == updateDiagonalNeighbors + oldState.b(world, pos, NOTIFY); + if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { + CraftWorld craftWorld = world.getWorld(); + if (craftWorld != null) { + BlockPhysicsEvent event = new BlockPhysicsEvent(craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), CraftBlockData.fromData(newState)); + world.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + } + } + newState.a(world, pos, NOTIFY); + newState.b(world, pos, NOTIFY); + } + + @Override + public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) { + getWorld().a(pos, oldState, newState); + } + + @Override + public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { + return this.adapter.setBlock(this.getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4).bukkitChunk, position.getBlockX(), position.getBlockY(), position.getBlockZ(), block, sideEffectSet.shouldApply(SideEffect.LIGHTING)); + } +} \ No newline at end of file diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BlockMaterial_1_16_1.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BlockMaterial_1_16_1.java index ef492dbdd..dfa348a78 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BlockMaterial_1_16_1.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BlockMaterial_1_16_1.java @@ -23,7 +23,7 @@ public class BlockMaterial_1_16_1 implements BlockMaterial { this.material = defaultState.getMaterial(); this.craftBlockData = CraftBlockData.fromData(defaultState); this.craftMaterial = craftBlockData.getMaterial(); - this.isTranslucent = !(boolean) ReflectionUtil.getField(Block.class, block, "v"); //TODO Update Mapping for 1.16.1 + this.isTranslucent = !(boolean) ReflectionUtil.getField(Block.class, block, "at"); //TODO Update Mapping for 1.16.1 } public Block getBlock() { diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/FAWEWorldNativeAccess_1_16.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/FAWEWorldNativeAccess_1_16.java new file mode 100644 index 000000000..6b68ae95d --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/FAWEWorldNativeAccess_1_16.java @@ -0,0 +1,174 @@ +package com.boydti.fawe.bukkit.adapter.mc1_16_1; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.adapter.impl.FAWE_Spigot_v1_16_R1; +import com.sk89q.worldedit.internal.block.BlockStateIdAccess; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import net.minecraft.server.v1_16_R1.Block; +import net.minecraft.server.v1_16_R1.BlockPosition; +import net.minecraft.server.v1_16_R1.Chunk; +import net.minecraft.server.v1_16_R1.ChunkProviderServer; +import net.minecraft.server.v1_16_R1.EnumDirection; +import net.minecraft.server.v1_16_R1.IBlockData; +import net.minecraft.server.v1_16_R1.NBTBase; +import net.minecraft.server.v1_16_R1.NBTTagCompound; +import net.minecraft.server.v1_16_R1.PlayerChunk; +import net.minecraft.server.v1_16_R1.TileEntity; +import net.minecraft.server.v1_16_R1.World; +import org.bukkit.craftbukkit.v1_16_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_16_R1.block.data.CraftBlockData; +import org.bukkit.event.block.BlockPhysicsEvent; + +import javax.annotation.Nullable; +import java.lang.ref.WeakReference; +import java.util.Objects; + +public class FAWEWorldNativeAccess_1_16 implements WorldNativeAccess { + private static final int UPDATE = 1, NOTIFY = 2; + + private final FAWE_Spigot_v1_16_R1 adapter; + private final WeakReference world; + private SideEffectSet sideEffectSet; + + public FAWEWorldNativeAccess_1_16(FAWE_Spigot_v1_16_R1 adapter, WeakReference world) { + this.adapter = adapter; + this.world = world; + } + + private World getWorld() { + return Objects.requireNonNull(world.get(), "The reference to the world was lost"); + } + + @Override + public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { + this.sideEffectSet = sideEffectSet; + } + + @Override + public Chunk getChunk(int x, int z) { + return getWorld().getChunkAt(x, z); + } + + @Override + public IBlockData toNative(BlockState state) { + int stateId = BlockStateIdAccess.getBlockStateId(state); + return BlockStateIdAccess.isValidInternalId(stateId) + ? Block.getByCombinedId(stateId) + : ((CraftBlockData) BukkitAdapter.adapt(state)).getState(); + } + + @Override + public IBlockData getBlockState(Chunk chunk, BlockPosition position) { + return chunk.getType(position); + } + + @Nullable + @Override + public IBlockData setBlockState(Chunk chunk, BlockPosition position, IBlockData state) { + return chunk.setType(position, state, false); + } + + @Override + public IBlockData getValidBlockForPosition(IBlockData block, BlockPosition position) { + return Block.b(block, getWorld(), position); + } + + @Override + public BlockPosition getPosition(int x, int y, int z) { + return new BlockPosition(x, y, z); + } + + @Override + public void updateLightingForBlock(BlockPosition position) { + getWorld().getChunkProvider().getLightEngine().a(position); + } + + @Override + public boolean updateTileEntity(BlockPosition position, CompoundTag tag) { + // We will assume that the tile entity was created for us, + // though we do not do this on the other versions + TileEntity tileEntity = getWorld().getTileEntity(position); + if (tileEntity == null) { + return false; + } + NBTBase nativeTag = adapter.fromNative(tag); + tileEntity.load(tileEntity.getBlock(), (NBTTagCompound) nativeTag); + return true; + } + + @Override + public void notifyBlockUpdate(BlockPosition position, IBlockData oldState, IBlockData newState) { + getWorld().notify(position, oldState, newState, UPDATE | NOTIFY); + } + + @Override + public boolean isChunkTicking(Chunk chunk) { + return chunk.getState().isAtLeast(PlayerChunk.State.TICKING); + } + + @Override + public void markBlockChanged(BlockPosition position) { + ((ChunkProviderServer) getWorld().getChunkProvider()).flagDirty(position); + } + + private static final EnumDirection[] NEIGHBOUR_ORDER = { + EnumDirection.WEST, EnumDirection.EAST, + EnumDirection.DOWN, EnumDirection.UP, + EnumDirection.NORTH, EnumDirection.SOUTH + }; + + @Override + public void notifyNeighbors(BlockPosition pos, IBlockData oldState, IBlockData newState) { + World world = getWorld(); + if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { + world.update(pos, oldState.getBlock()); + } else { + // When we don't want events, manually run the physics without them. + // Un-nest neighbour updating + for (EnumDirection direction : NEIGHBOUR_ORDER) { + BlockPosition shifted = pos.shift(direction); + world.getType(shifted).doPhysics(world, shifted, oldState.getBlock(), pos, false); + } + } + if (newState.isComplexRedstone()) { + world.updateAdjacentComparators(pos, newState.getBlock()); + } + } + + @Override + public void updateNeighbors(BlockPosition pos, IBlockData oldState, IBlockData newState, int recursionLimit) { + World world = getWorld(); + // a == updateNeighbors + // b == updateDiagonalNeighbors + oldState.b(world, pos, NOTIFY, recursionLimit); + if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { + CraftWorld craftWorld = world.getWorld(); + if (craftWorld != null) { + BlockPhysicsEvent event = new BlockPhysicsEvent(craftWorld.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), CraftBlockData.fromData(newState)); + world.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + } + } + newState.a(world, pos, NOTIFY, recursionLimit); + newState.b(world, pos, NOTIFY, recursionLimit); + } + + @Override + public void onBlockStateChange(BlockPosition pos, IBlockData oldState, IBlockData newState) { + getWorld().a(pos, oldState, newState); + } + + @Override + public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { + return this.adapter.setBlock(this.getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4).bukkitChunk, position.getBlockX(), position.getBlockY(), position.getBlockZ(), block, sideEffectSet.shouldApply(SideEffect.LIGHTING)); + } +} \ No newline at end of file diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java index 4252d3f32..60e0f8037 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java @@ -884,6 +884,16 @@ public class AsyncWorld extends PassthroughExtent implements World { parent.setWaterAnimalSpawnLimit(limit); } + @Override + public int getWaterAmbientSpawnLimit() { + return 0; + } + + @Override + public void setWaterAmbientSpawnLimit(int limit) { + + } + @Override public int getAmbientSpawnLimit() { return parent.getAmbientSpawnLimit(); @@ -1285,18 +1295,28 @@ public class AsyncWorld extends PassthroughExtent implements World { } public long getTicksPerWaterSpawns() { - throw new UnsupportedOperationException(); + return parent.getTicksPerWaterSpawns(); } public void setTicksPerWaterSpawns(int ticksPerWaterSpawns) { - throw new UnsupportedOperationException(); + parent.setTicksPerWaterSpawns(ticksPerWaterSpawns); + } + + @Override + public long getTicksPerWaterAmbientSpawns() { + return parent.getTicksPerWaterAmbientSpawns(); + } + + @Override + public void setTicksPerWaterAmbientSpawns(int ticksPerAmbientSpawns) { + parent.setTicksPerWaterAmbientSpawns(ticksPerAmbientSpawns); } public long getTicksPerAmbientSpawns() { - throw new UnsupportedOperationException(); + return parent.getTicksPerAmbientSpawns(); } public void setTicksPerAmbientSpawns(int ticksPerAmbientSpawns) { - throw new UnsupportedOperationException(); + parent.setTicksPerAmbientSpawns(ticksPerAmbientSpawns); } } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/state/AsyncDataContainer.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/state/AsyncDataContainer.java index f1fbbcbb2..e64db1124 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/state/AsyncDataContainer.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/state/AsyncDataContainer.java @@ -3,15 +3,15 @@ package com.boydti.fawe.bukkit.wrapper.state; import com.boydti.fawe.FaweCache; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.Tag; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; + +import java.util.*; + import org.apache.commons.lang.Validate; import org.bukkit.NamespacedKey; import org.bukkit.persistence.PersistentDataAdapterContext; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; public final class AsyncDataContainer implements PersistentDataContainer { private final CompoundTag root; @@ -69,6 +69,20 @@ public final class AsyncDataContainer implements PersistentDataContainer { return z != null ? z : defaultValue; } + @NotNull + @Override + public Set getKeys() { + Set keys = new HashSet<>(); + this.get(false).keySet().forEach(key -> { + String[] keyData = key.split(":", 2); + if (keyData.length == 2) { + keys.add(new NamespacedKey(keyData[0], keyData[1])); + } + + }); + return keys; + } + public void remove(NamespacedKey key) { Validate.notNull(key, "The provided key for the custom value was null"); get(false).remove(key.toString()); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index f11fc13d3..588071c34 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -24,8 +24,9 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.boydti.fawe.Fawe; import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.implementation.packet.ChunkPacket; -import com.sk89q.jnbt.CompoundTag; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; +import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; @@ -34,6 +35,7 @@ import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; @@ -77,6 +79,7 @@ public class BukkitWorld extends AbstractWorld { } private final WeakReference worldRef; + private final WorldNativeAccess worldNativeAccess; /** * Construct the object. @@ -85,6 +88,12 @@ public class BukkitWorld extends AbstractWorld { */ public BukkitWorld(World world) { this.worldRef = new WeakReference<>(world); + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + if (adapter != null) { + this.worldNativeAccess = adapter.createWorldNativeAccess(world); + } else { + this.worldNativeAccess = null; + } } @Override @@ -464,26 +473,22 @@ public class BukkitWorld extends AbstractWorld { } @Override - public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); - if (adapter != null) { + public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) { + if (worldNativeAccess != null) { try { - return adapter.setBlock(BukkitAdapter.adapt(getWorld(), position), block, sideEffects); + return worldNativeAccess.setBlock(position, block, sideEffects); } catch (Exception e) { if (block instanceof BaseBlock && ((BaseBlock) block).getNbtData() != null) { - logger.warn("Tried to set a corrupt tile entity at " + position.toString()); - logger.warn(((BaseBlock) block).getNbtData().toString()); + logger.warn("Tried to set a corrupt tile entity at " + position.toString() + + ": " + ((BaseBlock) block).getNbtData(), e); + } else { + logger.warn("Failed to set block via adapter, falling back to generic", e); } - e.printStackTrace(); - Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - bukkitBlock.setBlockData(BukkitAdapter.adapt(block), sideEffects.doesApplyAny()); - return true; } - } else { - Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - bukkitBlock.setBlockData(BukkitAdapter.adapt(block), sideEffects.doesApplyAny()); - return true; } + Block bukkitBlock = getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + bukkitBlock.setBlockData(BukkitAdapter.adapt(block), sideEffects.doesApplyAny()); + return true; } @Override @@ -497,20 +502,17 @@ public class BukkitWorld extends AbstractWorld { } @Override - public Set applySideEffects(BlockVector3 position, com.sk89q.worldedit.world.block.BlockState previousType, SideEffectSet sideEffectSet) throws WorldEditException { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); - if (adapter != null) { - adapter.applySideEffects(BukkitAdapter.adapt(getWorld(), position), previousType, sideEffectSet); + public Set applySideEffects(BlockVector3 position, com.sk89q.worldedit.world.block.BlockState previousType, + SideEffectSet sideEffectSet) { + if (worldNativeAccess != null) { + worldNativeAccess.applySideEffects(position, previousType, sideEffectSet); return Sets.intersection( - adapter.getSupportedSideEffects(), + WorldEditPlugin.getInstance().getInternalPlatform().getSupportedSideEffects(), sideEffectSet.getSideEffectsToApply() ); } - return Sets.intersection( - WorldEditPlugin.getInstance().getInternalPlatform().getSupportedSideEffects(), - sideEffectSet.getSideEffectsToApply() - ); + return ImmutableSet.of(); } @Override diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java index 416b4b621..d77073045 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java @@ -30,17 +30,16 @@ import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.SideEffect; -import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.world.DataFixer; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.registry.BlockMaterial; import java.util.Map; @@ -98,23 +97,12 @@ public interface BukkitImplAdapter extends IBukkitAdapter { BaseBlock getBlock(Location location); /** - * Set the block at the given location. + * Create a {@link WorldNativeAccess} for the given world reference. * - * @param location the location - * @param state the block - * @param sideEffectSet side effects to apply - * @return true if a block was likely changed + * @param world the world reference + * @return the native access object */ - boolean setBlock(Location location, BlockStateHolder state, SideEffectSet sideEffectSet); - - /** - * Applies side effects on the given block. - * - * @param position position of the block - * @param previousType the type of the previous block that was there - * @param sideEffectSet side effects to apply - */ - void applySideEffects(Location position, BlockState previousType, SideEffectSet sideEffectSet); + WorldNativeAccess createWorldNativeAccess(World world); /** * Get the state for the given entity. diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/IDelegateBukkitImplAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/IDelegateBukkitImplAdapter.java index 9f5499dcd..5bf4d88af 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/IDelegateBukkitImplAdapter.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/IDelegateBukkitImplAdapter.java @@ -66,10 +66,6 @@ public interface IDelegateBukkitImplAdapter extends BukkitImplAdapter { return getParent().getBlock(location); } - default > boolean setBlock(Location location, B state, boolean notifyAndLight) { - return getParent().setBlock(location, state, SideEffectSet.none()); - } - @Override @Nullable default BaseEntity getEntity(Entity entity) { diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_14_R4.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_14_R4.java index 21bcf1718..09aa43ca3 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_14_R4.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_14_R4.java @@ -24,10 +24,7 @@ import com.boydti.fawe.FaweCache; import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.implementation.packet.ChunkPacket; import com.boydti.fawe.beta.implementation.queue.SingleThreadQueueExtent; -import com.boydti.fawe.bukkit.adapter.mc1_14.BlockMaterial_1_14; -import com.boydti.fawe.bukkit.adapter.mc1_14.BukkitAdapter_1_14; -import com.boydti.fawe.bukkit.adapter.mc1_14.BukkitGetBlocks_1_14; -import com.boydti.fawe.bukkit.adapter.mc1_14.MapChunkUtil_1_14; +import com.boydti.fawe.bukkit.adapter.mc1_14.*; import com.boydti.fawe.bukkit.adapter.mc1_14.nbt.LazyCompoundTag_1_14; import com.google.common.io.Files; import com.sk89q.jnbt.CompoundTag; @@ -42,13 +39,13 @@ import com.sk89q.worldedit.bukkit.adapter.CachedBukkitAdapter; import com.sk89q.worldedit.bukkit.adapter.IDelegateBukkitImplAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.LazyBaseEntity; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.*; import com.sk89q.worldedit.world.entity.EntityType; @@ -71,6 +68,7 @@ import org.bukkit.generator.ChunkGenerator; import javax.annotation.Nullable; import java.io.File; import java.io.IOException; +import java.lang.ref.WeakReference; import java.util.Map; import java.util.OptionalInt; import java.util.Set; @@ -151,26 +149,11 @@ public final class FAWE_Spigot_v1_14_R4 extends CachedBukkitAdapter implements I return state.toBaseBlock(); } - @Override - public boolean setBlock(Location location, BlockStateHolder state, SideEffectSet sideEffectSet) { - return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, sideEffectSet.shouldApply(SideEffect.LIGHTING)); - } - - @Override - public void applySideEffects(Location position, BlockState previousType, SideEffectSet sideEffectSet) { - return; //TODO: properly implement SideEffects into FAWE - } - @Override public Set getSupportedSideEffects() { return SideEffectSet.defaults().getSideEffectsToApply(); } - @Override - public > boolean setBlock(Location location, B state, boolean notifyAndLight) { - return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, notifyAndLight); - } - public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) { CraftChunk craftChunk = (CraftChunk) chunk; Chunk nmsChunk = craftChunk.getHandle(); @@ -222,6 +205,12 @@ public final class FAWE_Spigot_v1_14_R4 extends CachedBukkitAdapter implements I return true; } + @Override + public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { + return new FAWEWorldNativeAccess_1_14(this, + new WeakReference<>(((CraftWorld) world).getHandle())); + } + @Nullable private static String getEntityId(Entity entity) { MinecraftKey minecraftkey = EntityTypes.getName(entity.getEntityType()); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_15_R2.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_15_R2.java index ffbe28f1d..85dd26089 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_15_R2.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_15_R2.java @@ -26,10 +26,7 @@ import com.boydti.fawe.beta.IQueueChunk; import com.boydti.fawe.beta.IQueueExtent; import com.boydti.fawe.beta.implementation.packet.ChunkPacket; import com.boydti.fawe.beta.implementation.queue.SingleThreadQueueExtent; -import com.boydti.fawe.bukkit.adapter.mc1_15_2.BlockMaterial_1_15_2; -import com.boydti.fawe.bukkit.adapter.mc1_15_2.BukkitAdapter_1_15_2; -import com.boydti.fawe.bukkit.adapter.mc1_15_2.BukkitGetBlocks_1_15_2; -import com.boydti.fawe.bukkit.adapter.mc1_15_2.MapChunkUtil_1_15_2; +import com.boydti.fawe.bukkit.adapter.mc1_15_2.*; import com.boydti.fawe.bukkit.adapter.mc1_15_2.nbt.LazyCompoundTag_1_15_2; import com.google.common.io.Files; import com.sk89q.jnbt.CompoundTag; @@ -44,6 +41,7 @@ import com.sk89q.worldedit.bukkit.adapter.CachedBukkitAdapter; import com.sk89q.worldedit.bukkit.adapter.IDelegateBukkitImplAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.LazyBaseEntity; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.registry.state.Property; @@ -73,6 +71,7 @@ import org.bukkit.generator.ChunkGenerator; import javax.annotation.Nullable; import java.io.File; import java.io.IOException; +import java.lang.ref.WeakReference; import java.util.Map; import java.util.OptionalInt; import java.util.Set; @@ -160,26 +159,11 @@ public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements I return state.toBaseBlock(); } - @Override - public boolean setBlock(Location location, BlockStateHolder state, SideEffectSet sideEffectSet) { - return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, sideEffectSet.shouldApply(SideEffect.LIGHTING)); - } - - @Override - public void applySideEffects(Location position, BlockState previousType, SideEffectSet sideEffectSet) { - return; //TODO: properly implement SideEffects into FAWE - } - @Override public Set getSupportedSideEffects() { return SideEffectSet.defaults().getSideEffectsToApply(); } - @Override - public > boolean setBlock(Location location, B state, boolean notifyAndLight) { - return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, notifyAndLight); - } - public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) { CraftChunk craftChunk = (CraftChunk) chunk; Chunk nmsChunk = craftChunk.getHandle(); @@ -231,6 +215,12 @@ public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements I return true; } + @Override + public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { + return new FAWEWorldNativeAccess_1_15_2(this, + new WeakReference<>(((CraftWorld) world).getHandle())); + } + @Nullable private static String getEntityId(Entity entity) { MinecraftKey minecraftkey = EntityTypes.getName(entity.getEntityType()); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java index a97372095..3a5f2af11 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java @@ -26,10 +26,7 @@ import com.boydti.fawe.beta.IQueueChunk; import com.boydti.fawe.beta.IQueueExtent; import com.boydti.fawe.beta.implementation.packet.ChunkPacket; import com.boydti.fawe.beta.implementation.queue.SingleThreadQueueExtent; -import com.boydti.fawe.bukkit.adapter.mc1_16_1.BlockMaterial_1_16_1; -import com.boydti.fawe.bukkit.adapter.mc1_16_1.BukkitAdapter_1_16_1; -import com.boydti.fawe.bukkit.adapter.mc1_16_1.BukkitGetBlocks_1_16_1; -import com.boydti.fawe.bukkit.adapter.mc1_16_1.MapChunkUtil_1_16_1; +import com.boydti.fawe.bukkit.adapter.mc1_16_1.*; import com.boydti.fawe.bukkit.adapter.mc1_16_1.nbt.LazyCompoundTag_1_16_1; import com.google.common.io.Files; import com.sk89q.jnbt.CompoundTag; @@ -44,6 +41,7 @@ import com.sk89q.worldedit.bukkit.adapter.CachedBukkitAdapter; import com.sk89q.worldedit.bukkit.adapter.IDelegateBukkitImplAdapter; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.LazyBaseEntity; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.registry.state.Property; @@ -72,6 +70,7 @@ import org.bukkit.generator.ChunkGenerator; import javax.annotation.Nullable; import java.io.File; import java.io.IOException; +import java.lang.ref.WeakReference; import java.util.Map; import java.util.OptionalInt; import java.util.Set; @@ -159,26 +158,11 @@ public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements I return state.toBaseBlock(); } - @Override - public boolean setBlock(Location location, BlockStateHolder state, SideEffectSet sideEffectSet) { - return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, sideEffectSet.shouldApply(SideEffect.LIGHTING)); - } - - @Override - public void applySideEffects(Location position, BlockState previousType, SideEffectSet sideEffectSet) { - return; //TODO: properly implement SideEffects into FAWE - } - @Override public Set getSupportedSideEffects() { return SideEffectSet.defaults().getSideEffectsToApply(); } - @Override - public > boolean setBlock(Location location, B state, boolean notifyAndLight) { - return this.setBlock(location.getChunk(), location.getBlockX(), location.getBlockY(), location.getBlockZ(), state, notifyAndLight); - } - public boolean setBlock(org.bukkit.Chunk chunk, int x, int y, int z, BlockStateHolder state, boolean update) { CraftChunk craftChunk = (CraftChunk) chunk; Chunk nmsChunk = craftChunk.getHandle(); @@ -230,6 +214,12 @@ public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements I return true; } + @Override + public WorldNativeAccess createWorldNativeAccess(org.bukkit.World world) { + return new FAWEWorldNativeAccess_1_16(this, + new WeakReference<>(((CraftWorld)world).getHandle())); + } + @Nullable private static String getEntityId(Entity entity) { MinecraftKey minecraftkey = EntityTypes.getName(entity.getEntityType()); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/WorldNativeAccess.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/WorldNativeAccess.java new file mode 100644 index 000000000..ac32171e7 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/WorldNativeAccess.java @@ -0,0 +1,184 @@ +/* + * 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.internal.wna; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; + +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Natively access and perform operations on the world. + * + * @param the native chunk type + * @param the native block state type + * @param the native position type + */ +public interface WorldNativeAccess { + + default > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { + checkNotNull(position); + checkNotNull(block); + setCurrentSideEffectSet(sideEffects); + + int x = position.getBlockX(); + int y = position.getBlockY(); + int z = position.getBlockZ(); + + // First set the block + NC chunk = getChunk(x >> 4, z >> 4); + NP pos = getPosition(x, y, z); + NBS old = getBlockState(chunk, pos); + NBS newState = toNative(block.toImmutableState()); + // change block prior to placing if it should be fixed + if (sideEffects.shouldApply(SideEffect.VALIDATION)) { + newState = getValidBlockForPosition(newState, pos); + } + NBS successState = setBlockState(chunk, pos, newState); + boolean successful = successState != null; + + // Create the TileEntity + if (successful || old == newState) { + if (block instanceof BaseBlock) { + BaseBlock baseBlock = (BaseBlock) block; + CompoundTag tag = baseBlock.getNbtData(); + if (tag != null) { + tag = tag.createBuilder() + .putString("id", baseBlock.getNbtId()) + .putInt("x", position.getX()) + .putInt("y", position.getY()) + .putInt("z", position.getZ()) + .build(); + // update if TE changed as well + successful = updateTileEntity(pos, tag); + } + } + } + + if (successful) { + if (sideEffects.getState(SideEffect.LIGHTING) == SideEffect.State.ON) { + updateLightingForBlock(pos); + } + markAndNotifyBlock(pos, chunk, old, newState, sideEffects); + } + + return successful; + } + + default void applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) { + setCurrentSideEffectSet(sideEffectSet); + NP pos = getPosition(position.getX(), position.getY(), position.getZ()); + NC chunk = getChunk(position.getX() >> 4, position.getZ() >> 4); + NBS oldData = toNative(previousType); + NBS newData = getBlockState(chunk, pos); + + if (sideEffectSet.getState(SideEffect.LIGHTING) == SideEffect.State.ON) { + updateLightingForBlock(pos); + } + + markAndNotifyBlock(pos, chunk, oldData, newData, sideEffectSet); + } + + // state-keeping functions for WNA + // may be thread-unsafe, as this is single-threaded code + + /** + * Receive the current side-effect set from the high level call. + * + * This allows the implementation to branch on the side-effects internally. + * + * @param sideEffectSet the set of side-effects + */ + default void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { + } + + // access functions + + NC getChunk(int x, int z); + + NBS toNative(BlockState state); + + NBS getBlockState(NC chunk, NP position); + + @Nullable + NBS setBlockState(NC chunk, NP position, NBS state); + + NBS getValidBlockForPosition(NBS block, NP position); + + NP getPosition(int x, int y, int z); + + void updateLightingForBlock(NP position); + + boolean updateTileEntity(NP position, CompoundTag tag); + + void notifyBlockUpdate(NP position, NBS oldState, NBS newState); + + boolean isChunkTicking(NC chunk); + + void markBlockChanged(NP position); + + void notifyNeighbors(NP pos, NBS oldState, NBS newState); + + void updateNeighbors(NP pos, NBS oldState, NBS newState, int recursionLimit); + + void onBlockStateChange(NP pos, NBS oldState, NBS newState); + + /** + * This is a heavily modified function stripped from MC to apply worldedit-modifications. + * + * See Forge's World.markAndNotifyBlock + */ + default void markAndNotifyBlock(NP pos, NC chunk, NBS oldState, NBS newState, SideEffectSet sideEffectSet) { + NBS blockState1 = getBlockState(chunk, pos); + if (blockState1 != newState) { + return; + } + + // Remove redundant branches + if (isChunkTicking(chunk)) { + if (sideEffectSet.shouldApply(SideEffect.ENTITY_AI)) { + notifyBlockUpdate(pos, oldState, newState); + } else { + // If we want to skip entity AI, just mark the block for sending + markBlockChanged(pos); + } + } + + if (sideEffectSet.shouldApply(SideEffect.NEIGHBORS)) { + notifyNeighbors(pos, oldState, newState); + } + + // Make connection updates optional + if (sideEffectSet.shouldApply(SideEffect.VALIDATION)) { + updateNeighbors(pos, oldState, newState, 512); + } + + onBlockStateChange(pos, oldState, newState); + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/package-info.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/package-info.java new file mode 100644 index 000000000..69009eb59 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/wna/package-info.java @@ -0,0 +1,25 @@ +/* + * 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 . + */ + +/** + * "WNA", or WorldEdit Native Access. + * + * Contains internal helper functions for sharing code between platforms. + */ +package com.sk89q.worldedit.internal.wna; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffect.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffect.java index c4c814fcb..5b142a364 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffect.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffect.java @@ -24,9 +24,9 @@ import java.util.Locale; public enum SideEffect { LIGHTING(State.ON), NEIGHBORS(State.ON), - CONNECTIONS(State.ON), + VALIDATION(State.ON), ENTITY_AI(State.OFF), - PLUGIN_EVENTS(State.OFF); + EVENTS(State.OFF); private final String displayName; private final String description; diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index 4708d4596..016a3d60d 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -502,12 +502,12 @@ "worldedit.sideeffect.lighting.description": "Updates block lighting", "worldedit.sideeffect.neighbors": "Neighbors", "worldedit.sideeffect.neighbors.description": "Notifies nearby blocks of changes", - "worldedit.sideeffect.connections": "Connections", - "worldedit.sideeffect.connections.description": "Updates connections for blocks like fences", + "worldedit.sideeffect.validation": "Validation", + "worldedit.sideeffect.validation.description": "Validates and fixes inconsistent world state, such as disconnected blocks", "worldedit.sideeffect.entity_ai": "Entity AI", "worldedit.sideeffect.entity_ai.description": "Updates Entity AI paths for the block changes", - "worldedit.sideeffect.plugin_events": "Plugin Events", - "worldedit.sideeffect.plugin_events.description": "Tells other plugins/mods about these changes when applicable", + "worldedit.sideeffect.events": "Mod/Plugin Events", + "worldedit.sideeffect.events.description": "Tells other mods/plugins about these changes when applicable", "worldedit.sideeffect.state.on": "On", "worldedit.sideeffect.state.delayed": "Delayed", "worldedit.sideeffect.state.off": "Off", diff --git a/worldedit-fabric/build.gradle.kts b/worldedit-fabric/build.gradle.kts index 1cf6df8dd..4b7a7b079 100644 --- a/worldedit-fabric/build.gradle.kts +++ b/worldedit-fabric/build.gradle.kts @@ -7,8 +7,8 @@ applyShadowConfiguration() apply(plugin = "fabric-loom") val minecraftVersion = "1.15.2" -val yarnMappings = "1.15.2+build.8:v2" -val loaderVersion = "0.7.6+build.180" +val yarnMappings = "1.15.2+build.14:v2" +val loaderVersion = "0.7.8+build.189" configurations.all { resolutionStrategy { diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java index 317274331..33219c7a3 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricAdapter.java @@ -25,6 +25,7 @@ import com.google.common.collect.ImmutableList; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.fabric.internal.NBTConverter; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.registry.state.BooleanProperty; diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java index f307b789c..d82bb8f75 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricDataFixer.java @@ -36,9 +36,10 @@ import com.mojang.datafixers.DataFixerBuilder; import com.mojang.datafixers.Dynamic; import com.mojang.datafixers.schemas.Schema; import com.sk89q.jnbt.CompoundTag; -import net.minecraft.datafixers.NbtOps; -import net.minecraft.datafixers.Schemas; -import net.minecraft.datafixers.TypeReferences; +import com.sk89q.worldedit.fabric.internal.NBTConverter; +import net.minecraft.datafixer.NbtOps; +import net.minecraft.datafixer.Schemas; +import net.minecraft.datafixer.TypeReferences; import net.minecraft.nbt.FloatTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.StringTag; diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java index d1fb75a04..4ea3969fd 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricEntity.java @@ -25,6 +25,7 @@ import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.metadata.EntityProperties; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.fabric.internal.NBTConverter; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.NullWorld; diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java index 7fb18b0e7..bef543f6e 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java @@ -202,7 +202,7 @@ class FabricPlatform extends AbstractPlatform implements MultiUserPlatform { } private static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.CONNECTIONS, + SideEffect.VALIDATION, SideEffect.ENTITY_AI, SideEffect.LIGHTING, SideEffect.NEIGHBORS diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java index 48507f8fe..1ee00d311 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlayer.java @@ -25,6 +25,7 @@ import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extension.platform.AbstractPlayerActor; import com.sk89q.worldedit.extent.inventory.BlockBag; +import com.sk89q.worldedit.fabric.internal.NBTConverter; import com.sk89q.worldedit.fabric.mixin.AccessorServerPlayerEntity; import com.sk89q.worldedit.fabric.net.handler.WECUIPacketHandler; import com.sk89q.worldedit.internal.cui.CUIEvent; @@ -42,10 +43,10 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; import io.netty.buffer.Unpooled; import net.minecraft.block.Block; -import net.minecraft.client.network.packet.BlockEntityUpdateS2CPacket; -import net.minecraft.client.network.packet.BlockUpdateS2CPacket; -import net.minecraft.client.network.packet.CustomPayloadS2CPacket; import net.minecraft.item.ItemStack; +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; +import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; +import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java index e085d2326..93e05a820 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWorld.java @@ -34,6 +34,8 @@ import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.fabric.internal.FabricWorldNativeAccess; +import com.sk89q.worldedit.fabric.internal.NBTConverter; import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.math.BlockVector2; @@ -64,7 +66,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUsageContext; import net.minecraft.server.MinecraftServer; import net.minecraft.server.WorldGenerationProgressListener; -import net.minecraft.server.world.ChunkHolder; import net.minecraft.server.world.ServerChunkManager; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.ActionResult; @@ -129,6 +130,7 @@ public class FabricWorld extends AbstractWorld { private static final net.minecraft.block.BlockState JUNGLE_SHRUB = Blocks.OAK_LEAVES.getDefaultState().with(LeavesBlock.PERSISTENT, Boolean.TRUE); private final WeakReference worldRef; + private final FabricWorldNativeAccess worldNativeAccess; /** * Construct a new world. @@ -138,6 +140,7 @@ public class FabricWorld extends AbstractWorld { FabricWorld(World world) { checkNotNull(world); this.worldRef = new WeakReference<>(world); + this.worldNativeAccess = new FabricWorldNativeAccess(worldRef); } /** @@ -191,98 +194,14 @@ public class FabricWorld extends AbstractWorld { return null; } - public void markAndNotifyBlock(World world, BlockPos pos, @Nullable WorldChunk worldChunk, net.minecraft.block.BlockState blockState, - net.minecraft.block.BlockState state, SideEffectSet sideEffectSet) { - Block block = state.getBlock(); - net.minecraft.block.BlockState blockState2 = world.getBlockState(pos); - if (blockState2 == state) { - if (blockState != blockState2) { - world.checkBlockRerender(pos, blockState, blockState2); - } - - if (world.isClient || worldChunk.getLevelType() != null && worldChunk.getLevelType().isAfter(ChunkHolder.LevelType.TICKING)) { - if (sideEffectSet.shouldApply(SideEffect.ENTITY_AI)) { - world.updateListeners(pos, blockState, state, UPDATE | NOTIFY); - } else { - // If we want to skip entity AI, just call the chunk dirty flag. - ((ServerChunkManager) world.getChunkManager()).markForUpdate(pos); - } - } - - if (!world.isClient && sideEffectSet.shouldApply(SideEffect.NEIGHBORS)) { - world.updateNeighbors(pos, blockState.getBlock()); - if (state.hasComparatorOutput()) { - world.updateHorizontalAdjacent(pos, block); - } - } - - if (sideEffectSet.shouldApply(SideEffect.CONNECTIONS)) { - blockState.method_11637(world, pos, 2); - state.updateNeighborStates(world, pos, 2); - state.method_11637(world, pos, 2); - } - - // This is disabled for other platforms, but keep it for mods. - world.onBlockChanged(pos, blockState, blockState2); - } - } - @Override public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { - checkNotNull(position); - checkNotNull(block); - - World world = getWorldChecked(); - int x = position.getBlockX(); - int y = position.getBlockY(); - int z = position.getBlockZ(); - - // First set the block - WorldChunk chunk = world.getChunk(x >> 4, z >> 4); - BlockPos pos = new BlockPos(x, y, z); - net.minecraft.block.BlockState old = chunk.getBlockState(pos); - OptionalInt stateId = BlockStateIdAccess.getBlockStateId(block.toImmutableState()); - net.minecraft.block.BlockState newState = stateId.isPresent() ? Block.getStateFromRawId(stateId.getAsInt()) : FabricAdapter.adapt(block.toImmutableState()); - net.minecraft.block.BlockState successState = chunk.setBlockState(pos, newState, false); - boolean successful = successState != null; - - // Create the TileEntity - if (successful || old == newState) { - if (block instanceof BaseBlock) { - CompoundTag tag = ((BaseBlock) block).getNbtData(); - if (tag != null) { - net.minecraft.nbt.CompoundTag nativeTag = NBTConverter.toNative(tag); - BlockEntity tileEntity = getWorld().getWorldChunk(pos).getBlockEntity(pos); - if (tileEntity != null) { - tileEntity.fromTag(nativeTag); - tileEntity.setPos(pos); - tileEntity.setWorld(world); - successful = true; // update if TE changed as well - } - } - } - } - - if (successful) { - if (sideEffects.getState(SideEffect.LIGHTING) == SideEffect.State.ON) { - world.getChunkManager().getLightingProvider().checkBlock(pos); - } - markAndNotifyBlock(world, pos, chunk, old, newState, sideEffects); - } - - return successful; + return worldNativeAccess.setBlock(position, block, sideEffects); } @Override public Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) throws WorldEditException { - BlockPos pos = new BlockPos(position.getX(), position.getY(), position.getZ()); - net.minecraft.block.BlockState oldData = FabricAdapter.adapt(previousType); - net.minecraft.block.BlockState newData = getWorld().getBlockState(pos); - - if (sideEffectSet.getState(SideEffect.LIGHTING) == SideEffect.State.ON) { - getWorld().getChunkManager().getLightingProvider().checkBlock(pos); - } - markAndNotifyBlock(getWorld(), pos, null, oldData, newData, sideEffectSet); // Update + worldNativeAccess.applySideEffects(position, previousType, sideEffectSet); return Sets.intersection(FabricWorldEdit.inst.getPlatform().getSupportedSideEffects(), sideEffectSet.getSideEffectsToApply()); } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java new file mode 100644 index 000000000..6d64e39de --- /dev/null +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/FabricWorldNativeAccess.java @@ -0,0 +1,139 @@ +/* + * 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.fabric.internal; + +import com.sk89q.worldedit.fabric.FabricAdapter; +import com.sk89q.worldedit.internal.block.BlockStateIdAccess; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.world.ChunkHolder; +import net.minecraft.server.world.ServerChunkManager; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.WorldChunk; + +import javax.annotation.Nullable; +import java.lang.ref.WeakReference; +import java.util.Objects; + +public class FabricWorldNativeAccess implements WorldNativeAccess { + private static final int UPDATE = 1, NOTIFY = 2; + + private final WeakReference world; + + public FabricWorldNativeAccess(WeakReference world) { + this.world = world; + } + + private World getWorld() { + return Objects.requireNonNull(world.get(), "The reference to the world was lost"); + } + + @Override + public WorldChunk getChunk(int x, int z) { + return getWorld().getChunk(x, z); + } + + @Override + public BlockState toNative(com.sk89q.worldedit.world.block.BlockState state) { + int stateId = BlockStateIdAccess.getBlockStateId(state); + return BlockStateIdAccess.isValidInternalId(stateId) + ? Block.getStateFromRawId(stateId) + : FabricAdapter.adapt(state); + } + + @Override + public BlockState getBlockState(WorldChunk chunk, BlockPos position) { + return chunk.getBlockState(position); + } + + @Nullable + @Override + public BlockState setBlockState(WorldChunk chunk, BlockPos position, BlockState state) { + return chunk.setBlockState(position, state, false); + } + + @Override + public BlockState getValidBlockForPosition(BlockState block, BlockPos position) { + return Block.getRenderingState(block, getWorld(), position); + } + + @Override + public BlockPos getPosition(int x, int y, int z) { + return new BlockPos(x, y, z); + } + + @Override + public void updateLightingForBlock(BlockPos position) { + getWorld().getChunkManager().getLightingProvider().checkBlock(position); + } + + @Override + public boolean updateTileEntity(BlockPos position, com.sk89q.jnbt.CompoundTag tag) { + CompoundTag nativeTag = NBTConverter.toNative(tag); + BlockEntity tileEntity = getWorld().getWorldChunk(position).getBlockEntity(position); + if (tileEntity == null) { + return false; + } + tileEntity.setLocation(getWorld(), position); + tileEntity.fromTag(nativeTag); + return true; + } + + @Override + public void notifyBlockUpdate(BlockPos position, BlockState oldState, BlockState newState) { + getWorld().updateListeners(position, oldState, newState, UPDATE | NOTIFY); + } + + @Override + public boolean isChunkTicking(WorldChunk chunk) { + return chunk.getLevelType().isAfter(ChunkHolder.LevelType.TICKING); + } + + @Override + public void markBlockChanged(BlockPos position) { + ((ServerChunkManager) getWorld().getChunkManager()).markForUpdate(position); + } + + @Override + public void notifyNeighbors(BlockPos pos, BlockState oldState, BlockState newState) { + getWorld().updateNeighbors(pos, oldState.getBlock()); + if (newState.hasComparatorOutput()) { + getWorld().updateHorizontalAdjacent(pos, newState.getBlock()); + } + } + + @Override + public void updateNeighbors(BlockPos pos, BlockState oldState, BlockState newState) { + World world = getWorld(); + // method_11637 = updateDiagonalNeighbors + oldState.method_11637(world, pos, NOTIFY); + newState.updateNeighborStates(world, pos, NOTIFY); + newState.method_11637(world, pos, NOTIFY); + } + + @Override + public void onBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) { + getWorld().onBlockChanged(pos, oldState, newState); + } +} diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/NBTConverter.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java similarity index 99% rename from worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/NBTConverter.java rename to worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java index 450dfcb65..2cdc6be4e 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/NBTConverter.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/internal/NBTConverter.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.fabric; +package com.sk89q.worldedit.fabric.internal; import com.sk89q.jnbt.ByteArrayTag; import com.sk89q.jnbt.ByteTag; @@ -44,7 +44,7 @@ import java.util.Set; /** * Converts between JNBT and Minecraft NBT classes. */ -final class NBTConverter { +public final class NBTConverter { private NBTConverter() { } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/net/handler/WECUIPacketHandler.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/net/handler/WECUIPacketHandler.java index 816d6c76f..4571e50d2 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/net/handler/WECUIPacketHandler.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/net/handler/WECUIPacketHandler.java @@ -23,15 +23,9 @@ import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.fabric.FabricAdapter; import com.sk89q.worldedit.fabric.FabricPlayer; import com.sk89q.worldedit.fabric.FabricWorldEdit; -import net.fabricmc.fabric.api.network.PacketConsumer; -import net.fabricmc.fabric.api.network.PacketContext; import net.fabricmc.fabric.api.network.ServerSidePacketRegistry; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.packet.CustomPayloadS2CPacket; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.network.packet.CustomPayloadC2SPacket; import net.minecraft.util.Identifier; -import net.minecraft.util.PacketByteBuf; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -58,4 +52,4 @@ public final class WECUIPacketHandler { session.describeCUI(actor); }); } -} \ No newline at end of file +} diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntity.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntity.java index a7f99e1a7..d522107d6 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntity.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeEntity.java @@ -25,6 +25,7 @@ import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.metadata.EntityProperties; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.forge.internal.NBTConverter; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.NullWorld; diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java index b844425eb..7c682b81d 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java @@ -208,7 +208,7 @@ class ForgePlatform extends AbstractPlatform implements MultiUserPlatform { } private static final Set SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.CONNECTIONS, + SideEffect.VALIDATION, SideEffect.ENTITY_AI, SideEffect.LIGHTING, SideEffect.NEIGHBORS diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java index 5d69754a6..4aa3b7a92 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorld.java @@ -19,8 +19,6 @@ package com.sk89q.worldedit.forge; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -34,6 +32,9 @@ import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.forge.internal.ForgeWorldNativeAccess; +import com.sk89q.worldedit.forge.internal.NBTConverter; +import com.sk89q.worldedit.forge.internal.TileEntityUtils; import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; import com.sk89q.worldedit.internal.util.BiomeMath; @@ -105,6 +106,7 @@ import net.minecraft.world.storage.SaveHandler; import net.minecraft.world.storage.WorldInfo; import net.minecraftforge.common.DimensionManager; +import javax.annotation.Nullable; import java.io.File; import java.io.IOException; import java.lang.ref.WeakReference; @@ -119,7 +121,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; -import javax.annotation.Nullable; +import static com.google.common.base.Preconditions.checkNotNull; /** * An adapter to Minecraft worlds for WorldEdit. @@ -127,13 +129,13 @@ import javax.annotation.Nullable; public class ForgeWorld extends AbstractWorld { private static final Random random = new Random(); - private static final int UPDATE = 1, NOTIFY = 2; private static final net.minecraft.block.BlockState JUNGLE_LOG = Blocks.JUNGLE_LOG.getDefaultState(); private static final net.minecraft.block.BlockState JUNGLE_LEAF = Blocks.JUNGLE_LEAVES.getDefaultState().with(LeavesBlock.PERSISTENT, Boolean.TRUE); private static final net.minecraft.block.BlockState JUNGLE_SHRUB = Blocks.OAK_LEAVES.getDefaultState().with(LeavesBlock.PERSISTENT, Boolean.TRUE); private final WeakReference worldRef; + private final ForgeWorldNativeAccess nativeAccess; /** * Construct a new world. @@ -143,6 +145,7 @@ public class ForgeWorld extends AbstractWorld { ForgeWorld(World world) { checkNotNull(world); this.worldRef = new WeakReference<>(world); + this.nativeAccess = new ForgeWorldNativeAccess(worldRef); } /** @@ -194,101 +197,14 @@ public class ForgeWorld extends AbstractWorld { return null; } - /** - * This is a heavily modified function stripped from MC to apply worldedit-modifications. - * - * @see World#markAndNotifyBlock - */ - public void markAndNotifyBlock(World world, BlockPos pos, @Nullable Chunk chunk, net.minecraft.block.BlockState blockstate, - net.minecraft.block.BlockState newState, SideEffectSet sideEffectSet) { - Block block = newState.getBlock(); - net.minecraft.block.BlockState blockstate1 = world.getBlockState(pos); - if (blockstate1 == newState) { - if (blockstate != blockstate1) { - world.markBlockRangeForRenderUpdate(pos, blockstate, blockstate1); - } - - // Remove redundant branches - if (world.isRemote || chunk == null || chunk.getLocationType().isAtLeast(ChunkHolder.LocationType.TICKING)) { - if (sideEffectSet.shouldApply(SideEffect.ENTITY_AI)) { - world.notifyBlockUpdate(pos, blockstate, newState, UPDATE | NOTIFY); - } else { - // If we want to skip entity AI, just call the chunk dirty flag. - ((ServerChunkProvider) world.getChunkProvider()).markBlockChanged(pos); - } - } - - if (!world.isRemote && sideEffectSet.shouldApply(SideEffect.NEIGHBORS)) { - world.notifyNeighbors(pos, blockstate.getBlock()); - if (newState.hasComparatorInputOverride()) { - world.updateComparatorOutputLevel(pos, block); - } - } - - // Make connection updates optional - if (sideEffectSet.shouldApply(SideEffect.CONNECTIONS)) { - blockstate.updateDiagonalNeighbors(world, pos, 2); - newState.updateNeighbors(world, pos, 2); - newState.updateDiagonalNeighbors(world, pos, 2); - } - - // This is disabled for other platforms, but keep it for mods. - world.onBlockStateChange(pos, blockstate, blockstate1); - } - } - @Override public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { - checkNotNull(position); - checkNotNull(block); - - World world = getWorldChecked(); - int x = position.getBlockX(); - int y = position.getBlockY(); - int z = position.getBlockZ(); - - // First set the block - Chunk chunk = world.getChunk(x >> 4, z >> 4); - BlockPos pos = new BlockPos(x, y, z); - net.minecraft.block.BlockState old = chunk.getBlockState(pos); - OptionalInt stateId = BlockStateIdAccess.getBlockStateId(block.toImmutableState()); - net.minecraft.block.BlockState newState = stateId.isPresent() ? Block.getStateById(stateId.getAsInt()) : ForgeAdapter.adapt(block.toImmutableState()); - net.minecraft.block.BlockState successState = chunk.setBlockState(pos, newState, false); - boolean successful = successState != null; - - // Create the TileEntity - if (successful || old == newState) { - if (block instanceof BaseBlock) { - CompoundTag tag = ((BaseBlock) block).getNbtData(); - if (tag != null) { - CompoundNBT nativeTag = NBTConverter.toNative(tag); - nativeTag.putString("id", ((BaseBlock) block).getNbtId()); - TileEntityUtils.setTileEntity(world, position, nativeTag); - successful = true; // update if TE changed as well - } - } - } - - if (successful) { - if (sideEffects.getState(SideEffect.LIGHTING) == SideEffect.State.ON) { - world.getChunkProvider().getLightManager().checkBlock(pos); - } - markAndNotifyBlock(world, pos, chunk, old, newState, sideEffects); - } - - return successful; + return nativeAccess.setBlock(position, block, sideEffects); } @Override public Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) throws WorldEditException { - BlockPos pos = new BlockPos(position.getX(), position.getY(), position.getZ()); - net.minecraft.block.BlockState oldData = ForgeAdapter.adapt(previousType); - net.minecraft.block.BlockState newData = getWorld().getBlockState(pos); - - if (sideEffectSet.getState(SideEffect.LIGHTING) == SideEffect.State.ON) { - getWorld().getChunkProvider().getLightManager().checkBlock(pos); - } - markAndNotifyBlock(getWorld(), pos, null, oldData, newData, sideEffectSet); // Update + nativeAccess.applySideEffects(position, previousType, sideEffectSet); return Sets.intersection(ForgeWorldEdit.inst.getPlatform().getSupportedSideEffects(), sideEffectSet.getSideEffectsToApply()); } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/ForgeWorldNativeAccess.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/ForgeWorldNativeAccess.java new file mode 100644 index 000000000..33784f1e7 --- /dev/null +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/ForgeWorldNativeAccess.java @@ -0,0 +1,152 @@ +/* + * 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.forge.internal; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.forge.ForgeAdapter; +import com.sk89q.worldedit.internal.block.BlockStateIdAccess; +import com.sk89q.worldedit.internal.wna.WorldNativeAccess; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.server.ChunkHolder; +import net.minecraft.world.server.ServerChunkProvider; + +import javax.annotation.Nullable; +import java.lang.ref.WeakReference; +import java.util.Objects; + +public class ForgeWorldNativeAccess implements WorldNativeAccess { + private static final int UPDATE = 1, NOTIFY = 2; + + private final WeakReference world; + private SideEffectSet sideEffectSet; + + public ForgeWorldNativeAccess(WeakReference world) { + this.world = world; + } + + private World getWorld() { + return Objects.requireNonNull(world.get(), "The reference to the world was lost"); + } + + @Override + public void setCurrentSideEffectSet(SideEffectSet sideEffectSet) { + this.sideEffectSet = sideEffectSet; + } + + @Override + public Chunk getChunk(int x, int z) { + return getWorld().getChunk(x, z); + } + + @Override + public BlockState toNative(com.sk89q.worldedit.world.block.BlockState state) { + int stateId = BlockStateIdAccess.getBlockStateId(state); + return BlockStateIdAccess.isValidInternalId(stateId) + ? Block.getStateById(stateId) + : ForgeAdapter.adapt(state); + } + + @Override + public BlockState getBlockState(Chunk chunk, BlockPos position) { + return chunk.getBlockState(position); + } + + @Nullable + @Override + public BlockState setBlockState(Chunk chunk, BlockPos position, BlockState state) { + return chunk.setBlockState(position, state, false); + } + + @Override + public BlockState getValidBlockForPosition(BlockState block, BlockPos position) { + return Block.getValidBlockForPosition(block, getWorld(), position); + } + + @Override + public BlockPos getPosition(int x, int y, int z) { + return new BlockPos(x, y, z); + } + + @Override + public void updateLightingForBlock(BlockPos position) { + getWorld().getChunkProvider().getLightManager().checkBlock(position); + } + + @Override + public boolean updateTileEntity(BlockPos position, CompoundTag tag) { + CompoundNBT nativeTag = NBTConverter.toNative(tag); + return TileEntityUtils.setTileEntity(getWorld(), position, nativeTag); + } + + @Override + public void notifyBlockUpdate(BlockPos position, BlockState oldState, BlockState newState) { + getWorld().notifyBlockUpdate(position, oldState, newState, UPDATE | NOTIFY); + } + + @Override + public boolean isChunkTicking(Chunk chunk) { + return chunk.getLocationType().isAtLeast(ChunkHolder.LocationType.TICKING); + } + + @Override + public void markBlockChanged(BlockPos position) { + ((ServerChunkProvider) getWorld().getChunkProvider()).markBlockChanged(position); + } + + @Override + public void notifyNeighbors(BlockPos pos, BlockState oldState, BlockState newState) { + World world = getWorld(); + if (sideEffectSet.shouldApply(SideEffect.EVENTS)) { + world.notifyNeighbors(pos, oldState.getBlock()); + } else { + // Manually update each side + Block block = oldState.getBlock(); + world.neighborChanged(pos.west(), block, pos); + world.neighborChanged(pos.east(), block, pos); + world.neighborChanged(pos.down(), block, pos); + world.neighborChanged(pos.up(), block, pos); + world.neighborChanged(pos.north(), block, pos); + world.neighborChanged(pos.south(), block, pos); + } + if (newState.hasComparatorInputOverride()) { + world.updateComparatorOutputLevel(pos, newState.getBlock()); + } + } + + @Override + public void updateNeighbors(BlockPos pos, BlockState oldState, BlockState newState) { + World world = getWorld(); + oldState.updateDiagonalNeighbors(world, pos, NOTIFY); + newState.updateNeighbors(world, pos, NOTIFY); + newState.updateDiagonalNeighbors(world, pos, NOTIFY); + } + + @Override + public void onBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) { + getWorld().onBlockStateChange(pos, oldState, newState); + } +} diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/TileEntityUtils.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/TileEntityUtils.java index 29d2b187e..dc3297c7b 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/TileEntityUtils.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/internal/TileEntityUtils.java @@ -24,13 +24,10 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.sk89q.worldedit.math.BlockVector3; import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.IntNBT; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import javax.annotation.Nullable; - /** * Utility methods for setting tile entities in the world. */ @@ -39,39 +36,21 @@ public final class TileEntityUtils { private TileEntityUtils() { } - /** - * Update the given tag compound with position information. - * - * @param tag the tag - * @param position the position - */ - private static void updateForSet(CompoundNBT tag, BlockVector3 position) { - checkNotNull(tag); - checkNotNull(position); - - tag.put("x", new IntNBT(position.getBlockX())); - tag.put("y", new IntNBT(position.getBlockY())); - tag.put("z", new IntNBT(position.getBlockZ())); - } - /** * Set a tile entity at the given location using the tile entity ID from * the tag. * * @param world the world * @param position the position - * @param tag the tag for the tile entity (may be null to do nothing) + * @param tag the tag for the tile entity */ - static boolean setTileEntity(World world, BlockVector3 position, @Nullable CompoundNBT tag) { - if (tag != null) { - updateForSet(tag, position); - TileEntity tileEntity = TileEntity.create(tag); - if (tileEntity == null) { - return false; - } - world.setTileEntity(new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()), tileEntity); - return true; + static boolean setTileEntity(World world, BlockPos position, CompoundNBT tag) { + TileEntity tileEntity = TileEntity.create(tag); + if (tileEntity == null) { + return false; } + world.setTileEntity(new BlockPos(position.getX(), position.getY(), position.getZ()), tileEntity); + return true; } public static CompoundNBT copyNbtData(TileEntity tile) { From ce406e404b73f46abf43fb1af39a1266a3616a43 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 1 Jul 2020 19:46:43 +0100 Subject: [PATCH 05/18] We shouldn't be setting REGENERATIVE_CLEAR to false --- .../fawe/bukkit/regions/plotsquared/PlotSquaredFeature.java | 4 ++-- .../fawe/bukkit/regions/plotsquaredv4/PlotSquaredFeature.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/PlotSquaredFeature.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/PlotSquaredFeature.java index db58aa9a5..02242021e 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/PlotSquaredFeature.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/PlotSquaredFeature.java @@ -76,9 +76,9 @@ public class PlotSquaredFeature extends FaweMaskManager { // If it's going to fail, throw an error now rather than later //QueueProvider provider = QueueProvider.of(FaweLocalBlockQueue.class, null); //GlobalBlockQueue.IMP.setProvider(provider); - HybridPlotManager.REGENERATIVE_CLEAR = false; + //HybridPlotManager.REGENERATIVE_CLEAR = false; //log.debug(" - QueueProvider: " + FaweLocalBlockQueue.class); - log.debug(" - HybridPlotManager.REGENERATIVE_CLEAR: " + HybridPlotManager.REGENERATIVE_CLEAR); + //log.debug(" - HybridPlotManager.REGENERATIVE_CLEAR: " + HybridPlotManager.REGENERATIVE_CLEAR); } private void setupRegionManager() throws RuntimeException { diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquaredv4/PlotSquaredFeature.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquaredv4/PlotSquaredFeature.java index 5ba0d0dad..d1df6b58d 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquaredv4/PlotSquaredFeature.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquaredv4/PlotSquaredFeature.java @@ -77,9 +77,9 @@ public class PlotSquaredFeature extends FaweMaskManager { // If it's going to fail, throw an error now rather than later //QueueProvider provider = QueueProvider.of(FaweLocalBlockQueue.class, null); //GlobalBlockQueue.IMP.setProvider(provider); - HybridPlotManager.REGENERATIVE_CLEAR = false; + //HybridPlotManager.REGENERATIVE_CLEAR = false; //log.debug(" - QueueProvider: " + FaweLocalBlockQueue.class); - log.debug(" - HybridPlotManager.REGENERATIVE_CLEAR: " + HybridPlotManager.REGENERATIVE_CLEAR); + //log.debug(" - HybridPlotManager.REGENERATIVE_CLEAR: " + HybridPlotManager.REGENERATIVE_CLEAR); } private void setupChunkManager() throws RuntimeException { From ac314fcedb196120635c17b299d4232aa66c94bb Mon Sep 17 00:00:00 2001 From: MattBDev <4009945+MattBDev@users.noreply.github.com> Date: Wed, 1 Jul 2020 20:06:59 -0400 Subject: [PATCH 06/18] Gradle update --- gradle/wrapper/gradle-wrapper.jar | Bin 58694 -> 58910 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 ++ gradlew.bat | 1 + worldedit-core/build.gradle.kts | 2 +- worldedit-core/doctools/build.gradle.kts | 2 +- worldedit-libs/core/build.gradle.kts | 2 +- 7 files changed, 7 insertions(+), 4 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 490fda8577df6c95960ba7077c43220e5bb2c0d9..62d4c053550b91381bbd28b1afc82d634bf73a8a 100644 GIT binary patch delta 6447 zcmY*dbyQSczlH%shY+L(kQ}C6ise@?c@F%#`dE9xT=qM=Dm?$VxD1hrECD1a#01Q8o zMyT3}z+1K>hPE%4doH=x5X;^NP(OFD5GByp;5FQ^bpzkBa(;eudMu7Iyv$DE+N=>p z{3Y5_BP>F3)tXW*Styc(Ji3jnK-giGA_&42fsbZ@#+e+ly3w0VmLC;LA)h1UY(ChA zfwqQ?-@}@S93F|exOv;Se;P|SrYvEG(8q&|ltqvQHO9KgCSwM!Y+#d5eIRq$Mi`pU__N$FTxW@KAWIw= zayY6@9EyxG<_tr&{Wi87m5*mf=u&=;eL1gf{Mt)q8Drick8CcxzLW>cG~TbW)|$*D zYMc|5eZNNzt7O_C1LqgaI`Z0B+2#;3yO;E7N4oMY@~7$4;MRonU+Ca z#*cD!7$u9pZ|3f!-_6rpN}XhAWd`1qiR{e*1CJK1dvBsjUyY@BuT|;EAz}*0uSwT_ zq(g0jXTAK4wsQ>kIKEfRQZw^GIKNRZmV)b;c*Kpc?IvNuq{+eCM4%IBoRUk!JeJ4IVH!pLl+5gQn^$0Fw(WROw~SclOYWbMmvR+x&lYa zrU`5lck*s2zl;n6HEa_E|Btu!_BeeF8T=~0Z-pdJsKtN8nr88*8loznbI`@@8U-bc zCE&MaHH#?LN;6&wU%>->{X&6n*c6ECkP#Bn{lafo9KW+AKK>>f)YfzG#t`XCsl$WX zeS|50l&G{J6yrdD0#njv3|C}K(~azN%1+c#*-JXtZd=Rs-zr)f{Mneaqpgewz^3OM5FaDaH3?RpqMyL}=5sFu_zcDc^E~=$H zp`mutZ0ahrf32c`6ROBh&lI`>vuFJE*(NVpjr~^d53MZ0v$G#mHqBLpZ_=3?pNjHc zq`Dn6xbc32BSg`U@YE?)%%`LvRRWt@NnS4GSj=p><<_-c6l`myAJE0fSp^QbBfdS( zl>BC`;EiMtvPQ^FVSL|sjTc(?b%8Qt@%U>rt&`4_cYT+R`OvMomf#104S~4%y%G=i zSF$4cuIxlIe>@1E=sfXhVt@RqP-*grJnW~;iWiY{&Bqh7J|{vYQ!^1x4cnyGk6Wb9 zO0~}ejH&5@bEj&`2?Wl*cf=IV=$oa9rzh+#gN?j{IY z{cFM?b1*TT+&S2rOIFFvy{`FvX}_js+9rw1O*1ySv8Q}r2b0@*h|1Di0R1v* zVt4yRX`%ac3xeH;(y!FJ1wfX0u z(vEffdladd}+qfb##M5s|vX#V+!&>>0;o_Le@c)+7jDwJJ(9>+3CRkGH z##M)o)xY%3-ifK*iFpo7NiBT`wYVc=lYIZtKF{pxNfod2V)Ml&<=??l)7w5)Glopn z8#scqBz@^rE2-5aVDT_~Q#A7m4S6@B{QM6c_oY?)xk>z8r!qnbkvnqHoIRTMZijQ5 zv*ir-hjrA??C7S({;peDbjO+Kk0=tpoYQr7VQMJ*cR43?@CVMwg=}e<87k-T@wQ2`}bwe-}AAk?H=&0Yz~Zbk~bc>EP@tV zZ}M>Z2br)mwHOaQS1^~;AVlgQS(~eqTT3cQ)Jq8?bKk~$>tZSLgMW6sF{Os2*%OD^ z#@G{w=c@536Pgy5n{C*b?yf@Kd`v9zOG*56432l!^U3K)m1;qIzM*3ZS)XJnJ4THC z^e*Y&BQ)hyIA?LzXpqWK1`GN&gr?{?;qw?0wZ2-3WO3HI;)oY4YL?q5>F9QpzV?jw z%Ae1D+te?r(`vL~!tzayt@-830@#ZS)-KyoF0$s!Vw0Vud%!J!?moY0m8#gODn9F+ zY?TnBMwOKomVz60?|&V3HO!Z!cH+<9qbk>I-tT86n9=X9g`Zr=G+ zeJZH~&WtV__tcQ~B#c3;HnlwX+UoXIT>zqV;hho> zm(S|vbkcOsiPJd5fwJn%e%@Z(YNs#TqQ-MTQNPf9zDS)^#q=x)hn0wzK&7Tn_|BdK zx}|&Y!FqT|pVs!!ayLJ%C$M2LMR|s6aQ%QUi>oqMG=a-^oPaKfKR>DyX9dBV*%R!+ z%FvBF>KN67w@!4Lj7{*vhaGWkP344{vG@LFna%+6y+SB#;an8bz1SAoZg)%>it7$I$^*bWXoT6hbhk;!C7 z5tAKrT@VO5N!8a8G3=U4NL5yNqYdEsc2}2^o5ctj;Hrf0Dk~jL|srk z+XuB%H@ROKFqLw>LUu0bqRXw}B*R!OLo6|5*Q4|0dPlcG;>@4(_wZ})Yf&doH+L*RE=D|Z6RxTU#a|+qO_A4p z2U{|br!ER>QqRY>(awtH6L-S8zx$EeC$o;?KH-zEE{_f%M55>lLD!d9KbLpEyv&z3 zOD}@>1Exq4C9v6urtETRrtB>6m;qqJfh)6o@&+S>@D45s~ccePF=|y`U z-f~hKH|y8x$ovl1NJi3Qqom;ERzIG#^&!~fFQcyl0+H+;`yV@UyA|P*R^h1K*<8h{ zZqjSxw79HGC?HMzs;UY)%J2b0gXnQ=OY;dHMi3-zr7BZ6SnFxTu8VCoySbgs>l^A8 zmN&kvh~36=TRu2B!zInA7+dp6$aaef-&PgtbENZDyV(2Qh!`{>wDfZGw=1SFg*E{+ z#RVlY)C{0iP0+Q52$nQXhK{cVx<)i;=tyb=4mRyl7vX}F8Q%QL>_d6O7MM}r2)$$y+>m{$P8lbYz;fZ z3QWqj-`0^M+YpnVm!KE9$7?qn-uiDEF=*G=DW84fhX*c2c78!Mp!igEq_TE#1gLe8 zl$ro$nqM(yq&C?t-G#o9^eY1)Q9PX&YrAtOX|lboS9pTS>3XVy+T*%QF@Dx%R! zi~z%gEL!?kG{Q%?*cWYwt#5W}g>qQ?$$RX%E0(03W7ZERFNIOjpM5e?6J0JAro(i1 zsQeyE7G{}iSZNnP(n4FwvEp+ztGzd?jYx+(7Mk46X^c!>`oO7{i_yo>FV+t|SvS!} zBkOPHlUb!OPh1Y-8duD(b2u@P=5b8soW*+wnMY4Q8Eq!-L)~5b=n{68|ISew8k>Nt zjw!awOP?W8P1$OO`+#?*f{M(%*J)%E_^tKqR(nv#swuRijXecgwQacnz4TE8 z=2-p0u+VG&&^ePGuUHKIgI+h>XY*ZqAI5N*4Wc%8CXbXf57?Mpl#k^M=OHx26*X=b z@XIHOwsp{@XZ?Foo*@>FnvH!0EQsZ*BR?l&zm|TjE+bDiqA$Y2SY>Copx~1PHa4js z_!C`yon1&oi{Kr00~T|`DcYfvr^uu*F03OLS>^N@6Zi4VhFx(|WVY7whxD`RzX@{a zbt^j09cW#7p^J^3)}YLkrHR`G;mbL@W6__7SC=}Xh$OzjG!>tu=ubtG%LthmSDE)Y zfp>6T8@qS6C@y(<;eHyUqHzM9+%$!LWjRr*z1Qw1s?bAYrK7*KD*C^qP{W=T31H#9%+CXSZ;mJdIE6lN%IxBUk0hr5P})$QDM>4>ow%muHv z-zVTS+rI9+PV|%56*~qa^GKRWwz;dLtoUR%*1M}RGh$LcGlrHaAh-`>BW&!A6mvv( zo}57{BhH+Bqiza~XoxEIpXk_BGR8GzhcQwT4ND>~ahppmV*4SGve=@GE0zZGn}Z_l zMJ~Bi7prl4W<5m=nXZVtIYs=mwv2O*-UXG(Y9#Tfu8=c%NzSja+#d#gJ}FZhj)shN zMhx$^a#S-Ji`_niAxIQ^8YN)tqqJ!k5S_*BUFNY4F-4u9`G(W0v9;O*=f94+)C?7x zvYptQhDL9z*Ef*V5;DWma#Kwl4duDaGW=wP;`7wCjpnvd1`SO#b!fM0%!1J-u}iOT zS`t%%#@E|EzErxcRQ`fYJ)?gm)spx4eAd0@1P(T8Pr4n}5d$L~0>gytVD-^eF2bLx zW3i^+7-f{_=5Zq77xY&vCpL~@OTUZ`^myD;mRijH9fO>_Qdw^gurX%)NhZcgCIxgN z4yJcYrgaS}O8U(X^mwaTnrkxmt*ni+Cdmv>X$)_K4fl)^GtOUWQ~h>K$_^s;h!1Dw z*q&qAD_pNCM3lb9=U3Af`-?xuwb62P12trTb=MXKaYoNRHZPDJv9*`Aw)QF0Tb@g}XFL;| zdJF}(@e5r%*LCQBK*U(pdQRDeKE!)FF+}k{9Fz>A6zUP@OV+3DhvOQ zm{2a0QrQ^kn~?Df`@q(xA(yDoo!~Q+;;_*@_h(a`J~*mJkCa@npgsiRZAQ#pqSOZK z!muT4MNvG*<^MYIQN0h-W#UtDprj`i7Xxq=bTN{>rHH}V?ZdT~kd!O-X zt5JI4SH&YHnn(%JNKh$z*YZsO#t%LLA680?$^5V~dE8Pl^cPrXu++@2D?!)`KkPkM zE{Jaq+MNaAl)!{f!@ID?j@Fh)p!zU~?G%ODNge-447;DM8a%=PGRAB#D&LD5-=atG zY9Y3SF$2Xq8v`e8Rvmy3(wxGi--=L0eqRV6KFsU+waZV(WuPT00CKK)a--{eLpmBy zcXLs^*FtPQfeF;&p!YXTs3p9?U8Q0nzxqE+bM#Y7^_TmK zsw$bo4WCokyvS6N_0(KUJ2!8X|5~{<8pDd7rDt;^sCOx&=RxoN<`o-B}EwumojPl2bzq!x}k%%W5t9nTM1xeXi zQv;z_icyd<$#$rBJk9nk)8!h|c`$y~+NUVUGMRKk0aIBHQxP%YPu#d}ntgv1C_my; zpbt9K?YSK7jR%!jIUz+E3dnfbRMkv&7^h$B&oh5Ae2U{ka*7&~Z|XGk#69p1c_G1FC{&L1hn#)ZCmqpbHXC6uk;Obwn7kSJKaZ`H?u#%dz%W!fJP&`<51T`RomXjQ_%* zZ6iKVWhSW(o;7GYUuAwQxLzZTMt^H4@rorBp`tprXq9xsaKz)V<&_~zzsbGC#J2xC zQqiFYS<^~7D^Pcs?HzZm78=|`Ql?|`KIZR%#&qOMAEpStCrEMl8R0iZLR|#8%!;8p z0VGG*J(7WAxG~ij`ISsxDD--ge}1Dh3vAj>!wtQtec=#YCHNFKz$`Il6fa~c`rYYD z(xqyH;ETfFb?fK!?^*s3`))*65xs|5*^u3Snz(6t59|0kESGze=0W7f>LL{K_sC3& z*ardr??S+*s+p>{8sni`20|xZQ#^D^AQTjp`=*)izGeFN$qoSHK6K7(lg#A*T_gM( zK|#q5@BmyU)j&wqjB*=s29ufgV)YL%VJRV>@1p)anJxE7WkARdZ36Lb~f2b6Q zlm7uK{1gU}2|U1INlYN^Cl9Dh;{WL3PjQf^)PE=rpfSw?($jsQrq#T^it69uKY15Tb~K=hm} zh{fw3iUZN>cmUlz1T^;!pw6KHjOL|4uKo}3i|5k^cjn$5g+E9&YZL(c0t7^Yyr*;k z{39mNJB|kkA^-oNpr8j6hJ*m~3oM}A&ow%Xk22_5P%a?j<^aqv(ILmiH2Q>4Owl^89`~3rMHp zp3(w1Yh0kR@38~4fWByT)-r6kJki5KxqsSQ->5QD8+n7Lblrq&rqbQu<4GcZbwU*DehL0!uF< zAtALa2-nN~-E+^Kf9CT%^Pcydcg~!dGjHY)VIP{X+Mk5X+Z1~yNkl;K;}!vd91tr< z3$)!P0ZK`15GdXAY=~6eS|ICMe*_|EtvP9boO{_-?eWIq(~Zo-^Ni?kUPq%Frv%84 zr)oV1Do+g^<-_H;g&&6jZW30jA}03FK{ok6%fnpg;T?i6z?Ni4>j&X84{fZopFMV_ zPgq3;2ochOBOr>*RYtVW6qFYa2RCa+Rij=CocWr`A#j^WVQcy=l`bl)`?rJh=2@6e z5{>%T3cj@IohTK=HSz{HCTuU>e9Jdy(opO40;jY>4CYhDaoW$2zlNl%@5(Qiu=y0y zcPW^JHHod;>lqb~jFKYaMy2xYMtqcZ)tr_RM@6k9lIwWE8QrU-RZ^X=V;RcRRkvfh zd1>Ux5k>B6Zog!6HSDMhQY$F;vke(i*FG4;(;LQ}mHEaN8B^s8K(WGkdBU85Nh-nw z3TtcD!M5Wr+_o`vA0(6W&{4w4+nrWDTW1^{ z`epH{pQuSybd8I*sYD3SJ~2ag z)Yl_lSuF&Mbw4X`D?Zu`D`om|Xx`05WdlZ9t=JoV-6wy-R)lz9Vmu3c>A*fG30~0(?uQ5FkJ%zGK6$qDU~&hJ-V3Gc6s?!hhw*e)&1k)r=FnmzLWcywDn{+ksed*I9(B{*s3K(%lJ)U)|9X0a^E2 z?>RlLCvy+s4faLC0}D1!+cYzr%>h-s0|&9TBc1a9Zj|0mYS(5 zrQ~xRl7za1>q_E^{8c1q74LqFM-}HUQKs z-HX=BqDsXVjC!$_)l0!SF$o_V=RXM+z&V&q6#jU#AuF*Ji7|_5#Z1IhRaGYUxFADf zpXVNXi^mIuN^VZCEy?r%N`o=v9TuU`3mG^fHWsJ7ia5E@h3U;R^8nN0<6mS@yNZ|*5X zjEnxhb4H)?Mxy|QSTBrESL0adG6`arE$lH-Quq8IpQfLyXQ6-~q4$o-rhCpAt($tI zaQa-ZZM^S!;$?}%kABf#XFUWGO|RZjOJYN?9`~l2FNCPG(y>&9>G2l#+5fWW;j7y+ zQId*;#2h|q8>}2c^sysZFYgKl&gLAc8b;;_h%M^v5(yp^hO`DU#mFTN zZo|S}wZuF&o_J(DA!5AX>d=y}Iw7%z*yBr$?F*l*`ncP=hjAJ8zx2t%b$OWhk#*>L zp`+b!2vJ%5!5Pm;TXyhUy>17398}g9$AA1ssrPvPv44N`QtuuEE{>Jfe<@nFgB5?k zeEE{>t*#8BJh%#1a}!~{TtS;f#A-UQO!fR1zuQA~$WHb8_sW<`I zOQt1l>b3%|CE-m#+H%q)ASiMAt&ke3SnvD{cC0Ff;U-w5o;8ioQdl~qkLfEQ-TaIu~%rf%rG#UXd z#FXb(La?+7@`V^U+FMI3**T4yDFF#ZXU;?IM6Bw#p@kx86Xq&q-1cybR(211`S}V* znO%<4o*ixUE0Pbh+Yz&y$*tl-EYXj4#@j5-Wj6CQ7slhaV>Bq)HZf-lb{<_}t>aYl z&=`I3F_+?^Q~lAB&dSS|O^qS%5er4X>)d^YqM{p>F_t3F+O*!(aZ;%_yJJ}DE$sT^ zD?V+F1o)k|;MJA7`df*pD~TA{i+^wLEi5h3gr(29e5~cw@g{21H}^GSsQD@#%k03a zK9?s{0JjBaTq z%7|3eul{k|8$TQf8qMtCiY(ub>dVMH!d3$^aEg9r8e~r>3sXIyah&#Of9~35eqFVQ>knQg8ZBr~gYpRT*COY|4$vZssNa2NxUeYfsm!1qND_;I$wR~eah0d%+M7?x^JA+$)Ce~Rg zeqN7OxBK8sNnuySGL7AXp>`pLB^Uz@)H+Fq#6*xz^WQ%C8FYh2c}ibM$objs+y-d? zrX=r$2HB8GQAT(a-w^I+Es60?fl37;e}5$RjTuFMKXp%mne_VmrD+=0@u#&VHEO>T z0+aDh{lgzr?z>~c5JWEZg`onQ5xvC~Pg`I34~`FcnLIpC<-1wExH5^!-;y8S-GaK$ zqV%<$D)?4;qGGHu8a=-ztvXSqxh#zCt;e8A_h?gwd4CR;I%At`%CO^gi0;$9($Z`nsRqjuU6#in|WCc2vnFl7_u}-ps18Z*4Id%R4g&)zX z=u-}T0Ym3Y-i-H&S?xF}yw?AdonDV+mwfb*odRY)h;UL3);X$Jjcc$Zn&D^A3CtT} z(yDV3RddXi$VJUPVhedH^S0)1&)Bbgt@+Paok?^h;$k*W0Cbh`vG2mpVU2}c99a5HuH!aSi! z`nGbfL^TymSO0$QBNCccZm*uW{Nh09Z~MGCeOOU2RMqHJ-N&DuF-2n_ObxbNZG*JV zbI(4ArNKZ@CUt-@eo_k@7Mxy(MarP*DVP^#5Z;ZCqEYjzxIeI@q|R4zFEvIRGSVU% z$duRe?0xKK+(*?VWjN^l{Is8>%$ zZ+M=HCS<3MQ`&8i7~}*7hNPrD|Jpj|yihO~({IdOBM?%{!ygU%^BJyBmS%6`!UkVo zL^v<&C;4Th7tx1l!)WXNrYFSMljXe=FPsxEl#gW6l0I%9R?<>^G5~ze5H_V;gf+ny zkoSHZ-~~LeKBBjvGOTE0$zT3w3P}2At4ce)1Y^c=mw9(lJ+3FzO|?53ToOlD?jbsQ z5vy<+b*YLnYm1m9*uo+Hv$3$6AsTswxYOo$!QDU1@_I;r+|0PE$m%;+gL_=h`{M0G z<%5f$DRD1rkyN$KcaWOd?Z>Vcr0Itq->o9Q2%tOr{?NT>&{g$V>kWg|J-0^vg*>mq zXDCk~jYn^7od`Ep|5+kxII7RTuS?Tx=nETO{85~G=6slBjlci%kz`5LkHx;b8HlZh zw*1dWnq*D}N{}lP?*^3Sl#PuDO{Q#n_};J|DU39cPe7s2pX@nCXO~n(FReYqJ3s!S zxpR+QJYxy(_V`@?XTfn8#(w-Z6!{lnk#x%5?42|OsX85_8tK`R_Ov3I#G8T%~|m5^dSLk z=E+zY@@x=EdFQ?R+(^!|Odf9!syD1W>9@W&hWlp@K0RyhEXqPgul#0a-Iymp?(Z8+ zedpt^fW(v;4&6%_BXA z4ML%iVq3UBLjtrypnLM(5fbb$$>*yu%nuPX34Rq^>h*W~m(1Af3XeCtwBOBnb(dcg z+c1f(KCz$tT8{k$O(PYvpV-y?HCzAn)o{Gqea*A+gt|&S*q!p*I7C$ro)~UpMuq~z zD|2*bHB0PErq1`Q`F1;cdmrI%ATwI3T;F3jc(Op`_q zG9GZ(b!$5`zCYFbU0gY*arcOL7%Z11HI8N< zcq<&EOTU~%Z3Q#_Ew?K+2p9%*Mv-*1Nf&fk%@LxhKX;1l5O|Iu>j}ovw{mq96>@dX zRyxG|0z=J$nFIqD!E-Q&?67!glaAo1mOtCUh7{Ar?dWVzC&DU-cGcQD zdZs=K!wc!qJbJ4aoRX@L zBRa?Q9N7R5#0tl=(2)H*61@~nW?QcNN)aonJBtDj!>d+B8l-Vjc1vu()AGLsOg;z= z3z>Lgn+88SWz5<$r*2$j5F6$glpX51lvo`8iT|m8vPVVVa|jx z&hfX2>kf%tAM?<=>xP+`#7lZs61$5|7J_%%!KyPj!t#T}j$H#+@?leTQwL&WsN$BN zuXS}6RGLD|V8HiN%M-zT^@+Hmns8IP+?%IVh@_upzIr!I+-a7r=-%NBXw*Op0`LK3 zG5fdG`C@Axy?d+8VQLq(qkUTD+FNVrN5Q|J6R&jh2Lv)Ole+5pGloEZZQ79>m7YGM zSPJ1GRDQtW?r9jb{g**e3Mr>PHrRWagZ|ku4kjL;JOdL~Id05kc*CA+ui@= zieS-e>hskR-1I9Sx7b4i6p>2LP#vgtG6;8vGL>E3$NPQ$J2r~XGQDNg;Sw=& zC}lz+3@Sq%I2q-97R&9|8Ij2^?^DGQK_oiqZS2$!-rzVqn=~d~TS{n&I+svxt4dWO zT?K0)JEx>9E7saW8h!5+MmAkC`g~v*@ z6VKn0>eZdon>BH(O$mACnxk3D?vSlCFFnvZ#+&hUs)Wr!aP{<@|oc^G>bJk59^xhmz!RA%|K_$o)V`D@gVs>@bSmXVID_PQXp znfja8U01+t3V!o{8ZKi~G@#q$KrAH-Ks3$G{Qo}H|N1ijJMsgZDgOmM1O$Fi0>0CX zpbAzXhYbP@PV;~=*nn7eQGjoT2b9nGFNg-PpHT$a@?7JL7I&pmkmclS7#Y#zRYg_`D0h47O z&|%88tXNh8{Yk$@@*HA-B9r#tDkY$>!U#Ie`j1TupjRn@;(ykyyld-zJ{@qm!UG~I zxR#ZxV8CEi5JXV?ANc~bS9*;MYtkTvifc5iynmg!XpIr%SN*R#E?|3&2QVs~N02d=N!1;GdfNGr)gc$|K#-y*M=Ra9B4#cmk-naoQuS*cWnE3C4 F{|nTN-B$nr diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4c5803d13..ac33e9944 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 2fe81a7d9..fbd7c5158 100755 --- a/gradlew +++ b/gradlew @@ -82,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -129,6 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/gradlew.bat b/gradlew.bat index 9109989e3..a9f778a7a 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -84,6 +84,7 @@ set CMD_LINE_ARGS=%* set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% diff --git a/worldedit-core/build.gradle.kts b/worldedit-core/build.gradle.kts index f18e45a3e..5d965a63d 100644 --- a/worldedit-core/build.gradle.kts +++ b/worldedit-core/build.gradle.kts @@ -10,7 +10,7 @@ plugins { id("net.ltgt.apt-idea") id("antlr") id("com.mendhak.gradlecrowdin") - kotlin("jvm") version "1.3.61" + kotlin("jvm") version "1.3.72" } repositories { diff --git a/worldedit-core/doctools/build.gradle.kts b/worldedit-core/doctools/build.gradle.kts index 0fba2e7f2..a9b2a7439 100644 --- a/worldedit-core/doctools/build.gradle.kts +++ b/worldedit-core/doctools/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - kotlin("jvm") version "1.3.41" + kotlin("jvm") version "1.3.72" application } diff --git a/worldedit-libs/core/build.gradle.kts b/worldedit-libs/core/build.gradle.kts index 128dab86c..d78841df8 100644 --- a/worldedit-libs/core/build.gradle.kts +++ b/worldedit-libs/core/build.gradle.kts @@ -14,5 +14,5 @@ dependencies { "shade"("org.enginehub.piston:core:${Versions.PISTON}") "shade"("org.enginehub.piston.core-ap:runtime:${Versions.PISTON}") "shade"("org.enginehub.piston:default-impl:${Versions.PISTON}") - "shade"("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.61") + "shade"("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72") } From d3afc9c65d4fd8137d00c45cc27d269573ae20e4 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 2 Jul 2020 14:34:05 +0100 Subject: [PATCH 07/18] Update to p2 5.12.2 and implement clear pipeline --- .../plotsquared/FaweRegionManager.java | 82 +++++++++++++++++++ .../regions/plotsquared/PlotSetBiome.java | 2 +- .../plotsquared/PlotSquaredFeature.java | 3 +- worldedit-core/build.gradle.kts | 2 +- 4 files changed, 85 insertions(+), 4 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/FaweRegionManager.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/FaweRegionManager.java index 7fe036c90..78da2d18b 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/FaweRegionManager.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/FaweRegionManager.java @@ -2,14 +2,22 @@ package com.boydti.fawe.bukkit.regions.plotsquared; import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.TaskManager; +import com.plotsquared.core.configuration.Settings; +import com.plotsquared.core.generator.HybridPlotManager; +import com.plotsquared.core.generator.HybridPlotWorld; import com.plotsquared.core.location.Location; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.PlotAreaTerrainType; +import com.plotsquared.core.plot.PlotAreaType; +import com.plotsquared.core.plot.PlotManager; import com.plotsquared.core.util.RegionManager; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.function.FlatRegionFunction; import com.sk89q.worldedit.function.biome.BiomeReplace; import com.sk89q.worldedit.function.operation.ForwardExtentCopy; @@ -21,7 +29,12 @@ import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypes; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.util.Set; import static org.bukkit.Bukkit.getWorld; @@ -65,6 +78,75 @@ public class FaweRegionManager extends RegionManager { return true; } + @Override + public boolean notifyClear(PlotManager manager) { + if (!(manager instanceof HybridPlotManager)) { + return false; + } + final HybridPlotWorld hpw = ((HybridPlotManager) manager).getHybridPlotWorld(); + return hpw.getType() != PlotAreaType.AUGMENTED || hpw.getTerrain() == PlotAreaTerrainType.NONE; + } + + @Override + public boolean handleClear(final Plot plot, final Runnable whenDone, final PlotManager manager) { + if (!(manager instanceof HybridPlotManager)) { + return false; + } + TaskManager.IMP.async(() -> { + synchronized (FaweRegionManager.class) { + final HybridPlotWorld hybridPlotWorld = ((HybridPlotManager) manager).getHybridPlotWorld(); + EditSession editSession = new EditSessionBuilder(BukkitAdapter.adapt(getWorld(hybridPlotWorld.getWorldName()))).checkMemory(false).fastmode(true).limitUnlimited().changeSetNull().autoQueue(false).build(); + + if (!hybridPlotWorld.PLOT_SCHEMATIC || !Settings.Schematics.PASTE_ON_TOP) { + final BlockState bedrock; + final BlockState air = BlockTypes.AIR.getDefaultState(); + if (hybridPlotWorld.PLOT_BEDROCK) { + bedrock = BlockTypes.BEDROCK.getDefaultState(); + } else { + bedrock = air; + } + + final Pattern filling = hybridPlotWorld.MAIN_BLOCK.toPattern(); + final Pattern plotfloor = hybridPlotWorld.TOP_BLOCK.toPattern(); + + BlockVector3 pos1 = plot.getBottomAbs().getBlockVector3(); + BlockVector3 pos2 = plot.getExtendedTopAbs().getBlockVector3(); + + Region bedrockRegion = new CuboidRegion(pos1.withY(0), pos2.withY(0)); + Region fillingRegion = new CuboidRegion(pos1.withY(1), pos2.withY(hybridPlotWorld.PLOT_HEIGHT - 1)); + Region floorRegion = new CuboidRegion(pos1.withY(hybridPlotWorld.PLOT_HEIGHT), + pos2.withY(hybridPlotWorld.PLOT_HEIGHT)); + Region airRegion = new CuboidRegion(pos1.withY(hybridPlotWorld.PLOT_HEIGHT + 1), + pos2.withY(manager.getWorldHeight())); + + editSession.setBlocks(bedrockRegion, bedrock); + editSession.setBlocks(fillingRegion, filling); + editSession.setBlocks(floorRegion, plotfloor); + editSession.setBlocks(airRegion, air); + } + + if (hybridPlotWorld.PLOT_SCHEMATIC) { + File schematicFile = new File(hybridPlotWorld.getRoot(), "plot.schem"); + if (!schematicFile.exists()) { + schematicFile = new File(hybridPlotWorld.getRoot(), "plot.schematic"); + } + BlockVector3 to = plot.getBottomAbs().getBlockVector3().withY(Settings.Schematics.PASTE_ON_TOP ? hybridPlotWorld.SCHEM_Y : 1); + try { + Clipboard clip = ClipboardFormats.findByFile(schematicFile).getReader(new FileInputStream(schematicFile)).read(); + clip.paste(editSession, to, true, true, true); + } catch (IOException e) { + e.printStackTrace(); + } + } + + editSession.flushQueue(); + + TaskManager.IMP.task(whenDone); + } + }); + return true; + } + @Override public void swap(final Location pos1, final Location pos2, final Location pos3, final Location pos4, final Runnable whenDone) { TaskManager.IMP.async(() -> { diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/PlotSetBiome.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/PlotSetBiome.java index b0374799d..30ed06ff2 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/PlotSetBiome.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/PlotSetBiome.java @@ -45,7 +45,7 @@ public class PlotSetBiome extends Command { } @Override - public CompletableFuture execute(final PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) throws CommandException { + public CompletableFuture execute(final PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) throws CommandException { final Plot plot = check(player.getCurrentPlot(), Captions.NOT_IN_PLOT); checkTrue(plot.isOwner(player.getUUID()) || Permissions .hasPermission(player, "plots.admin.command.generatebiome"), Captions.NO_PLOT_PERMS); diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/PlotSquaredFeature.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/PlotSquaredFeature.java index 02242021e..e51494aed 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/PlotSquaredFeature.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/PlotSquaredFeature.java @@ -5,11 +5,11 @@ import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.regions.FaweMask; import com.boydti.fawe.regions.FaweMaskManager; import com.boydti.fawe.regions.general.RegionFilter; +import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.command.MainCommand; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.database.DBFunc; -import com.plotsquared.core.generator.HybridPlotManager; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; @@ -18,7 +18,6 @@ import com.plotsquared.core.plot.flag.implementations.NoWorldeditFlag; import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.WEManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; diff --git a/worldedit-core/build.gradle.kts b/worldedit-core/build.gradle.kts index 5d965a63d..41dac87ff 100644 --- a/worldedit-core/build.gradle.kts +++ b/worldedit-core/build.gradle.kts @@ -59,7 +59,7 @@ dependencies { "compile"("com.github.intellectualsites.plotsquared:PlotSquared-API:latest") { isTransitive = false } - "compile"("com.plotsquared:PlotSquared-Core:5.11.2") { + "compile"("com.plotsquared:PlotSquared-Core:5.12.2") { isTransitive = false } implementation(kotlin("stdlib-jdk8", "1.3.61")) From b58877a57b3998fe9bb2e0579acac16bb553e1c4 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 2 Jul 2020 14:51:09 +0100 Subject: [PATCH 08/18] Use BlockType not BlockState --- .../bukkit/regions/plotsquared/FaweRegionManager.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/FaweRegionManager.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/FaweRegionManager.java index 78da2d18b..4660c20e4 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/FaweRegionManager.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/regions/plotsquared/FaweRegionManager.java @@ -29,7 +29,7 @@ import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.World; 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.File; @@ -98,10 +98,10 @@ public class FaweRegionManager extends RegionManager { EditSession editSession = new EditSessionBuilder(BukkitAdapter.adapt(getWorld(hybridPlotWorld.getWorldName()))).checkMemory(false).fastmode(true).limitUnlimited().changeSetNull().autoQueue(false).build(); if (!hybridPlotWorld.PLOT_SCHEMATIC || !Settings.Schematics.PASTE_ON_TOP) { - final BlockState bedrock; - final BlockState air = BlockTypes.AIR.getDefaultState(); + final BlockType bedrock; + final BlockType air = BlockTypes.AIR; if (hybridPlotWorld.PLOT_BEDROCK) { - bedrock = BlockTypes.BEDROCK.getDefaultState(); + bedrock = BlockTypes.BEDROCK; } else { bedrock = air; } From 18c9da372c8e3ab3f27e1fd053c80592a5dc2753 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 2 Jul 2020 18:16:15 +0100 Subject: [PATCH 09/18] GetBlocks should default to air not reserved --- .../bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java | 5 ++++- .../adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java | 5 ++++- .../adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java | 5 ++++- .../beta/implementation/blocks/CharGetBlocks.java | 12 ++++++++++-- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java index ae871b419..c2c4395d1 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java @@ -563,10 +563,13 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks { ChunkSection section = getSections()[layer]; // Section is null, return empty array if (section == null) { - return FaweCache.IMP.EMPTY_CHAR_4096; + data = new char[4096]; + Arrays.fill(data, (char) 1); + return data; } if (data == null || data == FaweCache.IMP.EMPTY_CHAR_4096) { data = new char[4096]; + Arrays.fill(data, (char) 1); } DelegateLock lock = BukkitAdapter_1_14.applyLock(section); synchronized (lock) { diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java index e0cbf7266..e77c06f85 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java @@ -581,10 +581,13 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks { ChunkSection section = getSections()[layer]; // Section is null, return empty array if (section == null) { - return FaweCache.IMP.EMPTY_CHAR_4096; + data = new char[4096]; + Arrays.fill(data, (char) 1); + return data; } if (data == null || data == FaweCache.IMP.EMPTY_CHAR_4096) { data = new char[4096]; + Arrays.fill(data, (char) 1); } DelegateLock lock = BukkitAdapter_1_15_2.applyLock(section); synchronized (lock) { diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java index d6dada109..d09240f6c 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java @@ -552,10 +552,13 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks { ChunkSection section = getSections()[layer]; // Section is null, return empty array if (section == null) { - return FaweCache.IMP.EMPTY_CHAR_4096; + data = new char[4096]; + Arrays.fill(data, (char) 1); + return data; } if (data == null || data == FaweCache.IMP.EMPTY_CHAR_4096) { data = new char[4096]; + Arrays.fill(data, (char) 1); } DelegateLock lock = BukkitAdapter_1_16_1.applyLock(section); synchronized (lock) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java index f38d1bae4..fc2b72b96 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java @@ -2,12 +2,12 @@ package com.boydti.fawe.beta.implementation.blocks; import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.IChunkSet; -import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; +import java.util.Arrays; + public abstract class CharGetBlocks extends CharBlocks implements IChunkGet { @Override @@ -25,6 +25,14 @@ public abstract class CharGetBlocks extends CharBlocks implements IChunkGet { return true; } + public char[] update(int layer, char[] data) { + if (data == null) { + return new char[4096]; + } + Arrays.fill(data, (char) 1); + return data; + } + @Override public boolean trim(boolean aggressive, int layer) { sections[layer] = EMPTY; From f1d41044804c044d17a44db95332796f6f768569 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 2 Jul 2020 22:09:12 +0100 Subject: [PATCH 10/18] Bunch of changes to help masks --- .../adapter/mc1_14/BukkitGetBlocks_1_14.java | 12 ++++++++++++ .../adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java | 12 ++++++++++++ .../adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java | 12 ++++++++++++ .../beta/implementation/blocks/CharGetBlocks.java | 2 +- .../sk89q/worldedit/function/mask/BlockMask.java | 2 +- .../mask/InverseSingleBlockStateMask.java | 15 ++++++++++++--- .../function/mask/SingleBlockTypeMask.java | 2 +- 7 files changed, 51 insertions(+), 6 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java index c2c4395d1..0f5d33fe0 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java @@ -609,6 +609,10 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks { } else { ordinal = adapter.adaptToChar(ibd); } + // Don't read "empty". + if (ordinal == 0) { + ordinal = 1; + } paletteToBlockChars[paletteVal] = ordinal; } data[i] = ordinal; @@ -636,10 +640,18 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks { val = ordinal(palette.a(i), adapter); paletteToOrdinal[i] = val; } + // Don't read "empty". + if (val == 0) { + val = 1; + } data[i] = val; } } else { char ordinal = ordinal(palette.a(0), adapter); + // Don't read "empty". + if (ordinal == 0) { + ordinal = 1; + } Arrays.fill(data, ordinal); } } finally { diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java index e77c06f85..4518420a2 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java @@ -629,6 +629,10 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks { } paletteToBlockChars[paletteVal] = ordinal; } + // Don't read "empty". + if (ordinal == 0) { + ordinal = 1; + } data[i] = ordinal; } } finally { @@ -654,10 +658,18 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks { val = ordinal(palette.a(i), adapter); paletteToOrdinal[i] = val; } + // Don't read "empty". + if (val == 0) { + val = 1; + } data[i] = val; } } else { char ordinal = ordinal(palette.a(0), adapter); + // Don't read "empty". + if (ordinal == 0) { + ordinal = 1; + } Arrays.fill(data, ordinal); } } finally { diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java index d09240f6c..2d5ace231 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java @@ -600,6 +600,10 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks { } paletteToBlockChars[paletteVal] = ordinal; } + // Don't read "empty". + if (ordinal == 0) { + ordinal = 1; + } data[i] = ordinal; } } finally { @@ -625,10 +629,18 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks { val = ordinal(palette.a(i), adapter); paletteToOrdinal[i] = val; } + // Don't read "empty". + if (val == 0) { + val = 1; + } data[i] = val; } } else { char ordinal = ordinal(palette.a(0), adapter); + // Don't read "empty". + if (ordinal == 0) { + ordinal = 1; + } Arrays.fill(data, ordinal); } } finally { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java index fc2b72b96..9f3fd88a8 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java @@ -27,7 +27,7 @@ public abstract class CharGetBlocks extends CharBlocks implements IChunkGet { public char[] update(int layer, char[] data) { if (data == null) { - return new char[4096]; + data = new char[4096]; } Arrays.fill(data, (char) 1); return data; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java index e13026ba7..31259f5dd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java @@ -184,7 +184,7 @@ public class BlockMask extends ABlockMask { } @Override public boolean test(BlockState state) { - return ordinals[state.getOrdinal()]; + return ordinals[state.getOrdinal()] || replacesAir() && state.getOrdinal() <= 3; } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/InverseSingleBlockStateMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/InverseSingleBlockStateMask.java index 0f0ddb907..18812adac 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/InverseSingleBlockStateMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/InverseSingleBlockStateMask.java @@ -3,10 +3,10 @@ package com.sk89q.worldedit.function.mask; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; public class InverseSingleBlockStateMask extends ABlockMask { private final char ordinal; + private final boolean isAir; public BlockState getBlockState() { return BlockState.getFromOrdinal(ordinal); @@ -14,17 +14,26 @@ public class InverseSingleBlockStateMask extends ABlockMask { public InverseSingleBlockStateMask(Extent extent, BlockState state) { super(extent); + isAir = state.isAir(); this.ordinal = state.getOrdinalChar(); } @Override public boolean test(Extent extent, BlockVector3 vector) { - return ordinal != vector.getOrdinal(extent); + int test = vector.getOrdinal(extent); + if (isAir && test == 0) { + return false; + } + return ordinal != test; } @Override public final boolean test(BlockState state) { - return state.getOrdinalChar() != ordinal; + int test = state.getOrdinalChar(); + if (isAir && test == 0) { + return false; + } + return test != ordinal; } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SingleBlockTypeMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SingleBlockTypeMask.java index 466f51c7e..d21eaf28d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SingleBlockTypeMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SingleBlockTypeMask.java @@ -13,7 +13,7 @@ public class SingleBlockTypeMask extends ABlockMask { public SingleBlockTypeMask(Extent extent, BlockType type) { super(extent); isAir = type == BlockTypes.AIR || type == BlockTypes.CAVE_AIR || type == BlockTypes.VOID_AIR; - this.internalId = type.getInternalId(); + this.internalId = type.getInternalId(); } @Override From fae528ab64dca14dc7435b6ae411c98995825d10 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Fri, 3 Jul 2020 13:18:09 +0100 Subject: [PATCH 11/18] add a couple more changes++ Fixes #508 --- .../fawe/beta/implementation/queue/ParallelQueueExtent.java | 4 +++- .../src/main/java/com/sk89q/worldedit/EditSession.java | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java index b68207afe..bab16d39a 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java @@ -157,7 +157,9 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap } // TODO optimize parallel for (BlockVector3 blockVector3 : vset) { - pattern.apply(this, blockVector3, blockVector3); + if (pattern.apply(this, blockVector3, blockVector3)) { + this.changes++; + } } return this.changes; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index e3e38757c..b3679aacb 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -2756,6 +2756,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { BlockVector3 tipv = interpol.getPosition(loop).toBlockPoint(); if (radius == 0) { pattern.apply(this, tipv, tipv); + changes++; } else { vset.add(tipv); } From 63bc151f6cb8fea47dc17f9039ceae3296ecb291 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Fri, 3 Jul 2020 13:27:26 +0100 Subject: [PATCH 12/18] Hopefully allow for unloaded world to be referenced after GC. Possibly fixes #504 --- .../com/sk89q/worldedit/bukkit/BukkitWorld.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index 588071c34..bdfcf27d0 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -55,6 +55,8 @@ import java.lang.ref.WeakReference; import java.nio.file.Path; import java.util.*; import javax.annotation.Nullable; + +import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.TreeType; import org.bukkit.World; @@ -78,7 +80,8 @@ public class BukkitWorld extends AbstractWorld { } } - private final WeakReference worldRef; + private WeakReference worldRef; + private final String worldNameRef; private final WorldNativeAccess worldNativeAccess; /** @@ -88,6 +91,7 @@ public class BukkitWorld extends AbstractWorld { */ public BukkitWorld(World world) { this.worldRef = new WeakReference<>(world); + this.worldNameRef = world.getName(); BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); if (adapter != null) { this.worldNativeAccess = adapter.createWorldNativeAccess(world); @@ -150,7 +154,12 @@ public class BukkitWorld extends AbstractWorld { * @return the world */ public World getWorld() { - return checkNotNull(worldRef.get(), "The world was unloaded and the reference is unavailable"); + World tmp = worldRef.get(); + if (tmp == null) { + tmp = Bukkit.getWorld(worldNameRef); + if (tmp != null) worldRef = new WeakReference<>(tmp); + } + return checkNotNull(tmp, "The world was unloaded and the reference is unavailable"); } /** From ea7897934f93243764ac8e4566e0475557bdf68e Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Fri, 3 Jul 2020 13:49:17 +0100 Subject: [PATCH 13/18] Implement ability to use -w flag on //drain fixes #464 --- .../java/com/sk89q/worldedit/EditSession.java | 15 ++++++++------- .../function/pattern/WaterloggedRemover.java | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index b3679aacb..ce1b78f05 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -63,6 +63,7 @@ import com.sk89q.worldedit.function.block.BlockReplace; import com.sk89q.worldedit.function.block.Naturalizer; import com.sk89q.worldedit.function.generator.ForestGenerator; import com.sk89q.worldedit.function.generator.GardenPatchGenerator; +import com.sk89q.worldedit.function.mask.BlockStateMask; import com.sk89q.worldedit.function.mask.BlockTypeMask; import com.sk89q.worldedit.function.mask.BoundedHeightMask; import com.sk89q.worldedit.function.mask.ExistingBlockMask; @@ -135,6 +136,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -1624,13 +1626,12 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { checkNotNull(origin); checkArgument(radius >= 0, "radius >= 0 required"); - Mask liquidMask; - // Not thread safe, use hardcoded liquidmask -// if (getWorld() != null) { -// liquidMask = getWorld().createLiquidMask(); -// } else { -// } - liquidMask = new BlockTypeMask(this, BlockTypes.LAVA, BlockTypes.WATER); + Mask liquidMask = new BlockTypeMask(this, BlockTypes.LAVA, BlockTypes.WATER); + if (waterlogged) { + Map stateMap = new HashMap<>(); + stateMap.put("waterlogged", "true"); + liquidMask = new MaskUnion(liquidMask, new BlockStateMask(this, stateMap, true)); + } Mask mask = new MaskIntersection( new BoundedHeightMask(0, getWorld().getMaxY()), new RegionMask(new EllipsoidRegion(null, origin, Vector3.at(radius, radius, radius))), diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/WaterloggedRemover.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/WaterloggedRemover.java index 886706f08..a8610b80d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/WaterloggedRemover.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/WaterloggedRemover.java @@ -45,7 +45,7 @@ public class WaterloggedRemover extends AbstractExtentPattern { // init for (int i = 0; i < remap.length; i++) { - BlockState state = remap[i]; + BlockState state = BlockTypesCache.states[i]; BlockType type = state.getBlockType(); if (!type.hasProperty(PropertyKey.WATERLOGGED)) { continue; From 28128414815959079496eb9833383d335cebe37d Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Fri, 3 Jul 2020 14:01:16 +0100 Subject: [PATCH 14/18] Add -p flag to //drain to allow kelp and watergrass to be removed. properly fixed #464 --- .../java/com/sk89q/worldedit/EditSession.java | 22 ++++++++++++++++++- .../worldedit/command/UtilityCommands.java | 6 +++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index ce1b78f05..f309f27a3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -1623,10 +1623,30 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { * @throws MaxChangedBlocksException thrown if too many blocks are changed */ public int drainArea(BlockVector3 origin, double radius, boolean waterlogged) throws MaxChangedBlocksException { + return drainArea(origin, radius, waterlogged, false); + } + + /** + * Drain nearby pools of water or lava, optionally removed waterlogged states from blocks. + * + * @param origin the origin to drain from, which will search a 3x3 area + * @param radius the radius of the removal, where a value should be 0 or greater + * @param waterlogged true to make waterlogged blocks non-waterlogged as well + * @param plants true to remove underwater plants + * @return number of blocks affected + * @throws MaxChangedBlocksException thrown if too many blocks are changed + */ + public int drainArea(BlockVector3 origin, double radius, boolean waterlogged, boolean plants) throws MaxChangedBlocksException { checkNotNull(origin); checkArgument(radius >= 0, "radius >= 0 required"); - Mask liquidMask = new BlockTypeMask(this, BlockTypes.LAVA, BlockTypes.WATER); + Mask liquidMask; + if (plants) { + liquidMask = new BlockTypeMask(this, BlockTypes.LAVA, BlockTypes.WATER, + BlockTypes.KELP_PLANT, BlockTypes.KELP, BlockTypes.SEAGRASS, BlockTypes.TALL_SEAGRASS); + } else { + liquidMask = new BlockTypeMask(this, BlockTypes.LAVA, BlockTypes.WATER); + } if (waterlogged) { Map stateMap = new HashMap<>(); stateMap.put("waterlogged", "true"); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index 58e20bc6c..b320dc300 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -326,11 +326,13 @@ public class UtilityCommands { @Arg(desc = "The radius to drain") Expression radiusExp, @Switch(name = 'w', desc = "Also un-waterlog blocks") - boolean waterlogged) throws WorldEditException { + boolean waterlogged, + @Switch(name = 'p', desc = "Also remove water plants") + boolean plants) throws WorldEditException { double radius = radiusExp.evaluate(); radius = Math.max(0, radius); we.checkMaxRadius(radius); - int affected = editSession.drainArea(session.getPlacementPosition(actor), radius, waterlogged); + int affected = editSession.drainArea(session.getPlacementPosition(actor), radius, waterlogged, plants); actor.printInfo(TranslatableComponent.of("worldedit.drain.drained", TextComponent.of(affected))); return affected; } From 9e25c736a0156d451d8f6096dbfbfbfc39790401 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Fri, 3 Jul 2020 14:12:43 +0100 Subject: [PATCH 15/18] Add new blocks to BlockTypes --- .../worldedit/world/block/BlockTypes.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java index a2e73ae26..e38247c68 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypes.java @@ -56,6 +56,7 @@ public final class BlockTypes { @Nullable public static final BlockType ACTIVATOR_RAIL = init(); @Nullable public static final BlockType AIR = init(); @Nullable public static final BlockType ALLIUM = init(); + @Nullable public static final BlockType ANCIENT_DEBRIS = init(); @Nullable public static final BlockType ANDESITE = init(); @Nullable public static final BlockType ANDESITE_SLAB = init(); @Nullable public static final BlockType ANDESITE_STAIRS = init(); @@ -68,6 +69,7 @@ public final class BlockTypes { @Nullable public static final BlockType BAMBOO_SAPLING = init(); @Nullable public static final BlockType BARREL = init(); @Nullable public static final BlockType BARRIER = init(); + @Nullable public static final BlockType BASALT = init(); @Nullable public static final BlockType BEACON = init(); @Nullable public static final BlockType BEDROCK = init(); @Nullable public static final BlockType BEE_NEST = init(); @@ -101,6 +103,10 @@ public final class BlockTypes { @Nullable public static final BlockType BLACK_TERRACOTTA = init(); @Nullable public static final BlockType BLACK_WALL_BANNER = init(); @Nullable public static final BlockType BLACK_WOOL = init(); + @Nullable public static final BlockType BLACKSTONE = init(); + @Nullable public static final BlockType BLACKSTONE_SLAB = init(); + @Nullable public static final BlockType BLACKSTONE_STAIRS = init(); + @Nullable public static final BlockType BLACKSTONE_WALL = init(); @Nullable public static final BlockType BLAST_FURNACE = init(); @Nullable public static final BlockType BLUE_BANNER = init(); @Nullable public static final BlockType BLUE_BED = init(); @@ -154,9 +160,12 @@ public final class BlockTypes { @Nullable public static final BlockType CARVED_PUMPKIN = init(); @Nullable public static final BlockType CAULDRON = init(); @Nullable public static final BlockType CAVE_AIR = init(); + @Nullable public static final BlockType CHAIN = init(); @Nullable public static final BlockType CHAIN_COMMAND_BLOCK = init(); @Nullable public static final BlockType CHEST = init(); @Nullable public static final BlockType CHIPPED_ANVIL = init(); + @Nullable public static final BlockType CHISELED_NETHER_BRICKS = init(); + @Nullable public static final BlockType CHISELED_POLISHED_BLACKSTONE = init(); @Nullable public static final BlockType CHISELED_QUARTZ_BLOCK = init(); @Nullable public static final BlockType CHISELED_RED_SANDSTONE = init(); @Nullable public static final BlockType CHISELED_SANDSTONE = init(); @@ -178,10 +187,29 @@ public final class BlockTypes { @Nullable public static final BlockType COMPOSTER = init(); @Nullable public static final BlockType CONDUIT = init(); @Nullable public static final BlockType CORNFLOWER = init(); + @Nullable public static final BlockType CRACKED_NETHER_BRICKS = init(); + @Nullable public static final BlockType CRACKED_POLISHED_BLACKSTONE_BRICKS = init(); @Nullable public static final BlockType CRACKED_STONE_BRICKS = init(); @Nullable public static final BlockType CRAFTING_TABLE = init(); @Nullable public static final BlockType CREEPER_HEAD = init(); @Nullable public static final BlockType CREEPER_WALL_HEAD = init(); + @Nullable public static final BlockType CRIMSON_BUTTON = init(); + @Nullable public static final BlockType CRIMSON_DOOR = init(); + @Nullable public static final BlockType CRIMSON_FENCE = init(); + @Nullable public static final BlockType CRIMSON_FENCE_GATE = init(); + @Nullable public static final BlockType CRIMSON_FUNGUS = init(); + @Nullable public static final BlockType CRIMSON_HYPHAE = init(); + @Nullable public static final BlockType CRIMSON_NYLIUM = init(); + @Nullable public static final BlockType CRIMSON_PLANKS = init(); + @Nullable public static final BlockType CRIMSON_PRESSURE_PLATE = init(); + @Nullable public static final BlockType CRIMSON_ROOTS = init(); + @Nullable public static final BlockType CRIMSON_SIGN = init(); + @Nullable public static final BlockType CRIMSON_SLAB = init(); + @Nullable public static final BlockType CRIMSON_STAIRS = init(); + @Nullable public static final BlockType CRIMSON_STEM = init(); + @Nullable public static final BlockType CRIMSON_TRAPDOOR = init(); + @Nullable public static final BlockType CRIMSON_WALL_SIGN = init(); + @Nullable public static final BlockType CRYING_OBSIDIAN = init(); @Nullable public static final BlockType CUT_RED_SANDSTONE = init(); @Nullable public static final BlockType CUT_RED_SANDSTONE_SLAB = init(); @Nullable public static final BlockType CUT_SANDSTONE = init(); @@ -278,6 +306,7 @@ public final class BlockTypes { @Nullable public static final BlockType FLOWER_POT = init(); @Nullable public static final BlockType FROSTED_ICE = init(); @Nullable public static final BlockType FURNACE = init(); + @Nullable public static final BlockType GILDED_BLACKSTONE = init(); @Nullable public static final BlockType GLASS = init(); @Nullable public static final BlockType GLASS_PANE = init(); @Nullable public static final BlockType GLOWSTONE = init(); @@ -405,6 +434,7 @@ public final class BlockTypes { @Nullable public static final BlockType LIME_TERRACOTTA = init(); @Nullable public static final BlockType LIME_WALL_BANNER = init(); @Nullable public static final BlockType LIME_WOOL = init(); + @Nullable public static final BlockType LODESTONE = init(); @Nullable public static final BlockType LOOM = init(); @Nullable public static final BlockType MAGENTA_BANNER = init(); @Nullable public static final BlockType MAGENTA_BED = init(); @@ -437,10 +467,13 @@ public final class BlockTypes { @Nullable public static final BlockType NETHER_BRICK_STAIRS = init(); @Nullable public static final BlockType NETHER_BRICK_WALL = init(); @Nullable public static final BlockType NETHER_BRICKS = init(); + @Nullable public static final BlockType NETHER_GOLD_ORE = init(); @Nullable public static final BlockType NETHER_PORTAL = init(); @Nullable public static final BlockType NETHER_QUARTZ_ORE = init(); + @Nullable public static final BlockType NETHER_SPROUTS = init(); @Nullable public static final BlockType NETHER_WART = init(); @Nullable public static final BlockType NETHER_WART_BLOCK = init(); + @Nullable public static final BlockType NETHERITE_BLOCK = init(); @Nullable public static final BlockType NETHERRACK = init(); @Nullable public static final BlockType NOTE_BLOCK = init(); @Nullable public static final BlockType OAK_BUTTON = init(); @@ -498,6 +531,17 @@ public final class BlockTypes { @Nullable public static final BlockType POLISHED_ANDESITE = init(); @Nullable public static final BlockType POLISHED_ANDESITE_SLAB = init(); @Nullable public static final BlockType POLISHED_ANDESITE_STAIRS = init(); + @Nullable public static final BlockType POLISHED_BASALT = init(); + @Nullable public static final BlockType POLISHED_BLACKSTONE = init(); + @Nullable public static final BlockType POLISHED_BLACKSTONE_BRICK_SLAB = init(); + @Nullable public static final BlockType POLISHED_BLACKSTONE_BRICK_STAIRS = init(); + @Nullable public static final BlockType POLISHED_BLACKSTONE_BRICK_WALL = init(); + @Nullable public static final BlockType POLISHED_BLACKSTONE_BRICKS = init(); + @Nullable public static final BlockType POLISHED_BLACKSTONE_BUTTON = init(); + @Nullable public static final BlockType POLISHED_BLACKSTONE_PRESSURE_PLATE = init(); + @Nullable public static final BlockType POLISHED_BLACKSTONE_SLAB = init(); + @Nullable public static final BlockType POLISHED_BLACKSTONE_STAIRS = init(); + @Nullable public static final BlockType POLISHED_BLACKSTONE_WALL = init(); @Nullable public static final BlockType POLISHED_DIORITE = init(); @Nullable public static final BlockType POLISHED_DIORITE_SLAB = init(); @Nullable public static final BlockType POLISHED_DIORITE_STAIRS = init(); @@ -515,6 +559,8 @@ public final class BlockTypes { @Nullable public static final BlockType POTTED_BROWN_MUSHROOM = init(); @Nullable public static final BlockType POTTED_CACTUS = init(); @Nullable public static final BlockType POTTED_CORNFLOWER = init(); + @Nullable public static final BlockType POTTED_CRIMSON_FUNGUS = init(); + @Nullable public static final BlockType POTTED_CRIMSON_ROOTS = init(); @Nullable public static final BlockType POTTED_DANDELION = init(); @Nullable public static final BlockType POTTED_DARK_OAK_SAPLING = init(); @Nullable public static final BlockType POTTED_DEAD_BUSH = init(); @@ -529,6 +575,8 @@ public final class BlockTypes { @Nullable public static final BlockType POTTED_RED_MUSHROOM = init(); @Nullable public static final BlockType POTTED_RED_TULIP = init(); @Nullable public static final BlockType POTTED_SPRUCE_SAPLING = init(); + @Nullable public static final BlockType POTTED_WARPED_FUNGUS = init(); + @Nullable public static final BlockType POTTED_WARPED_ROOTS = init(); @Nullable public static final BlockType POTTED_WHITE_TULIP = init(); @Nullable public static final BlockType POTTED_WITHER_ROSE = init(); @Nullable public static final BlockType POWERED_RAIL = init(); @@ -558,6 +606,7 @@ public final class BlockTypes { @Nullable public static final BlockType PURPUR_SLAB = init(); @Nullable public static final BlockType PURPUR_STAIRS = init(); @Nullable public static final BlockType QUARTZ_BLOCK = init(); + @Nullable public static final BlockType QUARTZ_BRICKS = init(); @Nullable public static final BlockType QUARTZ_PILLAR = init(); @Nullable public static final BlockType QUARTZ_SLAB = init(); @Nullable public static final BlockType QUARTZ_STAIRS = init(); @@ -594,6 +643,7 @@ public final class BlockTypes { @Nullable public static final BlockType REDSTONE_WIRE = init(); @Nullable public static final BlockType REPEATER = init(); @Nullable public static final BlockType REPEATING_COMMAND_BLOCK = init(); + @Nullable public static final BlockType RESPAWN_ANCHOR = init(); @Nullable public static final BlockType ROSE_BUSH = init(); @Nullable public static final BlockType SAND = init(); @Nullable public static final BlockType SANDSTONE = init(); @@ -604,6 +654,7 @@ public final class BlockTypes { @Nullable public static final BlockType SEA_LANTERN = init(); @Nullable public static final BlockType SEA_PICKLE = init(); @Nullable public static final BlockType SEAGRASS = init(); + @Nullable public static final BlockType SHROOMLIGHT = init(); @Nullable public static final BlockType SHULKER_BOX = init(); @Nullable public static final BlockType SKELETON_SKULL = init(); @Nullable public static final BlockType SKELETON_WALL_SKULL = init(); @@ -623,7 +674,13 @@ public final class BlockTypes { @Nullable public static final BlockType SMOOTH_STONE_SLAB = init(); @Nullable public static final BlockType SNOW = init(); @Nullable public static final BlockType SNOW_BLOCK = init(); + @Nullable public static final BlockType SOUL_CAMPFIRE = init(); + @Nullable public static final BlockType SOUL_FIRE = init(); + @Nullable public static final BlockType SOUL_LANTERN = init(); @Nullable public static final BlockType SOUL_SAND = init(); + @Nullable public static final BlockType SOUL_SOIL = init(); + @Nullable public static final BlockType SOUL_TORCH = init(); + @Nullable public static final BlockType SOUL_WALL_TORCH = init(); @Nullable public static final BlockType SPAWNER = init(); @Nullable public static final BlockType SPONGE = init(); @Nullable public static final BlockType SPRUCE_BUTTON = init(); @@ -656,6 +713,8 @@ public final class BlockTypes { @Nullable public static final BlockType STRIPPED_ACACIA_WOOD = init(); @Nullable public static final BlockType STRIPPED_BIRCH_LOG = init(); @Nullable public static final BlockType STRIPPED_BIRCH_WOOD = init(); + @Nullable public static final BlockType STRIPPED_CRIMSON_HYPHAE = init(); + @Nullable public static final BlockType STRIPPED_CRIMSON_STEM = init(); @Nullable public static final BlockType STRIPPED_DARK_OAK_LOG = init(); @Nullable public static final BlockType STRIPPED_DARK_OAK_WOOD = init(); @Nullable public static final BlockType STRIPPED_JUNGLE_LOG = init(); @@ -664,6 +723,8 @@ public final class BlockTypes { @Nullable public static final BlockType STRIPPED_OAK_WOOD = init(); @Nullable public static final BlockType STRIPPED_SPRUCE_LOG = init(); @Nullable public static final BlockType STRIPPED_SPRUCE_WOOD = init(); + @Nullable public static final BlockType STRIPPED_WARPED_HYPHAE = init(); + @Nullable public static final BlockType STRIPPED_WARPED_STEM = init(); @Nullable public static final BlockType STRUCTURE_BLOCK = init(); @Nullable public static final BlockType STRUCTURE_VOID = init(); @Nullable public static final BlockType SUGAR_CANE = init(); @@ -671,6 +732,7 @@ public final class BlockTypes { @Nullable public static final BlockType SWEET_BERRY_BUSH = init(); @Nullable public static final BlockType TALL_GRASS = init(); @Nullable public static final BlockType TALL_SEAGRASS = init(); + @Nullable public static final BlockType TARGET = init(); @Nullable public static final BlockType TERRACOTTA = init(); @Nullable public static final BlockType TNT = init(); @Nullable public static final BlockType TORCH = init(); @@ -682,10 +744,31 @@ public final class BlockTypes { @Nullable public static final BlockType TUBE_CORAL_FAN = init(); @Nullable public static final BlockType TUBE_CORAL_WALL_FAN = init(); @Nullable public static final BlockType TURTLE_EGG = init(); + @Nullable public static final BlockType TWISTING_VINES = init(); + @Nullable public static final BlockType TWISTING_VINES_PLANT = init(); @Nullable public static final BlockType VINE = init(); @Nullable public static final BlockType VOID_AIR = init(); @Nullable public static final BlockType WALL_TORCH = init(); + @Nullable public static final BlockType WARPED_BUTTON = init(); + @Nullable public static final BlockType WARPED_DOOR = init(); + @Nullable public static final BlockType WARPED_FENCE = init(); + @Nullable public static final BlockType WARPED_FENCE_GATE = init(); + @Nullable public static final BlockType WARPED_FUNGUS = init(); + @Nullable public static final BlockType WARPED_HYPHAE = init(); + @Nullable public static final BlockType WARPED_NYLIUM = init(); + @Nullable public static final BlockType WARPED_PLANKS = init(); + @Nullable public static final BlockType WARPED_PRESSURE_PLATE = init(); + @Nullable public static final BlockType WARPED_ROOTS = init(); + @Nullable public static final BlockType WARPED_SIGN = init(); + @Nullable public static final BlockType WARPED_SLAB = init(); + @Nullable public static final BlockType WARPED_STAIRS = init(); + @Nullable public static final BlockType WARPED_STEM = init(); + @Nullable public static final BlockType WARPED_TRAPDOOR = init(); + @Nullable public static final BlockType WARPED_WALL_SIGN = init(); + @Nullable public static final BlockType WARPED_WART_BLOCK = init(); @Nullable public static final BlockType WATER = init(); + @Nullable public static final BlockType WEEPING_VINES = init(); + @Nullable public static final BlockType WEEPING_VINES_PLANT = init(); @Nullable public static final BlockType WET_SPONGE = init(); @Nullable public static final BlockType WHEAT = init(); @Nullable public static final BlockType WHITE_BANNER = init(); From f7d375c76ce5b504d4d361f594ab4dd4fa96f5f9 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Fri, 3 Jul 2020 16:29:27 +0100 Subject: [PATCH 16/18] Lazy heightmap range fix --- .../com/sk89q/worldedit/math/convolution/HeightMap.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/convolution/HeightMap.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/convolution/HeightMap.java index 432445223..ea4d57ff3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/convolution/HeightMap.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/convolution/HeightMap.java @@ -286,7 +286,12 @@ public class HeightMap { if (existing.getBlockType().getMaterial().isMovementBlocker()) { int y0 = newHeight - 1; for (int setY = y0, getY = curHeight - 1; setY >= curHeight; setY--, getY--) { - BlockState get = session.getBlock(xr, getY, zr); + BlockState get; + if (getY >= 0 && getY < 256) { + get = session.getBlock(xr, getY, zr); + } else { + get = BlockTypes.AIR.getDefaultState(); + } if (get != BlockTypes.AIR.getDefaultState()) tmpBlock = get; session.setBlock(xr, setY, zr, tmpBlock); ++blocksChanged; From e2ab87cc073e7d2f52573902566747451d0c4cf1 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Fri, 3 Jul 2020 16:45:28 +0100 Subject: [PATCH 17/18] lazy //deform AIOOB fix. Fixes #495 --- .../src/main/java/com/sk89q/worldedit/EditSession.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index f309f27a3..6905ce17f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -2506,8 +2506,15 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { int yv = (int) (y.getValue() * unit.getY() + zero2.getY()); int zv = (int) (z.getValue() * unit.getZ() + zero2.getZ()); + BlockState get; + if (yv >= 0 && yv < 265) { + get = getBlock(xv, yv, zv); + } else { + get = BlockTypes.AIR.getDefaultState(); + } + // read block from world - return setBlock(position, getBlock(xv, yv, zv)); + return setBlock(position, get); } catch (EvaluationException e) { throw new RuntimeException(e); } From 77204df3f06b8bf512178e23512bb392212f7586 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Fri, 3 Jul 2020 16:56:20 +0100 Subject: [PATCH 18/18] prevent players being teleported down a single block after some edits --- .../extension/platform/AbstractPlayerActor.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java index 040c5bb74..4419f34f6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java @@ -161,12 +161,16 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { Extent world = searchPos.getExtent(); int x = searchPos.getBlockX(); int y = Math.max(0, searchPos.getBlockY()); + int origY = y; + int yPlusSearchHeight = y + WorldEdit.getInstance().getConfiguration().defaultVerticalHeight; int z = searchPos.getBlockZ(); + int maxY = Math.min(255, yPlusSearchHeight) + 2; + byte free = 0; BlockVector3 mutablePos = MutableBlockVector3.ZERO; - while (y <= world.getMaximumPoint().getBlockY() + 2) { + while (y <= maxY) { if (!world.getBlock(mutablePos.setComponents(x, y, z)).getBlockType().getMaterial() .isMovementBlocker()) { ++free; @@ -175,10 +179,10 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { } if (free == 2) { - final BlockVector3 pos = mutablePos.setComponents(x, y - 2, z); - final BlockState state = world.getBlock(pos); - setPosition(Vector3.at(x + 0.5, y - 2 + BlockTypeUtil.centralTopLimit(state), z + 0.5)); - return; + if (y - 1 != origY) { + setPosition(Vector3.at(x + 0.5, y - 2 + 1, z + 0.5)); + return; + } } ++y;