Various minor

Fix surfacespread pattern
Add schematic loadall
Fix brush reset
This commit is contained in:
Jesse Boyd 2017-04-10 20:41:07 +10:00
parent e79559650f
commit eef3eff310
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
11 changed files with 197 additions and 62 deletions

View File

@ -105,6 +105,7 @@ public enum BBC {
SELECTION_SHIFT("Region shifted", "WorldEdit.Selection"),
SELECTION_CLEARED("Selection cleared", "WorldEdit.Selection"),
BRUSH_RESET("Reset your brush.", "WorldEdit.Brush"),
BRUSH_NONE("You aren't holding a brush!", "WorldEdit.Brush"),
BRUSH_SCROLL_ACTION_SET("Set scroll action to %s0", "WorldEdit.Brush"),
BRUSH_VISUAL_MODE_SET("Set visual mode to %s0", "WorldEdit.Brush"),

View File

@ -13,6 +13,7 @@ import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks;
@ -28,9 +29,11 @@ public class CopyPastaBrush implements Brush, ResettableTool {
private final LocalSession session;
private final boolean randomRotate;
private final Player player;
public CopyPastaBrush(LocalSession session, boolean randomRotate) {
public CopyPastaBrush(Player player, LocalSession session, boolean randomRotate) {
session.setClipboard(null);
this.player = player;
this.session = session;
this.randomRotate = randomRotate;
}
@ -38,6 +41,7 @@ public class CopyPastaBrush implements Brush, ResettableTool {
@Override
public boolean reset() {
session.setClipboard(null);
BBC.BRUSH_RESET.send(player);
return true;
}

View File

@ -0,0 +1,37 @@
package com.boydti.fawe.object.clipboard;
import com.boydti.fawe.object.PseudoRandom;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.registry.WorldData;
public class MultiClipboardHolder extends ClipboardHolder{
private final ClipboardHolder[] holders;
private ClipboardHolder holder;
public MultiClipboardHolder(WorldData worldData, ClipboardHolder... holders) {
super(holders[0].getClipboard(), worldData);
holder = holders[0];
this.holders = holders;
}
@Override
public Clipboard getClipboard() {
holder = holders[PseudoRandom.random.nextInt(holders.length)];
return holder.getClipboard();
}
@Override
public Transform getTransform() {
return holder.getTransform();
}
@Override
public void setTransform(Transform transform) {
holder.setTransform(transform);
}
}

View File

@ -5,6 +5,7 @@ import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.BlockMask;
import java.util.Arrays;
import java.util.Collection;
/**
@ -14,6 +15,10 @@ public class AdjacentAnyMask extends BlockMask {
private MutableBlockVector mutable = new MutableBlockVector();
public AdjacentAnyMask(Extent extent, BaseBlock... blocks) {
this(extent, Arrays.asList(blocks));
}
public AdjacentAnyMask(Extent extent, Collection<BaseBlock> blocks) {
super(extent, blocks);
}

View File

@ -4,65 +4,124 @@ import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.PseudoRandom;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.BreadthFirstSearch;
public class SurfaceRandomOffsetPattern extends AbstractPattern {
private final PseudoRandom r = new PseudoRandom();
private final int dx, dy, dz, dx2, dy2, dz2;
private final Pattern pattern;
private final MutableBlockVector mutable = new MutableBlockVector();
boolean[] solid;
private final Extent extent;
public SurfaceRandomOffsetPattern(Pattern pattern, int dx, int dy, int dz) {
private int moves;
private final MutableBlockVector cur = new MutableBlockVector();
private final MutableBlockVector[] buffer;
private final MutableBlockVector[] allowed;
private MutableBlockVector next;
public SurfaceRandomOffsetPattern(Extent extent, Pattern pattern, int distance) {
this.pattern = pattern;
this.dx = dx;
this.dy = dy;
this.dz = dz;
this.dx2 = dx * 2 + 1;
this.dy2 = dy * 2 + 1;
this.dz2 = dz * 2 + 1;
solid = new boolean[Character.MAX_VALUE + 1];
for (int id = 0; id < 4096; id++) {
for (int data = 0; data < 16; data++) {
if (!BlockType.canPassThrough(id, data)) {
solid[FaweCache.getCombined(id, data)] = true;
}
}
this.extent = extent;
this.moves = Math.min(255, distance);
this.buffer = new MutableBlockVector[BreadthFirstSearch.DIAGONAL_DIRECTIONS.length];
for (int i = 0; i < buffer.length; i++) {
buffer[i] = new MutableBlockVector();
}
allowed = new MutableBlockVector[buffer.length];
}
@Override
public BaseBlock apply(Vector position) {
mutable.mutX((position.getX() + r.nextInt(dx2) - dx));
mutable.mutY((position.getY() + r.nextInt(dy2) - dy));
mutable.mutZ((position.getZ() + r.nextInt(dz2) - dz));
BaseBlock block = pattern.apply(mutable);
if (solid[FaweCache.getCombined(block)]) {
mutable.mutY(mutable.getY() + 1);
if (!solid[FaweCache.getCombined(pattern.apply(mutable))]) {
return block;
}
}
return pattern.apply(position);
return pattern.apply(travel(position));
}
@Override
public boolean apply(Extent extent, Vector set, Vector get) throws WorldEditException {
mutable.mutX((get.getX() + r.nextInt(dx2) - dx));
mutable.mutY((get.getY() + r.nextInt(dy2) - dy));
mutable.mutZ((get.getZ() + r.nextInt(dz2) - dz));
BaseBlock block = pattern.apply(mutable);
if (solid[FaweCache.getCombined(block)]) {
mutable.mutY(mutable.getY() + 1);
if (!solid[FaweCache.getCombined(pattern.apply(mutable))]) {
return pattern.apply(extent, set, mutable);
private Vector travel(Vector pos) {
cur.setComponents(pos);
for (int move = 0; move < moves; move++) {
int index = 0;
for (int i = 0; i < allowed.length; i++) {
next = buffer[i];
Vector dir = BreadthFirstSearch.DIAGONAL_DIRECTIONS[i];
next.setComponents(cur.getBlockX() + dir.getBlockX(), cur.getBlockY() + dir.getBlockY(), cur.getBlockZ() + dir.getBlockZ());
if (allowed(next)) {
allowed[index++] = next;
}
}
return pattern.apply(extent, set, get);
if (index == 0) {
return cur;
}
next = allowed[PseudoRandom.random.nextInt(index)];
cur.setComponents(next.getBlockX(), next.getBlockY(), next.getBlockZ());
}
return cur;
}
private boolean allowed(Vector v) {
BaseBlock block = pattern.apply(v);
if (FaweCache.canPassThrough(block.getId(), block.getData())) {
return false;
}
int x = v.getBlockX();
int y = v.getBlockY();
int z = v.getBlockZ();
v.mutY(y + 1);
if (canPassthrough(v)) { v.mutY(y); return true; }
v.mutY(y - 1);
if (canPassthrough(v)) { v.mutY(y); return true; }
v.mutY(y);
v.mutX(x + 1);
if (canPassthrough(v)) { v.mutX(x); return true; }
v.mutX(x - 1);
if (canPassthrough(v)) { v.mutX(x); return true; }
v.mutX(x);
v.mutZ(z + 1);
if (canPassthrough(v)) { v.mutZ(z); return true; }
v.mutZ(z - 1);
if (canPassthrough(v)) { v.mutZ(z); return true; }
v.mutZ(z);
return false;
}
private boolean canPassthrough(Vector v) {
BaseBlock block = pattern.apply(v);
return FaweCache.canPassThrough(block.getId(), block.getData());
}
//
// @Override
// public BaseBlock apply(Vector position) {
// mutable.mutX((position.getX() + r.nextInt(dx2) - dx));
// mutable.mutY((position.getY() + r.nextInt(dy2) - dy));
// mutable.mutZ((position.getZ() + r.nextInt(dz2) - dz));
// BaseBlock block = pattern.apply(mutable);
// if (solid[FaweCache.getCombined(block)]) {
// if (solid[FaweCache.getCombined(mutable)])
// mutable.mutY(mutable.getY() + 1);
// if (!solid[FaweCache.getCombined(pattern.apply(mutable))]) {
// return block;
// }
// }
// return pattern.apply(position);
// }
//
// private Vector get(Vector input) {
// for (dir :
// BreadthFirstSearch.DIAGONAL_DIRECTIONS)
// }
//
// @Override
// public boolean apply(Extent extent, Vector set, Vector get) throws WorldEditException {
// mutable.mutX((get.getX() + r.nextInt(dx2) - dx));
// mutable.mutY((get.getY() + r.nextInt(dy2) - dy));
// mutable.mutZ((get.getZ() + r.nextInt(dz2) - dz));
// BaseBlock block = pattern.apply(mutable);
// if (solid[FaweCache.getCombined(block)]) {
// mutable.mutY(mutable.getY() + 1);
// if (!solid[FaweCache.getCombined(pattern.apply(mutable))]) {
// return pattern.apply(extent, set, mutable);
// }
// }
// return pattern.apply(extent, set, get);
// }
}

View File

@ -29,6 +29,10 @@ public class MutableBlockVector extends BlockVector {
super(0, 0, 0);
}
public MutableBlockVector setComponents(Vector other) {
return setComponents(other.getBlockX(), other.getBlockY(), other.getBlockZ());
}
@Override
public MutableBlockVector setComponents(double x, double y, double z) {
return this.setComponents((int) x, (int) y, (int) z);

View File

@ -895,7 +895,7 @@ public class BrushCommands {
worldEdit.checkMaxBrushRadius(radius);
BrushTool tool = session.getBrushTool(player);
tool.setSize(radius);
tool.setBrush(new CopyPastaBrush(session, rotate), "worldedit.brush.copy", player);
tool.setBrush(new CopyPastaBrush(player, session, rotate), "worldedit.brush.copy", player);
player.print(BBC.getPrefix() + BBC.BRUSH_COPY.f(radius));
}

View File

@ -21,6 +21,7 @@ package com.sk89q.worldedit.command;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
import com.boydti.fawe.object.schematic.StructureFormat;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MathMan;
@ -89,6 +90,28 @@ public class SchematicCommands {
this.worldEdit = worldEdit;
}
@Command(aliases = { "loadall" }, usage = "[<format>] <filename|url>", desc = "Load a schematic into your clipboard")
@Deprecated
@CommandPermissions({ "worldedit.clipboard.load", "worldedit.schematic.load", "worldedit.schematic.upload" })
public void loadall(final Player player, final LocalSession session, @Optional("schematic") final String formatName, final String filename) throws FilenameException {
final ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
if (format == null) {
BBC.CLIPBOARD_INVALID_FORMAT.send(player, formatName);
return;
}
try {
WorldData wd = player.getWorld().getWorldData();
ClipboardHolder[] all = format.loadAllFromInput(player, wd, filename, true);
if (all != null) {
MultiClipboardHolder multi = new MultiClipboardHolder(wd, all);
session.setClipboard(multi);
BBC.SCHEMATIC_LOADED.send(player, filename);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Command(aliases = { "load" }, usage = "[<format>] <filename>", desc = "Load a schematic into your clipboard")
@Deprecated
@CommandPermissions({ "worldedit.clipboard.load", "worldedit.schematic.load", "worldedit.schematic.upload" })
@ -96,7 +119,7 @@ public class SchematicCommands {
final LocalConfiguration config = this.worldEdit.getConfiguration();
final ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
if (format == null) {
player.printError("Unknown schematic format: " + formatName);
BBC.CLIPBOARD_INVALID_FORMAT.send(player, formatName);
return;
}
InputStream in = null;

View File

@ -598,9 +598,8 @@ public class UtilityCommands {
}
if (effectiveLength > 0) {
String cat = args.getString(0);
ArrayList<CommandMapping> mappings = grouped.get(cat);
ArrayList<CommandMapping> mappings = effectiveLength == 1 ? grouped.get(cat) : null;
if (mappings == null) {
System.out.println("Aliases not found!");
// Drill down to the command
for (int i = 0; i < effectiveLength; i++) {
String command = args.getString(i);
@ -624,8 +623,6 @@ public class UtilityCommands {
return;
}
}
effectiveLength--;
visited.add(args.getString(i));
isRootLevel = false;
} else {
@ -641,7 +638,6 @@ public class UtilityCommands {
dispatcher = (Dispatcher) callable;
aliases = new ArrayList<CommandMapping>(dispatcher.getCommands());
} else {
System.out.println("Set aliases " + aliases);
aliases = mappings;
}
page = Math.max(0, page);
@ -683,9 +679,7 @@ public class UtilityCommands {
for (CommandMapping mapping : list) {
CommandCallable c = mapping.getCallable();
StringBuilder s1 = new StringBuilder();
if (isRootLevel) {
s1.append("/");
}
if (!visited.isEmpty()) {
s1.append(Joiner.on(" ").join(visited));
s1.append(" ");

View File

@ -6,6 +6,7 @@ import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.brush.BrushSettings;
import com.boydti.fawe.object.brush.MovableTool;
import com.boydti.fawe.object.brush.ResettableTool;
import com.boydti.fawe.object.brush.TargetMode;
import com.boydti.fawe.object.brush.scroll.ScrollAction;
import com.boydti.fawe.object.brush.scroll.ScrollTool;
@ -40,7 +41,7 @@ import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool {
public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool, ResettableTool {
public enum BrushAction {
PRIMARY,
@ -133,6 +134,15 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
return getContext().sourceMask;
}
@Override
public boolean reset() {
Brush br = getBrush();
if (br instanceof ResettableTool) {
return ((ResettableTool) br).reset();
}
return false;
}
/**
* Set the block filter used for identifying blocks to replace.
*

View File

@ -245,15 +245,13 @@ public class HashTagPatternParser extends FaweParser<Pattern> {
}
case "#surfacespread": {
try {
List<String> split3 = suggestRemaining(rest, "#surfacespread", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());
rest = StringMan.join(split3.subList(3, split3.size()), ":");
List<String> split3 = suggestRemaining(rest, "#surfacespread", "<distance>", "<pattern>");
int dist = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
rest = StringMan.join(split3.subList(1, split3.size()), ":");
Pattern pattern = catchSuggestion(input, rest, context);
return new SurfaceRandomOffsetPattern(pattern, x, y, z);
return new SurfaceRandomOffsetPattern(Request.request().getExtent(), pattern, dist);
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
throw new SuggestInputParseException(null, "#surfacespread:<dx>:<dy>:<dz>:<pattern>");
throw new SuggestInputParseException(null, "#surfacespread:<distance>:<pattern>");
}
}
case "#solidspread": {