Various minor

add debug command moveto512
main command aliases are now configurable
clean thread pools when discarded
switch to BaseBlock and deprecate BlockPattern
Add SparseBlockSet
- uncompressed, memory efficient set of arbitrary bit length numbers
- if access is sequencial, use a compressed data structure instead
change SetQueue time allocation algorithm
This commit is contained in:
Jesse Boyd 2017-06-26 17:56:07 +10:00
parent a7cd6c8715
commit d7d897d11b
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
34 changed files with 662 additions and 152 deletions

View File

@ -378,6 +378,7 @@ public class BukkitQueue_1_12 extends BukkitQueue_0<net.minecraft.server.v1_12_R
iter.remove(); iter.remove();
} }
pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
pool.shutdown();
} }
synchronized (lock) { synchronized (lock) {
lock.notifyAll(); lock.notifyAll();

View File

@ -3,6 +3,7 @@ package com.boydti.fawe.jnbt.anvil;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.PseudoRandom; import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.object.collection.IterableThreadLocal;
import com.boydti.fawe.object.collection.LocalBlockVector2DSet; import com.boydti.fawe.object.collection.LocalBlockVector2DSet;
import com.boydti.fawe.object.collection.SummedAreaTable; import com.boydti.fawe.object.collection.SummedAreaTable;
import com.boydti.fawe.object.schematic.Schematic; import com.boydti.fawe.object.schematic.Schematic;
@ -20,7 +21,6 @@ import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.math.transform.Transform;
@ -562,8 +562,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
public void setOverlay(BufferedImage img, Pattern pattern, boolean white) { public void setOverlay(BufferedImage img, Pattern pattern, boolean white) {
if (pattern instanceof BlockPattern) { if (pattern instanceof BaseBlock) {
setOverlay(img, (char) ((BlockPattern) pattern).getBlock().getCombined(), white); setOverlay(img, (char) ((BaseBlock) pattern).getCombined(), white);
return; return;
} }
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) if (img.getWidth() != getWidth() || img.getHeight() != getLength())
@ -584,8 +584,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
public void setMain(BufferedImage img, Pattern pattern, boolean white) { public void setMain(BufferedImage img, Pattern pattern, boolean white) {
if (pattern instanceof BlockPattern) { if (pattern instanceof BaseBlock) {
setMain(img, (char) ((BlockPattern) pattern).getBlock().getCombined(), white); setMain(img, (char) ((BaseBlock) pattern).getCombined(), white);
return; return;
} }
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) if (img.getWidth() != getWidth() || img.getHeight() != getLength())
@ -606,8 +606,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
public void setFloor(BufferedImage img, Pattern pattern, boolean white) { public void setFloor(BufferedImage img, Pattern pattern, boolean white) {
if (pattern instanceof BlockPattern) { if (pattern instanceof BaseBlock) {
setFloor(img, (char) ((BlockPattern) pattern).getBlock().getCombined(), white); setFloor(img, (char) ((BaseBlock) pattern).getCombined(), white);
return; return;
} }
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) if (img.getWidth() != getWidth() || img.getHeight() != getLength())
@ -627,8 +627,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
public void setColumn(BufferedImage img, Pattern pattern, boolean white) { public void setColumn(BufferedImage img, Pattern pattern, boolean white) {
if (pattern instanceof BlockPattern) { if (pattern instanceof BaseBlock) {
setColumn(img, (char) ((BlockPattern) pattern).getBlock().getCombined(), white); setColumn(img, (char) ((BaseBlock) pattern).getCombined(), white);
return; return;
} }
if (img.getWidth() != getWidth() || img.getHeight() != getLength()) if (img.getWidth() != getWidth() || img.getHeight() != getLength())
@ -651,8 +651,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
public void setOverlay(Mask mask, Pattern pattern) { public void setOverlay(Mask mask, Pattern pattern) {
if (pattern instanceof BlockPattern) { if (pattern instanceof BaseBlock) {
setOverlay(mask, (char) ((BlockPattern) pattern).getBlock().getCombined()); setOverlay(mask, (char) ((BaseBlock) pattern).getCombined());
return; return;
} }
int index = 0; int index = 0;
@ -671,8 +671,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
public void setFloor(Mask mask, Pattern pattern) { public void setFloor(Mask mask, Pattern pattern) {
if (pattern instanceof BlockPattern) { if (pattern instanceof BaseBlock) {
setFloor(mask, (char) ((BlockPattern) pattern).getBlock().getCombined()); setFloor(mask, (char) ((BaseBlock) pattern).getCombined());
return; return;
} }
int index = 0; int index = 0;
@ -690,8 +690,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
public void setMain(Mask mask, Pattern pattern) { public void setMain(Mask mask, Pattern pattern) {
if (pattern instanceof BlockPattern) { if (pattern instanceof BaseBlock) {
setMain(mask, (char) ((BlockPattern) pattern).getBlock().getCombined()); setMain(mask, (char) ((BaseBlock) pattern).getCombined());
return; return;
} }
modifiedMain = true; modifiedMain = true;
@ -710,8 +710,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
public void setColumn(Mask mask, Pattern pattern) { public void setColumn(Mask mask, Pattern pattern) {
if (pattern instanceof BlockPattern) { if (pattern instanceof BaseBlock) {
setColumn(mask, (char) ((BlockPattern) pattern).getBlock().getCombined()); setColumn(mask, (char) ((BaseBlock) pattern).getCombined());
return; return;
} }
modifiedMain = true; modifiedMain = true;
@ -736,8 +736,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
public void setFloor(Pattern value) { public void setFloor(Pattern value) {
if (value instanceof BlockPattern) { if (value instanceof BaseBlock) {
setFloor(((BlockPattern) value).getBlock().getCombined()); setFloor(((BaseBlock) value).getCombined());
return; return;
} }
int index = 0; int index = 0;
@ -753,8 +753,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
public void setColumn(Pattern value) { public void setColumn(Pattern value) {
if (value instanceof BlockPattern) { if (value instanceof BaseBlock) {
setColumn(((BlockPattern) value).getBlock().getCombined()); setColumn(((BaseBlock) value).getCombined());
return; return;
} }
int index = 0; int index = 0;
@ -772,8 +772,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
public void setMain(Pattern value) { public void setMain(Pattern value) {
if (value instanceof BlockPattern) { if (value instanceof BaseBlock) {
setMain(((BlockPattern) value).getBlock().getCombined()); setMain(((BaseBlock) value).getCombined());
return; return;
} }
int index = 0; int index = 0;
@ -790,8 +790,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
public void setOverlay(Pattern value) { public void setOverlay(Pattern value) {
if (overlay == null) overlay = new char[getArea()]; if (overlay == null) overlay = new char[getArea()];
if (value instanceof BlockPattern) { if (value instanceof BaseBlock) {
setOverlay(((BlockPattern) value).getBlock().getCombined()); setOverlay(((BaseBlock) value).getCombined());
return; return;
} }
int index = 0; int index = 0;
@ -1180,4 +1180,10 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
} }
} }
} }
@Override
protected void finalize() throws Throwable {
IterableThreadLocal.clean(indexStore);
super.finalize();
}
} }

View File

@ -9,11 +9,14 @@ import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.util.ArrayUtil; import com.boydti.fawe.util.ArrayUtil;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTConstants; import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.Tag;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -267,6 +270,27 @@ public class MCAChunk extends FaweChunk<Void> {
} }
} }
} }
if (!other.tiles.isEmpty()) {
for (Map.Entry<Short, CompoundTag> entry : other.tiles.entrySet()) {
int key = entry.getKey();
int x = MathMan.untripleBlockCoordX(key);
int y = MathMan.untripleBlockCoordY(key);
int z = MathMan.untripleBlockCoordZ(key);
if (x < minX || x > maxX) continue;
if (z < minZ || z > maxZ) continue;
if (y < minY || y > maxY) continue;
x += offsetX;
y += offsetY;
z += offsetZ;
short pair = MathMan.tripleBlockCoord(x, y, z);
CompoundTag tag = entry.getValue();
Map<String, Tag> map = ReflectionUtils.getMap(tag.getValue());
map.put("x", new IntTag(x + (getX() << 4)));
map.put("y", new IntTag(y));
map.put("z", new IntTag(z + (getZ() << 4)));
tiles.put(pair, tag);
}
}
} }
public void copyFrom(MCAChunk other, int minY, int maxY, int offsetY) { public void copyFrom(MCAChunk other, int minY, int maxY, int offsetY) {
@ -746,6 +770,57 @@ public class MCAChunk extends FaweChunk<Void> {
entities.remove(uuid); entities.remove(uuid);
} }
private final boolean idsEqual(byte[] a, byte[] b) {
// Assumes both are null, or none are (idsEqual - 2d array)
// Assumes length is 4096
if (a == b) return true;
for (char i = 0; i < 4096; i++) {
if (a[i] != b[i]) return false;
}
return true;
}
private final boolean idsEqual(byte[][] a, byte[][] b, boolean matchNullToAir) {
// Assumes length is 16
for (byte i = 0; i < 16; i++) {
if ((a[i] == null) != (b[i] == null)) {
if (matchNullToAir) {
if (b[i] != null) {
for (byte c : b[i]) {
if (c != 0) return false;
}
} else if (a[i] != null) {
for (byte c : a[i]) {
if (c != 0) return false;
}
}
}
return false;
}
}
// Check the chunks close to the ground first
for (byte i = 4; i < 8; i++) {
if (!idsEqual(a[i], b[i])) return false;
}
for (byte i = 3; i >= 0; i--) {
if (!idsEqual(a[i], b[i])) return false;
}
for (byte i = 8; i < 16; i++) {
if (!idsEqual(a[i], b[i])) return false;
}
return true;
}
/**
* Check if the ids match the ids in the other chunk
* @param other
* @param matchNullToAir
* @return
*/
public boolean idsEqual(MCAChunk other, boolean matchNullToAir) {
return idsEqual(other.ids, this.ids, matchNullToAir);
}
@Override @Override
public Void getChunk() { public Void getChunk() {
throw new UnsupportedOperationException("Not applicable for this"); throw new UnsupportedOperationException("Not applicable for this");

View File

@ -5,6 +5,7 @@ import com.boydti.fawe.jnbt.NBTStreamer;
import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.RunnableVal4; import com.boydti.fawe.object.RunnableVal4;
import com.boydti.fawe.object.collection.IterableThreadLocal;
import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.io.BufferedRandomAccessFile; import com.boydti.fawe.object.io.BufferedRandomAccessFile;
import com.boydti.fawe.object.io.FastByteArrayInputStream; import com.boydti.fawe.object.io.FastByteArrayInputStream;
@ -97,6 +98,14 @@ public class MCAFile {
locations = null; locations = null;
} }
@Override
protected void finalize() throws Throwable {
IterableThreadLocal.clean(byteStore1);
IterableThreadLocal.clean(byteStore2);
IterableThreadLocal.clean(byteStore3);
super.finalize();
}
public void setDeleted(boolean deleted) { public void setDeleted(boolean deleted) {
this.deleted = deleted; this.deleted = deleted;
} }
@ -573,5 +582,8 @@ public class MCAFile {
} }
} }
} }
IterableThreadLocal.clean(byteStore1);
IterableThreadLocal.clean(byteStore2);
IterableThreadLocal.clean(byteStore3);
} }
} }

View File

@ -10,6 +10,7 @@ import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.RunnableVal4; import com.boydti.fawe.object.RunnableVal4;
import com.boydti.fawe.object.collection.IterableThreadLocal;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
@ -38,6 +39,12 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
} }
}; };
@Override
protected void finalize() throws Throwable {
IterableThreadLocal.clean(blockStore);
super.finalize();
}
public MCAQueue(FaweQueue parent) { public MCAQueue(FaweQueue parent) {
super(parent.getWEWorld(), new MCAQueueMap()); super(parent.getWEWorld(), new MCAQueueMap());
this.parent = parent; this.parent = parent;
@ -82,6 +89,59 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
} }
} }
/**
*
* @param newChunk
* @param bx
* @param tx
* @param bz
* @param tz
* @param oX
* @param oZ
* @return true if the newChunk has been changed
*/
public boolean copyTo(MCAChunk newChunk, int bx, int tx, int bz, int tz, int oX, int oZ) {
int obx = bx - oX;
int obz = bz - oZ;
int otx = tx - oX;
int otz = tz - oZ;
int otherBCX = (obx) >> 4;
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;
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;
}
public void pasteRegion(MCAQueue from, final RegionWrapper regionFrom, Vector offset) throws IOException { public void pasteRegion(MCAQueue from, final RegionWrapper regionFrom, Vector offset) throws IOException {
int oX = offset.getBlockX(); int oX = offset.getBlockX();
int oZ = offset.getBlockZ(); int oZ = offset.getBlockZ();
@ -206,6 +266,7 @@ public class MCAQueue extends NMSMappedFaweQueue<FaweQueue, FaweChunk, FaweChunk
} }
from.clear(); from.clear();
pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
pool.shutdown();
} }
public <G, T extends MCAFilter<G>> T filterRegion(final T filter, final RegionWrapper region) { public <G, T extends MCAFilter<G>> T filterRegion(final T filter, final RegionWrapper region) {

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.jnbt.anvil; package com.boydti.fawe.jnbt.anvil;
import com.boydti.fawe.object.collection.IterableThreadLocal;
import com.boydti.fawe.object.io.BufferedRandomAccessFile; import com.boydti.fawe.object.io.BufferedRandomAccessFile;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import java.io.File; import java.io.File;
@ -103,8 +104,8 @@ public abstract class MCAWriter {
byte[] fileBuf = new byte[1 << 16]; byte[] fileBuf = new byte[1 << 16];
int mcaXMin = 0; int mcaXMin = 0;
int mcaZMin = 0; int mcaZMin = 0;
int mcaXMax = mcaXMin + width >> 9; int mcaXMax = mcaXMin + ((width - 1) >> 9);
int mcaZMax = mcaZMin + length >> 9; int mcaZMax = mcaZMin + ((length - 1) >> 9);
for (int mcaZ = mcaXMin; mcaZ <= mcaZMax; mcaZ++) { for (int mcaZ = mcaXMin; mcaZ <= mcaZMax; mcaZ++) {
for (int mcaX = mcaXMin; mcaX <= mcaXMax; mcaX++) { for (int mcaX = mcaXMin; mcaX <= mcaXMax; mcaX++) {
@ -208,5 +209,9 @@ public abstract class MCAWriter {
} }
} }
pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
pool.shutdown();
IterableThreadLocal.clean(byteStore1);
IterableThreadLocal.clean(byteStore2);
IterableThreadLocal.clean(deflateStore);
} }
} }

