Merge branch 'IntellectualSites:main' into main

This commit is contained in:
Telesphoreo 2024-03-31 17:40:51 -05:00 committed by GitHub
commit 26b1ceca58
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 386 additions and 84 deletions

View File

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Label conflicting PRs - name: Label conflicting PRs
uses: eps1lon/actions-label-merge-conflict@v2.1.0 uses: eps1lon/actions-label-merge-conflict@v3.0.0
with: with:
dirtyLabel: "unresolved-merge-conflict" dirtyLabel: "unresolved-merge-conflict"
repoToken: "${{ secrets.GITHUB_TOKEN }}" repoToken: "${{ secrets.GITHUB_TOKEN }}"

View File

@ -28,7 +28,7 @@ dependencies {
implementation(gradleApi()) implementation(gradleApi())
implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2") 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.12")
} }
kotlin { kotlin {

View File

@ -14,7 +14,7 @@ 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.20" towny = "0.100.1.24"
plotsquared = "7.3.6" plotsquared = "7.3.6"
# Third party # Third party
@ -43,7 +43,7 @@ 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.8" piston = "0.5.10"
# Tests # Tests
mockito = "5.11.0" mockito = "5.11.0"

Binary file not shown.

View File

@ -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.6-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

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

View File

@ -5,6 +5,7 @@ import com.fastasyncworldedit.core.function.mask.RadiusMask;
import com.fastasyncworldedit.core.function.mask.SurfaceMask; import com.fastasyncworldedit.core.function.mask.SurfaceMask;
import com.fastasyncworldedit.core.math.BlockVectorSet; import com.fastasyncworldedit.core.math.BlockVectorSet;
import com.fastasyncworldedit.core.math.LocalBlockVectorSet; import com.fastasyncworldedit.core.math.LocalBlockVectorSet;
import com.fastasyncworldedit.core.util.collection.BlockVector3Set;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.command.tool.brush.Brush; import com.sk89q.worldedit.command.tool.brush.Brush;
@ -64,8 +65,9 @@ public class ScatterBrush implements Brush {
length = 1; length = 1;
visited.add(position); visited.add(position);
} }
LocalBlockVectorSet placed = new LocalBlockVectorSet(); BlockVector3 patternSize = pattern.size();
placed.setOffset(position.getX(), position.getZ()); BlockVector3Set placed = BlockVector3Set.getAppropriateVectorSet(patternSize.add(distance, distance, distance));
placed.setOffset(position.getX(), position.getY(), position.getZ());
int maxFails = 1000; int maxFails = 1000;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
int index = ThreadLocalRandom.current().nextInt(length); int index = ThreadLocalRandom.current().nextInt(length);
@ -88,7 +90,20 @@ public class ScatterBrush implements Brush {
finish(editSession, placed, position, pattern, size); finish(editSession, placed, position, pattern, size);
} }
/**
* @deprecated Use {@link ScatterBrush#finish(EditSession, BlockVector3Set, BlockVector3, Pattern, double)}
*/
@Deprecated(forRemoval = true, since = "TODO")
public void finish(EditSession editSession, LocalBlockVectorSet placed, BlockVector3 pos, Pattern pattern, double size) { 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 TODO
*/
public void finish(EditSession editSession, BlockVector3Set placed, BlockVector3 pos, Pattern pattern, double size) {
} }
public boolean canApply(BlockVector3 pos) { public boolean canApply(BlockVector3 pos) {
@ -99,8 +114,23 @@ public class ScatterBrush implements Brush {
return surface.direction(pt); return surface.direction(pt);
} }
/**
* @deprecated Use {@link ScatterBrush#apply(EditSession, BlockVector3Set, BlockVector3, Pattern, double)}
*/
@Deprecated(forRemoval = true, since = "TODO")
public void apply(EditSession editSession, LocalBlockVectorSet placed, BlockVector3 pt, Pattern p, double size) throws public void apply(EditSession editSession, LocalBlockVectorSet placed, BlockVector3 pt, Pattern p, double size) throws
MaxChangedBlocksException { MaxChangedBlocksException {
apply(editSession, (BlockVector3Set) placed, pt, p, size);
}
/**
* Apply the scatter brush to a given position
*
* @since TODO
*/
public void apply(EditSession editSession, BlockVector3Set placed, BlockVector3 pt, Pattern p, double size) throws
MaxChangedBlocksException {
editSession.setBlock(pt, p); editSession.setBlock(pt, p);
} }

View File

@ -3,6 +3,7 @@ package com.fastasyncworldedit.core.command.tool.brush;
import com.fastasyncworldedit.core.function.mask.SurfaceMask; import com.fastasyncworldedit.core.function.mask.SurfaceMask;
import com.fastasyncworldedit.core.math.LocalBlockVectorSet; import com.fastasyncworldedit.core.math.LocalBlockVectorSet;
import com.fastasyncworldedit.core.math.MutableBlockVector3; import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.fastasyncworldedit.core.util.collection.BlockVector3Set;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
@ -24,7 +25,7 @@ public class ShatterBrush extends ScatterBrush {
@Override @Override
public void apply( public void apply(
final EditSession editSession, final EditSession editSession,
final LocalBlockVectorSet placed, final BlockVector3Set placed,
final BlockVector3 position, final BlockVector3 position,
Pattern p, Pattern p,
double size double size
@ -34,7 +35,7 @@ public class ShatterBrush extends ScatterBrush {
@Override @Override
public void finish( public void finish(
EditSession editSession, EditSession editSession,
LocalBlockVectorSet placed, BlockVector3Set placed,
final BlockVector3 position, final BlockVector3 position,
Pattern pattern, Pattern pattern,
double size double size

View File

@ -19,12 +19,9 @@ import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -80,28 +77,18 @@ public class MultiBatchProcessor implements IBatchProcessor {
@Override @Override
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
Map<Integer, Set<IBatchProcessor>> ordered = new HashMap<>(); Map<Integer, List<IBatchProcessor>> ordered = new HashMap<>();
IChunkSet chunkSet = set; IChunkSet chunkSet = set;
for (IBatchProcessor processor : processors) { for (IBatchProcessor processor : processors) {
if (processor.getScope() != ProcessorScope.ADDING_BLOCKS) { if (processor.getScope() != ProcessorScope.ADDING_BLOCKS) {
ordered.merge( ordered.computeIfAbsent(processor.getScope().intValue(), k -> new ArrayList<>())
processor.getScope().intValue(), .add(processor);
new HashSet<>(Collections.singleton(processor)),
(existing, theNew) -> {
existing.add(processor);
return existing;
}
);
continue; continue;
} }
chunkSet = processSet(processor, chunk, get, chunkSet); chunkSet = processSet(processor, chunk, get, chunkSet);
} }
if (ordered.size() > 0) { if (!ordered.isEmpty()) {
for (int i = 1; i <= 4; i++) { for (List<IBatchProcessor> processors : ordered.values()) {
Set<IBatchProcessor> processors = ordered.get(i);
if (processors == null) {
continue;
}
for (IBatchProcessor processor : processors) { for (IBatchProcessor processor : processors) {
chunkSet = processSet(processor, chunk, get, chunkSet); chunkSet = processSet(processor, chunk, get, chunkSet);
if (chunkSet == null) { if (chunkSet == null) {

View File

@ -1,6 +1,7 @@
package com.fastasyncworldedit.core.function.pattern; package com.fastasyncworldedit.core.function.pattern;
import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.expression.EvaluationException; import com.sk89q.worldedit.internal.expression.EvaluationException;
import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.internal.expression.ExpressionException;
@ -57,4 +58,9 @@ public class ExpressionPattern extends AbstractPattern {
} }
} }
@Override
public Pattern fork() {
return new ExpressionPattern(this.expression.clone());
}
} }

View File

@ -7,6 +7,8 @@ import com.sk89q.worldedit.function.pattern.Pattern;
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.Arrays;
import static java.lang.Math.floorDiv; import static java.lang.Math.floorDiv;
/** /**
@ -52,4 +54,10 @@ public class Linear2DBlockPattern extends AbstractPattern {
return patternsArray[index].apply(extent, get, set); return patternsArray[index].apply(extent, get, set);
} }
@Override
public Pattern fork() {
final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new);
return new Linear2DBlockPattern(forked, this.xScale, this.zScale);
}
} }

View File

@ -7,6 +7,8 @@ import com.sk89q.worldedit.function.pattern.Pattern;
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.Arrays;
import static java.lang.Math.floorDiv; import static java.lang.Math.floorDiv;
/** /**
@ -56,4 +58,10 @@ public class Linear3DBlockPattern extends AbstractPattern {
return patternsArray[index].apply(extent, get, set); return patternsArray[index].apply(extent, get, set);
} }
@Override
public Pattern fork() {
final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new);
return new Linear3DBlockPattern(forked, this.xScale, this.yScale, this.zScale);
}
} }

View File

@ -1,5 +1,6 @@
package com.fastasyncworldedit.core.function.pattern; package com.fastasyncworldedit.core.function.pattern;
import com.fastasyncworldedit.core.queue.Filter;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.AbstractPattern;
@ -7,6 +8,8 @@ import com.sk89q.worldedit.function.pattern.Pattern;
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.Arrays;
public class LinearBlockPattern extends AbstractPattern implements ResettablePattern { public class LinearBlockPattern extends AbstractPattern implements ResettablePattern {
private final Pattern[] patternsArray; private final Pattern[] patternsArray;
@ -15,7 +18,7 @@ public class LinearBlockPattern extends AbstractPattern implements ResettablePat
/** /**
* Create a new {@link Pattern} instance * Create a new {@link Pattern} instance
* *
* @param patterns array of patterns to linearly choose from based on x/z coordinates * @param patterns array of patterns to linearly choose from
*/ */
public LinearBlockPattern(Pattern[] patterns) { public LinearBlockPattern(Pattern[] patterns) {
this.patternsArray = patterns; this.patternsArray = patterns;
@ -23,18 +26,14 @@ public class LinearBlockPattern extends AbstractPattern implements ResettablePat
@Override @Override
public BaseBlock applyBlock(BlockVector3 position) { public BaseBlock applyBlock(BlockVector3 position) {
if (index == patternsArray.length) { index = (index + 1) % patternsArray.length;
index = 0; return patternsArray[index].applyBlock(position);
}
return patternsArray[index++].applyBlock(position);
} }
@Override @Override
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
if (index == patternsArray.length) { index = (index + 1) % patternsArray.length;
index = 0; return patternsArray[index].apply(extent, get, set);
}
return patternsArray[index++].apply(extent, get, set);
} }
@Override @Override
@ -42,4 +41,10 @@ public class LinearBlockPattern extends AbstractPattern implements ResettablePat
index = 0; index = 0;
} }
@Override
public Pattern fork() {
final Pattern[] forked = Arrays.stream(this.patternsArray).map(Pattern::fork).toArray(Pattern[]::new);
return new LinearBlockPattern(forked);
}
} }

View File

@ -43,4 +43,9 @@ public class MaskedPattern extends AbstractPattern {
return secondary.apply(extent, get, set); return secondary.apply(extent, get, set);
} }
@Override
public Pattern fork() {
return new MaskedPattern(this.mask.copy(), this.primary.fork(), this.secondary.fork());
}
} }

View File

@ -36,4 +36,9 @@ public class NoXPattern extends AbstractPattern {
return pattern.apply(extent, mutable, set); return pattern.apply(extent, mutable, set);
} }
@Override
public Pattern fork() {
return new NoXPattern(this.pattern.fork());
}
} }

View File

@ -36,4 +36,9 @@ public class NoYPattern extends AbstractPattern {
return pattern.apply(extent, mutable, set); return pattern.apply(extent, mutable, set);
} }
@Override
public Pattern fork() {
return new NoYPattern(this.pattern.fork());
}
} }

