mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-22 17:27:38 +00:00
fix: introduce approx size to patterns and use in ScatterBrush (#2631)
* fix: introduce approx size to patterns and use in ScatterBrush - fixes #2610 * Do not use patternsize in blockvectorset offset
This commit is contained in:
parent
b60a0c532c
commit
23bcdb0409
@ -5,6 +5,7 @@ import com.fastasyncworldedit.core.function.mask.RadiusMask;
|
||||
import com.fastasyncworldedit.core.function.mask.SurfaceMask;
|
||||
import com.fastasyncworldedit.core.math.BlockVectorSet;
|
||||
import com.fastasyncworldedit.core.math.LocalBlockVectorSet;
|
||||
import com.fastasyncworldedit.core.util.collection.BlockVector3Set;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.command.tool.brush.Brush;
|
||||
@ -64,8 +65,9 @@ public class ScatterBrush implements Brush {
|
||||
length = 1;
|
||||
visited.add(position);
|
||||
}
|
||||
LocalBlockVectorSet placed = new LocalBlockVectorSet();
|
||||
placed.setOffset(position.getX(), position.getZ());
|
||||
BlockVector3 patternSize = pattern.size();
|
||||
BlockVector3Set placed = BlockVector3Set.getAppropriateVectorSet(patternSize.add(distance, distance, distance));
|
||||
placed.setOffset(position.getX(), position.getY(), position.getZ());
|
||||
int maxFails = 1000;
|
||||
for (int i = 0; i < count; i++) {
|
||||
int index = ThreadLocalRandom.current().nextInt(length);
|
||||
@ -88,7 +90,20 @@ public class ScatterBrush implements Brush {
|
||||
finish(editSession, placed, position, pattern, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link ScatterBrush#finish(EditSession, BlockVector3Set, BlockVector3, Pattern, double)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "TODO")
|
||||
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) {
|
||||
@ -99,8 +114,23 @@ public class ScatterBrush implements Brush {
|
||||
return surface.direction(pt);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link ScatterBrush#apply(EditSession, BlockVector3Set, BlockVector3, Pattern, double)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "TODO")
|
||||
public void apply(EditSession editSession, LocalBlockVectorSet placed, BlockVector3 pt, Pattern p, double size) throws
|
||||
MaxChangedBlocksException {
|
||||
apply(editSession, (BlockVector3Set) placed, pt, p, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the scatter brush to a given position
|
||||
*
|
||||
* @since TODO
|
||||
*/
|
||||
public void apply(EditSession editSession, BlockVector3Set placed, BlockVector3 pt, Pattern p, double size) throws
|
||||
MaxChangedBlocksException {
|
||||
editSession.setBlock(pt, p);
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package com.fastasyncworldedit.core.command.tool.brush;
|
||||
import com.fastasyncworldedit.core.function.mask.SurfaceMask;
|
||||
import com.fastasyncworldedit.core.math.LocalBlockVectorSet;
|
||||
import com.fastasyncworldedit.core.math.MutableBlockVector3;
|
||||
import com.fastasyncworldedit.core.util.collection.BlockVector3Set;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
@ -24,7 +25,7 @@ public class ShatterBrush extends ScatterBrush {
|
||||
@Override
|
||||
public void apply(
|
||||
final EditSession editSession,
|
||||
final LocalBlockVectorSet placed,
|
||||
final BlockVector3Set placed,
|
||||
final BlockVector3 position,
|
||||
Pattern p,
|
||||
double size
|
||||
@ -34,7 +35,7 @@ public class ShatterBrush extends ScatterBrush {
|
||||
@Override
|
||||
public void finish(
|
||||
EditSession editSession,
|
||||
LocalBlockVectorSet placed,
|
||||
BlockVector3Set placed,
|
||||
final BlockVector3 position,
|
||||
Pattern pattern,
|
||||
double size
|
||||
|
@ -60,6 +60,13 @@ public class OffsetPattern extends AbstractPattern {
|
||||
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);
|
||||
|
@ -1,7 +1,9 @@
|
||||
package com.fastasyncworldedit.core.function.pattern;
|
||||
|
||||
import com.fastasyncworldedit.core.math.MutableBlockVector3;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.pattern.AbstractPattern;
|
||||
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.transform.AffineTransform;
|
||||
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.world.block.BaseBlock;
|
||||
|
||||
@ -23,6 +27,7 @@ public class RandomFullClipboardPattern extends AbstractPattern {
|
||||
private final boolean randomRotate;
|
||||
private final boolean randomFlip;
|
||||
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
|
||||
@ -34,6 +39,12 @@ public class RandomFullClipboardPattern extends AbstractPattern {
|
||||
public RandomFullClipboardPattern(List<ClipboardHolder> clipboards, boolean randomRotate, boolean randomFlip) {
|
||||
checkNotNull(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.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!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -72,6 +72,11 @@ public class RandomOffsetPattern extends AbstractPattern {
|
||||
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);
|
||||
|
@ -129,6 +129,11 @@ public class SurfaceRandomOffsetPattern extends AbstractPattern {
|
||||
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);
|
||||
|
@ -78,6 +78,49 @@ public class BlockVectorSet extends AbstractCollection<BlockVector3> implements
|
||||
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
|
||||
public boolean contains(Object o) {
|
||||
if (o instanceof BlockVector3 v) {
|
||||
|
@ -100,14 +100,7 @@ public class LocalBlockVectorSet implements BlockVector3Set {
|
||||
return new LocalBlockVectorSet(offsetX, offsetY, offsetZ, set.clone());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@Override
|
||||
public boolean containsRadius(int x, int y, int z, int radius) {
|
||||
if (radius <= 0) {
|
||||
return contains(x, y, z);
|
||||
@ -130,9 +123,11 @@ public class LocalBlockVectorSet implements BlockVector3Set {
|
||||
return false;
|
||||
}
|
||||
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(x + xx, y + yy, z + zz)) {
|
||||
if (contains(rx, ry, z + zz)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -141,27 +136,13 @@ public class LocalBlockVectorSet implements BlockVector3Set {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@Override
|
||||
public void setOffset(int x, int z) {
|
||||
this.offsetX = x;
|
||||
this.offsetZ = 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 2.2.0
|
||||
*/
|
||||
@Override
|
||||
public void setOffset(int x, int y, int z) {
|
||||
this.offsetX = x;
|
||||
this.offsetY = y;
|
||||
|
@ -61,6 +61,22 @@ public class MutableBlockVector3 extends BlockVector3 {
|
||||
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
|
||||
public MutableBlockVector3 mutX(double x) {
|
||||
this.x = (int) x;
|
||||
|
@ -9,29 +9,80 @@ import java.util.Set;
|
||||
|
||||
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) {
|
||||
BlockVector3 max = region.getMaximumPoint();
|
||||
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) {
|
||||
return new BlockVectorSet();
|
||||
} else {
|
||||
// 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;
|
||||
}
|
||||
return new LocalBlockVectorSet(offsetX, offsetY, offsetZ);
|
||||
return new LocalBlockVectorSet();
|
||||
}
|
||||
}
|
||||
boolean add(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);
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.internal.util.NonAbstractForCompatibility;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
|
||||
/**
|
||||
@ -74,4 +75,14 @@ public interface Pattern extends Filter {
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user