Telesphoreo 2024-01-02 15:53:42 -06:00
commit 637dc2df15
No known key found for this signature in database
GPG Key ID: 9D1991811E093C02
17 changed files with 243 additions and 73 deletions

View File

@ -27,10 +27,10 @@ jobs:
cache: gradle cache: gradle
java-version: 17 java-version: 17
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v2 uses: github/codeql-action/init@v3
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v2 uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2 uses: github/codeql-action/analyze@v3

View File

@ -34,7 +34,7 @@ logger.lifecycle("""
******************************************* *******************************************
""") """)
var rootVersion by extra("2.8.4") var rootVersion by extra("2.8.5")
var snapshot by extra("SNAPSHOT") var snapshot by extra("SNAPSHOT")
var revision: String by extra("") var revision: String by extra("")
var buildNumber by extra("") var buildNumber by extra("")

View File

@ -24,7 +24,7 @@ dependencies {
implementation(gradleApi()) implementation(gradleApi())
implementation("org.ajoberstar.grgit:grgit-gradle:5.2.1") implementation("org.ajoberstar.grgit:grgit-gradle:5.2.1")
implementation("com.github.johnrengelman:shadow:8.1.1") implementation("com.github.johnrengelman:shadow:8.1.1")
implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.5.10") implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.5.11")
} }
kotlin { kotlin {

View File

@ -1,6 +1,6 @@
[versions] [versions]
# Minecraft expectations # Minecraft expectations
paper = "1.20.2-R0.1-SNAPSHOT" paper = "1.20.4-R0.1-SNAPSHOT"
fastutil = "8.5.9" fastutil = "8.5.9"
guava = "31.1-jre" guava = "31.1-jre"
log4j = "2.19.0" log4j = "2.19.0"
@ -14,16 +14,16 @@ mapmanager = "1.8.0-SNAPSHOT"
griefprevention = "16.18.1" griefprevention = "16.18.1"
griefdefender = "2.1.0-SNAPSHOT" griefdefender = "2.1.0-SNAPSHOT"
residence = "4.5._13.1" residence = "4.5._13.1"
towny = "0.100.0.8" towny = "0.100.0.11"
plotsquared = "7.2.0" plotsquared = "7.2.1"
# Third party # Third party
bstats = "3.0.2" bstats = "3.0.2"
sparsebitset = "1.3" sparsebitset = "1.3"
parallelgzip = "1.0.5" parallelgzip = "1.0.5"
adventure = "4.14.0" adventure = "4.15.0"
adventure-bukkit = "4.3.1" adventure-bukkit = "4.3.2"
checkerqual = "3.41.0" checkerqual = "3.42.0"
truezip = "6.8.4" truezip = "6.8.4"
auto-value = "1.10.4" auto-value = "1.10.4"
findbugs = "3.0.2" findbugs = "3.0.2"

View File

@ -12,6 +12,6 @@ repositories {
dependencies { dependencies {
// https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/ // https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.4-R0.1-20231207.202833-1") the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.4-R0.1-20231221.211952-22")
compileOnly(libs.paperlib) compileOnly(libs.paperlib)
} }

View File

@ -183,7 +183,7 @@ tasks.named<ShadowJar>("shadowJar") {
include(dependency("org.lz4:lz4-java:1.8.0")) include(dependency("org.lz4:lz4-java:1.8.0"))
} }
relocate("net.kyori", "com.fastasyncworldedit.core.adventure") { relocate("net.kyori", "com.fastasyncworldedit.core.adventure") {
include(dependency("net.kyori:adventure-nbt:4.14.0")) include(dependency("net.kyori:adventure-nbt:4.15.0"))
} }
relocate("com.zaxxer", "com.fastasyncworldedit.core.math") { relocate("com.zaxxer", "com.fastasyncworldedit.core.math") {
include(dependency("com.zaxxer:SparseBitSet:1.3")) include(dependency("com.zaxxer:SparseBitSet:1.3"))

View File

@ -721,6 +721,13 @@ public class Settings extends Config {
" - Requires clipboard.use-disk to be enabled" " - Requires clipboard.use-disk to be enabled"
}) })
public boolean SAVE_CLIPBOARD_NBT_TO_DISK = true; public boolean SAVE_CLIPBOARD_NBT_TO_DISK = true;
@Comment({
"Apply a file lock on the clipboard file (only relevant if clipboad.on-disk is enabled)",
" - Prevents other processes using the file whilst in use by FAWE",
" - This extends to other servers, useful if you have multiple servers using a unified clipboard folder",
" - May run into issues where a file lock is not correctly lifted"
})
public boolean LOCK_CLIPBOARD_FILE = false;
} }

View File

@ -6,12 +6,11 @@ import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IChunkSet;
import com.fastasyncworldedit.core.regions.RegionWrapper; import com.fastasyncworldedit.core.regions.RegionWrapper;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
public class HeightBoundExtent extends FaweRegionExtent { public class HeightBoundExtent extends FaweRegionExtent {
@ -50,7 +49,8 @@ public class HeightBoundExtent extends FaweRegionExtent {
@Override @Override
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
if (trimY(set, min, max, true) | trimNBT(set, this::contains)) { BlockVector3 chunkPos = chunk.getChunkBlockCoord().withY(0);
if (trimY(set, min, max, true) | trimNBT(set, this::contains, pos -> this.contains(pos.add(chunkPos)))) {
return set; return set;
} }
return null; return null;

View File

@ -305,22 +305,24 @@ public class DiskOptimizedClipboard extends LinearClipboard {
private void init() throws IOException { private void init() throws IOException {
if (this.fileChannel == null) { if (this.fileChannel == null) {
this.fileChannel = braf.getChannel(); this.fileChannel = braf.getChannel();
try { if (Settings.settings().CLIPBOARD.LOCK_CLIPBOARD_FILE) {
FileLock lock = this.fileChannel.lock(); try {
LOCK_HOLDER_CACHE.put(file.getName(), new LockHolder(lock)); FileLock lock = this.fileChannel.lock();
} catch (OverlappingFileLockException e) { LOCK_HOLDER_CACHE.put(file.getName(), new LockHolder(lock));
LockHolder existing = LOCK_HOLDER_CACHE.get(file.getName()); } catch (OverlappingFileLockException e) {
if (existing != null) { LockHolder existing = LOCK_HOLDER_CACHE.get(file.getName());
long ms = System.currentTimeMillis() - existing.lockHeldSince; if (existing != null) {
LOGGER.error( long ms = System.currentTimeMillis() - existing.lockHeldSince;
"Cannot lock clipboard file {} acquired by thread {}, {}ms ago", LOGGER.error(
file.getName(), "Cannot lock clipboard file {} acquired by thread {}, {}ms ago",
existing.thread, file.getName(),
ms existing.thread,
); ms
);
}
// Rethrow to prevent clipboard access
throw e;
} }
// Rethrow to prevent clipboard access
throw e;
} }
this.byteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, braf.length()); this.byteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, braf.length());
} }

View File

@ -155,7 +155,9 @@ public interface IBatchProcessor {
* Utility method to trim entity and blocks with a provided contains function. * Utility method to trim entity and blocks with a provided contains function.
* *
* @return false if chunk is empty of NBT * @return false if chunk is empty of NBT
* @deprecated tiles are stored in chunk-normalised coordinate space and thus cannot use the same function as entities
*/ */
@Deprecated(forRemoval = true, since = "2.8.4")
default boolean trimNBT(IChunkSet set, Function<BlockVector3, Boolean> contains) { default boolean trimNBT(IChunkSet set, Function<BlockVector3, Boolean> contains) {
Set<CompoundTag> ents = set.getEntities(); Set<CompoundTag> ents = set.getEntities();
if (!ents.isEmpty()) { if (!ents.isEmpty()) {
@ -169,6 +171,26 @@ public interface IBatchProcessor {
return !tiles.isEmpty() || !ents.isEmpty(); return !tiles.isEmpty() || !ents.isEmpty();
} }
/**
* Utility method to trim entity and blocks with a provided contains function.
*
* @return false if chunk is empty of NBT
* @since 2.8.4
*/
default boolean trimNBT(
IChunkSet set, Function<BlockVector3, Boolean> containsEntity, Function<BlockVector3, Boolean> containsTile
) {
Set<CompoundTag> ents = set.getEntities();
if (!ents.isEmpty()) {
ents.removeIf(ent -> !containsEntity.apply(ent.getEntityPosition().toBlockPoint()));
}
Map<BlockVector3, CompoundTag> tiles = set.getTiles();
if (!tiles.isEmpty()) {
tiles.entrySet().removeIf(blockVector3CompoundTagEntry -> !containsTile.apply(blockVector3CompoundTagEntry.getKey()));
}
return !tiles.isEmpty() || !ents.isEmpty();
}
/** /**
* Join two processors and return the result. * Join two processors and return the result.
*/ */

View File

@ -1,6 +1,7 @@
package com.fastasyncworldedit.core.queue; package com.fastasyncworldedit.core.queue;
import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -33,6 +34,16 @@ public interface IChunk extends Trimable, IChunkGet, IChunkSet {
*/ */
int getZ(); int getZ();
/**
* Return the minimum block coordinate of the chunk
*
* @return BlockVector3 of minimum block coordinate
* @since 2.8.4
*/
default BlockVector3 getChunkBlockCoord() {
return BlockVector3.at(getX() << 4, getMinY(), getZ() << 4);
}
/** /**
* If the chunk is a delegate, returns its parent's root * If the chunk is a delegate, returns its parent's root
* *

View File

@ -47,6 +47,7 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.command.util.Logging;
import com.sk89q.worldedit.command.util.annotation.Confirm; import com.sk89q.worldedit.command.util.annotation.Confirm;
import com.sk89q.worldedit.command.util.annotation.Preload; import com.sk89q.worldedit.command.util.annotation.Preload;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
@ -70,6 +71,7 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.NullRegion; import com.sk89q.worldedit.regions.NullRegion;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionIntersection; import com.sk89q.worldedit.regions.RegionIntersection;
@ -351,7 +353,9 @@ public class ClipboardCommands {
@Switch(name = 'e', desc = "Paste entities if available") @Switch(name = 'e', desc = "Paste entities if available")
boolean pasteEntities, boolean pasteEntities,
@Switch(name = 'b', desc = "Paste biomes if available") @Switch(name = 'b', desc = "Paste biomes if available")
boolean pasteBiomes boolean pasteBiomes,
@Switch(name = 'x', desc = "Remove existing entities in the affected region")
boolean removeEntities
) throws WorldEditException { ) throws WorldEditException {
ClipboardHolder holder = session.getClipboard(); ClipboardHolder holder = session.getClipboard();
final Clipboard clipboard = holder.getClipboard(); final Clipboard clipboard = holder.getClipboard();
@ -364,17 +368,22 @@ public class ClipboardCommands {
} }
Region region = clipboard.getRegion().clone(); Region region = clipboard.getRegion().clone();
if (selectPasted || onlySelect) { if (selectPasted || onlySelect || removeEntities) {
BlockVector3 clipboardOffset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin()); BlockVector3 clipboardOffset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin());
BlockVector3 realTo = to.add(holder.getTransform().apply(clipboardOffset.toVector3()).toBlockPoint()); BlockVector3 realTo = to.add(holder.getTransform().apply(clipboardOffset.toVector3()).toBlockPoint());
BlockVector3 max = realTo.add(holder BlockVector3 max = realTo.add(holder
.getTransform() .getTransform()
.apply(region.getMaximumPoint().subtract(region.getMinimumPoint()).toVector3()) .apply(region.getMaximumPoint().subtract(region.getMinimumPoint()).toVector3())
.toBlockPoint()); .toBlockPoint());
RegionSelector selector = new CuboidRegionSelector(world, realTo, max); if (removeEntities) {
session.setRegionSelector(world, selector); editSession.getEntities(new CuboidRegion(realTo, max)).forEach(Entity::remove);
selector.learnChanges(); }
selector.explainRegionAdjust(actor, session); if (selectPasted || onlySelect) {
RegionSelector selector = new CuboidRegionSelector(world, realTo, max);
session.setRegionSelector(world, selector);
selector.learnChanges();
selector.explainRegionAdjust(actor, session);
}
} }
if (onlySelect) { if (onlySelect) {
actor.print(Caption.of("worldedit.paste.selected")); actor.print(Caption.of("worldedit.paste.selected"));
@ -411,14 +420,19 @@ public class ClipboardCommands {
boolean pasteBiomes, boolean pasteBiomes,
@ArgFlag(name = 'm', desc = "Only paste blocks matching this mask") @ArgFlag(name = 'm', desc = "Only paste blocks matching this mask")
@ClipboardMask @ClipboardMask
Mask sourceMask Mask sourceMask,
//FAWE start - entity removal
@Switch(name = 'x', desc = "Remove existing entities in the affected region")
boolean removeEntities
//FAWE end
) throws WorldEditException { ) throws WorldEditException {
ClipboardHolder holder = session.getClipboard(); ClipboardHolder holder = session.getClipboard();
//FAWE start - use place //FAWE start - use place
if (holder.getTransform().isIdentity() && sourceMask == null) { if (holder.getTransform().isIdentity() && sourceMask == null) {
place(actor, world, session, editSession, ignoreAirBlocks, atOrigin, selectPasted, onlySelect, place(actor, world, session, editSession, ignoreAirBlocks, atOrigin, selectPasted, onlySelect,
pasteEntities, pasteBiomes pasteEntities, pasteBiomes, removeEntities
); );
return; return;
} }
@ -445,21 +459,29 @@ public class ClipboardCommands {
messages.addAll(Lists.newArrayList(operation.getStatusMessages())); messages.addAll(Lists.newArrayList(operation.getStatusMessages()));
} }
if (selectPasted || onlySelect) { if (selectPasted || onlySelect || removeEntities) {
BlockVector3 clipboardOffset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin()); BlockVector3 clipboardOffset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin());
Vector3 realTo = to.toVector3().add(holder.getTransform().apply(clipboardOffset.toVector3())); Vector3 realTo = to.toVector3().add(holder.getTransform().apply(clipboardOffset.toVector3()));
Vector3 max = realTo.add(holder Vector3 max = realTo.add(holder
.getTransform() .getTransform()
.apply(region.getMaximumPoint().subtract(region.getMinimumPoint()).toVector3())); .apply(region.getMaximumPoint().subtract(region.getMinimumPoint()).toVector3()));
final CuboidRegionSelector selector;
if (session.getRegionSelector(world) instanceof ExtendingCuboidRegionSelector) { // FAWE start - entity remova;l
selector = new ExtendingCuboidRegionSelector(world, realTo.toBlockPoint(), max.toBlockPoint()); if (removeEntities) {
} else { editSession.getEntities(new CuboidRegion(realTo.toBlockPoint(), max.toBlockPoint())).forEach(Entity::remove);
selector = new CuboidRegionSelector(world, realTo.toBlockPoint(), max.toBlockPoint()); }
if (selectPasted || onlySelect) {
//FAWE end
final CuboidRegionSelector selector;
if (session.getRegionSelector(world) instanceof ExtendingCuboidRegionSelector) {
selector = new ExtendingCuboidRegionSelector(world, realTo.toBlockPoint(), max.toBlockPoint());
} else {
selector = new CuboidRegionSelector(world, realTo.toBlockPoint(), max.toBlockPoint());
}
session.setRegionSelector(world, selector);
selector.learnChanges();
selector.explainRegionAdjust(actor, session);
} }
session.setRegionSelector(world, selector);
selector.learnChanges();
selector.explainRegionAdjust(actor, session);
} }
if (onlySelect) { if (onlySelect) {

View File

@ -25,27 +25,34 @@ import com.fastasyncworldedit.core.extent.HistoryExtent;
import com.fastasyncworldedit.core.extent.NullExtent; import com.fastasyncworldedit.core.extent.NullExtent;
import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet; import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet;
import com.fastasyncworldedit.core.internal.exception.FaweException; import com.fastasyncworldedit.core.internal.exception.FaweException;
import com.fastasyncworldedit.core.queue.Filter;
import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IBatchProcessor;
import com.fastasyncworldedit.core.util.ExtentTraverser; import com.fastasyncworldedit.core.util.ExtentTraverser;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.buffer.ForgetfulExtentBuffer; import com.sk89q.worldedit.extent.buffer.ForgetfulExtentBuffer;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.OperationQueue; import com.sk89q.worldedit.function.operation.OperationQueue;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -168,6 +175,7 @@ public class AbstractDelegateExtent implements Extent {
} }
} }
//FAWE start
@Override @Override
public boolean cancel() { public boolean cancel() {
ExtentTraverser<Extent> traverser = new ExtentTraverser<>(this); ExtentTraverser<Extent> traverser = new ExtentTraverser<>(this);
@ -188,7 +196,6 @@ public class AbstractDelegateExtent implements Extent {
return true; return true;
} }
//FAWE start
@Override @Override
public void removeEntity(int x, int y, int z, UUID uuid) { public void removeEntity(int x, int y, int z, UUID uuid) {
extent.removeEntity(x, y, z, uuid); extent.removeEntity(x, y, z, uuid);
@ -225,11 +232,72 @@ public class AbstractDelegateExtent implements Extent {
} }
} }
@Override
public boolean isWorld() {
return extent.isWorld();
}
@Override
public List<Countable<BlockType>> getBlockDistribution(final Region region) {
return extent.getBlockDistribution(region);
}
@Override
public List<Countable<BlockState>> getBlockDistributionWithData(final Region region) {
return extent.getBlockDistributionWithData(region);
}
@Override @Override
public int getMaxY() { public int getMaxY() {
return extent.getMaxY(); return extent.getMaxY();
} }
@Override
public int countBlocks(final Region region, final Set<BaseBlock> searchBlocks) {
return extent.countBlocks(region, searchBlocks);
}
@Override
public int countBlocks(final Region region, final Mask searchMask) {
return extent.countBlocks(region, searchMask);
}
@Override
public <B extends BlockStateHolder<B>> int setBlocks(final Region region, final B block) throws MaxChangedBlocksException {
return extent.setBlocks(region, block);
}
@Override
public int setBlocks(final Region region, final Pattern pattern) throws MaxChangedBlocksException {
return extent.setBlocks(region, pattern);
}
@Override
public <B extends BlockStateHolder<B>> int replaceBlocks(
final Region region,
final Set<BaseBlock> filter,
final B replacement
)
throws MaxChangedBlocksException {
return extent.replaceBlocks(region, filter, replacement);
}
@Override
public int replaceBlocks(final Region region, final Set<BaseBlock> filter, final Pattern pattern) throws
MaxChangedBlocksException {
return extent.replaceBlocks(region, filter, pattern);
}
@Override
public int replaceBlocks(final Region region, final Mask mask, final Pattern pattern) throws MaxChangedBlocksException {
return extent.replaceBlocks(region, mask, pattern);
}
@Override
public int setBlocks(final Set<BlockVector3> vset, final Pattern pattern) {
return extent.setBlocks(vset, pattern);
}
@Override @Override
public int getMinY() { public int getMinY() {
return extent.getMinY(); return extent.getMinY();
@ -295,23 +363,29 @@ public class AbstractDelegateExtent implements Extent {
return this; return this;
} }
@Override
public <T extends Filter> T apply(final Region region, final T filter, final boolean full) {
return extent.apply(region, filter, full);
}
//FAWE end
protected Operation commitBefore() { protected Operation commitBefore() {
return null; return null;
} }
@Override
public BiomeType getBiome(BlockVector3 position) {
//FAWE start - switch top x,y,z
return extent.getBiomeType(position.getX(), position.getY(), position.getZ());
//FAWE end
}
//FAWE start
@Override @Override
public BiomeType getBiomeType(int x, int y, int z) { public BiomeType getBiomeType(int x, int y, int z) {
return extent.getBiomeType(x, y, z); return extent.getBiomeType(x, y, z);
} }
@Override
public BiomeType getBiome(BlockVector3 position) {
return extent.getBiome(position);
}
/*
History
*/
@Override @Override
public int getEmittedLight(int x, int y, int z) { public int getEmittedLight(int x, int y, int z) {
return extent.getEmittedLight(x, y, z); return extent.getEmittedLight(x, y, z);
@ -341,13 +415,17 @@ public class AbstractDelegateExtent implements Extent {
new ExtentTraverser<>(this).setNext(new HistoryExtent(extent, changeSet)); new ExtentTraverser<>(this).setNext(new HistoryExtent(extent, changeSet));
} }
} }
//FAWE end
@Override @Override
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block) public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block)
throws WorldEditException { throws WorldEditException {
//FAWE start - switch to x,y,z
return extent.setBlock(position.getX(), position.getY(), position.getZ(), block); return extent.setBlock(position.getX(), position.getY(), position.getZ(), block);
//FAWE end
} }
//FAWE start
@Override @Override
public <T extends BlockStateHolder<T>> boolean setBlock( public <T extends BlockStateHolder<T>> boolean setBlock(
int x, int y, int x, int y,
@ -360,6 +438,7 @@ public class AbstractDelegateExtent implements Extent {
public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException {
return setBlock(x, y, z, getBlock(x, y, z).toBaseBlock(tile)); return setBlock(x, y, z, getBlock(x, y, z).toBaseBlock(tile));
} }
//FAWE end
@Override @Override
public boolean fullySupports3DBiomes() { public boolean fullySupports3DBiomes() {
@ -367,13 +446,16 @@ public class AbstractDelegateExtent implements Extent {
} }
@Override @Override
public boolean setBiome(int x, int y, int z, BiomeType biome) { public boolean setBiome(BlockVector3 position, BiomeType biome) {
return extent.setBiome(x, y, z, biome); //FAWE start - switch to x,y,z
return extent.setBiome(position.getX(), position.getY(), position.getZ(), biome);
//FAWE end
} }
//FAWE start
@Override @Override
public boolean setBiome(BlockVector3 position, BiomeType biome) { public boolean setBiome(int x, int y, int z, BiomeType biome) {
return extent.setBiome(position.getX(), position.getY(), position.getZ(), biome); return extent.setBiome(x, y, z, biome);
} }
@Override @Override

View File

@ -22,7 +22,6 @@ package com.sk89q.worldedit.regions;
import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock;
import com.fastasyncworldedit.core.math.BlockVectorSet; import com.fastasyncworldedit.core.math.BlockVectorSet;
import com.fastasyncworldedit.core.math.MutableBlockVector2;
import com.fastasyncworldedit.core.math.MutableBlockVector3; import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.Filter;
import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunk;
@ -805,7 +804,8 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
return set; return set;
} }
trimY(set, minY, maxY, true); trimY(set, minY, maxY, true);
trimNBT(set, this::contains); BlockVector3 chunkPos = chunk.getChunkBlockCoord().withY(0);
trimNBT(set, this::contains, pos -> this.contains(pos.add(chunkPos)));
return set; return set;
} }
if (tx >= minX && bx <= maxX && tz >= minZ && bz <= maxZ) { if (tx >= minX && bx <= maxX && tz >= minZ && bz <= maxZ) {
@ -868,8 +868,8 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
} }
set.setBlocks(layer, arr); set.setBlocks(layer, arr);
} }
final BlockVector3 chunkPos = BlockVector3.at(chunk.getX() << 4, 0, chunk.getZ() << 4);
trimNBT(set, this::contains); trimNBT(set, this::contains, pos -> this.contains(pos.add(chunkPos)));
return set; return set;
} }
return null; return null;
@ -893,7 +893,8 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
return null; return null;
} }
trimY(set, minY, maxY, false); trimY(set, minY, maxY, false);
trimNBT(set, this::contains); BlockVector3 chunkPos = chunk.getChunkBlockCoord().withY(0);
trimNBT(set, this::contains, pos -> this.contains(pos.add(chunkPos)));
return set; return set;
} }
if (tx >= minX && bx <= maxX && tz >= minZ && bz <= maxZ) { if (tx >= minX && bx <= maxX && tz >= minZ && bz <= maxZ) {
@ -943,7 +944,8 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
} }
set.setBlocks(layer, arr); set.setBlocks(layer, arr);
} }
trimNBT(set, bv3 -> !this.contains(bv3)); BlockVector3 chunkPos = chunk.getChunkBlockCoord().withY(0);
trimNBT(set, bv3 -> !this.contains(bv3), bv3 -> !this.contains(bv3.add(chunkPos)));
return set; return set;
} }
return set; return set;

View File

@ -425,7 +425,8 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
} }
} }
if (processExtra) { if (processExtra) {
trimNBT(set, this::contains); BlockVector3 chunkPos = chunk.getChunkBlockCoord().withY(0);
trimNBT(set, this::contains, pos -> this.contains(pos.add(chunkPos)));
} }
return set; return set;
} else { } else {
@ -477,7 +478,8 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
} }
} }
if (processExtra) { if (processExtra) {
trimNBT(set, bv3 -> !this.contains(bv3)); BlockVector3 chunkPos = chunk.getChunkBlockCoord().withY(0);
trimNBT(set, bv3 -> !this.contains(bv3), bv3 -> !this.contains(bv3.add(chunkPos)));
} }
return set; return set;
} else { } else {

View File

@ -178,9 +178,18 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
String name = property.getName(); String name = property.getName();
charSequence.setSubstring(propStrStart + name.length() + 2, state.length() - 1); charSequence.setSubstring(propStrStart + name.length() + 2, state.length() - 1);
int index = charSequence.length() <= 0 ? -1 : property.getIndexFor(charSequence); try {
if (index != -1) { int index = charSequence.length() <= 0 ? -1 : property.getIndexFor(charSequence);
return type.withPropertyId(index); if (index != -1) {
return type.withPropertyId(index);
}
} catch (Exception e) {
throw new InputParseException(Caption.of(
"fawe.error.invalid-block-state-property",
TextComponent.of(charSequence.toString()),
TextComponent.of(name),
TextComponent.of(state)
), e);
} }
} }
int stateId; int stateId;
@ -200,7 +209,17 @@ public class BlockState implements BlockStateHolder<BlockState>, Pattern {
case ',': { case ',': {
charSequence.setSubstring(last, i); charSequence.setSubstring(last, i);
if (property != null) { if (property != null) {
int index = property.getIndexFor(charSequence); int index;
try {
index = property.getIndexFor(charSequence);
} catch (Exception e) {
throw new InputParseException(Caption.of(
"fawe.error.invalid-block-state-property",
TextComponent.of(charSequence.toString()),
TextComponent.of(property.getName()),
TextComponent.of(state)
), e);
}
if (index == -1) { if (index == -1) {
throw SuggestInputParseException.of(charSequence.toString(), (List<Object>) property.getValues()); throw SuggestInputParseException.of(charSequence.toString(), (List<Object>) property.getValues());
} }

View File

@ -92,6 +92,7 @@
"fawe.error.parser.invalid-data": "Invalid data: {0}", "fawe.error.parser.invalid-data": "Invalid data: {0}",
"fawe.error.unsupported": "Unsupported!", "fawe.error.unsupported": "Unsupported!",
"fawe.error.invalid-block-type": "Does not match a valid block type: {0}", "fawe.error.invalid-block-type": "Does not match a valid block type: {0}",
"fawe.error.invalid-block-state-property": "Cannot parse value `{0}` for property `{1}`, block state: `{2}`",
"fawe.error.nbt.forbidden": "You are not allowed to use nbt. Lacking permission: {0}", "fawe.error.nbt.forbidden": "You are not allowed to use nbt. Lacking permission: {0}",
"fawe.error.invalid-arguments": "Invalid amount of arguments. Expected: {0}", "fawe.error.invalid-arguments": "Invalid amount of arguments. Expected: {0}",
"fawe.error.unrecognised-tag": "Unrecognised tag: {0} {1}", "fawe.error.unrecognised-tag": "Unrecognised tag: {0} {1}",