From 6e4f8770b603bea6ba9bcb2cebbb3894072bcee0 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Mon, 27 May 2024 17:54:36 +0100 Subject: [PATCH] Add (untested) processing capability and second passes where appropriate --- .../ext/fawe/v1_19_R3/PaperweightAdapter.java | 10 +- .../FaweMutableBlockPlaceContext.java | 6 +- .../fawe/v1_19_R3/PaperweightFaweAdapter.java | 19 +- .../PaperweightPlacementStateProcessor.java | 38 +++- .../ext/fawe/v1_20_R1/PaperweightAdapter.java | 10 +- .../FaweMutableBlockPlaceContext.java | 6 +- .../fawe/v1_20_R1/PaperweightFaweAdapter.java | 19 +- .../PaperweightPlacementStateProcessor.java | 38 +++- .../ext/fawe/v1_20_R2/PaperweightAdapter.java | 10 +- .../FaweMutableBlockPlaceContext.java | 6 +- .../fawe/v1_20_R2/PaperweightFaweAdapter.java | 19 +- .../PaperweightPlacementStateProcessor.java | 38 +++- .../ext.fawe/v1_20_R3/PaperweightAdapter.java | 10 +- .../FaweMutableBlockPlaceContext.java | 6 +- .../fawe/v1_20_R3/PaperweightFaweAdapter.java | 19 +- .../PaperweightPlacementStateProcessor.java | 38 +++- .../ext.fawe/v1_20_R4/PaperweightAdapter.java | 10 +- .../FaweMutableBlockPlaceContext.java | 6 +- .../fawe/v1_20_R4/PaperweightFaweAdapter.java | 20 +- .../fawe/v1_20_R4/PaperweightLevelProxy.java | 13 +- .../PaperweightPlacementStateProcessor.java | 57 +++-- .../bukkit/BukkitServerInterface.java | 9 +- .../bukkit/adapter/BukkitImplAdapter.java | 7 +- .../core/configuration/Settings.java | 5 + .../processor/PlacementStateProcessor.java | 204 ++++++++++++++---- .../core/queue/IBatchProcessor.java | 3 +- .../implementation/ParallelQueueExtent.java | 10 +- .../sk89q/worldedit/EditSessionBuilder.java | 49 ++++- .../com/sk89q/worldedit/LocalSession.java | 1 + .../worldedit/command/RegionCommands.java | 7 +- .../extension/platform/Platform.java | 7 +- .../function/mask/BlockTypeMask.java | 2 +- .../com/sk89q/worldedit/util/SideEffect.java | 17 +- 33 files changed, 559 insertions(+), 160 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightAdapter.java index 22c5a07b2..9e9fe4654 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_19_R3/PaperweightAdapter.java @@ -780,12 +780,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.NEIGHBORS, + //FAWE start - FAWE-supported side effects + SideEffect.HISTORY, + SideEffect.HEIGHTMAPS, SideEffect.LIGHTING, - SideEffect.VALIDATION, - SideEffect.ENTITY_AI, - SideEffect.EVENTS, - SideEffect.UPDATE + SideEffect.NEIGHBORS + //FAWE end ); @Override diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/FaweMutableBlockPlaceContext.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/FaweMutableBlockPlaceContext.java index 7968f9546..a61680063 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/FaweMutableBlockPlaceContext.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/FaweMutableBlockPlaceContext.java @@ -16,7 +16,11 @@ import javax.annotation.Nullable; public class FaweMutableBlockPlaceContext extends BlockPlaceContext { - private static final BlockHitResult DEFAULT_BLOCK_HIT = new BlockHitResult(Vec3.ZERO, Direction.NORTH, BlockPos.ZERO, false); + private static final BlockHitResult DEFAULT_BLOCK_HIT = new BlockHitResult(new Vec3( + Integer.MAX_VALUE, + Integer.MAX_VALUE, + Integer.MAX_VALUE + ), Direction.NORTH, BlockPos.ZERO, false); private final ServerLevel level; private BlockHitResult hitResult = null; private Direction direction = null; diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweAdapter.java index 6f8c056bf..0fc156a31 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweAdapter.java @@ -13,6 +13,7 @@ import com.fastasyncworldedit.core.util.NbtUtils; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Sets; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.bukkit.BukkitAdapter; @@ -283,9 +284,16 @@ public final class PaperweightFaweAdapter extends FaweAdapter SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( + SideEffect.HISTORY, + SideEffect.HEIGHTMAPS, + SideEffect.LIGHTING, + SideEffect.NEIGHBORS + ); + @Override public Set getSupportedSideEffects() { - return SideEffectSet.defaults().getSideEffectsToApply(); + return SUPPORTED_SIDE_EFFECTS; } @Override @@ -606,8 +614,13 @@ public final class PaperweightFaweAdapter extends FaweAdapter crossChunkSecondPasses, + PaperweightLevelProxy proxyLevel + ) { + super(extent, mask, secondPass, includeUnedited, crossChunkSecondPasses); + this.proxyLevel = proxyLevel; + this.mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel); } @Override @@ -85,12 +104,19 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor if (child == getExtent()) { return this; } - return new PaperweightPlacementStateProcessor(child, mask, includeUnedited); + return new PaperweightPlacementStateProcessor(child, mask, secondPass, includeUnedited); } @Override public PlacementStateProcessor fork() { - return new PaperweightPlacementStateProcessor(extent, mask, includeUnedited); + return new PaperweightPlacementStateProcessor( + extent, + mask, + secondPass, + includeUnedited, + crossChunkSecondPasses, + proxyLevel + ); } } diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightAdapter.java index b40c12b1a..6a8db61e7 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R1/PaperweightAdapter.java @@ -831,12 +831,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.NEIGHBORS, + //FAWE start - FAWE-supported side effects + SideEffect.HISTORY, + SideEffect.HEIGHTMAPS, SideEffect.LIGHTING, - SideEffect.VALIDATION, - SideEffect.ENTITY_AI, - SideEffect.EVENTS, - SideEffect.UPDATE + SideEffect.NEIGHBORS + //FAWE end ); @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/FaweMutableBlockPlaceContext.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/FaweMutableBlockPlaceContext.java index 5b0a42632..261e974c7 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/FaweMutableBlockPlaceContext.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/FaweMutableBlockPlaceContext.java @@ -16,7 +16,11 @@ import javax.annotation.Nullable; public class FaweMutableBlockPlaceContext extends BlockPlaceContext { - private static final BlockHitResult DEFAULT_BLOCK_HIT = new BlockHitResult(Vec3.ZERO, Direction.NORTH, BlockPos.ZERO, false); + private static final BlockHitResult DEFAULT_BLOCK_HIT = new BlockHitResult(new Vec3( + Integer.MAX_VALUE, + Integer.MAX_VALUE, + Integer.MAX_VALUE + ), Direction.NORTH, BlockPos.ZERO, false); private final ServerLevel level; private BlockHitResult hitResult = null; private Direction direction = null; diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java index 2e96c82ef..8f3223711 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java @@ -13,6 +13,7 @@ import com.fastasyncworldedit.core.util.NbtUtils; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Sets; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.bukkit.BukkitAdapter; @@ -283,9 +284,16 @@ public final class PaperweightFaweAdapter extends FaweAdapter SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( + SideEffect.HISTORY, + SideEffect.HEIGHTMAPS, + SideEffect.LIGHTING, + SideEffect.NEIGHBORS + ); + @Override public Set getSupportedSideEffects() { - return SideEffectSet.defaults().getSideEffectsToApply(); + return SUPPORTED_SIDE_EFFECTS; } @Override @@ -606,8 +614,13 @@ public final class PaperweightFaweAdapter extends FaweAdapter crossChunkSecondPasses, + PaperweightLevelProxy proxyLevel + ) { + super(extent, mask, secondPass, includeUnedited, crossChunkSecondPasses); + this.proxyLevel = proxyLevel; + this.mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel); } @Override @@ -85,12 +104,19 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor if (child == getExtent()) { return this; } - return new PaperweightPlacementStateProcessor(child, mask, includeUnedited); + return new PaperweightPlacementStateProcessor(child, mask, secondPass, includeUnedited); } @Override public PlacementStateProcessor fork() { - return new PaperweightPlacementStateProcessor(extent, mask, includeUnedited); + return new PaperweightPlacementStateProcessor( + extent, + mask, + secondPass, + includeUnedited, + crossChunkSecondPasses, + proxyLevel + ); } } diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightAdapter.java index b73e6d06e..7bf3a5f4e 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightAdapter.java @@ -780,12 +780,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.NEIGHBORS, + //FAWE start - FAWE-supported side effects + SideEffect.HISTORY, + SideEffect.HEIGHTMAPS, SideEffect.LIGHTING, - SideEffect.VALIDATION, - SideEffect.ENTITY_AI, - SideEffect.EVENTS, - SideEffect.UPDATE + SideEffect.NEIGHBORS + //FAWE end ); @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/FaweMutableBlockPlaceContext.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/FaweMutableBlockPlaceContext.java index 4f6828429..a05be1dbe 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/FaweMutableBlockPlaceContext.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/FaweMutableBlockPlaceContext.java @@ -16,7 +16,11 @@ import javax.annotation.Nullable; public class FaweMutableBlockPlaceContext extends BlockPlaceContext { - private static final BlockHitResult DEFAULT_BLOCK_HIT = new BlockHitResult(Vec3.ZERO, Direction.NORTH, BlockPos.ZERO, false); + private static final BlockHitResult DEFAULT_BLOCK_HIT = new BlockHitResult(new Vec3( + Integer.MAX_VALUE, + Integer.MAX_VALUE, + Integer.MAX_VALUE + ), Direction.NORTH, BlockPos.ZERO, false); private final ServerLevel level; private BlockHitResult hitResult = null; private Direction direction = null; diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweAdapter.java index 308a7f6cc..a1bcc0448 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweAdapter.java @@ -13,6 +13,7 @@ import com.fastasyncworldedit.core.util.NbtUtils; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Sets; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.bukkit.BukkitAdapter; @@ -286,9 +287,16 @@ public final class PaperweightFaweAdapter extends FaweAdapter SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( + SideEffect.HISTORY, + SideEffect.HEIGHTMAPS, + SideEffect.LIGHTING, + SideEffect.NEIGHBORS + ); + @Override public Set getSupportedSideEffects() { - return SideEffectSet.defaults().getSideEffectsToApply(); + return SUPPORTED_SIDE_EFFECTS; } @Override @@ -609,8 +617,13 @@ public final class PaperweightFaweAdapter extends FaweAdapter crossChunkSecondPasses, + PaperweightLevelProxy proxyLevel + ) { + super(extent, mask, secondPass, includeUnedited, crossChunkSecondPasses); + this.proxyLevel = proxyLevel; + this.mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel); } @Override @@ -85,12 +104,19 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor if (child == getExtent()) { return this; } - return new PaperweightPlacementStateProcessor(child, mask, includeUnedited); + return new PaperweightPlacementStateProcessor(child, mask, secondPass, includeUnedited); } @Override public PlacementStateProcessor fork() { - return new PaperweightPlacementStateProcessor(extent, mask, includeUnedited); + return new PaperweightPlacementStateProcessor( + extent, + mask, + secondPass, + includeUnedited, + crossChunkSecondPasses, + proxyLevel + ); } } diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightAdapter.java index 899c6e0c4..1313dec20 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightAdapter.java @@ -780,12 +780,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.NEIGHBORS, + //FAWE start - FAWE-supported side effects + SideEffect.HISTORY, + SideEffect.HEIGHTMAPS, SideEffect.LIGHTING, - SideEffect.VALIDATION, - SideEffect.ENTITY_AI, - SideEffect.EVENTS, - SideEffect.UPDATE + SideEffect.NEIGHBORS + //FAWE end ); @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/FaweMutableBlockPlaceContext.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/FaweMutableBlockPlaceContext.java index 36aab0805..13034892c 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/FaweMutableBlockPlaceContext.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/FaweMutableBlockPlaceContext.java @@ -16,7 +16,11 @@ import javax.annotation.Nullable; public class FaweMutableBlockPlaceContext extends BlockPlaceContext { - private static final BlockHitResult DEFAULT_BLOCK_HIT = new BlockHitResult(Vec3.ZERO, Direction.NORTH, BlockPos.ZERO, false); + private static final BlockHitResult DEFAULT_BLOCK_HIT = new BlockHitResult(new Vec3( + Integer.MAX_VALUE, + Integer.MAX_VALUE, + Integer.MAX_VALUE + ), Direction.NORTH, BlockPos.ZERO, false); private final ServerLevel level; private BlockHitResult hitResult = null; private Direction direction = null; diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweAdapter.java index e46e54617..6c162630e 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweAdapter.java @@ -13,6 +13,7 @@ import com.fastasyncworldedit.core.util.NbtUtils; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Sets; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.bukkit.BukkitAdapter; @@ -285,9 +286,16 @@ public final class PaperweightFaweAdapter extends FaweAdapter SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( + SideEffect.HISTORY, + SideEffect.HEIGHTMAPS, + SideEffect.LIGHTING, + SideEffect.NEIGHBORS + ); + @Override public Set getSupportedSideEffects() { - return SideEffectSet.defaults().getSideEffectsToApply(); + return SUPPORTED_SIDE_EFFECTS; } @Override @@ -607,8 +615,13 @@ public final class PaperweightFaweAdapter extends FaweAdapter crossChunkSecondPasses, + PaperweightLevelProxy proxyLevel + ) { + super(extent, mask, secondPass, includeUnedited, crossChunkSecondPasses); + this.proxyLevel = proxyLevel; + this.mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel); } @Override @@ -85,12 +104,19 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor if (child == getExtent()) { return this; } - return new PaperweightPlacementStateProcessor(child, mask, includeUnedited); + return new PaperweightPlacementStateProcessor(child, mask, secondPass, includeUnedited); } @Override public PlacementStateProcessor fork() { - return new PaperweightPlacementStateProcessor(extent, mask, includeUnedited); + return new PaperweightPlacementStateProcessor( + extent, + mask, + secondPass, + includeUnedited, + crossChunkSecondPasses, + proxyLevel + ); } } diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightAdapter.java index e629c4611..73fd8d7f5 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightAdapter.java @@ -857,12 +857,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( - SideEffect.NEIGHBORS, + //FAWE start - FAWE-supported side effects + SideEffect.HISTORY, + SideEffect.HEIGHTMAPS, SideEffect.LIGHTING, - SideEffect.VALIDATION, - SideEffect.ENTITY_AI, - SideEffect.EVENTS, - SideEffect.UPDATE + SideEffect.NEIGHBORS + //FAWE end ); @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/FaweMutableBlockPlaceContext.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/FaweMutableBlockPlaceContext.java index 609ad796d..b4d4802dc 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/FaweMutableBlockPlaceContext.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/FaweMutableBlockPlaceContext.java @@ -16,7 +16,11 @@ import javax.annotation.Nullable; public class FaweMutableBlockPlaceContext extends BlockPlaceContext { - private static final BlockHitResult DEFAULT_BLOCK_HIT = new BlockHitResult(Vec3.ZERO, Direction.NORTH, BlockPos.ZERO, false); + private static final BlockHitResult DEFAULT_BLOCK_HIT = new BlockHitResult(new Vec3( + Integer.MAX_VALUE, + Integer.MAX_VALUE, + Integer.MAX_VALUE + ), Direction.NORTH, BlockPos.ZERO, false); private final ServerLevel level; private BlockHitResult hitResult = null; private Direction direction = null; diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweAdapter.java index 827199895..bdd961ecc 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweAdapter.java @@ -13,6 +13,7 @@ import com.fastasyncworldedit.core.util.NbtUtils; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Sets; import com.mojang.serialization.Codec; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.blocks.BaseItemStack; @@ -35,7 +36,6 @@ import com.sk89q.worldedit.registry.state.IntegerProperty; 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.util.concurrency.LazyReference; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.nbt.BinaryTag; @@ -295,9 +295,16 @@ public final class PaperweightFaweAdapter extends FaweAdapter SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet( + SideEffect.HISTORY, + SideEffect.HEIGHTMAPS, + SideEffect.LIGHTING, + SideEffect.NEIGHBORS + ); + @Override public Set getSupportedSideEffects() { - return SideEffectSet.defaults().getSideEffectsToApply(); + return SUPPORTED_SIDE_EFFECTS; } @Override @@ -631,8 +638,13 @@ public final class PaperweightFaweAdapter extends FaweAdapter crossChunkSecondPasses, + PaperweightLevelProxy proxyLevel + ) { + super(extent, mask, secondPass, includeUnedited, crossChunkSecondPasses); + this.proxyLevel = proxyLevel; + this.mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel); } @Override protected char getStateAtFor( - int x, - int y, - int z, - BlockState state, - Vector3 clickPos, - Direction clickedFaceDirection, - BlockVector3 clickedBlock + int x, int y, int z, BlockState state, Vector3 clickPos, Direction clickedFaceDirection, BlockVector3 clickedBlock ) { Block block = ((PaperweightBlockMaterial) state.getMaterial()).getBlock(); Vec3 pos = new Vec3(clickPos.x(), clickPos.y(), clickPos.z()); net.minecraft.core.Direction side = net.minecraft.core.Direction.valueOf(clickedFaceDirection.toString()); BlockPos blockPos = new BlockPos(clickedBlock.x(), clickedBlock.y(), clickedBlock.z()); - net.minecraft.world.level.block.state.BlockState newState = block.getStateForPlacement(mutableBlockPlaceContext.withSetting( - new BlockHitResult(pos, side, blockPos, false), + net.minecraft.world.level.block.state.BlockState newState = block.getStateForPlacement(mutableBlockPlaceContext.withSetting(new BlockHitResult(pos, side, blockPos, false), side.getOpposite() )); - return newState == null ? BlockTypesCache.ReservedIDs.AIR : - adapter.ibdIDToOrdinal(Block.BLOCK_STATE_REGISTRY.getId(newState)); + return newState == null ? BlockTypesCache.ReservedIDs.AIR : adapter.ibdIDToOrdinal(Block.BLOCK_STATE_REGISTRY.getId( + newState)); } @Override @@ -85,12 +93,19 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor if (child == getExtent()) { return this; } - return new PaperweightPlacementStateProcessor(child, mask, includeUnedited); + return new PaperweightPlacementStateProcessor(child, mask, secondPass, includeUnedited); } @Override public PlacementStateProcessor fork() { - return new PaperweightPlacementStateProcessor(extent, mask, includeUnedited); + return new PaperweightPlacementStateProcessor( + extent, + mask, + secondPass, + includeUnedited, + crossChunkSecondPasses, + proxyLevel + ); } } 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 725e2b6b7..a7ba552da 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 @@ -314,8 +314,13 @@ public class BukkitServerInterface extends AbstractPlatform implements MultiUser } @Override - public PlacementStateProcessor getPlatformPlacementProcessor(Extent extent, BlockTypeMask mask, boolean includeUnedited) { - return this.plugin.getBukkitImplAdapter().getPlatformPlacementProcessor(extent, mask, includeUnedited); + public PlacementStateProcessor getPlatformPlacementProcessor( + Extent extent, + BlockTypeMask mask, + boolean secondPass, + boolean includeUnedited + ) { + return this.plugin.getBukkitImplAdapter().getPlatformPlacementProcessor(extent, mask, secondPass, includeUnedited); } //FAWE end } 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 b6e06e439..07924c8e9 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 @@ -368,7 +368,12 @@ public interface BukkitImplAdapter extends IBukkitAdapter { * Returns an {@link PlacementStateProcessor} instance for processing placed blocks to "fix" them. * @since TODO */ - default PlacementStateProcessor getPlatformPlacementProcessor(Extent extent, BlockTypeMask mask, boolean includeUnedited) { + default PlacementStateProcessor getPlatformPlacementProcessor( + Extent extent, + BlockTypeMask mask, + boolean secondPass, + boolean includeUnedited + ) { return null; } //FAWE end diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java index 33c8c94f0..800189c76 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java @@ -784,6 +784,11 @@ public class Settings extends Config { }) public boolean UNSTUCK_ON_GENERATE = true; + @Comment({ + "If edits that have a block update processor applied should also perform a second pass", + }) + public boolean PERFORM_SECOND_UPDATE_PASS = true; + } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/PlacementStateProcessor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/PlacementStateProcessor.java index d49942dbc..61d68c9bd 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/PlacementStateProcessor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/PlacementStateProcessor.java @@ -1,9 +1,10 @@ package com.fastasyncworldedit.core.extent.processor; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; +import com.fastasyncworldedit.core.math.IntPair; +import com.fastasyncworldedit.core.math.IntTriple; import com.fastasyncworldedit.core.math.MutableBlockVector3; import com.fastasyncworldedit.core.math.MutableVector3; -import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; @@ -27,23 +28,39 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; +import java.util.ArrayDeque; import java.util.EnumSet; +import java.util.Queue; import java.util.Set; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.stream.Collectors; -public abstract class PlacementStateProcessor extends AbstractDelegateExtent implements IBatchProcessor, Filter, Pattern { +public abstract class PlacementStateProcessor extends AbstractDelegateExtent implements IBatchProcessor, Pattern { private static final Direction[] NESW = new Direction[]{Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; private static volatile boolean SETUP = false; private static BlockTypeMask DEFAULT_MASK = null; + private static BlockTypeMask SECOND_MASK = null; + private static BlockTypeMask REQUIRES_SECOND_PASS = null; protected final Extent extent; protected final BlockTypeMask mask; protected final boolean includeUnedited; + protected final boolean secondPass; + protected final Queue crossChunkSecondPasses; private final MutableVector3 clickPos = new MutableVector3(); private final MutableBlockVector3 clickedBlock = new MutableBlockVector3(); - public PlacementStateProcessor(Extent extent, BlockTypeMask mask, boolean includeUnedited) { + /** + * Process/extent/pattern for performing block updates, e.g. stair shape and glass pane connections + * + * @param extent Extent to use + * @param mask Mask of blocks to perform updates on + * @param secondPass Perform a second pass typically around stairs. May perform cross-chunk second passes too + * @param includeUnedited if unedited blocks should be processed as well + * @since TODO + */ + public PlacementStateProcessor(Extent extent, BlockTypeMask mask, boolean secondPass, boolean includeUnedited) { super(extent); // Required here as child classes are located within adapters and will therefore be statically accessed on startup, // meaning we attempt to access BlockTypes class before it is correctly initialised. @@ -56,12 +73,29 @@ public abstract class PlacementStateProcessor extends AbstractDelegateExtent imp } this.extent = extent; this.mask = mask == null ? DEFAULT_MASK : mask; + this.secondPass = secondPass; this.includeUnedited = includeUnedited; + this.crossChunkSecondPasses = secondPass ? null : new ConcurrentLinkedQueue<>(); + } + + protected PlacementStateProcessor( + Extent extent, + BlockTypeMask mask, + boolean secondPass, + boolean includeUnedited, + Queue crossChunkSecondPasses + ) { + super(extent); + this.extent = extent; + this.mask = mask; + this.secondPass = secondPass; + this.includeUnedited = includeUnedited; + this.crossChunkSecondPasses = crossChunkSecondPasses; } private static void setup() { - DEFAULT_MASK = new BlockTypeMask(new NullExtent()); - DEFAULT_MASK.add( + REQUIRES_SECOND_PASS = new BlockTypeMask(new NullExtent()); + REQUIRES_SECOND_PASS.add( BlockTypes.IRON_BARS, BlockTypes.GLASS_PANE, BlockTypes.BLACK_STAINED_GLASS_PANE, @@ -80,6 +114,27 @@ public abstract class PlacementStateProcessor extends AbstractDelegateExtent imp BlockTypes.ORANGE_STAINED_GLASS_PANE, BlockTypes.RED_STAINED_GLASS_PANE, BlockTypes.WHITE_STAINED_GLASS_PANE, + BlockTypes.TRIPWIRE, + BlockTypes.TWISTING_VINES_PLANT, + BlockTypes.CAVE_VINES_PLANT, + BlockTypes.WEEPING_VINES_PLANT, + BlockTypes.VINE, + BlockTypes.REDSTONE_WIRE + ); + BlockCategory[] categories = new BlockCategory[]{ + BlockCategories.FENCES, + BlockCategories.FENCE_GATES, + BlockCategories.WALLS, + BlockCategories.CAVE_VINES + }; + for (BlockCategory category : categories) { + if (category != null) { + REQUIRES_SECOND_PASS.add(category.getAll()); + } + } + + DEFAULT_MASK = REQUIRES_SECOND_PASS.copy(); + DEFAULT_MASK.add( BlockTypes.CHORUS_PLANT, BlockTypes.DRIPSTONE_BLOCK, BlockTypes.POINTED_DRIPSTONE, @@ -91,20 +146,20 @@ public abstract class PlacementStateProcessor extends AbstractDelegateExtent imp BlockTypes.CRAFTER, BlockTypes.MUSHROOM_STEM, BlockTypes.BROWN_MUSHROOM_BLOCK, - BlockTypes.RED_MUSHROOM_BLOCK, - BlockTypes.TRIPWIRE, - BlockTypes.TWISTING_VINES_PLANT, - BlockTypes.CAVE_VINES_PLANT, - BlockTypes.WEEPING_VINES_PLANT, - BlockTypes.VINE, - BlockTypes.REDSTONE_WIRE + BlockTypes.RED_MUSHROOM_BLOCK ); - BlockCategory[] categories = new BlockCategory[]{BlockCategories.FENCES, BlockCategories.FENCE_GATES, BlockCategories.STAIRS, BlockCategories.WALLS, BlockCategories.BAMBOO_BLOCKS, BlockCategories.CAVE_VINES, BlockCategories.TALL_FLOWERS}; + categories = new BlockCategory[]{ + BlockCategories.STAIRS, + BlockCategories.BAMBOO_BLOCKS, + BlockCategories.TALL_FLOWERS + }; for (BlockCategory category : categories) { if (category != null) { DEFAULT_MASK.add(category.getAll()); } } + SECOND_MASK = new BlockTypeMask(new NullExtent()); + SECOND_MASK.add(BlockCategories.STAIRS.getAll()); SETUP = true; } @@ -121,57 +176,128 @@ public abstract class PlacementStateProcessor extends AbstractDelegateExtent imp continue; } } + Queue secondPasses = this.secondPass ? new ArrayDeque<>() : null; for (int y = 0, i = 0; y < 16; y++) { int blockY = layerY + y; + // Perform second pass to ensure changes to stairs are propagated to fences, walls, etc. + // Always perform if within chunk boundaries as this is not very costly. + // Only perform outside chunk boundaries if secondPass is not null for (int z = 0; z < 16; z++) { int blockZ = chunkZ + z; for (int x = 0; x < 16; x++, i++) { int blockX = chunkX + x; - char ordinal = set == null ? BlockTypesCache.ReservedIDs.__RESERVED__ : set[i]; - if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { - if (!includeUnedited) { - continue; - } - if (get == null) { - get = iChunkGet.load(layer); - } - ordinal = get[i]; - } - BlockState state = BlockTypesCache.states[ordinal]; - if (!mask.test(state.getBlockType())) { - continue; - } - char newOrdinal = getBlockOrdinal(blockX, blockY, blockZ, state); - if (set == null) { - set = iChunkSet.load(layer); - } - set[i] = newOrdinal; + checkAndPerformUpdate(iChunkGet, iChunkSet, get, set, layer, i, blockX, blockY, blockZ, x, z, secondPasses); } } + if (!secondPass || secondPasses.isEmpty()) { + continue; + } + IntPair pair; + while ((pair = secondPasses.poll()) != null) { + int x = pair.x(); + int z = pair.z(); + int blockX = chunkX + x; + int blockZ = chunkZ + z; + if (x < 0 || x > 15 || z < 0 || z > 15) { + crossChunkSecondPasses.add(new IntTriple(blockX, blockY, blockZ)); + } + int index = (y & 15) << 8 | z << 4 | x; + checkAndPerformUpdate(iChunkGet, iChunkSet, get, set, layer, index, blockX, blockY, blockZ, x, z, null); + } } } return iChunkSet; } + private void checkAndPerformUpdate( + IChunkGet iChunkGet, + IChunkSet iChunkSet, + char[] get, + char[] set, + int layer, + int index, + int blockX, + int blockY, + int blockZ, + int x, + int z, + Queue secondPasses + ) { + char ordinal = set == null ? BlockTypesCache.ReservedIDs.__RESERVED__ : set[index]; + if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { + if (!includeUnedited) { + return; + } + if (get == null) { + get = iChunkGet.load(layer); + } + ordinal = get[index]; + } + BlockState state = BlockTypesCache.states[ordinal]; + if (secondPasses == null && secondPass) { + if (!REQUIRES_SECOND_PASS.test(state.getBlockType())) { + return; + } + } + if (!mask.test(state.getBlockType())) { + return; + } + char newOrdinal = getBlockOrdinal(blockX, blockY, blockZ, state); + if (newOrdinal == ordinal) { + return; + } + if (secondPasses != null && (BlockCategories.STAIRS.contains(state) || secondPass && SECOND_MASK.test(state.getBlockType()))) { + secondPasses.add(new IntPair(x - 1, z)); + secondPasses.add(new IntPair(x + 1, z)); + secondPasses.add(new IntPair(x, z - 1)); + secondPasses.add(new IntPair(x, z + 1)); + } + if (set == null) { + set = iChunkSet.load(layer); + } + set[index] = newOrdinal; + } + @Override public ProcessorScope getScope() { return ProcessorScope.CHANGING_BLOCKS; } + @Override + public void flush() { + IntTriple coords; + while ((coords = crossChunkSecondPasses.poll()) != null) { + BlockState state = extent.getBlock(coords.x(), coords.y(), coords.z()); + char ordinal = state.getOrdinalChar(); + if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { + continue; + } + if (!mask.test(state.getBlockType())) { + continue; + } + char newOrdinal = getBlockOrdinal(coords.x(), coords.y(), coords.z(), state); + if (newOrdinal == ordinal) { + continue; + } + extent.setBlock(coords.x(), coords.y(), coords.z(), BlockTypesCache.states[newOrdinal]); + } + } + @Override public abstract PlacementStateProcessor fork(); // Require block type to avoid duplicate lookup protected abstract char getStateAtFor( - int x, int y, int z, BlockState state, Vector3 clickPos, Direction clickedFaceDirection, BlockVector3 clickedBlock + int x, + int y, + int z, + BlockState state, + Vector3 clickPos, + Direction clickedFaceDirection, + BlockVector3 clickedBlock ); - private char getBlockOrdinal( - final int blockX, - final int blockY, - final int blockZ, - final BlockState state - ) { + private char getBlockOrdinal(final int blockX, final int blockY, final int blockZ, final BlockState state) { EnumSet dirs = Direction.getDirections(state); Direction clickedFaceDirection = null; // This should be always be set by the below. Set states = state.getStates().keySet().stream().map(Property::getName).collect(Collectors.toSet()); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java index 778f85ce4..152833cd4 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java @@ -10,13 +10,14 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BlockTypesCache; import javax.annotation.Nullable; +import java.io.Flushable; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; import java.util.function.Function; -public interface IBatchProcessor { +public interface IBatchProcessor extends Flushable { /** * Process a chunk that has been set. diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java index e88a9ccd3..8faabaf9d 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java @@ -37,6 +37,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import org.apache.logging.log4j.Logger; +import java.io.Flushable; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -135,7 +136,7 @@ public class ParallelQueueExtent extends PassthroughExtent { // if PQE is ever used with PARALLEL_THREADS = 1, or only one chunk is edited, just run sequentially while (chunksIter.hasNext()) { BlockVector2 pos = chunksIter.next(); - getExtent().apply(null, filter, region, pos.getX(), pos.getZ(), full); + getExtent().apply(null, filter, region, pos.x(), pos.z(), full); } } else { final ForkJoinTask[] tasks = IntStream.range(0, size).mapToObj(i -> handler.submit(() -> { @@ -159,11 +160,14 @@ public class ParallelQueueExtent extends PassthroughExtent { break; } final BlockVector2 pos = chunksIter.next(); - chunkX = pos.getX(); - chunkZ = pos.getZ(); + chunkX = pos.x(); + chunkZ = pos.z(); } block = queue.apply(block, newFilter, region, chunkX, chunkZ, full); } + if (newFilter instanceof Flushable flushable) { + flushable.flush(); + } queue.flush(); } catch (Throwable t) { if (t instanceof FaweException) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java index ca6f3b6a5..18d6ee69b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java @@ -65,6 +65,8 @@ import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Identifiable; +import com.sk89q.worldedit.util.SideEffect; +import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.eventbus.EventBus; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; @@ -104,6 +106,7 @@ public final class EditSessionBuilder { private Extent extent; private boolean compiled; private boolean wrapped; + private SideEffectSet sideEffectSet = SideEffectSet.defaults(); private @Nullable World world; @@ -415,6 +418,14 @@ public final class EditSessionBuilder { return setDirty(); } + /** + * Set the side effects to be used with this edit + */ + public EditSessionBuilder setSideEffectSet(@Nullable SideEffectSet sideEffectSet) { + this.sideEffectSet = sideEffectSet; + return setDirty(); + } + /** * Compile the builder to the settings given. Prepares history, limits, lighting, etc. */ @@ -445,6 +456,9 @@ public final class EditSessionBuilder { fastMode = actor.getSession().hasFastMode(); } } + if (fastMode) { + sideEffectSet = SideEffectSet.none(); + } if (checkMemory == null) { checkMemory = actor != null && !this.fastMode; } @@ -491,7 +505,7 @@ public final class EditSessionBuilder { } extent = this.bypassAll = wrapExtent(extent, eventBus, event, EditSession.Stage.BEFORE_CHANGE); this.bypassHistory = this.extent = wrapExtent(bypassAll, eventBus, event, EditSession.Stage.BEFORE_REORDER); - if (!this.fastMode || changeSet != null) { + if (!this.fastMode || this.sideEffectSet.shouldApply(SideEffect.HISTORY) || changeSet != null) { if (changeSet == null) { if (Settings.settings().HISTORY.USE_DISK) { UUID uuid = actor == null ? Identifiable.CONSOLE : actor.getUniqueId(); @@ -546,13 +560,31 @@ public final class EditSessionBuilder { } // There's no need to do the below (and it'll also just be a pain to implement) if we're not placing chunks if (placeChunks) { - if (((relightMode != null && relightMode != RelightMode.NONE) || (relightMode == null && Settings.settings().LIGHTING.MODE > 0))) { - relighter = WorldEdit.getInstance().getPlatformManager() + if (this.sideEffectSet.shouldApply(SideEffect.LIGHTING) && + ((relightMode != null && relightMode != RelightMode.NONE) || (relightMode == null && Settings.settings().LIGHTING.MODE > 0))) { + relighter = WorldEdit + .getInstance() + .getPlatformManager() .queryCapability(Capability.WORLD_EDITING) - .getRelighterFactory().createRelighter(relightMode, world, queue); + .getRelighterFactory() + .createRelighter(relightMode, world, queue); queue.addProcessor(new RelightProcessor(relighter)); } - queue.addProcessor(new HeightmapProcessor(world.getMinY(), world.getMaxY())); + if (this.sideEffectSet.shouldApply(SideEffect.HEIGHTMAPS)) { + queue.addProcessor(new HeightmapProcessor(world.getMinY(), world.getMaxY())); + } + if (this.sideEffectSet.shouldApply(SideEffect.UPDATE) || this.sideEffectSet.shouldApply(SideEffect.NEIGHBORS)) { + queue.addProcessor(WorldEdit + .getInstance() + .getPlatformManager() + .queryCapability(Capability.WORLD_EDITING) + .getPlatformPlacementProcessor( + queue, + null, + Settings.settings().GENERAL.PERFORM_SECOND_UPDATE_PASS, + true + )); + } if (!Settings.settings().EXPERIMENTAL.KEEP_ENTITIES_IN_BLOCKS) { queue.addProcessor(new EntityInBlockRemovingProcessor()); @@ -710,6 +742,13 @@ public final class EditSessionBuilder { return changeSet; } + /** + * Get the SideEffectSet that will be used + */ + public SideEffectSet getSideEffectSet() { + return sideEffectSet; + } + /** * Get the ultimate resultant extent */ 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 5a5fa654e..6f678ed49 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -1730,6 +1730,7 @@ public class LocalSession implements TextureHolder { } builder.command(command); builder.fastMode(!this.sideEffectSet.doesApplyAny()); + builder.setSideEffectSet(this.sideEffectSet); editSession = builder.build(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index 183c9c74d..2a4697a38 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -41,6 +41,7 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.function.GroundFunction; import com.sk89q.worldedit.function.generator.FloraGenerator; +import com.sk89q.worldedit.function.mask.BlockTypeMask; import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.MaskIntersection; @@ -903,7 +904,9 @@ public class RegionCommands { @Confirm(Confirm.Processor.REGION) @Preload(Preload.PreloadCheck.PRELOAD) public int fixblocks( - Actor actor, EditSession editSession, @Selection Region region + Actor actor, EditSession editSession, @Selection Region region, + @Switch(name = 'n', desc = "Do not perform a second pass ") + boolean noSecondPass ) { int affected = editSession.setBlocks( region, @@ -911,7 +914,7 @@ public class RegionCommands { .getInstance() .getPlatformManager() .queryCapability(Capability.WORLD_EDITING) - .getPlatformPlacementProcessor(editSession, null, true) + .getPlatformPlacementProcessor(editSession, null, !noSecondPass, true) ); if (affected != 0) { actor.print(Caption.of("worldedit.set.done", TextComponent.of(affected))); 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 50ef475d6..ca3e014b2 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 @@ -284,7 +284,12 @@ public interface Platform extends Keyed { * Returns an {@link PlacementStateProcessor} instance for processing placed blocks to "fix" them. * @since TODO */ - default PlacementStateProcessor getPlatformPlacementProcessor(Extent extent, BlockTypeMask mask, boolean includeUnedited) { + default PlacementStateProcessor getPlatformPlacementProcessor( + Extent extent, + BlockTypeMask mask, + boolean secondPass, + boolean includeUnedited + ) { return null; } //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java index 17f1419e5..38d547930 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java @@ -149,7 +149,7 @@ public class BlockTypeMask extends AbstractExtentMask { } @Override - public Mask copy() { + public BlockTypeMask copy() { return new BlockTypeMask(getExtent(), types.clone(), hasAir); } 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 3c3910be7..9cc92fbf1 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 @@ -19,23 +19,30 @@ package com.sk89q.worldedit.util; +import com.fastasyncworldedit.core.configuration.Settings; + import java.util.Locale; public enum SideEffect { - LIGHTING(State.ON, true), - NEIGHBORS(State.ON, true), - UPDATE(State.ON, true), + //FAWE start - adjust defaults, add history and heightmaps + HISTORY(State.ON, true), + HEIGHTMAPS(State.ON, true), + LIGHTING(State.OFF, true), // Off defaults to falling through to config + NEIGHBORS(State.OFF, true), + UPDATE(State.OFF, true), + //FAWE end VALIDATION(State.OFF, true), ENTITY_AI(State.OFF, true), EVENTS(State.OFF, true), /** * Internal use only. */ - POI_UPDATE(State.ON, false), + POI_UPDATE(State.OFF, false), /** * Internal use only. */ - NETWORK(State.ON, false); + NETWORK(State.OFF, false); + //FAWE end private final String displayName; private final String description;