View File

@ -1,6 +1,7 @@
package com.fastasyncworldedit.core.function.pattern; package com.fastasyncworldedit.core.function.pattern;
import com.fastasyncworldedit.core.math.MutableBlockVector3; import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.fastasyncworldedit.core.queue.Filter;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.AbstractPattern;
@ -36,4 +37,9 @@ public class NoZPattern extends AbstractPattern {
return pattern.apply(extent, mutable, set); return pattern.apply(extent, mutable, set);
} }
@Override
public Pattern fork() {
return new NoZPattern(this.pattern.fork());
}
} }

View File

@ -60,4 +60,16 @@ public class OffsetPattern extends AbstractPattern {
return pattern.apply(extent, get, mutable); return pattern.apply(extent, get, mutable);
} }
@Override
public BlockVector3 size() {
// Not exactly the "size" but offset should be taken into consideration in most
// places where the "size" matters
return BlockVector3.at(dx, dy, dz);
}
@Override
public Pattern fork() {
return new OffsetPattern(this.pattern.fork(), this.dx, this.dy, this.dz, this.minY, this.maxY);
}
} }

View File

@ -1,7 +1,9 @@
package com.fastasyncworldedit.core.function.pattern; package com.fastasyncworldedit.core.function.pattern;
import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
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.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
@ -9,6 +11,8 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
@ -23,6 +27,7 @@ public class RandomFullClipboardPattern extends AbstractPattern {
private final boolean randomRotate; private final boolean randomRotate;
private final boolean randomFlip; private final boolean randomFlip;
private final Vector3 flipVector = Vector3.at(1, 0, 0).multiply(-2).add(1, 1, 1); private final Vector3 flipVector = Vector3.at(1, 0, 0).multiply(-2).add(1, 1, 1);
private final BlockVector3 size;
/** /**
* Create a new {@link Pattern} instance * Create a new {@link Pattern} instance
@ -34,6 +39,12 @@ public class RandomFullClipboardPattern extends AbstractPattern {
public RandomFullClipboardPattern(List<ClipboardHolder> clipboards, boolean randomRotate, boolean randomFlip) { public RandomFullClipboardPattern(List<ClipboardHolder> clipboards, boolean randomRotate, boolean randomFlip) {
checkNotNull(clipboards); checkNotNull(clipboards);
this.clipboards = clipboards; this.clipboards = clipboards;
MutableBlockVector3 mut = new MutableBlockVector3();
clipboards.stream().flatMap(c -> c.getClipboards().stream()).map(c -> {
Region region = c.getRegion();
return region.getMaximumPoint().subtract(c.getOrigin().getMinimum(region.getMinimumPoint()));
}).forEach(mut::getMaximum);
this.size = mut.toImmutable();
this.randomRotate = randomRotate; this.randomRotate = randomRotate;
this.randomFlip = randomFlip; this.randomFlip = randomFlip;
} }
@ -66,4 +77,9 @@ public class RandomFullClipboardPattern extends AbstractPattern {
throw new IllegalStateException("Incorrect use. This pattern can only be applied to an extent!"); throw new IllegalStateException("Incorrect use. This pattern can only be applied to an extent!");
} }
@Override
public BlockVector3 size() {
return size;
}
} }

View File

@ -72,4 +72,14 @@ public class RandomOffsetPattern extends AbstractPattern {
return pattern.apply(extent, get, mutable); return pattern.apply(extent, get, mutable);
} }
@Override
public BlockVector3 size() {
return BlockVector3.at(dx2, dy2, dz2);
}
@Override
public Pattern fork() {
return new RandomOffsetPattern(this.pattern.fork(), this.dx, this.dy, this.dz, this.minY, this.maxY);
}
} }

View File

@ -63,4 +63,11 @@ public class RelativePattern extends AbstractPattern implements ResettablePatter
origin = null; origin = null;
} }
@Override
public Pattern fork() {
RelativePattern forked = new RelativePattern(this.pattern.fork(), this.minY, this.maxY);
forked.origin = this.origin; // maintain origin for forks
return forked;
}
} }

View File

@ -94,4 +94,9 @@ public class SolidRandomOffsetPattern extends AbstractPattern {
return pattern.apply(extent, get, set); return pattern.apply(extent, get, set);
} }
@Override
public Pattern fork() {
return new SolidRandomOffsetPattern(this.pattern.fork(), this.dx, this.dy, this.dz, this.minY, this.maxY);
}
} }

View File

@ -129,4 +129,14 @@ public class SurfaceRandomOffsetPattern extends AbstractPattern {
return !block.getBlockType().getMaterial().isMovementBlocker(); return !block.getBlockType().getMaterial().isMovementBlocker();
} }
@Override
public BlockVector3 size() {
return BlockVector3.at(moves, moves, moves);
}
@Override
public Pattern fork() {
return new SurfaceRandomOffsetPattern(this.pattern.fork(), this.moves, this.minY, this.maxY);
}
} }

View File

@ -78,6 +78,49 @@ public class BlockVectorSet extends AbstractCollection<BlockVector3> implements
return localMap != null && localMap.contains(x & 2047, ((y + 128) & 511) - 128, z & 2047); return localMap != null && localMap.contains(x & 2047, ((y + 128) & 511) - 128, z & 2047);
} }
@Override
public void setOffset(final int x, final int z) {
// Do nothing
}
@Override
public void setOffset(final int x, final int y, final int z) {
// Do nothing
}
@Override
public boolean containsRadius(final int x, final int y, final int z, final int radius) {
if (radius <= 0) {
return contains(x, y, z);
}
// Quick corners check
if (!contains(x - radius, y, z - radius)) {
return false;
}
if (!contains(x + radius, y, z + radius)) {
return false;
}
if (!contains(x - radius, y, z + radius)) {
return false;
}
if (!contains(x + radius, y, z - radius)) {
return false;
}
// Slow but if someone wants to think of an elegant way then feel free to add it
for (int xx = -radius; xx <= radius; xx++) {
int rx = x + xx;
for (int yy = -radius; yy <= radius; yy++) {
int ry = y + yy;
for (int zz = -radius; zz <= radius; zz++) {
if (contains(rx, ry, z + zz)) {
return true;
}
}
}
}
return false;
}
@Override @Override
public boolean contains(Object o) { public boolean contains(Object o) {
if (o instanceof BlockVector3 v) { if (o instanceof BlockVector3 v) {

View File

@ -100,14 +100,7 @@ public class LocalBlockVectorSet implements BlockVector3Set {
return new LocalBlockVectorSet(offsetX, offsetY, offsetZ, set.clone()); return new LocalBlockVectorSet(offsetX, offsetY, offsetZ, set.clone());
} }
/** @Override
* If a radius is contained by the set
*
* @param x x radius center
* @param y y radius center
* @param z z radius center
* @return if radius is contained by the set
*/
public boolean containsRadius(int x, int y, int z, int radius) { public boolean containsRadius(int x, int y, int z, int radius) {
if (radius <= 0) { if (radius <= 0) {
return contains(x, y, z); return contains(x, y, z);
@ -130,9 +123,11 @@ public class LocalBlockVectorSet implements BlockVector3Set {
return false; return false;
} }
for (int xx = -radius; xx <= radius; xx++) { for (int xx = -radius; xx <= radius; xx++) {
int rx = x + xx;
for (int yy = -radius; yy <= radius; yy++) { for (int yy = -radius; yy <= radius; yy++) {
int ry = y + yy;
for (int zz = -radius; zz <= radius; zz++) { for (int zz = -radius; zz <= radius; zz++) {
if (contains(x + xx, y + yy, z + zz)) { if (contains(rx, ry, z + zz)) {
return true; return true;
} }
} }
@ -141,27 +136,13 @@ public class LocalBlockVectorSet implements BlockVector3Set {
return false; return false;
} }
/** @Override
* Set the offset applied to values when storing and reading to keep the values within -1024 to 1023. Uses default y offset
* of 128 to allow -64 -> 320 world height use.
*
* @param x x offset
* @param z z offset
*/
public void setOffset(int x, int z) { public void setOffset(int x, int z) {
this.offsetX = x; this.offsetX = x;
this.offsetZ = z; this.offsetZ = z;
} }
/** @Override
* Set the offset applied to values when storing and reading to keep the x and z values within -1024 to 1023. Y values
* require keeping withing -256 and 255.
*
* @param x x offset
* @param y y offset
* @param z z offset
* @since 2.2.0
*/
public void setOffset(int x, int y, int z) { public void setOffset(int x, int y, int z) {
this.offsetX = x; this.offsetX = x;
this.offsetY = y; this.offsetY = y;

View File

@ -61,6 +61,22 @@ public class MutableBlockVector3 extends BlockVector3 {
return z; return z;
} }
@Override
public BlockVector3 getMinimum(BlockVector3 v2) {
this.x = Math.min(v2.getX(), x);
this.y = Math.min(v2.getY(), y);
this.z = Math.min(v2.getZ(), z);
return this;
}
@Override
public BlockVector3 getMaximum(BlockVector3 v2) {
this.x = Math.max(v2.getX(), x);
this.y = Math.max(v2.getY(), y);
this.z = Math.max(v2.getZ(), z);
return this;
}
@Override @Override
public MutableBlockVector3 mutX(double x) { public MutableBlockVector3 mutX(double x) {
this.x = (int) x; this.x = (int) x;

View File

@ -51,11 +51,10 @@ public class ExtentTraverser<T extends Extent> {
return last; return last;
} }
@SuppressWarnings("unchecked")
@Nullable @Nullable
public <U> U findAndGet(Class<U> clazz) { public <U extends Extent> U findAndGet(Class<U> clazz) {
ExtentTraverser<Extent> traverser = find(clazz); ExtentTraverser<U> traverser = find(clazz);
return (traverser != null) ? (U) traverser.get() : null; return (traverser != null) ? traverser.get() : null;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -40,6 +40,7 @@ import javax.annotation.Nullable;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam; import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader; import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
@ -58,6 +59,9 @@ import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
@ -94,6 +98,10 @@ import static java.lang.System.arraycopy;
public class MainUtil { public class MainUtil {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
private static final String CURL_USER_AGENT = "curl/8.1.1";
private static final HttpClient HTTP_CLIENT = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.NORMAL)
.build();
public static List<String> filter(String prefix, List<String> suggestions) { public static List<String> filter(String prefix, List<String> suggestions) {
if (prefix.isEmpty()) { if (prefix.isEmpty()) {
@ -523,25 +531,52 @@ public class MainUtil {
} }
public static BufferedImage readImage(InputStream stream) throws IOException { public static BufferedImage readImage(InputStream stream) throws IOException {
Iterator<ImageReader> iter = ImageIO.getImageReaders(stream); final ImageInputStream imageStream = ImageIO.createImageInputStream(stream);
if (imageStream == null) {
throw new IOException("Can't find suitable ImageInputStream");
}
Iterator<ImageReader> iter = ImageIO.getImageReaders(imageStream);
if (!iter.hasNext()) { if (!iter.hasNext()) {
throw new IOException("Could not get image reader from stream."); throw new IOException("Could not get image reader from stream.");
} }
ImageReader reader = iter.next(); ImageReader reader = iter.next();
ImageReadParam param = reader.getDefaultReadParam(); ImageReadParam param = reader.getDefaultReadParam();
reader.setInput(stream, true, true); reader.setInput(imageStream, true, true);
BufferedImage bi; BufferedImage bi;
try { try {
bi = reader.read(0, param); bi = reader.read(0, param);
} finally { } finally {
reader.dispose(); reader.dispose();
stream.close(); stream.close();
imageStream.close();
} }
return MainUtil.toRGB(bi); return MainUtil.toRGB(bi);
} }
public static BufferedImage readImage(URL url) throws IOException { public static BufferedImage readImage(URL url) throws IOException {
return readImage(url.openStream()); try {
final URI uri = url.toURI();
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET();
if (uri.getHost().equalsIgnoreCase("i.imgur.com")) {
requestBuilder = requestBuilder.setHeader("User-Agent", CURL_USER_AGENT);
}
final HttpResponse<InputStream> response = HTTP_CLIENT.send(
requestBuilder.build(),
HttpResponse.BodyHandlers.ofInputStream()
);
try (final InputStream body = response.body()) {
if (response.statusCode() > 299) {
throw new IOException("Expected 2xx as response code, but received " + response.statusCode());
}
return readImage(body);
}
} catch (InterruptedException e) {
throw new IOException("request was interrupted", e);
} catch (URISyntaxException e) {
throw new IOException("failed to parse url to uri reference", e);
}
} }
public static BufferedImage readImage(File file) throws IOException { public static BufferedImage readImage(File file) throws IOException {

View File

@ -9,29 +9,80 @@ import java.util.Set;
public interface BlockVector3Set extends Set<BlockVector3> { public interface BlockVector3Set extends Set<BlockVector3> {
/**
* Get the appropriate {@link BlockVector3Set} implementation for the given region. Either {@link LocalBlockVectorSet} or
* {@link BlockVectorSet}. Sets the offset if using {@link LocalBlockVectorSet}.
*
* @param region Region to get for
* @return Appropriate {@link BlockVector3Set} implementation
*/
static BlockVector3Set getAppropriateVectorSet(Region region) { static BlockVector3Set getAppropriateVectorSet(Region region) {
BlockVector3 max = region.getMaximumPoint(); BlockVector3 max = region.getMaximumPoint();
BlockVector3 min = region.getMinimumPoint(); BlockVector3 min = region.getMinimumPoint();
BlockVector3 size = region.getDimensions(); BlockVector3Set set = getAppropriateVectorSet(region.getDimensions());
// Set default offset as many operations utilising a region are likely to start in a corner, this initialising the
// LocalBlockVectorSet poorly
// This needs to be ceiling as LocalBlockVector extends 1 block further "negative"
int offsetX = (int) Math.ceil((min.getX() + max.getX()) / 2d);
int offsetZ = (int) Math.ceil((min.getZ() + max.getZ()) / 2d);
int offsetY;
if (region.getMinimumY() < -128 || region.getMaximumY() > 320) {
offsetY = (min.getY() + max.getY()) / 2;
} else {
offsetY = 128;
}
set.setOffset(offsetX, offsetY, offsetZ);
return set;
}
/**
* Get the appropriate {@link BlockVector3Set} implementation for the given dimensions. Either {@link LocalBlockVectorSet} or
* {@link BlockVectorSet}. The offset should be manually set.
*
* @param size Dimensions to get for
* @return Appropriate {@link BlockVector3Set} implementation
*/
static BlockVector3Set getAppropriateVectorSet(BlockVector3 size) {
if (size.getBlockX() > 2048 || size.getBlockZ() > 2048 || size.getBlockY() > 512) { if (size.getBlockX() > 2048 || size.getBlockZ() > 2048 || size.getBlockY() > 512) {
return new BlockVectorSet(); return new BlockVectorSet();
} else { } else {
// Set default offset as many operations utilising a region are likely to start in a corner, this initialising the return new LocalBlockVectorSet();
// LocalBlockVectorSet poorly
// This needs to be ceiling as LocalBlockVector extends 1 block further "negative"
int offsetX = (int) Math.ceil((min.getX() + max.getX()) / 2d);
int offsetZ = (int) Math.ceil((min.getZ() + max.getZ()) / 2d);
int offsetY;
if (region.getMinimumY() < -128 || region.getMaximumY() > 320) {
offsetY = (min.getY() + max.getY()) / 2;
} else {
offsetY = 128;
}
return new LocalBlockVectorSet(offsetX, offsetY, offsetZ);
} }
} }
boolean add(int x, int y, int z); boolean add(int x, int y, int z);
boolean contains(int x, int y, int z); boolean contains(int x, int y, int z);
/**
* Set the offset applied to values when storing and reading to keep the values within -1024 to 1023. Uses default y offset
* of 128 to allow -64 -> 320 world height use.
*
* @param x x offset
* @param z z offset
* @since TODO
*/
void setOffset(int x, int z);
/**
* Set the offset applied to values when storing and reading to keep the x and z values within -1024 to 1023. Y values
* require keeping withing -256 and 255.
*
* @param x x offset
* @param y y offset
* @param z z offset
* @since TODO
*/
void setOffset(int x, int y, int z);
/**
* If a radius is contained by the set
*
* @param x x radius center
* @param y y radius center
* @param z z radius center
* @return if radius is contained by the set
* @since TODO
*/
boolean containsRadius(int x, int y, int z, int radius);
} }

View File

@ -235,4 +235,11 @@ public class ForgetfulExtentBuffer extends AbstractDelegateExtent implements Pat
}; };
} }
//FAWE - stateful pattern
@Override
public Pattern fork() {
return new ForgetfulExtentBuffer(extent, mask.copy());
}
//FAWE end
} }

View File

@ -25,6 +25,8 @@ import com.sk89q.worldedit.extent.buffer.ExtentBuffer;
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.Arrays;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
/** /**
@ -64,4 +66,12 @@ public class ExtentBufferedCompositePattern extends AbstractExtentPattern {
return lastBlock; return lastBlock;
} }
//FAWE - stateful pattern
@Override
public Pattern fork() {
final Pattern[] forkedPatterns = Arrays.stream(patterns).map(Pattern::fork).toArray(Pattern[]::new);
return new ExtentBufferedCompositePattern(getExtent(), forkedPatterns);
}
//FAWE end
} }

View File

@ -25,6 +25,7 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility; import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
/** /**
@ -59,6 +60,11 @@ public interface Pattern extends Filter {
apply(block, block, block); apply(block, block, block);
} }
@Override
default Pattern fork() { // covariant return type
return this;
}
//FAWE end //FAWE end
/** /**
@ -69,4 +75,14 @@ public interface Pattern extends Filter {
*/ */
BaseBlock applyBlock(BlockVector3 position); BaseBlock applyBlock(BlockVector3 position);
/**
* Get the likely maximum size of the volume this pattern will affect
*
* @return Pattern size
* @since TODO
*/
default BlockVector3 size() {
return BlockVector3.ONE;
}
} }

View File

@ -67,6 +67,13 @@ public class RandomPattern extends AbstractPattern {
this.collection = RandomCollection.of(weights, random); this.collection = RandomCollection.of(weights, random);
this.patterns = parent.patterns; this.patterns = parent.patterns;
} }
private RandomPattern(SimpleRandom random, Map<Pattern, Double> weights) {
this.random = random;
this.weights = weights;
this.collection = RandomCollection.of(weights, random);
this.patterns = new LinkedHashSet<>(weights.keySet());
}
//FAWE end //FAWE end
/** /**
@ -107,6 +114,14 @@ public class RandomPattern extends AbstractPattern {
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
return collection.next(get.getBlockX(), get.getBlockY(), get.getBlockZ()).apply(extent, get, set); return collection.next(get.getBlockX(), get.getBlockY(), get.getBlockZ()).apply(extent, get, set);
} }
@Override
public Pattern fork() {
final LinkedHashMap<Pattern, Double> newWeights = new LinkedHashMap<>();
this.weights.forEach((p, w) -> newWeights.put(p.fork(), w));
return new RandomPattern(this.random, newWeights);
}
//FAWE end //FAWE end
} }

View File

@ -29,13 +29,16 @@ import com.sk89q.worldedit.world.block.BlockType;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import static com.sk89q.worldedit.blocks.Blocks.resolveProperties; import static com.sk89q.worldedit.blocks.Blocks.resolveProperties;
public class StateApplyingPattern extends AbstractExtentPattern { public class StateApplyingPattern extends AbstractExtentPattern {
private final Map<String, String> states; private final Map<String, String> states;
private final Map<BlockType, Map<Property<Object>, Object>> cache = Maps.newHashMap(); //FAWE - avoid race conditions
private final Map<BlockType, Map<Property<Object>, Object>> cache = new ConcurrentHashMap<>();
//FAWE end
public StateApplyingPattern(Extent extent, Map<String, String> statesToSet) { public StateApplyingPattern(Extent extent, Map<String, String> statesToSet) {
super(extent); super(extent);

View File

@ -85,7 +85,7 @@ public class WorldEditExpressionEnvironment implements ExpressionEnvironment {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@Override @Override
public int getBlockDataRel(double x, double y, double z) { public int getBlockDataRel(double x, double y, double z) {
return extent.getBlock(toWorld(x, y, z)).getBlockType().getLegacyCombinedId() & 0xF; return extent.getBlock(toWorldRel(x, y, z).toBlockPoint()).getBlockType().getLegacyCombinedId() & 0xF;
} }
//FAWE start //FAWE start