View File

@ -12,7 +12,6 @@ import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.SolidBlockMask; import com.sk89q.worldedit.function.mask.SolidBlockMask;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.RecursiveVisitor; import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
import java.util.Arrays; import java.util.Arrays;
@ -33,7 +32,7 @@ public class SplatterBrush extends ScatterBrush {
if (solid) { if (solid) {
Pattern tmp; Pattern tmp;
try { try {
tmp = new BlockPattern(p.apply(position)); tmp = p.apply(position);
} catch (BiomePattern.BiomePatternException ignore) { } catch (BiomePattern.BiomePatternException ignore) {
tmp = ignore.getPattern(); tmp = ignore.getPattern();
} }

View File

@ -1,5 +1,9 @@
package com.boydti.fawe.object.collection; package com.boydti.fawe.object.collection;
import java.lang.ref.Reference;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
@ -30,7 +34,86 @@ public abstract class IterableThreadLocal<T> extends ThreadLocal<T> implements I
return null; return null;
} }
public void clean() {
IterableThreadLocal.clean(this);
}
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];
}
}
Field tl = Thread.class.getDeclaredField("threadLocals");
tl.setAccessible(true);
Method methodRemove = null;
for (Thread thread : threads) {
if (thread != null) {
Object tlm = tl.get(thread);
if (tlm != null) {
if (methodRemove == null) {
methodRemove = tlm.getClass().getDeclaredMethod("remove", ThreadLocal.class);
methodRemove.setAccessible(true);
}
methodRemove.invoke(tlm, instance);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void cleanAll() {
try {
// Get a reference to the thread locals table of the current thread
Thread thread = Thread.currentThread();
Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
threadLocalsField.setAccessible(true);
Object threadLocalTable = threadLocalsField.get(thread);
// Get a reference to the array holding the thread local variables inside the
// ThreadLocalMap of the current thread
Class threadLocalMapClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
Field tableField = threadLocalMapClass.getDeclaredField("table");
tableField.setAccessible(true);
Object table = tableField.get(threadLocalTable);
// The key to the ThreadLocalMap is a WeakReference object. The referent field of this object
// is a reference to the actual ThreadLocal variable
Field referentField = Reference.class.getDeclaredField("referent");
referentField.setAccessible(true);
for (int i = 0; i < Array.getLength(table); i++) {
// Each entry in the table array of ThreadLocalMap is an Entry object
// representing the thread local reference and its value
Object entry = Array.get(table, i);
if (entry != null) {
// Get a reference to the thread local object and remove it from the table
ThreadLocal threadLocal = (ThreadLocal)referentField.get(entry);
clean(threadLocal);
}
}
} catch(Exception e) {
// We will tolerate an exception here and just log it
throw new IllegalStateException(e);
}
}
public final Collection<T> getAll() { public final Collection<T> getAll() {
return Collections.unmodifiableCollection(allValues); return Collections.unmodifiableCollection(allValues);
} }
@Override
protected void finalize() throws Throwable {
clean(this);
super.finalize();
}
} }

View File

@ -47,7 +47,7 @@ import java.io.Serializable;
* @version 1.0, 2009-03-17 * @version 1.0, 2009-03-17
* @since 1.6 * @since 1.6
*/ */
public class SparseBitSet implements Cloneable, Serializable { public final class SparseBitSet implements Cloneable, Serializable {
/* My apologies for listing all the additional authors, but concepts, code, /* My apologies for listing all the additional authors, but concepts, code,
and even comments have been re-used in this class definition from code in and even comments have been re-used in this class definition from code in
the JDK that was written and/or maintained by these people. I owe a debt, the JDK that was written and/or maintained by these people. I owe a debt,
@ -541,14 +541,6 @@ public class SparseBitSet implements Cloneable, Serializable {
return cache.cardinality; return cache.cardinality;
} }
/**
* Sets the bit at the specified index to <code>false</code>.
*
* @param i a bit index.
* @throws IndexOutOfBoundsException if the specified index is negative
* or equal to Integer.MAX_VALUE.
* @since 1.6
*/
public void clear(int i) { public void clear(int i) {
/* In the interests of speed, no check is made here on whether the /* In the interests of speed, no check is made here on whether the
level3 block goes to all zero. This may be found and corrected level3 block goes to all zero. This may be found and corrected
@ -559,13 +551,14 @@ public class SparseBitSet implements Cloneable, Serializable {
return; return;
final int w = i >> SHIFT3; final int w = i >> SHIFT3;
long[][] a2; long[][] a2;
if ((a2 = bits[w >> SHIFT1]) == null) int ws1 = w >> SHIFT1;
if (bits.length <= ws1 || (a2 = bits[ws1]) == null)
return; return;
long[] a3; long[] a3;
if ((a3 = a2[(w >> SHIFT2) & MASK2]) == null) if ((a3 = a2[(w >> SHIFT2) & MASK2]) == null)
return; return;
a3[w & MASK3] &= ~(1L << i); // Clear the indicated bit a3[w & MASK3] &= ~(1L << i); // Clear the indicated bit
cache.hash = 0; // Invalidate size, etc., cache.hash = 0; // Invalidate size, etc.,
} }
/** /**
@ -1798,6 +1791,7 @@ public class SparseBitSet implements Cloneable, Serializable {
long[][] a2; long[][] a2;
long[] a3; long[] a3;
long word; long word;
int last = 0;
for (int w1 = 0; w1 != aLength1; ++w1) for (int w1 = 0; w1 != aLength1; ++w1)
if ((a2 = a1[w1]) != null) if ((a2 = a1[w1]) != null)
for (int w2 = 0; w2 != LENGTH2; ++w2) for (int w2 = 0; w2 != LENGTH2; ++w2)
@ -1805,7 +1799,7 @@ public class SparseBitSet implements Cloneable, Serializable {
final int base = (w1 << SHIFT1) + (w2 << SHIFT2); final int base = (w1 << SHIFT1) + (w2 << SHIFT2);
for (int w3 = 0; w3 != LENGTH3; ++w3) for (int w3 = 0; w3 != LENGTH3; ++w3)
if ((word = a3[w3]) != 0) { if ((word = a3[w3]) != 0) {
s.writeInt(base + w3); s.writeInt(-last + (last = (base + w3)));
s.writeLong(word); s.writeLong(word);
--count; --count;
} }
@ -1844,8 +1838,9 @@ public class SparseBitSet implements Cloneable, Serializable {
/* Read the keys and values, them into the set array, areas, and blocks. */ /* Read the keys and values, them into the set array, areas, and blocks. */
long[][] a2; long[][] a2;
long[] a3; long[] a3;
int w = 0;
for (int n = 0; n != count; ++n) { for (int n = 0; n != count; ++n) {
final int w = s.readInt(); w += s.readInt();
final int w3 = w & MASK3; final int w3 = w & MASK3;
final int w2 = (w >> SHIFT2) & MASK2; final int w2 = (w >> SHIFT2) & MASK2;
final int w1 = w >> SHIFT1; final int w1 = w >> SHIFT1;

View File

@ -0,0 +1,36 @@
package com.boydti.fawe.object.collection;
import java.io.Serializable;
public class SparseBlockSet implements Serializable {
private SparseBitSet[] sets;
public SparseBlockSet(int depth) {
sets = new SparseBitSet[depth];
for (int i = 0; i < sets.length; i++) {
sets[i] = new SparseBitSet();
}
}
public void setBlock(int index, int id) {
for (int i = 0; i < sets.length; i++) {
SparseBitSet set = sets[i];
if (((id >> i) & 1) == 1) {
set.set(index);
} else {
set.clear(index);
}
}
}
public int getBlock(int index) {
int id = 0;
for (int i = 0; i < sets.length; i++) {
SparseBitSet set = sets[i];
if (set.get(index)) {
id += 1 << i;
}
}
return id;
}
}

View File

@ -60,7 +60,7 @@ import javax.imageio.ImageIO;
aliases = {"createfromheightmap", "createfromimage", "cfhm"}, aliases = {"createfromheightmap", "createfromimage", "cfhm"},
category = CommandCategory.APPEARANCE, category = CommandCategory.APPEARANCE,
requiredType = RequiredType.NONE, requiredType = RequiredType.NONE,
description = "Generate a world from an image heightmap: [More info](https://www.youtube.com/watch?v=cJZk1GTig7A)", description = "Generate a world from an image heightmap: [More info](https://goo.gl/friFbV)",
usage = "/plots cfi [url or dimensions]" usage = "/plots cfi [url or dimensions]"
) )
public class CreateFromImage extends Command { public class CreateFromImage extends Command {

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.regions.general.plot; package com.boydti.fawe.regions.general.plot;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.example.NullFaweChunk; import com.boydti.fawe.example.NullFaweChunk;
import com.boydti.fawe.jnbt.anvil.MCAChunk; import com.boydti.fawe.jnbt.anvil.MCAChunk;
import com.boydti.fawe.jnbt.anvil.MCAQueue; import com.boydti.fawe.jnbt.anvil.MCAQueue;
@ -13,6 +14,8 @@ import com.intellectualcrafters.plot.commands.CommandCategory;
import com.intellectualcrafters.plot.commands.MainCommand; import com.intellectualcrafters.plot.commands.MainCommand;
import com.intellectualcrafters.plot.commands.RequiredType; import com.intellectualcrafters.plot.commands.RequiredType;
import com.intellectualcrafters.plot.config.C; import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.database.SQLManager;
import com.intellectualcrafters.plot.generator.HybridPlotWorld; import com.intellectualcrafters.plot.generator.HybridPlotWorld;
import com.intellectualcrafters.plot.object.Location; import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.Plot;
@ -27,6 +30,11 @@ import com.plotsquared.general.commands.Command;
import com.plotsquared.general.commands.CommandDeclaration; import com.plotsquared.general.commands.CommandDeclaration;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.World;
@CommandDeclaration( @CommandDeclaration(
command = "moveto512", command = "moveto512",
@ -41,8 +49,107 @@ public class MoveTo512 extends Command {
super(MainCommand.getInstance(), true); super(MainCommand.getInstance(), true);
} }
public static void main(String[] args) { private MCAChunk emptyPlot(MCAChunk chunk, HybridPlotWorld hpw) {
int maxLayer = (hpw.PLOT_HEIGHT) >> 4;
for (int i = maxLayer + 1; i < chunk.ids.length; i++) {
chunk.ids[i] = null;
chunk.data[i] = null;
}
for (int layer = 0; layer <= maxLayer; layer++) {
byte[] ids = chunk.ids[layer];
if (ids == null) {
ids = chunk.ids[layer] = new byte[4096];
chunk.data[layer] = new byte[2048];
chunk.skyLight[layer] = new byte[2048];
chunk.blockLight[layer] = new byte[2048];
} else {
Arrays.fill(ids, (byte) 0);
Arrays.fill(chunk.data[layer], (byte) 0);
Arrays.fill(chunk.skyLight[layer], (byte) 0);
Arrays.fill(chunk.blockLight[layer], (byte) 0);
}
if (layer == maxLayer) {
int yMax = hpw.PLOT_HEIGHT & 15;
for (int y = yMax + 1; y < 15; y++) {
Arrays.fill(chunk.skyLight[layer], y << 7, (y << 7) + 128, (byte) 255);
}
if (layer == 0) {
Arrays.fill(ids, 0, 256, (byte) 7);
for (int y = 1; y < yMax; y++) {
int y8 = y << 8;
Arrays.fill(ids, y8, y8 + 256, (byte) 3);
}
} else {
for (int y = 0; y < yMax; y++) {
int y8 = y << 8;
Arrays.fill(ids, y8, y8 + 256, (byte) 3);
}
}
int yMax15 = yMax & 15;
int yMax158 = yMax15 << 8;
Arrays.fill(ids, yMax158, yMax158 + 256, (byte) 2);
if (yMax != 15) {
Arrays.fill(ids, yMax158 + 256, 4096, (byte) 0);
}
} else if (layer == 0){
Arrays.fill(ids, 256, 4096, (byte) 3);
Arrays.fill(ids, 0, 256, (byte) 7);
} else {
Arrays.fill(ids, (byte) 3);
}
}
return chunk;
}
private MCAChunk emptyRoad(MCAChunk chunk, HybridPlotWorld hpw) {
int maxLayer = (hpw.ROAD_HEIGHT) >> 4;
for (int i = maxLayer + 1; i < chunk.ids.length; i++) {
chunk.ids[i] = null;
chunk.data[i] = null;
}
for (int layer = 0; layer <= maxLayer; layer++) {
byte[] ids = chunk.ids[layer];
if (ids == null) {
ids = chunk.ids[layer] = new byte[4096];
chunk.data[layer] = new byte[2048];
chunk.skyLight[layer] = new byte[2048];
chunk.blockLight[layer] = new byte[2048];
} else {
Arrays.fill(ids, (byte) 0);
Arrays.fill(chunk.data[layer], (byte) 0);
Arrays.fill(chunk.skyLight[layer], (byte) 0);
Arrays.fill(chunk.blockLight[layer], (byte) 0);
}
if (layer == maxLayer) {
int yMax = hpw.ROAD_HEIGHT & 15;
for (int y = yMax + 1; y < 15; y++) {
Arrays.fill(chunk.skyLight[layer], y << 7, (y << 7) + 128, (byte) 255);
}
if (layer == 0) {
Arrays.fill(ids, 0, 256, (byte) 7);
for (int y = 1; y <= yMax; y++) {
int y8 = y << 8;
Arrays.fill(ids, y8, y8 + 256, (byte) hpw.ROAD_BLOCK.id);
}
} else {
for (int y = 0; y <= yMax; y++) {
int y8 = y << 8;
Arrays.fill(ids, y8, y8 + 256, (byte) hpw.ROAD_BLOCK.id);
}
}
if (yMax != 15) {
int yMax15 = yMax & 15;
int yMax158 = yMax15 << 8;
Arrays.fill(ids, yMax158 + 256, 4096, (byte) 0);
}
} else if (layer == 0){
Arrays.fill(ids, 256, 4096, (byte) hpw.ROAD_BLOCK.id);
Arrays.fill(ids, 0, 256, (byte) 7);
} else {
Arrays.fill(ids, (byte) hpw.ROAD_BLOCK.id);
}
}
return chunk;
} }
@Override @Override
@ -52,46 +159,92 @@ public class MoveTo512 extends Command {
check(area, C.COMMAND_SYNTAX, getUsage()); check(area, C.COMMAND_SYNTAX, getUsage());
checkTrue(area instanceof HybridPlotWorld, C.NOT_VALID_HYBRID_PLOT_WORLD); checkTrue(area instanceof HybridPlotWorld, C.NOT_VALID_HYBRID_PLOT_WORLD);
for (World world : Bukkit.getWorlds()) {
world.save();
}
FaweQueue defaultQueue = SetQueue.IMP.getNewQueue(area.worldname, true, false); FaweQueue defaultQueue = SetQueue.IMP.getNewQueue(area.worldname, true, false);
MCAQueue queueFrom = new MCAQueue(area.worldname, defaultQueue.getSaveFolder(), defaultQueue.hasSky()); MCAQueue queueFrom = new MCAQueue(area.worldname, defaultQueue.getSaveFolder(), defaultQueue.hasSky());
String world = args[0]; String world = args[0];
File folder = new File(PS.imp().getWorldContainer(), world); File folder = new File(PS.imp().getWorldContainer(), world + File.separator + "region");
checkTrue(!folder.exists(), C.SETUP_WORLD_TAKEN, world); checkTrue(!folder.exists(), C.SETUP_WORLD_TAKEN, world);
HybridPlotWorld hpw = (HybridPlotWorld) area; HybridPlotWorld hpw = (HybridPlotWorld) area;
int minRoad = 5; int minRoad = 7;
int pLen = Math.max(hpw.PLOT_WIDTH, 512 - minRoad); int pLen = Math.min(hpw.PLOT_WIDTH, 512 - minRoad);
int roadWidth = pLen - 512; int roadWidth = 512 - pLen;
int roadPosLower; int roadPosLower;
if ((roadWidth & 1) == 0) { if ((roadWidth & 1) == 0) {
roadPosLower = (short) (Math.floor(roadWidth / 2) - 1); roadPosLower = (short) (Math.floor(roadWidth / 2) - 1);
} else { } else {
roadPosLower = (short) Math.floor(roadWidth / 2); roadPosLower = (short) Math.floor(roadWidth / 2);
} }
int roadPosUpper = 512 - roadWidth + roadPosLower; int roadPosUpper = 512 - roadWidth + roadPosLower + 1;
final ThreadLocal<boolean[]> roadCache = new ThreadLocal<boolean[]>() {
@Override
protected boolean[] initialValue() {
return new boolean[64];
}
};
MCAChunk reference = new MCAChunk(null, 0, 0);
{
reference.fillCuboid(0, 15, 0, 0, 0, 15, 7, (byte) 0);
reference.fillCuboid(0, 15, 1, hpw.PLOT_HEIGHT - 1, 0, 15, 3, (byte) 0);
reference.fillCuboid(0, 15, hpw.PLOT_HEIGHT, hpw.PLOT_HEIGHT, 0, 15, 2, (byte) 0);
}
Map<PlotId, Plot> rawPlots = area.getPlotsRaw();
ArrayList<Plot> plots = new ArrayList(rawPlots.values());
int size = plots.size();
PlotId nextId = new PlotId(0, 0); PlotId nextId = new PlotId(0, 0);
for (Plot plot : area.getPlots()) {
long start = System.currentTimeMillis();
int percent = 0;
for (Plot plot : plots) {
Fawe.debug(((percent += 100) / size) + "% complete!");
Location bot = plot.getBottomAbs(); Location bot = plot.getBottomAbs();
Location top = plot.getTopAbs(); Location top = plot.getTopAbs();
int oX = roadPosLower - bot.getX(); int oX = roadPosLower - bot.getX() + 1;
int oZ = roadPosLower - bot.getZ(); int oZ = roadPosLower - bot.getZ() + 1;
{ // Move
PlotId id = plot.getId();
Fawe.debug("Moving " + plot.getId() + " to " + nextId);
id.x = nextId.x;
id.y = nextId.y;
id.recalculateHash();
}
MCAWriter writer = new MCAWriter(512, 512, folder) { MCAWriter writer = new MCAWriter(512, 512, folder) {
@Override @Override
public boolean shouldWrite(int chunkX, int chunkZ) { public boolean shouldWrite(int chunkX, int chunkZ) {
return true; int bx = chunkX << 4;
int bz = chunkZ << 4;
int tx = bx + 15;
int tz = bz + 15;
return !(tx < roadPosLower || tz < roadPosLower || bx > roadPosUpper || bz > roadPosUpper);
} }
@Override @Override
public MCAChunk write(MCAChunk newChunk, int bx, int tx, int bz, int tz) { public MCAChunk write(MCAChunk newChunk, int bx, int tx, int bz, int tz) {
Arrays.fill(newChunk.biomes, (byte) 4);
if (!newChunk.tiles.isEmpty()) newChunk.tiles.clear();
if (tx < roadPosLower || tz < roadPosLower || bx > roadPosUpper || bz > roadPosUpper) { if (tx < roadPosLower || tz < roadPosLower || bx > roadPosUpper || bz > roadPosUpper) {
newChunk.fillCuboid(0, 15, 0, hpw.ROAD_HEIGHT, 0, 15, hpw.ROAD_BLOCK.id, hpw.ROAD_BLOCK.data); return emptyRoad(newChunk, hpw);
newChunk.fillCuboid(0, 15, 0, 0, 0, 15, 7, (byte) 0);
} else { } else {
boolean partRoad = (bx <= roadPosLower || bz <= roadPosLower || tx >= roadPosUpper || tz >= roadPosUpper);
boolean changed = false;
emptyPlot(newChunk, hpw);
int obx = bx - oX; int obx = bx - oX;
int obz = bz - oZ; int obz = bz - oZ;
int otx = tx - oX; int otx = tx - oX;
@ -102,13 +255,17 @@ public class MoveTo512 extends Command {
int otherTCZ = (otz) >> 4; int otherTCZ = (otz) >> 4;
int cx = newChunk.getX(); int cx = newChunk.getX();
int cz = newChunk.getZ(); int cz = newChunk.getZ();
int cbx = (cx << 4) - oX; int cbx = (cx << 4) - oX;
int cbz = (cz << 4) - oZ; int cbz = (cz << 4) - oZ;
for (int otherCZ = otherBCZ; otherCZ <= otherTCZ; otherCZ++) { for (int otherCZ = otherBCZ; otherCZ <= otherTCZ; otherCZ++) {
for (int otherCX = otherBCX; otherCX <= otherTCX; otherCX++) { for (int otherCX = otherBCX; otherCX <= otherTCX; otherCX++) {
FaweChunk chunk = queueFrom.getFaweChunk(otherCX, otherCZ); FaweChunk chunk;
synchronized (queueFrom) {
chunk = queueFrom.getFaweChunk(otherCX, otherCZ);
}
if (!(chunk instanceof NullFaweChunk)) { if (!(chunk instanceof NullFaweChunk)) {
changed = true;
MCAChunk other = (MCAChunk) chunk; MCAChunk other = (MCAChunk) chunk;
int ocbx = otherCX << 4; int ocbx = otherCX << 4;
int ocbz = otherCZ << 4; int ocbz = otherCZ << 4;
@ -125,43 +282,50 @@ public class MoveTo512 extends Command {
} }
} }
} }
if (bx < roadPosLower || bz < roadPosLower || tx > roadPosUpper || tz > roadPosUpper) { if (!changed || reference.idsEqual(newChunk, false)) {
boolean[] gx = new boolean[16]; return null;
boolean[] wx = new boolean[16]; }
boolean[] gz = new boolean[16]; if (partRoad) {
boolean[] wz = new boolean[16]; boolean[] rwp = roadCache.get();
for (short i = 0; i < 16; i++) { for (short i = 0; i < 16; i++) {
int vx = bx + i; int vx = bx + i;
int vz = bz + i; int vz = bz + i;
gz[i] = vz < roadPosLower || vz > roadPosUpper; rwp[i] = vx < roadPosLower || vx > roadPosUpper;
wz[i] = vz == roadPosLower || vz == roadPosUpper; rwp[i + 32] = vx == roadPosLower || vx == roadPosUpper;
gx[i] = vx < roadPosLower || vx > roadPosUpper; rwp[i + 16] = vz < roadPosLower || vz > roadPosUpper;
wx[i] = vx == roadPosLower || vx == roadPosUpper; rwp[i + 48] = vz == roadPosLower || vz == roadPosUpper;
} }
for (int z = 0; z < 16; z++) { for (int z = 0; z < 16; z++) {
final boolean rwpz16 = rwp[z + 16];
final boolean rwpz48 = rwp[z + 48];
for (int x = 0; x < 16; x++) { for (int x = 0; x < 16; x++) {
if (gx[x] || gz[z]) { if (rwpz16 || rwp[x]) {
for (int y = 1; y < hpw.ROAD_HEIGHT; y++) { for (int y = 1; y <= hpw.ROAD_HEIGHT; y++) {
newChunk.setBlock(x, y, z, hpw.ROAD_BLOCK.id, hpw.ROAD_BLOCK.data); newChunk.setBlock(x, y, z, hpw.ROAD_BLOCK.id, hpw.ROAD_BLOCK.data);
} }
} else if (wx[x] || wz[z]) { for (int y = hpw.ROAD_HEIGHT + 1; y < 256; y++) {
for (int y = 1; y < hpw.WALL_HEIGHT; y++) { newChunk.setBlock(x, y, z, 0, 0);
}
} else if (rwpz48 || rwp[x + 32]) {
for (int y = 1; y <= hpw.WALL_HEIGHT; y++) {
newChunk.setBlock(x, y, z, hpw.WALL_FILLING.id, hpw.WALL_FILLING.data); newChunk.setBlock(x, y, z, hpw.WALL_FILLING.id, hpw.WALL_FILLING.data);
} }
newChunk.setBlock(x, hpw.WALL_HEIGHT, z, hpw.CLAIMED_WALL_BLOCK.id, hpw.CLAIMED_WALL_BLOCK.data); for (int y = hpw.WALL_HEIGHT + 2; y < 256; y++) {
newChunk.setBlock(x, y, z, 0, 0);
}
newChunk.setBlock(x, hpw.WALL_HEIGHT + 1, z, hpw.CLAIMED_WALL_BLOCK.id, hpw.CLAIMED_WALL_BLOCK.data);
} }
} }
} }
newChunk.fillCuboid(0, 15, 0, 0, 0, 15, 7, (byte) 0);
} }
} }
return newChunk; return newChunk;
} }
}; };
writer.setMCAOffset(nextId.x, nextId.y); writer.setMCAOffset(nextId.x - 1, nextId.y - 1);
try { try {
writer.generate(); writer.generate();
System.gc();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
return; return;
@ -169,7 +333,28 @@ public class MoveTo512 extends Command {
queueFrom.clear(); queueFrom.clear();
nextId = nextId.getNextId(1); nextId = nextId.getNextId(1);
} }
Fawe.debug("Anvil copy completed in " + ((System.currentTimeMillis() - start) / 1000d) + "s");
Fawe.debug("Updating database, please wait...");
rawPlots.clear();
for (Plot plot : plots) {
rawPlots.put(plot.getId(), plot);
DBFunc.movePlot(plot, plot);
}
SQLManager db = (SQLManager) DBFunc.dbManager;
db.addNotifyTask(new Runnable() {
@Override
public void run() {
Fawe.debug("Instructions");
Fawe.debug(" - Stop the server");
Fawe.debug(" - Rename the folder for the new world to the current world");
Fawe.debug(" - Change the plot size to " + pLen);
Fawe.debug(" - Change the road size to " + roadWidth);
Fawe.debug(" - Start the server");
}
});
ConfigurationSection section = PS.get().worlds.getConfigurationSection("worlds." + world); ConfigurationSection section = PS.get().worlds.getConfigurationSection("worlds." + world);
if (section == null) section = PS.get().worlds.createSection("worlds." + world);
area.saveConfiguration(section); area.saveConfiguration(section);
section.set("plot.size", pLen); section.set("plot.size", pLen);
section.set("road.width", roadWidth); section.set("road.width", roadWidth);

View File

@ -36,10 +36,10 @@ public class PlotSquaredFeature extends FaweMaskManager {
new PlotSetBiome(); new PlotSetBiome();
} }
try { try {
new MoveTo512();
if (Settings.Enabled_Components.WORLDS) { if (Settings.Enabled_Components.WORLDS) {
new CreateFromImage(); new CreateFromImage();
new ReplaceAll(); new ReplaceAll();
new MoveTo512();
} }
} catch (Throwable e) { } catch (Throwable e) {
Fawe.debug("You need to update PlotSquared to access the CFI and REPLACEALL commands"); Fawe.debug("You need to update PlotSquared to access the CFI and REPLACEALL commands");

View File

@ -34,7 +34,7 @@ public class SetQueue {
* Used to calculate elapsed time in milliseconds and ensure block placement doesn't lag the server * Used to calculate elapsed time in milliseconds and ensure block placement doesn't lag the server
*/ */
private long last; private long last;
private long secondLast; private long allocate = 50;
private long lastSuccess; private long lastSuccess;
/** /**
@ -78,6 +78,7 @@ public class SetQueue {
@Override @Override
public void run() { public void run() {
try { try {
long now = System.currentTimeMillis();
targetTPS = 18 - Math.max(Settings.IMP.QUEUE.EXTRA_TIME_MS * 0.05, 0); targetTPS = 18 - Math.max(Settings.IMP.QUEUE.EXTRA_TIME_MS * 0.05, 0);
do { do {
Runnable task = tasks.poll(); Runnable task = tasks.poll();
@ -88,13 +89,15 @@ public class SetQueue {
} }
} while (Fawe.get().getTimer().isAbove(targetTPS)); } while (Fawe.get().getTimer().isAbove(targetTPS));
if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) { if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) {
lastSuccess = System.currentTimeMillis(); last = lastSuccess = now;
runEmptyTasks(); runEmptyTasks();
return; return;
} }
if (!MemUtil.isMemoryFree()) { if (!MemUtil.isMemoryFree()) {
final int mem = MemUtil.calculateMemory(); final int mem = MemUtil.calculateMemory();
if (mem != Integer.MAX_VALUE) { if (mem != Integer.MAX_VALUE) {
last = now;
allocate = Math.max(5, allocate - 1);
if ((mem <= 1) && Settings.IMP.PREVENT_CRASHES) { if ((mem <= 1) && Settings.IMP.PREVENT_CRASHES) {
for (FaweQueue queue : getAllQueues()) { for (FaweQueue queue : getAllQueues()) {
queue.saveMemory(); queue.saveMemory();
@ -110,13 +113,26 @@ public class SetQueue {
} }
} }
FaweQueue queue = getNextQueue(); FaweQueue queue = getNextQueue();
if (queue == null || !Fawe.get().getTimer().isAbove(targetTPS)) { if (queue == null) {
last = now;
return;
}
if (!Fawe.get().getTimer().isAbove(targetTPS)) {
allocate = Math.max(5, allocate - 1);
last = now;
return; return;
} }
if (Thread.currentThread() != Fawe.get().getMainThread()) { if (Thread.currentThread() != Fawe.get().getMainThread()) {
throw new IllegalStateException("This shouldn't be possible for placement to occur off the main thread"); throw new IllegalStateException("This shouldn't be possible for placement to occur off the main thread");
} }
long time = Settings.IMP.QUEUE.EXTRA_TIME_MS + 50 + Math.min((50 + SetQueue.this.last) - (SetQueue.this.last = System.currentTimeMillis()), SetQueue.this.secondLast - System.currentTimeMillis()); long diff = (50 + SetQueue.this.last) - (SetQueue.this.last = now);
long absDiff = Math.abs(diff);
if (diff == 0) {
allocate = Math.min(50, allocate + 1);
} else if (diff < 0) {
allocate = Math.max(5, allocate + diff);
}
long time = Settings.IMP.QUEUE.EXTRA_TIME_MS + allocate - absDiff - System.currentTimeMillis() + now;
// Disable the async catcher as it can't discern async vs parallel // Disable the async catcher as it can't discern async vs parallel
boolean parallel = Settings.IMP.QUEUE.PARALLEL_THREADS > 1; boolean parallel = Settings.IMP.QUEUE.PARALLEL_THREADS > 1;
queue.startSet(parallel); queue.startSet(parallel);
@ -142,7 +158,6 @@ public class SetQueue {
// completer = new ExecutorCompletionService(pool); // completer = new ExecutorCompletionService(pool);
// } // }
} }
secondLast = System.currentTimeMillis();
queue.endSet(parallel); queue.endSet(parallel);
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -1444,7 +1444,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public int fillXZ(final Vector origin, final BaseBlock block, final double radius, final int depth, final boolean recursive) throws MaxChangedBlocksException { public int fillXZ(final Vector origin, final BaseBlock block, final double radius, final int depth, final boolean recursive) throws MaxChangedBlocksException {
return this.fillXZ(origin, new BlockPattern(block), radius, depth, recursive); return this.fillXZ(origin, (Pattern) block, radius, depth, recursive);
} }
/** /**
@ -1562,7 +1562,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
final Region region = new CuboidRegion(this.getWorld(), // Causes clamping of Y range final Region region = new CuboidRegion(this.getWorld(), // Causes clamping of Y range
position.add(-apothem + 1, 0, -apothem + 1), position.add(apothem - 1, height - 1, apothem - 1)); position.add(-apothem + 1, 0, -apothem + 1), position.add(apothem - 1, height - 1, apothem - 1));
final Pattern pattern = new BlockPattern(new BaseBlock(BlockID.AIR)); final Pattern pattern = (new BaseBlock(BlockID.AIR));
return this.setBlocks(region, pattern); return this.setBlocks(region, pattern);
} }
@ -1583,7 +1583,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
final Region region = new CuboidRegion(this.getWorld(), // Causes clamping of Y range final Region region = new CuboidRegion(this.getWorld(), // Causes clamping of Y range
position.add(-apothem + 1, 0, -apothem + 1), position.add(apothem - 1, -height + 1, apothem - 1)); position.add(-apothem + 1, 0, -apothem + 1), position.add(apothem - 1, -height + 1, apothem - 1));
final Pattern pattern = new BlockPattern(new BaseBlock(BlockID.AIR)); final Pattern pattern = (new BaseBlock(BlockID.AIR));
return this.setBlocks(region, pattern); return this.setBlocks(region, pattern);
} }
@ -1605,7 +1605,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
final Vector adjustment = new Vector(1, 1, 1).multiply(apothem - 1); final Vector adjustment = new Vector(1, 1, 1).multiply(apothem - 1);
final Region region = new CuboidRegion(this.getWorld(), // Causes clamping of Y range final Region region = new CuboidRegion(this.getWorld(), // Causes clamping of Y range
position.add(adjustment.multiply(-1)), position.add(adjustment)); position.add(adjustment.multiply(-1)), position.add(adjustment));
final Pattern pattern = new BlockPattern(new BaseBlock(BlockID.AIR)); final Pattern pattern = (new BaseBlock(BlockID.AIR));
return this.replaceBlocks(region, mask, pattern); return this.replaceBlocks(region, mask, pattern);
} }
@ -1657,7 +1657,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
} }
try { try {
if (hasExtraExtents()) { if (hasExtraExtents()) {
RegionVisitor visitor = new RegionVisitor(region, new BlockReplace(extent, new BlockPattern(block)), this); RegionVisitor visitor = new RegionVisitor(region, new BlockReplace(extent, (block)), this);
Operations.completeBlindly(visitor); Operations.completeBlindly(visitor);
this.changes += visitor.getAffected(); this.changes += visitor.getAffected();
} else { } else {
@ -1689,7 +1689,10 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
checkNotNull(region); checkNotNull(region);
checkNotNull(pattern); checkNotNull(pattern);
if (pattern instanceof BlockPattern) { if (pattern instanceof BlockPattern) {
return setBlocks(region, ((BlockPattern) pattern).getBlock()); return setBlocks(region, ((BaseBlock) pattern));
}
if (pattern instanceof BaseBlock) {
return setBlocks(region, (BaseBlock) pattern);
} }
final BlockReplace replace = new BlockReplace(EditSession.this, pattern); final BlockReplace replace = new BlockReplace(EditSession.this, pattern);
final RegionVisitor visitor = new RegionVisitor(region, replace, queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null); final RegionVisitor visitor = new RegionVisitor(region, replace, queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null);
@ -1714,7 +1717,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
// return changes = region.getArea(); // return changes = region.getArea();
// } // }
// TODO fast replace // TODO fast replace
return this.replaceBlocks(region, filter, new BlockPattern(replacement)); return this.replaceBlocks(region, filter, (replacement));
} }
@ -1730,8 +1733,8 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public int replaceBlocks(final Region region, final Set<BaseBlock> filter, final Pattern pattern) throws MaxChangedBlocksException { public int replaceBlocks(final Region region, final Set<BaseBlock> filter, final Pattern pattern) throws MaxChangedBlocksException {
// if (pattern instanceof BlockPattern) { // if (pattern instanceof BaseBlock) {
// return replaceBlocks(region, filter, ((BlockPattern) pattern).getBlock()); // return replaceBlocks(region, filter, ((BaseBlock) pattern));
// } // }
final Mask mask = filter == null ? new ExistingBlockMask(this) : new FuzzyBlockMask(this, filter); final Mask mask = filter == null ? new ExistingBlockMask(this) : new FuzzyBlockMask(this, filter);
return this.replaceBlocks(region, mask, pattern); return this.replaceBlocks(region, mask, pattern);
@ -1794,7 +1797,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public int makeCuboidFaces(final Region region, final BaseBlock block) throws MaxChangedBlocksException { public int makeCuboidFaces(final Region region, final BaseBlock block) throws MaxChangedBlocksException {
return this.makeCuboidFaces(region, new BlockPattern(block)); return this.makeCuboidFaces(region, (Pattern) (block));
} }
/** /**
@ -1848,7 +1851,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public int makeCuboidWalls(final Region region, final BaseBlock block) throws MaxChangedBlocksException { public int makeCuboidWalls(final Region region, final BaseBlock block) throws MaxChangedBlocksException {
return this.makeCuboidWalls(region, new BlockPattern(block)); return this.makeCuboidWalls(region, (Pattern) (block));
} }
/** /**
@ -1917,7 +1920,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public int overlayCuboidBlocks(final Region region, final BaseBlock block) throws MaxChangedBlocksException { public int overlayCuboidBlocks(final Region region, final BaseBlock block) throws MaxChangedBlocksException {
checkNotNull(block); checkNotNull(block);
return this.overlayCuboidBlocks(region, new BlockPattern(block)); return this.overlayCuboidBlocks(region, (Pattern) (block));
} }
/** /**
@ -2013,7 +2016,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
final Vector to = region.getMinimumPoint(); final Vector to = region.getMinimumPoint();
final ForwardExtentCopy copy = new ForwardExtentCopy(EditSession.this, region, EditSession.this, to); final ForwardExtentCopy copy = new ForwardExtentCopy(EditSession.this, region, EditSession.this, to);
final com.sk89q.worldedit.function.pattern.Pattern pattern = replacement != null ? new BlockPattern(replacement) : new BlockPattern(new BaseBlock(BlockID.AIR)); final com.sk89q.worldedit.function.pattern.Pattern pattern = replacement != null ? replacement : (new BaseBlock(BlockID.AIR));
final BlockReplace remove = new BlockReplace(EditSession.this, pattern) { final BlockReplace remove = new BlockReplace(EditSession.this, pattern) {
private MutableBlockVector mutable = new MutableBlockVector(); private MutableBlockVector mutable = new MutableBlockVector();
@ -2089,7 +2092,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
new EllipsoidRegion(null, origin, new EllipsoidRegion(null, origin,
new Vector(radius, radius, radius))), liquidMask); new Vector(radius, radius, radius))), liquidMask);
final BlockReplace replace = new BlockReplace(EditSession.this, new BlockPattern(new BaseBlock(BlockID.AIR))); final BlockReplace replace = new BlockReplace(EditSession.this, new BaseBlock(BlockID.AIR));
final RecursiveVisitor visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1), this); final RecursiveVisitor visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1), this);
// Around the origin in a 3x3 block // Around the origin in a 3x3 block
@ -2148,7 +2151,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
new RegionMask(new EllipsoidRegion(null, origin, new Vector(radius, radius, radius))), new RegionMask(new EllipsoidRegion(null, origin, new Vector(radius, radius, radius))),
blockMask); blockMask);
BlockReplace replace = new BlockReplace(this, new BlockPattern(FaweCache.getBlock(stationary, 0))); BlockReplace replace = new BlockReplace(this, (FaweCache.getBlock(stationary, 0)));
NonRisingVisitor visitor = new NonRisingVisitor(mask, replace, (int) (radius * 2 + 1), this); NonRisingVisitor visitor = new NonRisingVisitor(mask, replace, (int) (radius * 2 + 1), this);
// Around the origin in a 3x3 block // Around the origin in a 3x3 block

View File

@ -80,7 +80,6 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.function.mask.BlockMask; import com.sk89q.worldedit.function.mask.BlockMask;
import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.command.InvalidUsageException; import com.sk89q.worldedit.util.command.InvalidUsageException;
@ -102,7 +101,7 @@ import javafx.scene.paint.Color;
* Commands to set brush shape. * Commands to set brush shape.
*/ */
@Command(aliases = {"brush", "br", "/b"}, @Command(aliases = {"brush", "br", "/b"},
desc = "Commands to build and draw from far away. [More Info](https://github.com/boy0001/FastAsyncWorldedit/wiki/Brushes)" desc = "Commands to build and draw from far away. [More Info](https://git.io/vSPYf)"
) )
public class BrushCommands extends MethodCommands { public class BrushCommands extends MethodCommands {
@ -287,8 +286,8 @@ public class BrushCommands extends MethodCommands {
} else { } else {
brush = new SphereBrush(); brush = new SphereBrush();
} }
if (fill instanceof BlockPattern) { if (fill instanceof BaseBlock) {
BaseBlock block = ((BlockPattern) fill).getBlock(); BaseBlock block = (BaseBlock) fill;
switch (block.getId()) { switch (block.getId()) {
case BlockID.SAND: case BlockID.SAND:
case BlockID.GRAVEL: case BlockID.GRAVEL:
@ -595,7 +594,7 @@ public class BrushCommands extends MethodCommands {
public BrushSettings extinguishBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius, CommandContext context) throws WorldEditException { public BrushSettings extinguishBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius); worldEdit.checkMaxBrushRadius(radius);
Pattern fill = new BlockPattern(new BaseBlock(0)); Pattern fill = (new BaseBlock(0));
return get(context) return get(context)
.setBrush(new SphereBrush()) .setBrush(new SphereBrush())
.setSize(radius) .setSize(radius)

View File

@ -45,7 +45,8 @@ import java.util.zip.GZIPInputStream;
/** /**
* Tool commands. * Tool commands.
*/ */
@Command(aliases = {}, desc = "Tool commands")
@Command(aliases = {"brush", "br", "/b"}, desc = "Tool commands")
public class BrushOptionsCommands extends MethodCommands { public class BrushOptionsCommands extends MethodCommands {
public BrushOptionsCommands(WorldEdit we) { public BrushOptionsCommands(WorldEdit we) {

View File

@ -73,7 +73,7 @@ import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
/** /**
* Clipboard commands. * Clipboard commands.
*/ */
@Command(aliases = {}, desc = "Related commands to copy and pasting blocks: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Clipboard)") @Command(aliases = {}, desc = "Related commands to copy and pasting blocks: [More Info](https://goo.gl/z2ScQR)")
public class ClipboardCommands { public class ClipboardCommands {
private final WorldEdit worldEdit; private final WorldEdit worldEdit;

View File

@ -68,7 +68,7 @@ import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
/** /**
* Commands for the generation of shapes and other objects. * Commands for the generation of shapes and other objects.
*/ */
@Command(aliases = {}, desc = "Create structures and features: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Generation)") @Command(aliases = {}, desc = "Create structures and features: [More Info](https://goo.gl/KuLFRW)")
public class GenerationCommands { public class GenerationCommands {
private final WorldEdit worldEdit; private final WorldEdit worldEdit;
@ -125,8 +125,8 @@ public class GenerationCommands {
public void image(Player player, LocalSession session, EditSession editSession, String arg, @Optional("true") boolean randomize, @Optional("100") int threshold) throws WorldEditException, ParameterException, IOException { public void image(Player player, LocalSession session, EditSession editSession, String arg, @Optional("true") boolean randomize, @Optional("100") int threshold) throws WorldEditException, ParameterException, IOException {
TextureUtil tu = Fawe.get().getCachedTextureUtil(randomize, 0, threshold); TextureUtil tu = Fawe.get().getCachedTextureUtil(randomize, 0, threshold);
URL url = new URL(arg); URL url = new URL(arg);
if (!url.getHost().equalsIgnoreCase("i.imgur.com")) { if (!url.getHost().equalsIgnoreCase("i.imgur.com") && !url.getHost().equalsIgnoreCase("empcraft.com")) {
throw new IOException("Only i.imgur.com links are allowed!"); throw new IOException("Only i.imgur.com or empcraft.com/ui links are allowed!");
} }
FawePlayer<Object> fp = FawePlayer.wrap(player); FawePlayer<Object> fp = FawePlayer.wrap(player);
BufferedImage image = MainUtil.toRGB(ImageIO.read(url)); BufferedImage image = MainUtil.toRGB(ImageIO.read(url));

View File

@ -46,7 +46,7 @@ import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.biome.BaseBiome;
@Command(aliases = {"masks"}, @Command(aliases = {"masks"},
desc = "Help for the various masks. [More Info](https://github.com/boy0001/FastAsyncWorldedit/wiki/WorldEdit---FAWE-mask-list)" desc = "Help for the various masks. [More Info](https://git.io/v9r4K)"
) )
public class MaskCommands extends MethodCommands { public class MaskCommands extends MethodCommands {
public MaskCommands(WorldEdit worldEdit) { public MaskCommands(WorldEdit worldEdit) {

View File

@ -43,7 +43,7 @@ import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
/** /**
* Commands for moving the player around. * Commands for moving the player around.
*/ */
@Command(aliases = {}, desc = "Commands for moving the player around: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Getting_around)") @Command(aliases = {}, desc = "Commands for moving the player around: [More Info](https://goo.gl/uQTUiT)")
public class NavigationCommands { public class NavigationCommands {
@SuppressWarnings("unused") @SuppressWarnings("unused")

View File

@ -58,7 +58,7 @@ import java.util.Set;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
@Command(aliases = {"patterns"}, @Command(aliases = {"patterns"},
desc = "Help for the various patterns. [More Info](https://github.com/boy0001/FastAsyncWorldedit/wiki/WorldEdit-and-FAWE-patterns)" desc = "Help for the various patterns. [More Info](https://git.io/vSPmA)"
) )
public class PatternCommands extends MethodCommands { public class PatternCommands extends MethodCommands {
public PatternCommands(WorldEdit worldEdit) { public PatternCommands(WorldEdit worldEdit) {

View File

@ -53,7 +53,6 @@ import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.NoiseFilter2D; import com.sk89q.worldedit.function.mask.NoiseFilter2D;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.LayerVisitor; import com.sk89q.worldedit.function.visitor.LayerVisitor;
import com.sk89q.worldedit.internal.annotation.Direction; import com.sk89q.worldedit.internal.annotation.Direction;
@ -330,11 +329,7 @@ public class RegionCommands extends MethodCommands {
public void set(FawePlayer player, LocalSession session, EditSession editSession, @Selection Region selection, Pattern to, CommandContext context) throws WorldEditException { public void set(FawePlayer player, LocalSession session, EditSession editSession, @Selection Region selection, Pattern to, CommandContext context) throws WorldEditException {
player.checkConfirmation(getArguments(context)); player.checkConfirmation(getArguments(context));
int affected; int affected;
if (to instanceof BlockPattern) { affected = editSession.setBlocks(selection, to);
affected = editSession.setBlocks(selection, ((BlockPattern) to).getBlock());
} else {
affected = editSession.setBlocks(selection, to);
}
if (affected != 0) { if (affected != 0) {
BBC.OPERATION.send(player, affected); BBC.OPERATION.send(player, affected);
if (!player.hasPermission("fawe.tips")) if (!player.hasPermission("fawe.tips"))

View File

@ -37,7 +37,7 @@ import static com.sk89q.minecraft.util.commands.Logging.LogMode.ALL;
/** /**
* Commands related to scripting. * Commands related to scripting.
*/ */
@Command(aliases = {}, desc = "Run craftscripts: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Scripting)") @Command(aliases = {}, desc = "Run craftscripts: [More Info](https://goo.gl/dHDxLG)")
public class ScriptingCommands { public class ScriptingCommands {
private final WorldEdit worldEdit; private final WorldEdit worldEdit;

View File

@ -32,7 +32,7 @@ import com.sk89q.worldedit.command.tool.RecursivePickaxe;
import com.sk89q.worldedit.command.tool.SinglePickaxe; import com.sk89q.worldedit.command.tool.SinglePickaxe;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
@Command(aliases = {"superpickaxe", "pickaxe", "sp"}, desc = "Super-pickaxe commands: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Super_pickaxe)") @Command(aliases = {"superpickaxe", "pickaxe", "sp"}, desc = "Super-pickaxe commands: [More Info](https://goo.gl/aBtGHo)")
public class SuperPickaxeCommands { public class SuperPickaxeCommands {
private final WorldEdit we; private final WorldEdit we;

View File

@ -44,7 +44,7 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.util.command.parametric.Optional;
@Command(aliases = {"brush", "br", "/b", "tool"}, desc = "Bind functions to held items: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Tools)") @Command(aliases = {"brush", "br", "/b", "tool"}, desc = "Bind functions to held items: [More Info](https://goo.gl/xPnPxj)")
public class ToolCommands { public class ToolCommands {
private final WorldEdit we; private final WorldEdit we;

View File

@ -22,7 +22,7 @@ import com.sk89q.worldedit.util.command.parametric.Optional;
import java.util.Set; import java.util.Set;
@Command(aliases = {"transforms"}, @Command(aliases = {"transforms"},
desc = "Help for the various transforms. [More Info](https://github.com/boy0001/FastAsyncWorldedit/wiki/Transforms)" desc = "Help for the various transforms. [More Info](https://git.io/v9KHO)"
) )
public class TransformCommands extends MethodCommands { public class TransformCommands extends MethodCommands {
public TransformCommands(WorldEdit worldEdit) { public TransformCommands(WorldEdit worldEdit) {

View File

@ -51,7 +51,6 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.EntityVisitor; import com.sk89q.worldedit.function.visitor.EntityVisitor;
import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.Expression;
@ -116,8 +115,8 @@ public class UtilityCommands extends MethodCommands {
worldEdit.checkMaxRadius(radius); worldEdit.checkMaxRadius(radius);
Vector pos = session.getPlacementPosition(player); Vector pos = session.getPlacementPosition(player);
int affected = 0; int affected = 0;
if (pattern instanceof BlockPattern) { if (pattern instanceof BaseBlock) {
affected = editSession.fillXZ(pos, ((BlockPattern) pattern).getBlock(), radius, (int) depth, false); affected = editSession.fillXZ(pos, ((BaseBlock) pattern), radius, (int) depth, false);
} else { } else {
affected = editSession.fillXZ(pos, pattern, radius, (int) depth, false); affected = editSession.fillXZ(pos, pattern, radius, (int) depth, false);
} }
@ -137,8 +136,8 @@ public class UtilityCommands extends MethodCommands {
worldEdit.checkMaxRadius(radius); worldEdit.checkMaxRadius(radius);
Vector pos = session.getPlacementPosition(player); Vector pos = session.getPlacementPosition(player);
int affected = 0; int affected = 0;
if (pattern instanceof BlockPattern) { if (pattern instanceof BaseBlock) {
affected = editSession.fillXZ(pos, ((BlockPattern) pattern).getBlock(), radius, (int) depth, true); affected = editSession.fillXZ(pos, ((BaseBlock) pattern), radius, (int) depth, true);
} else { } else {
affected = editSession.fillXZ(pos, pattern, radius, (int) depth, true); affected = editSession.fillXZ(pos, pattern, radius, (int) depth, true);
} }

View File

@ -45,7 +45,6 @@ import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.block.BlockReplace; import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.RegionVisitor; import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
@ -106,8 +105,8 @@ public class SelectionCommand extends SimpleCommand<Operation> {
Field field = replace.getClass().getDeclaredField("pattern"); Field field = replace.getClass().getDeclaredField("pattern");
field.setAccessible(true); field.setAccessible(true);
Pattern pattern = (Pattern) field.get(replace); Pattern pattern = (Pattern) field.get(replace);
if (pattern instanceof BlockPattern) { if (pattern instanceof BaseBlock) {
BaseBlock block = ((BlockPattern) pattern).getBlock(); BaseBlock block = ((BaseBlock) pattern);
final FaweQueue queue = editSession.getQueue(); final FaweQueue queue = editSession.getQueue();
final int minY = cuboid.getMinimumY(); final int minY = cuboid.getMinimumY();
final int maxY = cuboid.getMaximumY(); final int maxY = cuboid.getMaximumY();

View File

@ -13,7 +13,6 @@ import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.function.block.BlockReplace; import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.visitor.RecursiveVisitor; import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
@ -53,7 +52,7 @@ public class RecursivePickaxe implements BlockTool {
editSession.getSurvivalExtent().setToolUse(config.superPickaxeManyDrop); editSession.getSurvivalExtent().setToolUse(config.superPickaxeManyDrop);
final int radius = (int) range; final int radius = (int) range;
final BlockReplace replace = new BlockReplace(editSession, new BlockPattern(editSession.nullBlock)); final BlockReplace replace = new BlockReplace(editSession, (editSession.nullBlock));
editSession.setMask((Mask) null); editSession.setMask((Mask) null);
RecursiveVisitor visitor = new RecursiveVisitor(new IdMask(editSession), replace, radius, editSession); RecursiveVisitor visitor = new RecursiveVisitor(new IdMask(editSession), replace, radius, editSession);
visitor.visit(pos); visitor.visit(pos);

View File

@ -238,13 +238,10 @@ public final class CommandManager {
.registerMethods(new BrushOptionsCommands(worldEdit)) .registerMethods(new BrushOptionsCommands(worldEdit))
.registerMethods(new ToolCommands(worldEdit)) .registerMethods(new ToolCommands(worldEdit))
.registerMethods(new UtilityCommands(worldEdit)) .registerMethods(new UtilityCommands(worldEdit))
.group("worldedit", "we", "fawe") .registerSubMethods(new WorldEditCommands(worldEdit))
.describeAs("FAWE commands") .registerSubMethods(new SchematicCommands(worldEdit))
.registerMethods(new WorldEditCommands(worldEdit)).parent().group("schematic", "schem", "/schematic", "/schem") .registerSubMethods(new SnapshotCommands(worldEdit))
.describeAs("Schematic commands for saving/loading areas") .groupAndDescribe(BrushCommands.class)
.registerMethods(new SchematicCommands(worldEdit)).parent().group("snapshot", "snap")
.describeAs("Schematic commands for saving/loading areas")
.registerMethods(new SnapshotCommands(worldEdit)).parent().group("brush", "br", "/b", "tool").describeAs("Bind brushes and tools to items")
.registerMethods(new ToolCommands(worldEdit)) .registerMethods(new ToolCommands(worldEdit))
.registerMethods(new BrushOptionsCommands(worldEdit)) .registerMethods(new BrushOptionsCommands(worldEdit))
.registerMethods(new BrushCommands(worldEdit), new BrushProcessor(worldEdit)) .registerMethods(new BrushCommands(worldEdit), new BrushProcessor(worldEdit))
@ -254,7 +251,8 @@ public final class CommandManager {
.register(adapt(new ShapedBrushCommand(new ApplyCommand(), "worldedit.brush.apply")), "apply") .register(adapt(new ShapedBrushCommand(new ApplyCommand(), "worldedit.brush.apply")), "apply")
.register(adapt(new ShapedBrushCommand(new PaintCommand(new TreeGeneratorParser("treeType")), "worldedit.brush.forest")), "forest") .register(adapt(new ShapedBrushCommand(new PaintCommand(new TreeGeneratorParser("treeType")), "worldedit.brush.forest")), "forest")
.register(adapt(new ShapedBrushCommand(ProvidedValue.create(new Deform("y-=1", Mode.RAW_COORD), "Raise one block"), "worldedit.brush.raise")), "raise") .register(adapt(new ShapedBrushCommand(ProvidedValue.create(new Deform("y-=1", Mode.RAW_COORD), "Raise one block"), "worldedit.brush.raise")), "raise")
.register(adapt(new ShapedBrushCommand(ProvidedValue.create(new Deform("y+=1", Mode.RAW_COORD), "Lower one block"), "worldedit.brush.lower")), "lower").parent() .register(adapt(new ShapedBrushCommand(ProvidedValue.create(new Deform("y+=1", Mode.RAW_COORD), "Lower one block"), "worldedit.brush.lower")), "lower")
.parent()
.group("superpickaxe", "pickaxe", "sp").describeAs("Super-pickaxe commands") .group("superpickaxe", "pickaxe", "sp").describeAs("Super-pickaxe commands")
.registerMethods(new SuperPickaxeCommands(worldEdit)) .registerMethods(new SuperPickaxeCommands(worldEdit))
.parent().graph().getDispatcher(); .parent().graph().getDispatcher();
@ -374,7 +372,7 @@ public final class CommandManager {
final Actor finalActor = actor; final Actor finalActor = actor;
locals.put("arguments", args); locals.put("arguments", args);
final long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
try { try {
// This is a bit of a hack, since the call method can only throw CommandExceptions // This is a bit of a hack, since the call method can only throw CommandExceptions
// everything needs to be wrapped at least once. Which means to handle all WorldEdit // everything needs to be wrapped at least once. Which means to handle all WorldEdit

View File

@ -17,7 +17,6 @@ import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
@ -176,17 +175,17 @@ public interface Extent extends InputExtent, OutputExtent {
} }
default public void addOres(Region region, Mask mask) throws WorldEditException { default public void addOres(Region region, Mask mask) throws WorldEditException {
addOre(region, mask, new BlockPattern(BlockID.DIRT), 33, 10, 100, 0, 255); addOre(region, mask, FaweCache.getBlock(BlockID.DIRT, 0), 33, 10, 100, 0, 255);
addOre(region, mask, new BlockPattern(BlockID.GRAVEL), 33, 8, 100, 0, 255); addOre(region, mask, FaweCache.getBlock(BlockID.GRAVEL, 0), 33, 8, 100, 0, 255);
addOre(region, mask, new BlockPattern(BlockID.STONE, 1), 33, 10, 100, 0, 79); addOre(region, mask, FaweCache.getBlock(BlockID.STONE, 1), 33, 10, 100, 0, 79);
addOre(region, mask, new BlockPattern(BlockID.STONE, 3), 33, 10, 100, 0, 79); addOre(region, mask, FaweCache.getBlock(BlockID.STONE, 3), 33, 10, 100, 0, 79);
addOre(region, mask, new BlockPattern(BlockID.STONE, 5), 33, 10, 100, 0, 79); addOre(region, mask, FaweCache.getBlock(BlockID.STONE, 5), 33, 10, 100, 0, 79);
addOre(region, mask, new BlockPattern(BlockID.COAL_ORE), 17, 20, 100, 0, 127); addOre(region, mask, FaweCache.getBlock(BlockID.COAL_ORE, 0), 17, 20, 100, 0, 127);
addOre(region, mask, new BlockPattern(BlockID.IRON_ORE), 9, 20, 100, 0, 63); addOre(region, mask, FaweCache.getBlock(BlockID.IRON_ORE, 0), 9, 20, 100, 0, 63);
addOre(region, mask, new BlockPattern(BlockID.GOLD_ORE), 9, 2, 100, 0, 31); addOre(region, mask, FaweCache.getBlock(BlockID.GOLD_ORE, 0), 9, 2, 100, 0, 31);
addOre(region, mask, new BlockPattern(BlockID.REDSTONE_ORE), 8, 8, 100, 0, 15); addOre(region, mask, FaweCache.getBlock(BlockID.REDSTONE_ORE, 0), 8, 8, 100, 0, 15);
addOre(region, mask, new BlockPattern(BlockID.DIAMOND_ORE), 8, 1, 100, 0, 15); addOre(region, mask, FaweCache.getBlock(BlockID.DIAMOND_ORE, 0), 8, 1, 100, 0, 15);
addOre(region, mask, new BlockPattern(BlockID.LAPIS_LAZULI_ORE), 7, 1, 100, 0, 15); addOre(region, mask, FaweCache.getBlock(BlockID.LAPIS_LAZULI_ORE, 0), 7, 1, 100, 0, 15);
addOre(region, mask, new BlockPattern(BlockID.EMERALD_ORE), 5, 1, 100, 4, 31); addOre(region, mask, FaweCache.getBlock(BlockID.EMERALD_ORE, 0), 5, 1, 100, 4, 31);
} }
} }

View File

@ -7,6 +7,10 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
/**
* @deprecated Just use BaseBlock directly
*/
@Deprecated
public class BlockPattern implements Pattern { public class BlockPattern implements Pattern {
private BaseBlock block; private BaseBlock block;

View File

@ -19,11 +19,14 @@
package com.sk89q.worldedit.util.command.fluent; package com.sk89q.worldedit.util.command.fluent;
import com.boydti.fawe.config.Commands;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.worldedit.util.command.CallableProcessor; import com.sk89q.worldedit.util.command.CallableProcessor;
import com.sk89q.worldedit.util.command.CommandCallable; import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.util.command.SimpleDispatcher; import com.sk89q.worldedit.util.command.SimpleDispatcher;
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder; import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
import javax.annotation.Nullable;
/** /**
* A collection of commands. * A collection of commands.
@ -93,7 +96,7 @@ public class DispatcherNode {
* @return this object * @return this object
* @see ParametricBuilder#registerMethodsAsCommands(com.sk89q.worldedit.util.command.Dispatcher, Object) * @see ParametricBuilder#registerMethodsAsCommands(com.sk89q.worldedit.util.command.Dispatcher, Object)
*/ */
public DispatcherNode registerMethods(Object object, CallableProcessor processor) { public DispatcherNode registerMethods(Object object, @Nullable CallableProcessor processor) {
ParametricBuilder builder = graph.getBuilder(); ParametricBuilder builder = graph.getBuilder();
if (builder == null) { if (builder == null) {
throw new RuntimeException("No ParametricBuilder set"); throw new RuntimeException("No ParametricBuilder set");
@ -102,6 +105,43 @@ public class DispatcherNode {
return this; return this;
} }
/**
* Build and register sub commands with this dispatcher using the
* {@link ParametricBuilder} assigned on the objects registered command aliases {@link com.sk89q.minecraft.util.commands.Command}.
*
* @param object the object provided to the {@link ParametricBuilder}
* @return this object
*/
public DispatcherNode registerSubMethods(Object object) {
return registerSubMethods(object, null);
}
/**
* Build and register sub commands with this dispatcher using the
* {@link ParametricBuilder} assigned on the objects registered command aliases {@link com.sk89q.minecraft.util.commands.Command}.
*
* @param object the object provided to the {@link ParametricBuilder}
* @param processor the command processor
* @return this object
*/
public DispatcherNode registerSubMethods(Object object, @Nullable CallableProcessor processor) {
Class<? extends Object> clazz = object.getClass();
return groupAndDescribe(clazz).registerMethods(object, processor).parent();
}
public DispatcherNode groupAndDescribe(Class clazz) {
Command cmd = (Command) clazz.getAnnotation(Command.class);
if (cmd == null) {
throw new RuntimeException("This class does not have any command annotations");
}
cmd = Commands.translate(clazz, cmd);
DispatcherNode res = group(cmd.aliases());
if (cmd.desc() != null && !cmd.desc().isEmpty()) {
res = res.describeAs(cmd.desc());
}
return res;
}
/** /**
* Create a new command that will contain sub-commands. * Create a new command that will contain sub-commands.
* <p> * <p>
@ -114,7 +154,8 @@ public class DispatcherNode {
public DispatcherNode group(String... alias) { public DispatcherNode group(String... alias) {
SimpleDispatcher command = new SimpleDispatcher(); SimpleDispatcher command = new SimpleDispatcher();
getDispatcher().registerCommand(command, alias); getDispatcher().registerCommand(command, alias);
return new DispatcherNode(graph, this, command); DispatcherNode res = new DispatcherNode(graph, this, command);
return res;
} }
/** /**