2023-09-27 15:25:07 -05:00
36 changed files with 387 additions and 319 deletions

View File

@ -400,6 +400,7 @@ public class Settings extends Config {
"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]\"",

View File

@ -4,19 +4,19 @@ import sun.misc.Unsafe;
import javax.annotation.Nonnull;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Comparator;
/**
* This is an internal class not meant to be used outside the FAWE internals.
*/
public class ReflectionUtils {
private static final VarHandle REFERENCE_ARRAY_HANDLE = MethodHandles.arrayElementVarHandle(Object[].class);
private static Unsafe UNSAFE;
static {
@ -33,6 +33,21 @@ public class ReflectionUtils {
return t.isInstance(o) ? t.cast(o) : null;
}
/**
* Performs CAS on the array element at the given index.
*
* @param array the array in which to compare and set the value
* @param expectedValue the value expected to be at the index
* @param newValue the new value to be set at the index if the expected value matches
* @param index the index at which to compare and set the value
* @param <T> the type of elements in the array
* @return true if the value at the index was successfully updated to the new value, false otherwise
* @see VarHandle#compareAndSet(Object...)
*/
public static <T> boolean compareAndSet(T[] array, T expectedValue, T newValue, int index) {
return REFERENCE_ARRAY_HANDLE.compareAndSet(array, index, expectedValue, newValue);
}
public static void setAccessibleNonFinal(Field field) {
// let's make the field accessible
field.setAccessible(true);

View File

@ -98,6 +98,8 @@ public class YAMLProcessor extends YAMLNode {
LoaderOptions loaderOptions = new LoaderOptions();
try {
int yamlAliasLimit = Integer.getInteger("worldedit.yaml.aliasLimit", 50);
loaderOptions.setMaxAliasesForCollections(yamlAliasLimit);
// 64 MB default
int yamlCodePointLimit = Integer.getInteger("worldedit.yaml.codePointLimit", 64 * 1024 * 1024);
loaderOptions.setCodePointLimit(yamlCodePointLimit);
@ -105,7 +107,7 @@ public class YAMLProcessor extends YAMLNode {
// pre-1.32 snakeyaml
}
yaml = new Yaml(new SafeConstructor(new LoaderOptions()), representer, dumperOptions, loaderOptions);
yaml = new Yaml(new SafeConstructor(loaderOptions), representer, dumperOptions, loaderOptions);
this.file = file;
}

View File

@ -55,4 +55,9 @@ public abstract class AbstractPlatform implements Platform {
return null;
}
@Override
public long getTickCount() {
return System.nanoTime() / 50_000_000;
}
}

View File

@ -216,6 +216,14 @@ public interface Platform extends Keyed {
*/
Set<SideEffect> getSupportedSideEffects();
/**
* Get the number of ticks since the server started.
* On some platforms this value may be an approximation based on the JVM run time.
*
* @return The number of ticks since the server started.
*/
long getTickCount();
//FAWE start
/**

View File

@ -0,0 +1,69 @@
/*
* 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.sk89q.worldedit.internal.event;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.util.Identifiable;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
public class InteractionDebouncer {
private final Platform platform;
private final Map<UUID, Interaction> lastInteractions = new HashMap<>();
public InteractionDebouncer(Platform platform) {
this.platform = platform;
}
public void clearInteraction(Identifiable player) {
lastInteractions.remove(player.getUniqueId());
}
public void setLastInteraction(Identifiable player, boolean result) {
lastInteractions.put(player.getUniqueId(), new Interaction(platform.getTickCount(), result));
}
public Optional<Boolean> getDuplicateInteractionResult(Identifiable player) {
Interaction last = lastInteractions.get(player.getUniqueId());
if (last == null) {
return Optional.empty();
}
long now = platform.getTickCount();
if (now - last.tick <= 1) {
return Optional.of(last.result);
}
return Optional.empty();
}
private static class Interaction {
public final long tick;
public final boolean result;
public Interaction(long tick, boolean result) {
this.tick = tick;
this.result = result;
}
}
}