Merge remote-tracking branch 'upstream/main'
# Conflicts: # build.gradle.kts # settings.gradle.kts # worldedit-bukkit/build.gradle.kts
This commit is contained in:
@ -12,7 +12,7 @@ applyPlatformAndCoreConfiguration()
|
||||
dependencies {
|
||||
constraints {
|
||||
implementation(libs.snakeyaml) {
|
||||
version { strictly("2.0") }
|
||||
version { strictly("2.2") }
|
||||
because("Bukkit provides SnakeYaml")
|
||||
}
|
||||
}
|
||||
@ -46,7 +46,6 @@ dependencies {
|
||||
implementation(libs.findbugs)
|
||||
implementation(libs.rhino)
|
||||
compileOnly(libs.adventureApi)
|
||||
compileOnlyApi(libs.adventureNbt)
|
||||
compileOnlyApi(libs.adventureMiniMessage)
|
||||
implementation(libs.zstd) { isTransitive = false }
|
||||
compileOnly(libs.paster)
|
||||
@ -56,10 +55,10 @@ dependencies {
|
||||
antlr(libs.antlr4)
|
||||
implementation(libs.antlr4Runtime)
|
||||
implementation(libs.jsonSimple) { isTransitive = false }
|
||||
implementation(platform(libs.linBus.bom))
|
||||
|
||||
// Tests
|
||||
testRuntimeOnly(libs.log4jCore)
|
||||
testImplementation(libs.adventureNbt)
|
||||
testImplementation(libs.parallelgzip)
|
||||
}
|
||||
|
||||
|
||||
@ -1,16 +1,12 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version "1.8.20"
|
||||
kotlin("jvm") version "1.9.23"
|
||||
application
|
||||
}
|
||||
|
||||
applyCommonConfiguration()
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
kotlinOptions.jvmTarget = "17"
|
||||
}
|
||||
|
||||
application.mainClass.set("com.sk89q.worldedit.internal.util.DocumentationPrinter")
|
||||
tasks.named<JavaExec>("run") {
|
||||
workingDir = rootProject.projectDir
|
||||
|
||||
@ -125,7 +125,7 @@ public class MobSpawnerBlock extends BaseBlock {
|
||||
|
||||
@Override
|
||||
public CompoundTag getNbtData() {
|
||||
Map<String, Tag> values = new HashMap<>();
|
||||
Map<String, Tag<?, ?>> values = new HashMap<>();
|
||||
values.put("Delay", new ShortTag(delay));
|
||||
values.put("SpawnCount", new ShortTag(spawnCount));
|
||||
values.put("SpawnRange", new ShortTag(spawnRange));
|
||||
@ -170,7 +170,7 @@ public class MobSpawnerBlock extends BaseBlock {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Tag> values = rootTag.getValue();
|
||||
Map<String, Tag<?, ?>> values = rootTag.getValue();
|
||||
|
||||
Tag t = values.get("id");
|
||||
if (!(t instanceof StringTag) || !((StringTag) t).getValue().equals(getNbtId())) {
|
||||
|
||||
@ -104,7 +104,7 @@ public class SignBlock extends BaseBlock {
|
||||
|
||||
@Override
|
||||
public CompoundTag getNbtData() {
|
||||
Map<String, Tag> values = new HashMap<>();
|
||||
Map<String, Tag<?, ?>> values = new HashMap<>();
|
||||
if (isLegacy()) {
|
||||
values.put("Text1", new StringTag(text[0]));
|
||||
values.put("Text2", new StringTag(text[1]));
|
||||
@ -112,7 +112,7 @@ public class SignBlock extends BaseBlock {
|
||||
values.put("Text4", new StringTag(text[3]));
|
||||
} else {
|
||||
ListTag messages = new ListTag(StringTag.class, Arrays.stream(text).map(StringTag::new).collect(Collectors.toList()));
|
||||
Map<String, Tag> frontTextTag = new HashMap<>();
|
||||
Map<String, Tag<?, ?>> frontTextTag = new HashMap<>();
|
||||
frontTextTag.put("messages", messages);
|
||||
values.put("front_text", new CompoundTag(frontTextTag));
|
||||
}
|
||||
@ -125,9 +125,9 @@ public class SignBlock extends BaseBlock {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Tag> values = rootTag.getValue();
|
||||
Map<String, Tag<?, ?>> values = rootTag.getValue();
|
||||
|
||||
Tag t;
|
||||
Tag<?, ?> t;
|
||||
|
||||
text = new String[]{EMPTY, EMPTY, EMPTY, EMPTY};
|
||||
|
||||
|
||||
@ -100,8 +100,8 @@ public class SkullBlock extends BaseBlock {
|
||||
|
||||
@Override
|
||||
public CompoundTag getNbtData() {
|
||||
Map<String, Tag> values = new HashMap<>();
|
||||
Map<String, Tag> inner = new HashMap<>();
|
||||
Map<String, Tag<?, ?>> values = new HashMap<>();
|
||||
Map<String, Tag<?, ?>> inner = new HashMap<>();
|
||||
inner.put("Name", new StringTag(owner));
|
||||
values.put(DeprecationUtil.getHeadOwnerKey(), new CompoundTag(inner));
|
||||
return new CompoundTag(values);
|
||||
@ -113,7 +113,7 @@ public class SkullBlock extends BaseBlock {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Tag> values = rootTag.getValue();
|
||||
Map<String, Tag<?, ?>> values = rootTag.getValue();
|
||||
|
||||
Tag t;
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ package com.fastasyncworldedit.core;
|
||||
|
||||
import com.fastasyncworldedit.core.configuration.Settings;
|
||||
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||
import com.fastasyncworldedit.core.queue.implementation.QueueHandler;
|
||||
import com.fastasyncworldedit.core.util.CachedTextureUtil;
|
||||
import com.fastasyncworldedit.core.util.CleanTextureUtil;
|
||||
@ -13,8 +14,8 @@ import com.fastasyncworldedit.core.util.TaskManager;
|
||||
import com.fastasyncworldedit.core.util.TextureUtil;
|
||||
import com.fastasyncworldedit.core.util.WEManager;
|
||||
import com.fastasyncworldedit.core.util.task.KeyQueuedExecutorService;
|
||||
import com.fastasyncworldedit.core.util.task.UUIDKeyQueuedThreadFactory;
|
||||
import com.github.luben.zstd.Zstd;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||
import net.jpountz.lz4.LZ4Factory;
|
||||
@ -36,46 +37,43 @@ import java.lang.management.MemoryUsage;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* [ WorldEdit action]
|
||||
* |
|
||||
* \|/
|
||||
* [ WorldEdit action ]
|
||||
* <br>
|
||||
* [ EditSession ] - The change is processed (area restrictions, change limit, block type)
|
||||
* |
|
||||
* \|/
|
||||
* [Block change] - A block change from some location
|
||||
* |
|
||||
* \|/
|
||||
* <br>
|
||||
* [ Block change ] - A block change from some location
|
||||
* <br>
|
||||
* [ Set Queue ] - The SetQueue manages the implementation specific queue
|
||||
* |
|
||||
* \|/
|
||||
* <br>
|
||||
* [ Fawe Queue] - A queue of chunks - check if the queue has the chunk for a change
|
||||
* |
|
||||
* \|/
|
||||
* <br>
|
||||
* [ Fawe Chunk Implementation ] - Otherwise create a new FaweChunk object which is a wrapper around the Chunk object
|
||||
* |
|
||||
* \|/
|
||||
* <br>
|
||||
* [ Execution ] - When done, the queue then sets the blocks for the chunk, performs lighting updates and sends the chunk packet to the clients
|
||||
* <p>
|
||||
* Why it's faster:
|
||||
* - The chunk is modified directly rather than through the API
|
||||
* \ Removes some overhead, and means some processing can be done async
|
||||
* - Lighting updates are performed on the chunk level rather than for every block
|
||||
* \ e.g., A blob of stone: only the visible blocks need to have the lighting calculated
|
||||
* - Block changes are sent with a chunk packet
|
||||
* \ A chunk packet is generally quicker to create and smaller for large world edits
|
||||
* - No physics updates
|
||||
* \ Physics updates are slow, and are usually performed on each block
|
||||
* - Block data shortcuts
|
||||
* \ Some known blocks don't need to have the data set or accessed (e.g., air is never going to have data)
|
||||
* - Remove redundant extents
|
||||
* \ Up to 11 layers of extents can be removed
|
||||
* - History bypassing
|
||||
* \ FastMode bypasses history and means blocks in the world don't need to be checked and recorded
|
||||
* <br> The chunk is modified directly rather than through the API
|
||||
* - Removes some overhead, and means some processing can be done async
|
||||
* <br> Lighting updates are performed on the chunk level rather than for every block
|
||||
* - e.g., A blob of stone: only the visible blocks need to have the lighting calculated
|
||||
* <br> Block changes are sent with a chunk packet
|
||||
* - A chunk packet is generally quicker to create and smaller for large world edits
|
||||
* <br> No physics updates
|
||||
* - Physics updates are slow, and are usually performed on each block
|
||||
* <br> Block data shortcuts
|
||||
* - Some known blocks don't need to have the data set or accessed (e.g., air is never going to have data)
|
||||
* <br> Remove redundant extents
|
||||
* - Up to 11 layers of extents can be removed
|
||||
* <br> History bypassing
|
||||
* - FastMode bypasses history and means blocks in the world don't need to be checked and recorded
|
||||
*/
|
||||
public class Fawe {
|
||||
|
||||
@ -91,7 +89,7 @@ public class Fawe {
|
||||
* The platform specific implementation.
|
||||
*/
|
||||
private final IFawe implementation;
|
||||
private final KeyQueuedExecutorService<UUID> clipboardExecutor;
|
||||
private final KeyQueuedExecutorService<UUID> uuidKeyQueuedExecutorService;
|
||||
private FaweVersion version;
|
||||
private TextureUtil textures;
|
||||
private QueueHandler queueHandler;
|
||||
@ -105,6 +103,8 @@ public class Fawe {
|
||||
* Implementation dependent stuff
|
||||
*/
|
||||
this.setupConfigs();
|
||||
FaweLimit.MAX.CONFIRM_LARGE =
|
||||
Settings.settings().LIMITS.get("default").CONFIRM_LARGE || Settings.settings().GENERAL.LIMIT_UNLIMITED_CONFIRMS;
|
||||
TaskManager.IMP = this.implementation.getTaskManager();
|
||||
|
||||
TaskManager.taskManager().async(() -> {
|
||||
@ -137,14 +137,13 @@ public class Fawe {
|
||||
}, 0);
|
||||
|
||||
TaskManager.taskManager().repeat(timer, 1);
|
||||
|
||||
clipboardExecutor = new KeyQueuedExecutorService<>(new ThreadPoolExecutor(
|
||||
uuidKeyQueuedExecutorService = new KeyQueuedExecutorService<>(new ThreadPoolExecutor(
|
||||
1,
|
||||
Settings.settings().QUEUE.PARALLEL_THREADS,
|
||||
0L,
|
||||
TimeUnit.MILLISECONDS,
|
||||
new LinkedBlockingQueue<>(),
|
||||
new ThreadFactoryBuilder().setNameFormat("fawe-clipboard-%d").build()
|
||||
new UUIDKeyQueuedThreadFactory()
|
||||
));
|
||||
}
|
||||
|
||||
@ -362,6 +361,18 @@ public class Fawe {
|
||||
Settings.settings().QUEUE.PARALLEL_THREADS
|
||||
);
|
||||
}
|
||||
if (Settings.settings().HISTORY.DELETE_DISK_ON_LOGOUT && Settings.settings().HISTORY.USE_DATABASE) {
|
||||
LOGGER.warn("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
LOGGER.warn("!!! !!!");
|
||||
LOGGER.warn("!!! Using history database whilst deleting disk history! !!!");
|
||||
LOGGER.warn("!!! You will not be able to rollback edits after a user logs !!!");
|
||||
LOGGER.warn("!!! out, recommended to disable delete-disk-on-logout if you !!!");
|
||||
LOGGER.warn("!!! you want to have full history rollback functionality. !!!");
|
||||
LOGGER.warn("!!! Disable use-database if you do not need to have rollback !!!");
|
||||
LOGGER.warn("!!! functionality and wish to disable this warning. !!!");
|
||||
LOGGER.warn("!!! !!!");
|
||||
LOGGER.warn("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||
}
|
||||
try {
|
||||
byte[] in = new byte[0];
|
||||
byte[] compressed = LZ4Factory.fastestJavaInstance().fastCompressor().compress(in);
|
||||
@ -448,9 +459,58 @@ public class Fawe {
|
||||
*
|
||||
* @return Executor used for clipboard IO if clipboard on disk is enabled or null
|
||||
* @since 2.6.2
|
||||
* @deprecated Use any of {@link Fawe#submitUUIDKeyQueuedTask(UUID, Runnable)},
|
||||
* {@link Fawe#submitUUIDKeyQueuedTask(UUID, Runnable, Object)}, {@link Fawe#submitUUIDKeyQueuedTask(UUID, Callable)}
|
||||
* to ensure if a thread is already a UUID-queued thread, the task is immediately run
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2.12.1")
|
||||
public KeyQueuedExecutorService<UUID> getClipboardExecutor() {
|
||||
return this.clipboardExecutor;
|
||||
return this.uuidKeyQueuedExecutorService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit a task to the UUID key-queued executor
|
||||
*
|
||||
* @return Future representing the tank
|
||||
* @since 2.12.1
|
||||
*/
|
||||
public Future<?> submitUUIDKeyQueuedTask(UUID uuid, Runnable runnable) {
|
||||
if (Thread.currentThread() instanceof UUIDKeyQueuedThreadFactory.UUIDKeyQueuedThread) {
|
||||
runnable.run();
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
return this.uuidKeyQueuedExecutorService.submit(uuid, runnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit a task to the UUID key-queued executor
|
||||
*
|
||||
* @return Future representing the tank
|
||||
* @since 2.12.1
|
||||
*/
|
||||
public <T> Future<T> submitUUIDKeyQueuedTask(UUID uuid, Runnable runnable, T result) {
|
||||
if (Thread.currentThread() instanceof UUIDKeyQueuedThreadFactory.UUIDKeyQueuedThread) {
|
||||
runnable.run();
|
||||
return CompletableFuture.completedFuture(result);
|
||||
}
|
||||
return this.uuidKeyQueuedExecutorService.submit(uuid, runnable, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit a task to the UUID key-queued executor
|
||||
*
|
||||
* @return Future representing the tank
|
||||
* @since 2.12.1
|
||||
*/
|
||||
public <T> Future<T> submitUUIDKeyQueuedTask(UUID uuid, Callable<T> callable) {
|
||||
if (Thread.currentThread() instanceof UUIDKeyQueuedThreadFactory.UUIDKeyQueuedThread) {
|
||||
try {
|
||||
return CompletableFuture.completedFuture(callable.call());
|
||||
} catch (Throwable t) {
|
||||
return CompletableFuture.failedFuture(t);
|
||||
}
|
||||
}
|
||||
return this.uuidKeyQueuedExecutorService.submit(uuid, callable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -116,7 +116,10 @@ public class FaweAPI {
|
||||
* @param file the file to load
|
||||
* @return a clipboard containing the schematic
|
||||
* @see ClipboardFormat
|
||||
* @deprecated Opens streams that are not then closed. Use {@link ClipboardFormats#findByFile(File)} and its relevant
|
||||
* methods to allow closing created streams/closing the reader (which will close the stream(s))
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2.11.1")
|
||||
public static Clipboard load(File file) throws IOException {
|
||||
return ClipboardFormats.findByFile(file).load(file);
|
||||
}
|
||||
@ -339,11 +342,11 @@ public class FaweAPI {
|
||||
final BlockVector3 bot = selection.getMinimumPoint();
|
||||
final BlockVector3 top = selection.getMaximumPoint();
|
||||
|
||||
final int minX = bot.getBlockX() >> 4;
|
||||
final int minZ = bot.getBlockZ() >> 4;
|
||||
final int minX = bot.x() >> 4;
|
||||
final int minZ = bot.z() >> 4;
|
||||
|
||||
final int maxX = top.getBlockX() >> 4;
|
||||
final int maxZ = top.getBlockZ() >> 4;
|
||||
final int maxX = top.x() >> 4;
|
||||
final int maxZ = top.z() >> 4;
|
||||
|
||||
int count = 0;
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@ import com.fastasyncworldedit.core.util.collection.CleanableThreadLocal;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.sk89q.jnbt.ByteArrayTag;
|
||||
import com.sk89q.jnbt.ByteTag;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -48,7 +49,6 @@ import java.util.Map.Entry;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -60,16 +60,17 @@ import java.util.function.Supplier;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public enum FaweCache implements Trimable {
|
||||
/**
|
||||
* @deprecated Use {@link #INSTANCE} to get an instance.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2.0.0")
|
||||
IMP,
|
||||
/**
|
||||
* @since 2.0.0
|
||||
*/
|
||||
INSTANCE;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #INSTANCE} to get an instance.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2.0.0")
|
||||
public static final FaweCache IMP = INSTANCE;
|
||||
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
|
||||
public final int BLOCKS_PER_LAYER = 4096;
|
||||
@ -191,17 +192,22 @@ public enum FaweCache implements Trimable {
|
||||
Type.OUTSIDE_REGION
|
||||
);
|
||||
public static final FaweException MAX_CHECKS = new FaweException(
|
||||
Caption.of("fawe.cancel.reason.max" + ".checks"),
|
||||
Caption.of("fawe.cancel.reason.max.checks"),
|
||||
Type.MAX_CHECKS,
|
||||
true
|
||||
);
|
||||
public static final FaweException MAX_FAILS = new FaweException(
|
||||
Caption.of("fawe.cancel.reason.max.fails"),
|
||||
Type.MAX_CHECKS,
|
||||
true
|
||||
);
|
||||
public static final FaweException MAX_CHANGES = new FaweException(
|
||||
Caption.of("fawe.cancel.reason.max" + ".changes"),
|
||||
Caption.of("fawe.cancel.reason.max.changes"),
|
||||
Type.MAX_CHANGES,
|
||||
false
|
||||
);
|
||||
public static final FaweException LOW_MEMORY = new FaweException(
|
||||
Caption.of("fawe.cancel.reason.low" + ".memory"),
|
||||
Caption.of("fawe.cancel.reason.low.memory"),
|
||||
Type.LOW_MEMORY,
|
||||
false
|
||||
);
|
||||
@ -531,7 +537,7 @@ public enum FaweCache implements Trimable {
|
||||
}
|
||||
|
||||
public CompoundTag asTag(Map<String, Object> value) {
|
||||
HashMap<String, Tag> map = new HashMap<>();
|
||||
HashMap<String, Tag<?, ?>> map = new HashMap<>();
|
||||
for (Map.Entry<String, Object> entry : value.entrySet()) {
|
||||
Object child = entry.getValue();
|
||||
Tag tag = asTag(child);
|
||||
@ -611,12 +617,38 @@ public enum FaweCache implements Trimable {
|
||||
/*
|
||||
Thread stuff
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a new blocking executor with default name and FaweCache logger
|
||||
*
|
||||
* @return new blocking executor
|
||||
*/
|
||||
public ThreadPoolExecutor newBlockingExecutor() {
|
||||
return newBlockingExecutor("FAWE Blocking Executor - %d");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new blocking executor with specified name and FaweCache logger
|
||||
*
|
||||
* @return new blocking executor
|
||||
* @since 2.9.0
|
||||
*/
|
||||
public ThreadPoolExecutor newBlockingExecutor(String name) {
|
||||
return newBlockingExecutor(name, LOGGER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new blocking executor with specified name and logger
|
||||
*
|
||||
* @return new blocking executor
|
||||
* @since 2.9.0
|
||||
*/
|
||||
public ThreadPoolExecutor newBlockingExecutor(String name, Logger logger) {
|
||||
int nThreads = Settings.settings().QUEUE.PARALLEL_THREADS;
|
||||
ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(nThreads, true);
|
||||
return new ThreadPoolExecutor(nThreads, nThreads,
|
||||
0L, TimeUnit.MILLISECONDS, queue,
|
||||
Executors.defaultThreadFactory(),
|
||||
new ThreadFactoryBuilder().setNameFormat(name).build(),
|
||||
new ThreadPoolExecutor.CallerRunsPolicy()
|
||||
) {
|
||||
|
||||
@ -651,10 +683,10 @@ public enum FaweCache implements Trimable {
|
||||
int hash = throwable.getMessage() != null ? throwable.getMessage().hashCode() : 0;
|
||||
if (hash != lastException) {
|
||||
lastException = hash;
|
||||
LOGGER.catching(throwable);
|
||||
logger.catching(throwable);
|
||||
count = 0;
|
||||
} else if (count < Settings.settings().QUEUE.PARALLEL_THREADS) {
|
||||
LOGGER.warn(throwable.getMessage());
|
||||
logger.warn(throwable.getMessage());
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@ -664,10 +696,10 @@ public enum FaweCache implements Trimable {
|
||||
private void handleFaweException(FaweException e) {
|
||||
FaweException.Type type = e.getType();
|
||||
if (e.getType() == FaweException.Type.OTHER) {
|
||||
LOGGER.catching(e);
|
||||
logger.catching(e);
|
||||
} else if (!faweExceptionReasonsUsed[type.ordinal()]) {
|
||||
faweExceptionReasonsUsed[type.ordinal()] = true;
|
||||
LOGGER.warn("FaweException: " + e.getMessage());
|
||||
logger.warn("FaweException: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -50,9 +50,9 @@ public class BlendBall implements Brush {
|
||||
final int outsetSize = (int) (size + 1);
|
||||
double brushSizeSquared = size * size;
|
||||
|
||||
int tx = position.getBlockX();
|
||||
int ty = position.getBlockY();
|
||||
int tz = position.getBlockZ();
|
||||
int tx = position.x();
|
||||
int ty = position.y();
|
||||
int tz = position.z();
|
||||
|
||||
int[] frequency = new int[BlockTypes.size()];
|
||||
|
||||
|
||||
@ -81,9 +81,9 @@ public class CatenaryBrush implements Brush, ResettableTool {
|
||||
return pos1.add(pos2).divide(2).toBlockPoint();
|
||||
}
|
||||
double curveLen = pos1.distance(pos2) * lenPercent;
|
||||
double dy = pos2.getY() - pos1.getY();
|
||||
double dx = pos2.getX() - pos1.getX();
|
||||
double dz = pos2.getZ() - pos1.getZ();
|
||||
double dy = pos2.y() - pos1.y();
|
||||
double dx = pos2.x() - pos1.x();
|
||||
double dz = pos2.z() - pos1.z();
|
||||
double dh = Math.sqrt(dx * dx + dz * dz);
|
||||
double g = Math.sqrt(curveLen * curveLen - dy * dy) / 2;
|
||||
double a = 0.00001;
|
||||
|
||||
@ -54,9 +54,9 @@ public class CommandBrush implements Brush {
|
||||
position.subtract(radius, radius, radius),
|
||||
position.add(radius, radius, radius)
|
||||
);
|
||||
String replaced = command.replace("{x}", Integer.toString(position.getBlockX()))
|
||||
.replace("{y}", Integer.toString(position.getBlockY()))
|
||||
.replace("{z}", Integer.toString(position.getBlockZ()))
|
||||
String replaced = command.replace("{x}", Integer.toString(position.x()))
|
||||
.replace("{y}", Integer.toString(position.y()))
|
||||
.replace("{z}", Integer.toString(position.z()))
|
||||
.replace("{world}", editSession.getWorld().getName())
|
||||
.replace("{size}", Integer.toString(radius));
|
||||
|
||||
|
||||
@ -65,11 +65,11 @@ public class CopyPastaBrush implements Brush, ResettableTool {
|
||||
mask = Masks.alwaysTrue();
|
||||
}
|
||||
final ResizableClipboardBuilder builder = new ResizableClipboardBuilder(editSession.getWorld());
|
||||
final int minY = position.getBlockY();
|
||||
final int minY = position.y();
|
||||
mask = new AbstractDelegateMask(mask) {
|
||||
@Override
|
||||
public boolean test(BlockVector3 vector) {
|
||||
if (super.test(vector) && vector.getBlockY() >= minY) {
|
||||
if (super.test(vector) && vector.y() >= minY) {
|
||||
BaseBlock block = editSession.getFullBlock(vector);
|
||||
if (!block.getBlockType().getMaterial().isAir()) {
|
||||
builder.add(vector, BlockTypes.AIR.getDefaultState().toBaseBlock(), block);
|
||||
@ -91,7 +91,7 @@ public class CopyPastaBrush implements Brush, ResettableTool {
|
||||
newClipboard.setOrigin(position);
|
||||
ClipboardHolder holder = new ClipboardHolder(newClipboard);
|
||||
session.setClipboard(holder);
|
||||
int blocks = builder.size();
|
||||
long blocks = builder.longSize();
|
||||
player.print(Caption.of("fawe.worldedit.copy.command.copy", blocks));
|
||||
} else {
|
||||
AffineTransform transform = null;
|
||||
|
||||
@ -63,15 +63,15 @@ public class ErodeBrush implements Brush {
|
||||
Clipboard buffer1 = new CPUOptimizedClipboard(region);
|
||||
Clipboard buffer2 = new CPUOptimizedClipboard(region);
|
||||
|
||||
final int bx = target.getBlockX();
|
||||
final int by = target.getBlockY();
|
||||
final int bz = target.getBlockZ();
|
||||
final int bx = target.x();
|
||||
final int by = target.y();
|
||||
final int bz = target.z();
|
||||
|
||||
for (int x = -brushSize, relx = 0; x <= brushSize; x++, relx++) {
|
||||
for (int x = -brushSize, relx = 0; x <= brushSize && relx < buffer1.getWidth(); x++, relx++) {
|
||||
int x0 = x + bx;
|
||||
for (int y = -brushSize, rely = 0; y <= brushSize; y++, rely++) {
|
||||
for (int y = -brushSize, rely = 0; y <= brushSize && rely < buffer1.getHeight(); y++, rely++) {
|
||||
int y0 = y + by;
|
||||
for (int z = -brushSize, relz = 0; z <= brushSize; z++, relz++) {
|
||||
for (int z = -brushSize, relz = 0; z <= brushSize && relz < buffer1.getLength(); z++, relz++) {
|
||||
int z0 = z + bz;
|
||||
BlockState state = es.getBlock(x0, y0, z0);
|
||||
buffer1.setBlock(relx, rely, relz, state);
|
||||
@ -106,7 +106,7 @@ public class ErodeBrush implements Brush {
|
||||
|
||||
for (BlockVector3 pos : finalBuffer) {
|
||||
BlockState block = pos.getBlock(finalBuffer);
|
||||
es.setBlock(pos.getX() + bx - brushSize, pos.getY() + by - brushSize, pos.getZ() + bz - brushSize, block);
|
||||
es.setBlock(pos.x() + bx - brushSize, pos.y() + by - brushSize, pos.z() + bz - brushSize, block);
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,11 +115,11 @@ public class ErodeBrush implements Brush {
|
||||
Clipboard current, Clipboard target
|
||||
) {
|
||||
int[] frequency = null;
|
||||
for (int x = -brushSize, relx = 0; x <= brushSize; x++, relx++) {
|
||||
for (int x = -brushSize, relx = 0; x <= brushSize && relx < target.getWidth(); x++, relx++) {
|
||||
int x2 = x * x;
|
||||
for (int z = -brushSize, relz = 0; z <= brushSize; z++, relz++) {
|
||||
for (int z = -brushSize, relz = 0; z <= brushSize && relz < target.getLength(); z++, relz++) {
|
||||
int x2y2 = x2 + z * z;
|
||||
for (int y = -brushSize, rely = 0; y <= brushSize; y++, rely++) {
|
||||
for (int y = -brushSize, rely = 0; y <= brushSize && rely < target.getHeight(); y++, rely++) {
|
||||
int cube = x2y2 + y * y;
|
||||
target.setBlock(relx, rely, relz, current.getBlock(relx, rely, relz));
|
||||
if (cube >= brushSizeSquared) {
|
||||
@ -139,9 +139,9 @@ public class ErodeBrush implements Brush {
|
||||
int highest = 1;
|
||||
for (BlockVector3 offs : FACES_TO_CHECK) {
|
||||
BaseBlock next = current.getFullBlock(
|
||||
relx + offs.getBlockX(),
|
||||
rely + offs.getBlockY(),
|
||||
relz + offs.getBlockZ()
|
||||
relx + offs.x(),
|
||||
rely + offs.y(),
|
||||
relz + offs.z()
|
||||
);
|
||||
if (!next.getBlockType().getMaterial().isMovementBlocker()) {
|
||||
continue;
|
||||
@ -166,11 +166,11 @@ public class ErodeBrush implements Brush {
|
||||
Clipboard current, Clipboard target
|
||||
) {
|
||||
int[] frequency = null;
|
||||
for (int x = -brushSize, relx = 0; x <= brushSize; x++, relx++) {
|
||||
for (int x = -brushSize, relx = 0; x <= brushSize && relx < target.getWidth(); x++, relx++) {
|
||||
int x2 = x * x;
|
||||
for (int z = -brushSize, relz = 0; z <= brushSize; z++, relz++) {
|
||||
for (int z = -brushSize, relz = 0; z <= brushSize && relz < target.getLength(); z++, relz++) {
|
||||
int x2y2 = x2 + z * z;
|
||||
for (int y = -brushSize, rely = 0; y <= brushSize; y++, rely++) {
|
||||
for (int y = -brushSize, rely = 0; y <= brushSize && rely < target.getHeight(); y++, rely++) {
|
||||
int cube = x2y2 + y * y;
|
||||
target.setBlock(relx, rely, relz, current.getBlock(relx, rely, relz));
|
||||
if (cube >= brushSizeSquared) {
|
||||
@ -190,9 +190,9 @@ public class ErodeBrush implements Brush {
|
||||
int total = 0;
|
||||
for (BlockVector3 offs : FACES_TO_CHECK) {
|
||||
BaseBlock next = current.getFullBlock(
|
||||
relx + offs.getBlockX(),
|
||||
rely + offs.getBlockY(),
|
||||
relz + offs.getBlockZ()
|
||||
relx + offs.x(),
|
||||
rely + offs.y(),
|
||||
relz + offs.z()
|
||||
);
|
||||
if (next.getMaterial().isMovementBlocker()) {
|
||||
continue;
|
||||
|
||||
@ -12,9 +12,9 @@ public class FallingSphere implements Brush {
|
||||
@Override
|
||||
public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws
|
||||
MaxChangedBlocksException {
|
||||
int px = position.getBlockX();
|
||||
int py = position.getBlockY();
|
||||
int pz = position.getBlockZ();
|
||||
int px = position.x();
|
||||
int py = position.y();
|
||||
int pz = position.z();
|
||||
int maxY = editSession.getMaxY();
|
||||
int minY = editSession.getMinY();
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ public class HeightBrush implements Brush {
|
||||
try {
|
||||
heightMap = ScalableHeightMap.fromPNG(stream);
|
||||
} catch (IOException e) {
|
||||
throw new FaweException(Caption.of("fawe.worldedit.brush.brush.height.invalid"));
|
||||
throw new FaweException(Caption.of("fawe.worldedit.brush.brush.height.invalid", e.getMessage()));
|
||||
}
|
||||
} else if (clipboard != null) {
|
||||
heightMap = ScalableHeightMap.fromClipboard(clipboard, minY, maxY);
|
||||
|
||||
@ -14,7 +14,6 @@ import com.sk89q.worldedit.command.tool.BrushTool;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
@ -25,7 +24,6 @@ import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
|
||||
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
@ -74,10 +72,15 @@ public class InspectBrush extends BrushTool {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
BlockVector3 target = getTarget(player, rightClick).toBlockPoint();
|
||||
final int x = target.getBlockX();
|
||||
final int y = target.getBlockY();
|
||||
final int z = target.getBlockZ();
|
||||
Vector3 targetVector = getTarget(player, rightClick);
|
||||
if (targetVector == null) {
|
||||
player.print(Caption.of("worldedit.tool.no-block"));
|
||||
return true;
|
||||
}
|
||||
BlockVector3 target = targetVector.toBlockPoint();
|
||||
final int x = target.x();
|
||||
final int y = target.y();
|
||||
final int z = target.z();
|
||||
World world = player.getWorld();
|
||||
RollbackDatabase db = DBHandler.dbHandler().getDatabase(world);
|
||||
int count = 0;
|
||||
|
||||
@ -24,7 +24,8 @@ public record PopulateSchem(Mask mask, List<ClipboardHolder> clipboards, int rar
|
||||
CuboidRegion cuboid = new CuboidRegion(
|
||||
editSession.getWorld(),
|
||||
position.subtract(size1, size1, size1),
|
||||
position.add(size1, size1, size1)
|
||||
position.add(size1, size1, size1),
|
||||
true
|
||||
);
|
||||
try {
|
||||
editSession.addSchems(cuboid, mask, clipboards, rarity, randomRotate);
|
||||
|
||||
@ -35,7 +35,7 @@ public record RecurseBrush(boolean dfs) implements Brush {
|
||||
DFSRecursiveVisitor visitor = new DFSRecursiveVisitor(mask, replace, Integer.MAX_VALUE, Integer.MAX_VALUE) {
|
||||
@Override
|
||||
public boolean isVisitable(BlockVector3 from, BlockVector3 to) {
|
||||
int y = to.getBlockY();
|
||||
int y = to.y();
|
||||
return y < maxY && radMask.test(to) && super.isVisitable(from, to);
|
||||
}
|
||||
};
|
||||
@ -45,7 +45,7 @@ public record RecurseBrush(boolean dfs) implements Brush {
|
||||
RecursiveVisitor visitor = new RecursiveVisitor(mask, replace, radius, editSession.getMinY(), editSession.getMaxY()) {
|
||||
@Override
|
||||
public boolean isVisitable(BlockVector3 from, BlockVector3 to) {
|
||||
int y = to.getBlockY();
|
||||
int y = to.y();
|
||||
return y < maxY && super.isVisitable(from, to);
|
||||
}
|
||||
};
|
||||
|
||||
@ -19,15 +19,15 @@ public record RockBrush(double amplitude, double frequency, Vector3 radius) impl
|
||||
double seedY = ThreadLocalRandom.current().nextDouble();
|
||||
double seedZ = ThreadLocalRandom.current().nextDouble();
|
||||
|
||||
int px = position.getBlockX();
|
||||
int py = position.getBlockY();
|
||||
int pz = position.getBlockZ();
|
||||
int px = position.x();
|
||||
int py = position.y();
|
||||
int pz = position.z();
|
||||
|
||||
double distort = this.frequency / size;
|
||||
|
||||
double modX = 1D / radius.getX();
|
||||
double modY = 1D / radius.getY();
|
||||
double modZ = 1D / radius.getZ();
|
||||
double modX = 1D / radius.x();
|
||||
double modY = 1D / radius.y();
|
||||
double modZ = 1D / radius.z();
|
||||
|
||||
int radiusSqr = (int) (size * size);
|
||||
int sizeInt = (int) size * 2;
|
||||
|
||||
@ -5,6 +5,7 @@ import com.fastasyncworldedit.core.function.mask.RadiusMask;
|
||||
import com.fastasyncworldedit.core.function.mask.SurfaceMask;
|
||||
import com.fastasyncworldedit.core.math.BlockVectorSet;
|
||||
import com.fastasyncworldedit.core.math.LocalBlockVectorSet;
|
||||
import com.fastasyncworldedit.core.util.collection.BlockVector3Set;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.command.tool.brush.Brush;
|
||||
@ -64,16 +65,17 @@ public class ScatterBrush implements Brush {
|
||||
length = 1;
|
||||
visited.add(position);
|
||||
}
|
||||
LocalBlockVectorSet placed = new LocalBlockVectorSet();
|
||||
placed.setOffset(position.getX(), position.getZ());
|
||||
BlockVector3 patternSize = pattern.size();
|
||||
BlockVector3Set placed = BlockVector3Set.getAppropriateVectorSet(patternSize.add(distance, distance, distance));
|
||||
placed.setOffset(position.x(), position.y(), position.z());
|
||||
int maxFails = 1000;
|
||||
for (int i = 0; i < count; i++) {
|
||||
int index = ThreadLocalRandom.current().nextInt(length);
|
||||
BlockVector3 pos = visited.get(index);
|
||||
if (pos != null && canApply(pos)) {
|
||||
int x = pos.getBlockX();
|
||||
int y = pos.getBlockY();
|
||||
int z = pos.getBlockZ();
|
||||
int x = pos.x();
|
||||
int y = pos.y();
|
||||
int z = pos.z();
|
||||
if (placed.containsRadius(x, y, z, distance)) {
|
||||
if (maxFails-- <= 0) {
|
||||
break;
|
||||
@ -88,7 +90,20 @@ public class ScatterBrush implements Brush {
|
||||
finish(editSession, placed, position, pattern, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link ScatterBrush#finish(EditSession, BlockVector3Set, BlockVector3, Pattern, double)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2.9.2")
|
||||
public void finish(EditSession editSession, LocalBlockVectorSet placed, BlockVector3 pos, Pattern pattern, double size) {
|
||||
finish(editSession, (BlockVector3Set) placed, pos, pattern, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the scatter brush process.
|
||||
*
|
||||
* @since 2.9.2
|
||||
*/
|
||||
public void finish(EditSession editSession, BlockVector3Set placed, BlockVector3 pos, Pattern pattern, double size) {
|
||||
}
|
||||
|
||||
public boolean canApply(BlockVector3 pos) {
|
||||
@ -99,8 +114,23 @@ public class ScatterBrush implements Brush {
|
||||
return surface.direction(pt);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link ScatterBrush#apply(EditSession, BlockVector3Set, BlockVector3, Pattern, double)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2.9.2")
|
||||
public void apply(EditSession editSession, LocalBlockVectorSet placed, BlockVector3 pt, Pattern p, double size) throws
|
||||
MaxChangedBlocksException {
|
||||
apply(editSession, (BlockVector3Set) placed, pt, p, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the scatter brush to a given position
|
||||
*
|
||||
* @since 2.9.2
|
||||
*/
|
||||
public void apply(EditSession editSession, BlockVector3Set placed, BlockVector3 pt, Pattern p, double size) throws
|
||||
MaxChangedBlocksException {
|
||||
editSession.setBlock(pt, p);
|
||||
}
|
||||
|
||||
|
||||
@ -45,9 +45,9 @@ public class ScatterCommand extends ScatterBrush {
|
||||
position.subtract(radius, radius, radius),
|
||||
position.add(radius, radius, radius)
|
||||
);
|
||||
String replaced = command.replace("{x}", Integer.toString(position.getBlockX()))
|
||||
.replace("{y}", Integer.toString(position.getBlockY()))
|
||||
.replace("{z}", Integer.toString(position.getBlockZ()))
|
||||
String replaced = command.replace("{x}", Integer.toString(position.x()))
|
||||
.replace("{y}", Integer.toString(position.y()))
|
||||
.replace("{z}", Integer.toString(position.z()))
|
||||
.replace("{world}", editSession.getWorld().getName())
|
||||
.replace("{size}", Integer.toString(radius));
|
||||
|
||||
|
||||
@ -16,9 +16,9 @@ public class ScatterOverlayBrush extends ScatterBrush {
|
||||
@Override
|
||||
public void apply(EditSession editSession, LocalBlockVectorSet placed, BlockVector3 pt, Pattern p, double size) throws
|
||||
MaxChangedBlocksException {
|
||||
final int x = pt.getBlockX();
|
||||
final int y = pt.getBlockY();
|
||||
final int z = pt.getBlockZ();
|
||||
final int x = pt.x();
|
||||
final int y = pt.y();
|
||||
final int z = pt.z();
|
||||
BlockVector3 dir = getDirection(pt);
|
||||
if (dir == null) {
|
||||
getDir:
|
||||
@ -37,7 +37,7 @@ public class ScatterOverlayBrush extends ScatterBrush {
|
||||
return;
|
||||
}
|
||||
}
|
||||
editSession.setBlock(x + dir.getBlockX(), y + dir.getBlockY(), z + dir.getBlockZ(), p);
|
||||
editSession.setBlock(x + dir.x(), y + dir.y(), z + dir.z(), p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package com.fastasyncworldedit.core.command.tool.brush;
|
||||
import com.fastasyncworldedit.core.function.mask.SurfaceMask;
|
||||
import com.fastasyncworldedit.core.math.LocalBlockVectorSet;
|
||||
import com.fastasyncworldedit.core.math.MutableBlockVector3;
|
||||
import com.fastasyncworldedit.core.util.collection.BlockVector3Set;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
@ -24,7 +25,7 @@ public class ShatterBrush extends ScatterBrush {
|
||||
@Override
|
||||
public void apply(
|
||||
final EditSession editSession,
|
||||
final LocalBlockVectorSet placed,
|
||||
final BlockVector3Set placed,
|
||||
final BlockVector3 position,
|
||||
Pattern p,
|
||||
double size
|
||||
@ -34,7 +35,7 @@ public class ShatterBrush extends ScatterBrush {
|
||||
@Override
|
||||
public void finish(
|
||||
EditSession editSession,
|
||||
LocalBlockVectorSet placed,
|
||||
BlockVector3Set placed,
|
||||
final BlockVector3 position,
|
||||
Pattern pattern,
|
||||
double size
|
||||
@ -79,13 +80,13 @@ public class ShatterBrush extends ScatterBrush {
|
||||
}
|
||||
for (int i1 = 0; i1 < BreadthFirstSearch.DIAGONAL_DIRECTIONS.length; i1++) {
|
||||
BlockVector3 direction = BreadthFirstSearch.DIAGONAL_DIRECTIONS[i1];
|
||||
int x2 = x + direction.getBlockX();
|
||||
int y2 = y + direction.getBlockY();
|
||||
int z2 = z + direction.getBlockZ();
|
||||
int x2 = x + direction.x();
|
||||
int y2 = y + direction.y();
|
||||
int z2 = z + direction.z();
|
||||
// Check boundary
|
||||
int dx = position.getBlockX() - x2;
|
||||
int dy = position.getBlockY() - y2;
|
||||
int dz = position.getBlockZ() - z2;
|
||||
int dx = position.x() - x2;
|
||||
int dy = position.y() - y2;
|
||||
int dz = position.z() - z2;
|
||||
int dSqr = (dx * dx) + (dy * dy) + (dz * dz);
|
||||
if (dSqr <= radius2) {
|
||||
BlockVector3 bv = mutable.setComponents(x2, y2, z2);
|
||||
|
||||
@ -130,9 +130,9 @@ public class SplineBrush implements Brush, ResettableTool {
|
||||
private Vector3 getCentroid(Collection<BlockVector3> points) {
|
||||
MutableVector3 sum = new MutableVector3();
|
||||
for (BlockVector3 p : points) {
|
||||
sum.mutX(sum.getX() + p.getX());
|
||||
sum.mutY(sum.getY() + p.getY());
|
||||
sum.mutZ(sum.getZ() + p.getZ());
|
||||
sum.mutX(sum.x() + p.x());
|
||||
sum.mutY(sum.y() + p.y());
|
||||
sum.mutZ(sum.z() + p.z());
|
||||
}
|
||||
return sum.multiply(1.0 / points.size());
|
||||
}
|
||||
|
||||
@ -38,16 +38,16 @@ public class SurfaceSpline implements Brush {
|
||||
int minY = editSession.getMinY();
|
||||
if (path.isEmpty() || !pos.equals(path.get(path.size() - 1))) {
|
||||
int max = editSession.getNearestSurfaceTerrainBlock(
|
||||
pos.getBlockX(),
|
||||
pos.getBlockZ(),
|
||||
pos.getBlockY(),
|
||||
pos.x(),
|
||||
pos.z(),
|
||||
pos.y(),
|
||||
minY,
|
||||
maxY
|
||||
);
|
||||
if (max == -1) {
|
||||
return;
|
||||
}
|
||||
path.add(BlockVector3.at(pos.getBlockX(), max, pos.getBlockZ()));
|
||||
path.add(BlockVector3.at(pos.x(), max, pos.z()));
|
||||
if (editSession.getActor() != null) {
|
||||
editSession.getActor().print(Caption.of("fawe.worldedit.brush.spline.primary.2"));
|
||||
}
|
||||
@ -69,9 +69,9 @@ public class SurfaceSpline implements Brush {
|
||||
LocalBlockVectorSet vset = new LocalBlockVectorSet();
|
||||
for (double loop = 0; loop <= 1; loop += 1D / splinelength / quality) {
|
||||
final Vector3 tipv = interpol.getPosition(loop);
|
||||
final int tipx = MathMan.roundInt(tipv.getX());
|
||||
final int tipz = (int) tipv.getZ();
|
||||
int tipy = MathMan.roundInt(tipv.getY());
|
||||
final int tipx = MathMan.roundInt(tipv.x());
|
||||
final int tipz = (int) tipv.z();
|
||||
int tipy = MathMan.roundInt(tipv.y());
|
||||
tipy = editSession.getNearestSurfaceTerrainBlock(tipx, tipz, tipy, minY, maxY, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||
if (tipy == Integer.MIN_VALUE || tipy == Integer.MAX_VALUE) {
|
||||
continue;
|
||||
@ -88,15 +88,15 @@ public class SurfaceSpline implements Brush {
|
||||
LocalBlockVectorSet newSet = new LocalBlockVectorSet();
|
||||
final int ceilrad = (int) Math.ceil(radius);
|
||||
for (BlockVector3 v : vset) {
|
||||
final int tipx = v.getBlockX();
|
||||
final int tipz = v.getBlockZ();
|
||||
final int tipx = v.x();
|
||||
final int tipz = v.z();
|
||||
for (int loopx = tipx - ceilrad; loopx <= tipx + ceilrad; loopx++) {
|
||||
for (int loopz = tipz - ceilrad; loopz <= tipz + ceilrad; loopz++) {
|
||||
if (MathMan.hypot2(loopx - tipx, 0, loopz - tipz) <= radius2) {
|
||||
int y = editSession.getNearestSurfaceTerrainBlock(
|
||||
loopx,
|
||||
loopz,
|
||||
v.getBlockY(),
|
||||
v.y(),
|
||||
minY,
|
||||
maxY,
|
||||
Integer.MIN_VALUE,
|
||||
|
||||
@ -51,6 +51,7 @@ public abstract class Scroll implements ScrollTool {
|
||||
parserContext.setActor(player);
|
||||
parserContext.setWorld(player.getWorld());
|
||||
parserContext.setSession(session);
|
||||
parserContext.setTryLegacy(player.getLimit().ALLOW_LEGACY);
|
||||
switch (mode) {
|
||||
case CLIPBOARD:
|
||||
if (arguments.size() != 2) {
|
||||
|
||||
@ -13,7 +13,7 @@ public class ScrollRange extends Scroll {
|
||||
|
||||
@Override
|
||||
public boolean increment(Player player, int amount) {
|
||||
int max = WorldEdit.getInstance().getConfiguration().maxBrushRadius;
|
||||
int max = player.getLimit().MAX_BRUSH_RADIUS;
|
||||
int newSize = MathMan.wrap(getTool().getRange() + amount, (int) (getTool().getSize() + 1), max);
|
||||
getTool().setRange(newSize);
|
||||
return true;
|
||||
|
||||
@ -12,7 +12,7 @@ public class ScrollSize extends Scroll {
|
||||
|
||||
@Override
|
||||
public boolean increment(Player player, int amount) {
|
||||
int max = WorldEdit.getInstance().getConfiguration().maxRadius;
|
||||
int max = player.getLimit().MAX_RADIUS;
|
||||
double newSize = Math.max(0, Math.min(max == -1 ? 4095 : max, getTool().getSize() + amount));
|
||||
getTool().setSize(newSize);
|
||||
return true;
|
||||
|
||||
@ -83,7 +83,7 @@ public class ClipboardSpline extends Spline {
|
||||
Region region = clipboard.getRegion();
|
||||
BlockVector3 origin = clipboard.getOrigin();
|
||||
// center = region.getCenter().setY(origin.getY() - 1);
|
||||
center = region.getCenter().withY(origin.getY() - 1).toBlockPoint();
|
||||
center = region.getCenter().withY(origin.y() - 1).toBlockPoint();
|
||||
this.centerOffset = center.subtract(center.round());
|
||||
this.center = center.subtract(centerOffset);
|
||||
this.transform = transform;
|
||||
@ -108,15 +108,15 @@ public class ClipboardSpline extends Spline {
|
||||
clipboardHolder.setTransform(transform);
|
||||
|
||||
BlockVector3 functionOffset = target.subtract(clipboard.getOrigin());
|
||||
final int offX = functionOffset.getBlockX();
|
||||
final int offY = functionOffset.getBlockY();
|
||||
final int offZ = functionOffset.getBlockZ();
|
||||
final int offX = functionOffset.x();
|
||||
final int offY = functionOffset.y();
|
||||
final int offZ = functionOffset.z();
|
||||
|
||||
Operation operation = clipboardHolder
|
||||
.createPaste(editSession)
|
||||
.to(target)
|
||||
.ignoreAirBlocks(true)
|
||||
.filter(v -> buffer.add(v.getBlockX() + offX, v.getBlockY() + offY, v.getBlockZ() + offZ))
|
||||
.filter(v -> buffer.add(v.x() + offX, v.y() + offY, v.z() + offZ))
|
||||
.build();
|
||||
Operations.completeLegacy(operation);
|
||||
|
||||
|
||||
@ -121,7 +121,7 @@ public abstract class Spline {
|
||||
* 2 dimensional "cross" product. cross2D(v1, v2) = |v1|*|v2|*sin(theta) or v1 X v2 taking Y to be 0
|
||||
*/
|
||||
private double cross2D(Vector2 v1, Vector2 v2) {
|
||||
return v1.getX() * v2.getZ() - v2.getX() * v1.getZ();
|
||||
return v1.x() * v2.z() - v2.x() * v1.z();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,7 +144,7 @@ public abstract class Spline {
|
||||
// Calculate rotation from spline
|
||||
|
||||
Vector3 deriv = interpolation.get1stDerivative(position);
|
||||
Vector2 deriv2D = Vector2.at(deriv.getX(), deriv.getZ()).normalize();
|
||||
Vector2 deriv2D = Vector2.at(deriv.x(), deriv.z()).normalize();
|
||||
double angle = Math.toDegrees(
|
||||
-Math.atan2(cross2D(direction, deriv2D), direction.dot(deriv2D))
|
||||
);
|
||||
|
||||
@ -79,13 +79,13 @@ public class SweepBrush implements Brush, ResettableTool {
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
|
||||
BlockVector3 dimensions = clipboard.getDimensions();
|
||||
double quality = Math.max(dimensions.getBlockX(), dimensions.getBlockZ());
|
||||
double quality = Math.max(dimensions.x(), dimensions.z());
|
||||
|
||||
AffineTransform transform = new AffineTransform();
|
||||
|
||||
ClipboardSpline spline = new ClipboardSpline(editSession, holder, interpol, transform, nodes.size());
|
||||
|
||||
if (dimensions.getBlockX() > dimensions.getBlockZ()) {
|
||||
if (dimensions.x() > dimensions.z()) {
|
||||
spline.setDirection(Vector2.at(0, 1));
|
||||
}
|
||||
|
||||
|
||||
@ -2,9 +2,11 @@ package com.fastasyncworldedit.core.configuration;
|
||||
|
||||
import com.fastasyncworldedit.core.configuration.file.YamlConfiguration;
|
||||
import com.fastasyncworldedit.core.util.StringMan;
|
||||
import com.sk89q.util.StringUtil;
|
||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
@ -14,8 +16,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@ -27,8 +32,16 @@ public class Config {
|
||||
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
|
||||
private final Map<String, Object> removedKeyVals = new HashMap<>();
|
||||
@Nullable
|
||||
private Map<String, Map.Entry<String, Object>> copyTo = new HashMap<>();
|
||||
private boolean performCopyTo = false;
|
||||
private List<String> existingMigrateNodes = null;
|
||||
|
||||
public Config() {
|
||||
save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0);
|
||||
// This is now definitely required as the save -> load -> save order means the @CopiedFrom annotated fields work
|
||||
save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0, null);
|
||||
performCopyTo = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -43,7 +56,8 @@ public class Config {
|
||||
try {
|
||||
return (T) field.get(instance);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("Failed to get config option: {}", key, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -53,11 +67,12 @@ public class Config {
|
||||
|
||||
/**
|
||||
* Set the value of a specific node. Probably throws some error if you supply non existing keys or invalid values.
|
||||
* This should only be called during loading of a config file
|
||||
*
|
||||
* @param key config node
|
||||
* @param value value
|
||||
*/
|
||||
private void set(String key, Object value, Class<?> root) {
|
||||
private void setLoadedNode(String key, Object value, Class<?> root) {
|
||||
String[] split = key.split("\\.");
|
||||
Object instance = getInstance(split, root);
|
||||
if (instance != null) {
|
||||
@ -67,6 +82,20 @@ public class Config {
|
||||
if (field.getAnnotation(Final.class) != null) {
|
||||
return;
|
||||
}
|
||||
if (copyTo != null) {
|
||||
copyTo.remove(key); // Remove if the config field is already written
|
||||
final Object finalValue = value;
|
||||
copyTo.replaceAll((copyToNode, entry) -> {
|
||||
if (!key.equals(entry.getKey())) {
|
||||
return entry;
|
||||
}
|
||||
return new AbstractMap.SimpleEntry<>(key, finalValue);
|
||||
});
|
||||
}
|
||||
Migrate migrate = field.getAnnotation(Migrate.class);
|
||||
if (migrate != null) {
|
||||
existingMigrateNodes.add(migrate.value());
|
||||
}
|
||||
if (field.getType() == String.class && !(value instanceof String)) {
|
||||
value = value + "";
|
||||
}
|
||||
@ -74,25 +103,38 @@ public class Config {
|
||||
field.set(instance, value);
|
||||
return;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("Failed to set config option: {}", key);
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGGER.error("Failed to set config option: {}: {} | {} | {}.yml", key, value, instance, root.getSimpleName());
|
||||
removedKeyVals.put(key, value);
|
||||
LOGGER.warn(
|
||||
"Failed to set config option: {}: {} | {} | {}.yml. This is likely because it was removed or was set with an " +
|
||||
"invalid value.",
|
||||
key,
|
||||
value,
|
||||
instance,
|
||||
root.getSimpleName()
|
||||
);
|
||||
}
|
||||
|
||||
public boolean load(File file) {
|
||||
if (!file.exists()) {
|
||||
return false;
|
||||
}
|
||||
existingMigrateNodes = new ArrayList<>();
|
||||
YamlConfiguration yml = YamlConfiguration.loadConfiguration(file);
|
||||
for (String key : yml.getKeys(true)) {
|
||||
Object value = yml.get(key);
|
||||
if (value instanceof MemorySection) {
|
||||
continue;
|
||||
}
|
||||
set(key, value, getClass());
|
||||
setLoadedNode(key, value, getClass());
|
||||
}
|
||||
for (String node : existingMigrateNodes) {
|
||||
removedKeyVals.remove(node);
|
||||
}
|
||||
existingMigrateNodes = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -110,10 +152,10 @@ public class Config {
|
||||
}
|
||||
PrintWriter writer = new PrintWriter(file);
|
||||
Object instance = this;
|
||||
save(writer, getClass(), instance, 0);
|
||||
save(writer, getClass(), instance, 0, null);
|
||||
writer.close();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("Failed to save config file: {}", file, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,6 +208,32 @@ public class Config {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that a field should be migrated from a node that is deleted
|
||||
*
|
||||
* @since 2.10.0
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
public @interface Migrate {
|
||||
|
||||
String value();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that a field's default value should match another input if the config is otherwise already generated
|
||||
*
|
||||
* @since 2.11.0
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD})
|
||||
public @interface CopiedFrom {
|
||||
|
||||
String value();
|
||||
|
||||
}
|
||||
|
||||
@Ignore // This is not part of the config
|
||||
public static class ConfigBlock<T> {
|
||||
|
||||
@ -218,11 +286,10 @@ public class Config {
|
||||
return value != null ? value.toString() : "null";
|
||||
}
|
||||
|
||||
private void save(PrintWriter writer, Class<?> clazz, final Object instance, int indent) {
|
||||
private void save(PrintWriter writer, Class<?> clazz, final Object instance, int indent, String parentNode) {
|
||||
try {
|
||||
String CTRF = System.lineSeparator();
|
||||
String spacing = StringMan.repeat(" ", indent);
|
||||
HashMap<Class<?>, Object> instances = new HashMap<>();
|
||||
for (Field field : clazz.getFields()) {
|
||||
if (field.getAnnotation(Ignore.class) != null) {
|
||||
continue;
|
||||
@ -239,31 +306,26 @@ public class Config {
|
||||
}
|
||||
if (current == ConfigBlock.class) {
|
||||
current = (Class<?>) ((ParameterizedType) (field.getGenericType())).getActualTypeArguments()[0];
|
||||
comment = current.getAnnotation(Comment.class);
|
||||
if (comment != null) {
|
||||
for (String commentLine : comment.value()) {
|
||||
writer.write(spacing + "# " + commentLine + CTRF);
|
||||
}
|
||||
}
|
||||
BlockName blockNames = current.getAnnotation(BlockName.class);
|
||||
if (blockNames != null) {
|
||||
writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF);
|
||||
ConfigBlock configBlock = (ConfigBlock) field.get(instance);
|
||||
if (configBlock == null || configBlock.getInstances().isEmpty()) {
|
||||
configBlock = new ConfigBlock();
|
||||
field.set(instance, configBlock);
|
||||
for (String blockName : blockNames.value()) {
|
||||
configBlock.put(blockName, current.getDeclaredConstructor().newInstance());
|
||||
}
|
||||
}
|
||||
// Save each instance
|
||||
for (Map.Entry<String, Object> entry : ((Map<String, Object>) configBlock.getRaw()).entrySet()) {
|
||||
String key = entry.getKey();
|
||||
writer.write(spacing + " " + toNodeName(key) + ":" + CTRF);
|
||||
save(writer, current, entry.getValue(), indent + 4);
|
||||
}
|
||||
}
|
||||
handleConfigBlockSave(writer, instance, indent, field, spacing, CTRF, current, parentNode);
|
||||
continue;
|
||||
} else if (!removedKeyVals.isEmpty()) {
|
||||
Migrate migrate = field.getAnnotation(Migrate.class);
|
||||
Object value;
|
||||
if (migrate != null && (value = removedKeyVals.remove(migrate.value())) != null) {
|
||||
field.set(instance, value);
|
||||
}
|
||||
}
|
||||
CopiedFrom copiedFrom;
|
||||
if (copyTo != null && (copiedFrom = field.getAnnotation(CopiedFrom.class)) != null) {
|
||||
String node = toNodeName(field.getName());
|
||||
node = parentNode == null ? node : parentNode + "." + node;
|
||||
Map.Entry<String, Object> entry = copyTo.remove(node);
|
||||
Object copiedVal;
|
||||
if (entry == null) {
|
||||
copyTo.put(node, new AbstractMap.SimpleEntry<>(copiedFrom.value(), null));
|
||||
} else if ((copiedVal = entry.getValue()) != null) {
|
||||
field.set(instance, copiedVal);
|
||||
}
|
||||
}
|
||||
Create create = field.getAnnotation(Create.class);
|
||||
if (create != null) {
|
||||
@ -278,12 +340,12 @@ public class Config {
|
||||
writer.write(spacing + "# " + commentLine + CTRF);
|
||||
}
|
||||
}
|
||||
writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF);
|
||||
String node = toNodeName(current.getSimpleName());
|
||||
writer.write(spacing + node + ":" + CTRF);
|
||||
if (value == null) {
|
||||
field.set(instance, value = current.getDeclaredConstructor().newInstance());
|
||||
instances.put(current, value);
|
||||
}
|
||||
save(writer, current, value, indent + 2);
|
||||
save(writer, current, value, indent + 2, parentNode == null ? node : parentNode + "." + node);
|
||||
} else {
|
||||
writer.write(spacing + toNodeName(field.getName() + ": ") + toYamlString(
|
||||
field.get(instance),
|
||||
@ -292,7 +354,48 @@ public class Config {
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("Failed to save config file", e);
|
||||
}
|
||||
if (parentNode == null && performCopyTo) {
|
||||
performCopyTo = false;
|
||||
copyTo = null;
|
||||
}
|
||||
}
|
||||
|
||||
private <T> void handleConfigBlockSave(
|
||||
PrintWriter writer,
|
||||
Object instance,
|
||||
int indent,
|
||||
Field field,
|
||||
String spacing,
|
||||
String CTRF,
|
||||
Class<T> current,
|
||||
String parentNode
|
||||
) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
|
||||
Comment comment = current.getAnnotation(Comment.class);
|
||||
if (comment != null) {
|
||||
for (String commentLine : comment.value()) {
|
||||
writer.write(spacing + "# " + commentLine + CTRF);
|
||||
}
|
||||
}
|
||||
BlockName blockNames = current.getAnnotation(BlockName.class);
|
||||
if (blockNames != null) {
|
||||
String node = toNodeName(current.getSimpleName());
|
||||
writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF);
|
||||
ConfigBlock<T> configBlock = (ConfigBlock<T>) field.get(instance);
|
||||
if (configBlock == null || configBlock.getInstances().isEmpty()) {
|
||||
configBlock = new ConfigBlock<>();
|
||||
field.set(instance, configBlock);
|
||||
for (String blockName : blockNames.value()) {
|
||||
configBlock.put(blockName, current.getDeclaredConstructor().newInstance());
|
||||
}
|
||||
}
|
||||
// Save each instance
|
||||
for (Map.Entry<String, T> entry : configBlock.getRaw().entrySet()) {
|
||||
String key = entry.getKey();
|
||||
writer.write(spacing + " " + toNodeName(key) + ":" + CTRF);
|
||||
save(writer, current, entry.getValue(), indent + 4, parentNode == null ? node : parentNode + "." + node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -311,7 +414,7 @@ public class Config {
|
||||
return field;
|
||||
} catch (Throwable ignored) {
|
||||
LOGGER.warn(
|
||||
"Invalid config field: {} for {}",
|
||||
"Invalid config field: {} for {}. It is possible this is because it has been removed.",
|
||||
StringMan.join(split, "."),
|
||||
toNodeName(instance.getClass().getSimpleName())
|
||||
);
|
||||
@ -379,7 +482,7 @@ public class Config {
|
||||
return null;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("Failed retrieving instance for config node: {}", StringUtil.joinString(split, "."), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.configuration;
|
||||
|
||||
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||
import com.fastasyncworldedit.core.limit.PropertyRemap;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.registry.state.Property;
|
||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||
@ -19,14 +20,14 @@ import java.util.stream.Stream;
|
||||
|
||||
public class Settings extends Config {
|
||||
|
||||
@Ignore
|
||||
static Settings INSTANCE = new Settings();
|
||||
/**
|
||||
* @deprecated Use {@link #settings()} instead to get an instance.
|
||||
*/
|
||||
@Ignore
|
||||
@Deprecated(forRemoval = true, since = "2.0.0")
|
||||
public static final Settings IMP = new Settings();
|
||||
@Ignore
|
||||
static Settings INSTANCE = new Settings();
|
||||
public static final Settings IMP = INSTANCE;
|
||||
@Ignore
|
||||
public boolean PROTOCOL_SUPPORT_FIX = false;
|
||||
@Comment("These first 6 aren't configurable") // This is a comment
|
||||
@ -79,6 +80,8 @@ public class Settings extends Config {
|
||||
@Create
|
||||
public REGION_RESTRICTIONS_OPTIONS REGION_RESTRICTIONS_OPTIONS;
|
||||
@Create
|
||||
public GENERAL GENERAL;
|
||||
@Create
|
||||
public ConfigBlock<LIMITS> LIMITS;
|
||||
|
||||
private Settings() {
|
||||
@ -102,7 +105,7 @@ public class Settings extends Config {
|
||||
|
||||
public FaweLimit getLimit(Actor actor) {
|
||||
FaweLimit limit;
|
||||
if (actor.hasPermission("fawe.bypass") || actor.hasPermission("fawe.limit.unlimited")) {
|
||||
if (actor.hasPermission("fawe.limit.unlimited")) {
|
||||
return FaweLimit.MAX.copy();
|
||||
}
|
||||
limit = new FaweLimit();
|
||||
@ -120,31 +123,55 @@ public class Settings extends Config {
|
||||
limit.MAX_ACTIONS,
|
||||
newLimit.MAX_ACTIONS != -1 ? newLimit.MAX_ACTIONS : Integer.MAX_VALUE
|
||||
);
|
||||
limit.MAX_CHANGES = Math.max(
|
||||
limit.MAX_CHANGES,
|
||||
limit.MAX_CHANGES.set(Math.max(
|
||||
limit.MAX_CHANGES.get(),
|
||||
newLimit.MAX_CHANGES != -1 ? newLimit.MAX_CHANGES : Long.MAX_VALUE
|
||||
);
|
||||
limit.MAX_BLOCKSTATES = Math.max(
|
||||
limit.MAX_BLOCKSTATES,
|
||||
));
|
||||
limit.MAX_BLOCKSTATES.set(Math.max(
|
||||
limit.MAX_BLOCKSTATES.get(),
|
||||
newLimit.MAX_BLOCKSTATES != -1 ? newLimit.MAX_BLOCKSTATES : Integer.MAX_VALUE
|
||||
);
|
||||
limit.MAX_CHECKS = Math.max(
|
||||
limit.MAX_CHECKS,
|
||||
));
|
||||
limit.MAX_CHECKS.set(Math.max(
|
||||
limit.MAX_CHECKS.get(),
|
||||
newLimit.MAX_CHECKS != -1 ? newLimit.MAX_CHECKS : Long.MAX_VALUE
|
||||
);
|
||||
limit.MAX_ENTITIES = Math.max(
|
||||
limit.MAX_ENTITIES,
|
||||
));
|
||||
limit.MAX_ENTITIES.set(Math.max(
|
||||
limit.MAX_ENTITIES.get(),
|
||||
newLimit.MAX_ENTITIES != -1 ? newLimit.MAX_ENTITIES : Integer.MAX_VALUE
|
||||
);
|
||||
limit.MAX_FAILS = Math.max(limit.MAX_FAILS, newLimit.MAX_FAILS != -1 ? newLimit.MAX_FAILS : Integer.MAX_VALUE);
|
||||
limit.MAX_ITERATIONS = Math.max(
|
||||
limit.MAX_ITERATIONS,
|
||||
));
|
||||
limit.MAX_FAILS.set(Math.max(
|
||||
limit.MAX_FAILS.get(),
|
||||
newLimit.MAX_FAILS != -1 ? newLimit.MAX_FAILS : Integer.MAX_VALUE
|
||||
));
|
||||
limit.MAX_ITERATIONS.set(Math.max(
|
||||
limit.MAX_ITERATIONS.get(),
|
||||
newLimit.MAX_ITERATIONS != -1 ? newLimit.MAX_ITERATIONS : Integer.MAX_VALUE
|
||||
));
|
||||
limit.MAX_RADIUS = Math.max(limit.MAX_RADIUS, newLimit.MAX_RADIUS != -1 ? newLimit.MAX_RADIUS : Integer.MAX_VALUE);
|
||||
limit.MAX_SUPER_PICKAXE_SIZE = Math.max(
|
||||
limit.MAX_SUPER_PICKAXE_SIZE,
|
||||
newLimit.MAX_SUPER_PICKAXE_SIZE != -1 ? newLimit.MAX_SUPER_PICKAXE_SIZE : Integer.MAX_VALUE
|
||||
);
|
||||
limit.MAX_BRUSH_RADIUS = Math.max(
|
||||
limit.MAX_BRUSH_RADIUS,
|
||||
newLimit.MAX_BRUSH_RADIUS != -1 ? newLimit.MAX_BRUSH_RADIUS : Integer.MAX_VALUE
|
||||
);
|
||||
limit.MAX_BUTCHER_RADIUS = Math.max(
|
||||
limit.MAX_BUTCHER_RADIUS,
|
||||
newLimit.MAX_BUTCHER_RADIUS != -1 ? newLimit.MAX_BUTCHER_RADIUS : Integer.MAX_VALUE
|
||||
);
|
||||
limit.MAX_HISTORY = Math.max(
|
||||
limit.MAX_HISTORY,
|
||||
newLimit.MAX_HISTORY_MB != -1 ? newLimit.MAX_HISTORY_MB : Integer.MAX_VALUE
|
||||
);
|
||||
limit.SCHEM_FILE_NUM_LIMIT = Math.max(
|
||||
limit.SCHEM_FILE_NUM_LIMIT,
|
||||
newLimit.SCHEM_FILE_NUM_LIMIT != -1 ? newLimit.SCHEM_FILE_NUM_LIMIT : Integer.MAX_VALUE
|
||||
);
|
||||
limit.SCHEM_FILE_SIZE_LIMIT = Math.max(
|
||||
limit.SCHEM_FILE_SIZE_LIMIT,
|
||||
newLimit.SCHEM_FILE_SIZE_LIMIT != -1 ? newLimit.SCHEM_FILE_SIZE_LIMIT : Integer.MAX_VALUE
|
||||
);
|
||||
limit.MAX_EXPRESSION_MS = Math.max(
|
||||
limit.MAX_EXPRESSION_MS,
|
||||
newLimit.MAX_EXPRESSION_MS != -1 ? newLimit.MAX_EXPRESSION_MS : Integer.MAX_VALUE
|
||||
@ -166,6 +193,7 @@ public class Settings extends Config {
|
||||
}
|
||||
}
|
||||
limit.UNIVERSAL_DISALLOWED_BLOCKS &= newLimit.UNIVERSAL_DISALLOWED_BLOCKS;
|
||||
limit.ALLOW_LEGACY &= newLimit.ALLOW_LEGACY;
|
||||
|
||||
if (limit.DISALLOWED_BLOCKS == null) {
|
||||
limit.DISALLOWED_BLOCKS = newLimit.DISALLOWED_BLOCKS.isEmpty() ? Collections.emptySet() : new HashSet<>(
|
||||
@ -342,6 +370,14 @@ public class Settings extends Config {
|
||||
public int MAX_ITERATIONS = 1000;
|
||||
@Comment("Max allowed entities (e.g. cows)")
|
||||
public int MAX_ENTITIES = 1337;
|
||||
@Comment("Max allowed radius (e.g. for //sphere)")
|
||||
public int MAX_RADIUS = LocalConfiguration.MAX_RADIUS;
|
||||
@Comment("Max allowed superpickaxe size")
|
||||
public int MAX_SUPER_PICKAXE_SIZE = LocalConfiguration.MAX_SUPER_RADIUS;
|
||||
@Comment("Max allowed brush radius")
|
||||
public int MAX_BRUSH_RADIUS = LocalConfiguration.MAX_BRUSH_RADIUS;
|
||||
@Comment("Max allowed butcher radius")
|
||||
public int MAX_BUTCHER_RADIUS = LocalConfiguration.MAX_BUTCHER_RADIUS;
|
||||
@Comment({
|
||||
"Blockstates include Banner, Beacon, BrewingStand, Chest, CommandBlock, ",
|
||||
"CreatureSpawner, Dispenser, Dropper, EndGateway, Furnace, Hopper, Jukebox, ",
|
||||
@ -353,6 +389,18 @@ public class Settings extends Config {
|
||||
" - History on disk or memory will be deleted",
|
||||
})
|
||||
public int MAX_HISTORY_MB = -1;
|
||||
@Comment({
|
||||
"Sets a maximum limit (in kb) for the size of a player's schematics directory (per-player mode only)",
|
||||
"Set to -1 to disable"
|
||||
})
|
||||
@Migrate("experimental.per-player-file-size-limit")
|
||||
public int SCHEM_FILE_SIZE_LIMIT = -1;
|
||||
@Comment({
|
||||
"Sets a maximum limit for the amount of schematics in a player's schematics directory (per-player mode only)",
|
||||
"Set to -1 to disable"
|
||||
})
|
||||
@Migrate("experimental.per-player-file-num-limit")
|
||||
public int SCHEM_FILE_NUM_LIMIT = -1;
|
||||
@Comment("Maximum time in milliseconds //calc can execute")
|
||||
public int MAX_EXPRESSION_MS = 50;
|
||||
@Comment({
|
||||
@ -394,12 +442,17 @@ public class Settings extends Config {
|
||||
" - If fast-placement is disabled, this may cause edits to be slower."
|
||||
})
|
||||
public boolean UNIVERSAL_DISALLOWED_BLOCKS = true;
|
||||
@Comment({
|
||||
"If legacy, mumerical, blocks IDs should be able to be used (i.e. 12:2),"
|
||||
})
|
||||
public boolean ALLOW_LEGACY = true;
|
||||
@Comment({
|
||||
"List of blocks to deny use of. Can be either an entire block type or a block with a specific property value.",
|
||||
"Where block properties are specified, any blockstate with the property will be disallowed (e.g. all directions",
|
||||
"of a waterlogged fence). For blocking/remapping of all occurrences of a property like waterlogged, see",
|
||||
"remap-properties below.",
|
||||
"To generate a blank list, substitute the default content with a set of square brackets [] instead.",
|
||||
"The 'worldedit.anyblock' permission is not considered here.",
|
||||
"Example block property blocking:",
|
||||
" - \"minecraft:conduit[waterlogged=true]\"",
|
||||
" - \"minecraft:piston[extended=false,facing=west]\"",
|
||||
@ -472,6 +525,9 @@ public class Settings extends Config {
|
||||
public int DELETE_AFTER_DAYS = 7;
|
||||
@Comment("Delete history in memory on logout (does not effect disk)")
|
||||
public boolean DELETE_ON_LOGOUT = true;
|
||||
@Comment("Delete history on disk on logout")
|
||||
@CopiedFrom("history.delete-on-logout")
|
||||
public boolean DELETE_DISK_ON_LOGOUT = false;
|
||||
@Comment({
|
||||
"If history should be enabled by default for plugins using WorldEdit:",
|
||||
" - It is faster to have disabled",
|
||||
@ -510,7 +566,7 @@ public class Settings extends Config {
|
||||
" - A larger value will use slightly less CPU time",
|
||||
" - A smaller value will reduce memory usage",
|
||||
" - A value too small may break some operations (deform?)",
|
||||
" - Values smaller than the configurated parallel-threads are not accepted",
|
||||
" - Values smaller than the configured parallel-threads are not accepted",
|
||||
" - It is recommended this option be at least 4x greater than parallel-threads"
|
||||
|
||||
})
|
||||
@ -543,12 +599,6 @@ public class Settings extends Config {
|
||||
})
|
||||
public boolean POOL = true;
|
||||
|
||||
@Comment({
|
||||
"When using fastmode do not bother to tick existing/placed blocks/fluids",
|
||||
"Only works in versions up to 1.17.1"
|
||||
})
|
||||
public boolean NO_TICK_FASTMODE = true;
|
||||
|
||||
public static class PROGRESS {
|
||||
|
||||
@Comment({"Display constant titles about the progress of a user's edit",
|
||||
@ -574,6 +624,13 @@ public class Settings extends Config {
|
||||
})
|
||||
public static class EXPERIMENTAL {
|
||||
|
||||
@Comment({
|
||||
"Undo operation batch size",
|
||||
" - The size defines the number of changes read at once.",
|
||||
" - Larger numbers might reduce overhead but increase latency for edits with only few changes.",
|
||||
" - 0 means undo operations are not batched."})
|
||||
public int UNDO_BATCH_SIZE = 128;
|
||||
|
||||
@Comment({
|
||||
"[UNSAFE] Directly modify the region files. (OBSOLETE - USE ANVIL COMMANDS)",
|
||||
" - IMPROPER USE CAN CAUSE WORLD CORRUPTION!",
|
||||
@ -621,16 +678,9 @@ public class Settings extends Config {
|
||||
public boolean ALLOW_TICK_FLUIDS = false;
|
||||
|
||||
@Comment({
|
||||
"Sets a maximum limit (in kb) for the size of a player's schematics directory (per-player mode only)",
|
||||
"Set to -1 to disable"
|
||||
"Whether FAWE should use the incubator Vector API to accelerate some operations"
|
||||
})
|
||||
public int PER_PLAYER_FILE_SIZE_LIMIT = -1;
|
||||
|
||||
@Comment({
|
||||
"Sets a maximum limit for the amount of schematics in a player's schematics directory (per-player mode only)",
|
||||
"Set to -1 to disable"
|
||||
})
|
||||
public int PER_PLAYER_FILE_NUM_LIMIT = -1;
|
||||
public boolean USE_VECTOR_API = false;
|
||||
|
||||
}
|
||||
|
||||
@ -640,6 +690,13 @@ public class Settings extends Config {
|
||||
@Comment({"The web interface for clipboards", " - All schematics are anonymous and private", " - Downloads can be deleted by the user", " - Supports clipboard uploads, downloads and saves",})
|
||||
public String URL = "https://schem.intellectualsites.com/fawe/";
|
||||
|
||||
@Comment({"The url of the backend server (Arkitektonika)"})
|
||||
public String ARKITEKTONIKA_BACKEND_URL = "https://api.schematic.cloud/";
|
||||
@Comment({"The url used to generate a download link from.", "{key} will be replaced with the generated key"})
|
||||
public String ARKITEKTONIKA_DOWNLOAD_URL = "https://schematic.cloud/download/{key}";
|
||||
@Comment({"The url used to generate a deletion link from.", "{key} will be replaced with the generated key"})
|
||||
public String ARKITEKTONIKA_DELETE_URL = "https://schematic.cloud/delete/{key}";
|
||||
|
||||
@Comment("The maximum amount of time in seconds the plugin can attempt to load images for.")
|
||||
public int MAX_IMAGE_LOAD_TIME = 5;
|
||||
|
||||
@ -720,6 +777,13 @@ public class Settings extends Config {
|
||||
" - Requires clipboard.use-disk to be enabled"
|
||||
})
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
@ -742,4 +806,18 @@ public class Settings extends Config {
|
||||
|
||||
}
|
||||
|
||||
public static class GENERAL {
|
||||
|
||||
@Comment({
|
||||
"If the player should be relocated/unstuck when a generation command would bury them",
|
||||
})
|
||||
public boolean UNSTUCK_ON_GENERATE = true;
|
||||
|
||||
@Comment({
|
||||
"If unlimited limits should still require /confirm on large. Defaults to limits.default.confirm-large otherwise."
|
||||
})
|
||||
public boolean LIMIT_UNLIMITED_CONFIRMS = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -68,6 +68,7 @@ public class YamlConfiguration extends FileConfiguration {
|
||||
LOGGER.error("Could not read {}\n" + "Renamed to {}", file, dest.getAbsolutePath(), ex);
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ public class DBHandler {
|
||||
* @deprecated Use {@link #dbHandler()} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2.0.0")
|
||||
public static final DBHandler IMP = new DBHandler();
|
||||
public static final DBHandler IMP = dbHandler();
|
||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||
private static DBHandler INSTANCE;
|
||||
private final Map<World, RollbackDatabase> databases = new ConcurrentHashMap<>(8, 0.9f, 1);
|
||||
|
||||
@ -64,26 +64,47 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
||||
public Future<Boolean> init() {
|
||||
return call(() -> {
|
||||
try (PreparedStatement stmt = connection.prepareStatement("CREATE TABLE IF NOT EXISTS`" + this.prefix +
|
||||
"edits` (`player` BLOB(16) NOT NULL,`id` INT NOT NULL, `time` INT NOT NULL,`x1`" +
|
||||
"INT NOT NULL,`x2` INT NOT NULL,`z1` INT NOT NULL,`z2` INT NOT NULL,`y1`" +
|
||||
"INT NOT NULL, `y2` INT NOT NULL, `size` INT NOT NULL, `command` VARCHAR, PRIMARY KEY (player, id))")) {
|
||||
"_edits` (`player` BLOB(16) NOT NULL,`id` INT NOT NULL, `time` INT NOT NULL,`x1` " +
|
||||
"INT NOT NULL,`x2` INT NOT NULL,`z1` INT NOT NULL,`z2` INT NOT NULL,`y1` " +
|
||||
"INT NOT NULL, `y2` INT NOT NULL, `size` BIGINT NOT NULL, `command` VARCHAR, PRIMARY KEY (player, id))")) {
|
||||
stmt.executeUpdate();
|
||||
}
|
||||
try (PreparedStatement stmt = connection.prepareStatement("ALTER TABLE`" + this.prefix + "edits` ADD COLUMN `command` VARCHAR")) {
|
||||
String alterTablePrefix = "ALTER TABLE`" + this.prefix + "edits` ";
|
||||
try (PreparedStatement stmt =
|
||||
connection.prepareStatement(alterTablePrefix + "ADD COLUMN `command` VARCHAR")) {
|
||||
stmt.executeUpdate();
|
||||
} catch (SQLException ignored) {
|
||||
} // Already updated
|
||||
try (PreparedStatement stmt = connection.prepareStatement("ALTER TABLE`" + this.prefix + "edits` ADD SIZE INT DEFAULT 0 NOT NULL")) {
|
||||
try (PreparedStatement stmt =
|
||||
connection.prepareStatement(alterTablePrefix + "ADD COLUMN `size` BIGINT DEFAULT 0 NOT NULL")) {
|
||||
stmt.executeUpdate();
|
||||
} catch (SQLException ignored) {
|
||||
} // Already updated
|
||||
|
||||
boolean migrated = false;
|
||||
try (PreparedStatement stmt =
|
||||
connection.prepareStatement("INSERT INTO `" + this.prefix + "_edits` " +
|
||||
"(player, id, time, x1, x2, z1, z2, y1, y2, size, command) " +
|
||||
"SELECT player, id, time, x1, x2, z1, z2, y1, y2, size, command " +
|
||||
"FROM `" + this.prefix + "edits`")) {
|
||||
|
||||
stmt.executeUpdate();
|
||||
migrated = true;
|
||||
} catch (SQLException ignored) {
|
||||
} // Already updated
|
||||
if (migrated) {
|
||||
try (PreparedStatement stmt = connection.prepareStatement("DROP TABLE `" + this.prefix + "edits`")) {
|
||||
stmt.executeUpdate();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public Future<Integer> delete(UUID uuid, int id) {
|
||||
return call(() -> {
|
||||
try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix + "edits` WHERE `player`=? AND `id`=?")) {
|
||||
try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix + "_edits` WHERE `player`=? " +
|
||||
"AND `id`=?")) {
|
||||
stmt.setBytes(1, toBytes(uuid));
|
||||
stmt.setInt(2, id);
|
||||
return stmt.executeUpdate();
|
||||
@ -94,7 +115,7 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
||||
public Future<RollbackOptimizedHistory> getEdit(@Nonnull UUID uuid, int id) {
|
||||
return call(() -> {
|
||||
try (PreparedStatement stmt = connection.prepareStatement("SELECT * FROM`" + this.prefix +
|
||||
"edits` WHERE `player`=? AND `id`=?")) {
|
||||
"_edits` WHERE `player`=? AND `id`=?")) {
|
||||
stmt.setBytes(1, toBytes(uuid));
|
||||
stmt.setInt(2, id);
|
||||
ResultSet result = stmt.executeQuery();
|
||||
@ -119,7 +140,7 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
||||
CuboidRegion region = new CuboidRegion(BlockVector3.at(x1, y1, z1), BlockVector3.at(x2, y2, z2));
|
||||
|
||||
long time = result.getInt("time") * 1000L;
|
||||
long size = result.getInt("size");
|
||||
long size = result.getLong("size");
|
||||
|
||||
String command = result.getString("command");
|
||||
|
||||
@ -135,7 +156,7 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
||||
long now = System.currentTimeMillis() / 1000;
|
||||
final int then = (int) (now - diff);
|
||||
return call(() -> {
|
||||
try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix + "edits` WHERE `time`<?")) {
|
||||
try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix + "_edits` WHERE `time`<?")) {
|
||||
stmt.setInt(1, then);
|
||||
return stmt.executeUpdate();
|
||||
}
|
||||
@ -159,23 +180,33 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
||||
Future<Integer> future = call(() -> {
|
||||
try {
|
||||
int count = 0;
|
||||
String stmtStr = ascending ? uuid == null ? "SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND `x2`>=? AND" +
|
||||
" `x1`<=? AND `z2`>=? AND `z1`<=? AND `y2`>=? AND `y1`<=? ORDER BY `time` , `id`" :
|
||||
"SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND" +
|
||||
" `x2`>=? AND `x1`<=? AND `z2`>=? AND `z1`<=? AND `y2`>=? AND `y1`<=? AND `player`=? ORDER BY `time` ASC, `id` ASC" :
|
||||
uuid == null ? "SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND `x2`>=? AND `x1`<=? AND `z2`>=? " +
|
||||
"AND `z1`<=? AND `y2`>=? AND `y1`<=? ORDER BY `time` DESC, `id` DESC" :
|
||||
"SELECT * FROM`" + this.prefix + "edits` WHERE `time`>? AND `x2`>=? AND `x1`<=? AND" +
|
||||
" `z2`>=? AND `z1`<=? AND `y2`>=? AND `y1`<=? AND `player`=? ORDER BY `time` DESC, `id` DESC";
|
||||
try (PreparedStatement stmt = connection.prepareStatement(stmtStr)) {
|
||||
String stmtStr = """
|
||||
SELECT * FROM `%s_edits`
|
||||
WHERE `time` > ?
|
||||
AND `x2` >= ?
|
||||
AND `x1` <= ?
|
||||
AND `z2` >= ?
|
||||
AND `z1` <= ?
|
||||
AND `y2` >= ?
|
||||
AND `y1` <= ?
|
||||
""";
|
||||
if (uuid != null) {
|
||||
stmtStr += "\n AND `player`= ?";
|
||||
}
|
||||
if (ascending) {
|
||||
stmtStr += "\n ORDER BY `time` ASC, `id` ASC";
|
||||
} else {
|
||||
stmtStr += "\n ORDER BY `time` DESC, `id` DESC";
|
||||
}
|
||||
try (PreparedStatement stmt = connection.prepareStatement(stmtStr.formatted(this.prefix))) {
|
||||
stmt.setInt(1, (int) (minTime / 1000));
|
||||
stmt.setInt(2, pos1.getBlockX());
|
||||
stmt.setInt(3, pos2.getBlockX());
|
||||
stmt.setInt(4, pos1.getBlockZ());
|
||||
stmt.setInt(5, pos2.getBlockZ());
|
||||
stmt.setInt(2, pos1.x());
|
||||
stmt.setInt(3, pos2.x());
|
||||
stmt.setInt(4, pos1.z());
|
||||
stmt.setInt(5, pos2.z());
|
||||
// Keep 128 offset for backwards-compatibility
|
||||
stmt.setInt(6, pos1.getBlockY() - 128);
|
||||
stmt.setInt(7, pos2.getBlockY() - 128);
|
||||
stmt.setInt(6, pos1.y() - 128);
|
||||
stmt.setInt(7, pos2.y() - 128);
|
||||
if (uuid != null) {
|
||||
byte[] uuidBytes = toBytes(uuid);
|
||||
stmt.setBytes(8, uuidBytes);
|
||||
@ -192,21 +223,22 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
||||
}
|
||||
if (delete && uuid != null) {
|
||||
try (PreparedStatement stmt = connection.prepareStatement("DELETE FROM`" + this.prefix +
|
||||
"edits` WHERE `player`=? AND `time`>? AND `x2`>=? AND `x1`<=? AND `y2`>=? AND `y1`<=? AND `z2`>=? AND `z1`<=?")) {
|
||||
stmt.setInt(1, (int) (minTime / 1000));
|
||||
stmt.setInt(2, pos1.getBlockX());
|
||||
stmt.setInt(3, pos2.getBlockX());
|
||||
stmt.setInt(4, pos1.getBlockZ());
|
||||
stmt.setInt(5, pos2.getBlockZ());
|
||||
// Keep 128 offset for backwards-compatibility
|
||||
stmt.setInt(6, pos1.getBlockY() - 128);
|
||||
stmt.setInt(7, pos2.getBlockY() - 128);
|
||||
"_edits` WHERE `player`=? AND `time`>? AND `x2`>=? AND `x1`<=? AND `y2`>=? AND `y1`<=? AND `z2`>=? " +
|
||||
"AND `z1`<=?")) {
|
||||
byte[] uuidBytes = ByteBuffer
|
||||
.allocate(16)
|
||||
.putLong(uuid.getMostSignificantBits())
|
||||
.putLong(uuid.getLeastSignificantBits())
|
||||
.array();
|
||||
stmt.setBytes(8, uuidBytes);
|
||||
stmt.setBytes(1, uuidBytes);
|
||||
stmt.setInt(2, (int) (minTime / 1000));
|
||||
stmt.setInt(3, pos1.x());
|
||||
stmt.setInt(4, pos2.x());
|
||||
stmt.setInt(5, pos1.z());
|
||||
stmt.setInt(6, pos2.z());
|
||||
// Keep 128 offset for backwards-compatibility
|
||||
stmt.setInt(7, pos1.y() - 128);
|
||||
stmt.setInt(8, pos2.y() - 128);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
@ -239,7 +271,7 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
||||
RollbackOptimizedHistory[] copy = IntStream.range(0, size)
|
||||
.mapToObj(i -> historyChanges.poll()).toArray(RollbackOptimizedHistory[]::new);
|
||||
|
||||
try (PreparedStatement stmt = connection.prepareStatement("INSERT OR REPLACE INTO`" + this.prefix + "edits`" +
|
||||
try (PreparedStatement stmt = connection.prepareStatement("INSERT OR REPLACE INTO`" + this.prefix + "_edits`" +
|
||||
" (`player`,`id`,`time`,`x1`,`x2`,`z1`,`z2`,`y1`,`y2`,`command`,`size`) VALUES(?,?,?,?,?,?,?,?,?,?,?)")) {
|
||||
// `player`,`id`,`time`,`x1`,`x2`,`z1`,`z2`,`y1`,`y2`,`command`,`size`) VALUES(?,?,?,?,?,?,?,?,?,?,?)"
|
||||
for (RollbackOptimizedHistory change : copy) {
|
||||
@ -252,15 +284,15 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
||||
BlockVector3 pos1 = change.getMinimumPoint();
|
||||
BlockVector3 pos2 = change.getMaximumPoint();
|
||||
|
||||
stmt.setInt(4, pos1.getX());
|
||||
stmt.setInt(5, pos2.getX());
|
||||
stmt.setInt(6, pos1.getZ());
|
||||
stmt.setInt(7, pos2.getZ());
|
||||
stmt.setInt(4, pos1.x());
|
||||
stmt.setInt(5, pos2.x());
|
||||
stmt.setInt(6, pos1.z());
|
||||
stmt.setInt(7, pos2.z());
|
||||
// Keep 128 offset for backwards-compatibility
|
||||
stmt.setInt(8, pos1.getY() - 128);
|
||||
stmt.setInt(9, pos2.getY() - 128);
|
||||
stmt.setInt(8, pos1.y() - 128);
|
||||
stmt.setInt(9, pos2.y() - 128);
|
||||
stmt.setString(10, change.getCommand());
|
||||
stmt.setInt(11, change.size());
|
||||
stmt.setLong(11, change.longSize());
|
||||
stmt.executeUpdate();
|
||||
stmt.clearParameters();
|
||||
}
|
||||
|
||||
@ -3,25 +3,25 @@ package com.fastasyncworldedit.core.entity;
|
||||
import com.fastasyncworldedit.core.Fawe;
|
||||
import com.fastasyncworldedit.core.util.TaskManager;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.util.nbt.CompoundBinaryTag;
|
||||
import com.sk89q.worldedit.world.entity.EntityType;
|
||||
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class LazyBaseEntity extends BaseEntity {
|
||||
|
||||
private Supplier<CompoundBinaryTag> saveTag;
|
||||
private Supplier<LinCompoundTag> saveTag;
|
||||
|
||||
public LazyBaseEntity(EntityType type, Supplier<CompoundBinaryTag> saveTag) {
|
||||
public LazyBaseEntity(EntityType type, Supplier<LinCompoundTag> saveTag) {
|
||||
super(type);
|
||||
this.saveTag = saveTag;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CompoundBinaryTag getNbt() {
|
||||
Supplier<CompoundBinaryTag> tmp = saveTag;
|
||||
public LinCompoundTag getNbt() {
|
||||
Supplier<LinCompoundTag> tmp = saveTag;
|
||||
if (tmp != null) {
|
||||
saveTag = null;
|
||||
if (Fawe.isMainThread()) {
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.fastasyncworldedit.core.exception;
|
||||
|
||||
/**
|
||||
* Thrown when a maximum radius for a brush is reached.
|
||||
*/
|
||||
public class BrushRadiusLimitException extends RadiusLimitException {
|
||||
|
||||
public BrushRadiusLimitException(int maxBrushRadius) {
|
||||
super(maxBrushRadius);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.fastasyncworldedit.core.exception;
|
||||
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
|
||||
public class OutsideWorldBoundsException extends WorldEditException {
|
||||
|
||||
private final int y;
|
||||
|
||||
public OutsideWorldBoundsException(int y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public int y() {
|
||||
return y;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.fastasyncworldedit.core.exception;
|
||||
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
|
||||
/**
|
||||
* Thrown when a maximum radius is reached, such as, for example,
|
||||
* in the case of a sphere command.
|
||||
*/
|
||||
public class RadiusLimitException extends WorldEditException {
|
||||
|
||||
private final int maxRadius;
|
||||
|
||||
public RadiusLimitException(int maxRadius) {
|
||||
this.maxRadius = maxRadius;
|
||||
}
|
||||
|
||||
public int getMaxRadius() {
|
||||
return maxRadius;
|
||||
}
|
||||
//FAWE end
|
||||
|
||||
}
|
||||
@ -21,22 +21,17 @@ import com.sk89q.worldedit.internal.registry.AbstractFactory;
|
||||
import com.sk89q.worldedit.internal.registry.InputParser;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TransformFactory extends AbstractFactory<ResettableExtent> {
|
||||
|
||||
private final RichTransformParser richTransformParser;
|
||||
|
||||
/**
|
||||
* Create a new factory.
|
||||
*
|
||||
* @param worldEdit the WorldEdit instance
|
||||
*/
|
||||
public TransformFactory(WorldEdit worldEdit) {
|
||||
super(worldEdit, new NullTransformParser(worldEdit));
|
||||
|
||||
richTransformParser = new RichTransformParser(worldEdit);
|
||||
super(worldEdit, new NullTransformParser(worldEdit), new RichTransformParser(worldEdit));
|
||||
|
||||
// split and parse each sub-transform
|
||||
register(new RandomTransformParser(worldEdit));
|
||||
@ -51,68 +46,7 @@ public class TransformFactory extends AbstractFactory<ResettableExtent> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResettableExtent parseFromInput(String input, ParserContext context) throws InputParseException {
|
||||
List<ResettableExtent> transforms = new ArrayList<>();
|
||||
|
||||
for (String component : input.split(" ")) {
|
||||
if (component.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ResettableExtent match = richTransformParser.parseFromInput(component, context);
|
||||
if (match != null) {
|
||||
transforms.add(match);
|
||||
continue;
|
||||
}
|
||||
parseFromParsers(context, transforms, component);
|
||||
}
|
||||
|
||||
return getResettableExtent(input, transforms);
|
||||
}
|
||||
|
||||
private void parseFromParsers(
|
||||
final ParserContext context,
|
||||
final List<ResettableExtent> transforms,
|
||||
final String component
|
||||
) {
|
||||
ResettableExtent match = null;
|
||||
for (InputParser<ResettableExtent> parser : getParsers()) {
|
||||
match = parser.parseFromInput(component, context);
|
||||
|
||||
if (match != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match == null) {
|
||||
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(component)));
|
||||
}
|
||||
transforms.add(match);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a transform without considering parsing through the {@link RichTransformParser}, therefore not accepting
|
||||
* "richer" parsing where & and , are used. Exists to prevent stack overflows.
|
||||
*
|
||||
* @param input input string
|
||||
* @param context input context
|
||||
* @return parsed result
|
||||
* @throws InputParseException if no result found
|
||||
*/
|
||||
public ResettableExtent parseWithoutRich(String input, ParserContext context) throws InputParseException {
|
||||
List<ResettableExtent> transforms = new ArrayList<>();
|
||||
|
||||
for (String component : input.split(" ")) {
|
||||
if (component.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
parseFromParsers(context, transforms, component);
|
||||
}
|
||||
|
||||
return getResettableExtent(input, transforms);
|
||||
}
|
||||
|
||||
private ResettableExtent getResettableExtent(final String input, final List<ResettableExtent> transforms) {
|
||||
protected ResettableExtent getParsed(final String input, final List<ResettableExtent> transforms) {
|
||||
switch (transforms.size()) {
|
||||
case 0:
|
||||
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
|
||||
|
||||
@ -37,14 +37,14 @@ public abstract class FaweParser<T> extends InputParser<T> implements AliasedPar
|
||||
for (int i = 0; i < toParse.length(); i++) {
|
||||
char c = toParse.charAt(i);
|
||||
switch (c) {
|
||||
case ',', '&' -> {
|
||||
case ',', '&', ' ' -> {
|
||||
if (expression) {
|
||||
continue;
|
||||
}
|
||||
String result = toParse.substring(last, i);
|
||||
if (!result.isEmpty()) {
|
||||
inputs.add(result);
|
||||
and.add(c == '&');
|
||||
and.add(c == '&' || c == ' ');
|
||||
} else {
|
||||
throw new InputParseException(Caption.of("fawe.error.parse.invalid-dangling-character", c));
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ public abstract class RichParser<E> extends InputParser<E> implements AliasedPar
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Function<String, Stream<? extends String>> extractArguments(String input) {
|
||||
private Function<String, Stream<? extends String>> extractArguments(String input, ParserContext context) {
|
||||
return prefix -> {
|
||||
if (input.length() > prefix.length() && input.startsWith(prefix + "[")) {
|
||||
// input already contains argument(s) -> extract them
|
||||
@ -65,7 +65,7 @@ public abstract class RichParser<E> extends InputParser<E> implements AliasedPar
|
||||
}
|
||||
String previous = prefix + builder;
|
||||
// read the suggestions for the last argument
|
||||
return getSuggestions(strings[strings.length - 1], strings.length - 1)
|
||||
return getSuggestions(strings[strings.length - 1], strings.length - 1, context)
|
||||
.map(suggestion -> previous + "[" + suggestion);
|
||||
} else {
|
||||
return Stream.of(prefix);
|
||||
@ -95,7 +95,7 @@ public abstract class RichParser<E> extends InputParser<E> implements AliasedPar
|
||||
public Stream<String> getSuggestions(String input) {
|
||||
return Arrays.stream(this.prefixes)
|
||||
.filter(validPrefix(input))
|
||||
.flatMap(extractArguments(input));
|
||||
.flatMap(extractArguments(input, new ParserContext()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -122,8 +122,25 @@ public abstract class RichParser<E> extends InputParser<E> implements AliasedPar
|
||||
* @param argumentInput the already provided input for the argument at the given index.
|
||||
* @param index the index of the argument to get suggestions for.
|
||||
* @return a stream of suggestions matching the given input for the argument at the given index.
|
||||
*
|
||||
* @deprecated Use the version that takes a {@link ParserContext}, {@link #getSuggestions(String, int, ParserContext)}
|
||||
*/
|
||||
protected abstract Stream<String> getSuggestions(String argumentInput, int index);
|
||||
@Deprecated
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stream of suggestions for the argument at the given index.
|
||||
*
|
||||
* @param argumentInput the already provided input for the argument at the given index.
|
||||
* @param index the index of the argument to get suggestions for.
|
||||
* @param context the context which may optionally be provided by a parser.
|
||||
* @return a stream of suggestions matching the given input for the argument at the given index.
|
||||
*/
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
return getSuggestions(argumentInput, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the already split arguments.
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
package com.fastasyncworldedit.core.extension.factory.parser.common;
|
||||
|
||||
import com.fastasyncworldedit.core.configuration.Caption;
|
||||
import com.fastasyncworldedit.core.extent.inventory.SlottableBlockBag;
|
||||
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.input.DisallowedUsageException;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.internal.registry.SimpleInputParser;
|
||||
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public abstract class HotbarParser<T> extends SimpleInputParser<T> {
|
||||
|
||||
private final List<String> aliases = ImmutableList.of("#hotbar");
|
||||
|
||||
protected HotbarParser(final WorldEdit worldEdit) {
|
||||
super(worldEdit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMatchedAliases() {
|
||||
return aliases;
|
||||
}
|
||||
|
||||
protected List<BlockType> getBlockTypes(ParserContext context) {
|
||||
Player player = context.requirePlayer();
|
||||
BlockBag bag = player.getInventoryBlockBag();
|
||||
if (!(bag instanceof final SlottableBlockBag slottable)) {
|
||||
// Matches DefaultBlockParser
|
||||
throw new InputParseException(Caption.of("fawe.error.unsupported"));
|
||||
}
|
||||
List<BlockType> types = new ArrayList<>();
|
||||
FaweLimit limit = player.getLimit();
|
||||
boolean anyBlock = player.hasPermission("worldedit.anyblock");
|
||||
for (int slot = 0; slot < 9; slot++) {
|
||||
BaseItem item = slottable.getItem(slot);
|
||||
if (item != null && item.getType().hasBlockType()) {
|
||||
BlockType type = item.getType().getBlockType();
|
||||
if (!anyBlock && worldEdit.getConfiguration().disallowedBlocks.contains(type.id().toLowerCase(Locale.ROOT))) {
|
||||
throw new DisallowedUsageException(Caption.of(
|
||||
"worldedit.error.disallowed-block",
|
||||
TextComponent.of(type.getId())
|
||||
));
|
||||
}
|
||||
if (!limit.isUnlimited()) {
|
||||
if (limit.DISALLOWED_BLOCKS.contains(type.id().toLowerCase(Locale.ROOT))) {
|
||||
throw new DisallowedUsageException(Caption.of(
|
||||
"fawe.error.limit.disallowed-block",
|
||||
TextComponent.of(type.getId())
|
||||
));
|
||||
}
|
||||
}
|
||||
types.add(type);
|
||||
}
|
||||
}
|
||||
if (types.isEmpty()) {
|
||||
throw new InputParseException(Caption.of("fawe.error.no-valid-on-hotbar"));
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
}
|
||||
@ -19,9 +19,9 @@ public class AdjacentMaskParser extends RichParser<Mask> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0) {
|
||||
return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream();
|
||||
return worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream();
|
||||
} else if (index == 1 || index == 2) {
|
||||
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ public class AngleMaskParser extends RichParser<Mask> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0 || index == 1) {
|
||||
return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d"));
|
||||
} else if (index > 1 && index <= 1 + flags.length) {
|
||||
|
||||
@ -18,9 +18,9 @@ public class BesideMaskParser extends RichParser<Mask> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(final String argumentInput, final int index) {
|
||||
protected Stream<String> getSuggestions(final String argumentInput, final int index, ParserContext context) {
|
||||
if (index == 0) {
|
||||
return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream();
|
||||
return worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream();
|
||||
} else if (index == 1 || index == 2) {
|
||||
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ public class ExtremaMaskParser extends RichParser<Mask> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0 || index == 1) {
|
||||
return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d"));
|
||||
} else if (index > 1 && index <= 1 + flags.length) {
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
package com.fastasyncworldedit.core.extension.factory.parser.mask;
|
||||
|
||||
import com.fastasyncworldedit.core.extension.factory.parser.common.HotbarParser;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.function.mask.BlockTypeMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
|
||||
public class HotbarMaskParser extends HotbarParser<Mask> {
|
||||
|
||||
public HotbarMaskParser(WorldEdit worldEdit) {
|
||||
super(worldEdit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mask parseFromSimpleInput(String input, ParserContext context) {
|
||||
return new BlockTypeMask(context.getExtent(), getBlockTypes(context));
|
||||
}
|
||||
|
||||
}
|
||||
@ -22,7 +22,7 @@ public class ROCAngleMaskParser extends RichParser<Mask> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0 || index == 1) {
|
||||
return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d"));
|
||||
} else if (index > 1 && index <= 1 + flags.length) {
|
||||
|
||||
@ -18,7 +18,7 @@ public class RadiusMaskParser extends RichParser<Mask> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0 || index == 1) {
|
||||
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import com.fastasyncworldedit.core.command.SuggestInputParseException;
|
||||
import com.fastasyncworldedit.core.configuration.Caption;
|
||||
import com.fastasyncworldedit.core.extension.factory.parser.FaweParser;
|
||||
import com.fastasyncworldedit.core.function.mask.BlockMaskBuilder;
|
||||
import com.fastasyncworldedit.core.function.mask.MaskUnion;
|
||||
import com.sk89q.worldedit.function.mask.MaskUnion;
|
||||
import com.fastasyncworldedit.core.util.StringMan;
|
||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
@ -97,11 +97,11 @@ public class RichMaskParser extends FaweParser<Mask> {
|
||||
)),
|
||||
() -> {
|
||||
if (full.length() == 1) {
|
||||
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions(""));
|
||||
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions("", context));
|
||||
}
|
||||
return new ArrayList<>(worldEdit
|
||||
.getMaskFactory()
|
||||
.getSuggestions(command.toLowerCase(Locale.ROOT)));
|
||||
.getSuggestions(command.toLowerCase(Locale.ROOT), context));
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -143,7 +143,7 @@ public class RichMaskParser extends FaweParser<Mask> {
|
||||
int end = command.lastIndexOf(']');
|
||||
mask = parseFromInput(command.substring(1, end == -1 ? command.length() : end), context);
|
||||
} else {
|
||||
BlockMaskBuilder builder = new BlockMaskBuilder();
|
||||
BlockMaskBuilder builder = new BlockMaskBuilder(context);
|
||||
try {
|
||||
builder.addRegex(full);
|
||||
} catch (InputParseException ignored) {
|
||||
@ -164,11 +164,11 @@ public class RichMaskParser extends FaweParser<Mask> {
|
||||
)),
|
||||
() -> {
|
||||
if (full.length() == 1) {
|
||||
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions(""));
|
||||
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions("", context));
|
||||
}
|
||||
return new ArrayList<>(worldEdit
|
||||
.getMaskFactory()
|
||||
.getSuggestions(command.toLowerCase(Locale.ROOT)));
|
||||
.getSuggestions(command.toLowerCase(Locale.ROOT), context));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@ -24,12 +24,12 @@ public class RichOffsetMaskParser extends RichParser<Mask> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index < 3) {
|
||||
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
|
||||
}
|
||||
if (index == 3) {
|
||||
return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream();
|
||||
return worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ public class SimplexMaskParser extends RichParser<Mask> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index < 3) {
|
||||
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ public class SurfaceAngleMaskParser extends RichParser<Mask> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index <= 2) {
|
||||
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ public class AngleColorPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index != 0) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ public class AverageColorPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index > 4) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ public class BiomePatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0) {
|
||||
return BiomeType.REGISTRY.getSuggestions(argumentInput);
|
||||
}
|
||||
|
||||
@ -26,9 +26,9 @@ public class BufferedPattern2DParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0) {
|
||||
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -26,9 +26,9 @@ public class BufferedPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0) {
|
||||
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ public class ColorPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index > 4) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ public class DesaturatePatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0) {
|
||||
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
|
||||
}
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
|
||||
|
||||
import com.fastasyncworldedit.core.extension.factory.parser.common.HotbarParser;
|
||||
import com.fastasyncworldedit.core.math.random.TrueRandom;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.pattern.RandomPattern;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
|
||||
public class HotbarPatternParser extends HotbarParser<Pattern> {
|
||||
|
||||
public HotbarPatternParser(WorldEdit worldEdit) {
|
||||
super(worldEdit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pattern parseFromSimpleInput(String input, ParserContext context) {
|
||||
RandomPattern random = new RandomPattern(new TrueRandom());
|
||||
for (BlockType type : getBlockTypes(context)) {
|
||||
random.add(type, 1);
|
||||
}
|
||||
return random;
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,7 @@ package com.fastasyncworldedit.core.extension.factory.parser.pattern;
|
||||
|
||||
import com.fastasyncworldedit.core.configuration.Caption;
|
||||
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
|
||||
import com.fastasyncworldedit.core.function.pattern.Linear2DBlockPattern;
|
||||
import com.fastasyncworldedit.core.math.random.Linear2DRandom;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.command.util.SuggestionHelper;
|
||||
@ -14,7 +14,6 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Linear2DPatternParser extends RichParser<Pattern> {
|
||||
@ -29,9 +28,9 @@ public class Linear2DPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
return switch (index) {
|
||||
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
case 1, 2 -> SuggestionHelper.suggestPositiveIntegers(argumentInput);
|
||||
default -> Stream.empty();
|
||||
};
|
||||
@ -59,9 +58,8 @@ public class Linear2DPatternParser extends RichParser<Pattern> {
|
||||
zScale = Integer.parseInt(arguments[2]);
|
||||
Preconditions.checkArgument(zScale != 0);
|
||||
}
|
||||
if (inner instanceof RandomPattern) {
|
||||
Set<Pattern> patterns = ((RandomPattern) inner).getPatterns();
|
||||
return new Linear2DBlockPattern(patterns.toArray(new Pattern[0]), xScale, zScale);
|
||||
if (inner instanceof RandomPattern rp) {
|
||||
return new RandomPattern(new Linear2DRandom(xScale, zScale), rp);
|
||||
}
|
||||
throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName()
|
||||
+ " cannot be used with " + getPrefix()));
|
||||
|
||||
@ -2,7 +2,7 @@ package com.fastasyncworldedit.core.extension.factory.parser.pattern;
|
||||
|
||||
import com.fastasyncworldedit.core.configuration.Caption;
|
||||
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
|
||||
import com.fastasyncworldedit.core.function.pattern.Linear3DBlockPattern;
|
||||
import com.fastasyncworldedit.core.math.random.Linear3DRandom;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.command.util.SuggestionHelper;
|
||||
@ -14,7 +14,6 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Linear3DPatternParser extends RichParser<Pattern> {
|
||||
@ -29,9 +28,9 @@ public class Linear3DPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
return switch (index) {
|
||||
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput);
|
||||
default -> Stream.empty();
|
||||
};
|
||||
@ -64,9 +63,8 @@ public class Linear3DPatternParser extends RichParser<Pattern> {
|
||||
zScale = Integer.parseInt(arguments[3]);
|
||||
Preconditions.checkArgument(zScale != 0);
|
||||
}
|
||||
if (inner instanceof RandomPattern) {
|
||||
Set<Pattern> patterns = ((RandomPattern) inner).getPatterns();
|
||||
return new Linear3DBlockPattern(patterns.toArray(new Pattern[0]), xScale, yScale, zScale);
|
||||
if (inner instanceof RandomPattern rp) {
|
||||
return new RandomPattern(new Linear3DRandom(xScale, yScale, zScale), rp);
|
||||
}
|
||||
throw new InputParseException(TextComponent.of("Pattern " + inner.getClass().getSimpleName()
|
||||
+ " cannot be used with " + getPrefix()));
|
||||
|
||||
@ -28,9 +28,9 @@ public class LinearPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
return switch (index) {
|
||||
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput);
|
||||
default -> Stream.empty();
|
||||
};
|
||||
|
||||
@ -25,10 +25,10 @@ public class MaskedPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
return switch (index) {
|
||||
case 0 -> this.worldEdit.getMaskFactory().getSuggestions(argumentInput).stream();
|
||||
case 1, 2 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
case 0 -> this.worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream();
|
||||
case 1, 2 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
default -> Stream.empty();
|
||||
};
|
||||
}
|
||||
|
||||
@ -24,9 +24,9 @@ public class NoXPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0) {
|
||||
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -24,9 +24,9 @@ public class NoYPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0) {
|
||||
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -24,9 +24,9 @@ public class NoZPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0) {
|
||||
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -36,12 +36,12 @@ public abstract class NoisePatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0) {
|
||||
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
|
||||
}
|
||||
if (index == 1) {
|
||||
return worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
return worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -25,9 +25,9 @@ public class OffsetPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
return switch (index) {
|
||||
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput);
|
||||
default -> Stream.empty();
|
||||
};
|
||||
|
||||
@ -4,6 +4,7 @@ import com.fastasyncworldedit.core.configuration.Caption;
|
||||
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
|
||||
import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder;
|
||||
import com.fastasyncworldedit.core.function.pattern.RandomFullClipboardPattern;
|
||||
import com.google.common.base.Function;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.command.util.SuggestionHelper;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
@ -33,7 +34,7 @@ public class RandomFullClipboardPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
if (argumentInput.equals("#") || argumentInput.equals("#c")) {
|
||||
|
||||
@ -25,9 +25,9 @@ public class RandomOffsetPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
return switch (index) {
|
||||
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput);
|
||||
default -> Stream.empty();
|
||||
};
|
||||
|
||||
@ -24,9 +24,9 @@ public class RelativePatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0) {
|
||||
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ public class SaturatePatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index > 3) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -25,9 +25,9 @@ public class SolidRandomOffsetPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
return switch (index) {
|
||||
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput);
|
||||
default -> Stream.empty();
|
||||
};
|
||||
|
||||
@ -25,9 +25,9 @@ public class SurfaceRandomOffsetPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
return switch (index) {
|
||||
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
case 1 -> SuggestionHelper.suggestPositiveIntegers(argumentInput);
|
||||
default -> Stream.empty();
|
||||
};
|
||||
|
||||
@ -28,7 +28,7 @@ public class TypeSwapPatternParser extends RichParser<Pattern> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
public Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index > 2) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -23,9 +23,9 @@ public class Linear3DTransformParser extends RichParser<ResettableExtent> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0) {
|
||||
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
|
||||
return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -23,9 +23,9 @@ public class LinearTransformParser extends RichParser<ResettableExtent> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0) {
|
||||
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
|
||||
return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -26,11 +26,11 @@ public class OffsetTransformParser extends RichParser<ResettableExtent> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index < 3) {
|
||||
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
|
||||
} else if (index == 3) {
|
||||
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
|
||||
return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -24,11 +24,11 @@ public class PatternTransformParser extends RichParser<ResettableExtent> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index == 0) {
|
||||
return worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
|
||||
return worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream();
|
||||
} else if (index == 1) {
|
||||
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
|
||||
return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -25,12 +25,12 @@ public class RotateTransformParser extends RichParser<ResettableExtent> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index < 3) {
|
||||
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
|
||||
}
|
||||
if (index == 3) {
|
||||
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
|
||||
return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -24,11 +24,11 @@ public class ScaleTransformParser extends RichParser<ResettableExtent> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index < 3) {
|
||||
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
|
||||
} else if (index == 3) {
|
||||
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
|
||||
return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -24,11 +24,11 @@ public class SpreadTransformParser extends RichParser<ResettableExtent> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index) {
|
||||
protected Stream<String> getSuggestions(String argumentInput, int index, ParserContext context) {
|
||||
if (index < 3) {
|
||||
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
|
||||
} else if (index == 3) {
|
||||
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
|
||||
return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@ -200,6 +200,7 @@ public class ConsumeBindings extends Bindings {
|
||||
public BaseBlock baseBlock(Actor actor, String argument) {
|
||||
ParserContext parserContext = new ParserContext();
|
||||
parserContext.setActor(actor);
|
||||
parserContext.setTryLegacy(actor.getLimit().ALLOW_LEGACY);
|
||||
if (actor instanceof Entity) {
|
||||
Extent extent = ((Entity) actor).getExtent();
|
||||
if (extent instanceof World) {
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
package com.fastasyncworldedit.core.extension.platform.binding;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
|
||||
public record EditSessionHolder(EditSession session) {
|
||||
|
||||
}
|
||||
@ -3,7 +3,11 @@ package com.fastasyncworldedit.core.extension.platform.binding;
|
||||
import com.fastasyncworldedit.core.configuration.Caption;
|
||||
import com.fastasyncworldedit.core.database.DBHandler;
|
||||
import com.fastasyncworldedit.core.database.RollbackDatabase;
|
||||
import com.fastasyncworldedit.core.extent.LimitExtent;
|
||||
import com.fastasyncworldedit.core.extent.processor.ExtentBatchProcessorHolder;
|
||||
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||
import com.fastasyncworldedit.core.regions.FaweMaskManager;
|
||||
import com.fastasyncworldedit.core.util.ExtentTraverser;
|
||||
import com.fastasyncworldedit.core.util.TextureUtil;
|
||||
import com.fastasyncworldedit.core.util.image.ImageUtil;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
@ -11,6 +15,7 @@ import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.command.argument.Arguments;
|
||||
import com.sk89q.worldedit.command.util.annotation.AllowedRegion;
|
||||
import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
@ -25,6 +30,7 @@ import org.enginehub.piston.inject.Key;
|
||||
import org.enginehub.piston.util.ValueProvider;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.util.Optional;
|
||||
|
||||
@ -52,11 +58,33 @@ public class ProvideBindings extends Bindings {
|
||||
|
||||
@Binding
|
||||
public EditSession editSession(LocalSession localSession, Actor actor, InjectedValueAccess context) {
|
||||
Method commandMethod =
|
||||
context.injectedValue(Key.of(InjectedValueStore.class)).get().injectedValue(Key.of(Method.class)).get();
|
||||
|
||||
Arguments arguments = context.injectedValue(Key.of(Arguments.class)).orElse(null);
|
||||
String command = arguments == null ? null : arguments.get();
|
||||
EditSession editSession = localSession.createEditSession(actor, command);
|
||||
editSession.enableStandardMode();
|
||||
Request.request().setEditSession(editSession);
|
||||
boolean synchronousSetting = commandMethod.getAnnotation(SynchronousSettingExpected.class) != null;
|
||||
EditSessionHolder holder = context.injectedValue(Key.of(EditSessionHolder.class)).orElse(null);
|
||||
EditSession editSession = holder != null ? holder.session() : null;
|
||||
if (editSession == null) {
|
||||
editSession = localSession.createEditSession(actor, command);
|
||||
editSession.enableStandardMode();
|
||||
} else {
|
||||
LimitExtent limitExtent = new ExtentTraverser<>(editSession).findAndGet(LimitExtent.class);
|
||||
if (limitExtent != null) {
|
||||
limitExtent.setProcessing(!synchronousSetting);
|
||||
if (!synchronousSetting) {
|
||||
ExtentBatchProcessorHolder processorHolder = new ExtentTraverser<>(editSession).findAndGet(
|
||||
ExtentBatchProcessorHolder.class);
|
||||
if (processorHolder != null) {
|
||||
processorHolder.addProcessor(limitExtent);
|
||||
} else {
|
||||
throw new FaweException(Caption.of("fawe.error.no-process-non-synchronous-edit"));
|
||||
}
|
||||
}
|
||||
}
|
||||
Request.request().setEditSession(editSession);
|
||||
}
|
||||
return editSession;
|
||||
}
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ public class BlockTranslateExtent extends AbstractDelegateExtent {
|
||||
|
||||
@Override
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 location, T block) throws WorldEditException {
|
||||
return getExtent().setBlock(location.getX() + dx, location.getY() + dy, location.getZ() + dz, block);
|
||||
return getExtent().setBlock(location.x() + dx, location.y() + dy, location.z() + dz, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -49,7 +49,7 @@ public class BlockTranslateExtent extends AbstractDelegateExtent {
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(BlockVector3 location) {
|
||||
return getBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
return getBlock(location.x(), location.y(), location.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -101,7 +101,7 @@ public class DisallowedBlocksExtent extends AbstractDelegateExtent implements IB
|
||||
@SuppressWarnings("unchecked")
|
||||
private <B extends BlockStateHolder<B>> B checkBlock(B block) {
|
||||
if (blockedBlocks != null) {
|
||||
if (blockedBlocks.contains(block.getBlockType().getId())) {
|
||||
if (blockedBlocks.contains(block.getBlockType().id())) {
|
||||
return (B) (block instanceof BlockState ? RESERVED : RESERVED.toBaseBlock()); // set to reserved/empty
|
||||
}
|
||||
}
|
||||
@ -140,7 +140,7 @@ public class DisallowedBlocksExtent extends AbstractDelegateExtent implements IB
|
||||
}
|
||||
BlockState state = BlockTypesCache.states[block];
|
||||
if (blockedBlocks != null) {
|
||||
if (blockedBlocks.contains(state.getBlockType().getId())) {
|
||||
if (blockedBlocks.contains(state.getBlockType().id())) {
|
||||
blocks[i] = BlockTypesCache.ReservedIDs.__RESERVED__;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -64,11 +64,11 @@ public abstract class FaweRegionExtent extends ResettableExtent implements IBatc
|
||||
|
||||
@Override
|
||||
public final boolean contains(BlockVector3 p) {
|
||||
return contains(p.getBlockX(), p.getBlockY(), p.getBlockZ());
|
||||
return contains(p.x(), p.y(), p.z());
|
||||
}
|
||||
|
||||
public final boolean contains(BlockVector2 p) {
|
||||
return contains(p.getBlockX(), p.getBlockZ());
|
||||
return contains(p.x(), p.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -96,12 +96,12 @@ public abstract class FaweRegionExtent extends ResettableExtent implements IBatc
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
return getBiomeType(position.getX(), position.getY(), position.getZ());
|
||||
return getBiomeType(position.x(), position.y(), position.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiomeType(int x, int y, int z) {
|
||||
if (!contains(x, z)) {
|
||||
if (!contains(x, y, z)) {
|
||||
if (!limit.MAX_FAILS()) {
|
||||
WEManager.weManager().cancelEditSafe(this, FaweCache.OUTSIDE_REGION);
|
||||
}
|
||||
@ -112,7 +112,7 @@ public abstract class FaweRegionExtent extends ResettableExtent implements IBatc
|
||||
|
||||
@Override
|
||||
public BaseBlock getFullBlock(BlockVector3 position) {
|
||||
return getFullBlock(position.getX(), position.getY(), position.getZ());
|
||||
return getFullBlock(position.x(), position.y(), position.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -128,7 +128,7 @@ public abstract class FaweRegionExtent extends ResettableExtent implements IBatc
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(BlockVector3 position) {
|
||||
return getBlock(position.getX(), position.getY(), position.getZ());
|
||||
return getBlock(position.x(), position.y(), position.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -6,12 +6,11 @@ import com.fastasyncworldedit.core.queue.IChunkGet;
|
||||
import com.fastasyncworldedit.core.queue.IChunkSet;
|
||||
import com.fastasyncworldedit.core.regions.RegionWrapper;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class HeightBoundExtent extends FaweRegionExtent {
|
||||
|
||||
@ -50,7 +49,8 @@ public class HeightBoundExtent extends FaweRegionExtent {
|
||||
|
||||
@Override
|
||||
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 null;
|
||||
|
||||
@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.extent;
|
||||
|
||||
import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet;
|
||||
import com.fastasyncworldedit.core.math.MutableBlockVector3;
|
||||
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
@ -66,7 +67,7 @@ public class HistoryExtent extends AbstractDelegateExtent {
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block) throws WorldEditException {
|
||||
return setBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ(), block);
|
||||
return setBlock(location.x(), location.y(), location.z(), block);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -74,7 +75,7 @@ public class HistoryExtent extends AbstractDelegateExtent {
|
||||
public Entity createEntity(Location location, BaseEntity state) {
|
||||
final Entity entity = super.createEntity(location, state);
|
||||
if (state != null) {
|
||||
this.changeSet.addEntityCreate(state.getNbtData());
|
||||
this.changeSet.addEntityCreate(FaweCompoundTag.of(state.getNbt()));
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
@ -84,7 +85,7 @@ public class HistoryExtent extends AbstractDelegateExtent {
|
||||
public Entity createEntity(Location location, BaseEntity state, UUID uuid) {
|
||||
final Entity entity = super.createEntity(location, state, uuid);
|
||||
if (state != null) {
|
||||
this.changeSet.addEntityCreate(state.getNbtData());
|
||||
this.changeSet.addEntityCreate(FaweCompoundTag.of(state.getNbt()));
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
@ -110,8 +111,8 @@ public class HistoryExtent extends AbstractDelegateExtent {
|
||||
@Override
|
||||
public boolean setBiome(BlockVector3 position, BiomeType newBiome) {
|
||||
BiomeType oldBiome = this.getBiome(position);
|
||||
if (!oldBiome.getId().equals(newBiome.getId())) {
|
||||
this.changeSet.addBiomeChange(position.getBlockX(), position.getBlockY(), position.getBlockZ(), oldBiome, newBiome);
|
||||
if (!oldBiome.id().equals(newBiome.id())) {
|
||||
this.changeSet.addBiomeChange(position.x(), position.y(), position.z(), oldBiome, newBiome);
|
||||
return getExtent().setBiome(position, newBiome);
|
||||
} else {
|
||||
return false;
|
||||
@ -121,7 +122,7 @@ public class HistoryExtent extends AbstractDelegateExtent {
|
||||
@Override
|
||||
public boolean setBiome(int x, int y, int z, BiomeType newBiome) {
|
||||
BiomeType oldBiome = this.getBiome(mutable.setComponents(x, y, z));
|
||||
if (!oldBiome.getId().equals(newBiome.getId())) {
|
||||
if (!oldBiome.id().equals(newBiome.id())) {
|
||||
this.changeSet.addBiomeChange(x, y, z, oldBiome, newBiome);
|
||||
return getExtent().setBiome(x, y, z, newBiome);
|
||||
} else {
|
||||
@ -154,11 +155,10 @@ public class HistoryExtent extends AbstractDelegateExtent {
|
||||
|
||||
@Override
|
||||
public boolean remove() {
|
||||
final Location location = this.entity.getLocation();
|
||||
final BaseEntity state = this.entity.getState();
|
||||
final boolean success = this.entity.remove();
|
||||
if (state != null && success) {
|
||||
HistoryExtent.this.changeSet.addEntityRemove(state.getNbtData());
|
||||
HistoryExtent.this.changeSet.addEntityRemove(FaweCompoundTag.of(state.getNbt()));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -1,11 +1,15 @@
|
||||
package com.fastasyncworldedit.core.extent;
|
||||
|
||||
import com.fastasyncworldedit.core.extent.filter.block.ExtentFilterBlock;
|
||||
import com.fastasyncworldedit.core.function.generator.GenBase;
|
||||
import com.fastasyncworldedit.core.function.generator.Resource;
|
||||
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
||||
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||
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.fastasyncworldedit.core.util.ExtentTraverser;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
@ -17,7 +21,6 @@ import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.util.Countable;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
@ -37,18 +40,22 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class LimitExtent extends AbstractDelegateExtent {
|
||||
public class LimitExtent extends AbstractDelegateExtent implements IBatchProcessor {
|
||||
|
||||
private final FaweLimit limit;
|
||||
private final boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length];
|
||||
private final Consumer<Component> onErrorMessage;
|
||||
private final int chunk_size;
|
||||
private boolean processing;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param limit the limit
|
||||
* @deprecated Use {@link LimitExtent#LimitExtent(Extent, FaweLimit, Consumer, boolean)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2.12.0")
|
||||
public LimitExtent(Extent extent, FaweLimit limit) {
|
||||
this(extent, limit, c -> {
|
||||
});
|
||||
@ -60,11 +67,33 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
* @param extent the extent
|
||||
* @param limit the limit
|
||||
* @param onErrorMessage consumer to handle a component generated by exceptions
|
||||
* @deprecated Use {@link LimitExtent#LimitExtent(Extent, FaweLimit, Consumer, boolean)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2.12.0")
|
||||
public LimitExtent(Extent extent, FaweLimit limit, Consumer<Component> onErrorMessage) {
|
||||
this(extent, limit, onErrorMessage, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param limit the limit
|
||||
* @param onErrorMessage consumer to handle a component generated by exceptions
|
||||
* @param processing if this limit extent is expected to be processing
|
||||
* @since 2.12.0
|
||||
*/
|
||||
public LimitExtent(
|
||||
Extent extent,
|
||||
FaweLimit limit,
|
||||
Consumer<Component> onErrorMessage,
|
||||
boolean processing
|
||||
) {
|
||||
super(extent);
|
||||
this.limit = limit;
|
||||
this.onErrorMessage = onErrorMessage;
|
||||
this.chunk_size = 16 * 16 * (extent.getMaxY() - extent.getMinY());
|
||||
this.processing = processing;
|
||||
}
|
||||
|
||||
private void handleException(FaweException e) {
|
||||
@ -81,7 +110,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public List<? extends Entity> getEntities(Region region) {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
try {
|
||||
return super.getEntities(region);
|
||||
return extent.getEntities(region);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return Collections.emptyList();
|
||||
@ -92,7 +121,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public List<? extends Entity> getEntities() {
|
||||
limit.THROW_MAX_CHECKS();
|
||||
try {
|
||||
return super.getEntities();
|
||||
return extent.getEntities();
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return Collections.emptyList();
|
||||
@ -105,7 +134,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
limit.THROW_MAX_CHANGES();
|
||||
limit.THROW_MAX_ENTITIES();
|
||||
try {
|
||||
return super.createEntity(location, entity);
|
||||
return extent.createEntity(location, entity);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return null;
|
||||
@ -118,7 +147,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
limit.THROW_MAX_CHANGES();
|
||||
limit.THROW_MAX_ENTITIES();
|
||||
try {
|
||||
return super.createEntity(location, entity, uuid);
|
||||
return extent.createEntity(location, entity, uuid);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return null;
|
||||
@ -130,7 +159,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
limit.THROW_MAX_CHANGES();
|
||||
limit.THROW_MAX_ENTITIES();
|
||||
try {
|
||||
super.removeEntity(x, y, z, uuid);
|
||||
extent.removeEntity(x, y, z, uuid);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
}
|
||||
@ -138,9 +167,9 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(int x, int z, @Nullable BiomeType type, @Nullable Long seed) {
|
||||
limit.THROW_MAX_CHANGES(Character.MAX_VALUE);
|
||||
limit.THROW_MAX_CHANGES(chunk_size);
|
||||
try {
|
||||
return super.regenerateChunk(x, z, type, seed);
|
||||
return extent.regenerateChunk(x, z, type, seed);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return false;
|
||||
@ -151,7 +180,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public int getHighestTerrainBlock(int x, int z, int minY, int maxY) {
|
||||
limit.THROW_MAX_CHECKS(maxY - minY + 1);
|
||||
try {
|
||||
return super.getHighestTerrainBlock(x, z, minY, maxY);
|
||||
return extent.getHighestTerrainBlock(x, z, minY, maxY);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return minY;
|
||||
@ -162,7 +191,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public int getHighestTerrainBlock(int x, int z, int minY, int maxY, Mask filter) {
|
||||
limit.THROW_MAX_CHECKS(maxY - minY + 1);
|
||||
try {
|
||||
return super.getHighestTerrainBlock(x, z, minY, maxY, filter);
|
||||
return extent.getHighestTerrainBlock(x, z, minY, maxY, filter);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return minY;
|
||||
@ -173,7 +202,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) {
|
||||
limit.THROW_MAX_CHECKS(maxY - minY + 1);
|
||||
try {
|
||||
return super.getNearestSurfaceLayer(x, z, y, minY, maxY);
|
||||
return extent.getNearestSurfaceLayer(x, z, y, minY, maxY);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return minY;
|
||||
@ -184,7 +213,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, boolean ignoreAir) {
|
||||
limit.THROW_MAX_CHECKS(maxY - minY + 1);
|
||||
try {
|
||||
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, ignoreAir);
|
||||
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, ignoreAir);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return minY;
|
||||
@ -195,7 +224,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) {
|
||||
limit.THROW_MAX_CHECKS(maxY - minY + 1);
|
||||
try {
|
||||
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY);
|
||||
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return minY;
|
||||
@ -206,7 +235,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) {
|
||||
limit.THROW_MAX_CHECKS(maxY - minY + 1);
|
||||
try {
|
||||
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax);
|
||||
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return minY;
|
||||
@ -217,7 +246,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax, Mask mask) {
|
||||
limit.THROW_MAX_CHECKS(maxY - minY + 1);
|
||||
try {
|
||||
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, mask);
|
||||
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, mask);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return minY;
|
||||
@ -237,91 +266,47 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
) {
|
||||
limit.THROW_MAX_CHECKS(maxY - minY + 1);
|
||||
try {
|
||||
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, ignoreAir);
|
||||
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, ignoreAir);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return minY;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCaves(Region region) throws WorldEditException {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
limit.THROW_MAX_CHANGES(region.getVolume());
|
||||
super.addCaves(region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(Region region, GenBase gen) throws WorldEditException {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
limit.THROW_MAX_CHANGES(region.getVolume());
|
||||
super.generate(region, gen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSchems(Region region, Mask mask, List<ClipboardHolder> clipboards, int rarity, boolean rotate) throws
|
||||
WorldEditException {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
limit.THROW_MAX_CHANGES(region.getVolume());
|
||||
super.addSchems(region, mask, clipboards, rarity, rotate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnResource(Region region, Resource gen, int rarity, int frequency) throws WorldEditException {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
limit.THROW_MAX_CHANGES(region.getVolume());
|
||||
super.spawnResource(region, gen, rarity, frequency);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOre(Region region, Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws
|
||||
WorldEditException {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
limit.THROW_MAX_CHANGES(region.getVolume());
|
||||
super.addOre(region, mask, material, size, frequency, rarity, minY, maxY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOres(Region region, Mask mask) throws WorldEditException {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
limit.THROW_MAX_CHANGES(region.getVolume());
|
||||
super.addOres(region, mask);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Countable<BlockType>> getBlockDistribution(Region region) {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
return super.getBlockDistribution(region);
|
||||
return extent.getBlockDistribution(region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Countable<BlockState>> getBlockDistributionWithData(Region region) {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
return super.getBlockDistributionWithData(region);
|
||||
return extent.getBlockDistributionWithData(region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countBlocks(Region region, Set<BaseBlock> searchBlocks) {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
return super.countBlocks(region, searchBlocks);
|
||||
return extent.countBlocks(region, searchBlocks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countBlocks(Region region, Mask searchMask) {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
return super.countBlocks(region, searchMask);
|
||||
return extent.countBlocks(region, searchMask);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> int setBlocks(Region region, B block) throws MaxChangedBlocksException {
|
||||
limit.THROW_MAX_CHANGES(region.getVolume());
|
||||
return super.setBlocks(region, block);
|
||||
return extent.setBlocks(region, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException {
|
||||
limit.THROW_MAX_CHANGES(region.getVolume());
|
||||
return super.setBlocks(region, pattern);
|
||||
return extent.setBlocks(region, pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -329,41 +314,34 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
MaxChangedBlocksException {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
limit.THROW_MAX_CHANGES(region.getVolume());
|
||||
return super.replaceBlocks(region, filter, replacement);
|
||||
return extent.replaceBlocks(region, filter, replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int replaceBlocks(Region region, Set<BaseBlock> filter, Pattern pattern) throws MaxChangedBlocksException {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
limit.THROW_MAX_CHANGES(region.getVolume());
|
||||
return super.replaceBlocks(region, filter, pattern);
|
||||
return extent.replaceBlocks(region, filter, pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
limit.THROW_MAX_CHANGES(region.getVolume());
|
||||
return super.replaceBlocks(region, mask, pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int center(Region region, Pattern pattern) throws MaxChangedBlocksException {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
limit.THROW_MAX_CHANGES(region.getVolume());
|
||||
return super.center(region, pattern);
|
||||
return extent.replaceBlocks(region, mask, pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBlocks(Set<BlockVector3> vset, Pattern pattern) {
|
||||
limit.THROW_MAX_CHANGES(vset.size());
|
||||
return super.setBlocks(vset, pattern);
|
||||
return extent.setBlocks(vset, pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Filter> T apply(Region region, T filter, boolean full) {
|
||||
limit.THROW_MAX_CHECKS(region.getVolume());
|
||||
limit.THROW_MAX_CHANGES(region.getVolume());
|
||||
return super.apply(region, filter, full);
|
||||
return extent.apply(region, filter, full);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -373,12 +351,12 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
size = ((Collection<BlockVector3>) positions).size();
|
||||
} else if (positions instanceof Region) {
|
||||
BlockVector3 dim = ((Region) positions).getDimensions();
|
||||
size = dim.getX() * dim.getY() * dim.getZ();
|
||||
size = dim.x() * dim.y() * dim.z();
|
||||
} else if (positions instanceof Extent) {
|
||||
BlockVector3 min = ((Extent) positions).getMinimumPoint();
|
||||
BlockVector3 max = ((Extent) positions).getMinimumPoint();
|
||||
BlockVector3 dim = max.subtract(min).add(BlockVector3.ONE);
|
||||
size = dim.getX() * dim.getY() * dim.getZ();
|
||||
size = dim.x() * dim.y() * dim.z();
|
||||
} else {
|
||||
ExtentFilterBlock block = new ExtentFilterBlock(this);
|
||||
for (BlockVector3 pos : positions) {
|
||||
@ -393,14 +371,14 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
}
|
||||
limit.THROW_MAX_CHECKS(size);
|
||||
limit.THROW_MAX_CHANGES(size);
|
||||
return super.apply(positions, filter);
|
||||
return extent.apply(positions, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(BlockVector3 position) {
|
||||
limit.THROW_MAX_CHECKS();
|
||||
try {
|
||||
return super.getBlock(position);
|
||||
return extent.getBlock(position);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return BlockTypes.AIR.getDefaultState();
|
||||
@ -411,7 +389,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public BlockState getBlock(int x, int y, int z) {
|
||||
limit.THROW_MAX_CHECKS();
|
||||
try {
|
||||
return super.getBlock(x, y, z);
|
||||
return extent.getBlock(x, y, z);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return BlockTypes.AIR.getDefaultState();
|
||||
@ -422,7 +400,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public BaseBlock getFullBlock(BlockVector3 position) {
|
||||
limit.THROW_MAX_CHECKS();
|
||||
try {
|
||||
return super.getFullBlock(position);
|
||||
return extent.getFullBlock(position);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return BlockTypes.AIR.getDefaultState().toBaseBlock();
|
||||
@ -433,7 +411,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public BaseBlock getFullBlock(int x, int y, int z) {
|
||||
limit.THROW_MAX_CHECKS();
|
||||
try {
|
||||
return super.getFullBlock(x, y, z);
|
||||
return extent.getFullBlock(x, y, z);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return BlockTypes.AIR.getDefaultState().toBaseBlock();
|
||||
@ -444,7 +422,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
limit.THROW_MAX_CHECKS();
|
||||
try {
|
||||
return super.getBiome(position);
|
||||
return extent.getBiome(position);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return BiomeTypes.FOREST;
|
||||
@ -455,7 +433,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public BiomeType getBiomeType(int x, int y, int z) {
|
||||
limit.THROW_MAX_CHECKS();
|
||||
try {
|
||||
return super.getBiomeType(x, y, z);
|
||||
return extent.getBiomeType(x, y, z);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return BiomeTypes.FOREST;
|
||||
@ -470,7 +448,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
limit.THROW_MAX_BLOCKSTATES();
|
||||
}
|
||||
try {
|
||||
return super.setBlock(position, block);
|
||||
return extent.setBlock(position, block);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return false;
|
||||
@ -484,7 +462,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
limit.THROW_MAX_BLOCKSTATES();
|
||||
}
|
||||
try {
|
||||
return super.setBlock(x, y, z, block);
|
||||
return extent.setBlock(x, y, z, block);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return false;
|
||||
@ -494,9 +472,9 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
@Override
|
||||
public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException {
|
||||
limit.THROW_MAX_CHANGES();
|
||||
limit.MAX_BLOCKSTATES();
|
||||
limit.THROW_MAX_BLOCKSTATES();
|
||||
try {
|
||||
return super.setTile(x, y, z, tile);
|
||||
return extent.setTile(x, y, z, tile);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return false;
|
||||
@ -507,7 +485,7 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
limit.THROW_MAX_CHANGES();
|
||||
try {
|
||||
return super.setBiome(position, biome);
|
||||
return extent.setBiome(position, biome);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return false;
|
||||
@ -518,11 +496,41 @@ public class LimitExtent extends AbstractDelegateExtent {
|
||||
public boolean setBiome(int x, int y, int z, BiomeType biome) {
|
||||
limit.THROW_MAX_CHANGES();
|
||||
try {
|
||||
return super.setBiome(x, y, z, biome);
|
||||
return extent.setBiome(x, y, z, biome);
|
||||
} catch (FaweException e) {
|
||||
handleException(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setProcessing(boolean processing) {
|
||||
this.processing = processing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
|
||||
if (!processing) {
|
||||
return set;
|
||||
}
|
||||
int tiles = set.tiles().size();
|
||||
int ents = set.entities().size() + set.getEntityRemoves().size();
|
||||
limit.THROW_MAX_CHANGES(tiles + ents);
|
||||
limit.THROW_MAX_BLOCKSTATES(tiles);
|
||||
limit.THROW_MAX_ENTITIES(ents);
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Extent construct(final Extent child) {
|
||||
if (extent != child) {
|
||||
new ExtentTraverser<Extent>(this).setNext(child);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessorScope getScope() {
|
||||
return ProcessorScope.READING_SET_BLOCKS;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -38,9 +38,9 @@ public class PositionTransformExtent extends ResettableExtent {
|
||||
if (min == null) {
|
||||
min = pos;
|
||||
}
|
||||
mutable.mutX(pos.getX() - min.getX());
|
||||
mutable.mutY(pos.getY() - min.getY());
|
||||
mutable.mutZ(pos.getZ() - min.getZ());
|
||||
mutable.mutX(pos.x() - min.x());
|
||||
mutable.mutY(pos.y() - min.y());
|
||||
mutable.mutZ(pos.z() - min.z());
|
||||
MutableVector3 tmp = new MutableVector3(transform.apply(mutable.toVector3()));
|
||||
return min.add(tmp.roundHalfUp().toBlockPoint());
|
||||
}
|
||||
@ -49,9 +49,9 @@ public class PositionTransformExtent extends ResettableExtent {
|
||||
if (min == null) {
|
||||
min = BlockVector3.at(x, y, z);
|
||||
}
|
||||
mutable.mutX(x - min.getX());
|
||||
mutable.mutY(y - min.getY());
|
||||
mutable.mutZ(z - min.getZ());
|
||||
mutable.mutX(x - min.x());
|
||||
mutable.mutY(y - min.y());
|
||||
mutable.mutZ(z - min.z());
|
||||
MutableVector3 tmp = new MutableVector3(transform.apply(mutable.toVector3()));
|
||||
return min.add(tmp.roundHalfUp().toBlockPoint());
|
||||
}
|
||||
@ -73,10 +73,10 @@ public class PositionTransformExtent extends ResettableExtent {
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
mutable.mutX(position.getBlockX());
|
||||
mutable.mutZ(position.getBlockZ());
|
||||
mutable.mutY(position.getBlockY());
|
||||
return super.getBiome(getPos(mutable.getX(), mutable.getY(), mutable.getZ()));
|
||||
mutable.mutX(position.x());
|
||||
mutable.mutZ(position.z());
|
||||
mutable.mutY(position.y());
|
||||
return super.getBiome(getPos(mutable.x(), mutable.y(), mutable.z()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -92,10 +92,10 @@ public class PositionTransformExtent extends ResettableExtent {
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||
mutable.mutX(position.getBlockX());
|
||||
mutable.mutZ(position.getBlockZ());
|
||||
mutable.mutY(position.getBlockY());
|
||||
return super.setBiome(getPos(mutable.getX(), mutable.getY(), mutable.getZ()), biome);
|
||||
mutable.mutX(position.x());
|
||||
mutable.mutZ(position.z());
|
||||
mutable.mutY(position.y());
|
||||
return super.setBiome(getPos(mutable.x(), mutable.y(), mutable.z()), biome);
|
||||
}
|
||||
|
||||
public void setTransform(Transform transform) {
|
||||
|
||||
@ -80,12 +80,12 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block)
|
||||
throws WorldEditException {
|
||||
return setBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ(), block);
|
||||
return setBlock(location.x(), location.y(), location.z(), block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(BlockVector3 location) {
|
||||
return getBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
return getBlock(location.x(), location.y(), location.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -41,8 +41,8 @@ public class SourceMaskExtent extends TemporalExtent {
|
||||
|
||||
@Override
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 location, T block) throws WorldEditException {
|
||||
set(location.getBlockX(), location.getBlockY(), location.getBlockZ(), block);
|
||||
return mask.test(location) && super.setBlock(location.getX(), location.getY(), location.getZ(), block);
|
||||
set(location.x(), location.y(), location.z(), block);
|
||||
return mask.test(location) && super.setBlock(location.x(), location.y(), location.z(), block);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -2,14 +2,12 @@ package com.fastasyncworldedit.core.extent;
|
||||
|
||||
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
||||
import com.fastasyncworldedit.core.math.BlockVector3ChunkMap;
|
||||
import com.fastasyncworldedit.core.nbt.FaweCompoundTag;
|
||||
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.fastasyncworldedit.core.util.ExtentTraverser;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
@ -20,18 +18,17 @@ import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.NbtValued;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||
import org.enginehub.linbus.tree.LinTag;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProcessor {
|
||||
@ -77,79 +74,82 @@ public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProc
|
||||
if (!(block instanceof BaseBlock localBlock)) {
|
||||
return block;
|
||||
}
|
||||
if (!localBlock.hasNbtData()) {
|
||||
final LinCompoundTag nbt = localBlock.getNbt();
|
||||
if (nbt == null) {
|
||||
return block;
|
||||
}
|
||||
CompoundTag nbt = localBlock.getNbtData();
|
||||
Map<String, Tag> value = new HashMap<>(nbt.getValue());
|
||||
LinCompoundTag.Builder nbtBuilder = nbt.toBuilder();
|
||||
for (String key : strip) {
|
||||
value.remove(key);
|
||||
nbtBuilder.remove(key);
|
||||
}
|
||||
return (B) localBlock.toBaseBlock(new CompoundTag(value));
|
||||
return (B) localBlock.toBaseBlock(nbtBuilder.build());
|
||||
}
|
||||
|
||||
public <T extends NbtValued> T stripEntityNBT(T entity) {
|
||||
if (!entity.hasNbtData()) {
|
||||
LinCompoundTag nbt = entity.getNbt();
|
||||
if (nbt == null) {
|
||||
return entity;
|
||||
}
|
||||
CompoundTag nbt = entity.getNbtData();
|
||||
Map<String, Tag> value = new HashMap<>(nbt.getValue());
|
||||
LinCompoundTag.Builder nbtBuilder = nbt.toBuilder();
|
||||
for (String key : strip) {
|
||||
value.remove(key);
|
||||
nbtBuilder.remove(key);
|
||||
}
|
||||
entity.setNbtData(new CompoundTag(value));
|
||||
entity.setNbt(nbtBuilder.build());
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) {
|
||||
Map<BlockVector3, CompoundTag> tiles = set.getTiles();
|
||||
Set<CompoundTag> entities = set.getEntities();
|
||||
Map<BlockVector3, FaweCompoundTag> tiles = set.tiles();
|
||||
Collection<FaweCompoundTag> entities = set.entities();
|
||||
if (tiles.isEmpty() && entities.isEmpty()) {
|
||||
return set;
|
||||
}
|
||||
boolean isBv3ChunkMap = tiles instanceof BlockVector3ChunkMap;
|
||||
for (final Map.Entry<BlockVector3, CompoundTag> entry : tiles.entrySet()) {
|
||||
ImmutableMap.Builder<String, Tag> map = ImmutableMap.builder();
|
||||
final AtomicBoolean isStripped = new AtomicBoolean(false);
|
||||
entry.getValue().getValue().forEach((k, v) -> {
|
||||
if (strip.contains(k.toLowerCase())) {
|
||||
isStripped.set(true);
|
||||
} else {
|
||||
map.put(k, v);
|
||||
}
|
||||
});
|
||||
if (isStripped.get()) {
|
||||
for (final var entry : tiles.entrySet()) {
|
||||
FaweCompoundTag original = entry.getValue();
|
||||
FaweCompoundTag result = stripNbt(original);
|
||||
if (original != result) {
|
||||
if (isBv3ChunkMap) {
|
||||
// Replace existing value with stripped value
|
||||
tiles.put(entry.getKey(), new CompoundTag(map.build()));
|
||||
tiles.put(entry.getKey(), result);
|
||||
} else {
|
||||
entry.setValue(new CompoundTag(map.build()));
|
||||
entry.setValue(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
Set<CompoundTag> stripped = new HashSet<>();
|
||||
Iterator<CompoundTag> iterator = entities.iterator();
|
||||
Set<FaweCompoundTag> stripped = new HashSet<>();
|
||||
Iterator<FaweCompoundTag> iterator = entities.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
CompoundTag entity = iterator.next();
|
||||
ImmutableMap.Builder<String, Tag> map = ImmutableMap.builder();
|
||||
final AtomicBoolean isStripped = new AtomicBoolean(false);
|
||||
entity.getValue().forEach((k, v) -> {
|
||||
if (strip.contains(k.toUpperCase(Locale.ROOT))) {
|
||||
isStripped.set(true);
|
||||
} else {
|
||||
map.put(k, v);
|
||||
}
|
||||
});
|
||||
if (isStripped.get()) {
|
||||
FaweCompoundTag original = iterator.next();
|
||||
FaweCompoundTag result = stripNbt(original);
|
||||
if (original != result) {
|
||||
iterator.remove();
|
||||
stripped.add(new CompoundTag(map.build()));
|
||||
stripped.add(result);
|
||||
}
|
||||
}
|
||||
set.getEntities().addAll(stripped);
|
||||
// this relies on entities.addAll(...) not throwing an exception if empty+unmodifiable (=> stripped is empty too)
|
||||
entities.addAll(stripped);
|
||||
return set;
|
||||
}
|
||||
|
||||
private FaweCompoundTag stripNbt(
|
||||
FaweCompoundTag compoundTag
|
||||
) {
|
||||
LinCompoundTag.Builder builder = LinCompoundTag.builder();
|
||||
boolean stripped = false;
|
||||
for (var entry : compoundTag.linTag().value().entrySet()) {
|
||||
String k = entry.getKey();
|
||||
LinTag<?> v = entry.getValue();
|
||||
if (strip.contains(k.toLowerCase(Locale.ROOT))) {
|
||||
stripped = true;
|
||||
} else {
|
||||
builder.put(k, v);
|
||||
}
|
||||
}
|
||||
return stripped ? FaweCompoundTag.of(builder.build()) : compoundTag;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Extent construct(final Extent child) {
|
||||
|
||||
@ -44,7 +44,7 @@ public class TemporalExtent extends PassthroughExtent {
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(BlockVector3 position) {
|
||||
if (position.getX() == x && position.getY() == y && position.getZ() == z) {
|
||||
if (position.x() == x && position.y() == y && position.z() == z) {
|
||||
return block.toImmutableState();
|
||||
}
|
||||
return super.getBlock(position);
|
||||
@ -60,7 +60,7 @@ public class TemporalExtent extends PassthroughExtent {
|
||||
|
||||
@Override
|
||||
public BaseBlock getFullBlock(BlockVector3 position) {
|
||||
if (position.getX() == x && position.getY() == y && position.getZ() == z) {
|
||||
if (position.x() == x && position.y() == y && position.z() == z) {
|
||||
if (block instanceof BaseBlock) {
|
||||
return (BaseBlock) block;
|
||||
} else {
|
||||
@ -72,7 +72,7 @@ public class TemporalExtent extends PassthroughExtent {
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector3 position) {
|
||||
if (position.getX() == bx && position.getZ() == bz) {
|
||||
if (position.x() == bx && position.z() == bz) {
|
||||
return biome;
|
||||
}
|
||||
return super.getBiome(position);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user