Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-11-19 17:30:08 +01:00
Merge branch 'main' into feat/feature-placement
Dieser Commit ist enthalten in:
Commit
e89e2664bb
3
.github/renovate.json
vendored
3
.github/renovate.json
vendored
@ -33,9 +33,6 @@
|
|||||||
"Renovate"
|
"Renovate"
|
||||||
],
|
],
|
||||||
"rebaseWhen" : "conflicted",
|
"rebaseWhen" : "conflicted",
|
||||||
"schedule" : [
|
|
||||||
"on the first day of the month"
|
|
||||||
],
|
|
||||||
"customManagers" : [
|
"customManagers" : [
|
||||||
{
|
{
|
||||||
"customType" : "regex",
|
"customType" : "regex",
|
||||||
|
2
.github/workflows/build-pr.yml
vendored
2
.github/workflows/build-pr.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
|||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Validate Gradle Wrapper
|
- name: Validate Gradle Wrapper
|
||||||
uses: gradle/wrapper-validation-action@v1
|
uses: gradle/wrapper-validation-action@v2
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
|
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
|||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Validate Gradle Wrapper
|
- name: Validate Gradle Wrapper
|
||||||
uses: gradle/wrapper-validation-action@v1
|
uses: gradle/wrapper-validation-action@v2
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
|
2
.github/workflows/release-drafter.yml
vendored
2
.github/workflows/release-drafter.yml
vendored
@ -12,6 +12,6 @@ jobs:
|
|||||||
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
|
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: release-drafter/release-drafter@v5
|
- uses: release-drafter/release-drafter@v6
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
2
.github/workflows/upload-release-assets.yml
vendored
2
.github/workflows/upload-release-assets.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Validate Gradle Wrapper
|
- name: Validate Gradle Wrapper
|
||||||
uses: gradle/wrapper-validation-action@v1
|
uses: gradle/wrapper-validation-action@v2
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
|
@ -7,7 +7,7 @@ import xyz.jpenilla.runpaper.task.RunServer
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("io.github.gradle-nexus.publish-plugin") version "1.3.0"
|
id("io.github.gradle-nexus.publish-plugin") version "1.3.0"
|
||||||
id("xyz.jpenilla.run-paper") version "2.2.2"
|
id("xyz.jpenilla.run-paper") version "2.2.3"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!File("$rootDir/.git").exists()) {
|
if (!File("$rootDir/.git").exists()) {
|
||||||
@ -34,7 +34,7 @@ logger.lifecycle("""
|
|||||||
*******************************************
|
*******************************************
|
||||||
""")
|
""")
|
||||||
|
|
||||||
var rootVersion by extra("2.8.5")
|
var rootVersion by extra("2.9.2")
|
||||||
var snapshot by extra("SNAPSHOT")
|
var snapshot by extra("SNAPSHOT")
|
||||||
var revision: String by extra("")
|
var revision: String by extra("")
|
||||||
var buildNumber by extra("")
|
var buildNumber by extra("")
|
||||||
|
@ -22,7 +22,7 @@ val properties = Properties().also { props ->
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(gradleApi())
|
implementation(gradleApi())
|
||||||
implementation("org.ajoberstar.grgit:grgit-gradle:5.2.1")
|
implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2")
|
||||||
implementation("com.github.johnrengelman:shadow:8.1.1")
|
implementation("com.github.johnrengelman:shadow:8.1.1")
|
||||||
implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.5.11")
|
implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.5.11")
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,14 @@ mapmanager = "1.8.0-SNAPSHOT"
|
|||||||
griefprevention = "17.0.0"
|
griefprevention = "17.0.0"
|
||||||
griefdefender = "2.1.0-SNAPSHOT"
|
griefdefender = "2.1.0-SNAPSHOT"
|
||||||
residence = "4.5._13.1"
|
residence = "4.5._13.1"
|
||||||
towny = "0.100.1.5"
|
towny = "0.100.1.20"
|
||||||
plotsquared = "7.3.1"
|
plotsquared = "7.3.6"
|
||||||
|
|
||||||
# Third party
|
# Third party
|
||||||
bstats = "3.0.2"
|
bstats = "3.0.2"
|
||||||
sparsebitset = "1.3"
|
sparsebitset = "1.3"
|
||||||
parallelgzip = "1.0.5"
|
parallelgzip = "1.0.5"
|
||||||
adventure = "4.15.0"
|
adventure = "4.16.0"
|
||||||
adventure-bukkit = "4.3.2"
|
adventure-bukkit = "4.3.2"
|
||||||
checkerqual = "3.42.0"
|
checkerqual = "3.42.0"
|
||||||
truezip = "6.8.4"
|
truezip = "6.8.4"
|
||||||
@ -43,10 +43,10 @@ serverlib = "2.3.4"
|
|||||||
## Internal
|
## Internal
|
||||||
text-adapter = "3.0.6"
|
text-adapter = "3.0.6"
|
||||||
text = "3.0.4"
|
text = "3.0.4"
|
||||||
piston = "0.5.7"
|
piston = "0.5.8"
|
||||||
|
|
||||||
# Tests
|
# Tests
|
||||||
mockito = "5.9.0"
|
mockito = "5.11.0"
|
||||||
|
|
||||||
# Gradle plugins
|
# Gradle plugins
|
||||||
pluginyml = "0.6.0"
|
pluginyml = "0.6.0"
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
20
gradlew.bat
vendored
20
gradlew.bat
vendored
@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
|
|||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ tasks.named<ShadowJar>("shadowJar") {
|
|||||||
include(dependency("org.lz4:lz4-java:1.8.0"))
|
include(dependency("org.lz4:lz4-java:1.8.0"))
|
||||||
}
|
}
|
||||||
relocate("net.kyori", "com.fastasyncworldedit.core.adventure") {
|
relocate("net.kyori", "com.fastasyncworldedit.core.adventure") {
|
||||||
include(dependency("net.kyori:adventure-nbt:4.15.0"))
|
include(dependency("net.kyori:adventure-nbt:4.16.0"))
|
||||||
}
|
}
|
||||||
relocate("com.zaxxer", "com.fastasyncworldedit.core.math") {
|
relocate("com.zaxxer", "com.fastasyncworldedit.core.math") {
|
||||||
include(dependency("com.zaxxer:SparseBitSet:1.3"))
|
include(dependency("com.zaxxer:SparseBitSet:1.3"))
|
||||||
|
@ -163,13 +163,22 @@ public class WorldGuardFeature extends BukkitMaskManager implements Listener {
|
|||||||
final Location location = player.getLocation();
|
final Location location = player.getLocation();
|
||||||
final Set<ProtectedRegion> regions = this.getRegions(localplayer, location, isWhitelist);
|
final Set<ProtectedRegion> regions = this.getRegions(localplayer, location, isWhitelist);
|
||||||
if (!regions.isEmpty()) {
|
if (!regions.isEmpty()) {
|
||||||
|
RegionManager manager = WorldGuard
|
||||||
|
.getInstance()
|
||||||
|
.getPlatform()
|
||||||
|
.getRegionContainer()
|
||||||
|
.get(BukkitAdapter.adapt(location.getWorld()));
|
||||||
|
if (manager == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Set<Region> result = new HashSet<>();
|
Set<Region> result = new HashSet<>();
|
||||||
for (ProtectedRegion myRegion : regions) {
|
for (ProtectedRegion myRegion : regions) {
|
||||||
if (myRegion.getId().equals("__global__")) {
|
if (myRegion.getId().equals("__global__")) {
|
||||||
return new FaweMask(RegionWrapper.GLOBAL()) {
|
return new FaweMask(RegionWrapper.GLOBAL()) {
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid(com.sk89q.worldedit.entity.Player player, MaskType type) {
|
public boolean isValid(com.sk89q.worldedit.entity.Player player, MaskType type) {
|
||||||
return isAllowed(worldguard.wrapPlayer(BukkitAdapter.adapt(player)), myRegion);
|
return manager.hasRegion(myRegion.getId())
|
||||||
|
&& isAllowed(worldguard.wrapPlayer(BukkitAdapter.adapt(player)), myRegion);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
@ -185,7 +194,7 @@ public class WorldGuardFeature extends BukkitMaskManager implements Listener {
|
|||||||
public boolean isValid(com.sk89q.worldedit.entity.Player player, MaskType type) {
|
public boolean isValid(com.sk89q.worldedit.entity.Player player, MaskType type) {
|
||||||
final LocalPlayer localplayer = worldguard.wrapPlayer(BukkitAdapter.adapt(player));
|
final LocalPlayer localplayer = worldguard.wrapPlayer(BukkitAdapter.adapt(player));
|
||||||
for (ProtectedRegion myRegion : regions) {
|
for (ProtectedRegion myRegion : regions) {
|
||||||
if (!isAllowed(localplayer, myRegion)) {
|
if (!manager.hasRegion(myRegion.getId()) || !isAllowed(localplayer, myRegion)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -626,7 +626,7 @@ public enum FaweCache implements Trimable {
|
|||||||
* Create a new blocking executor with specified name and FaweCache logger
|
* Create a new blocking executor with specified name and FaweCache logger
|
||||||
*
|
*
|
||||||
* @return new blocking executor
|
* @return new blocking executor
|
||||||
* @since TODO
|
* @since 2.9.0
|
||||||
*/
|
*/
|
||||||
public ThreadPoolExecutor newBlockingExecutor(String name) {
|
public ThreadPoolExecutor newBlockingExecutor(String name) {
|
||||||
return newBlockingExecutor(name, LOGGER);
|
return newBlockingExecutor(name, LOGGER);
|
||||||
@ -636,7 +636,7 @@ public enum FaweCache implements Trimable {
|
|||||||
* Create a new blocking executor with specified name and logger
|
* Create a new blocking executor with specified name and logger
|
||||||
*
|
*
|
||||||
* @return new blocking executor
|
* @return new blocking executor
|
||||||
* @since TODO
|
* @since 2.9.0
|
||||||
*/
|
*/
|
||||||
public ThreadPoolExecutor newBlockingExecutor(String name, Logger logger) {
|
public ThreadPoolExecutor newBlockingExecutor(String name, Logger logger) {
|
||||||
int nThreads = Settings.settings().QUEUE.PARALLEL_THREADS;
|
int nThreads = Settings.settings().QUEUE.PARALLEL_THREADS;
|
||||||
|
@ -159,18 +159,23 @@ public class RollbackDatabase extends AsyncNotifyQueue {
|
|||||||
Future<Integer> future = call(() -> {
|
Future<Integer> future = call(() -> {
|
||||||
try {
|
try {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
String stmtStr;
|
String stmtStr = """
|
||||||
|
SELECT * FROM `%sedits`
|
||||||
|
WHERE `time` > ?
|
||||||
|
AND `x2` >= ?
|
||||||
|
AND `x1` <= ?
|
||||||
|
AND `z2` >= ?
|
||||||
|
AND `z1` <= ?
|
||||||
|
AND `y2` >= ?
|
||||||
|
AND `y1` <= ?
|
||||||
|
""";
|
||||||
|
if (uuid != null) {
|
||||||
|
stmtStr += "\n AND `player`= ?";
|
||||||
|
}
|
||||||
if (ascending) {
|
if (ascending) {
|
||||||
if (uuid == null) {
|
stmtStr += "\n ORDER BY `time` ASC, `id` ASC";
|
||||||
stmtStr = "SELECT * FROM`%sedits` WHERE `time`>? AND `x2`>=? AND `x1`<=? AND `z2`>=? AND `z1`<=? AND " +
|
|
||||||
"`y2`>=? AND `y1`<=? ORDER BY `time` , `id`";
|
|
||||||
} else {
|
|
||||||
stmtStr = "SELECT * FROM`%sedits` WHERE `time`>? AND `x2`>=? AND `x1`<=? AND `z2`>=? AND `z1`<=? AND " +
|
|
||||||
"`y2`>=? AND `y1`<=? AND `player`=? ORDER BY `time` ASC, `id` ASC";
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
stmtStr = "SELECT * FROM`%sedits` WHERE `time`>? AND `x2`>=? AND `x1`<=? AND `z2`>=? AND `z1`<=? AND " +
|
stmtStr += "\n ORDER BY `time` DESC, `id` DESC";
|
||||||
"`y2`>=? AND `y1`<=? AND `player`=? ORDER BY `time` DESC, `id` DESC";
|
|
||||||
}
|
}
|
||||||
try (PreparedStatement stmt = connection.prepareStatement(stmtStr.formatted(this.prefix))) {
|
try (PreparedStatement stmt = connection.prepareStatement(stmtStr.formatted(this.prefix))) {
|
||||||
stmt.setInt(1, (int) (minTime / 1000));
|
stmt.setInt(1, (int) (minTime / 1000));
|
||||||
|
@ -53,7 +53,7 @@ public abstract class RichParser<E> extends InputParser<E> implements AliasedPar
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private Function<String, Stream<? extends String>> extractArguments(String input) {
|
private Function<String, Stream<? extends String>> extractArguments(String input, ParserContext context) {
|
||||||
return prefix -> {
|
return prefix -> {
|
||||||
if (input.length() > prefix.length() && input.startsWith(prefix + "[")) {
|
if (input.length() > prefix.length() && input.startsWith(prefix + "[")) {
|
||||||
// input already contains argument(s) -> extract them
|
// 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;
|
String previous = prefix + builder;
|
||||||
// read the suggestions for the last argument
|
// 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);
|
.map(suggestion -> previous + "[" + suggestion);
|
||||||
} else {
|
} else {
|
||||||
return Stream.of(prefix);
|
return Stream.of(prefix);
|
||||||
@ -95,7 +95,7 @@ public abstract class RichParser<E> extends InputParser<E> implements AliasedPar
|
|||||||
public Stream<String> getSuggestions(String input) {
|
public Stream<String> getSuggestions(String input) {
|
||||||
return Arrays.stream(this.prefixes)
|
return Arrays.stream(this.prefixes)
|
||||||
.filter(validPrefix(input))
|
.filter(validPrefix(input))
|
||||||
.flatMap(extractArguments(input));
|
.flatMap(extractArguments(input, new ParserContext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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 argumentInput the already provided input for the argument at the given index.
|
||||||
* @param index the index of the argument to get suggestions for.
|
* @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.
|
* @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.
|
* Parses the already split arguments.
|
||||||
|
@ -97,11 +97,11 @@ public class RichMaskParser extends FaweParser<Mask> {
|
|||||||
)),
|
)),
|
||||||
() -> {
|
() -> {
|
||||||
if (full.length() == 1) {
|
if (full.length() == 1) {
|
||||||
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions(""));
|
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions("", context));
|
||||||
}
|
}
|
||||||
return new ArrayList<>(worldEdit
|
return new ArrayList<>(worldEdit
|
||||||
.getMaskFactory()
|
.getMaskFactory()
|
||||||
.getSuggestions(command.toLowerCase(Locale.ROOT)));
|
.getSuggestions(command.toLowerCase(Locale.ROOT), context));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -164,11 +164,11 @@ public class RichMaskParser extends FaweParser<Mask> {
|
|||||||
)),
|
)),
|
||||||
() -> {
|
() -> {
|
||||||
if (full.length() == 1) {
|
if (full.length() == 1) {
|
||||||
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions(""));
|
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions("", context));
|
||||||
}
|
}
|
||||||
return new ArrayList<>(worldEdit
|
return new ArrayList<>(worldEdit
|
||||||
.getMaskFactory()
|
.getMaskFactory()
|
||||||
.getSuggestions(command.toLowerCase(Locale.ROOT)));
|
.getSuggestions(command.toLowerCase(Locale.ROOT), context));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import com.fastasyncworldedit.core.queue.Filter;
|
|||||||
import com.fastasyncworldedit.core.queue.IQueueChunk;
|
import com.fastasyncworldedit.core.queue.IQueueChunk;
|
||||||
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
||||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||||
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.function.mask.BlockMask;
|
import com.sk89q.worldedit.function.mask.BlockMask;
|
||||||
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||||
@ -45,6 +46,7 @@ import java.util.stream.IntStream;
|
|||||||
public class ParallelQueueExtent extends PassthroughExtent {
|
public class ParallelQueueExtent extends PassthroughExtent {
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||||
|
private static final ThreadLocal<Extent> extents = new ThreadLocal<>();
|
||||||
|
|
||||||
private final World world;
|
private final World world;
|
||||||
private final QueueHandler handler;
|
private final QueueHandler handler;
|
||||||
@ -73,10 +75,36 @@ public class ParallelQueueExtent extends PassthroughExtent {
|
|||||||
this.fastmode = fastmode;
|
this.fastmode = fastmode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the extent currently associated with the calling thread.
|
||||||
|
*/
|
||||||
|
public static void clearCurrentExtent() {
|
||||||
|
extents.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the extent associated with the calling thread.
|
||||||
|
*/
|
||||||
|
public static void setCurrentExtent(Extent extent) {
|
||||||
|
extents.set(extent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enter(Extent extent) {
|
||||||
|
setCurrentExtent(extent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exit() {
|
||||||
|
clearCurrentExtent();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
public IQueueExtent<IQueueChunk> getExtent() {
|
public IQueueExtent<IQueueChunk> getExtent() {
|
||||||
return (IQueueExtent<IQueueChunk>) super.getExtent();
|
Extent extent = extents.get();
|
||||||
|
if (extent == null) {
|
||||||
|
extent = super.getExtent();
|
||||||
|
}
|
||||||
|
return (IQueueExtent<IQueueChunk>) extent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -103,9 +131,12 @@ public class ParallelQueueExtent extends PassthroughExtent {
|
|||||||
|
|
||||||
// Get a pool, to operate on the chunks in parallel
|
// Get a pool, to operate on the chunks in parallel
|
||||||
final int size = Math.min(chunks.size(), Settings.settings().QUEUE.PARALLEL_THREADS);
|
final int size = Math.min(chunks.size(), Settings.settings().QUEUE.PARALLEL_THREADS);
|
||||||
if (size <= 1 && chunksIter.hasNext()) {
|
if (size <= 1) {
|
||||||
BlockVector2 pos = chunksIter.next();
|
// if PQE is ever used with PARALLEL_THREADS = 1, or only one chunk is edited, just run sequentially
|
||||||
getExtent().apply(null, filter, region, pos.getX(), pos.getZ(), full);
|
while (chunksIter.hasNext()) {
|
||||||
|
BlockVector2 pos = chunksIter.next();
|
||||||
|
getExtent().apply(null, filter, region, pos.getX(), pos.getZ(), full);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
final ForkJoinTask[] tasks = IntStream.range(0, size).mapToObj(i -> handler.submit(() -> {
|
final ForkJoinTask[] tasks = IntStream.range(0, size).mapToObj(i -> handler.submit(() -> {
|
||||||
try {
|
try {
|
||||||
@ -114,6 +145,7 @@ public class ParallelQueueExtent extends PassthroughExtent {
|
|||||||
final SingleThreadQueueExtent queue = (SingleThreadQueueExtent) getNewQueue();
|
final SingleThreadQueueExtent queue = (SingleThreadQueueExtent) getNewQueue();
|
||||||
queue.setFastMode(fastmode);
|
queue.setFastMode(fastmode);
|
||||||
queue.setFaweExceptionArray(faweExceptionReasonsUsed);
|
queue.setFaweExceptionArray(faweExceptionReasonsUsed);
|
||||||
|
enter(queue);
|
||||||
synchronized (queue) {
|
synchronized (queue) {
|
||||||
try {
|
try {
|
||||||
ChunkFilterBlock block = null;
|
ChunkFilterBlock block = null;
|
||||||
@ -154,6 +186,8 @@ public class ParallelQueueExtent extends PassthroughExtent {
|
|||||||
exceptionCount++;
|
exceptionCount++;
|
||||||
LOGGER.warn(message);
|
LOGGER.warn(message);
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
exit();
|
||||||
}
|
}
|
||||||
})).toArray(ForkJoinTask[]::new);
|
})).toArray(ForkJoinTask[]::new);
|
||||||
// Join filters
|
// Join filters
|
||||||
|
@ -408,7 +408,7 @@ public abstract class QueueHandler implements Trimable, Runnable {
|
|||||||
* Sets the current thread's {@link IQueueExtent} instance in the queue pool to null.
|
* Sets the current thread's {@link IQueueExtent} instance in the queue pool to null.
|
||||||
*/
|
*/
|
||||||
public void unCache() {
|
public void unCache() {
|
||||||
queuePool.set(null);
|
queuePool.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IQueueExtent<IQueueChunk> pool() {
|
private IQueueExtent<IQueueChunk> pool() {
|
||||||
|
@ -9,7 +9,6 @@ import com.fastasyncworldedit.core.extent.processor.EmptyBatchProcessor;
|
|||||||
import com.fastasyncworldedit.core.extent.processor.ExtentBatchProcessorHolder;
|
import com.fastasyncworldedit.core.extent.processor.ExtentBatchProcessorHolder;
|
||||||
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
||||||
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
import com.fastasyncworldedit.core.internal.exception.FaweException;
|
||||||
import com.fastasyncworldedit.core.queue.IChunk;
|
|
||||||
import com.fastasyncworldedit.core.queue.IChunkCache;
|
import com.fastasyncworldedit.core.queue.IChunkCache;
|
||||||
import com.fastasyncworldedit.core.queue.IChunkGet;
|
import com.fastasyncworldedit.core.queue.IChunkGet;
|
||||||
import com.fastasyncworldedit.core.queue.IChunkSet;
|
import com.fastasyncworldedit.core.queue.IChunkSet;
|
||||||
@ -48,11 +47,9 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
|
|||||||
|
|
||||||
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||||
|
|
||||||
// Pool discarded chunks for reuse (can safely be cleared by another thread)
|
|
||||||
// private static final ConcurrentLinkedQueue<IChunk> CHUNK_POOL = new ConcurrentLinkedQueue<>();
|
|
||||||
// Chunks currently being queued / worked on
|
// Chunks currently being queued / worked on
|
||||||
private final Long2ObjectLinkedOpenHashMap<IQueueChunk> chunks = new Long2ObjectLinkedOpenHashMap<>();
|
private final Long2ObjectLinkedOpenHashMap<IQueueChunk<?>> chunks = new Long2ObjectLinkedOpenHashMap<>();
|
||||||
private final ConcurrentLinkedQueue<Future> submissions = new ConcurrentLinkedQueue<>();
|
private final ConcurrentLinkedQueue<Future<?>> submissions = new ConcurrentLinkedQueue<>();
|
||||||
private final ReentrantLock getChunkLock = new ReentrantLock();
|
private final ReentrantLock getChunkLock = new ReentrantLock();
|
||||||
private World world = null;
|
private World world = null;
|
||||||
private int minY = 0;
|
private int minY = 0;
|
||||||
@ -142,12 +139,10 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
|
|||||||
if (!this.initialized) {
|
if (!this.initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.chunks.isEmpty()) {
|
getChunkLock.lock();
|
||||||
getChunkLock.lock();
|
try {
|
||||||
for (IChunk chunk : this.chunks.values()) {
|
|
||||||
chunk.recycle();
|
|
||||||
}
|
|
||||||
this.chunks.clear();
|
this.chunks.clear();
|
||||||
|
} finally {
|
||||||
getChunkLock.unlock();
|
getChunkLock.unlock();
|
||||||
}
|
}
|
||||||
this.enabledQueue = true;
|
this.enabledQueue = true;
|
||||||
@ -234,7 +229,6 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (chunk.isEmpty()) {
|
if (chunk.isEmpty()) {
|
||||||
chunk.recycle();
|
|
||||||
Future result = Futures.immediateFuture(null);
|
Future result = Futures.immediateFuture(null);
|
||||||
return (V) result;
|
return (V) result;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package com.fastasyncworldedit.core.queue.implementation.chunk;
|
package com.fastasyncworldedit.core.queue.implementation.chunk;
|
||||||
|
|
||||||
import com.fastasyncworldedit.core.FaweCache;
|
|
||||||
import com.fastasyncworldedit.core.configuration.Settings;
|
|
||||||
import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock;
|
import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock;
|
||||||
import com.fastasyncworldedit.core.extent.processor.EmptyBatchProcessor;
|
import com.fastasyncworldedit.core.extent.processor.EmptyBatchProcessor;
|
||||||
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
|
import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType;
|
||||||
@ -11,36 +9,34 @@ import com.fastasyncworldedit.core.queue.IChunkGet;
|
|||||||
import com.fastasyncworldedit.core.queue.IChunkSet;
|
import com.fastasyncworldedit.core.queue.IChunkSet;
|
||||||
import com.fastasyncworldedit.core.queue.IQueueChunk;
|
import com.fastasyncworldedit.core.queue.IQueueChunk;
|
||||||
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
||||||
import com.fastasyncworldedit.core.queue.Pool;
|
import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent;
|
||||||
import com.fastasyncworldedit.core.util.MemUtil;
|
import com.fastasyncworldedit.core.util.MemUtil;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract {@link IChunk} class that implements basic get/set blocks.
|
* An abstract {@link IChunk} class that implements basic get/set blocks.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
||||||
|
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||||
private static final Pool<ChunkHolder> POOL = FaweCache.INSTANCE.registerPool(
|
|
||||||
ChunkHolder.class,
|
|
||||||
ChunkHolder::new,
|
|
||||||
Settings.settings().QUEUE.POOL
|
|
||||||
);
|
|
||||||
|
|
||||||
public static ChunkHolder newInstance() {
|
public static ChunkHolder newInstance() {
|
||||||
return POOL.poll();
|
return new ChunkHolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
private volatile IChunkGet chunkExisting; // The existing chunk (e.g. a clipboard, or the world, before changes)
|
private volatile IChunkGet chunkExisting; // The existing chunk (e.g. a clipboard, or the world, before changes)
|
||||||
@ -63,16 +59,12 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
|||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final AtomicBoolean recycleWarning = new AtomicBoolean(false);
|
||||||
@Override
|
@Override
|
||||||
public synchronized void recycle() {
|
public void recycle() {
|
||||||
delegate = NULL;
|
if (!recycleWarning.getAndSet(true)) {
|
||||||
if (chunkSet != null) {
|
LOGGER.warn("ChunkHolder should not be recycled.", new Exception());
|
||||||
chunkSet.recycle();
|
|
||||||
chunkSet = null;
|
|
||||||
}
|
}
|
||||||
chunkExisting = null;
|
|
||||||
extent = null;
|
|
||||||
POOL.offer(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long initAge() {
|
public long initAge() {
|
||||||
@ -1018,7 +1010,6 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
|||||||
// Do nothing
|
// Do nothing
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
recycle();
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1031,6 +1022,7 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
|||||||
IChunkGet get = getOrCreateGet();
|
IChunkGet get = getOrCreateGet();
|
||||||
try {
|
try {
|
||||||
get.lockCall();
|
get.lockCall();
|
||||||
|
trackExtent();
|
||||||
boolean postProcess = !(getExtent().getPostProcessor() instanceof EmptyBatchProcessor);
|
boolean postProcess = !(getExtent().getPostProcessor() instanceof EmptyBatchProcessor);
|
||||||
final int copyKey = get.setCreateCopy(postProcess);
|
final int copyKey = get.setCreateCopy(postProcess);
|
||||||
final IChunkSet iChunkSet = getExtent().processSet(this, get, set);
|
final IChunkSet iChunkSet = getExtent().processSet(this, get, set);
|
||||||
@ -1046,11 +1038,24 @@ public class ChunkHolder<T extends Future<T>> implements IQueueChunk<T> {
|
|||||||
return get.call(set, finalizer);
|
return get.call(set, finalizer);
|
||||||
} finally {
|
} finally {
|
||||||
get.unlockCall();
|
get.unlockCall();
|
||||||
|
untrackExtent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "call" can be called by QueueHandler#blockingExecutor. In such case, we still want the other thread
|
||||||
|
// to use this SingleThreadQueueExtent. Otherwise, many threads might end up locking on **one** STQE.
|
||||||
|
// This way, locking is spread across multiple STQEs, allowing for better performance
|
||||||
|
|
||||||
|
private void trackExtent() {
|
||||||
|
ParallelQueueExtent.setCurrentExtent(extent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void untrackExtent() {
|
||||||
|
ParallelQueueExtent.clearCurrentExtent();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the extent this chunk is in.
|
* Get the extent this chunk is in.
|
||||||
*/
|
*/
|
||||||
|
@ -33,7 +33,7 @@ public abstract class RandomCollection<T> {
|
|||||||
public static <T> RandomCollection<T> of(Map<T, Double> weights, SimpleRandom random) {
|
public static <T> RandomCollection<T> of(Map<T, Double> weights, SimpleRandom random) {
|
||||||
checkNotNull(random);
|
checkNotNull(random);
|
||||||
return FastRandomCollection.create(weights, random)
|
return FastRandomCollection.create(weights, random)
|
||||||
.orElse(new SimpleRandomCollection<>(weights, random));
|
.orElseGet(() -> new SimpleRandomCollection<>(weights, random));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRandom(SimpleRandom random) {
|
public void setRandom(SimpleRandom random) {
|
||||||
|
@ -32,6 +32,7 @@ import com.fastasyncworldedit.core.internal.io.FaweOutputStream;
|
|||||||
import com.fastasyncworldedit.core.limit.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.util.BrushCache;
|
import com.fastasyncworldedit.core.util.BrushCache;
|
||||||
import com.fastasyncworldedit.core.util.MainUtil;
|
import com.fastasyncworldedit.core.util.MainUtil;
|
||||||
|
import com.fastasyncworldedit.core.util.MaskTraverser;
|
||||||
import com.fastasyncworldedit.core.util.StringMan;
|
import com.fastasyncworldedit.core.util.StringMan;
|
||||||
import com.fastasyncworldedit.core.util.TaskManager;
|
import com.fastasyncworldedit.core.util.TaskManager;
|
||||||
import com.fastasyncworldedit.core.util.TextureHolder;
|
import com.fastasyncworldedit.core.util.TextureHolder;
|
||||||
@ -53,6 +54,7 @@ import com.sk89q.worldedit.command.tool.Tool;
|
|||||||
import com.sk89q.worldedit.entity.Player;
|
import com.sk89q.worldedit.entity.Player;
|
||||||
import com.sk89q.worldedit.extension.platform.Actor;
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
import com.sk89q.worldedit.extension.platform.Locatable;
|
import com.sk89q.worldedit.extension.platform.Locatable;
|
||||||
|
import com.sk89q.worldedit.extent.NullExtent;
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||||
@ -594,6 +596,9 @@ public class LocalSession implements TextureHolder {
|
|||||||
long size = MainUtil.getSize(item);
|
long size = MainUtil.getSize(item);
|
||||||
historySize -= size;
|
historySize -= size;
|
||||||
}
|
}
|
||||||
|
// free the mask from any remaining references to e.g. extents
|
||||||
|
// if used again
|
||||||
|
new MaskTraverser(mask).reset(NullExtent.INSTANCE);
|
||||||
} finally {
|
} finally {
|
||||||
historyWriteLock.unlock();
|
historyWriteLock.unlock();
|
||||||
}
|
}
|
||||||
|
@ -113,8 +113,7 @@ public class FactoryConverter<T> implements ArgumentConverter<T> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private ParserContext createContext(InjectedValueAccess context) {
|
||||||
public ConversionResult<T> convert(String argument, InjectedValueAccess context) {
|
|
||||||
Actor actor = context.injectedValue(Key.of(Actor.class))
|
Actor actor = context.injectedValue(Key.of(Actor.class))
|
||||||
.orElseThrow(() -> new IllegalStateException("No actor"));
|
.orElseThrow(() -> new IllegalStateException("No actor"));
|
||||||
LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor);
|
LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor);
|
||||||
@ -139,6 +138,13 @@ public class FactoryConverter<T> implements ArgumentConverter<T> {
|
|||||||
contextTweaker.accept(parserContext);
|
contextTweaker.accept(parserContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return parserContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConversionResult<T> convert(String argument, InjectedValueAccess context) {
|
||||||
|
ParserContext parserContext = createContext(context);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return SuccessfulConversion.fromSingle(
|
return SuccessfulConversion.fromSingle(
|
||||||
factoryExtractor.apply(worldEdit).parseFromInput(argument, parserContext)
|
factoryExtractor.apply(worldEdit).parseFromInput(argument, parserContext)
|
||||||
@ -150,7 +156,9 @@ public class FactoryConverter<T> implements ArgumentConverter<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getSuggestions(String input, InjectedValueAccess context) {
|
public List<String> getSuggestions(String input, InjectedValueAccess context) {
|
||||||
return factoryExtractor.apply(worldEdit).getSuggestions(input);
|
ParserContext parserContext = createContext(context);
|
||||||
|
|
||||||
|
return factoryExtractor.apply(worldEdit).getSuggestions(input, parserContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -127,13 +127,13 @@ public final class MaskFactory extends AbstractFactory<Mask> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getSuggestions(String input) {
|
public List<String> getSuggestions(String input, final ParserContext parserContext) {
|
||||||
final String[] split = input.split(" ");
|
final String[] split = input.split(" ");
|
||||||
if (split.length > 1) {
|
if (split.length > 1) {
|
||||||
String prev = input.substring(0, input.lastIndexOf(" ")) + " ";
|
String prev = input.substring(0, input.lastIndexOf(" ")) + " ";
|
||||||
return super.getSuggestions(split[split.length - 1]).stream().map(s -> prev + s).collect(Collectors.toList());
|
return super.getSuggestions(split[split.length - 1], parserContext).stream().map(s -> prev + s).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
return super.getSuggestions(input);
|
return super.getSuggestions(input, parserContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -91,9 +91,7 @@ public class AbstractDelegateExtent implements Extent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getBlock(BlockVector3 position) {
|
public BlockState getBlock(BlockVector3 position) {
|
||||||
//FAWE start - return coordinates
|
return extent.getBlock(position);
|
||||||
return extent.getBlock(position.getX(), position.getY(), position.getZ());
|
|
||||||
//FAWE end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -103,9 +101,7 @@ public class AbstractDelegateExtent implements Extent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseBlock getFullBlock(BlockVector3 position) {
|
public BaseBlock getFullBlock(BlockVector3 position) {
|
||||||
//FAWE start - return coordinates
|
return extent.getFullBlock(position);
|
||||||
return extent.getFullBlock(position.getX(), position.getY(), position.getZ());
|
|
||||||
//FAWE end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//FAWE start
|
//FAWE start
|
||||||
@ -117,9 +113,7 @@ public class AbstractDelegateExtent implements Extent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseBlock getFullBlock(int x, int y, int z) {
|
public BaseBlock getFullBlock(int x, int y, int z) {
|
||||||
//FAWE start - return coordinates
|
|
||||||
return extent.getFullBlock(x, y, z);
|
return extent.getFullBlock(x, y, z);
|
||||||
//FAWE end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -375,9 +369,7 @@ public class AbstractDelegateExtent implements Extent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BiomeType getBiome(BlockVector3 position) {
|
public BiomeType getBiome(BlockVector3 position) {
|
||||||
//FAWE start - switch top x,y,z
|
return extent.getBiome(position);
|
||||||
return extent.getBiomeType(position.getX(), position.getY(), position.getZ());
|
|
||||||
//FAWE end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//FAWE start
|
//FAWE start
|
||||||
@ -420,9 +412,7 @@ public class AbstractDelegateExtent implements Extent {
|
|||||||
@Override
|
@Override
|
||||||
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block)
|
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block)
|
||||||
throws WorldEditException {
|
throws WorldEditException {
|
||||||
//FAWE start - switch to x,y,z
|
return extent.setBlock(position, block);
|
||||||
return extent.setBlock(position.getX(), position.getY(), position.getZ(), block);
|
|
||||||
//FAWE end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//FAWE start
|
//FAWE start
|
||||||
@ -447,9 +437,7 @@ public class AbstractDelegateExtent implements Extent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
public boolean setBiome(BlockVector3 position, BiomeType biome) {
|
||||||
//FAWE start - switch to x,y,z
|
return extent.setBiome(position, biome);
|
||||||
return extent.setBiome(position.getX(), position.getY(), position.getZ(), biome);
|
|
||||||
//FAWE end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//FAWE start
|
//FAWE start
|
||||||
|
@ -27,7 +27,7 @@ import com.sk89q.worldedit.extent.Extent;
|
|||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -41,7 +41,7 @@ public class RandomPattern extends AbstractPattern {
|
|||||||
|
|
||||||
//FAWE start - SimpleRandom > Random, LHS<P> > List
|
//FAWE start - SimpleRandom > Random, LHS<P> > List
|
||||||
private final SimpleRandom random;
|
private final SimpleRandom random;
|
||||||
private Map<Pattern, Double> weights = new HashMap<>();
|
private Map<Pattern, Double> weights = new LinkedHashMap<>();
|
||||||
private RandomCollection<Pattern> collection;
|
private RandomCollection<Pattern> collection;
|
||||||
private LinkedHashSet<Pattern> patterns = new LinkedHashSet<>();
|
private LinkedHashSet<Pattern> patterns = new LinkedHashSet<>();
|
||||||
//FAWE end
|
//FAWE end
|
||||||
|
@ -24,6 +24,7 @@ import com.sk89q.worldedit.WorldEdit;
|
|||||||
import com.sk89q.worldedit.antlr.ExpressionLexer;
|
import com.sk89q.worldedit.antlr.ExpressionLexer;
|
||||||
import com.sk89q.worldedit.antlr.ExpressionParser;
|
import com.sk89q.worldedit.antlr.ExpressionParser;
|
||||||
import com.sk89q.worldedit.internal.expression.invoke.ExpressionCompiler;
|
import com.sk89q.worldedit.internal.expression.invoke.ExpressionCompiler;
|
||||||
|
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
|
||||||
import org.antlr.v4.runtime.CharStream;
|
import org.antlr.v4.runtime.CharStream;
|
||||||
import org.antlr.v4.runtime.CharStreams;
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
import org.antlr.v4.runtime.CommonTokenStream;
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
@ -199,7 +200,9 @@ public class Expression implements Cloneable {
|
|||||||
|
|
||||||
//FAWE start
|
//FAWE start
|
||||||
public Expression clone() {
|
public Expression clone() {
|
||||||
return new Expression(initialExpression, new HashSet<>(providedSlots));
|
Expression expression = new Expression(initialExpression, new HashSet<>(providedSlots));
|
||||||
|
expression.setEnvironment(getEnvironment().clone());
|
||||||
|
return expression;
|
||||||
}
|
}
|
||||||
//FAWE end
|
//FAWE end
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ package com.sk89q.worldedit.internal.expression;
|
|||||||
/**
|
/**
|
||||||
* Represents a way to access blocks in a world. Has to accept non-rounded coordinates.
|
* Represents a way to access blocks in a world. Has to accept non-rounded coordinates.
|
||||||
*/
|
*/
|
||||||
public interface ExpressionEnvironment {
|
public interface ExpressionEnvironment extends Cloneable {
|
||||||
|
|
||||||
int getBlockType(double x, double y, double z);
|
int getBlockType(double x, double y, double z);
|
||||||
|
|
||||||
@ -36,4 +36,7 @@ public interface ExpressionEnvironment {
|
|||||||
|
|
||||||
int getBlockDataRel(double x, double y, double z);
|
int getBlockDataRel(double x, double y, double z);
|
||||||
|
|
||||||
|
// FAWE start
|
||||||
|
ExpressionEnvironment clone();
|
||||||
|
// FAWE end
|
||||||
}
|
}
|
||||||
|
@ -96,9 +96,14 @@ public abstract class AbstractFactory<E> {
|
|||||||
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
|
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public List<String> getSuggestions(String input) {
|
public List<String> getSuggestions(String input) {
|
||||||
|
return getSuggestions(input, new ParserContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getSuggestions(String input, ParserContext context) {
|
||||||
return parsers.stream().flatMap(
|
return parsers.stream().flatMap(
|
||||||
p -> p.getSuggestions(input)
|
p -> p.getSuggestions(input, context)
|
||||||
).collect(Collectors.toList());
|
).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,9 +45,22 @@ public abstract class InputParser<E> {
|
|||||||
* Gets a stream of suggestions of input to this parser.
|
* Gets a stream of suggestions of input to this parser.
|
||||||
*
|
*
|
||||||
* @return a stream of suggestions
|
* @return a stream of suggestions
|
||||||
|
* @deprecated Use the version that takes a {@link ParserContext}, {@link #getSuggestions(String, ParserContext)}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public Stream<String> getSuggestions(String input) {
|
public Stream<String> getSuggestions(String input) {
|
||||||
return Stream.empty();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a stream of suggestions of input to this parser.
|
||||||
|
*
|
||||||
|
* @param input The string input
|
||||||
|
* @param context The parser context
|
||||||
|
*
|
||||||
|
* @return a stream of suggestions
|
||||||
|
*/
|
||||||
|
public Stream<String> getSuggestions(String input, ParserContext context) {
|
||||||
|
return getSuggestions(input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion {
|
|||||||
*/
|
*/
|
||||||
public void setRadius(Vector2 radius) {
|
public void setRadius(Vector2 radius) {
|
||||||
this.radius = radius.add(0.5, 0.5);
|
this.radius = radius.add(0.5, 0.5);
|
||||||
this.radiusInverse = Vector2.ONE.divide(radius);
|
this.radiusInverse = Vector2.ONE.divide(this.radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -413,11 +413,12 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion {
|
|||||||
final IChunk chunk, final Filter filter, final ChunkFilterBlock block,
|
final IChunk chunk, final Filter filter, final ChunkFilterBlock block,
|
||||||
final IChunkGet get, final IChunkSet set, boolean full
|
final IChunkGet get, final IChunkSet set, boolean full
|
||||||
) {
|
) {
|
||||||
int bcx = chunk.getX() >> 4;
|
int bcx = chunk.getX() << 4;
|
||||||
int bcz = chunk.getZ() >> 4;
|
int bcz = chunk.getZ() << 4;
|
||||||
int tcx = bcx + 15;
|
int tcx = bcx + 15;
|
||||||
int tcz = bcz + 15;
|
int tcz = bcz + 15;
|
||||||
if (contains(bcx, bcz) && contains(tcx, tcz)) {
|
// must contain all 4 corners for fast path
|
||||||
|
if (contains(bcx, bcz) && contains(tcx, tcz) && contains(bcx, tcz) && contains(tcx, bcz)) {
|
||||||
filter(chunk, filter, block, get, set, minY, maxY, full);
|
filter(chunk, filter, block, get, set, minY, maxY, full);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,8 @@ import com.sk89q.worldedit.math.Vector3;
|
|||||||
|
|
||||||
public class WorldEditExpressionEnvironment implements ExpressionEnvironment {
|
public class WorldEditExpressionEnvironment implements ExpressionEnvironment {
|
||||||
|
|
||||||
|
private static final Vector3 BLOCK_CENTER_OFFSET = Vector3.at(0.5, 0.5, 0.5);
|
||||||
|
|
||||||
private final Vector3 unit;
|
private final Vector3 unit;
|
||||||
private final Vector3 zero2;
|
private final Vector3 zero2;
|
||||||
//FAWE start - MutableVector3
|
//FAWE start - MutableVector3
|
||||||
@ -42,7 +44,7 @@ public class WorldEditExpressionEnvironment implements ExpressionEnvironment {
|
|||||||
public WorldEditExpressionEnvironment(Extent extent, Vector3 unit, Vector3 zero) {
|
public WorldEditExpressionEnvironment(Extent extent, Vector3 unit, Vector3 zero) {
|
||||||
this.extent = extent;
|
this.extent = extent;
|
||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
this.zero2 = zero.add(0.5, 0.5, 0.5);
|
this.zero2 = zero.add(BLOCK_CENTER_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockVector3 toWorld(double x, double y, double z) {
|
public BlockVector3 toWorld(double x, double y, double z) {
|
||||||
@ -94,10 +96,13 @@ public class WorldEditExpressionEnvironment implements ExpressionEnvironment {
|
|||||||
public Vector3 toWorldRel(double x, double y, double z) {
|
public Vector3 toWorldRel(double x, double y, double z) {
|
||||||
return current.add(x, y, z);
|
return current.add(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WorldEditExpressionEnvironment clone() {
|
||||||
|
return new WorldEditExpressionEnvironment(extent, unit, zero2.subtract(BLOCK_CENTER_OFFSET));
|
||||||
|
}
|
||||||
//FAWe end
|
//FAWe end
|
||||||
|
|
||||||
public void setCurrentBlock(Vector3 current) {
|
public void setCurrentBlock(Vector3 current) {
|
||||||
this.current = current;
|
this.current = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ import com.google.gson.Gson;
|
|||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.math.Vector3;
|
import com.sk89q.worldedit.math.Vector3;
|
||||||
|
import com.sk89q.worldedit.world.item.ItemType;
|
||||||
|
import com.sk89q.worldedit.world.item.ItemTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods for Google's GSON library.
|
* Utility methods for Google's GSON library.
|
||||||
@ -41,6 +43,7 @@ public final class GsonUtil {
|
|||||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||||
gsonBuilder.registerTypeAdapter(Vector3.class, new VectorAdapter());
|
gsonBuilder.registerTypeAdapter(Vector3.class, new VectorAdapter());
|
||||||
gsonBuilder.registerTypeAdapter(BlockVector3.class, new BlockVectorAdapter());
|
gsonBuilder.registerTypeAdapter(BlockVector3.class, new BlockVectorAdapter());
|
||||||
|
gsonBuilder.registerTypeAdapter(ItemType.class, new ItemTypeAdapter());
|
||||||
return gsonBuilder;
|
return gsonBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.sk89q.worldedit.util.gson;
|
||||||
|
|
||||||
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonDeserializer;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.sk89q.worldedit.world.item.ItemType;
|
||||||
|
import com.sk89q.worldedit.world.item.ItemTypes;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
public final class ItemTypeAdapter implements JsonDeserializer<ItemType> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemType deserialize(JsonElement json, Type type, JsonDeserializationContext cont) throws JsonParseException {
|
||||||
|
JsonObject jsonObject = json.getAsJsonObject();
|
||||||
|
String id = jsonObject.get("id").getAsString();
|
||||||
|
ItemType itemType = ItemTypes.get(id);
|
||||||
|
if (itemType == null) {
|
||||||
|
throw new JsonParseException("Could not parse item type `" + id + "`");
|
||||||
|
}
|
||||||
|
return itemType;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -79,7 +79,7 @@ public class ItemType implements RegistryItem, Keyed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//FAWE start
|
//FAWE start
|
||||||
private int internalId;
|
private transient int internalId;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setInternalId(int internalId) {
|
public void setInternalId(int internalId) {
|
||||||
|
@ -114,6 +114,11 @@ class BaseExpressionTest {
|
|||||||
public int getBlockDataRel(double x, double y, double z) {
|
public int getBlockDataRel(double x, double y, double z) {
|
||||||
return (int) y * 100;
|
return (int) y * 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExpressionEnvironment clone() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return expression.evaluate();
|
return expression.evaluate();
|
||||||
|
@ -28,7 +28,7 @@ dependencies {
|
|||||||
})
|
})
|
||||||
api("org.apache.logging.log4j:log4j-api")
|
api("org.apache.logging.log4j:log4j-api")
|
||||||
api("org.bstats:bstats-sponge:1.7")
|
api("org.bstats:bstats-sponge:1.7")
|
||||||
testImplementation("org.mockito:mockito-core:5.9.0")
|
testImplementation("org.mockito:mockito-core:5.11.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
<<<<<<< HEAD
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren