Masking changes
Add light related masks - #opacity - #brightness - #blocklight - #skylight - #light - #nolight - #haslight Add mask tab completion Add source masks - `/gsmask` and `/smask` - Masking the source instead of the destination (e.g. with //paste) - if there is no source, the current block/extent will be used
This commit is contained in:
parent
bde4749e2c
commit
30700559db
44
core/src/main/java/com/boydti/fawe/command/MaskBinding.java
Normal file
44
core/src/main/java/com/boydti/fawe/command/MaskBinding.java
Normal file
@ -0,0 +1,44 @@
|
||||
package com.boydti.fawe.command;
|
||||
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.StringMan;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.extension.factory.DefaultMaskParser;
|
||||
import com.sk89q.worldedit.util.command.parametric.ParameterData;
|
||||
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class MaskBinding extends FaweBinding {
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
public MaskBinding(WorldEdit worldEdit) {
|
||||
super(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(ParameterData parameter, String prefix) {
|
||||
int index = prefix.lastIndexOf(",");
|
||||
String start = index != -1 ? prefix.substring(0, index) : "";
|
||||
String current = index != -1 ? prefix.substring(index) : prefix;
|
||||
if (current.isEmpty()) {
|
||||
return MainUtil.prepend(start, Arrays.asList(DefaultMaskParser.ALL_MASKS));
|
||||
}
|
||||
if (current.startsWith("#") || current.startsWith("=")) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
if (StringMan.isAlphanumeric(current.charAt(0) + "")) {
|
||||
String[] split2 = current.split(":");
|
||||
if (split2.length == 2 || current.endsWith(":")) {
|
||||
start = (start.isEmpty() ? split2[0] : start + " " + split2[0]) + ":";
|
||||
current = split2.length == 2 ? split2[1] : "";
|
||||
return MainUtil.prepend(start, MainUtil.filter(current, BundledBlockData.getInstance().getBlockStates(split2[0])));
|
||||
}
|
||||
List<String> blocks = BundledBlockData.getInstance().getBlockNames(split2[0]);
|
||||
return MainUtil.prepend(start, blocks);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
@ -50,6 +50,8 @@ public enum BBC {
|
||||
|
||||
MASK_DISABLED("Global mask disabled", "WorldEdit.General"),
|
||||
MASK("Global mask set", "WorldEdit.General"),
|
||||
SOURCE_MASK_DISABLED("Global source mask disabled", "WorldEdit.General"),
|
||||
SOURCE_MASK("Global source mask set", "WorldEdit.General"),
|
||||
TRANSFORM_DISABLED("Global transform disabled", "WorldEdit.General"),
|
||||
TRANSFORM("Global transform set", "WorldEdit.General"),
|
||||
|
||||
@ -85,6 +87,7 @@ public enum BBC {
|
||||
SELECTION_CLEARED("Selection cleared", "WorldEdit.Selection"),
|
||||
SELECTION_NONE("Make a region selection first", "WorldEdit.Selection"),
|
||||
|
||||
BRUSH_NONE("You aren't holding a brush!", "WorldEdit.Brush"),
|
||||
BRUSH_BUTCHER("Butcher brush equiped (%s0)", "WorldEdit.Brush"),
|
||||
BRUSH_CLIPBOARD("Clipboard brush shape equipped", "WorldEdit.Brush"),
|
||||
BRUSH_CYLINDER("Cylinder brush shape equipped (%s0 by %s1).", "WorldEdit.Brush"),
|
||||
@ -110,6 +113,8 @@ public enum BBC {
|
||||
BRUSH_RANGE("Brush size set", "WorldEdit.Brush"),
|
||||
BRUSH_MASK_DISABLED("Brush mask disabled", "WorldEdit.Brush"),
|
||||
BRUSH_MASK("Brush mask set", "WorldEdit.Brush"),
|
||||
BRUSH_SOURCE_MASK_DISABLED("Brush source mask disabled", "WorldEdit.Brush"),
|
||||
BRUSH_SOURCE_MASK("Brush source mask set", "WorldEdit.Brush"),
|
||||
BRUSH_TRANSFORM_DISABLED("Brush transform disabled", "WorldEdit.Brush"),
|
||||
BRUSH_TRANSFORM("Brush transform set", "WorldEdit.Brush"),
|
||||
BRUSH_MATERIAL("Brush material set", "WorldEdit.Brush"),
|
||||
|
@ -30,6 +30,7 @@ public class DoubleActionBrushTool implements DoubleActionTraceTool {
|
||||
protected static int MAX_RANGE = 500;
|
||||
protected int range = -1;
|
||||
private Mask mask = null;
|
||||
private Mask sourceMask = null;
|
||||
private ResettableExtent transform = null;
|
||||
private DoubleActionBrush brush = null;
|
||||
@Nullable
|
||||
@ -69,6 +70,15 @@ public class DoubleActionBrushTool implements DoubleActionTraceTool {
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filter.
|
||||
*
|
||||
* @return the filter
|
||||
*/
|
||||
public Mask getSourceMask() {
|
||||
return sourceMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block filter used for identifying blocks to replace.
|
||||
*
|
||||
@ -78,6 +88,15 @@ public class DoubleActionBrushTool implements DoubleActionTraceTool {
|
||||
this.mask = filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block filter used for identifying blocks to replace.
|
||||
*
|
||||
* @param filter the filter to set
|
||||
*/
|
||||
public void setSourceMask(Mask filter) {
|
||||
this.sourceMask = filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the brush.
|
||||
*
|
||||
@ -178,6 +197,19 @@ public class DoubleActionBrushTool implements DoubleActionTraceTool {
|
||||
editSession.setMask(newMask);
|
||||
}
|
||||
}
|
||||
if (sourceMask != null) {
|
||||
Mask existingMask = editSession.getSourceMask();
|
||||
|
||||
if (existingMask == null) {
|
||||
editSession.setSourceMask(sourceMask);
|
||||
} else if (existingMask instanceof MaskIntersection) {
|
||||
((MaskIntersection) existingMask).add(sourceMask);
|
||||
} else {
|
||||
MaskIntersection newMask = new MaskIntersection(existingMask);
|
||||
newMask.add(sourceMask);
|
||||
editSession.setSourceMask(newMask);
|
||||
}
|
||||
}
|
||||
if (transform != null) {
|
||||
editSession.addTransform(transform);
|
||||
}
|
||||
|
@ -40,6 +40,31 @@ public class FastWorldEditExtent extends AbstractDelegateExtent implements HasFa
|
||||
return queue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLight(int x, int y, int z) {
|
||||
return queue.getLight(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockLight(int x, int y, int z) {
|
||||
return queue.getEmmittedLight(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(int x, int y, int z) {
|
||||
return queue.getSkyLight(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBrightness(int x, int y, int z) {
|
||||
return queue.getBrightness(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity(int x, int y, int z) {
|
||||
return queue.getOpacity(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity createEntity(final Location loc, final BaseEntity entity) {
|
||||
if (entity != null) {
|
||||
|
@ -0,0 +1,11 @@
|
||||
package com.boydti.fawe.object.extent;
|
||||
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
|
||||
public interface LightingExtent extends Extent {
|
||||
int getLight(int x, int y, int z);
|
||||
int getSkyLight(int x, int y, int z);
|
||||
int getBlockLight(int x, int y, int z);
|
||||
int getOpacity(int x, int y, int z);
|
||||
int getBrightness(int x, int y, int z);
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.boydti.fawe.object.extent;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class SourceMaskExtent extends TemporalExtent {
|
||||
private Mask mask;
|
||||
private Vector mutable = new Vector();
|
||||
|
||||
|
||||
/**
|
||||
* Get the mask.
|
||||
*
|
||||
* @return the mask
|
||||
*/
|
||||
public Mask getMask() {
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a mask.
|
||||
*
|
||||
* @param mask a mask
|
||||
*/
|
||||
public void setMask(Mask mask) {
|
||||
checkNotNull(mask);
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
public SourceMaskExtent(Extent extent, Mask mask) {
|
||||
super(extent);
|
||||
checkNotNull(mask);
|
||||
this.mask = mask;
|
||||
}
|
||||
@Override
|
||||
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
|
||||
set((int) location.x, (int) location.y, (int) location.z, block);
|
||||
return mask.test(location) && super.setBlock(location, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException {
|
||||
set(x, y, z, block);
|
||||
mutable.x = x;
|
||||
mutable.y = y;
|
||||
mutable.z = z;
|
||||
return mask.test(mutable) && super.setBlock(x, y, z, block);
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package com.boydti.fawe.object.extent;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockMaterial;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
||||
|
||||
public class TemporalExtent extends AbstractDelegateExtent {
|
||||
private int x,y,z = Integer.MAX_VALUE;
|
||||
private BaseBlock block = EditSession.nullBlock;
|
||||
|
||||
private int bx,bz = Integer.MAX_VALUE;
|
||||
private BaseBiome biome = EditSession.nullBiome;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param extent the extent
|
||||
*/
|
||||
public TemporalExtent(Extent extent) {
|
||||
super(extent);
|
||||
}
|
||||
|
||||
|
||||
public void set(int x, int y, int z, BaseBlock block) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
public void set(int x, int z, BaseBiome biome) {
|
||||
this.bx = x;
|
||||
this.bz = z;
|
||||
this.biome = biome;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBrightness(int x, int y, int z) {
|
||||
if (this.x == x && this.y == y && this.z == z) {
|
||||
BlockMaterial block = BundledBlockData.getInstance().getMaterialById(this.block.getId());
|
||||
if (block == null) {
|
||||
return 15;
|
||||
}
|
||||
return Math.min(15, block.getLightValue());
|
||||
}
|
||||
return super.getBrightness(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlock(Vector position) {
|
||||
if (position.x == x && position.y == y && position.z == z) {
|
||||
return block;
|
||||
}
|
||||
return super.getBlock(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getLazyBlock(Vector position) {
|
||||
if (position.x == x && position.y == y && position.z == z) {
|
||||
return block;
|
||||
}
|
||||
return super.getLazyBlock(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getLazyBlock(int x, int y, int z) {
|
||||
if (this.x == x && this.y == y && this.z == z) {
|
||||
return block;
|
||||
}
|
||||
return super.getLazyBlock(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBiome getBiome(Vector2D position) {
|
||||
if (position.getX() == bx && position.getZ() == bz) {
|
||||
return biome;
|
||||
}
|
||||
return super.getBiome(position);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.boydti.fawe.object.extent.LightingExtent;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Mask2D;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BlockLightMask implements Mask {
|
||||
|
||||
private final Extent extent;
|
||||
private final int min,max;
|
||||
|
||||
public BlockLightMask(Extent extent, int min, int max) {
|
||||
this.extent = extent;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Vector vector) {
|
||||
if (extent instanceof LightingExtent) {
|
||||
int light = ((LightingExtent) extent).getBlockLight((int) vector.x, (int) vector.y, (int) vector.z);
|
||||
return light >= min && light <= max;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Mask2D toMask2D() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.boydti.fawe.object.extent.LightingExtent;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Mask2D;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BrightnessMask implements Mask {
|
||||
|
||||
private final Extent extent;
|
||||
private final int min,max;
|
||||
|
||||
public BrightnessMask(Extent extent, int min, int max) {
|
||||
this.extent = extent;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Vector vector) {
|
||||
if (extent instanceof LightingExtent) {
|
||||
int light = ((LightingExtent) extent).getBrightness((int) vector.x, (int) vector.y, (int) vector.z);
|
||||
return light >= min && light <= max;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Mask2D toMask2D() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.boydti.fawe.object.extent.LightingExtent;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Mask2D;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class LightMask implements Mask {
|
||||
|
||||
private final Extent extent;
|
||||
private final int min,max;
|
||||
|
||||
public LightMask(Extent extent, int min, int max) {
|
||||
this.extent = extent;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Vector vector) {
|
||||
if (extent instanceof LightingExtent) {
|
||||
int light = ((LightingExtent) extent).getLight((int) vector.x, (int) vector.y, (int) vector.z);
|
||||
return light >= min && light <= max;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Mask2D toMask2D() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.boydti.fawe.object.extent.LightingExtent;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Mask2D;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class OpacityMask implements Mask {
|
||||
|
||||
private final Extent extent;
|
||||
private final int min,max;
|
||||
|
||||
public OpacityMask(Extent extent, int min, int max) {
|
||||
this.extent = extent;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Vector vector) {
|
||||
if (extent instanceof LightingExtent) {
|
||||
int light = ((LightingExtent) extent).getOpacity((int) vector.x, (int) vector.y, (int) vector.z);
|
||||
return light >= min && light <= max;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Mask2D toMask2D() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.boydti.fawe.object.mask;
|
||||
|
||||
import com.boydti.fawe.object.extent.LightingExtent;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Mask2D;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class SkyLightMask implements Mask {
|
||||
|
||||
private final Extent extent;
|
||||
private final int min,max;
|
||||
|
||||
public SkyLightMask(Extent extent, int min, int max) {
|
||||
this.extent = extent;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Vector vector) {
|
||||
if (extent instanceof LightingExtent) {
|
||||
int light = ((LightingExtent) extent).getSkyLight((int) vector.x, (int) vector.y, (int) vector.z);
|
||||
return light >= min && light <= max;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Mask2D toMask2D() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package com.boydti.fawe.object.schematic;
|
||||
|
||||
import com.boydti.fawe.object.clipboard.ReadOnlyClipboard;
|
||||
import com.boydti.fawe.util.EditSessionBuilder;
|
||||
import com.boydti.fawe.util.MaskTraverser;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
@ -12,6 +13,7 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
|
||||
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
|
||||
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
@ -114,6 +116,12 @@ public class Schematic {
|
||||
if (transform != null) {
|
||||
copy.setTransform(transform);
|
||||
}
|
||||
Mask sourceMask = editSession.getSourceMask();
|
||||
if (sourceMask != null) {
|
||||
new MaskTraverser(sourceMask).reset(extent);
|
||||
copy.setSourceMask(sourceMask);
|
||||
editSession.setSourceMask(null);
|
||||
}
|
||||
if (!pasteAir) {
|
||||
copy.setSourceMask(new ExistingBlockMask(clipboard));
|
||||
}
|
||||
|
@ -44,10 +44,12 @@ import com.boydti.fawe.object.changeset.MemoryOptimizedHistory;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.object.extent.FastWorldEditExtent;
|
||||
import com.boydti.fawe.object.extent.FaweRegionExtent;
|
||||
import com.boydti.fawe.object.extent.LightingExtent;
|
||||
import com.boydti.fawe.object.extent.NullExtent;
|
||||
import com.boydti.fawe.object.extent.ProcessedWEExtent;
|
||||
import com.boydti.fawe.object.extent.ResettableExtent;
|
||||
import com.boydti.fawe.object.extent.SlowExtent;
|
||||
import com.boydti.fawe.object.extent.SourceMaskExtent;
|
||||
import com.boydti.fawe.object.mask.ResettableMask;
|
||||
import com.boydti.fawe.object.progress.DefaultProgressTracker;
|
||||
import com.boydti.fawe.util.ExtentTraverser;
|
||||
@ -155,7 +157,7 @@ import static com.sk89q.worldedit.regions.Regions.minimumBlockY;
|
||||
* {@link Extent}s that are chained together. For example, history is logged
|
||||
* using the {@link ChangeSetExtent}.</p>
|
||||
*/
|
||||
public class EditSession extends AbstractWorld implements HasFaweQueue {
|
||||
public class EditSession extends AbstractWorld implements HasFaweQueue, LightingExtent {
|
||||
/**
|
||||
* Used by {@link #setBlock(Vector, BaseBlock, Stage)} to
|
||||
* determine which {@link Extent}s should be bypassed.
|
||||
@ -592,6 +594,16 @@ public class EditSession extends AbstractWorld implements HasFaweQueue {
|
||||
return maskingExtent != null ? maskingExtent.get().getMask() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mask.
|
||||
*
|
||||
* @return mask, may be null
|
||||
*/
|
||||
public Mask getSourceMask() {
|
||||
ExtentTraverser<SourceMaskExtent> maskingExtent = new ExtentTraverser(this.extent).find(SourceMaskExtent.class);
|
||||
return maskingExtent != null ? maskingExtent.get().getMask() : null;
|
||||
}
|
||||
|
||||
public void addTransform(ResettableExtent transform) {
|
||||
if (transform == null) {
|
||||
ExtentTraverser<AbstractDelegateExtent> traverser = new ExtentTraverser(this.extent).find(ResettableExtent.class);
|
||||
@ -607,6 +619,29 @@ public class EditSession extends AbstractWorld implements HasFaweQueue {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a mask.
|
||||
*
|
||||
* @param mask mask or null
|
||||
*/
|
||||
public void setSourceMask(Mask mask) {
|
||||
if (mask == null) {
|
||||
mask = Masks.alwaysTrue();
|
||||
} else {
|
||||
new MaskTraverser(mask).reset(this);
|
||||
}
|
||||
ExtentTraverser<SourceMaskExtent> maskingExtent = new ExtentTraverser(this.extent).find(SourceMaskExtent.class);
|
||||
if (maskingExtent != null && maskingExtent.get() != null) {
|
||||
Mask oldMask = maskingExtent.get().getMask();
|
||||
if (oldMask instanceof ResettableMask) {
|
||||
((ResettableMask) oldMask).reset();
|
||||
}
|
||||
maskingExtent.get().setMask(mask);
|
||||
} else if (mask != Masks.alwaysTrue()) {
|
||||
this.extent = new SourceMaskExtent(this.extent, mask);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a mask.
|
||||
*
|
||||
@ -792,6 +827,31 @@ public class EditSession extends AbstractWorld implements HasFaweQueue {
|
||||
return this.extent.setBiome(position, biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLight(int x, int y, int z) {
|
||||
return queue.getLight(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockLight(int x, int y, int z) {
|
||||
return queue.getEmmittedLight(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(int x, int y, int z) {
|
||||
return queue.getSkyLight(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBrightness(int x, int y, int z) {
|
||||
return queue.getBrightness(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity(int x, int y, int z) {
|
||||
return queue.getOpacity(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getLazyBlock(final Vector position) {
|
||||
if (position.y > maxY || position.y < 0) {
|
||||
@ -1794,6 +1854,12 @@ public class EditSession extends AbstractWorld implements HasFaweQueue {
|
||||
final ForwardExtentCopy copy = new ForwardExtentCopy(EditSession.this, region, EditSession.this, to);
|
||||
copy.setRepetitions(count);
|
||||
copy.setTransform(new AffineTransform().translate(dir.multiply(size)));
|
||||
Mask sourceMask = getSourceMask();
|
||||
if (sourceMask != null) {
|
||||
new MaskTraverser(sourceMask).reset(EditSession.this);
|
||||
copy.setSourceMask(sourceMask);
|
||||
setSourceMask(null);
|
||||
}
|
||||
if (!copyAir) {
|
||||
copy.setSourceMask(new ExistingBlockMask(EditSession.this));
|
||||
}
|
||||
@ -1844,6 +1910,12 @@ public class EditSession extends AbstractWorld implements HasFaweQueue {
|
||||
copy.setTransform(new AffineTransform().translate(dir.multiply(distance)));
|
||||
copy.setSourceFunction(remove); // Remove
|
||||
copy.setRemovingEntities(true);
|
||||
Mask sourceMask = getSourceMask();
|
||||
if (sourceMask != null) {
|
||||
new MaskTraverser(sourceMask).reset(EditSession.this);
|
||||
copy.setSourceMask(sourceMask);
|
||||
setSourceMask(null);
|
||||
}
|
||||
if (!copyAir) {
|
||||
copy.setSourceMask(new ExistingBlockMask(EditSession.this));
|
||||
}
|
||||
|
@ -139,6 +139,7 @@ public class LocalSession {
|
||||
private transient int cuiVersion = -1;
|
||||
private transient boolean fastMode = false;
|
||||
private transient Mask mask;
|
||||
private transient Mask sourceMask;
|
||||
private ResettableExtent transform = null;
|
||||
private transient TimeZone timezone = TimeZone.getDefault();
|
||||
|
||||
@ -1238,6 +1239,9 @@ public class LocalSession {
|
||||
if (mask != null) {
|
||||
editSession.setMask(mask);
|
||||
}
|
||||
if (sourceMask != null) {
|
||||
editSession.setSourceMask(sourceMask);
|
||||
}
|
||||
if (transform != null) {
|
||||
editSession.addTransform(transform);
|
||||
}
|
||||
@ -1272,6 +1276,15 @@ public class LocalSession {
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mask.
|
||||
*
|
||||
* @return mask, may be null
|
||||
*/
|
||||
public Mask getSourceMask() {
|
||||
return sourceMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a mask.
|
||||
*
|
||||
@ -1281,6 +1294,15 @@ public class LocalSession {
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a mask.
|
||||
*
|
||||
* @param mask mask or null
|
||||
*/
|
||||
public void setSourceMask(Mask mask) {
|
||||
this.sourceMask = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a mask.
|
||||
*
|
||||
@ -1291,6 +1313,16 @@ public class LocalSession {
|
||||
setMask(mask != null ? Masks.wrap(mask) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a mask.
|
||||
*
|
||||
* @param mask mask or null
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setSourceMask(com.sk89q.worldedit.masks.Mask mask) {
|
||||
setSourceMask(mask != null ? Masks.wrap(mask) : null);
|
||||
}
|
||||
|
||||
public ResettableExtent getTransform() {
|
||||
return transform;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import com.boydti.fawe.object.RunnableVal2;
|
||||
import com.boydti.fawe.object.clipboard.ReadOnlyClipboard;
|
||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||
import com.boydti.fawe.util.ImgurUtility;
|
||||
import com.boydti.fawe.util.MaskTraverser;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
@ -141,6 +142,12 @@ public class ClipboardCommands {
|
||||
|
||||
clipboard.setOrigin(session.getPlacementPosition(player));
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
|
||||
Mask sourceMask = editSession.getSourceMask();
|
||||
if (sourceMask != null) {
|
||||
new MaskTraverser(sourceMask).reset(editSession);
|
||||
copy.setSourceMask(sourceMask);
|
||||
editSession.setSourceMask(null);
|
||||
}
|
||||
if (mask != null && mask != Masks.alwaysTrue()) {
|
||||
copy.setSourceMask(mask);
|
||||
}
|
||||
@ -173,6 +180,12 @@ public class ClipboardCommands {
|
||||
clipboard.setOrigin(session.getPlacementPosition(player));
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
|
||||
copy.setSourceFunction(new BlockReplace(editSession, leavePattern));
|
||||
Mask sourceMask = editSession.getSourceMask();
|
||||
if (sourceMask != null) {
|
||||
new MaskTraverser(sourceMask).reset(editSession);
|
||||
copy.setSourceMask(sourceMask);
|
||||
editSession.setSourceMask(null);
|
||||
}
|
||||
if (mask != null) {
|
||||
copy.setSourceMask(mask);
|
||||
}
|
||||
@ -253,7 +266,7 @@ public class ClipboardCommands {
|
||||
@Switch('a') boolean ignoreAirBlocks, @Switch('o') boolean atOrigin,
|
||||
@Switch('s') boolean selectPasted) throws WorldEditException {
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
if (holder.getTransform().isIdentity()) {
|
||||
if (holder.getTransform().isIdentity() && editSession.getSourceMask() == null) {
|
||||
place(player, session, editSession, ignoreAirBlocks, atOrigin, selectPasted);
|
||||
return;
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ public class GeneralCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/gmask", "gmask" },
|
||||
aliases = { "/gmask", "gmask", "globalmask", "/globalmask" },
|
||||
usage = "[mask]",
|
||||
desc = "Set the global mask",
|
||||
min = 0,
|
||||
@ -124,6 +124,30 @@ public class GeneralCommands {
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/gsmask", "gsmask", "globalsourcemask", "/globalsourcemask" },
|
||||
usage = "[mask]",
|
||||
desc = "Set the global source mask",
|
||||
min = 0,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("worldedit.global-mask")
|
||||
public void gsmask(Player player, LocalSession session, EditSession editSession, @Optional CommandContext context) throws WorldEditException {
|
||||
if (context == null || context.argsLength() == 0) {
|
||||
session.setSourceMask((Mask) null);
|
||||
BBC.SOURCE_MASK_DISABLED.send(player);
|
||||
} else {
|
||||
ParserContext parserContext = new ParserContext();
|
||||
parserContext.setActor(player);
|
||||
parserContext.setWorld(player.getWorld());
|
||||
parserContext.setSession(session);
|
||||
parserContext.setExtent(editSession);
|
||||
Mask mask = worldEdit.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext);
|
||||
session.setSourceMask(mask);
|
||||
BBC.SOURCE_MASK.send(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/gtransform", "gtransform" },
|
||||
usage = "[transform]",
|
||||
|
@ -577,11 +577,15 @@ public class RegionCommands {
|
||||
@Logging(REGION)
|
||||
public void regenerateChunk(Player player, LocalSession session, EditSession editSession, @Selection Region region) throws WorldEditException {
|
||||
Mask mask = session.getMask();
|
||||
Mask sourceMask = session.getSourceMask();
|
||||
try {
|
||||
session.setMask((Mask) null);
|
||||
session.setSourceMask((Mask) null);
|
||||
player.getWorld().regenerate(region, editSession);
|
||||
} finally {
|
||||
session.setMask(mask);
|
||||
session.setSourceMask(mask);
|
||||
|
||||
}
|
||||
BBC.COMMAND_REGEN.send(player);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ public class ToolUtilCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "mask" },
|
||||
aliases = { "mask", "/mask" },
|
||||
usage = "[mask]",
|
||||
desc = "Set the brush mask",
|
||||
min = 0,
|
||||
@ -71,6 +71,7 @@ public class ToolUtilCommands {
|
||||
public void mask(Player player, LocalSession session, EditSession editSession, @Optional CommandContext context) throws WorldEditException {
|
||||
Tool tool = session.getTool(player.getItemInHand());
|
||||
if (tool == null) {
|
||||
player.print(BBC.BRUSH_NONE.f());
|
||||
return;
|
||||
}
|
||||
if (context == null || context.argsLength() == 0) {
|
||||
@ -96,6 +97,43 @@ public class ToolUtilCommands {
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "smask", "/smask", "/sourcemask", "sourcemask" },
|
||||
usage = "[mask]",
|
||||
desc = "Set the brush mask",
|
||||
min = 0,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.options.mask")
|
||||
public void smask(Player player, LocalSession session, EditSession editSession, @Optional CommandContext context) throws WorldEditException {
|
||||
Tool tool = session.getTool(player.getItemInHand());
|
||||
if (tool == null) {
|
||||
player.print(BBC.BRUSH_NONE.f());
|
||||
return;
|
||||
}
|
||||
if (context == null || context.argsLength() == 0) {
|
||||
if (tool instanceof BrushTool) {
|
||||
((BrushTool) tool).setSourceMask(null);
|
||||
} else if (tool instanceof DoubleActionBrushTool) {
|
||||
((DoubleActionBrushTool) tool).setMask(null);
|
||||
}
|
||||
BBC.BRUSH_SOURCE_MASK_DISABLED.send(player);
|
||||
} else {
|
||||
ParserContext parserContext = new ParserContext();
|
||||
parserContext.setActor(player);
|
||||
parserContext.setWorld(player.getWorld());
|
||||
parserContext.setSession(session);
|
||||
parserContext.setExtent(editSession);
|
||||
Mask mask = we.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext);
|
||||
if (tool instanceof BrushTool) {
|
||||
((BrushTool) tool).setSourceMask(mask);
|
||||
} else if (tool instanceof DoubleActionBrushTool) {
|
||||
((DoubleActionBrushTool) tool).setSourceMask(mask);
|
||||
}
|
||||
BBC.BRUSH_SOURCE_MASK.send(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "transform" },
|
||||
usage = "[transform]",
|
||||
|
@ -29,6 +29,7 @@ public class BrushTool implements TraceTool {
|
||||
protected static int MAX_RANGE = 500;
|
||||
protected int range = -1;
|
||||
private Mask mask = null;
|
||||
private Mask sourceMask = null;
|
||||
private ResettableExtent transform = null;
|
||||
private Brush brush = new SphereBrush();
|
||||
@Nullable
|
||||
@ -77,6 +78,24 @@ public class BrushTool implements TraceTool {
|
||||
this.mask = filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filter.
|
||||
*
|
||||
* @return the filter
|
||||
*/
|
||||
public Mask getSourceMask() {
|
||||
return sourceMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block filter used for identifying blocks to replace.
|
||||
*
|
||||
* @param filter the filter to set
|
||||
*/
|
||||
public void setSourceMask(Mask filter) {
|
||||
this.sourceMask = filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the brush.
|
||||
*
|
||||
@ -178,6 +197,19 @@ public class BrushTool implements TraceTool {
|
||||
editSession.setMask(newMask);
|
||||
}
|
||||
}
|
||||
if (sourceMask != null) {
|
||||
Mask existingMask = editSession.getMask();
|
||||
|
||||
if (existingMask == null) {
|
||||
editSession.setSourceMask(sourceMask);
|
||||
} else if (existingMask instanceof MaskIntersection) {
|
||||
((MaskIntersection) existingMask).add(sourceMask);
|
||||
} else {
|
||||
MaskIntersection newMask = new MaskIntersection(existingMask);
|
||||
newMask.add(sourceMask);
|
||||
editSession.setSourceMask(newMask);
|
||||
}
|
||||
}
|
||||
if (transform != null) {
|
||||
editSession.addTransform(transform);
|
||||
}
|
||||
|
@ -1,24 +1,16 @@
|
||||
package com.sk89q.worldedit.extension.factory;
|
||||
|
||||
import com.boydti.fawe.command.FaweParser;
|
||||
import com.boydti.fawe.object.mask.AdjacentMask;
|
||||
import com.boydti.fawe.object.mask.AngleMask;
|
||||
import com.boydti.fawe.object.mask.CustomMask;
|
||||
import com.boydti.fawe.object.mask.DataMask;
|
||||
import com.boydti.fawe.object.mask.IdDataMask;
|
||||
import com.boydti.fawe.object.mask.IdMask;
|
||||
import com.boydti.fawe.object.mask.RadiusMask;
|
||||
import com.boydti.fawe.object.mask.WallMask;
|
||||
import com.boydti.fawe.object.mask.XAxisMask;
|
||||
import com.boydti.fawe.object.mask.YAxisMask;
|
||||
import com.boydti.fawe.object.mask.ZAxisMask;
|
||||
import com.boydti.fawe.command.SuggestInputParseException;
|
||||
import com.boydti.fawe.object.mask.*;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.StringMan;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.extension.input.NoMatchException;
|
||||
import com.sk89q.worldedit.extension.input.ParserContext;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.BiomeMask2D;
|
||||
@ -27,6 +19,7 @@ import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||
import com.sk89q.worldedit.function.mask.ExpressionMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.MaskIntersection;
|
||||
import com.sk89q.worldedit.function.mask.MaskUnion;
|
||||
import com.sk89q.worldedit.function.mask.Masks;
|
||||
import com.sk89q.worldedit.function.mask.NoiseFilter;
|
||||
import com.sk89q.worldedit.function.mask.OffsetMask;
|
||||
@ -58,16 +51,24 @@ public class DefaultMaskParser extends FaweParser<Mask> {
|
||||
|
||||
public static final String[] EXPRESSION_MASK = new String[] { "=<expression>" };
|
||||
|
||||
public static final String[] BLOCK_MASK = new String[] { "<block>" };
|
||||
public static final String[] BLOCK_MASK = new String[] { "<blocks>" };
|
||||
|
||||
public static final String[] SIMPLE_MASK = new String[] {
|
||||
"#existing", "#solid", "#dregion", "#dselection", "#dsel", "#selection", "#region", "#sel", "#xaxis", "#yaxis", "#zaxis", "#id", "#data", "#wall", "#surface",
|
||||
"#nolight", "#haslight", "#existing", "#solid", "#dregion", "#dselection", "#dsel", "#selection", "#region", "#sel", "#xaxis", "#yaxis", "#zaxis", "#id", "#data", "#wall", "#surface",
|
||||
};
|
||||
|
||||
public static final String[] MISC_PATTERNS = new String[] {
|
||||
"hand", "pos1",
|
||||
public static final String[] DELEGATE_MASKS = new String[] {
|
||||
"#offset:", "#light:", "#blocklight:", "#skylight:", "#brightness:", "#opacity:"
|
||||
};
|
||||
|
||||
public static final String[] CHARACTER_MASKS= new String[] {
|
||||
"/", "{", "|", "~", ">", "<", "$", "%", "=", "!",
|
||||
};
|
||||
|
||||
public static final String[] HASHTAG_MASKS = MainUtil.joinArrayGeneric(SIMPLE_MASK, DELEGATE_MASKS);
|
||||
|
||||
public static final String[] ALL_MASKS = MainUtil.joinArrayGeneric(EXPRESSION_MASK, BLOCK_MASK, SIMPLE_MASK, DELEGATE_MASKS, CHARACTER_MASKS);
|
||||
|
||||
public DefaultMaskParser(WorldEdit worldEdit) {
|
||||
super(worldEdit);
|
||||
}
|
||||
@ -111,19 +112,83 @@ public class DefaultMaskParser extends FaweParser<Mask> {
|
||||
}
|
||||
}
|
||||
|
||||
private Mask getBlockMaskComponent(List<Mask> masks, String component, ParserContext context) throws InputParseException {
|
||||
public Mask catchSuggestion(String currentInput, List<Mask> masks, String nextInput, ParserContext context) throws InputParseException {
|
||||
try {
|
||||
return getBlockMaskComponent(masks, nextInput, context);
|
||||
} catch (SuggestInputParseException e) {
|
||||
e.prepend(currentInput.substring(0, currentInput.length() - nextInput.length()));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private Mask getBlockMaskComponent(List<Mask> masks, String input, ParserContext context) throws InputParseException {
|
||||
Extent extent = Request.request().getExtent();
|
||||
|
||||
final char firstChar = component.charAt(0);
|
||||
final char firstChar = input.charAt(0);
|
||||
switch (firstChar) {
|
||||
case '#':
|
||||
int colon = component.indexOf(':');
|
||||
int colon = input.indexOf(':');
|
||||
String component = input;
|
||||
if (colon != -1) {
|
||||
String rest = component.substring(colon + 1);
|
||||
component = component.substring(0, colon);
|
||||
masks.add(getBlockMaskComponent(masks, rest, context));
|
||||
String rest = input.substring(colon + 1);
|
||||
switch (component.toLowerCase()) {
|
||||
case "#light":
|
||||
case "#skylight":
|
||||
case "#blocklight":
|
||||
case "#emittedlight":
|
||||
case "#opacity":
|
||||
case "#brightness":
|
||||
String[] split = rest.split(":");
|
||||
if (split.length < 2) {
|
||||
throw new SuggestInputParseException(input, component + ":<min>:<max>");
|
||||
} else if (split.length > 2) {
|
||||
masks.add(catchSuggestion(input, masks, StringMan.join(Arrays.copyOfRange(split, 2, split.length), ":"), context));
|
||||
}
|
||||
try {
|
||||
int y1 = (int) Math.abs(Expression.compile(split[0]).evaluate());
|
||||
int y2 = (int) Math.abs(Expression.compile(split[1]).evaluate());
|
||||
switch (component.toLowerCase()) {
|
||||
case "#light":
|
||||
return new LightMask(extent, y1, y2);
|
||||
case "#skylight":
|
||||
return new SkyLightMask(extent, y1, y2);
|
||||
case "#blocklight":
|
||||
case "#emittedlight":
|
||||
return new BlockLightMask(extent, y1, y2);
|
||||
case "#opacity":
|
||||
return new OpacityMask(extent, y1, y2);
|
||||
case "#brightness":
|
||||
return new BrightnessMask(extent, y1, y2);
|
||||
}
|
||||
} catch (NumberFormatException | ExpressionException e) {
|
||||
e.printStackTrace();
|
||||
throw new SuggestInputParseException(input, component + ":<min>:<max>");
|
||||
}
|
||||
case "#~":
|
||||
case "#rel":
|
||||
case "#relative":
|
||||
case "#offset":
|
||||
try {
|
||||
List<String> split3 = suggestRemaining(rest, "#offset", "<dx>", "<dy>", "<dz>", "<mask>");
|
||||
int x = (int) Expression.compile(split3.get(0)).evaluate();
|
||||
int y = (int) Expression.compile(split3.get(1)).evaluate();
|
||||
int z = (int) Expression.compile(split3.get(2)).evaluate();
|
||||
rest = StringMan.join(split3.subList(3, split3.size()), ":");
|
||||
Mask mask = catchSuggestion(input, masks, rest, context);
|
||||
return new OffsetMask(mask, new Vector(x, y, z));
|
||||
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
|
||||
throw new SuggestInputParseException(null, "#offset:<dx>:<dy>:<dz>:<mask>");
|
||||
}
|
||||
}
|
||||
Mask mask = catchSuggestion(input, masks, rest, context);
|
||||
masks.add(mask);
|
||||
}
|
||||
switch (component.toLowerCase()) {
|
||||
case "#haslight":
|
||||
return new LightMask(extent, 1, Integer.MAX_VALUE);
|
||||
case "#nolight":
|
||||
return new LightMask(extent, 0, 0);
|
||||
case "#existing":
|
||||
return new ExistingBlockMask(extent);
|
||||
case "#solid":
|
||||
@ -160,38 +225,38 @@ public class DefaultMaskParser extends FaweParser<Mask> {
|
||||
masks.add(new ExistingBlockMask(extent));
|
||||
return new AdjacentMask(extent, Arrays.asList(new BaseBlock(0)), 1, 8);
|
||||
default:
|
||||
throw new NoMatchException("Unrecognized mask '" + component + "'");
|
||||
throw new SuggestInputParseException(input, HASHTAG_MASKS);
|
||||
}
|
||||
case '\\':
|
||||
case '/': {
|
||||
String[] split = component.substring(1).split(",");
|
||||
String[] split = input.substring(1).split(":");
|
||||
if (split.length != 2) {
|
||||
throw new InputParseException("Unknown angle '" + component + "' (not in form `/#,#`)");
|
||||
throw new SuggestInputParseException(input, "/<min-angle>:<max-angle>");
|
||||
}
|
||||
try {
|
||||
int y1 = (int) Math.abs(Expression.compile(split[0]).evaluate());
|
||||
int y2 = (int) Math.abs(Expression.compile(split[1]).evaluate());
|
||||
return new AngleMask(extent, y1, y2);
|
||||
} catch (NumberFormatException | ExpressionException e) {
|
||||
throw new InputParseException("Unknown angle '" + component + "' (not in form `/#,#`)");
|
||||
throw new SuggestInputParseException(input, "/<min-angle>:<max-angle>");
|
||||
}
|
||||
}
|
||||
case '{': {
|
||||
String[] split = component.substring(1).split(",");
|
||||
String[] split = input.substring(1).split(":");
|
||||
if (split.length != 2) {
|
||||
throw new InputParseException("Unknown range '" + component + "' (not in form `{#,#`)");
|
||||
throw new SuggestInputParseException(input, "{<min-radius>:<max-radius>");
|
||||
}
|
||||
try {
|
||||
int y1 = (int) Math.abs(Expression.compile(split[0]).evaluate());
|
||||
int y2 = (int) Math.abs(Expression.compile(split[1]).evaluate());
|
||||
return new RadiusMask(y1, y2);
|
||||
} catch (NumberFormatException | ExpressionException e) {
|
||||
throw new InputParseException("Unknown range '" + component + "' (not in form `{#,#`)");
|
||||
throw new SuggestInputParseException(input, "{<min-radius>:<max-radius>");
|
||||
}
|
||||
}
|
||||
case '|':
|
||||
case '~': {
|
||||
String[] split = component.substring(1).split("=");
|
||||
String[] split = input.substring(1).split("=");
|
||||
ParserContext tempContext = new ParserContext(context);
|
||||
tempContext.setRestricted(false);
|
||||
tempContext.setPreferringWildcard(true);
|
||||
@ -206,19 +271,19 @@ public class DefaultMaskParser extends FaweParser<Mask> {
|
||||
}
|
||||
}
|
||||
if (firstChar == '~') {
|
||||
return new AdjacentMask(extent, worldEdit.getBlockFactory().parseFromListInput(component.substring(1), tempContext), requiredMin, requiredMax);
|
||||
return new AdjacentMask(extent, worldEdit.getBlockFactory().parseFromListInput(input.substring(1), tempContext), requiredMin, requiredMax);
|
||||
} else {
|
||||
return new WallMask(extent, worldEdit.getBlockFactory().parseFromListInput(component.substring(1), tempContext), requiredMin, requiredMax);
|
||||
return new WallMask(extent, worldEdit.getBlockFactory().parseFromListInput(input.substring(1), tempContext), requiredMin, requiredMax);
|
||||
}
|
||||
} catch (NumberFormatException | ExpressionException e) {
|
||||
throw new InputParseException("Unknown adjacent mask '" + component + "' (not in form `~<ids>[=count]`)");
|
||||
throw new SuggestInputParseException(input, "~<blocks>=<amount>");
|
||||
}
|
||||
}
|
||||
case '>':
|
||||
case '<':
|
||||
Mask submask;
|
||||
if (component.length() > 1) {
|
||||
submask = getBlockMaskComponent(masks, component.substring(1), context);
|
||||
if (input.length() > 1) {
|
||||
submask = getBlockMaskComponent(masks, input.substring(1), context);
|
||||
} else {
|
||||
submask = new ExistingBlockMask(extent);
|
||||
}
|
||||
@ -227,58 +292,80 @@ public class DefaultMaskParser extends FaweParser<Mask> {
|
||||
|
||||
case '$':
|
||||
Set<BaseBiome> biomes = new HashSet<BaseBiome>();
|
||||
String[] biomesList = component.substring(1).split(",");
|
||||
String[] biomesList = input.substring(1).split(",");
|
||||
BiomeRegistry biomeRegistry = context.requireWorld().getWorldData().getBiomeRegistry();
|
||||
List<BaseBiome> knownBiomes = biomeRegistry.getBiomes();
|
||||
for (String biomeName : biomesList) {
|
||||
BaseBiome biome = Biomes.findBiomeByName(knownBiomes, biomeName, biomeRegistry);
|
||||
if (biome == null) {
|
||||
throw new InputParseException("Unknown biome '" + biomeName + "'");
|
||||
throw new SuggestInputParseException(input, "$<biome>");
|
||||
}
|
||||
biomes.add(biome);
|
||||
}
|
||||
|
||||
return Masks.asMask(new BiomeMask2D(context.requireExtent(), biomes));
|
||||
|
||||
case '%':
|
||||
try {
|
||||
double i = Math.abs(Expression.compile(component.substring(1)).evaluate());
|
||||
double i = Math.abs(Expression.compile(input.substring(1)).evaluate());
|
||||
return new NoiseFilter(new RandomNoise(), (i) / 100);
|
||||
} catch (NumberFormatException | ExpressionException e) {
|
||||
throw new InputParseException("Unknown percentage '" + component.substring(1) + "'");
|
||||
throw new SuggestInputParseException(input, "%<percent>");
|
||||
}
|
||||
case '=':
|
||||
try {
|
||||
Expression exp = Expression.compile(component.substring(1), "x", "y", "z");
|
||||
Expression exp = Expression.compile(input.substring(1), "x", "y", "z");
|
||||
WorldEditExpressionEnvironment env = new WorldEditExpressionEnvironment(
|
||||
Request.request().getEditSession(), Vector.ONE, Vector.ZERO);
|
||||
exp.setEnvironment(env);
|
||||
return new ExpressionMask(exp);
|
||||
} catch (ExpressionException e) {
|
||||
throw new InputParseException("Invalid expression: " + e.getMessage());
|
||||
throw new SuggestInputParseException(input, "=<expression>");
|
||||
}
|
||||
|
||||
case '!':
|
||||
if (component.length() > 1) {
|
||||
return Masks.negate(getBlockMaskComponent(masks, component.substring(1), context));
|
||||
if (input.length() > 1) {
|
||||
return Masks.negate(getBlockMaskComponent(masks, input.substring(1), context));
|
||||
}
|
||||
|
||||
throw new SuggestInputParseException(input, "!<mask>");
|
||||
default:
|
||||
for (CustomMask mask : customMasks) {
|
||||
if (mask.accepts(component)) {
|
||||
if (mask.accepts(input)) {
|
||||
try {
|
||||
Constructor<? extends CustomMask> constructor = mask.getClass().getDeclaredConstructor(List.class, String.class, ParserContext.class);
|
||||
return constructor.newInstance(masks, component, context);
|
||||
return constructor.newInstance(masks, input, context);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParserContext tempContext = new ParserContext(context);
|
||||
tempContext.setRestricted(false);
|
||||
tempContext.setPreferringWildcard(true);
|
||||
return new BlockMask(extent, worldEdit.getBlockFactory().parseFromListInput(component, tempContext));
|
||||
List<String> split = split(input, ',');
|
||||
if (split.size() == 1) {
|
||||
ParserContext tempContext = new ParserContext(context);
|
||||
tempContext.setRestricted(false);
|
||||
tempContext.setPreferringWildcard(true);
|
||||
return new BlockMask(extent, worldEdit.getBlockFactory().parseFromListInput(input, tempContext));
|
||||
}
|
||||
HashSet<BaseBlock> blocks = new HashSet<BaseBlock>();
|
||||
ArrayList<Mask> maskUnion = new ArrayList<Mask>();
|
||||
for (String elem : split) {
|
||||
ArrayList<Mask> list = new ArrayList<Mask>();
|
||||
list.add(catchSuggestion(input, list, elem, context));
|
||||
if (list.size() == 1) {
|
||||
Mask mask = list.get(0);
|
||||
if (mask instanceof BlockMask) {
|
||||
blocks.addAll(((BlockMask) mask).getBlocks());
|
||||
} else {
|
||||
maskUnion.add(mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!blocks.isEmpty()) {
|
||||
maskUnion.add(new BlockMask(extent, blocks));
|
||||
}
|
||||
if (maskUnion.size() == 1) {
|
||||
return maskUnion.get(0);
|
||||
}
|
||||
return new MaskUnion(maskUnion);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,10 +145,10 @@ public class HashTagPatternParser extends FaweParser<Pattern> {
|
||||
case "#offset":
|
||||
try {
|
||||
List<String> split3 = suggestRemaining(rest, "#offset", "<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() - 1), ":");
|
||||
int x = (int) Expression.compile(split3.get(0)).evaluate();
|
||||
int y = (int) Expression.compile(split3.get(1)).evaluate();
|
||||
int z = (int) Expression.compile(split3.get(2)).evaluate();
|
||||
rest = StringMan.join(split3.subList(3, split3.size()), ":");
|
||||
Pattern pattern = catchSuggestion(input, rest, context);
|
||||
return new OffsetPattern(pattern, x, y, z);
|
||||
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
|
||||
@ -160,7 +160,7 @@ public class HashTagPatternParser extends FaweParser<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() - 1), ":");
|
||||
rest = StringMan.join(split3.subList(3, split3.size()), ":");
|
||||
Pattern pattern = catchSuggestion(input, rest, context);
|
||||
return new SurfaceRandomOffsetPattern(pattern, x, y, z);
|
||||
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
|
||||
@ -173,7 +173,7 @@ public class HashTagPatternParser extends FaweParser<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() - 1), ":");
|
||||
rest = StringMan.join(split3.subList(3, split3.size()), ":");
|
||||
Pattern pattern = catchSuggestion(input, rest, context);
|
||||
return new SolidRandomOffsetPattern(pattern, x, y, z);
|
||||
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
|
||||
@ -187,7 +187,7 @@ public class HashTagPatternParser extends FaweParser<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() - 1), ":");
|
||||
rest = StringMan.join(split3.subList(3, split3.size()), ":");
|
||||
Pattern pattern = catchSuggestion(input, rest, context);
|
||||
return new RandomOffsetPattern(pattern, x, y, z);
|
||||
} catch (NumberFormatException | ExpressionException | IndexOutOfBoundsException e) {
|
||||
|
@ -21,6 +21,7 @@ package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.command.AnvilCommands;
|
||||
import com.boydti.fawe.command.MaskBinding;
|
||||
import com.boydti.fawe.command.PatternBinding;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
@ -130,6 +131,7 @@ public final class CommandManager {
|
||||
builder.addBinding(new WorldEditBinding(worldEdit));
|
||||
|
||||
builder.addBinding(new PatternBinding(worldEdit), com.sk89q.worldedit.function.pattern.Pattern.class);
|
||||
builder.addBinding(new MaskBinding(worldEdit), com.sk89q.worldedit.function.mask.Mask.class);
|
||||
|
||||
builder.addInvokeListener(new LegacyCommandsHandler());
|
||||
builder.addInvokeListener(new CommandLoggingHandler(worldEdit, commandLog));
|
||||
|
@ -19,10 +19,12 @@
|
||||
|
||||
package com.sk89q.worldedit.extent;
|
||||
|
||||
import com.boydti.fawe.object.extent.LightingExtent;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockMaterial;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
@ -30,6 +32,7 @@ import com.sk89q.worldedit.function.operation.OperationQueue;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@ -39,7 +42,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
/**
|
||||
* A base class for {@link Extent}s that merely passes extents onto another.
|
||||
*/
|
||||
public abstract class AbstractDelegateExtent implements Extent {
|
||||
public abstract class AbstractDelegateExtent implements LightingExtent {
|
||||
|
||||
private final Extent extent;
|
||||
|
||||
@ -53,6 +56,50 @@ public abstract class AbstractDelegateExtent implements Extent {
|
||||
this.extent = extent;
|
||||
}
|
||||
|
||||
public int getSkyLight(int x, int y, int z) {
|
||||
if (extent instanceof LightingExtent) {
|
||||
return ((LightingExtent) extent).getSkyLight(x, y, z);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getBlockLight(int x, int y, int z) {
|
||||
if (extent instanceof LightingExtent) {
|
||||
return ((LightingExtent) extent).getBlockLight(x, y, z);
|
||||
}
|
||||
return getBrightness(x, y, z);
|
||||
}
|
||||
|
||||
public int getOpacity(int x, int y, int z) {
|
||||
if (extent instanceof LightingExtent) {
|
||||
return ((LightingExtent) extent).getOpacity(x, y, z);
|
||||
}
|
||||
BlockMaterial block = BundledBlockData.getInstance().getMaterialById(getLazyBlock(x, y, z).getId());
|
||||
if (block == null) {
|
||||
return 15;
|
||||
}
|
||||
return Math.min(15, block.getLightOpacity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLight(int x, int y, int z) {
|
||||
if (extent instanceof LightingExtent) {
|
||||
return ((LightingExtent) extent).getLight(x, y, z);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getBrightness(int x, int y, int z) {
|
||||
if (extent instanceof LightingExtent) {
|
||||
return ((LightingExtent) extent).getBrightness(x, y, z);
|
||||
}
|
||||
BlockMaterial block = BundledBlockData.getInstance().getMaterialById(getLazyBlock(x, y, z).getId());
|
||||
if (block == null) {
|
||||
return 15;
|
||||
}
|
||||
return Math.min(15, block.getLightValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extent.
|
||||
*
|
||||
|
@ -23,18 +23,21 @@ import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
||||
import com.boydti.fawe.object.clipboard.FaweClipboard;
|
||||
import com.boydti.fawe.object.clipboard.MemoryOptimizedClipboard;
|
||||
import com.boydti.fawe.object.extent.LightingExtent;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockMaterial;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -48,7 +51,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
* Stores block data as a multi-dimensional array of {@link BaseBlock}s and
|
||||
* other data as lists or maps.
|
||||
*/
|
||||
public class BlockArrayClipboard implements Clipboard {
|
||||
public class BlockArrayClipboard implements Clipboard, LightingExtent {
|
||||
|
||||
private Region region;
|
||||
public FaweClipboard IMP;
|
||||
@ -57,6 +60,7 @@ public class BlockArrayClipboard implements Clipboard {
|
||||
private int my;
|
||||
private int mz;
|
||||
private Vector origin;
|
||||
private Vector mutable = new Vector();
|
||||
|
||||
public BlockArrayClipboard(Region region) {
|
||||
checkNotNull(region);
|
||||
@ -227,4 +231,43 @@ public class BlockArrayClipboard implements Clipboard {
|
||||
public static Class<?> inject() {
|
||||
return BlockArrayClipboard.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLight(int x, int y, int z) {
|
||||
return getBlockLight(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(int x, int y, int z) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockLight(int x, int y, int z) {
|
||||
return getBrightness(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity(int x, int y, int z) {
|
||||
mutable.x = x;
|
||||
mutable.y = y;
|
||||
mutable.z = z;
|
||||
BlockMaterial block = BundledBlockData.getInstance().getMaterialById(getBlock(mutable).getId());
|
||||
if (block == null) {
|
||||
return 15;
|
||||
}
|
||||
return Math.min(15, block.getLightOpacity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBrightness(int x, int y, int z) {
|
||||
mutable.x = x;
|
||||
mutable.y = y;
|
||||
mutable.z = z;
|
||||
BlockMaterial block = BundledBlockData.getInstance().getMaterialById(getBlock(mutable).getId());
|
||||
if (block == null) {
|
||||
return 15;
|
||||
}
|
||||
return Math.min(15, block.getLightValue());
|
||||
}
|
||||
}
|
@ -19,11 +19,14 @@
|
||||
|
||||
package com.sk89q.worldedit.session;
|
||||
|
||||
import com.boydti.fawe.util.MaskTraverser;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
|
||||
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
@ -97,6 +100,14 @@ public class PasteBuilder {
|
||||
}
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(extent, clipboard.getRegion(), clipboard.getOrigin(), targetExtent, to);
|
||||
copy.setTransform(transform);
|
||||
if (targetExtent instanceof EditSession) {
|
||||
Mask sourceMask = ((EditSession) targetExtent).getSourceMask();
|
||||
if (sourceMask != null) {
|
||||
new MaskTraverser(sourceMask).reset(extent);
|
||||
copy.setSourceMask(sourceMask);
|
||||
((EditSession) targetExtent).setSourceMask(null);
|
||||
}
|
||||
}
|
||||
if (ignoreAirBlocks) {
|
||||
copy.setSourceMask(new ExistingBlockMask(clipboard));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user