Add command `//gtexture` for texture control

Used in various patterns
This commit is contained in:
Jesse Boyd 2018-05-08 20:53:17 +10:00
parent 345b344000
commit 8218e831ac
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
19 changed files with 418 additions and 153 deletions

View File

@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.extent.NullExtent;
import com.boydti.fawe.object.extent.ResettableExtent;
import com.boydti.fawe.util.TextureUtil;
import com.boydti.fawe.util.image.ImageUtil;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
@ -78,6 +79,18 @@ public class FawePrimitiveBinding extends BindingHelper {
return ImageUtil.getImage(context.next());
}
@BindingMatch(
type = {TextureUtil.class},
behavior = BindingBehavior.PROVIDES
)
public TextureUtil getTexture(ArgumentStack context) {
Actor actor = context.getContext().getLocals().get(Actor.class);
if (actor == null) return Fawe.get().getCachedTextureUtil(true, 0, 100);
LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor);
return session.getTextureUtil();
}
@BindingMatch(
type = {Extent.class},
behavior = BindingBehavior.PROVIDES

View File

@ -62,6 +62,8 @@ public enum BBC {
MASK_DISABLED("Global mask disabled", "WorldEdit.General"),
MASK("Global mask set", "WorldEdit.General"),
TEXTURE_DISABLED("Texturing reset", "WorldEdit.General"),
TEXTURE_SET("Set texturing to %s1", "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"),

View File

@ -116,36 +116,36 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
int otherBCZ = (obz) >> 4;
int otherTCX = (otx) >> 4;
int otherTCZ = (otz) >> 4;
int cx = newChunk.getX();
int cz = newChunk.getZ();
int cbx = (cx << 4) - oX;
int cbz = (cz << 4) - oZ;
int cx = newChunk.getX();
int cz = newChunk.getZ();
int cbx = (cx << 4) - oX;
int cbz = (cz << 4) - oZ;
boolean changed = false;
for (int otherCZ = otherBCZ; otherCZ <= otherTCZ; otherCZ++) {
for (int otherCX = otherBCX; otherCX <= otherTCX; otherCX++) {
FaweChunk chunk;
synchronized (this) {
chunk = this.getFaweChunk(otherCX, otherCZ);
}
if (!(chunk instanceof NullFaweChunk)) {
changed = true;
MCAChunk other = (MCAChunk) chunk;
int ocbx = otherCX << 4;
int ocbz = otherCZ << 4;
int octx = ocbx + 15;
int octz = ocbz + 15;
int offsetY = 0;
int minX = obx > ocbx ? (obx - ocbx) & 15 : 0;
int maxX = otx < octx ? (otx - ocbx) : 15;
int minZ = obz > ocbz ? (obz - ocbz) & 15 : 0;
int maxZ = otz < octz ? (otz - ocbz) : 15;
int offsetX = ocbx - cbx;
int offsetZ = ocbz - cbz;
newChunk.copyFrom(other, minX, maxX, 0, 255, minZ, maxZ, offsetX, offsetY, offsetZ);
boolean changed = false;
for (int otherCZ = otherBCZ; otherCZ <= otherTCZ; otherCZ++) {
for (int otherCX = otherBCX; otherCX <= otherTCX; otherCX++) {
FaweChunk chunk;
synchronized (this) {
chunk = this.getFaweChunk(otherCX, otherCZ);
}
if (!(chunk instanceof NullFaweChunk)) {
changed = true;
MCAChunk other = (MCAChunk) chunk;
int ocbx = otherCX << 4;
int ocbz = otherCZ << 4;
int octx = ocbx + 15;
int octz = ocbz + 15;
int offsetY = 0;
int minX = obx > ocbx ? (obx - ocbx) & 15 : 0;
int maxX = otx < octx ? (otx - ocbx) : 15;
int minZ = obz > ocbz ? (obz - ocbz) & 15 : 0;
int maxZ = otz < octz ? (otz - ocbz) : 15;
int offsetX = ocbx - cbx;
int offsetZ = ocbz - cbz;
newChunk.copyFrom(other, minX, maxX, 0, 255, minZ, maxZ, offsetX, offsetY, offsetZ);
}
}
}
}
return changed;
}
@ -530,7 +530,7 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
mutableBlock.setChunk(chunk);
int bx = cx << 4;
int bz = cz << 4;
for (int layer = 0; layer < chunk.ids.length; layer++) {
for (int layer = 0; layer < 16; layer++) {
if (chunk.doesSectionExist(layer)) {
mutableBlock.setArrays(layer);
int yStart = layer << 4;

View File

@ -0,0 +1,102 @@
package com.boydti.fawe.object.brush;
import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.object.brush.heightmap.HeightMap;
import com.boydti.fawe.object.mask.AdjacentAnyMask;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks;
import com.sk89q.worldedit.function.mask.RegionMask;
import com.sk89q.worldedit.function.mask.SolidBlockMask;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
import com.sk89q.worldedit.regions.CuboidRegion;
import java.io.InputStream;
import java.util.Arrays;
public class ImageBrush extends HeightBrush {
private final boolean onlyWhite;
private final Player player;
public ImageBrush(Player player, InputStream stream, int rotation, double yscale, boolean onlyWhite, Clipboard clipboard) {
super(stream, rotation, yscale, false, true, clipboard);
this.onlyWhite = onlyWhite;
this.player = player;
}
@Override
public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
final int cx = position.getBlockX();
final int cy = position.getBlockY();
final int cz = position.getBlockZ();
int size = (int) sizeDouble;
int maxY = editSession.getMaxY();
int add;
if (yscale < 0) {
add = maxY;
} else {
add = 0;
}
double scale = (yscale / sizeDouble) * (maxY + 1);
final HeightMap map = getHeightMap();
map.setSize(size);
int cutoff = onlyWhite ? maxY : 0;
final SolidBlockMask solid = new SolidBlockMask(editSession);
final AdjacentAnyMask adjacent = new AdjacentAnyMask(Masks.negate(solid));
RegionMask region = new RegionMask(new CuboidRegion(editSession.getWorld(), position.subtract(size, size, size), position.add(size, size, size)));
RecursiveVisitor visitor = new RecursiveVisitor(new Mask() {
@Override
public boolean test(Vector vector) {
if (solid.test(vector) && region.test(vector)) {
int dx = vector.getBlockX() - cx;
int dy = vector.getBlockY() - cy;
int dz = vector.getBlockZ() - cz;
if (dir != null) {
if (dy != 0) {
if (dir.getBlockX() != 0) {
dx += dir.getBlockX() * dy;
} else if (dir.getBlockZ() != 0) {
dz += dir.getBlockZ() * dy;
}
}
double raise = map.getHeight(dx, dz);
int val = (int) Math.ceil(raise * scale) + add;
if (val < cutoff) {
return true;
}
if (val >= 255 || PseudoRandom.random.random(maxY) < val) {
editSession.setBlock(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), pattern);
}
return true;
}
}
return false;
}
}, new RegionFunction() {
@Override
public boolean apply(Vector vector) throws WorldEditException {
return true;
}
}, Integer.MAX_VALUE, editSession);
visitor.setDirections(Arrays.asList(visitor.DIAGONAL_DIRECTIONS));
visitor.visit(position);
Operations.completeBlindly(visitor);
}
private void apply(double val) {
}
}

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.object.collection;
import com.boydti.fawe.util.MainUtil;
import java.lang.ref.Reference;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
@ -40,17 +41,7 @@ public abstract class IterableThreadLocal<T> extends ThreadLocal<T> implements I
public static void clean(ThreadLocal instance) {
try {
ThreadGroup rootGroup = Thread.currentThread( ).getThreadGroup( );
ThreadGroup parentGroup;
while ( ( parentGroup = rootGroup.getParent() ) != null ) {
rootGroup = parentGroup;
}
Thread[] threads = new Thread[ rootGroup.activeCount() ];
if (threads.length != 0) {
while (rootGroup.enumerate(threads, true) == threads.length) {
threads = new Thread[threads.length * 2];
}
}
Thread[] threads = MainUtil.getThreads();
Field tl = Thread.class.getDeclaredField("threadLocals");
tl.setAccessible(true);
Method methodRemove = null;

View File

@ -16,6 +16,16 @@ public class RandomAccessInputStream extends InputStream {
return raf.read();
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return raf.read(b, off, len);
}
@Override
public int read(byte[] b) throws IOException {
return raf.read(b);
}
@Override
public int available() throws IOException {
return (int) (raf.length() - raf.getFilePointer());

View File

@ -3,7 +3,7 @@ package com.boydti.fawe.object.pattern;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.DataAnglePattern;
import com.boydti.fawe.util.TextureUtil;
import com.boydti.fawe.util.TextureHolder;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
@ -11,16 +11,11 @@ import com.sk89q.worldedit.extent.Extent;
import java.io.IOException;
public class AngleColorPattern extends DataAnglePattern {
private transient TextureUtil util;
protected transient TextureHolder util;
private final boolean randomize;
private final int complexity;
public AngleColorPattern(Extent extent, int complexity, boolean randomize, int distance) {
public AngleColorPattern(Extent extent, TextureHolder util, int distance) {
super(extent, distance);
this.complexity = complexity;
this.randomize = randomize;
this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
this.util = util;
}
public int getColor(int color, int slope) {
@ -37,10 +32,10 @@ public class AngleColorPattern extends DataAnglePattern {
BaseBlock block = extent.getBlock(position);
int slope = getSlope(block, position);
if (slope == -1) return block;
int color = util.getColor(block);
int color = util.getTextureUtil().getColor(block);
if (color == 0) return block;
int newColor = getColor(color, slope);
return util.getNearestBlock(newColor);
return util.getTextureUtil().getNearestBlock(newColor);
}
@Override
@ -66,16 +61,16 @@ public class AngleColorPattern extends DataAnglePattern {
BaseBlock block = extent.getBlock(getPosition);
int slope = getSlope(block, getPosition);
if (slope == -1) return false;
int color = util.getColor(block);
int color = util.getTextureUtil().getColor(block);
if (color == 0) return false;
int newColor = getColor(color, slope);
BaseBlock newBlock = util.getNearestBlock(newColor);
BaseBlock newBlock = util.getTextureUtil().getNearestBlock(newColor);
if (newBlock == null) return false;
return extent.setBlock(setPosition, newBlock);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
util = Fawe.get().getCachedTextureUtil(true, 0, 100);
}
}

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object.pattern;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.util.TextureHolder;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
@ -10,22 +11,19 @@ import java.awt.Color;
import java.io.IOException;
public class AverageColorPattern extends AbstractExtentPattern {
private transient TextureUtil util;
private final boolean randomize;
private final int complexity;
private transient TextureHolder holder;
private final int color;
public AverageColorPattern(Extent extent, int color, int complexity, boolean randomize) {
public AverageColorPattern(Extent extent, int color, TextureHolder util) {
super(extent);
this.complexity = complexity;
this.randomize = randomize;
this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
this.holder = util;
this.color = new Color(color).getRGB();
}
@Override
public BaseBlock apply(Vector position) {
BaseBlock block = getExtent().getBlock(position);
TextureUtil util = holder.getTextureUtil();
int currentColor = util.getColor(block);
int newColor = util.averageColor(currentColor, color);
return util.getNearestBlock(newColor);
@ -34,6 +32,7 @@ public class AverageColorPattern extends AbstractExtentPattern {
@Override
public boolean apply(Extent extent, Vector setPosition, Vector getPosition) throws WorldEditException {
BaseBlock block = extent.getBlock(getPosition);
TextureUtil util = holder.getTextureUtil();
int currentColor = util.getColor(block);
if (currentColor == 0) return false;
int newColor = util.averageColor(currentColor, color);
@ -44,6 +43,6 @@ public class AverageColorPattern extends AbstractExtentPattern {
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
holder = Fawe.get().getCachedTextureUtil(true, 0, 100);
}
}

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object.pattern;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.util.TextureHolder;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
@ -10,23 +11,20 @@ import com.sk89q.worldedit.function.pattern.AbstractPattern;
import java.io.IOException;
public class DesaturatePattern extends AbstractPattern {
private transient TextureUtil util;
private final boolean randomize;
private final int complexity;
private transient TextureHolder holder;
private final Extent extent;
private final double value;
public DesaturatePattern(Extent extent, double value, int complexity, boolean randomize) {
public DesaturatePattern(Extent extent, double value, TextureHolder util) {
this.extent = extent;
this.complexity = complexity;
this.randomize = randomize;
this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
this.holder = util;
this.value = Math.max(0, Math.min(1, value));
}
@Override
public BaseBlock apply(Vector position) {
BaseBlock block = extent.getBlock(position);
TextureUtil util = holder.getTextureUtil();
int color = util.getColor(block);
int r = (color >> 16) & 0xFF;
int g = (color >> 8) & 0xFF;
@ -43,6 +41,7 @@ public class DesaturatePattern extends AbstractPattern {
@Override
public boolean apply(Extent extent, Vector setPosition, Vector getPosition) throws WorldEditException {
BaseBlock block = extent.getBlock(getPosition);
TextureUtil util = holder.getTextureUtil();
int color = util.getColor(block);
int r = (color >> 16) & 0xFF;
int g = (color >> 8) & 0xFF;
@ -65,6 +64,6 @@ public class DesaturatePattern extends AbstractPattern {
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
holder = Fawe.get().getCachedTextureUtil(true, 0, 100);
}
}

View File

@ -1,6 +1,7 @@
package com.boydti.fawe.object.pattern;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.util.TextureHolder;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
@ -11,24 +12,21 @@ import java.awt.Color;
import java.io.IOException;
public class SaturatePattern extends AbstractPattern {
private transient TextureUtil util;
private final boolean randomize;
private final int complexity;
private transient TextureHolder holder;
private final int color;
private final Extent extent;
public SaturatePattern(Extent extent, int color, int complexity, boolean randomize) {
public SaturatePattern(Extent extent, int color, TextureHolder texture) {
this.extent = extent;
this.complexity = complexity;
this.randomize = randomize;
this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
this.holder = texture;
this.color = new Color(color).getRGB();
}
@Override
public BaseBlock apply(Vector position) {
BaseBlock block = extent.getBlock(position);
TextureUtil util = holder.getTextureUtil();
int currentColor = util.getColor(block);
int newColor = util.multiplyColor(currentColor, color);
return util.getNearestBlock(newColor);
@ -37,6 +35,7 @@ public class SaturatePattern extends AbstractPattern {
@Override
public boolean apply(Extent extent, Vector setPosition, Vector getPosition) throws WorldEditException {
BaseBlock block = extent.getBlock(getPosition);
TextureUtil util = holder.getTextureUtil();
int currentColor = util.getColor(block);
if (currentColor == 0) return false;
int newColor = util.multiplyColor(currentColor, color);
@ -47,6 +46,6 @@ public class SaturatePattern extends AbstractPattern {
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
holder = Fawe.get().getCachedTextureUtil(true, 0, 100);
}
}

View File

@ -13,17 +13,13 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class ShadePattern extends AbstractPattern {
private transient TextureUtil util;
private final boolean randomize;
private final int complexity;
private final Extent extent;
private final boolean darken;
public ShadePattern(Extent extent, boolean darken, int complexity, boolean randomize) {
public ShadePattern(Extent extent, boolean darken, TextureUtil util) {
checkNotNull(extent);
this.extent = extent;
this.complexity = complexity;
this.randomize = randomize;
this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
this.util = util;
this.darken = darken;
}
@ -35,6 +31,6 @@ public class ShadePattern extends AbstractPattern {
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
util = Fawe.get().getCachedTextureUtil(true, 0, 100);
}
}

View File

@ -488,7 +488,7 @@ public class MainUtil {
private static final Class[] parameters = new Class[]{URL.class};
public static void loadURLClasspath(URL u) throws IOException {
public static ClassLoader loadURLClasspath(URL u) throws IOException {
ClassLoader sysloader = ClassLoader.getSystemClassLoader();
Class sysclass = URLClassLoader.class;
@ -496,11 +496,27 @@ public class MainUtil {
try {
Method method = sysclass.getDeclaredMethod("addURL", parameters);
method.setAccessible(true);
method.invoke(sysloader, new Object[]{u});
} catch (Throwable t) {
t.printStackTrace();
throw new IOException("Error, could not add URL to system classloader");
if (sysloader instanceof URLClassLoader) {
System.out.println("Sys loader");
method.invoke(sysloader, new Object[]{u});
} else {
System.out.println("Not sys loader");
ClassLoader loader = MainUtil.class.getClassLoader();
while (!(loader instanceof URLClassLoader) && loader.getParent() != null) {
loader = loader.getParent();
}
if (loader instanceof URLClassLoader) {
method.invoke(sysloader, new Object[]{u});
} else {
loader = new URLClassLoader(new URL[]{u}, MainUtil.class.getClassLoader());
System.out.println("Loaded true");
return loader;
}
}
} catch (Throwable ignore) {
ignore.printStackTrace();
}
return sysloader;
}
public static String getText(String url) throws IOException {
@ -578,6 +594,21 @@ public class MainUtil {
}
}
public static Thread[] getThreads() {
ThreadGroup rootGroup = Thread.currentThread( ).getThreadGroup( );
ThreadGroup parentGroup;
while ( ( parentGroup = rootGroup.getParent() ) != null ) {
rootGroup = parentGroup;
}
Thread[] threads = new Thread[ rootGroup.activeCount() ];
if (threads.length != 0) {
while (rootGroup.enumerate(threads, true) == threads.length) {
threads = new Thread[threads.length * 2];
}
}
return threads;
}
public static File copyFile(File sourceFile, File destFile) throws IOException {
if (!destFile.exists()) {
File parent = destFile.getParentFile();

View File

@ -0,0 +1,5 @@
package com.boydti.fawe.util;
public interface TextureHolder {
TextureUtil getTextureUtil();
}

View File

@ -3,12 +3,17 @@ package com.boydti.fawe.util;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.pattern.PatternExtent;
import com.boydti.fawe.util.image.ImageUtil;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@ -26,7 +31,42 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.imageio.ImageIO;
public class TextureUtil {
public class TextureUtil implements TextureHolder {
public static TextureUtil fromClipboard(Clipboard clipboard) throws FileNotFoundException {
boolean[] ids = new boolean[Character.MAX_VALUE + 1];
for (Vector pt : clipboard.getRegion()) {
ids[clipboard.getBlock(pt).getCombined()] = true;
}
HashSet<BaseBlock> blocks = new HashSet<>();
for (int combined = 0; combined < ids.length; combined++) {
if (ids[combined]) blocks.add(FaweCache.CACHE_BLOCK[combined]);
}
return fromBlocks(blocks);
}
public static TextureUtil fromBlocks(Set<BaseBlock> blocks) throws FileNotFoundException {
return new FilteredTextureUtil(Fawe.get().getTextureUtil(), blocks);
}
public static TextureUtil fromMask(Mask mask) throws FileNotFoundException {
HashSet<BaseBlock> blocks = new HashSet<>();
BlockPattern pattern = new BlockPattern(new BaseBlock(BlockID.AIR));
PatternExtent extent = new PatternExtent(pattern);
new MaskTraverser(mask).reset(extent);
TextureUtil tu = Fawe.get().getTextureUtil();
for (int combinedId : tu.getValidBlockIds()) {
BaseBlock block = FaweCache.CACHE_BLOCK[combinedId];
pattern.setBlock(block);
if (mask.test(Vector.ZERO)) blocks.add(block);
}
return fromBlocks(blocks);
}
@Override
public TextureUtil getTextureUtil() {
return this;
}
private final File folder;
private static final int[] FACTORS = new int[766];

View File

@ -33,9 +33,7 @@ import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
import com.boydti.fawe.object.collection.SparseBitSet;
import com.boydti.fawe.object.extent.ResettableExtent;
import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.StringMan;
import com.boydti.fawe.util.*;
import com.boydti.fawe.util.cui.CUI;
import com.boydti.fawe.wrappers.WorldWrapper;
import com.sk89q.jchronic.Chronic;
@ -74,7 +72,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* Stores session information.
*/
public class LocalSession {
public class LocalSession implements TextureHolder {
@Deprecated
public transient static int MAX_HISTORY_SIZE = 15;
@ -117,6 +115,7 @@ public class LocalSession {
private transient boolean fastMode = false;
private transient Mask mask;
private transient Mask sourceMask;
private transient TextureUtil texture;
private transient ResettableExtent transform = null;
private transient TimeZone timezone = TimeZone.getDefault();
@ -1430,6 +1429,28 @@ public class LocalSession {
setSourceMask(mask != null ? Masks.wrap(mask) : null);
}
public void setTextureUtil(TextureUtil texture) {
synchronized (this) {
this.texture = texture;
}
}
/**
* Get the TextureUtil currently being used
* @return
*/
@Override
public TextureUtil getTextureUtil() {
TextureUtil tmp = texture;
if (tmp == null) {
synchronized (this) {
tmp = Fawe.get().getCachedTextureUtil(true, 0, 100);
this.texture = tmp;
}
}
return tmp;
}
public ResettableExtent getTransform() {
return transform;
}

View File

@ -391,6 +391,36 @@ public class BrushCommands extends MethodCommands {
.setFill(fill);
}
@Command(
aliases = {"stencil", "color"},
usage = "<pattern> [radius=5] [file|#clipboard|imgur=null] [rotation=360] [yscale=1.0]",
desc = "Use a height map to paint a surface",
help =
"Use a height map to paint any surface.\n" +
"The -w flag will only apply at maximum saturation\n" +
"The -r flag will apply random rotation",
min = 1,
max = -1
)
@CommandPermissions("worldedit.brush.stencil")
public BrushSettings stencilBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("") final String image, @Optional("0") @Step(90) @Range(min=0, max=360) final int rotation, @Optional("1") final double yscale, @Switch('w') boolean onlyWhite, @Switch('r') boolean randomRotate, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
InputStream stream = getHeightmapStream(image);
HeightBrush brush;
try {
brush = new StencilBrush(stream, rotation, yscale, onlyWhite, image.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null);
} catch (EmptyClipboardException ignore) {
brush = new StencilBrush(stream, rotation, yscale, onlyWhite, null);
}
if (randomRotate) {
brush.setRandomRotate(true);
}
return set(session, context,
brush)
.setSize(radius)
.setFill(fill);
}
// @Command(
// aliases = {"image", "img"}
// // TODO directional image coloring

View File

@ -345,7 +345,7 @@ public class BrushOptionsCommands extends MethodCommands {
min = 0,
max = -1
)
@CommandPermissions("worldedit.brush.options.mask")
@CommandPermissions({"worldedit.brush.options.mask", "worldedit.mask.brush"})
public void mask(Player player, LocalSession session, EditSession editSession, @Optional @Switch('h') boolean offHand, CommandContext context) throws WorldEditException {
BrushTool tool = session.getBrushTool(player, false);
if (tool == null) {
@ -378,7 +378,7 @@ public class BrushOptionsCommands extends MethodCommands {
min = 0,
max = -1
)
@CommandPermissions("worldedit.brush.options.mask")
@CommandPermissions({"worldedit.brush.options.mask", "worldedit.mask.brush"})
public void smask(Player player, LocalSession session, EditSession editSession, @Optional @Switch('h') boolean offHand, CommandContext context) throws WorldEditException {
BrushTool tool = session.getBrushTool(player, false);
if (tool == null) {
@ -410,7 +410,7 @@ public class BrushOptionsCommands extends MethodCommands {
min = 0,
max = -1
)
@CommandPermissions("worldedit.brush.options.transform")
@CommandPermissions({"worldedit.brush.options.transform", "worldedit.transform.brush"})
public void transform(Player player, LocalSession session, EditSession editSession, @Optional @Switch('h') boolean offHand, CommandContext context) throws WorldEditException {
BrushTool tool = session.getBrushTool(player, false);
if (tool == null) {

View File

@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.extent.ResettableExtent;
import com.boydti.fawe.util.*;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
@ -11,12 +12,17 @@ import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.ItemType;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.util.command.parametric.ParameterException;
import java.io.FileNotFoundException;
import java.util.HashSet;
import static com.google.common.base.Preconditions.checkNotNull;
@ -82,6 +88,68 @@ public class OptionsCommands {
}
}
@Command(
aliases = {"/gtexture", "gtexture"},
usage = "[mask|#clipboard|complexity] [randomization=true]",
help = "The global destination mask applies to all edits you do and masks based on the destination blocks (i.e. the blocks in the world).",
desc = "Set the global mask",
min = 0,
max = -1
)
@CommandPermissions("worldedit.global-texture")
public void gtexture(FawePlayer player, LocalSession session, EditSession editSession, @Optional CommandContext context) throws WorldEditException, FileNotFoundException, ParameterException {
if (context == null || context.argsLength() == 0) {
session.setTextureUtil(null);
BBC.TEXTURE_DISABLED.send(player);
} else {
String arg = context.getString(0);
String argLower = arg.toLowerCase();
TextureUtil util = Fawe.get().getTextureUtil();
int randomIndex = 1;
boolean checkRandomization = true;
if (context.argsLength() >= 2 && MathMan.isInteger(context.getString(0)) && MathMan.isInteger(context.getString(1))) {
// complexity
int min = Integer.parseInt(context.getString(0));
int max = Integer.parseInt(context.getString(1));
if (min < 0 || max > 100) throw new ParameterException("Complexity must be in the range 0-100");
System.out.println("Clean " + min + " | " + max);
if (min != 0 || max != 100) util = new CleanTextureUtil(util, min, max);
randomIndex = 2;
} else if (context.argsLength() == 1 && argLower.equals("true") || argLower.equals("false")) {
if (argLower.equals("true")) util = new RandomTextureUtil(util);
checkRandomization = false;
} else {
HashSet<BaseBlock> blocks = null;
if (argLower.equals("#copy") || argLower.equals("#clipboard")) {
Clipboard clipboard = player.getSession().getClipboard().getClipboard();
util = TextureUtil.fromClipboard(clipboard);
} else if (argLower.equals("*") || argLower.equals("true")) {
util = Fawe.get().getTextureUtil();
} else {
ParserContext parserContext = new ParserContext();
parserContext.setActor(player.getPlayer());
parserContext.setWorld(player.getWorld());
parserContext.setSession(session);
parserContext.setExtent(editSession);
Mask mask = worldEdit.getMaskFactory().parseFromInput(arg, parserContext);
util = TextureUtil.fromMask(mask);
}
}
if (checkRandomization) {
if (context.argsLength() > randomIndex) {
boolean random = Boolean.parseBoolean(context.getString(randomIndex));
if (random) util = new RandomTextureUtil(util);
}
}
if (!(util instanceof CachedTextureUtil)) util = new CachedTextureUtil(util);
session.setTextureUtil(util);
BBC.TEXTURE_SET.send(player, context.getJoinedStrings(0));
}
}
@Command(
aliases = {"/gmask", "gmask", "globalmask", "/globalmask"},
usage = "[mask]",
@ -90,7 +158,7 @@ public class OptionsCommands {
min = 0,
max = -1
)
@CommandPermissions("worldedit.global-mask")
@CommandPermissions({"worldedit.global-mask", "worldedit.mask.global"})
public void gmask(Player player, LocalSession session, EditSession editSession, @Optional CommandContext context) throws WorldEditException {
if (context == null || context.argsLength() == 0) {
session.setMask((Mask) null);
@ -115,7 +183,7 @@ public class OptionsCommands {
min = 0,
max = -1
)
@CommandPermissions("worldedit.global-mask")
@CommandPermissions({"worldedit.global-mask", "worldedit.mask.global"})
public void gsmask(Player player, LocalSession session, EditSession editSession, @Optional CommandContext context) throws WorldEditException {
if (context == null || context.argsLength() == 0) {
session.setSourceMask((Mask) null);
@ -139,7 +207,7 @@ public class OptionsCommands {
min = 0,
max = -1
)
@CommandPermissions("worldedit.global-transform")
@CommandPermissions({"worldedit.global-transform", "worldedit.transform.global"})
public void gtransform(Player player, EditSession editSession, LocalSession session, @Optional CommandContext context) throws WorldEditException {
if (context == null || context.argsLength() == 0) {
session.setTransform(null);

View File

@ -1,38 +1,10 @@
package com.sk89q.worldedit.command;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.DataAnglePattern;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
import com.boydti.fawe.object.collection.RandomCollection;
import com.boydti.fawe.object.pattern.AngleColorPattern;
import com.boydti.fawe.object.pattern.AverageColorPattern;
import com.boydti.fawe.object.pattern.BiomePattern;
import com.boydti.fawe.object.pattern.BufferedPattern;
import com.boydti.fawe.object.pattern.BufferedPattern2D;
import com.boydti.fawe.object.pattern.DataPattern;
import com.boydti.fawe.object.pattern.DesaturatePattern;
import com.boydti.fawe.object.pattern.ExistingPattern;
import com.boydti.fawe.object.pattern.ExpressionPattern;
import com.boydti.fawe.object.pattern.FullClipboardPattern;
import com.boydti.fawe.object.pattern.IdDataMaskPattern;
import com.boydti.fawe.object.pattern.IdPattern;
import com.boydti.fawe.object.pattern.Linear2DBlockPattern;
import com.boydti.fawe.object.pattern.Linear3DBlockPattern;
import com.boydti.fawe.object.pattern.LinearBlockPattern;
import com.boydti.fawe.object.pattern.MaskedPattern;
import com.boydti.fawe.object.pattern.NoXPattern;
import com.boydti.fawe.object.pattern.NoYPattern;
import com.boydti.fawe.object.pattern.NoZPattern;
import com.boydti.fawe.object.pattern.OffsetPattern;
import com.boydti.fawe.object.pattern.PatternExtent;
import com.boydti.fawe.object.pattern.RandomFullClipboardPattern;
import com.boydti.fawe.object.pattern.RandomOffsetPattern;
import com.boydti.fawe.object.pattern.RelativePattern;
import com.boydti.fawe.object.pattern.SaturatePattern;
import com.boydti.fawe.object.pattern.ShadePattern;
import com.boydti.fawe.object.pattern.SolidRandomOffsetPattern;
import com.boydti.fawe.object.pattern.SurfaceRandomOffsetPattern;
import com.boydti.fawe.object.pattern.*;
import com.boydti.fawe.object.random.SimplexRandom;
import com.boydti.fawe.util.ColorUtil;
import com.boydti.fawe.util.TextureUtil;
@ -116,9 +88,9 @@ public class PatternCommands extends MethodCommands {
min = 1,
max = 1
)
public Pattern color(String arg) {
public Pattern color(TextureUtil textureUtil, String arg) {
Color color = ColorUtil.parseColor(arg);
return Fawe.get().getTextureUtil().getNearestBlock(color.getRGB());
return textureUtil.getNearestBlock(color.getRGB());
}
@Command(
@ -128,9 +100,8 @@ public class PatternCommands extends MethodCommands {
min = 0,
max = 3
)
public Pattern anglecolor(Extent extent, @Optional("true") boolean randomize, @Optional("100") double maxComplexity, @Optional("1") int distance) {
TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity);
return new AngleColorPattern(extent, (int) maxComplexity, randomize, distance);
public Pattern anglecolor(Extent extent, LocalSession session, @Optional("true") boolean randomize, @Optional("100") double maxComplexity, @Optional("1") int distance) {
return new AngleColorPattern(extent, session, distance);
}
@Command(
@ -145,27 +116,25 @@ public class PatternCommands extends MethodCommands {
@Command(
aliases = {"#saturate"},
desc = "Saturate the existing block with a color",
usage = "<color> [randomize=true] [max-complexity=100]",
usage = "<color>",
min = 1,
max = 3
)
public Pattern saturate(Extent extent, String arg, @Optional("true") boolean randomize, @Optional("100") double maxComplexity) {
TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity);
public Pattern saturate(Extent extent, LocalSession session, String arg) {
Color color = ColorUtil.parseColor(arg);
return new SaturatePattern(extent, color.getRGB(), (int) maxComplexity, randomize);
return new SaturatePattern(extent, color.getRGB(), session);
}
@Command(
aliases = {"#averagecolor"},
desc = "Average between the existing block and a color",
usage = "<color> [randomize=true] [max-complexity=100]",
usage = "<color>",
min = 1,
max = 3
)
public Pattern averagecolor(Extent extent, String arg, @Optional("true") boolean randomize, @Optional("100") double maxComplexity) {
TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity);
public Pattern averagecolor(Extent extent, LocalSession session, String arg) {
Color color = ColorUtil.parseColor(arg);
return new AverageColorPattern(extent, color.getRGB(), (int) maxComplexity, randomize);
return new AverageColorPattern(extent, color.getRGB(), session);
}
@Command(
@ -175,33 +144,28 @@ public class PatternCommands extends MethodCommands {
min = 0,
max = 3
)
public Pattern desaturate(Extent extent, @Optional("100") double percent, @Optional("true") boolean randomize, @Optional("100") double maxComplexity) {
TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity);
return new DesaturatePattern(extent, percent / 100d, (int) maxComplexity, randomize);
public Pattern desaturate(Extent extent, LocalSession session, @Optional("100") double percent) {
return new DesaturatePattern(extent, percent / 100d, session);
}
@Command(
aliases = {"#lighten"},
desc = "Lighten the existing block",
usage = "[randomize=true] [max-complexity=100]",
min = 0,
max = 2
)
public Pattern lighten(Extent extent, @Optional("true") boolean randomize, @Optional("100") double maxComplexity) {
TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity);
return new ShadePattern(extent, false, (int) maxComplexity, randomize);
public Pattern lighten(Extent extent, TextureUtil util) {
return new ShadePattern(extent, false, util);
}
@Command(
aliases = {"#darken"},
desc = "Darken the existing block",
usage = "[randomize=true] [max-complexity=100]",
min = 0,
max = 2
)
public Pattern darken(Extent extent, @Optional("true") boolean randomize, @Optional("100") double maxComplexity) {
TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity);
return new ShadePattern(extent, true, (int) maxComplexity, randomize);
public Pattern darken(Extent extent, TextureUtil util) {
return new ShadePattern(extent, true, util);
}
@Command(