3
0
Mirror von https://github.com/IntellectualSites/FastAsyncWorldEdit.git synchronisiert 2024-11-16 16:10:07 +01:00

Add (untested) processing capability and second passes where appropriate

Dieser Commit ist enthalten in:
dordsor21 2024-05-27 17:54:36 +01:00
Ursprung 39fa07e572
Commit dc8841d3e1
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 1E53E88969FFCF0B
53 geänderte Dateien mit 1306 neuen und 673 gelöschten Zeilen

Datei anzeigen

@ -857,12 +857,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
}
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
SideEffect.NEIGHBORS,
SideEffect.LIGHTING,
SideEffect.VALIDATION,
SideEffect.ENTITY_AI,
SideEffect.EVENTS,
SideEffect.UPDATE
//FAWE start - FAWE-supported side effects
SideEffect.HISTORY,
SideEffect.HEIGHTMAPS,
SideEffect.LIGHTING,
SideEffect.NEIGHBORS
//FAWE end
);
@Override

Datei anzeigen

@ -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;

Datei anzeigen

@ -4,7 +4,7 @@ import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.entity.LazyBaseEntity;
import com.fastasyncworldedit.core.extent.processor.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
@ -14,6 +14,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;
@ -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.formatting.text.Component;
import com.sk89q.worldedit.world.RegenOptions;
import com.sk89q.worldedit.world.biome.BiomeType;
@ -294,9 +294,16 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
return state.toBaseBlock();
}
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
SideEffect.HISTORY,
SideEffect.HEIGHTMAPS,
SideEffect.LIGHTING,
SideEffect.NEIGHBORS
);
@Override
public Set<SideEffect> getSupportedSideEffects() {
return SideEffectSet.defaults().getSideEffectsToApply();
return SUPPORTED_SIDE_EFFECTS;
}
@Override
@ -445,7 +452,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
}
public net.minecraft.world.level.block.state.BlockState adapt(BlockState blockState) {
return Block.stateById(ordinalToIbdID[blockState.getOrdinal()]);
return Block.stateById(getOrdinalToIbdID()[blockState.getOrdinal()]);
}
@Override
@ -617,8 +624,8 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
}
@Override
public PlacementStateProcessor getPlatformPlacementProcessor(Extent extent, BlockTypeMask mask, boolean includeUnedited) {
return new PaperweightPlacementStateProcessor(extent, mask, includeUnedited);
public PlacementStateProcessor getPlatformPlacementProcessor(Extent extent, BlockTypeMask mask, Region region) {
return new PaperweightPlacementStateProcessor(extent, mask, region);
}
private boolean wasAccessibleSinceLastSave(ChunkHolder holder) {

Datei anzeigen

@ -20,6 +20,7 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
@ -834,7 +835,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
nmsChunk.mustNotSave = false;
nmsChunk.setUnsaved(true);
// send to player
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) {
if (!set
.getSideEffectSet()
.shouldApply(SideEffect.LIGHTING) || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) {
this.send();
}
if (finalizer != null) {

Datei anzeigen

@ -2,12 +2,12 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2;
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extent.Extent;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;
@ -20,17 +20,15 @@ import javax.annotation.Nullable;
public class PaperweightLevelProxy extends ServerLevel {
private PaperweightFaweAdapter adapter;
private Extent extent;
private ServerLevel serverLevel;
private boolean enabled = false;
private PaperweightPlacementStateProcessor processor;
@SuppressWarnings("DataFlowIssue")
public PaperweightLevelProxy() {
private PaperweightLevelProxy() {
super(null, null, null, null, null, null, null, true, 0L, null, true, null, null, null, null);
throw new IllegalStateException("Cannot be instantiated");
}
public static PaperweightLevelProxy getInstance(ServerLevel level, Extent extent) {
public static PaperweightLevelProxy getInstance(PaperweightPlacementStateProcessor processor) {
Unsafe unsafe = ReflectionUtils.getUnsafe();
PaperweightLevelProxy newLevel;
@ -39,45 +37,41 @@ public class PaperweightLevelProxy extends ServerLevel {
} catch (InstantiationException e) {
throw new RuntimeException(e);
}
newLevel.adapter = ((PaperweightFaweAdapter) WorldEditPlugin
.getInstance()
.getBukkitImplAdapter());
newLevel.extent = extent;
newLevel.serverLevel = level;
newLevel.processor = processor;
newLevel.adapter = ((PaperweightFaweAdapter) WorldEditPlugin.getInstance().getBukkitImplAdapter());
return newLevel;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Nullable
@Override
public BlockEntity getBlockEntity(@Nonnull BlockPos blockPos) {
if (!enabled) {
if (blockPos.getX() == Integer.MAX_VALUE) {
return null;
}
BlockEntity tileEntity = this.serverLevel.getChunkAt(blockPos).getBlockEntity(blockPos);
if (tileEntity == null) {
com.sk89q.jnbt.CompoundTag tag = processor.getTileAt(blockPos.getX(), blockPos.getY(), blockPos.getZ());
if (tag == null) {
return null;
}
BlockEntity newEntity = tileEntity.getType().create(blockPos, getBlockState(blockPos));
newEntity.load((CompoundTag) adapter.fromNativeLin(this.extent.getFullBlock(
blockPos.getX(),
blockPos.getY(),
blockPos.getZ()
).getNbtReference().getValue()));
return newEntity;
BlockState state = adapter.adapt(processor.getBlockStateAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
if (!(state.getBlock() instanceof EntityBlock entityBlock)) {
return null;
}
BlockEntity tileEntity = entityBlock.newBlockEntity(blockPos, state);
tileEntity.load((CompoundTag) adapter.fromNative(tag));
return tileEntity;
}
@Override
@Nonnull
public BlockState getBlockState(@Nonnull BlockPos blockPos) {
if (!enabled) {
if (blockPos.getX() == Integer.MAX_VALUE) {
return Blocks.AIR.defaultBlockState();
}
com.sk89q.worldedit.world.block.BlockState state = this.extent.getBlock(blockPos.getX(), blockPos.getY(), blockPos.getZ());
com.sk89q.worldedit.world.block.BlockState state = processor.getBlockStateAt(
blockPos.getX(),
blockPos.getY(),
blockPos.getZ()
);
return adapter.adapt(state);
}
@ -85,7 +79,7 @@ public class PaperweightLevelProxy extends ServerLevel {
@Override
@Nonnull
public FluidState getFluidState(@Nonnull BlockPos pos) {
if (!enabled) {
if (pos.getX() == Integer.MAX_VALUE) {
return Fluids.EMPTY.defaultFluidState();
}
return getBlockState(pos).getFluidState();
@ -94,7 +88,7 @@ public class PaperweightLevelProxy extends ServerLevel {
@SuppressWarnings("unused")
@Override
public boolean isWaterAt(@Nonnull BlockPos pos) {
if (!enabled) {
if (pos.getX() == Integer.MAX_VALUE) {
return false;
}
return getBlockState(pos).getFluidState().is(FluidTags.WATER);

Datei anzeigen

@ -1,26 +1,23 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2;
import com.fastasyncworldedit.core.extent.processor.PlacementStateProcessor;
import com.fastasyncworldedit.core.util.ExtentTraverser;
import com.fastasyncworldedit.core.wrappers.WorldWrapper;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.fastasyncworldedit.core.extent.PlacementStateProcessor;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.BlockTypeMask;
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.world.World;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
public class PaperweightPlacementStateProcessor extends PlacementStateProcessor {
@ -28,33 +25,25 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor
.getInstance()
.getBukkitImplAdapter());
private final FaweMutableBlockPlaceContext mutableBlockPlaceContext;
private final PaperweightLevelProxy proxyLevel;
public PaperweightPlacementStateProcessor(
final Extent extent,
final BlockTypeMask mask,
final boolean includeUnedited
public PaperweightPlacementStateProcessor(Extent extent, BlockTypeMask mask, Region region) {
super(extent, mask, region);
this.proxyLevel = PaperweightLevelProxy.getInstance(this);
this.mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel);
}
private PaperweightPlacementStateProcessor(
Extent extent,
BlockTypeMask mask,
Map<SecondPass, Character> crossChunkSecondPasses,
ThreadLocal<PlacementStateProcessor> threadProcessors,
Region region,
AtomicBoolean finished
) {
super(extent, mask, includeUnedited);
World world;
if (extent.isWorld()) {
world = (World) extent;
} else if (extent instanceof EditSession session) {
world = session.getWorld();
} else if ((world = new ExtentTraverser<>(extent).findAndGet(BukkitWorld.class)) == null) {
throw new UnsupportedOperationException("Cannot find world of extent.");
}
BukkitWorld bukkitWorld;
if (world instanceof WorldWrapper wrapper) {
bukkitWorld = (BukkitWorld) wrapper.getParent();
} else {
bukkitWorld = (BukkitWorld) world;
}
PaperweightLevelProxy proxyLevel = PaperweightLevelProxy.getInstance(
((CraftWorld) bukkitWorld.getWorld()).getHandle(),
extent
);
mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel);
proxyLevel.setEnabled(true);
super(extent, mask, crossChunkSecondPasses, threadProcessors, region, finished);
this.proxyLevel = PaperweightLevelProxy.getInstance(this);
this.mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel);
}
@Override
@ -75,8 +64,8 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor
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 +74,12 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor
if (child == getExtent()) {
return this;
}
return new PaperweightPlacementStateProcessor(child, mask, includeUnedited);
return new PaperweightPlacementStateProcessor(child, mask, region);
}
@Override
public PlacementStateProcessor fork() {
return new PaperweightPlacementStateProcessor(extent, mask, includeUnedited);
return new PaperweightPlacementStateProcessor(extent, mask, postCompleteSecondPasses, threadProcessors, region, finished);
}
}

Datei anzeigen

@ -856,12 +856,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
}
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
SideEffect.NEIGHBORS,
SideEffect.LIGHTING,
SideEffect.VALIDATION,
SideEffect.ENTITY_AI,
SideEffect.EVENTS,
SideEffect.UPDATE
//FAWE start - FAWE-supported side effects
SideEffect.HISTORY,
SideEffect.HEIGHTMAPS,
SideEffect.LIGHTING,
SideEffect.NEIGHBORS
//FAWE end
);
@Override

Datei anzeigen

@ -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;

Datei anzeigen

@ -4,7 +4,7 @@ import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.entity.LazyBaseEntity;
import com.fastasyncworldedit.core.extent.processor.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
@ -14,6 +14,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;
@ -34,7 +35,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.formatting.text.Component;
import com.sk89q.worldedit.world.RegenOptions;
import com.sk89q.worldedit.world.biome.BiomeType;
@ -293,9 +293,16 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
return state.toBaseBlock();
}
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
SideEffect.HISTORY,
SideEffect.HEIGHTMAPS,
SideEffect.LIGHTING,
SideEffect.NEIGHBORS
);
@Override
public Set<SideEffect> getSupportedSideEffects() {
return SideEffectSet.defaults().getSideEffectsToApply();
return SUPPORTED_SIDE_EFFECTS;
}
@Override
@ -444,7 +451,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
}
public net.minecraft.world.level.block.state.BlockState adapt(BlockState blockState) {
return Block.stateById(ordinalToIbdID[blockState.getOrdinal()]);
return Block.stateById(getOrdinalToIbdID()[blockState.getOrdinal()]);
}
@Override
@ -484,7 +491,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
@Override
public boolean canPlaceAt(org.bukkit.World world, BlockVector3 blockVector3, BlockState blockState) {
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(ordinalToIbdID[blockState.getOrdinal()]);
net.minecraft.world.level.block.state.BlockState blockState1 = Block.stateById(getOrdinalToIbdID()[blockState.getOrdinal()]);
return blockState1.hasPostProcess(
getServerLevel(world),
new BlockPos(blockVector3.x(), blockVector3.y(), blockVector3.z())
@ -615,8 +622,8 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
}
@Override
public PlacementStateProcessor getPlatformPlacementProcessor(Extent extent, BlockTypeMask mask, boolean includeUnedited) {
return new PaperweightPlacementStateProcessor(extent, mask, includeUnedited);
public PlacementStateProcessor getPlatformPlacementProcessor(Extent extent, BlockTypeMask mask, Region region) {
return new PaperweightPlacementStateProcessor(extent, mask, region);
}
private boolean wasAccessibleSinceLastSave(ChunkHolder holder) {

Datei anzeigen

@ -20,6 +20,7 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
@ -834,7 +835,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
nmsChunk.mustNotSave = false;
nmsChunk.setUnsaved(true);
// send to player
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) {
if (!set
.getSideEffectSet()
.shouldApply(SideEffect.LIGHTING) || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) {
this.send();
}
if (finalizer != null) {

Datei anzeigen

@ -2,12 +2,12 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3;
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extent.Extent;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;
@ -20,17 +20,15 @@ import javax.annotation.Nullable;
public class PaperweightLevelProxy extends ServerLevel {
private PaperweightFaweAdapter adapter;
private Extent extent;
private ServerLevel serverLevel;
private boolean enabled = false;
private PaperweightPlacementStateProcessor processor;
@SuppressWarnings("DataFlowIssue")
public PaperweightLevelProxy() {
private PaperweightLevelProxy() {
super(null, null, null, null, null, null, null, true, 0L, null, true, null, null, null, null);
throw new IllegalStateException("Cannot be instantiated");
}
public static PaperweightLevelProxy getInstance(ServerLevel level, Extent extent) {
public static PaperweightLevelProxy getInstance(PaperweightPlacementStateProcessor processor) {
Unsafe unsafe = ReflectionUtils.getUnsafe();
PaperweightLevelProxy newLevel;
@ -39,45 +37,41 @@ public class PaperweightLevelProxy extends ServerLevel {
} catch (InstantiationException e) {
throw new RuntimeException(e);
}
newLevel.adapter = ((PaperweightFaweAdapter) WorldEditPlugin
.getInstance()
.getBukkitImplAdapter());
newLevel.extent = extent;
newLevel.serverLevel = level;
newLevel.processor = processor;
newLevel.adapter = ((PaperweightFaweAdapter) WorldEditPlugin.getInstance().getBukkitImplAdapter());
return newLevel;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Nullable
@Override
public BlockEntity getBlockEntity(@Nonnull BlockPos blockPos) {
if (!enabled) {
if (blockPos.getY() == Integer.MAX_VALUE) {
return null;
}
BlockEntity tileEntity = this.serverLevel.getChunkAt(blockPos).getBlockEntity(blockPos);
if (tileEntity == null) {
com.sk89q.jnbt.CompoundTag tag = processor.getTileAt(blockPos.getX(), blockPos.getY(), blockPos.getZ());
if (tag == null) {
return null;
}
BlockEntity newEntity = tileEntity.getType().create(blockPos, getBlockState(blockPos));
newEntity.load((CompoundTag) adapter.fromNativeLin(this.extent.getFullBlock(
blockPos.getX(),
blockPos.getY(),
blockPos.getZ()
).getNbtReference().getValue()));
return newEntity;
BlockState state = adapter.adapt(processor.getBlockStateAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
if (!(state.getBlock() instanceof EntityBlock entityBlock)) {
return null;
}
BlockEntity tileEntity = entityBlock.newBlockEntity(blockPos, state);
tileEntity.load((CompoundTag) adapter.fromNative(tag));
return tileEntity;
}
@Override
@Nonnull
public BlockState getBlockState(@Nonnull BlockPos blockPos) {
if (!enabled) {
if (blockPos.getY() == Integer.MAX_VALUE) {
return Blocks.AIR.defaultBlockState();
}
com.sk89q.worldedit.world.block.BlockState state = this.extent.getBlock(blockPos.getX(), blockPos.getY(), blockPos.getZ());
com.sk89q.worldedit.world.block.BlockState state = processor.getBlockStateAt(
blockPos.getX(),
blockPos.getY(),
blockPos.getZ()
);
return adapter.adapt(state);
}
@ -85,7 +79,7 @@ public class PaperweightLevelProxy extends ServerLevel {
@Override
@Nonnull
public FluidState getFluidState(@Nonnull BlockPos pos) {
if (!enabled) {
if (pos.getY() == Integer.MAX_VALUE) {
return Fluids.EMPTY.defaultFluidState();
}
return getBlockState(pos).getFluidState();
@ -94,7 +88,7 @@ public class PaperweightLevelProxy extends ServerLevel {
@SuppressWarnings("unused")
@Override
public boolean isWaterAt(@Nonnull BlockPos pos) {
if (!enabled) {
if (pos.getY() == Integer.MAX_VALUE) {
return false;
}
return getBlockState(pos).getFluidState().is(FluidTags.WATER);

Datei anzeigen

@ -1,26 +1,23 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3;
import com.fastasyncworldedit.core.extent.processor.PlacementStateProcessor;
import com.fastasyncworldedit.core.util.ExtentTraverser;
import com.fastasyncworldedit.core.wrappers.WorldWrapper;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.fastasyncworldedit.core.extent.PlacementStateProcessor;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.BlockTypeMask;
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.world.World;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
public class PaperweightPlacementStateProcessor extends PlacementStateProcessor {
@ -28,44 +25,30 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor
.getInstance()
.getBukkitImplAdapter());
private final FaweMutableBlockPlaceContext mutableBlockPlaceContext;
private final PaperweightLevelProxy proxyLevel;
public PaperweightPlacementStateProcessor(
final Extent extent,
final BlockTypeMask mask,
final boolean includeUnedited
public PaperweightPlacementStateProcessor(Extent extent, BlockTypeMask mask, Region region) {
super(extent, mask, region);
this.proxyLevel = PaperweightLevelProxy.getInstance(this);
this.mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel);
}
private PaperweightPlacementStateProcessor(
Extent extent,
BlockTypeMask mask,
Map<SecondPass, Character> crossChunkSecondPasses,
ThreadLocal<PlacementStateProcessor> threadProcessors,
Region region,
AtomicBoolean finished
) {
super(extent, mask, includeUnedited);
World world;
if (extent.isWorld()) {
world = (World) extent;
} else if (extent instanceof EditSession session) {
world = session.getWorld();
} else if ((world = new ExtentTraverser<>(extent).findAndGet(BukkitWorld.class)) == null) {
throw new UnsupportedOperationException("Cannot find world of extent.");
}
BukkitWorld bukkitWorld;
if (world instanceof WorldWrapper wrapper) {
bukkitWorld = (BukkitWorld) wrapper.getParent();
} else {
bukkitWorld = (BukkitWorld) world;
}
PaperweightLevelProxy proxyLevel = PaperweightLevelProxy.getInstance(
((CraftWorld) bukkitWorld.getWorld()).getHandle(),
extent
);
mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel);
proxyLevel.setEnabled(true);
super(extent, mask, crossChunkSecondPasses, threadProcessors, region, finished);
this.proxyLevel = PaperweightLevelProxy.getInstance(this);
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());
@ -75,8 +58,8 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor
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 +68,12 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor
if (child == getExtent()) {
return this;
}
return new PaperweightPlacementStateProcessor(child, mask, includeUnedited);
return new PaperweightPlacementStateProcessor(child, mask, region);
}
@Override
public PlacementStateProcessor fork() {
return new PaperweightPlacementStateProcessor(extent, mask, includeUnedited);
return new PaperweightPlacementStateProcessor(extent, mask, postCompleteSecondPasses, threadProcessors, region, finished);
}
}

Datei anzeigen

@ -880,12 +880,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
}
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
SideEffect.NEIGHBORS,
SideEffect.LIGHTING,
SideEffect.VALIDATION,
SideEffect.ENTITY_AI,
SideEffect.EVENTS,
SideEffect.UPDATE
//FAWE start - FAWE-supported side effects
SideEffect.HISTORY,
SideEffect.HEIGHTMAPS,
SideEffect.LIGHTING,
SideEffect.NEIGHBORS
//FAWE end
);
@Override

Datei anzeigen

@ -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;

Datei anzeigen

@ -4,7 +4,7 @@ import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.entity.LazyBaseEntity;
import com.fastasyncworldedit.core.extent.processor.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
@ -14,6 +14,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;
@ -36,7 +37,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.world.RegenOptions;
@ -303,9 +303,16 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
return state.toBaseBlock();
}
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
SideEffect.HISTORY,
SideEffect.HEIGHTMAPS,
SideEffect.LIGHTING,
SideEffect.NEIGHBORS
);
@Override
public Set<SideEffect> getSupportedSideEffects() {
return SideEffectSet.defaults().getSideEffectsToApply();
return SUPPORTED_SIDE_EFFECTS;
}
@Override
@ -454,7 +461,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
}
public net.minecraft.world.level.block.state.BlockState adapt(BlockState blockState) {
return Block.stateById(ordinalToIbdID[blockState.getOrdinal()]);
return Block.stateById(getOrdinalToIbdID()[blockState.getOrdinal()]);
}
@Override
@ -639,8 +646,8 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
}
@Override
public PlacementStateProcessor getPlatformPlacementProcessor(Extent extent, BlockTypeMask mask, boolean includeUnedited) {
return new PaperweightPlacementStateProcessor(extent, mask, includeUnedited);
public PlacementStateProcessor getPlatformPlacementProcessor(Extent extent, BlockTypeMask mask, Region region) {
return new PaperweightPlacementStateProcessor(extent, mask, region);
}
private boolean wasAccessibleSinceLastSave(ChunkHolder holder) {

Datei anzeigen

@ -20,6 +20,7 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
@ -833,7 +834,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
nmsChunk.mustNotSave = false;
nmsChunk.setUnsaved(true);
// send to player
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) {
if (!set
.getSideEffectSet()
.shouldApply(SideEffect.LIGHTING) || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) {
this.send();
}
if (finalizer != null) {

Datei anzeigen

@ -2,12 +2,12 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4;
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extent.Extent;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;
@ -19,18 +19,17 @@ import javax.annotation.Nullable;
public class PaperweightLevelProxy extends ServerLevel {
protected ServerLevel serverLevel;
private PaperweightPlacementStateProcessor processor;
private PaperweightFaweAdapter adapter;
private Extent extent;
private ServerLevel serverLevel;
private boolean enabled = false;
@SuppressWarnings("DataFlowIssue")
public PaperweightLevelProxy() {
private PaperweightLevelProxy() {
super(null, null, null, null, null, null, null, true, 0L, null, true, null, null, null, null);
throw new IllegalStateException("Cannot be instantiated");
}
public static PaperweightLevelProxy getInstance(ServerLevel level, Extent extent) {
public static PaperweightLevelProxy getInstance(ServerLevel serverLevel, PaperweightPlacementStateProcessor processor) {
Unsafe unsafe = ReflectionUtils.getUnsafe();
PaperweightLevelProxy newLevel;
@ -39,48 +38,38 @@ public class PaperweightLevelProxy extends ServerLevel {
} catch (InstantiationException e) {
throw new RuntimeException(e);
}
newLevel.adapter = ((PaperweightFaweAdapter) WorldEditPlugin
.getInstance()
.getBukkitImplAdapter());
newLevel.extent = extent;
newLevel.serverLevel = level;
newLevel.processor = processor;
newLevel.adapter = ((PaperweightFaweAdapter) WorldEditPlugin.getInstance().getBukkitImplAdapter());
newLevel.serverLevel = serverLevel;
return newLevel;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Nullable
@Override
public BlockEntity getBlockEntity(@Nonnull BlockPos blockPos) {
if (!enabled) {
if (blockPos.getX() == Integer.MAX_VALUE) {
return null;
}
BlockEntity tileEntity = this.serverLevel.getChunkAt(blockPos).getBlockEntity(blockPos);
if (tileEntity == null) {
com.sk89q.jnbt.CompoundTag tag = processor.getTileAt(blockPos.getX(), blockPos.getY(), blockPos.getZ());
if (tag == null) {
return null;
}
BlockEntity newEntity = tileEntity.getType().create(blockPos, getBlockState(blockPos));
newEntity.loadWithComponents(
(CompoundTag) adapter.fromNativeLin(this.extent.getFullBlock(
blockPos.getX(),
blockPos.getY(),
blockPos.getZ()
).getNbtReference().getValue()),
this.serverLevel.registryAccess()
);
return newEntity;
BlockState state = adapter.adapt(processor.getBlockStateAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
if (!(state.getBlock() instanceof EntityBlock entityBlock)) {
return null;
}
BlockEntity tileEntity = entityBlock.newBlockEntity(blockPos, state);
tileEntity.loadWithComponents((CompoundTag) adapter.fromNative(tag), serverLevel.registryAccess());
return tileEntity;
}
@Override
@Nonnull
public BlockState getBlockState(@Nonnull BlockPos blockPos) {
if (!enabled) {
if (blockPos.getX() == Integer.MAX_VALUE) {
return Blocks.AIR.defaultBlockState();
}
com.sk89q.worldedit.world.block.BlockState state = this.extent.getBlock(
com.sk89q.worldedit.world.block.BlockState state = processor.getBlockStateAt(
blockPos.getX(),
blockPos.getY(),
blockPos.getZ()
@ -92,7 +81,7 @@ public class PaperweightLevelProxy extends ServerLevel {
@Override
@Nonnull
public FluidState getFluidState(@Nonnull BlockPos pos) {
if (!enabled) {
if (pos.getX() == Integer.MAX_VALUE) {
return Fluids.EMPTY.defaultFluidState();
}
return getBlockState(pos).getFluidState();
@ -101,7 +90,7 @@ public class PaperweightLevelProxy extends ServerLevel {
@SuppressWarnings("unused")
@Override
public boolean isWaterAt(@Nonnull BlockPos pos) {
if (!enabled) {
if (pos.getX() == Integer.MAX_VALUE) {
return false;
}
return getBlockState(pos).getFluidState().is(FluidTags.WATER);

Datei anzeigen

@ -1,47 +1,44 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4;
import com.fastasyncworldedit.core.extent.processor.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.PlacementStateProcessor;
import com.fastasyncworldedit.core.util.ExtentTraverser;
import com.fastasyncworldedit.core.wrappers.WorldWrapper;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.BlockTypeMask;
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.world.World;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import org.bukkit.craftbukkit.CraftWorld;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
public class PaperweightPlacementStateProcessor extends PlacementStateProcessor {
private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin
.getInstance()
.getBukkitImplAdapter());
private final PaperweightLevelProxy proxyLevel;
private final FaweMutableBlockPlaceContext mutableBlockPlaceContext;
public PaperweightPlacementStateProcessor(
final Extent extent,
final BlockTypeMask mask,
final boolean includeUnedited
) {
super(extent, mask, includeUnedited);
World world;
if (extent.isWorld()) {
world = (World) extent;
} else if (extent instanceof EditSession session) {
world = session.getWorld();
} else if ((world = new ExtentTraverser<>(extent).findAndGet(BukkitWorld.class)) == null) {
throw new UnsupportedOperationException("Cannot find world of extent.");
public PaperweightPlacementStateProcessor(Extent extent, BlockTypeMask mask, Region region) {
super(extent, mask, region);
World world = ExtentTraverser.getWorldFromExtent(extent);
if (world == null) {
throw new UnsupportedOperationException(
"World is required for PlacementStateProcessor but none found in given extent.");
}
BukkitWorld bukkitWorld;
if (world instanceof WorldWrapper wrapper) {
@ -49,12 +46,22 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor
} else {
bukkitWorld = (BukkitWorld) world;
}
PaperweightLevelProxy proxyLevel = PaperweightLevelProxy.getInstance(
((CraftWorld) bukkitWorld.getWorld()).getHandle(),
extent
);
mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel);
proxyLevel.setEnabled(true);
this.proxyLevel = PaperweightLevelProxy.getInstance(((CraftWorld) bukkitWorld.getWorld()).getHandle(), this);
this.mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel);
}
private PaperweightPlacementStateProcessor(
Extent extent,
BlockTypeMask mask,
Map<SecondPass, Character> crossChunkSecondPasses,
ServerLevel serverLevel,
ThreadLocal<PlacementStateProcessor> threadProcessors,
Region region,
AtomicBoolean finished
) {
super(extent, mask, crossChunkSecondPasses, threadProcessors, region, finished);
this.proxyLevel = PaperweightLevelProxy.getInstance(serverLevel, this);
this.mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel);
}
@Override
@ -75,8 +82,8 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor
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 +92,20 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor
if (child == getExtent()) {
return this;
}
return new PaperweightPlacementStateProcessor(child, mask, includeUnedited);
return new PaperweightPlacementStateProcessor(child, mask, region);
}
@Override
public PlacementStateProcessor fork() {
return new PaperweightPlacementStateProcessor(extent, mask, includeUnedited);
return new PaperweightPlacementStateProcessor(
extent,
mask,
postCompleteSecondPasses,
proxyLevel.serverLevel,
threadProcessors,
region,
finished
);
}
}

Datei anzeigen

@ -886,12 +886,12 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
}
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
SideEffect.NEIGHBORS,
SideEffect.LIGHTING,
SideEffect.VALIDATION,
SideEffect.ENTITY_AI,
SideEffect.EVENTS,
SideEffect.UPDATE
//FAWE start - FAWE-supported side effects
SideEffect.HISTORY,
SideEffect.HEIGHTMAPS,
SideEffect.LIGHTING,
SideEffect.NEIGHBORS
//FAWE end
);
@Override

Datei anzeigen

@ -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;

Datei anzeigen

@ -4,7 +4,7 @@ import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.entity.LazyBaseEntity;
import com.fastasyncworldedit.core.extent.processor.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
@ -14,6 +14,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;
@ -36,7 +37,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.world.RegenOptions;
@ -303,9 +303,16 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
return state.toBaseBlock();
}
private static final Set<SideEffect> SUPPORTED_SIDE_EFFECTS = Sets.immutableEnumSet(
SideEffect.HISTORY,
SideEffect.HEIGHTMAPS,
SideEffect.LIGHTING,
SideEffect.NEIGHBORS
);
@Override
public Set<SideEffect> getSupportedSideEffects() {
return SideEffectSet.defaults().getSideEffectsToApply();
return SUPPORTED_SIDE_EFFECTS;
}
@Override
@ -454,7 +461,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
}
public net.minecraft.world.level.block.state.BlockState adapt(BlockState blockState) {
return Block.stateById(ordinalToIbdID[blockState.getOrdinal()]);
return Block.stateById(getOrdinalToIbdID()[blockState.getOrdinal()]);
}
@Override
@ -639,8 +646,8 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
}
@Override
public PlacementStateProcessor getPlatformPlacementProcessor(Extent extent, BlockTypeMask mask, boolean includeUnedited) {
return new PaperweightPlacementStateProcessor(extent, mask, includeUnedited);
public PlacementStateProcessor getPlatformPlacementProcessor(Extent extent, BlockTypeMask mask, Region region ) {
return new PaperweightPlacementStateProcessor(extent, mask, region);
}
private boolean wasAccessibleSinceLastSave(ChunkHolder holder) {

Datei anzeigen

@ -20,6 +20,7 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
@ -828,7 +829,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc
nmsChunk.mustNotSave = false;
nmsChunk.setUnsaved(true);
// send to player
if (Settings.settings().LIGHTING.MODE == 0 || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) {
if (!set
.getSideEffectSet()
.shouldApply(SideEffect.LIGHTING) || !Settings.settings().LIGHTING.DELAY_PACKET_SENDING || finalMask == 0 && biomes != null) {
this.send();
}
if (finalizer != null) {

Datei anzeigen

@ -2,12 +2,12 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extent.Extent;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.FluidState;
@ -19,18 +19,17 @@ import javax.annotation.Nullable;
public class PaperweightLevelProxy extends ServerLevel {
protected ServerLevel serverLevel;
private PaperweightFaweAdapter adapter;
private Extent extent;
private ServerLevel serverLevel;
private boolean enabled = false;
private PaperweightPlacementStateProcessor processor;
@SuppressWarnings("DataFlowIssue")
public PaperweightLevelProxy() {
private PaperweightLevelProxy() {
super(null, null, null, null, null, null, null, true, 0L, null, true, null, null, null, null);
throw new IllegalStateException("Cannot be instantiated");
}
public static PaperweightLevelProxy getInstance(ServerLevel level, Extent extent) {
public static PaperweightLevelProxy getInstance(ServerLevel serverLevel, PaperweightPlacementStateProcessor processor) {
Unsafe unsafe = ReflectionUtils.getUnsafe();
PaperweightLevelProxy newLevel;
@ -39,48 +38,38 @@ public class PaperweightLevelProxy extends ServerLevel {
} catch (InstantiationException e) {
throw new RuntimeException(e);
}
newLevel.adapter = ((PaperweightFaweAdapter) WorldEditPlugin
.getInstance()
.getBukkitImplAdapter());
newLevel.extent = extent;
newLevel.serverLevel = level;
newLevel.processor = processor;
newLevel.adapter = ((PaperweightFaweAdapter) WorldEditPlugin.getInstance().getBukkitImplAdapter());
newLevel.serverLevel = serverLevel;
return newLevel;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Nullable
@Override
public BlockEntity getBlockEntity(@Nonnull BlockPos blockPos) {
if (!enabled) {
if (blockPos.getX() == Integer.MAX_VALUE) {
return null;
}
BlockEntity tileEntity = this.serverLevel.getChunkAt(blockPos).getBlockEntity(blockPos);
if (tileEntity == null) {
com.sk89q.jnbt.CompoundTag tag = processor.getTileAt(blockPos.getX(), blockPos.getY(), blockPos.getZ());
if (tag == null) {
return null;
}
BlockEntity newEntity = tileEntity.getType().create(blockPos, getBlockState(blockPos));
newEntity.loadWithComponents(
(CompoundTag) adapter.fromNativeLin(this.extent.getFullBlock(
blockPos.getX(),
blockPos.getY(),
blockPos.getZ()
).getNbtReference().getValue()),
this.serverLevel.registryAccess()
);
return newEntity;
BlockState state = adapter.adapt(processor.getBlockStateAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
if (!(state.getBlock() instanceof EntityBlock entityBlock)) {
return null;
}
BlockEntity tileEntity = entityBlock.newBlockEntity(blockPos, state);
tileEntity.loadWithComponents((CompoundTag) adapter.fromNative(tag), serverLevel.registryAccess());
return tileEntity;
}
@Override
@Nonnull
public BlockState getBlockState(@Nonnull BlockPos blockPos) {
if (!enabled) {
if (blockPos.getX() == Integer.MAX_VALUE) {
return Blocks.AIR.defaultBlockState();
}
com.sk89q.worldedit.world.block.BlockState state = this.extent.getBlock(
com.sk89q.worldedit.world.block.BlockState state = processor.getBlockStateAt(
blockPos.getX(),
blockPos.getY(),
blockPos.getZ()
@ -92,7 +81,7 @@ public class PaperweightLevelProxy extends ServerLevel {
@Override
@Nonnull
public FluidState getFluidState(@Nonnull BlockPos pos) {
if (!enabled) {
if (pos.getX() == Integer.MAX_VALUE) {
return Fluids.EMPTY.defaultFluidState();
}
return getBlockState(pos).getFluidState();
@ -101,7 +90,7 @@ public class PaperweightLevelProxy extends ServerLevel {
@SuppressWarnings("unused")
@Override
public boolean isWaterAt(@Nonnull BlockPos pos) {
if (!enabled) {
if (pos.getX() == Integer.MAX_VALUE) {
return false;
}
return getBlockState(pos).getFluidState().is(FluidTags.WATER);

Datei anzeigen

@ -1,26 +1,29 @@
package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1;
import com.fastasyncworldedit.core.extent.processor.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.PlacementStateProcessor;
import com.fastasyncworldedit.core.util.ExtentTraverser;
import com.fastasyncworldedit.core.wrappers.WorldWrapper;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.BlockTypeMask;
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.world.World;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import org.bukkit.craftbukkit.CraftWorld;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
public class PaperweightPlacementStateProcessor extends PlacementStateProcessor {
@ -28,20 +31,14 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor
.getInstance()
.getBukkitImplAdapter());
private final FaweMutableBlockPlaceContext mutableBlockPlaceContext;
private final PaperweightLevelProxy proxyLevel;
public PaperweightPlacementStateProcessor(
final Extent extent,
final BlockTypeMask mask,
final boolean includeUnedited
) {
super(extent, mask, includeUnedited);
World world;
if (extent.isWorld()) {
world = (World) extent;
} else if (extent instanceof EditSession session) {
world = session.getWorld();
} else if ((world = new ExtentTraverser<>(extent).findAndGet(BukkitWorld.class)) == null) {
throw new UnsupportedOperationException("Cannot find world of extent.");
public PaperweightPlacementStateProcessor(Extent extent, BlockTypeMask mask, Region region) {
super(extent, mask, region);
World world = ExtentTraverser.getWorldFromExtent(extent);
if (world == null) {
throw new UnsupportedOperationException(
"World is required for PlacementStateProcessor but none found in given extent.");
}
BukkitWorld bukkitWorld;
if (world instanceof WorldWrapper wrapper) {
@ -49,12 +46,22 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor
} else {
bukkitWorld = (BukkitWorld) world;
}
PaperweightLevelProxy proxyLevel = PaperweightLevelProxy.getInstance(
((CraftWorld) bukkitWorld.getWorld()).getHandle(),
extent
);
mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel);
proxyLevel.setEnabled(true);
this.proxyLevel = PaperweightLevelProxy.getInstance(((CraftWorld) bukkitWorld.getWorld()).getHandle(), this);
this.mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel);
}
private PaperweightPlacementStateProcessor(
Extent extent,
BlockTypeMask mask,
Map<SecondPass, Character> crossChunkSecondPasses,
ServerLevel serverLevel,
ThreadLocal<PlacementStateProcessor> threadProcessors,
Region region,
AtomicBoolean finished
) {
super(extent, mask, crossChunkSecondPasses, threadProcessors, region, finished);
this.proxyLevel = PaperweightLevelProxy.getInstance(serverLevel, this);
this.mutableBlockPlaceContext = new FaweMutableBlockPlaceContext(proxyLevel);
}
@Override
@ -85,12 +92,20 @@ public class PaperweightPlacementStateProcessor extends PlacementStateProcessor
if (child == getExtent()) {
return this;
}
return new PaperweightPlacementStateProcessor(child, mask, includeUnedited);
return new PaperweightPlacementStateProcessor(child, mask, region);
}
@Override
public PlacementStateProcessor fork() {
return new PaperweightPlacementStateProcessor(extent, mask, includeUnedited);
return new PaperweightPlacementStateProcessor(
extent,
mask,
postCompleteSecondPasses,
proxyLevel.serverLevel,
threadProcessors,
region,
finished
);
}
}

Datei anzeigen

@ -21,7 +21,7 @@ package com.sk89q.worldedit.bukkit;
import com.fastasyncworldedit.bukkit.util.MinecraftVersion;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.processor.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
import com.google.common.collect.Sets;
@ -41,6 +41,7 @@ import com.sk89q.worldedit.extension.platform.Watchdog;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.BlockTypeMask;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.lifecycle.Lifecycled;
import com.sk89q.worldedit.world.DataFixer;
@ -314,8 +315,8 @@ 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, Region region) {
return this.plugin.getBukkitImplAdapter().getPlatformPlacementProcessor(extent, mask, region);
}
//FAWE end
}

Datei anzeigen

@ -23,7 +23,7 @@ import com.fastasyncworldedit.bukkit.FaweBukkit;
import com.fastasyncworldedit.bukkit.adapter.IBukkitAdapter;
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.extent.processor.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
import com.fastasyncworldedit.core.queue.IChunkGet;
@ -409,7 +409,7 @@ public interface BukkitImplAdapter<T> 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, Region region) {
return null;
}
//FAWE end

Datei anzeigen

@ -32,6 +32,8 @@ import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3;
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.formatting.text.Component;
import com.sk89q.worldedit.world.World;
import org.apache.logging.log4j.Logger;
@ -355,8 +357,12 @@ public class FaweAPI {
if (unwrapped instanceof IQueueExtent) {
queue = (IQueueExtent) unwrapped;
} else if (Settings.settings().QUEUE.PARALLEL_THREADS > 1) {
ParallelQueueExtent parallel =
new ParallelQueueExtent(Fawe.instance().getQueueHandler(), world, true);
ParallelQueueExtent parallel = new ParallelQueueExtent(
Fawe.instance().getQueueHandler(),
world,
true,
SideEffectSet.none().with(SideEffect.LIGHTING, SideEffect.State.ON)
);
queue = parallel.getExtent();
} else {
queue = Fawe.instance().getQueueHandler().getQueue(world);

Datei anzeigen

@ -0,0 +1,51 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.fastasyncworldedit.core.function.mask.Adjacent2DMask;
import com.fastasyncworldedit.core.function.mask.AdjacentAny2DMask;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask;
import javax.annotation.Nonnull;
import java.util.stream.Stream;
public class Adjacent2DMaskParser extends RichParser<Mask> {
public Adjacent2DMaskParser(WorldEdit worldEdit) {
super(worldEdit, "~2d", "adjacent2d");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0) {
return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream();
} else if (index == 1 || index == 2) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}
return Stream.empty();
}
@Override
protected Mask parseFromInput(@Nonnull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length == 0) {
return null;
}
Mask subMask = worldEdit.getMaskFactory().parseFromInput(arguments[0], context);
int min = arguments.length > 1 ? Integer.parseInt(arguments[1]) : -1;
int max = arguments.length > 2 ? Integer.parseInt(arguments[2]) : -1;
if (min == -1 && max == -1) {
min = 1;
max = 4;
} else if (max == -1) {
max = min;
}
if (max >= 4 && min == 1) {
return new AdjacentAny2DMask(subMask);
}
return new Adjacent2DMask(subMask, min, max);
}
}

Datei anzeigen

@ -10,7 +10,6 @@ import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
@ -215,12 +214,6 @@ public class PassthroughExtent extends AbstractDelegateExtent {
return getExtent().setBiome(position, biome);
}
@Override
@Nullable
public Operation commit() {
return getExtent().commit();
}
@Override
public boolean cancel() {
return getExtent().cancel();

Datei anzeigen

@ -0,0 +1,462 @@
package com.fastasyncworldedit.core.extent;
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
import com.fastasyncworldedit.core.function.mask.AdjacentAny2DMask;
import com.fastasyncworldedit.core.math.BlockVector3ChunkMap;
import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.fastasyncworldedit.core.math.MutableVector3;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
import com.fastasyncworldedit.core.queue.IChunk;
import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.NullExtent;
import com.sk89q.worldedit.function.mask.BlockTypeMask;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockCategories;
import com.sk89q.worldedit.world.block.BlockCategory;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import org.enginehub.linbus.tree.LinCompoundTag;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
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 final int CHUNK_BLOCK_POS_MASK = -1 << 4;
private static volatile boolean SETUP = false;
private static BlockTypeMask DEFAULT_MASK = null;
private static BlockTypeMask REQUIRES_SECOND_PASS = null;
private static AdjacentAny2DMask ADJACENT_STAIR_MASK = null;
protected final Extent extent;
protected final BlockTypeMask mask;
protected final Region region;
protected final Map<SecondPass, Character> postCompleteSecondPasses;
protected final ThreadLocal<PlacementStateProcessor> threadProcessors;
protected final AtomicBoolean finished;
private final MutableVector3 clickPos = new MutableVector3();
private final MutableBlockVector3 clickedBlock = new MutableBlockVector3();
private IChunkGet processChunkGet = null;
private IChunkSet processChunkSet = null;
private int processChunkX;
private int processChunkZ;
/**
* 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
* @since TODO
*/
public PlacementStateProcessor(Extent extent, BlockTypeMask mask, Region region) {
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.
if (!SETUP) {
synchronized (PlacementStateProcessor.class) {
if (!SETUP) {
setup();
}
}
}
this.extent = extent;
this.mask = mask == null ? DEFAULT_MASK : mask;
this.region = region;
this.postCompleteSecondPasses = new ConcurrentHashMap<>();
this.threadProcessors = ThreadLocal.withInitial(this::fork);
this.finished = new AtomicBoolean();
}
protected PlacementStateProcessor(
Extent extent,
BlockTypeMask mask,
Map<SecondPass, Character> crossChunkSecondPasses,
ThreadLocal<PlacementStateProcessor> threadProcessors,
Region region,
AtomicBoolean finished
) {
super(extent);
this.extent = extent;
this.mask = mask;
this.region = region;
this.postCompleteSecondPasses = crossChunkSecondPasses;
this.threadProcessors = threadProcessors;
this.finished = finished;
}
private static void setup() {
REQUIRES_SECOND_PASS = new BlockTypeMask(new NullExtent());
REQUIRES_SECOND_PASS.add(
BlockTypes.IRON_BARS,
BlockTypes.GLASS_PANE,
BlockTypes.BLACK_STAINED_GLASS_PANE,
BlockTypes.BLUE_STAINED_GLASS_PANE,
BlockTypes.BROWN_STAINED_GLASS_PANE,
BlockTypes.LIGHT_BLUE_STAINED_GLASS_PANE,
BlockTypes.PINK_STAINED_GLASS_PANE,
BlockTypes.LIGHT_GRAY_STAINED_GLASS_PANE,
BlockTypes.GRAY_STAINED_GLASS_PANE,
BlockTypes.CYAN_STAINED_GLASS_PANE,
BlockTypes.PURPLE_STAINED_GLASS_PANE,
BlockTypes.GREEN_STAINED_GLASS_PANE,
BlockTypes.LIME_STAINED_GLASS_PANE,
BlockTypes.MAGENTA_STAINED_GLASS_PANE,
BlockTypes.YELLOW_STAINED_GLASS_PANE,
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,
BlockTypes.BIG_DRIPLEAF,
BlockTypes.BIG_DRIPLEAF_STEM,
BlockTypes.CAMPFIRE,
BlockTypes.CHEST,
BlockTypes.TRAPPED_CHEST,
BlockTypes.CRAFTER,
BlockTypes.MUSHROOM_STEM,
BlockTypes.BROWN_MUSHROOM_BLOCK,
BlockTypes.RED_MUSHROOM_BLOCK
);
categories = new BlockCategory[]{BlockCategories.STAIRS, BlockCategories.BAMBOO_BLOCKS, BlockCategories.TALL_FLOWERS};
for (BlockCategory category : categories) {
if (category != null) {
DEFAULT_MASK.add(category.getAll());
}
}
BlockTypeMask stairs = new BlockTypeMask(new NullExtent(), BlockCategories.STAIRS.getAll());
ADJACENT_STAIR_MASK = new AdjacentAny2DMask(stairs, false);
SETUP = true;
}
@Override
public IChunkSet processSet(IChunk iChunk, IChunkGet chunkGet, IChunkSet chunkSet) {
if (finished.get()) {
return chunkSet;
}
PlacementStateProcessor threadProcessor = threadProcessors.get();
try {
threadProcessor.initProcess(iChunk, chunkGet, chunkSet);
return threadProcessor.process();
} finally {
threadProcessor.uninit();
}
}
private void initProcess(IChunk iChunk, IChunkGet chunkGet, IChunkSet chunkSet) {
this.processChunkX = iChunk.getX() << 4;
this.processChunkZ = iChunk.getZ() << 4;
this.processChunkGet = chunkGet;
this.processChunkSet = chunkSet;
}
private void uninit() {
this.processChunkGet = null;
this.processChunkSet = null;
}
private IChunkSet process() {
Map<BlockVector3, CompoundTag> setTiles = processChunkSet.getTiles();
for (int layer = processChunkGet.getMinSectionPosition(); layer <= processChunkGet.getMaxSectionPosition(); layer++) {
int layerY = layer << 4;
char[] set = processChunkSet.loadIfPresent(layer);
if (set == null) {
continue;
}
for (int y = 0, i = 0; y < 16; y++, i += 256) {
int blockY = layerY + y;
checkAndPerformUpdate(setTiles, set, i, blockY, true);
checkAndPerformUpdate(setTiles, set, i, blockY, false);
}
}
return processChunkSet;
}
private void checkAndPerformUpdate(Map<BlockVector3, CompoundTag> setTiles, char[] set, int index, int blockY, boolean firstPass) {
for (int z = 0; z < 16; z++) {
int blockZ = processChunkZ + z;
for (int x = 0; x < 16; x++, index++) {
int blockX = processChunkX + x;
char ordinal = set[index];
BlockState state = BlockTypesCache.states[ordinal];
if (firstPass && !BlockCategories.STAIRS.contains(state)) {
continue;
}
if (!mask.test(state)) {
continue;
}
if (!firstPass && REQUIRES_SECOND_PASS.test(state)) {
postCompleteSecondPasses.put(new SecondPass(
blockX,
blockY,
blockZ,
setTiles.isEmpty() ? null : ((BlockVector3ChunkMap<CompoundTag>) setTiles).remove(x, blockY, z)
), ordinal);
set[index] = BlockTypesCache.ReservedIDs.__RESERVED__;
continue;
}
char newOrdinal = getBlockOrdinal(blockX, blockY, blockZ, state);
if (newOrdinal == ordinal) {
continue;
}
set[index] = newOrdinal;
}
}
}
@Override
public ProcessorScope getScope() {
return ProcessorScope.CHANGING_BLOCKS;
}
@Override
public void finish() {
flush();
}
@Override
public void flush() {
finished.set(true);
for (Map.Entry<SecondPass, Character> entry : postCompleteSecondPasses.entrySet()) {
BlockState state;
char ordinal = entry.getValue();
SecondPass secondPass = entry.getKey();
if (ordinal != 0) {
state = BlockTypesCache.states[ordinal];
} else {
state = extent.getBlock(secondPass.x, secondPass.y, secondPass.z);
}
char newOrdinal = getBlockOrdinal(secondPass.x, secondPass.y, secondPass.z, state);
if (newOrdinal == state.getOrdinalChar() && ordinal == 0) {
continue;
}
if (secondPass.tile != null) {
extent.setTile(secondPass.x, secondPass.y, secondPass.z, secondPass.tile);
}
extent.setBlock(secondPass.x, secondPass.y, secondPass.z, BlockTypesCache.states[newOrdinal]);
}
postCompleteSecondPasses.clear();
}
@Override
public abstract PlacementStateProcessor fork();
protected abstract char getStateAtFor(
int x,
int y,
int z,
BlockState state,
Vector3 clickPos,
Direction clickedFaceDirection,
BlockVector3 clickedBlock
);
public BlockState getBlockStateAt(int x, int y, int z) {
Character ord = postCompleteSecondPasses.get(new SecondPass(x, y, z, null));
if (ord != null && ord != 0) {
return BlockTypesCache.states[ord];
}
if (processChunkSet == null || (x & CHUNK_BLOCK_POS_MASK) != processChunkX || (z & CHUNK_BLOCK_POS_MASK) != processChunkZ) {
return extent.getBlock(x, y, z);
}
char[] set = processChunkSet.loadIfPresent(y >> 4);
if (set == null) {
return processChunkGet.getBlock(x & 15, y, z & 15);
}
char ordinal = set[(y & 15) << 8 | (z & 15) << 4 | (x & 15)];
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
return processChunkGet.getBlock(x & 15, y, z & 15);
}
return BlockTypesCache.states[ordinal];
}
public CompoundTag getTileAt(int x, int y, int z) {
SecondPass secondPass = new SecondPass(x, y, z, null);
Character ord = postCompleteSecondPasses.get(secondPass);
if (ord != null && ord != 0) {
// This should be rare enough...
for (SecondPass pass : postCompleteSecondPasses.keySet()) {
if (pass.hashCode() == secondPass.hashCode()) {
return pass.tile != null ? pass.tile : BlockTypesCache.states[ord].getNbtData();
}
}
return BlockTypesCache.states[ord].getNbtData();
}
if (processChunkSet == null || (x & CHUNK_BLOCK_POS_MASK) != processChunkX || (z & CHUNK_BLOCK_POS_MASK) != processChunkZ) {
return extent.getFullBlock(x, y, z).getNbtData();
}
CompoundTag tile = processChunkSet.getTile(x & 15, y, z & 15);
if (tile != null) {
return tile;
}
char[] set = processChunkSet.loadIfPresent(y >> 4);
if (set == null) {
return processChunkGet.getFullBlock(x & 15, y, z & 15).getNbtData();
}
char ordinal = set[(y & 15) << 8 | (z & 15) << 4 | (x & 15)];
if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) {
return processChunkGet.getFullBlock(x & 15, y, z & 15).getNbtData();
}
return BlockTypesCache.states[ordinal].getNbtData();
}
private char getBlockOrdinal(final int blockX, final int blockY, final int blockZ, final BlockState state) {
EnumSet<Direction> dirs = Direction.getDirections(state);
Direction clickedFaceDirection = null; // This should be always be set by the below.
Set<String> states = state.getStates().keySet().stream().map(Property::getName).collect(Collectors.toSet());
if (dirs.isEmpty() || states.contains("NORTH") && states.contains("EAST")) {
clickPos.setComponents(blockX + 0.5d, blockY, blockZ + 0.5d);
clickedFaceDirection = Direction.UP;
clickedBlock.setComponents(blockX, blockY - 1, blockZ);
} else {
boolean hadNesw = false;
for (Direction dir : NESW) {
if (dirs.contains(dir)) {
clickedFaceDirection = dir.getLeft().getLeft(); // opposite
clickPos.setComponents(
(double) blockX + 0.5 * (1 + dir.getBlockX()),
(double) blockY + 0.2,
(double) blockZ + 0.5 * (1 + dir.getBlockZ())
);
clickedBlock.setComponents(blockX, blockY, blockZ).add(dir.toBlockVector());
hadNesw = true;
break;
}
}
if (hadNesw) {
if (dirs.contains(Direction.UP)) {
clickPos.mutY(blockY + 0.5);
}
} else if (dirs.contains(Direction.UP)) {
clickedFaceDirection = Direction.DOWN;
clickPos.setComponents(blockX + 0.5d, blockY + 1d, blockZ + 0.5d);
clickedBlock.setComponents(blockX, blockY + 1, blockZ);
} else if (dirs.contains(Direction.DOWN)) {
clickedFaceDirection = Direction.UP;
clickPos.setComponents(blockX + 0.5d, blockY - 1d, blockZ + 0.5d);
clickedBlock.setComponents(blockX, blockY - 1, blockZ);
}
}
return getStateAtFor(blockX, blockY, blockZ, state, clickPos, clickedFaceDirection, clickedBlock);
}
@Override
public void applyBlock(FilterBlock block) {
if (finished.get()) {
return;
}
BlockState state = BlockTypesCache.states[block.getOrdinal()];
if (!mask.test(state)) {
return;
}
if (REQUIRES_SECOND_PASS.test(block.getBlock()) && ADJACENT_STAIR_MASK.test(extent, block)) {
postCompleteSecondPasses.put(new SecondPass(block), (char) 0);
}
char ordinal = (char) block.getOrdinal();
char newOrdinal = getBlockOrdinal(block.x(), block.y(), block.z(), block.getBlock());
if (ordinal != newOrdinal) {
block.setBlock(BlockTypesCache.states[newOrdinal]);
}
}
@Override
public boolean apply(Extent orDefault, BlockVector3 get, BlockVector3 set) throws WorldEditException {
if (orDefault == null) {
orDefault = extent;
}
BaseBlock block = orDefault.getFullBlock(get);
if (!mask.test(block)) {
return false;
}
if (REQUIRES_SECOND_PASS.test(block) && ADJACENT_STAIR_MASK.test(extent, set)) {
postCompleteSecondPasses.put(new SecondPass(set), (char) 0);
return false;
}
char newOrdinal = getBlockOrdinal(set.x(), set.y(), set.z(), block.toBlockState());
if (block.getOrdinalChar() != newOrdinal) {
BlockState newState = BlockTypesCache.states[newOrdinal];
orDefault.setBlock(set.x(), set.y(), set.z(), newState);
LinCompoundTag nbt = block.getNbt();
if (nbt != null && newState.getBlockType() == block.getBlockType()) {
orDefault.setTile(set.x(), set.y(), set.z(), new CompoundTag(nbt));
}
return true;
}
return false;
}
@Override
public BaseBlock applyBlock(BlockVector3 position) {
if (finished.get()) {
return null;
}
BaseBlock block = extent.getFullBlock(position);
if (!mask.test(block)) {
return null;
}
if (REQUIRES_SECOND_PASS.test(block) && ADJACENT_STAIR_MASK.test(extent, position)) {
postCompleteSecondPasses.put(new SecondPass(position), (char) 0);
return null;
}
char newOrdinal = getBlockOrdinal(position.x(), position.y(), position.z(), block.toBlockState());
if (block.getOrdinalChar() != newOrdinal) {
BlockState state = BlockTypesCache.states[newOrdinal];
LinCompoundTag nbt = block.getNbt();
if (nbt != null && state.getBlockType() == block.getBlockType()) {
state.toBaseBlock(nbt);
}
return state.toBaseBlock();
}
return null;
}
protected record SecondPass(int x, int y, int z, CompoundTag tile) {
private SecondPass(BlockVector3 pos) {
this(pos.x(), pos.y(), pos.z(), null);
}
@Override
public int hashCode() {
return (x ^ (z << 12)) ^ (y << 24);
}
}
}

Datei anzeigen

@ -1,268 +0,0 @@
package com.fastasyncworldedit.core.extent.processor;
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
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;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.NBTUtils;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.NullExtent;
import com.sk89q.worldedit.function.mask.BlockTypeMask;
import com.sk89q.worldedit.function.pattern.Pattern;
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.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockCategories;
import com.sk89q.worldedit.world.block.BlockCategory;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache;
import org.enginehub.linbus.tree.LinCompoundTag;
import java.util.EnumSet;
import java.util.Set;
import java.util.stream.Collectors;
public abstract class PlacementStateProcessor extends AbstractDelegateExtent implements IBatchProcessor, Filter, 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;
protected final Extent extent;
protected final BlockTypeMask mask;
protected final boolean includeUnedited;
private final MutableVector3 clickPos = new MutableVector3();
private final MutableBlockVector3 clickedBlock = new MutableBlockVector3();
public PlacementStateProcessor(Extent extent, BlockTypeMask mask, 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.
if (!SETUP) {
synchronized (PlacementStateProcessor.class) {
if (!SETUP) {
setup();
}
}
}
this.extent = extent;
this.mask = mask == null ? DEFAULT_MASK : mask;
this.includeUnedited = includeUnedited;
}
private static void setup() {
DEFAULT_MASK = new BlockTypeMask(new NullExtent());
DEFAULT_MASK.add(
BlockTypes.IRON_BARS,
BlockTypes.GLASS_PANE,
BlockTypes.BLACK_STAINED_GLASS_PANE,
BlockTypes.BLUE_STAINED_GLASS_PANE,
BlockTypes.BROWN_STAINED_GLASS_PANE,
BlockTypes.LIGHT_BLUE_STAINED_GLASS_PANE,
BlockTypes.PINK_STAINED_GLASS_PANE,
BlockTypes.LIGHT_GRAY_STAINED_GLASS_PANE,
BlockTypes.GRAY_STAINED_GLASS_PANE,
BlockTypes.CYAN_STAINED_GLASS_PANE,
BlockTypes.PURPLE_STAINED_GLASS_PANE,
BlockTypes.GREEN_STAINED_GLASS_PANE,
BlockTypes.LIME_STAINED_GLASS_PANE,
BlockTypes.MAGENTA_STAINED_GLASS_PANE,
BlockTypes.YELLOW_STAINED_GLASS_PANE,
BlockTypes.ORANGE_STAINED_GLASS_PANE,
BlockTypes.RED_STAINED_GLASS_PANE,
BlockTypes.WHITE_STAINED_GLASS_PANE,
BlockTypes.CHORUS_PLANT,
BlockTypes.DRIPSTONE_BLOCK,
BlockTypes.POINTED_DRIPSTONE,
BlockTypes.BIG_DRIPLEAF,
BlockTypes.BIG_DRIPLEAF_STEM,
BlockTypes.CAMPFIRE,
BlockTypes.CHEST,
BlockTypes.TRAPPED_CHEST,
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
);
BlockCategory[] categories = new BlockCategory[]{BlockCategories.FENCES, BlockCategories.FENCE_GATES, BlockCategories.STAIRS, BlockCategories.WALLS, BlockCategories.BAMBOO_BLOCKS, BlockCategories.CAVE_VINES, BlockCategories.TALL_FLOWERS};
for (BlockCategory category : categories) {
if (category != null) {
DEFAULT_MASK.add(category.getAll());
}
}
SETUP = true;
}
@Override
public IChunkSet processSet(IChunk iChunk, IChunkGet iChunkGet, IChunkSet iChunkSet) {
int chunkX = iChunk.getX() << 4;
int chunkZ = iChunk.getZ() << 4;
for (int layer = iChunkGet.getMinSectionPosition(); layer <= iChunkGet.getMaxSectionPosition(); layer++) {
int layerY = layer << 4;
char[] set = iChunkSet.loadIfPresent(layer);
char[] get = null;
if (set == null) {
if (!includeUnedited) {
continue;
}
}
for (int y = 0, i = 0; y < 16; y++) {
int blockY = layerY + y;
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;
}
}
}
}
return iChunkSet;
}
@Override
public ProcessorScope getScope() {
return ProcessorScope.CHANGING_BLOCKS;
}
@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
);
private char getBlockOrdinal(
final int blockX,
final int blockY,
final int blockZ,
final BlockState state
) {
EnumSet<Direction> dirs = Direction.getDirections(state);
Direction clickedFaceDirection = null; // This should be always be set by the below.
Set<String> states = state.getStates().keySet().stream().map(Property::getName).collect(Collectors.toSet());
if (dirs.isEmpty() || states.contains("NORTH") && states.contains("EAST")) {
clickPos.setComponents(blockX + 0.5d, blockY, blockZ + 0.5d);
clickedFaceDirection = Direction.UP;
clickedBlock.setComponents(blockX, blockY - 1, blockZ);
} else {
boolean hadNesw = false;
for (Direction dir : NESW) {
if (dirs.contains(dir)) {
clickedFaceDirection = dir.getLeft().getLeft(); // opposite
clickPos.setComponents(
(double) blockX + 0.5 * (1 + dir.getBlockX()),
(double) blockY + 0.2,
(double) blockZ + 0.5 * (1 + dir.getBlockZ())
);
clickedBlock.setComponents(blockX, blockY, blockZ).add(dir.toBlockVector());
hadNesw = true;
break;
}
}
if (hadNesw) {
if (dirs.contains(Direction.UP)) {
clickPos.mutY(blockY + 0.5);
}
} else if (dirs.contains(Direction.UP)) {
clickedFaceDirection = Direction.DOWN;
clickPos.setComponents(blockX + 0.5d, blockY + 1d, blockZ + 0.5d);
clickedBlock.setComponents(blockX, blockY + 1, blockZ);
} else if (dirs.contains(Direction.DOWN)) {
clickedFaceDirection = Direction.UP;
clickPos.setComponents(blockX + 0.5d, blockY - 1d, blockZ + 0.5d);
clickedBlock.setComponents(blockX, blockY - 1, blockZ);
}
}
return getStateAtFor(blockX, blockY, blockZ, state, clickPos, clickedFaceDirection, clickedBlock);
}
@Override
public void applyBlock(FilterBlock block) {
BlockState state = BlockTypesCache.states[block.getOrdinal()];
if (!mask.test(state.getBlockType())) {
return;
}
char ordinal = (char) block.getOrdinal();
char newOrdinal = getBlockOrdinal(block.x(), block.y(), block.z(), block.getBlock());
if (ordinal != newOrdinal) {
block.setBlock(BlockTypesCache.states[newOrdinal]);
}
}
@Override
public boolean apply(Extent orDefault, BlockVector3 get, BlockVector3 set) throws WorldEditException {
if (orDefault == null) {
orDefault = extent;
}
BaseBlock block = orDefault.getFullBlock(get);
if (!mask.test(block.getBlockType())) {
return false;
}
char newOrdinal = getBlockOrdinal(set.x(), set.y(), set.z(), block.toBlockState());
if (block.getOrdinalChar() != newOrdinal) {
BlockState newState = BlockTypesCache.states[newOrdinal];
orDefault.setBlock(set, newState);
LinCompoundTag nbt = block.getNbt();
if (nbt != null && newState.getBlockType() == block.getBlockType()) {
orDefault.setTile(set.x(), set.y(), set.z(), new CompoundTag(nbt));
}
return true;
}
return false;
}
@Override
public BaseBlock applyBlock(final BlockVector3 position) {
BaseBlock block = extent.getFullBlock(position);
if (!mask.test(block.getBlockType())) {
return null;
}
char newOrdinal = getBlockOrdinal(position.x(), position.y(), position.z(), block.toBlockState());
if (block.getOrdinalChar() != newOrdinal) {
BlockState state = BlockTypesCache.states[newOrdinal];
LinCompoundTag nbt = block.getNbt();
if (nbt != null && state.getBlockType() == block.getBlockType()) {
return state.toBaseBlock(nbt);
}
return state.toBaseBlock();
}
return null;
}
}

Datei anzeigen

@ -0,0 +1,53 @@
package com.fastasyncworldedit.core.function.mask;
import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.sk89q.worldedit.function.mask.AbstractMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.math.BlockVector3;
public class Adjacent2DMask extends AbstractMask {
private final int min;
private final int max;
private final Mask mask;
private final MutableBlockVector3 vector;
public Adjacent2DMask(Mask mask, int requiredMin, int requiredMax) {
this.mask = mask;
this.min = requiredMin;
this.max = requiredMax;
this.vector = new MutableBlockVector3();
}
@Override
public boolean test(BlockVector3 bv) {
vector.setComponents(bv);
double x = bv.x();
double z = bv.z();
vector.mutX(x + 1);
int count = 0;
if (mask.test(vector) && ++count == min && max >= 4) {
return true;
}
vector.mutX(x - 1);
if (mask.test(vector) && ++count == min && max >= 4) {
return true;
}
vector.mutX(x);
vector.mutZ(z + 1);
if (mask.test(vector) && ++count == min && max >= 4) {
return true;
}
vector.mutZ(z - 1);
if (mask.test(vector) && ++count == min && max >= 4) {
return true;
}
return count >= min && count <= max;
}
@Override
public Mask copy() {
return new Adjacent2DMask(mask.copy(), min, max);
}
}

Datei anzeigen

@ -0,0 +1,66 @@
package com.fastasyncworldedit.core.function.mask;
import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.function.mask.AbstractMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.math.BlockVector3;
/**
* Just an optimized version of the Adjacent Mask for single adjacency.
*/
public class AdjacentAny2DMask extends AbstractMask {
private final Mask mask;
private final MutableBlockVector3 mutable;
public AdjacentAny2DMask(Mask mask) {
this(mask, true);
}
public AdjacentAny2DMask(Mask mask, boolean cache) {
this.mask = cache ? CachedMask.cache(mask) : mask;
mutable = new MutableBlockVector3();
}
@Override
public boolean test(BlockVector3 v) {
int x = v.x();
int y = v.y();
int z = v.z();
if (mask.test(mutable.setComponents(x + 1, y, z))) {
return true;
}
if (mask.test(mutable.setComponents(x - 1, y, z))) {
return true;
}
if (mask.test(mutable.setComponents(x, y, z + 1))) {
return true;
}
return mask.test(mutable.setComponents(x, y, z - 1));
}
public boolean test(Extent extent, BlockVector3 v) {
AbstractExtentMask extentMask = (AbstractExtentMask) mask;
int x = v.x();
int y = v.y();
int z = v.z();
if (extentMask.test(extent, mutable.setComponents(x + 1, y, z))) {
return true;
}
if (extentMask.test(extent, mutable.setComponents(x - 1, y, z))) {
return true;
}
if (extentMask.test(extent, mutable.setComponents(x, y, z + 1))) {
return true;
}
return extentMask.test(extent, mutable.setComponents(x, y, z - 1));
}
@Override
public Mask copy() {
return new AdjacentAny2DMask(mask.copy(), false);
}
}

Datei anzeigen

@ -23,7 +23,7 @@ public class AdjacentAnyMask extends AbstractMask implements ResettableMask {
}
AdjacentAnyMask(CachedMask mask, int minY, int maxY) {
this.mask = CachedMask.cache(mask);
this.mask = mask;
mutable = new MutableBlockVector3();
this.minY = minY;
this.maxY = maxY;

Datei anzeigen

@ -461,7 +461,6 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet {
} catch (EOFException ignored) {
} catch (Exception e) {
e.printStackTrace();
e.printStackTrace();
}
try {
is.close();

Datei anzeigen

@ -62,4 +62,13 @@ public interface Filter {
}
/**
* Signals to the filter the edit has concluded
*
* @since TODO
*/
default void finish() {
}
}

Datei anzeigen

@ -7,6 +7,7 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.OutputExtent;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockStateHolder;
@ -139,4 +140,19 @@ public interface IChunkSet extends IBlocks, OutputExtent {
return this;
}
/**
* Set the side effects to be used when settings these blocks
*
* @since TODO
*/
void setSideEffectSet(@Nonnull SideEffectSet sideEffectSet);
/**
* Get the side effects to be used when settings these blocks
*
* @since TODO
*/
@Nonnull
SideEffectSet getSideEffectSet();
}

Datei anzeigen

@ -38,6 +38,11 @@ public interface IDelegateFilter extends Filter {
return this;
}
@Override
default void finish() {
getParent().finish();
}
Filter newInstance(Filter other);
}

Datei anzeigen

@ -10,6 +10,7 @@ import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.SideEffectSet;
import javax.annotation.Nullable;
import java.io.Flushable;
@ -81,6 +82,20 @@ public interface IQueueExtent<T extends IChunk> extends Flushable, Trimable, ICh
boolean isFastMode();
/**
* Set the side effects to be used with this extent
*
* @since TODO
*/
void setSideEffectSet(SideEffectSet sideEffectSet);
/**
* Get the side effects to be used with this extent
*
* @since TODO
*/
SideEffectSet getSideEffectSet();
/**
* Create a new root IChunk object. Full chunks will be reused, so a more optimized chunk can be
* returned in that case.

Datei anzeigen

@ -20,11 +20,14 @@ import com.fastasyncworldedit.core.queue.Filter;
import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.fastasyncworldedit.core.queue.IQueueExtent;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.BlockMask;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.RunContext;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
@ -32,6 +35,7 @@ import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Countable;
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;
@ -39,6 +43,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@ -58,11 +63,12 @@ public class ParallelQueueExtent extends PassthroughExtent {
// not very important)
private final boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length];
private final boolean fastmode;
private final SideEffectSet sideEffectSet;
private int changes;
private int lastException = Integer.MIN_VALUE;
private int exceptionCount = 0;
public ParallelQueueExtent(QueueHandler handler, World world, boolean fastmode) {
public ParallelQueueExtent(QueueHandler handler, World world, boolean fastmode, @Nullable SideEffectSet sideEffectSet) {
super(handler.getQueue(world, new BatchProcessorHolder(), new BatchProcessorHolder()));
this.world = world;
this.handler = handler;
@ -75,6 +81,7 @@ public class ParallelQueueExtent extends PassthroughExtent {
((MultiBatchProcessor) this.postProcessor.getProcessor()).setFaweExceptionArray(faweExceptionReasonsUsed);
}
this.fastmode = fastmode;
this.sideEffectSet = sideEffectSet == null ? SideEffectSet.defaults() : sideEffectSet;
}
/**
@ -121,7 +128,12 @@ public class ParallelQueueExtent extends PassthroughExtent {
@SuppressWarnings("rawtypes")
private IQueueExtent<IQueueChunk> getNewQueue() {
return handler.getQueue(world, this.processor, this.postProcessor);
SingleThreadQueueExtent queue = (SingleThreadQueueExtent) handler.getQueue(world, this.processor, this.postProcessor);
queue.setFastMode(fastmode);
queue.setSideEffectSet(sideEffectSet);
queue.setFaweExceptionArray(faweExceptionReasonsUsed);
enter(queue);
return queue;
}
@Override
@ -140,6 +152,8 @@ public class ParallelQueueExtent extends PassthroughExtent {
BlockVector2 pos = chunksIter.next();
block = getExtent().apply(block, filter, region, pos.x(), pos.z(), full);
}
getExtent().flush();
filter.finish();
} else {
final ForkJoinTask[] tasks = IntStream.range(0, size).mapToObj(i -> handler.submit(() -> {
try {
@ -147,13 +161,9 @@ public class ParallelQueueExtent extends PassthroughExtent {
final Region newRegion = region.clone();
// Create a chunk that we will reuse/reset for each operation
final SingleThreadQueueExtent queue = (SingleThreadQueueExtent) getNewQueue();
queue.setFastMode(fastmode);
queue.setFaweExceptionArray(faweExceptionReasonsUsed);
enter(queue);
synchronized (queue) {
try {
ChunkFilterBlock block = null;
while (true) {
// Get the next chunk posWeakChunk
final int chunkX;
@ -169,6 +179,7 @@ public class ParallelQueueExtent extends PassthroughExtent {
block = queue.apply(block, newFilter, newRegion, chunkX, chunkZ, full);
}
queue.flush();
filter.finish();
} catch (Throwable t) {
if (t instanceof FaweException) {
Fawe.handleFaweException(faweExceptionReasonsUsed, (FaweException) t, LOGGER);
@ -205,6 +216,24 @@ public class ParallelQueueExtent extends PassthroughExtent {
return filter;
}
@Override
protected Operation commitBefore() {
return new Operation() {
@Override
public Operation resume(final RunContext run) throws WorldEditException {
getExtent().commit();
processor.flush();
getExtent().flush();
return null;
}
@Override
public void cancel() {
}
};
}
@Override
public int countBlocks(Region region, Mask searchMask) {
return

Datei anzeigen

@ -27,6 +27,7 @@ import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.world.World;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import org.apache.logging.log4j.Logger;
@ -68,6 +69,7 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
private boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length];
private int lastException = Integer.MIN_VALUE;
private int exceptionCount = 0;
private SideEffectSet sideEffectSet = SideEffectSet.defaults();
public SingleThreadQueueExtent() {
}
@ -110,6 +112,16 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
this.fastmode = fastmode;
}
@Override
public void setSideEffectSet(SideEffectSet sideEffectSet) {
this.sideEffectSet = sideEffectSet;
}
@Override
public SideEffectSet getSideEffectSet() {
return sideEffectSet;
}
@Override
public int getMinY() {
return minY;
@ -120,6 +132,10 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
return maxY;
}
public World getWorld() {
return world;
}
/**
* Sets the cached boolean array of length {@code FaweException.Type.values().length} that determines if a thrown
* {@link FaweException} of type {@link FaweException.Type} should be output to console, rethrown to attempt to be visible
@ -278,10 +294,16 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
private ChunkHolder poolOrCreate(int chunkX, int chunkZ) {
ChunkHolder next = create(false);
next.init(this, chunkX, chunkZ);
next.setFastMode(isFastMode());
return next;
}
@Override
public IQueueChunk wrap(IQueueChunk chunk) {
chunk.setFastMode(isFastMode());
chunk.setSideEffectSet(getSideEffectSet());
return chunk;
}
@Override
public final IQueueChunk getOrCreateChunk(int x, int z) {
getChunkLock.lock();

Datei anzeigen

@ -6,6 +6,7 @@ import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.util.collection.MemBlockSet;
import com.sk89q.worldedit.math.BlockVector3;
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.BlockStateHolder;
@ -212,6 +213,16 @@ public class BitSetBlocks implements IChunkSet {
return false;
}
@Override
public void setSideEffectSet(SideEffectSet sideEffectSet) {
}
@Override
public SideEffectSet getSideEffectSet() {
return SideEffectSet.none();
}
@Override
public int getSectionCount() {
return layers;

Datei anzeigen

@ -9,6 +9,7 @@ import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.Pool;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypesCache;
@ -44,6 +45,7 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
public EnumMap<HeightMapType, int[]> heightMaps;
private boolean fastMode = false;
private int bitMask = -1;
private SideEffectSet sideEffectSet = SideEffectSet.defaults();
private CharSetBlocks() {
// Expand as we go
@ -374,10 +376,21 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
heightMaps != null ? new EnumMap<>(heightMaps) : null,
defaultOrdinal(),
fastMode,
bitMask
bitMask,
sideEffectSet
);
}
@Override
public void setSideEffectSet(SideEffectSet sideEffectSet) {
this.sideEffectSet = sideEffectSet;
}
@Override
public SideEffectSet getSideEffectSet() {
return sideEffectSet;
}
static char[][] createLightCopy(char[][] lightArr, int sectionCount) {
if (lightArr == null) {
return null;

Datei anzeigen

@ -9,6 +9,7 @@ import com.fastasyncworldedit.core.queue.IBlocks;
import com.fastasyncworldedit.core.queue.IChunkSet;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3;
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.BlockStateHolder;
@ -51,6 +52,7 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks {
private Map<HeightMapType, int[]> heightMaps;
private boolean fastMode;
private int bitMask;
private SideEffectSet sideEffectSet;
/**
* New instance given the data stored in a {@link CharSetBlocks} instance.
@ -71,7 +73,8 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks {
Map<HeightMapType, int[]> heightMaps,
char defaultOrdinal,
boolean fastMode,
int bitMask
int bitMask,
SideEffectSet sideEffectSet
) {
this.blocks = blocks;
this.minSectionPosition = minSectionPosition;
@ -87,6 +90,7 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks {
this.defaultOrdinal = defaultOrdinal;
this.fastMode = fastMode;
this.bitMask = bitMask;
this.sideEffectSet = sideEffectSet;
}
@Override
@ -480,10 +484,21 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks {
heightMaps != null ? new HashMap<>(heightMaps) : null,
defaultOrdinal,
fastMode,
bitMask
bitMask,
sideEffectSet
);
}
@Override
public void setSideEffectSet(SideEffectSet sideEffectSet) {
this.sideEffectSet = sideEffectSet;
}
@Override
public SideEffectSet getSideEffectSet() {
return sideEffectSet;
}
@Override
public boolean trim(boolean aggressive) {
return false;

Datei anzeigen

@ -15,6 +15,7 @@ import com.fastasyncworldedit.core.util.MemUtil;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
@ -51,6 +52,7 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
private boolean isInit = false; // Lighting handles queue differently. It relies on the chunk cache and not doing init.
private boolean createCopy = false;
private long initTime = -1L;
private SideEffectSet sideEffectSet;
private ChunkHolder() {
this.delegate = NULL;
@ -150,6 +152,16 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
return chunkSet != null && chunkSet.hasBiomes(layer);
}
@Override
public void setSideEffectSet(SideEffectSet sideEffectSet) {
this.sideEffectSet = sideEffectSet;
}
@Override
public SideEffectSet getSideEffectSet() {
return sideEffectSet;
}
public boolean isInit() {
return isInit;
}
@ -874,7 +886,6 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
public synchronized void filterBlocks(Filter filter, ChunkFilterBlock block, @Nullable Region region, boolean full) {
final IChunkGet get = getOrCreateGet();
final IChunkSet set = getOrCreateSet();
set.setFastMode(fastmode);
try {
block.filter(this, get, set, filter, region, full);
} finally {
@ -948,13 +959,21 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
return chunkSet;
}
public final IChunkSet getChunkSet() {
return chunkSet;
}
/**
* Create a wrapped set object
* - The purpose of wrapping is to allow different extents to intercept / alter behavior
* - e.g., caching, optimizations, filtering
*/
private IChunkSet newWrappedSet() {
return extent.getCachedSet(chunkX, chunkZ);
IChunkSet set = extent.getCachedSet(chunkX, chunkZ);
set.setFastMode(fastmode);
set.setSideEffectSet(sideEffectSet);
set.setBitMask(bitMask);
return set;
}
/**
@ -985,7 +1004,6 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
@Override
public synchronized T call() {
if (chunkSet != null && !chunkSet.isEmpty()) {
chunkSet.setBitMask(bitMask);
IChunkSet copy = chunkSet.createCopy();
return this.call(copy, () -> {
// Do nothing

Datei anzeigen

@ -8,6 +8,7 @@ import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.queue.IQueueChunk;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
@ -86,6 +87,16 @@ public final class NullChunk implements IQueueChunk {
return false;
}
@Override
public void setSideEffectSet(SideEffectSet sideEffectSet) {
}
@Override
public SideEffectSet getSideEffectSet() {
return SideEffectSet.none();
}
@Nonnull
public int[] getHeightMap(@Nullable HeightMapType type) {
return new int[256];

Datei anzeigen

@ -1,7 +1,11 @@
package com.fastasyncworldedit.core.util;
import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent;
import com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -21,6 +25,26 @@ public class ExtentTraverser<T extends Extent> {
this.parent = parent;
}
/**
* Get the world backing the given extent, if present, else null.
*
* @since TODO
*/
@Nullable
public static World getWorldFromExtent(Extent extent) {
if (extent.isWorld()) {
return (World) extent;
} else if (extent instanceof EditSession session) {
return session.getWorld();
} else if (extent instanceof SingleThreadQueueExtent stqe) {
return stqe.getWorld();
} else if (extent instanceof ParallelQueueExtent pqe) {
return ((SingleThreadQueueExtent) pqe.getExtent()).getWorld();
} else {
return new ExtentTraverser<>(extent).findAndGet(World.class);
}
}
public boolean exists() {
return root != null;
}

Datei anzeigen

@ -64,7 +64,10 @@ import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionIntersection;
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 +107,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 +419,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 +457,9 @@ public final class EditSessionBuilder {
fastMode = actor.getSession().hasFastMode();
}
}
if (fastMode) {
sideEffectSet = SideEffectSet.none();
}
if (checkMemory == null) {
checkMemory = actor != null && !this.fastMode;
}
@ -470,7 +485,12 @@ public final class EditSessionBuilder {
if (unwrapped instanceof IQueueExtent) {
extent = queue = (IQueueExtent) unwrapped;
} else if (Settings.settings().QUEUE.PARALLEL_THREADS > 1 && !Fawe.isMainThread()) {
ParallelQueueExtent parallel = new ParallelQueueExtent(Fawe.instance().getQueueHandler(), world, fastMode);
ParallelQueueExtent parallel = new ParallelQueueExtent(
Fawe.instance().getQueueHandler(),
world,
fastMode,
sideEffectSet
);
queue = parallel.getExtent();
extent = parallel;
} else {
@ -491,7 +511,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 +566,29 @@ 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)) {
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) || this.sideEffectSet.shouldApply(
SideEffect.VALIDATION)) {
Region region = allowedRegions == null || allowedRegions.length == 0
? null
: allowedRegions.length == 1 ? allowedRegions[0] : new RegionIntersection(allowedRegions);
queue.addProcessor(WorldEdit
.getInstance()
.getPlatformManager()
.queryCapability(Capability.WORLD_EDITING)
.getPlatformPlacementProcessor(extent, null, region));
}
if (!Settings.settings().EXPERIMENTAL.KEEP_ENTITIES_IN_BLOCKS) {
queue.addProcessor(new EntityInBlockRemovingProcessor());
@ -714,6 +750,13 @@ public final class EditSessionBuilder {
return changeSet;
}
/**
* Get the SideEffectSet that will be used
*/
public SideEffectSet getSideEffectSet() {
return sideEffectSet;
}
/**
* Get the ultimate resultant extent
*/

Datei anzeigen

@ -1749,6 +1749,7 @@ public class LocalSession implements TextureHolder {
}
builder.command(command);
builder.fastMode(!this.sideEffectSet.doesApplyAny());
builder.setSideEffectSet(this.sideEffectSet);
editSession = builder.build();

Datei anzeigen

@ -118,7 +118,7 @@ public class RegionCommands {
Actor actor, EditSession editSession,
@Selection Region region,
@Arg(desc = "The pattern of blocks to set")
Pattern pattern
Pattern pattern
) {
int affected = editSession.setBlocks(region, pattern);
if (affected != 0) {
@ -233,11 +233,11 @@ public class RegionCommands {
Actor actor, EditSession editSession,
@Selection Region region,
@Arg(desc = "The pattern of blocks to place")
Pattern pattern,
Pattern pattern,
@Arg(desc = "The thickness of the line", def = "0")
int thickness,
int thickness,
@Switch(name = 'h', desc = "Generate only a shell")
boolean shell
boolean shell
) throws WorldEditException {
if (!(region instanceof CuboidRegion cuboidregion)) {
actor.print(Caption.of("worldedit.line.cuboid-only"));
@ -266,11 +266,11 @@ public class RegionCommands {
Actor actor, EditSession editSession,
@Selection Region region,
@Arg(desc = "The pattern of blocks to place")
Pattern pattern,
Pattern pattern,
@Arg(desc = "The thickness of the curve", def = "0")
int thickness,
int thickness,
@Switch(name = 'h', desc = "Generate only a shell")
boolean shell
boolean shell
) throws WorldEditException {
if (!(region instanceof ConvexPolyhedralRegion cpregion)) {
actor.print(Caption.of("worldedit.curve.invalid-type"));
@ -298,9 +298,9 @@ public class RegionCommands {
public int replace(
Actor actor, EditSession editSession, @Selection Region region,
@Arg(desc = "The mask representing blocks to replace", def = "")
Mask from,
Mask from,
@Arg(desc = "The pattern of blocks to replace with")
Pattern to
Pattern to
) throws WorldEditException {
if (from == null) {
from = new ExistingBlockMask(editSession);
@ -324,7 +324,7 @@ public class RegionCommands {
public int overlay(
Actor actor, EditSession editSession, @Selection Region region,
@Arg(desc = "The pattern of blocks to overlay")
Pattern pattern
Pattern pattern
) throws WorldEditException {
int affected = editSession.overlayCuboidBlocks(region, pattern);
actor.print(Caption.of("worldedit.overlay.overlaid", TextComponent.of(affected)));
@ -380,7 +380,7 @@ public class RegionCommands {
public int center(
Actor actor, EditSession editSession, @Selection Region region,
@Arg(desc = "The pattern of blocks to set")
Pattern pattern
Pattern pattern
) throws WorldEditException {
int affected = editSession.center(region, pattern);
actor.print(Caption.of("worldedit.center.changed", TextComponent.of(affected)));
@ -412,7 +412,7 @@ public class RegionCommands {
public int walls(
Actor actor, EditSession editSession, @Selection Region region,
@Arg(desc = "The pattern of blocks to set")
Pattern pattern
Pattern pattern
) throws WorldEditException {
int affected = editSession.makeWalls(region, pattern);
actor.print(Caption.of("worldedit.walls.changed", TextComponent.of(affected)));
@ -431,7 +431,7 @@ public class RegionCommands {
public int faces(
Actor actor, EditSession editSession, @Selection Region region,
@Arg(desc = "The pattern of blocks to set")
Pattern pattern
Pattern pattern
) throws WorldEditException {
int affected = editSession.makeFaces(region, pattern);
actor.print(Caption.of("worldedit.faces.changed", TextComponent.of(affected)));
@ -451,9 +451,9 @@ public class RegionCommands {
public int smooth(
Actor actor, EditSession editSession, @Selection Region region,
@Arg(desc = "# of iterations to perform", def = "1")
int iterations,
int iterations,
@Arg(desc = "The mask of blocks to use as the height map", def = "")
Mask mask
Mask mask
) throws WorldEditException {
//FAWE start > the mask will have been initialised with a WorldWrapper extent (very bad/slow)
new MaskTraverser(mask).setNewExtent(editSession);
@ -526,11 +526,11 @@ public class RegionCommands {
public int snowSmooth(
Actor actor, EditSession editSession, @Selection Region region,
@Arg(desc = "# of iterations to perform", def = "1")
int iterations,
int iterations,
@ArgFlag(name = 'l', desc = "Set the amount of snow blocks under the snow", def = "1")
int snowBlockCount,
int snowBlockCount,
@ArgFlag(name = 'm', desc = "The mask of blocks to use as the height map")
Mask mask
Mask mask
) throws WorldEditException {
SnowHeightMap heightMap = new SnowHeightMap(editSession, region, mask);
HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1.0));
@ -554,22 +554,22 @@ public class RegionCommands {
Actor actor, World world, EditSession editSession, LocalSession session,
@Selection Region region,
@Arg(desc = "# of blocks to move", def = "1")
int count,
int count,
@Arg(desc = "The direction to move", def = Direction.AIM)
@Direction(includeDiagonals = true)
BlockVector3 direction,
BlockVector3 direction,
@Arg(desc = "The pattern of blocks to leave", def = "air")
Pattern replace,
Pattern replace,
@Switch(name = 's', desc = "Shift the selection to the target location")
boolean moveSelection,
boolean moveSelection,
@Switch(name = 'a', desc = "Ignore air blocks")
boolean ignoreAirBlocks,
boolean ignoreAirBlocks,
@Switch(name = 'e', desc = "Also copy entities")
boolean copyEntities,
boolean copyEntities,
@Switch(name = 'b', desc = "Also copy biomes")
boolean copyBiomes,
boolean copyBiomes,
@ArgFlag(name = 'm', desc = "Set the include mask, non-matching blocks become air")
Mask mask
Mask mask
) throws WorldEditException {
checkCommandArgument(count >= 1, "Multiplier must be >= 1");
@ -618,9 +618,9 @@ public class RegionCommands {
Actor actor, EditSession editSession,
@Selection Region region,
@Arg(desc = "BlockStateHolder", def = "air")
BlockStateHolder replace,
BlockStateHolder replace,
@Switch(name = 'm', desc = "Only fall within the vertical selection")
boolean notFullHeight
boolean notFullHeight
) throws WorldEditException {
int affected = editSession.fall(region, !notFullHeight, replace);
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", affected));
@ -639,20 +639,20 @@ public class RegionCommands {
@Selection Region region,
@Arg(desc = "# of copies to stack", def = "1")
@Confirm(Confirm.Processor.REGION)
int count,
int count,
@Arg(desc = "How far to move the contents each stack", def = Offset.FORWARD)
@Offset
BlockVector3 direction,
BlockVector3 direction,
@Switch(name = 's', desc = "Shift the selection to the last stacked copy")
boolean moveSelection,
boolean moveSelection,
@Switch(name = 'a', desc = "Ignore air blocks")
boolean ignoreAirBlocks,
boolean ignoreAirBlocks,
@Switch(name = 'e', desc = "Also copy entities")
boolean copyEntities,
boolean copyEntities,
@Switch(name = 'b', desc = "Also copy biomes")
boolean copyBiomes,
boolean copyBiomes,
@ArgFlag(name = 'm', desc = "Set the include mask, non-matching blocks become air")
Mask mask
Mask mask
) throws WorldEditException {
checkCommandArgument(count >= 1, "Count must be >= 1");
@ -704,13 +704,13 @@ public class RegionCommands {
Actor actor, World world, LocalSession session, EditSession editSession,
@Selection Region region,
@Arg(desc = "The seed to regenerate with, otherwise uses world seed", def = "")
Long seed,
Long seed,
@Switch(name = 'b', desc = "Regenerate biomes as well")
boolean regenBiomes,
boolean regenBiomes,
@Switch(name = 'r', desc = "If the seed should be randomized")
boolean randomSeed,
boolean randomSeed,
@Arg(desc = "Biome to apply for this regeneration (only works in overworld)", def = "")
BiomeType biomeType
BiomeType biomeType
) throws WorldEditException {
Mask mask = session.getMask();
boolean success;
@ -759,13 +759,13 @@ public class RegionCommands {
Actor actor, LocalSession session, EditSession editSession,
@Selection Region region,
@Arg(desc = "The expression to use", variable = true)
List<String> expression,
List<String> expression,
@Switch(name = 'r', desc = "Use the game's coordinate origin")
boolean useRawCoords,
boolean useRawCoords,
@Switch(name = 'o', desc = "Use the placement's coordinate origin")
boolean offset,
boolean offset,
@Switch(name = 'c', desc = "Use the selection's center as origin")
boolean offsetCenter
boolean offsetCenter
) throws WorldEditException {
final Vector3 zero;
Vector3 unit;
@ -837,11 +837,11 @@ public class RegionCommands {
Actor actor, EditSession editSession,
@Selection Region region,
@Arg(desc = "Thickness of the shell to leave", def = "0")
int thickness,
int thickness,
@Arg(desc = "The pattern of blocks to replace the hollowed area with", def = "air")
Pattern pattern,
Pattern pattern,
@ArgFlag(name = 'm', desc = "Mask to hollow with")
Mask mask
Mask mask
) throws WorldEditException {
checkCommandArgument(thickness >= 0, "Thickness must be >= 0");
//FAWE start > the mask will have been initialised with a WorldWrapper extent (very bad/slow)
@ -871,9 +871,9 @@ public class RegionCommands {
public int forest(
Actor actor, EditSession editSession, @Selection Region region,
@Arg(desc = "The type of tree to place", def = "tree")
TreeType type,
TreeType type,
@Arg(desc = "The density of the forest", def = "5")
double density
double density
) throws WorldEditException {
checkCommandArgument(0 <= density && density <= 100, "Density must be in [0, 100]");
int affected = editSession.makeForest(region, density / 100, type);
@ -893,7 +893,7 @@ public class RegionCommands {
public int flora(
Actor actor, EditSession editSession, @Selection Region region,
@Arg(desc = "The density of the forest", def = "5")
double density
double density
) throws WorldEditException {
checkCommandArgument(0 <= density && density <= 100, "Density must be in [0, 100]");
density = density / 100;
@ -929,7 +929,7 @@ public class RegionCommands {
.getInstance()
.getPlatformManager()
.queryCapability(Capability.WORLD_EDITING)
.getPlatformPlacementProcessor(editSession, null, true)
.getPlatformPlacementProcessor(editSession, null, region)
);
if (affected != 0) {
actor.print(Caption.of("worldedit.set.done", TextComponent.of(affected)));

Datei anzeigen

@ -19,16 +19,16 @@
package com.sk89q.worldedit.extension.platform;
import com.fastasyncworldedit.core.extent.processor.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.PlacementStateProcessor;
import com.fastasyncworldedit.core.extent.processor.lighting.Relighter;
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
import com.fastasyncworldedit.core.queue.IBatchProcessor;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.BlockTypeMask;
import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.registry.Keyed;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.io.ResourceLoader;
@ -281,10 +281,12 @@ public interface Platform extends Keyed {
}
/**
* Returns an {@link PlacementStateProcessor} instance for processing placed blocks to "fix" them.
* Returns an {@link PlacementStateProcessor} instance for processing placed blocks to "fix" them. Optional region to
* prevent any changes outside of, as sometimes block neighbours will also be updated otherwise.
*
* @since TODO
*/
default PlacementStateProcessor getPlatformPlacementProcessor(Extent extent, BlockTypeMask mask, boolean includeUnedited) {
default PlacementStateProcessor getPlatformPlacementProcessor(Extent extent, BlockTypeMask mask, @Nullable Region region) {
return null;
}
//FAWE end

Datei anzeigen

@ -21,6 +21,7 @@ package com.sk89q.worldedit.function.mask;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
@ -140,6 +141,10 @@ public class BlockTypeMask extends AbstractExtentMask {
public boolean test(BlockType block) {
return types[block.getInternalId()];
}
public <B extends BlockStateHolder<B>> boolean test(B blockStateHolder) {
return types[blockStateHolder.getBlockType().getInternalId()];
}
//FAWE end
@Nullable
@ -149,7 +154,7 @@ public class BlockTypeMask extends AbstractExtentMask {
}
@Override
public Mask copy() {
public BlockTypeMask copy() {
return new BlockTypeMask(getExtent(), types.clone(), hasAir);
}

Datei anzeigen

@ -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(Settings.settings().LIGHTING.MODE == 0 ? State.OFF : State.ON, true),
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;