Add fuzzy region selection (with mask support)
`//sel fuzzy` or `//sel fuzzy=<mask>` - All connected blocks matching the mask (default is same id/data) will be added. - Left click to select the region - Right click to add to the existing region
This commit is contained in:
parent
f0a36ba1fa
commit
e7d97d030f
@ -149,6 +149,8 @@ public enum BBC {
|
||||
VISITOR_ENTITY("%s0 entities affected", "WorldEdit.Visitor"),
|
||||
VISITOR_FLAT("%s0 columns affected", "WorldEdit.Visitor"),
|
||||
|
||||
SELECTOR_FUZZY_POS1("Region set and expanded from %s0 %s1.", "WorldEdit.Selector"),
|
||||
SELECTOR_FUZZY_POS2("Added expansion of %s0 %s1.", "WorldEdit.Selector"),
|
||||
SELECTOR_CUBOID_POS1("pos1 set to %s0 %s1.", "WorldEdit.Selector"),
|
||||
SELECTOR_CUBOID_POS2("pos2 set to %s0 %s1.", "WorldEdit.Selector"),
|
||||
SELECTOR_INVALID_COORDINATES("Invalid coordinates %s0", "WorldEdit.Selector"),
|
||||
|
@ -4,7 +4,6 @@ import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
||||
import com.boydti.fawe.jnbt.SchematicStreamer;
|
||||
import com.boydti.fawe.object.IntegerTrio;
|
||||
import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.boydti.fawe.object.io.BufferedRandomAccessFile;
|
||||
@ -12,7 +11,6 @@ import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
@ -23,10 +21,8 @@ import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@ -34,7 +30,6 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
/**
|
||||
* A clipboard with disk backed storage. (lower memory + loads on crash)
|
||||
@ -426,17 +421,6 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException{
|
||||
long start = System.currentTimeMillis();
|
||||
File file = new File("C:/Users/Jesse/Desktop/OTHER/mc/plugins/WorldEdit/schematics/50mil.schematic");
|
||||
BufferedInputStream in = new BufferedInputStream(new GZIPInputStream(new BufferedInputStream(new FileInputStream(file))));
|
||||
NBTInputStream nbtin = new NBTInputStream(in);
|
||||
Settings.CLIPBOARD.USE_DISK = true;
|
||||
SchematicStreamer streamer = new SchematicStreamer(nbtin, UUID.randomUUID());
|
||||
streamer.getClipboard();
|
||||
System.out.println(System.currentTimeMillis() - start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(int i, int data) {
|
||||
try {
|
||||
|
@ -1,55 +1,92 @@
|
||||
package com.boydti.fawe.object.regions;
|
||||
|
||||
import com.boydti.fawe.util.EditSessionBuilder;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
||||
import com.sk89q.worldedit.regions.AbstractRegion;
|
||||
import com.sk89q.worldedit.regions.RegionOperationException;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.util.BitSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class MagicRegion extends AbstractRegion {
|
||||
public class FuzzyRegion extends AbstractRegion {
|
||||
|
||||
private final Mask mask;
|
||||
private BitSet set = new BitSet();
|
||||
private boolean populated;
|
||||
private int minX, minY, minZ, maxX, maxY, maxZ;
|
||||
private int offsetX, offsetY, offsetZ;
|
||||
private Extent extent;
|
||||
|
||||
{
|
||||
minX = minY = minZ = Integer.MAX_VALUE;
|
||||
maxX = maxY = maxZ = Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
public MagicRegion(World world) {
|
||||
public FuzzyRegion(World world, Extent editSession, Mask mask) {
|
||||
super(world);
|
||||
this.extent = editSession;
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
public Mask getMask() {
|
||||
return mask;
|
||||
}
|
||||
|
||||
private static int pair(int x, int y, int z) {
|
||||
byte b1 = (byte) y;
|
||||
byte b2 = (byte) (x);
|
||||
byte b3 = (byte) (z);
|
||||
int x16 = (x >> 8) & 0xF;
|
||||
int z16 = (z >> 8) & 0xF;
|
||||
byte b4 = MathMan.pair16(x16, z16);
|
||||
return (b1 & 0xFF)
|
||||
int x16 = (x >> 8) & 0x7;
|
||||
int z16 = (z >> 8) & 0x7;
|
||||
byte b4 = MathMan.pair8(x16, z16);
|
||||
return ((b1 & 0xFF)
|
||||
+ ((b2 & 0xFF) << 8)
|
||||
+ ((b3 & 0xFF) << 16)
|
||||
+ ((b4 & 0xFF) << 24)
|
||||
+ ((b4 & 0x7F) << 24))
|
||||
;
|
||||
}
|
||||
|
||||
public void select(int x, int y, int z) {
|
||||
EditSession editSession = new EditSessionBuilder(getWorld())
|
||||
.limitUnlimited()
|
||||
.changeSetNull()
|
||||
.fastmode(true)
|
||||
.allowedRegionsEverywhere()
|
||||
.checkMemory(false)
|
||||
.autoQueue(false)
|
||||
.build();
|
||||
@Override
|
||||
public int getArea() {
|
||||
return set.length();
|
||||
}
|
||||
|
||||
public void select(int x, int y, int z) {
|
||||
RecursiveVisitor visitor = new RecursiveVisitor(mask, new RegionFunction() {
|
||||
@Override
|
||||
public boolean apply(Vector position) throws WorldEditException {
|
||||
return true;
|
||||
}
|
||||
}) {
|
||||
@Override
|
||||
public boolean isVisited(Node node) {
|
||||
return contains(node.getX(), node.getY(), node.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisited(Node node, int depth) {
|
||||
try {
|
||||
set(node.getX(), node.getY(), node.getZ());
|
||||
} catch (RegionOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanVisited(int layer) {
|
||||
// Do nothing
|
||||
}
|
||||
};
|
||||
visitor.visit(new Vector(x, y, z));
|
||||
Operations.completeBlindly(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -67,13 +104,13 @@ public class MagicRegion extends AbstractRegion {
|
||||
|
||||
@Override
|
||||
public BlockVector next() {
|
||||
int b1 = index & 0xFF;
|
||||
int b2 = (index >> 8) & 0xFF;
|
||||
int b3 = (index >> 16) & 0xFF;
|
||||
byte b4 = (byte) ((index >> 24) & 0xFF);
|
||||
pos.x = offsetX + (((b2 & 0xFF) + ((MathMan.unpair16x(b4)) << 8)) << 20) >> 20;
|
||||
int b1 = ((byte) index) & 0xFF;
|
||||
int b2 = ((byte) (index >> 8)) & 0xFF;
|
||||
int b3 = ((byte)(index >> 16)) & 0xFF;
|
||||
byte b4 = (byte) (index >> 24);
|
||||
pos.x = offsetX + (((b2 + ((MathMan.unpair8x(b4)) << 8)) << 21) >> 21);
|
||||
pos.y = offsetY + b1;
|
||||
pos.z = offsetZ + (((b3) + ((MathMan.unpair16y(b4)) << 8)) << 20) >> 20;
|
||||
pos.z = offsetZ + (((b3 + ((MathMan.unpair8y(b4)) << 8)) << 21) >> 21);
|
||||
return pos;
|
||||
}
|
||||
|
||||
@ -84,13 +121,20 @@ public class MagicRegion extends AbstractRegion {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public void set(int x, int y, int z) throws RegionOperationException{
|
||||
x -= offsetX;
|
||||
y -= offsetY;
|
||||
z -= offsetZ;
|
||||
if (populated) {
|
||||
x -= offsetX;
|
||||
y -= offsetY;
|
||||
z -= offsetZ;
|
||||
} else {
|
||||
offsetX = x;
|
||||
offsetZ = z;
|
||||
x = 0;
|
||||
z = 0;
|
||||
populated = true;
|
||||
}
|
||||
set.set(pair(x, y, z), true);
|
||||
if (x >= 2048 || x <= -2048 || z >= 2048 || z <= -2048) {
|
||||
if (x >= 1024 || x <= -1024 || z >= 1024 || z <= -1024) {
|
||||
throw new RegionOperationException("Selection is too large!");
|
||||
}
|
||||
if (x > maxX) {
|
||||
@ -114,7 +158,11 @@ public class MagicRegion extends AbstractRegion {
|
||||
}
|
||||
|
||||
public boolean contains(int x, int y, int z) {
|
||||
return set.get(pair(x - offsetX, y - offsetY, z - offsetZ));
|
||||
try {
|
||||
return set.get(pair(x - offsetX, y - offsetY, z - offsetZ));
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -154,4 +202,8 @@ public class MagicRegion extends AbstractRegion {
|
||||
maxY += change.getBlockY();
|
||||
maxZ += change.getBlockZ();
|
||||
}
|
||||
|
||||
public void setExtent(EditSession extent) {
|
||||
this.extent = extent;
|
||||
}
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
package com.boydti.fawe.object.regions.selector;
|
||||
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.regions.FuzzyRegion;
|
||||
import com.boydti.fawe.util.EditSessionBuilder;
|
||||
import com.boydti.fawe.util.ExtentTraverser;
|
||||
import com.boydti.fawe.util.MaskTraverser;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.limit.SelectorLimits;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class FuzzyRegionSelector extends AbstractDelegateExtent implements RegionSelector {
|
||||
|
||||
private final Player player;
|
||||
private FuzzyRegion region;
|
||||
private ArrayList<Vector> positions;
|
||||
|
||||
public FuzzyRegionSelector(Player player, @Nullable World world, Mask mask) {
|
||||
super(new EditSessionBuilder(world)
|
||||
.player(FawePlayer.wrap(player))
|
||||
.changeSetNull()
|
||||
.checkMemory(false)
|
||||
.autoQueue(false)
|
||||
.build());
|
||||
this.player = player;
|
||||
this.region = new FuzzyRegion(world, getExtent(), mask);
|
||||
this.positions = new ArrayList<>();
|
||||
new MaskTraverser(mask).reset(getExtent());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return this.region.getWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWorld(@Nullable World world) {
|
||||
EditSession extent = new EditSessionBuilder(world)
|
||||
.player(FawePlayer.wrap(player))
|
||||
.changeSetNull()
|
||||
.checkMemory(false)
|
||||
.autoQueue(false)
|
||||
.build();
|
||||
new ExtentTraverser(this).setNext(extent);
|
||||
this.region.setWorld(world);
|
||||
this.region.setExtent(extent);
|
||||
new MaskTraverser(getMask()).reset(extent);
|
||||
}
|
||||
|
||||
public Mask getMask() {
|
||||
return region.getMask();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean selectPrimary(Vector position, SelectorLimits limits) {
|
||||
positions.clear();
|
||||
positions.add(position);
|
||||
Extent extent = getExtent();
|
||||
if (extent instanceof EditSession) {
|
||||
((EditSession) extent).resetLimit();
|
||||
}
|
||||
new MaskTraverser(getMask()).reset(extent);
|
||||
this.region = new FuzzyRegion(getWorld(), getExtent(), getMask());
|
||||
this.region.select((int) position.x, (int) position.y, (int) position.z);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean selectSecondary(Vector position, SelectorLimits limits) {
|
||||
this.positions.add(position);
|
||||
new MaskTraverser(getMask()).reset(getExtent());
|
||||
this.region.select((int) position.x, (int) position.y, (int) position.z);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void explainPrimarySelection(Actor actor, LocalSession session, Vector position) {
|
||||
int size = this.region.getArea();
|
||||
BBC.SELECTOR_FUZZY_POS1.send(player, position, "(" + region.getArea() + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void explainSecondarySelection(Actor actor, LocalSession session, Vector position) {
|
||||
int size = this.region.getArea();
|
||||
BBC.SELECTOR_FUZZY_POS2.send(player, position, "(" + region.getArea() + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void explainRegionAdjust(Actor actor, LocalSession session) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector getPrimaryPosition() throws IncompleteRegionException {
|
||||
if (positions.isEmpty()) {
|
||||
throw new IncompleteRegionException();
|
||||
}
|
||||
return new BlockVector(positions.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region getRegion() throws IncompleteRegionException {
|
||||
return region;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region getIncompleteRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefined() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArea() {
|
||||
return region.getArea();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void learnChanges() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
positions.clear();
|
||||
this.region = new FuzzyRegion(getWorld(), getExtent(), getMask());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return "fuzzy";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getInformationLines() {
|
||||
final List<String> lines = new ArrayList<String>();
|
||||
for (int i = 0; i < positions.size(); i++) {
|
||||
lines.add("Position " + i + ": " + positions.get(i));
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
package com.boydti.fawe.object.regions.selector;
|
||||
|
||||
import com.boydti.fawe.object.regions.MagicRegion;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.limit.SelectorLimits;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class MagicRegionSelector implements RegionSelector {
|
||||
|
||||
private MagicRegion region;
|
||||
|
||||
public MagicRegionSelector(@Nullable World world, Vector pos) {
|
||||
this.region = new MagicRegion(world);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return this.region.getWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWorld(@Nullable World world) {
|
||||
this.region.setWorld(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean selectPrimary(Vector position, SelectorLimits limits) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean selectSecondary(Vector position, SelectorLimits limits) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void explainPrimarySelection(Actor actor, LocalSession session, Vector position) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void explainSecondarySelection(Actor actor, LocalSession session, Vector position) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void explainRegionAdjust(Actor actor, LocalSession session) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector getPrimaryPosition() throws IncompleteRegionException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region getRegion() throws IncompleteRegionException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region getIncompleteRegion() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefined() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArea() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void learnChanges() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getInformationLines() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -92,6 +92,18 @@ public class MathMan {
|
||||
return (byte) ((value >> 4) & 0xF);
|
||||
}
|
||||
|
||||
public static final byte pair8(int x, int y) {
|
||||
return (byte) (x + (y << 3));
|
||||
}
|
||||
|
||||
public static byte unpair8x(byte value) {
|
||||
return (byte) (value & 0x7);
|
||||
}
|
||||
|
||||
public static byte unpair8y(byte value) {
|
||||
return (byte) ((value >> 3) & 0x7F);
|
||||
}
|
||||
|
||||
public static final int lossyFastDivide(int a, int b) {
|
||||
return (a*((1<<16)/b))>>16;
|
||||
}
|
||||
|
@ -360,6 +360,10 @@ public class EditSession extends AbstractWorld implements HasFaweQueue {
|
||||
return originalLimit;
|
||||
}
|
||||
|
||||
public void resetLimit() {
|
||||
this.limit = this.originalLimit.copy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new limit representing how much of this edit's limit has been used so far
|
||||
* @return
|
||||
|
@ -20,6 +20,8 @@
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.mask.IdMask;
|
||||
import com.boydti.fawe.object.regions.selector.FuzzyRegionSelector;
|
||||
import com.google.common.base.Optional;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
@ -35,8 +37,10 @@ import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockType;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionOperationException;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
@ -56,11 +60,11 @@ import com.sk89q.worldedit.util.formatting.StyledFragment;
|
||||
import com.sk89q.worldedit.util.formatting.component.CommandListBox;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.storage.ChunkStore;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
|
||||
|
||||
@ -748,6 +752,20 @@ public class SelectionCommands {
|
||||
if (limit.isPresent()) {
|
||||
player.print(limit.get() + " points maximum.");
|
||||
}
|
||||
} else if (typeName.startsWith("fuzzy") || typeName.startsWith("magic")) {
|
||||
Mask mask;
|
||||
if (typeName.length() > 6) {
|
||||
ParserContext parserContext = new ParserContext();
|
||||
parserContext.setActor(player);
|
||||
parserContext.setWorld(player.getWorld());
|
||||
parserContext.setSession(session);
|
||||
parserContext.setExtent(editSession);
|
||||
mask = we.getMaskFactory().parseFromInput(typeName.substring(6),parserContext);
|
||||
} else {
|
||||
mask = new IdMask(editSession);
|
||||
}
|
||||
selector = new FuzzyRegionSelector(player, editSession, mask);
|
||||
player.print("Fuzzy selector: Left click to select all contingent blocks, right click to add");
|
||||
} else {
|
||||
CommandListBox box = new CommandListBox("Selection modes");
|
||||
StyledFragment contents = box.getContents();
|
||||
@ -761,6 +779,7 @@ public class SelectionCommands {
|
||||
box.appendCommand("sphere", "Select a sphere");
|
||||
box.appendCommand("cyl", "Select a cylinder");
|
||||
box.appendCommand("convex", "Select a convex polyhedral");
|
||||
box.appendCommand("fuzzy[=<mask>]", "Select all connected blocks");
|
||||
|
||||
player.printRaw(ColorCodeBuilder.asColorCodes(box));
|
||||
return;
|
||||
|
@ -58,10 +58,38 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
|
||||
public void visit(final Vector pos) {
|
||||
Node node = new Node((int) pos.x, (int) pos.y, (int) pos.z);
|
||||
if (!this.visited.containsKey(node)) {
|
||||
if (!isVisited(node)) {
|
||||
isVisitable(pos, pos); // Ignore this, just to initialize mask on this point
|
||||
visited.put(node, 0);
|
||||
queue.add(node);
|
||||
addVisited(node, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void addVisited(Node node, int depth) {
|
||||
visited.put(node, depth);
|
||||
}
|
||||
|
||||
public boolean isVisited(Node node) {
|
||||
return visited.containsKey(node);
|
||||
}
|
||||
|
||||
public void cleanVisited(int layer) {
|
||||
if (layer == Integer.MAX_VALUE) {
|
||||
visited.clear();
|
||||
return;
|
||||
}
|
||||
int size = visited.size();
|
||||
if (size > 16384) {
|
||||
Iterator<Map.Entry<Node, Integer>> iter = visited.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Map.Entry<Node, Integer> entry = iter.next();
|
||||
Integer val = entry.getValue();
|
||||
if (val < layer) {
|
||||
iter.remove();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,7 +104,7 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
for (int layer = 0; !queue.isEmpty() && layer <= maxDepth; layer++) {
|
||||
int size = queue.size();
|
||||
if (layer == maxDepth) {
|
||||
visited.clear();
|
||||
cleanVisited(Integer.MAX_VALUE);
|
||||
for (Node current : queue) {
|
||||
mutable.x = current.getX();
|
||||
mutable.y = current.getY();
|
||||
@ -99,27 +127,15 @@ public abstract class BreadthFirstSearch implements Operation {
|
||||
mutable2.z = from.getZ() + direction.z;
|
||||
if (isVisitable(mutable, mutable2)) {
|
||||
adjacent = new Node(mutable2.getBlockX(), mutable2.getBlockY(), mutable2.getBlockZ());
|
||||
if (!visited.containsKey(adjacent)) {
|
||||
visited.put(adjacent, layer);
|
||||
if (!isVisited(adjacent)) {
|
||||
addVisited(adjacent, layer);
|
||||
queue.add(adjacent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int lastLayer = layer - 1;
|
||||
size = visited.size();
|
||||
if (shouldTrim || (shouldTrim = size > 16384)) {
|
||||
Iterator<Map.Entry<Node, Integer>> iter = visited.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Map.Entry<Node, Integer> entry = iter.next();
|
||||
Integer val = entry.getValue();
|
||||
if (val < lastLayer) {
|
||||
iter.remove();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
cleanVisited(lastLayer);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user