diff --git a/.gitignore b/.gitignore index 8e37aad62..dfea5f9e5 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ target forge-download out run +.jqwik-database /dependency-reduced-pom.xml *-private.sh diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 255e09c1b..e361084fc 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,7 @@ +7.3.6 +- [Bukkit] Allow 1.21 Paper adapter to load on 1.21.1 +- Revert "Shutdown the executor service on disable, to prevent waiting on async tasks before shutting down" due to it causing issues in some situations + 7.3.5 - [Bukkit] Utilise new Bukkit registry API, allowing WorldEdit to work with Commodore disabled (`paper.disableOldApiSupport` flag on Paper) - Fix queryRel not behaving correctly in //deform and the deform brush diff --git a/README.md b/README.md index 89126be62..77b7e4449 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,9 @@ Java Edition required. WorldEdit is compatible with Forge, Fabric, Bukkit, Spigo ## Download WorldEdit -This place contains the Java code for WorldEdit, but if you want to just use WorldEdit, get the mod or plugin from these pages: +This place contains the Java code for WorldEdit, but if you want to just use WorldEdit, get the mod or plugin from Modrinth: -* For the mod: https://www.curseforge.com/minecraft/mc-mods/worldedit -* For the server plugin: https://dev.bukkit.org/projects/worldedit +https://modrinth.com/plugin/worldedit/versions Edit the Code --------- diff --git a/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts b/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts index 781e429cd..576b9d832 100644 --- a/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts +++ b/build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts @@ -8,10 +8,6 @@ id("io.papermc.paperweight.userdev") } -configure { - banSlf4j = false -} - paperweight { injectPaperRepository = false } diff --git a/build-logic/src/main/kotlin/buildlogic.common-java.gradle.kts b/build-logic/src/main/kotlin/buildlogic.common-java.gradle.kts index 02011915e..0167e8a3c 100644 --- a/build-logic/src/main/kotlin/buildlogic.common-java.gradle.kts +++ b/build-logic/src/main/kotlin/buildlogic.common-java.gradle.kts @@ -8,9 +8,6 @@ id("buildlogic.common") } -val commonJava = extensions.create("commonJava") -commonJava.banSlf4j.convention(true) - tasks .withType() .matching { it.name == "compileJava" || it.name == "compileTestJava" } @@ -33,7 +30,9 @@ } tasks.withType().configureEach { - useJUnitPlatform() + useJUnitPlatform { + includeEngines("junit-jupiter", "jqwik") + } } dependencies { @@ -41,6 +40,7 @@ "testImplementation"(platform(stringyLibs.getLibrary("junit-bom"))) "testImplementation"(stringyLibs.getLibrary("junit-jupiter-api")) "testImplementation"(stringyLibs.getLibrary("junit-jupiter-params")) + "testImplementation"(stringyLibs.getLibrary("jqwik")) "testImplementation"(platform(stringyLibs.getLibrary("mockito-bom"))) "testImplementation"(stringyLibs.getLibrary("mockito-core")) "testImplementation"(stringyLibs.getLibrary("mockito-junit-jupiter")) @@ -67,16 +67,6 @@ withSourcesJar() } -configurations["compileClasspath"].apply { - resolutionStrategy.componentSelection { - withModule("org.slf4j:slf4j-api") { - if (commonJava.banSlf4j.get()) { - reject("No SLF4J allowed on compile classpath") - } - } - } -} - tasks.named("check").configure { dependsOn("checkstyleMain", "checkstyleTest") } diff --git a/build-logic/src/main/kotlin/buildlogic.platform.gradle.kts b/build-logic/src/main/kotlin/buildlogic.platform.gradle.kts index 259794771..c14b4b3b7 100644 --- a/build-logic/src/main/kotlin/buildlogic.platform.gradle.kts +++ b/build-logic/src/main/kotlin/buildlogic.platform.gradle.kts @@ -1,3 +1,6 @@ +import buildlogic.getLibrary +import buildlogic.stringyLibs + plugins { id("com.github.johnrengelman.shadow") id("buildlogic.core-and-platform") @@ -9,17 +12,23 @@ tasks.named("shadowJar") { archiveClassifier.set("dist") + relocate("com.sk89q.jchronic", "com.sk89q.worldedit.jchronic") + val jchronic = stringyLibs.getLibrary("jchronic").get() dependencies { include(project(":worldedit-libs:core")) include(project(":worldedit-libs:${project.name.replace("worldedit-", "")}")) include(project(":worldedit-core")) - exclude("com.google.code.findbugs:jsr305") + include(dependency(jchronic)) + exclude(dependency("com.google.code.findbugs:jsr305")) } exclude("GradleStart**") exclude(".cache") exclude("LICENSE*") exclude("META-INF/maven/**") - minimize() + minimize { + // jchronic uses reflection to load things, so we need to exclude it from minimizing + exclude(dependency(jchronic)) + } } val javaComponent = components["java"] as AdhocComponentWithVariants // I don't think we want this published (it's the shadow jar) diff --git a/build-logic/src/main/kotlin/buildlogic/CommonJavaExtension.kt b/build-logic/src/main/kotlin/buildlogic/CommonJavaExtension.kt deleted file mode 100644 index 8631f5379..000000000 --- a/build-logic/src/main/kotlin/buildlogic/CommonJavaExtension.kt +++ /dev/null @@ -1,7 +0,0 @@ -package buildlogic - -import org.gradle.api.provider.Property - -interface CommonJavaExtension { - val banSlf4j: Property -} diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index e3678ec6f..4c533604d 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -145,6 +145,10 @@ Checks based on Google Checks, modified for EngineHub. + + + + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d0e1925b9..69c0652ba 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -66,6 +66,8 @@ junit-jupiter-api.module = "org.junit.jupiter:junit-jupiter-api" junit-jupiter-params.module = "org.junit.jupiter:junit-jupiter-params" junit-jupiter-engine.module = "org.junit.jupiter:junit-jupiter-engine" +jqwik = "net.jqwik:jqwik:1.9.0" + mockito-bom = "org.mockito:mockito-bom:5.11.0" mockito-core.module = "org.mockito:mockito-core" mockito-junit-jupiter.module = "org.mockito:mockito-junit-jupiter" diff --git a/worldedit-bukkit/build.gradle.kts b/worldedit-bukkit/build.gradle.kts index 70801d597..1a2f57e4e 100644 --- a/worldedit-bukkit/build.gradle.kts +++ b/worldedit-bukkit/build.gradle.kts @@ -56,7 +56,6 @@ because("Resolving Spigot annotations") } "compileOnly"(libs.paperApi) { - exclude("org.slf4j", "slf4j-api") exclude("junit", "junit") } "implementation"(libs.paperLib) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index b44216319..5cf47c63b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -32,6 +32,7 @@ import com.sk89q.worldedit.extent.NullExtent; import com.sk89q.worldedit.extent.TracingExtent; import com.sk89q.worldedit.extent.buffer.ForgetfulExtentBuffer; +import com.sk89q.worldedit.extent.buffer.internal.BatchingExtent; import com.sk89q.worldedit.extent.cache.LastAccessExtentCache; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBagExtent; @@ -199,6 +200,7 @@ public String getDisplayName() { private @Nullable SideEffectExtent sideEffectExtent; private final SurvivalModeExtent survivalExtent; + private @Nullable BatchingExtent batchingExtent; private @Nullable ChunkBatchingExtent chunkBatchingExtent; private final BlockBagExtent blockBagExtent; @SuppressWarnings("deprecation") @@ -267,6 +269,7 @@ public String getDisplayName() { this.bypassReorderHistory = traceIfNeeded(new DataValidatorExtent(extent, world)); // This extent can be skipped by calling rawSetBlock() + extent = traceIfNeeded(batchingExtent = new BatchingExtent(extent)); @SuppressWarnings("deprecation") MultiStageReorder reorder = new MultiStageReorder(extent, false); extent = traceIfNeeded(reorderExtent = reorder); @@ -557,7 +560,7 @@ public void setSideEffectApplier(SideEffectSet sideEffectSet) { */ @Deprecated public boolean hasFastMode() { - return sideEffectExtent != null && this.sideEffectExtent.getSideEffectSet().doesApplyAny(); + return sideEffectExtent != null && !this.sideEffectExtent.getSideEffectSet().doesApplyAny(); } public SideEffectSet getSideEffectApplier() { @@ -616,10 +619,12 @@ public void setBatchingChunks(boolean batchingChunks) { } return; } + assert batchingExtent != null : "same nullness as chunkBatchingExtent"; if (!batchingChunks && isBatchingChunks()) { internalFlushSession(); } chunkBatchingExtent.setEnabled(batchingChunks); + batchingExtent.setEnabled(!batchingChunks); } /** @@ -648,6 +653,8 @@ public void disableBuffering() { setReorderMode(ReorderMode.NONE); if (chunkBatchingExtent != null) { chunkBatchingExtent.setEnabled(false); + assert batchingExtent != null : "same nullness as chunkBatchingExtent"; + batchingExtent.setEnabled(true); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index 8fefaab6a..5555bd399 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -134,7 +134,7 @@ public int line(Actor actor, EditSession editSession, @Arg(desc = "The pattern of blocks to place") Pattern pattern, @Arg(desc = "The thickness of the line", def = "0") - int thickness, + double thickness, @Switch(name = 'h', desc = "Generate only a shell") boolean shell) throws WorldEditException { if (!((region instanceof CuboidRegion) || (region instanceof ConvexPolyhedralRegion))) { @@ -171,7 +171,7 @@ public int curve(Actor actor, EditSession editSession, @Arg(desc = "The pattern of blocks to place") Pattern pattern, @Arg(desc = "The thickness of the curve", def = "0") - int thickness, + double thickness, @Switch(name = 'h', desc = "Generate only a shell") boolean shell) throws WorldEditException { if (!(region instanceof ConvexPolyhedralRegion cpregion)) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/buffer/internal/BatchingExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/buffer/internal/BatchingExtent.java new file mode 100644 index 000000000..674e0a5db --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/buffer/internal/BatchingExtent.java @@ -0,0 +1,111 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +package com.sk89q.worldedit.extent.buffer.internal; + +import com.google.common.base.Throwables; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.extent.AbstractBufferingExtent; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.operation.Operation; +import com.sk89q.worldedit.function.operation.RunContext; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.collection.BlockMap; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockStateHolder; + +/** + * An extent that buffers all changes until completed. + */ +public class BatchingExtent extends AbstractBufferingExtent { + + private final BlockMap blockMap = BlockMap.createForBaseBlock(); + private boolean enabled; + + public BatchingExtent(Extent extent) { + this(extent, true); + } + + public BatchingExtent(Extent extent, boolean enabled) { + super(extent); + this.enabled = enabled; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean commitRequired() { + return enabled; + } + + @Override + public > boolean setBlock(BlockVector3 location, B block) throws WorldEditException { + if (!enabled) { + return setDelegateBlock(location, block); + } + blockMap.put(location, block.toBaseBlock()); + return true; + } + + @Override + protected BaseBlock getBufferedFullBlock(BlockVector3 position) { + if (!enabled) { + // Early exit if we're not enabled. + return null; + } + return blockMap.get(position); + } + + @Override + protected Operation commitBefore() { + if (!commitRequired()) { + return null; + } + return new Operation() { + + @Override + public Operation resume(RunContext run) throws WorldEditException { + try { + blockMap.forEach((position, block) -> { + try { + getExtent().setBlock(position, block); + } catch (WorldEditException e) { + throw new RuntimeException(e); + } + }); + } catch (RuntimeException e) { + Throwables.throwIfInstanceOf(e.getCause(), WorldEditException.class); + throw e; + } + blockMap.clear(); + return null; + } + + @Override + public void cancel() { + } + }; + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV3Reader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV3Reader.java index 88285fbe5..ac7ecb9b0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV3Reader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV3Reader.java @@ -143,7 +143,7 @@ private void decodeBlocksIntoClipboard(VersionedDataFixer fixer, LinCompoundTag ); byte[] blocks = blockContainer.getTag("Data", LinTagType.byteArrayTag()).value(); - LinListTag blockEntities = blockContainer.getListTag("BlockEntities", LinTagType.compoundTag()); + LinListTag blockEntities = blockContainer.findListTag("BlockEntities", LinTagType.compoundTag()); ReaderUtil.initializeClipboardFromBlocks( clipboard, palette, blocks, blockEntities, fixer, true diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java index 49834fe9a..51ac0ccf7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/reorder/ChunkBatchingExtent.java @@ -31,7 +31,6 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; /** @@ -91,18 +90,11 @@ protected Operation commitBefore() { } return new Operation() { - // we get modified between create/resume -- only create this on resume to prevent CME - private Iterator iterator; - @Override public Operation resume(RunContext run) throws WorldEditException { - if (iterator == null) { - List blockVectors = new ArrayList<>(blockMap.keySet()); - RegionOptimizedVectorSorter.sort(blockVectors); - iterator = blockVectors.iterator(); - } - while (iterator.hasNext()) { - BlockVector3 position = iterator.next(); + List blockVectors = new ArrayList<>(blockMap.keySet()); + RegionOptimizedVectorSorter.sort(blockVectors); + for (BlockVector3 position : blockVectors) { BaseBlock block = blockMap.get(position); getExtent().setBlock(position, block); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java index d1a09a54f..639eabe89 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java @@ -283,7 +283,7 @@ public static > B transform(B block, Transform tra Property propAsObj = (Property) prop; result = result.with(propAsObj, "none"); } - directionalProperties.put(closestProp, result.getState(prop)); + directionalProperties.put(closestProp, state); } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandUtil.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandUtil.java index e18346470..61b03375c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandUtil.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandUtil.java @@ -227,7 +227,8 @@ private static Substring onlyOnLastQuotedWord(Substring lastArg, Substring sugge return suggestion; } String substr = suggestion.getSubstring(); - int sp = substr.lastIndexOf(' '); + // Check if there is a space inside the substring, and suggest starting from there instead. + int sp = substr.trim().lastIndexOf(' '); if (sp < 0) { return suggestion; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffectSet.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffectSet.java index e57ee500d..08109f2dc 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffectSet.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/SideEffectSet.java @@ -19,11 +19,12 @@ package com.sk89q.worldedit.util; +import com.google.common.base.Verify; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import java.util.Arrays; -import java.util.EnumMap; +import java.util.EnumSet; import java.util.Map; import java.util.Set; import java.util.function.Function; @@ -37,33 +38,73 @@ public class SideEffectSet { .collect(Collectors.toMap(Function.identity(), state -> SideEffect.State.OFF)) ); - private final Map sideEffects; - private final Set appliedSideEffects; - private final boolean appliesAny; + static { + Verify.verify( + SideEffect.State.values().length == 3, + "Implementation requires specifically 3 values in the SideEffect.State enum" + ); + int maxEffects = Integer.SIZE / 2; + Verify.verify( + SideEffect.values().length <= maxEffects, + "Implementation requires less than " + maxEffects + " side effects" + ); + Verify.verify( + SideEffect.State.OFF.ordinal() == 0, + "Implementation requires SideEffect.State.OFF to be the first value" + ); + } + + private static int shift(SideEffect effect) { + return effect.ordinal() * 2; + } + + private static int computeSideEffectsBitmap(Map sideEffects) { + int sideEffectsBitmap = 0; + for (SideEffect effect : SideEffect.values()) { + SideEffect.State state = sideEffects.getOrDefault(effect, effect.getDefaultValue()); + sideEffectsBitmap |= (state.ordinal() << shift(effect)); + } + return sideEffectsBitmap; + } + + /** + * Side-effects and state are encoded into this field, 2 bits per side-effect. Least-significant bit is first. + */ + private final int sideEffectsBitmap; + private final Set sideEffectsToApply; public SideEffectSet(Map sideEffects) { - this.sideEffects = Maps.immutableEnumMap(sideEffects); + this(computeSideEffectsBitmap(sideEffects)); + } - appliedSideEffects = sideEffects.entrySet() - .stream() - .filter(entry -> entry.getValue() != SideEffect.State.OFF) - .map(Map.Entry::getKey) - .collect(Collectors.toSet()); - appliesAny = !appliedSideEffects.isEmpty(); + private SideEffectSet(int sideEffectsBitmap) { + this.sideEffectsBitmap = sideEffectsBitmap; + var sideEffectsToApply = EnumSet.noneOf(SideEffect.class); + for (SideEffect effect : SideEffect.values()) { + if (shouldApply(effect)) { + sideEffectsToApply.add(effect); + } + } + this.sideEffectsToApply = Sets.immutableEnumSet(sideEffectsToApply); } public SideEffectSet with(SideEffect sideEffect, SideEffect.State state) { - Map entries = this.sideEffects.isEmpty() ? Maps.newEnumMap(SideEffect.class) : new EnumMap<>(this.sideEffects); - entries.put(sideEffect, state); - return new SideEffectSet(entries); + int mask = 0b11 << shift(sideEffect); + int newState = (state.ordinal() << shift(sideEffect)) & mask; + int newBitmap = (sideEffectsBitmap & ~mask) | newState; + return new SideEffectSet(newBitmap); } public boolean doesApplyAny() { - return this.appliesAny; + return sideEffectsBitmap != 0; } public SideEffect.State getState(SideEffect effect) { - return sideEffects.getOrDefault(effect, effect.getDefaultValue()); + return SideEffect.State.values()[getRawState(effect)]; + } + + private int getRawState(SideEffect effect) { + return (sideEffectsBitmap >> shift(effect)) & 0b11; } /** @@ -77,11 +118,11 @@ public SideEffect.State getState(SideEffect effect) { * @return Whether it should apply */ public boolean shouldApply(SideEffect effect) { - return getState(effect) != SideEffect.State.OFF; + return getRawState(effect) != 0; } public Set getSideEffectsToApply() { - return this.appliedSideEffects; + return sideEffectsToApply; } public static SideEffectSet defaults() { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ForwardSeekableInputStream.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ForwardSeekableInputStream.java index 328bfdb8c..bb424fc8f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ForwardSeekableInputStream.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/io/ForwardSeekableInputStream.java @@ -86,7 +86,6 @@ public long skip(long n) throws IOException { public void seek(long n) throws IOException { long diff = n - position; - System.err.println("Seek to " + n + " from position " + position + " using " + diff); if (diff < 0) { throw new IOException("Can't seek backwards"); diff --git a/worldedit-core/src/test/java/com/sk89q/worldedit/util/SideEffectSetTest.java b/worldedit-core/src/test/java/com/sk89q/worldedit/util/SideEffectSetTest.java new file mode 100644 index 000000000..d1eb0ea42 --- /dev/null +++ b/worldedit-core/src/test/java/com/sk89q/worldedit/util/SideEffectSetTest.java @@ -0,0 +1,78 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * 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 . + */ + +package com.sk89q.worldedit.util; + +import net.jqwik.api.ForAll; +import net.jqwik.api.Property; + +import java.util.Map; + +public class SideEffectSetTest { + @Property + public boolean stateOrDefaultIsCorrect( + @ForAll Map stateMap, + @ForAll SideEffect effectToTest + ) { + SideEffectSet set = new SideEffectSet(stateMap); + return set.getState(effectToTest) == stateMap.getOrDefault(effectToTest, effectToTest.getDefaultValue()); + } + + @Property + public boolean shouldApplyUnlessOff( + @ForAll Map stateMap, + @ForAll SideEffect effectToTest + ) { + SideEffectSet set = new SideEffectSet(stateMap); + return set.shouldApply(effectToTest) + == (stateMap.getOrDefault(effectToTest, effectToTest.getDefaultValue()) != SideEffect.State.OFF); + } + + @Property + public boolean withChangesState( + @ForAll Map stateMap, + @ForAll SideEffect effectToTest, + @ForAll SideEffect.State stateToSet + ) { + SideEffectSet set = new SideEffectSet(stateMap).with(effectToTest, stateToSet); + return set.getState(effectToTest) == stateToSet; + } + + @Property + public boolean anyShouldApplyEqualsDoesApplyAny(@ForAll Map stateMap) { + SideEffectSet set = new SideEffectSet(stateMap); + boolean anyShouldApply = false; + for (SideEffect effect : SideEffect.values()) { + if (set.shouldApply(effect)) { + anyShouldApply = true; + break; + } + } + return anyShouldApply == set.doesApplyAny(); + } + + @Property + public boolean shouldApplyEqualsApplySetContains( + @ForAll Map stateMap, + @ForAll SideEffect effectToTest + ) { + SideEffectSet set = new SideEffectSet(stateMap); + return set.shouldApply(effectToTest) == set.getSideEffectsToApply().contains(effectToTest); + } +} diff --git a/worldedit-core/src/test/resources/junit-platform.properties b/worldedit-core/src/test/resources/junit-platform.properties index ee7c4fad3..49883e6ba 100644 --- a/worldedit-core/src/test/resources/junit-platform.properties +++ b/worldedit-core/src/test/resources/junit-platform.properties @@ -3,3 +3,5 @@ junit.jupiter.execution.parallel.mode.default=concurrent junit.jupiter.execution.parallel.mode.classes.default=same_thread junit.jupiter.execution.parallel.config.strategy=dynamic junit.jupiter.execution.parallel.config.dynamic.factor=4 + +jqwik.tries.default = 10000 diff --git a/worldedit-fabric/build.gradle.kts b/worldedit-fabric/build.gradle.kts index a6af19e7b..a9fa0be5a 100644 --- a/worldedit-fabric/build.gradle.kts +++ b/worldedit-fabric/build.gradle.kts @@ -10,11 +10,6 @@ id("buildlogic.platform") } -commonJava { - // Not easy to do, because it's in a bunch of separate configurations - banSlf4j = false -} - platform { kind = buildlogic.WorldEditKind.Mod includeClasspath = true diff --git a/worldedit-neoforge/build.gradle.kts b/worldedit-neoforge/build.gradle.kts index 0c5c61dd1..18f2e45fe 100644 --- a/worldedit-neoforge/build.gradle.kts +++ b/worldedit-neoforge/build.gradle.kts @@ -7,11 +7,6 @@ id("buildlogic.platform") } -commonJava { - // Not easy to do, because it's in a bunch of separate configurations - banSlf4j = false -} - platform { kind = buildlogic.WorldEditKind.Mod } diff --git a/worldedit-sponge/build.gradle.kts b/worldedit-sponge/build.gradle.kts index 34ac6bc04..56518fa73 100644 --- a/worldedit-sponge/build.gradle.kts +++ b/worldedit-sponge/build.gradle.kts @@ -14,10 +14,6 @@ includeClasspath = true } -commonJava { - banSlf4j = false -} - minecraft { injectRepositories(false) version(libs.versions.sponge.minecraft.get())