Zstd/disk clipboard/version/various

Better compression with Zstd
Fix disk clipboard + minor optimizations
Fix version output
Some various incomplete stuff
This commit is contained in:
Jesse Boyd 2016-12-12 17:41:32 +11:00
parent 78640aef1c
commit f0a36ba1fa
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
25 changed files with 3423 additions and 110 deletions

View File

@ -36,6 +36,7 @@ apply plugin: 'com.github.johnrengelman.shadow'
// We only want the shadow jar produced // We only want the shadow jar produced
shadowJar { shadowJar {
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency(':core')) include(dependency(':core'))
} }
archiveName = "${parent.name}-${project.name}-${parent.version}.jar" archiveName = "${parent.name}-${project.name}-${parent.version}.jar"

View File

@ -6,6 +6,7 @@ dependencies {
compile 'com.sk89q:worldguard:6.0.0-SNAPSHOT' compile 'com.sk89q:worldguard:6.0.0-SNAPSHOT'
compile 'com.plotsquared:PlotSquared:3.4.1-SNAPSHOT' compile 'com.plotsquared:PlotSquared:3.4.1-SNAPSHOT'
compile 'org.primesoft:BlocksHub:2.0' compile 'org.primesoft:BlocksHub:2.0'
compile 'com.github.luben:zstd-jni:1.1.1'
compile(group: 'com.sk89q.worldedit', name: 'worldedit-core', version:'6.1.3-SNAPSHOT') { compile(group: 'com.sk89q.worldedit', name: 'worldedit-core', version:'6.1.3-SNAPSHOT') {
exclude(module: 'bukkit-classloader-check') exclude(module: 'bukkit-classloader-check')
} }

View File

@ -104,7 +104,6 @@ import javax.management.InstanceAlreadyExistsException;
import javax.management.Notification; import javax.management.Notification;
import javax.management.NotificationEmitter; import javax.management.NotificationEmitter;
import javax.management.NotificationListener; import javax.management.NotificationListener;
import net.jpountz.util.Native;
/**[ WorldEdit action] /**[ WorldEdit action]
* | * |
@ -465,7 +464,8 @@ public class Fawe {
debug("======================================="); debug("=======================================");
} }
try { try {
Native.load(); com.github.luben.zstd.util.Native.load();
net.jpountz.util.Native.load();
try { try {
String arch = System.getenv("PROCESSOR_ARCHITECTURE"); String arch = System.getenv("PROCESSOR_ARCHITECTURE");
String wow64Arch = System.getenv("PROCESSOR_ARCHITEW6432"); String wow64Arch = System.getenv("PROCESSOR_ARCHITEW6432");

View File

@ -0,0 +1,61 @@
package com.boydti.fawe.command;
import com.boydti.fawe.util.StringMan;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.internal.registry.InputParser;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public abstract class FaweParser<T> extends InputParser<T> {
protected FaweParser(WorldEdit worldEdit) {
super(worldEdit);
}
public List<String> split(String input, char delim) {
List<String> result = new ArrayList<String>();
int start = 0;
boolean inQuotes = false;
for (int current = 0; current < input.length(); current++) {
if (input.charAt(current) == '\"') inQuotes = !inQuotes; // toggle state
boolean atLastChar = (current == input.length() - 1);
if(atLastChar) result.add(input.substring(start));
else if (input.charAt(current) == delim && !inQuotes) {
String toAdd = input.substring(start, current);
if (toAdd.startsWith("\"")) {
toAdd = toAdd.substring(1, toAdd.length() - 1);
}
result.add(toAdd);
start = current + 1;
}
}
return result;
}
public T catchSuggestion(String currentInput, String nextInput, ParserContext context) throws InputParseException {
try {
return parseFromInput(nextInput, context);
} catch (SuggestInputParseException e) {
e.prepend(currentInput.substring(0, currentInput.length() - nextInput.length()));
throw e;
}
}
public List<String> suggestRemaining(String input, String... expected) throws InputParseException {
List<String> remainder = split(input, ':');
int len = remainder.size();
if (len != expected.length - 1) {
if (len <= expected.length - 1 && len != 0) {
if (remainder.get(len - 1).endsWith(":")) {
throw new SuggestInputParseException(null, StringMan.join(expected, ":"));
}
throw new SuggestInputParseException(null, expected[0] + ":" + input + ":" + StringMan.join(Arrays.copyOfRange(expected, len + 1, 3), ":"));
} else {
throw new SuggestInputParseException(null, StringMan.join(expected, ":"));
}
}
return remainder;
}
}

View File

@ -9,7 +9,9 @@ import com.boydti.fawe.util.HastebinUtility;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.time.LocalDate;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Map; import java.util.Map;
public class Reload extends FaweCommand { public class Reload extends FaweCommand {
@ -31,13 +33,14 @@ public class Reload extends FaweCommand {
MainUtil.sendMessage(player, "No version information available."); MainUtil.sendMessage(player, "No version information available.");
return false; return false;
} }
MainUtil.sendMessage(player, "Version Date: " + new Date(100 + version.year, version.month, version.day).toLocaleString()); Date date = new GregorianCalendar(2000 + version.year - 1, version.month - 1, version.day).getTime();
MainUtil.sendMessage(player, "Version Date: " + date.toLocaleString());
MainUtil.sendMessage(player, "Version Commit: " + Integer.toHexString(version.hash)); MainUtil.sendMessage(player, "Version Commit: " + Integer.toHexString(version.hash));
MainUtil.sendMessage(player, "Version Build: #" + version.build); MainUtil.sendMessage(player, "Version Build: #" + version.build);
return true; return true;
} }
case "threads": { case "threads": {
Map<Thread, StackTraceElement[]> stacks = Fawe.get().getMainThread().getAllStackTraces(); Map<Thread, StackTraceElement[]> stacks = Thread.getAllStackTraces();
for (Map.Entry<Thread, StackTraceElement[]> entry : stacks.entrySet()) { for (Map.Entry<Thread, StackTraceElement[]> entry : stacks.entrySet()) {
Thread thread = entry.getKey(); Thread thread = entry.getKey();
Fawe.debug("--------------------------------------------------------------------------------------------"); Fawe.debug("--------------------------------------------------------------------------------------------");

View File

@ -52,7 +52,6 @@ public class CPUOptimizedChangeSet extends FaweChangeSet {
} }
@Override @Override
public void add(int x, int y, int z, int combinedFrom, int combinedTo) { public void add(int x, int y, int z, int combinedFrom, int combinedTo) {
throw new UnsupportedOperationException("Invalid mode"); throw new UnsupportedOperationException("Invalid mode");
} }
@ -89,9 +88,9 @@ public class CPUOptimizedChangeSet extends FaweChangeSet {
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
if (changes.size() == 0) { if (changes.isEmpty()) {
flush(); flush();
return changes.size() == 0; return changes.isEmpty();
} else { } else {
return false; return false;
} }

View File

@ -257,7 +257,7 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
public abstract NBTInputStream getTileCreateIS() throws IOException; public abstract NBTInputStream getTileCreateIS() throws IOException;
public abstract NBTInputStream getTileRemoveIS() throws IOException; public abstract NBTInputStream getTileRemoveIS() throws IOException;
public int blockSize; private int blockSize;
public int entityCreateSize; public int entityCreateSize;
public int entityRemoveSize; public int entityRemoveSize;
public int tileCreateSize; public int tileCreateSize;

View File

@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache; import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.jnbt.NBTStreamer; import com.boydti.fawe.jnbt.NBTStreamer;
import com.boydti.fawe.jnbt.SchematicStreamer;
import com.boydti.fawe.object.IntegerTrio; import com.boydti.fawe.object.IntegerTrio;
import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.io.BufferedRandomAccessFile; import com.boydti.fawe.object.io.BufferedRandomAccessFile;
@ -11,6 +12,7 @@ import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.ReflectionUtils; 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.IntTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.BlockVector; import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
@ -21,8 +23,10 @@ import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import java.io.BufferedInputStream;
import java.io.Closeable; import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -30,6 +34,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.zip.GZIPInputStream;
/** /**
* A clipboard with disk backed storage. (lower memory + loads on crash) * A clipboard with disk backed storage. (lower memory + loads on crash)
@ -55,7 +60,6 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
private final byte[] buffer; private final byte[] buffer;
private final BufferedRandomAccessFile raf; private final BufferedRandomAccessFile raf;
private long lastAccessed;
private int last; private int last;
public DiskOptimizedClipboard(int width, int height, int length, UUID uuid) { public DiskOptimizedClipboard(int width, int height, int length, UUID uuid) {
@ -68,7 +72,6 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
entities = new HashSet<>(); entities = new HashSet<>();
this.buffer = new byte[2]; this.buffer = new byte[2];
this.file = file; this.file = file;
this.lastAccessed = System.currentTimeMillis();
this.raf = new BufferedRandomAccessFile(file, "rw", 16); this.raf = new BufferedRandomAccessFile(file, "rw", 16);
raf.setLength(file.length()); raf.setLength(file.length());
long size = (raf.length() - HEADER_SIZE) >> 1; long size = (raf.length() - HEADER_SIZE) >> 1;
@ -117,7 +120,6 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
entities = new HashSet<>(); entities = new HashSet<>();
this.file = file; this.file = file;
this.buffer = new byte[2]; this.buffer = new byte[2];
this.lastAccessed = System.currentTimeMillis();
this.width = width; this.width = width;
this.height = height; this.height = height;
this.length = length; this.length = length;
@ -132,6 +134,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
} }
this.raf = new BufferedRandomAccessFile(file, "rw", 16); this.raf = new BufferedRandomAccessFile(file, "rw", 16);
long volume = width * height * length * 2l + HEADER_SIZE; long volume = width * height * length * 2l + HEADER_SIZE;
raf.setLength(0);
raf.setLength(volume); raf.setLength(volume);
// write length etc // write length etc
raf.seek(2); raf.seek(2);
@ -325,7 +328,6 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
int i = getIndex(x, y, z); int i = getIndex(x, y, z);
if (i != last + 1) { if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1)); raf.seek((HEADER_SIZE) + (i << 1));
lastAccessed = System.currentTimeMillis();
} }
last = i; last = i;
int combinedId = raf.readChar(); int combinedId = raf.readChar();
@ -360,15 +362,15 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
int i = x + ((ylast == y) ? ylasti : (ylasti = ((ylast = y)) * area)) + ((zlast == z) ? zlasti : (zlasti = (zlast = z) * width)); int i = x + ((ylast == y) ? ylasti : (ylasti = ((ylast = y)) * area)) + ((zlast == z) ? zlasti : (zlasti = (zlast = z) * width));
if (i != last + 1) { if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1)); raf.seek((HEADER_SIZE) + (i << 1));
lastAccessed = System.currentTimeMillis();
} }
last = i; last = i;
final int id = block.getId(); final int id = block.getId();
final int data = block.getData(); final int data = block.getData();
int combined = (id << 4) + data; int combined = (id << 4) + data;
raf.writeChar(combined); raf.writeChar(combined);
if (FaweCache.hasNBT(id)) { CompoundTag tile = block.getNbtData();
setTile(x, y, z, block.getNbtData()); if (tile != null) {
setTile(x, y, z, tile);
} }
return true; return true;
} catch (Exception e) { } catch (Exception e) {
@ -382,15 +384,14 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
try { try {
if (i != last + 1) { if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1)); raf.seek((HEADER_SIZE) + (i << 1));
lastAccessed = System.currentTimeMillis();
} }
last = i; last = i;
// 00000000 00000000 // 00000000 00000000
// [ id ]data // [ id ]data
int id1 = raf.readCurrent(); int id1 = raf.readCurrent();
raf.write(id >> 4); raf.writeUnsafe(id >> 4);
int id2 = raf.readCurrent(); int id2 = raf.readCurrent();
raf.write(((id & 0xFF) << 4) + (id2 & 0xFF)); raf.writeUnsafe(((id & 0xFF) << 4) + (id2 & 0xFF));
} catch (Exception e) { } catch (Exception e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
@ -400,7 +401,6 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
try { try {
if (i != last + 1) { if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1)); raf.seek((HEADER_SIZE) + (i << 1));
lastAccessed = System.currentTimeMillis();
} }
last = i; last = i;
raf.writeChar(combined); raf.writeChar(combined);
@ -414,31 +414,43 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
try { try {
if (i != last + 1) { if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1)); raf.seek((HEADER_SIZE) + (i << 1));
lastAccessed = System.currentTimeMillis();
} }
last = i; last = i;
// 00000000 00000000 // 00000000 00000000
// [ id ]data // [ id ]data
raf.write((raf.readCurrent() & 0xFF) + (add >> 4)); int id = (raf.readCurrent() & 0xFF);
raf.writeUnsafe(id + (add >> 4));
raf.read1(); raf.read1();
} catch (Exception e) { } catch (Exception e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
} }
public static void main(String[] args) throws IOException{
long start = System.currentTimeMillis();
File file = new File("C:/Users/Jesse/Desktop/OTHER/mc/plugins/WorldEdit/schematics/50mil.schematic");
BufferedInputStream in = new BufferedInputStream(new GZIPInputStream(new BufferedInputStream(new FileInputStream(file))));
NBTInputStream nbtin = new NBTInputStream(in);
Settings.CLIPBOARD.USE_DISK = true;
SchematicStreamer streamer = new SchematicStreamer(nbtin, UUID.randomUUID());
streamer.getClipboard();
System.out.println(System.currentTimeMillis() - start);
}
@Override @Override
public void setData(int i, int data) { public void setData(int i, int data) {
try { try {
if (i != last + 1) { if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1)); raf.seek((HEADER_SIZE) + (i << 1) + 1);
lastAccessed = System.currentTimeMillis(); } else {
raf.seek(raf.getFilePointer() + 1);
} }
last = i; last = i;
// 00000000 00000000 // 00000000 00000000
// [ id ]data // [ id ]data
int id1 = raf.read1(); // int skip = raf.read1();
int id2 = raf.readCurrent(); int id2 = raf.readCurrent();
raf.write((id2 & 0xF0) + data); raf.writeUnsafe((id2 & 0xF0) + data);
} catch (Exception e) { } catch (Exception e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }

File diff suppressed because it is too large Load Diff

View File

@ -100,10 +100,10 @@ public class DefaultTransformParser extends InputParser<ResettableExtent> {
if (!rest.isEmpty()) { if (!rest.isEmpty()) {
parent = parseFromInput(rest, context); parent = parseFromInput(rest, context);
} }
ExtentTraverser traverser = new ExtentTraverser(parent).find(BlockTransformExtent.class); ExtentTraverser traverser = new ExtentTraverser(parent).find(TransformExtent.class);
BlockTransformExtent affine = (BlockTransformExtent) (traverser != null ? traverser.get() : null); BlockTransformExtent affine = (TransformExtent) (traverser != null ? traverser.get() : null);
if (affine == null) { if (affine == null) {
parent = affine = new BlockTransformExtent(parent, context.requireWorld().getWorldData().getBlockRegistry()); parent = affine = new TransformExtent(parent, context.requireWorld().getWorldData().getBlockRegistry());
} }
AffineTransform transform = (AffineTransform) affine.getTransform(); AffineTransform transform = (AffineTransform) affine.getTransform();
transform = transform.rotateX(x); transform = transform.rotateX(x);

View File

@ -316,7 +316,8 @@ public class BufferedRandomAccessFile extends RandomAccessFile
if (this.curr_ == this.hi_) if (this.curr_ == this.hi_)
return -1; return -1;
} }
byte res = this.buff_[(int) (this.curr_++ - this.lo_)]; byte res = this.buff_[(int) (this.curr_ - this.lo_)];
this.curr_++;
return res; return res;
} }
@ -388,6 +389,13 @@ public class BufferedRandomAccessFile extends RandomAccessFile
this.dirty_ = true; this.dirty_ = true;
} }
public void writeUnsafe(int b) throws IOException
{
this.buff_[(int) (this.curr_ - this.lo_)] = (byte) b;
this.curr_++;
this.dirty_ = true;
}
@Override @Override
public void write(int b) throws IOException public void write(int b) throws IOException
{ {

View File

@ -0,0 +1,157 @@
package com.boydti.fawe.object.regions;
import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.regions.AbstractRegion;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.world.World;
import java.util.BitSet;
import java.util.Iterator;
public class MagicRegion extends AbstractRegion {
private BitSet set = new BitSet();
private int minX, minY, minZ, maxX, maxY, maxZ;
private int offsetX, offsetY, offsetZ;
{
minX = minY = minZ = Integer.MAX_VALUE;
maxX = maxY = maxZ = Integer.MIN_VALUE;
}
public MagicRegion(World world) {
super(world);
}
private static int pair(int x, int y, int z) {
byte b1 = (byte) y;
byte b2 = (byte) (x);
byte b3 = (byte) (z);
int x16 = (x >> 8) & 0xF;
int z16 = (z >> 8) & 0xF;
byte b4 = MathMan.pair16(x16, z16);
return (b1 & 0xFF)
+ ((b2 & 0xFF) << 8)
+ ((b3 & 0xFF) << 16)
+ ((b4 & 0xFF) << 24)
;
}
public void select(int x, int y, int z) {
EditSession editSession = new EditSessionBuilder(getWorld())
.limitUnlimited()
.changeSetNull()
.fastmode(true)
.allowedRegionsEverywhere()
.checkMemory(false)
.autoQueue(false)
.build();
}
@Override
public Iterator<BlockVector> iterator() {
return new Iterator<BlockVector>() {
private int index = -1;
private BlockVector pos = new BlockVector(0, 0, 0);
@Override
public boolean hasNext() {
index = set.nextSetBit(index + 1);
return index != -1;
}
@Override
public BlockVector next() {
int b1 = index & 0xFF;
int b2 = (index >> 8) & 0xFF;
int b3 = (index >> 16) & 0xFF;
byte b4 = (byte) ((index >> 24) & 0xFF);
pos.x = offsetX + (((b2 & 0xFF) + ((MathMan.unpair16x(b4)) << 8)) << 20) >> 20;
pos.y = offsetY + b1;
pos.z = offsetZ + (((b3) + ((MathMan.unpair16y(b4)) << 8)) << 20) >> 20;
return pos;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
public void set(int x, int y, int z) throws RegionOperationException{
x -= offsetX;
y -= offsetY;
z -= offsetZ;
set.set(pair(x, y, z), true);
if (x >= 2048 || x <= -2048 || z >= 2048 || z <= -2048) {
throw new RegionOperationException("Selection is too large!");
}
if (x > maxX) {
maxX = x;
}
if (x < minX) {
minX = x;
}
if (z > maxZ) {
maxZ = z;
}
if (z < minZ) {
minZ = z;
}
if (y > maxY) {
maxY = y;
}
if (y < minY) {
minY = y;
}
}
public boolean contains(int x, int y, int z) {
return set.get(pair(x - offsetX, y - offsetY, z - offsetZ));
}
@Override
public Vector getMinimumPoint() {
return new Vector(minX, minY, minZ);
}
@Override
public Vector getMaximumPoint() {
return new Vector(maxX, maxY, maxZ);
}
@Override
public void expand(Vector... changes) throws RegionOperationException {
throw new RegionOperationException("Selection is too large!");
}
@Override
public void contract(Vector... changes) throws RegionOperationException {
throw new RegionOperationException("Selection is too large!");
}
@Override
public boolean contains(Vector position) {
return contains((int) position.x, (int) position.y, (int) position.z);
}
@Override
public void shift(Vector change) throws RegionOperationException {
offsetX += change.getBlockX();
offsetY += change.getBlockY();
offsetZ += change.getBlockZ();
minX += change.getBlockX();
minY += change.getBlockY();
minZ += change.getBlockZ();
maxX += change.getBlockX();
maxY += change.getBlockY();
maxZ += change.getBlockZ();
}
}

View File

@ -0,0 +1,104 @@
package com.boydti.fawe.object.regions.selector;
import com.boydti.fawe.object.regions.MagicRegion;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.limit.SelectorLimits;
import com.sk89q.worldedit.world.World;
import java.util.List;
import javax.annotation.Nullable;
public class MagicRegionSelector implements RegionSelector {
private MagicRegion region;
public MagicRegionSelector(@Nullable World world, Vector pos) {
this.region = new MagicRegion(world);
}
@Nullable
@Override
public World getWorld() {
return this.region.getWorld();
}
@Override
public void setWorld(@Nullable World world) {
this.region.setWorld(world);
}
@Override
public boolean selectPrimary(Vector position, SelectorLimits limits) {
}
@Override
public boolean selectSecondary(Vector position, SelectorLimits limits) {
}
@Override
public void explainPrimarySelection(Actor actor, LocalSession session, Vector position) {
}
@Override
public void explainSecondarySelection(Actor actor, LocalSession session, Vector position) {
}
@Override
public void explainRegionAdjust(Actor actor, LocalSession session) {
}
@Override
public BlockVector getPrimaryPosition() throws IncompleteRegionException {
return null;
}
@Override
public Region getRegion() throws IncompleteRegionException {
return null;
}
@Override
public Region getIncompleteRegion() {
return null;
}
@Override
public boolean isDefined() {
return false;
}
@Override
public int getArea() {
return 0;
}
@Override
public void learnChanges() {
}
@Override
public void clear() {
}
@Override
public String getTypeName() {
return null;
}
@Override
public List<String> getInformationLines() {
return null;
}
}

View File

@ -3,22 +3,51 @@ package com.boydti.fawe.util;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.*; import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.changeset.CPUOptimizedChangeSet; import com.boydti.fawe.object.changeset.CPUOptimizedChangeSet;
import com.boydti.fawe.object.changeset.FaweStreamChangeSet; import com.boydti.fawe.object.changeset.FaweStreamChangeSet;
import com.boydti.fawe.object.io.AbstractDelegateOutputStream; import com.boydti.fawe.object.io.AbstractDelegateOutputStream;
import com.boydti.fawe.object.io.PGZIPOutputStream; import com.github.luben.zstd.ZstdInputStream;
import com.sk89q.jnbt.*; import com.github.luben.zstd.ZstdOutputStream;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.EndTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.history.changeset.ChangeSet; import com.sk89q.worldedit.history.changeset.ChangeSet;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import java.io.*; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.*; import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.*; import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -28,11 +57,15 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.zip.Deflater;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
import net.jpountz.lz4.*; import net.jpountz.lz4.LZ4Compressor;
import net.jpountz.lz4.LZ4Factory;
import net.jpountz.lz4.LZ4FastDecompressor;
import net.jpountz.lz4.LZ4InputStream;
import net.jpountz.lz4.LZ4OutputStream;
import net.jpountz.lz4.LZ4Utils;
public class MainUtil { public class MainUtil {
/* /*
@ -213,17 +246,15 @@ public class MainUtil {
} }
public static FaweOutputStream getCompressedOS(OutputStream os, int amount, int buffer) throws IOException { public static FaweOutputStream getCompressedOS(OutputStream os, int amount, int buffer) throws IOException {
os.write((byte) amount); os.write((byte) -amount);
os = new BufferedOutputStream(os, buffer); os = new BufferedOutputStream(os, buffer);
if (amount == 0) { if (amount == 0) {
return new FaweOutputStream(os); return new FaweOutputStream(os);
} }
os = new BufferedOutputStream(os, buffer);
int gzipAmount = amount > 6 ? 1 : 0; int gzipAmount = amount > 6 ? 1 : 0;
for (int i = 0; i < gzipAmount; i++) { for (int i = 0; i < gzipAmount; i++) {
PGZIPOutputStream gzip = new PGZIPOutputStream(os, buffer); os = new ZstdOutputStream(os, 22);
os = new BufferedOutputStream(gzip);
gzip.setStrategy(Deflater.DEFAULT_STRATEGY);
gzip.setLevel(9);
} }
LZ4Factory factory = LZ4Factory.fastestInstance(); LZ4Factory factory = LZ4Factory.fastestInstance();
int fastAmount = 1 + ((amount - 1) % 3); int fastAmount = 1 + ((amount - 1) % 3);
@ -246,18 +277,22 @@ public class MainUtil {
} }
public static FaweInputStream getCompressedIS(InputStream is, int buffer) throws IOException { public static FaweInputStream getCompressedIS(InputStream is, int buffer) throws IOException {
int amount = is.read(); int amount = (byte) is.read();
is = new BufferedInputStream(is, buffer); is = new BufferedInputStream(is, buffer);
if (amount == 0) { if (amount == 0) {
return new FaweInputStream(is); return new FaweInputStream(is);
} }
int amountAbs = Math.abs(amount);
LZ4Factory factory = LZ4Factory.fastestInstance(); LZ4Factory factory = LZ4Factory.fastestInstance();
boolean gzip = amount > 6; if (amountAbs > 6) {
if (gzip) { if (amount > 0) {
is = new BufferedInputStream(new GZIPInputStream(is, buffer)); is = new BufferedInputStream(new GZIPInputStream(is, buffer));
} else {
is = new ZstdInputStream(is);
}
} }
amount = (1 + ((amount - 1) % 3)) + (amount > 3 ? 1 : 0); amountAbs = (1 + ((amountAbs - 1) % 3)) + (amountAbs > 3 ? 1 : 0);
for (int i = 0; i < amount; i++) { for (int i = 0; i < amountAbs; i++) {
is = new LZ4InputStream(is); is = new LZ4InputStream(is);
} }
return new FaweInputStream(is); return new FaweInputStream(is);
@ -351,8 +386,8 @@ public class MainUtil {
public static void sendCompressedMessage(FaweStreamChangeSet set, FawePlayer actor) public static void sendCompressedMessage(FaweStreamChangeSet set, FawePlayer actor)
{ {
try { try {
int elements = set.size(); long elements = set.size();
int compressedSize = set.getCompressedSize(); long compressedSize = set.getCompressedSize();
if (compressedSize == 0) { if (compressedSize == 0) {
return; return;
} }
@ -375,10 +410,10 @@ public class MainUtil {
* *
* This compares FAWE's usage to standard WE. * This compares FAWE's usage to standard WE.
*/ */
int total = 128 * elements; long total = 128 * elements;
int ratio = total / compressedSize; long ratio = total / compressedSize;
int saved = total - compressedSize; long saved = total - compressedSize;
if (ratio > 3 && Thread.currentThread() != Fawe.get().getMainThread() && actor != null) { if (ratio > 3 && Thread.currentThread() != Fawe.get().getMainThread() && actor != null) {
BBC.COMPRESSED.send(actor, saved, ratio); BBC.COMPRESSED.send(actor, saved, ratio);

View File

@ -286,6 +286,24 @@ public class RegionCommands {
BBC.VISITOR_BLOCK.send(player, affected); BBC.VISITOR_BLOCK.send(player, affected);
} }
@Command(
aliases = { "/mapreplace", "/mr", "/maprep" },
usage = "<from-block-1,from-block-2> <to-block-1,to-block-2>",
desc = "Replace all blocks in a selection 1:1 with the ",
flags = "f",
min = 1,
max = 2
)
@CommandPermissions("worldedit.region.mapreplace")
@Logging(REGION)
public void mapreplace(Player player, EditSession editSession, @Selection Region region, @Optional Mask from, Pattern to) throws WorldEditException {
if (from == null) {
from = new ExistingBlockMask(editSession);
}
int affected = editSession.replaceBlocks(region, from, Patterns.wrap(to));
BBC.VISITOR_BLOCK.send(player, affected);
}
@Command( @Command(
aliases = { "/set" }, aliases = { "/set" },
usage = "[pattern]", usage = "[pattern]",

View File

@ -1,5 +1,6 @@
package com.sk89q.worldedit.extension.factory; package com.sk89q.worldedit.extension.factory;
import com.boydti.fawe.command.FaweParser;
import com.boydti.fawe.object.mask.AdjacentMask; import com.boydti.fawe.object.mask.AdjacentMask;
import com.boydti.fawe.object.mask.AngleMask; import com.boydti.fawe.object.mask.AngleMask;
import com.boydti.fawe.object.mask.CustomMask; import com.boydti.fawe.object.mask.CustomMask;
@ -33,7 +34,6 @@ import com.sk89q.worldedit.function.mask.RegionMask;
import com.sk89q.worldedit.function.mask.SolidBlockMask; import com.sk89q.worldedit.function.mask.SolidBlockMask;
import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.math.noise.RandomNoise; import com.sk89q.worldedit.math.noise.RandomNoise;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment; import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.session.request.Request;
@ -54,7 +54,19 @@ import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* Parses mask input strings. * Parses mask input strings.
*/ */
public class DefaultMaskParser extends InputParser<Mask> { public class DefaultMaskParser extends FaweParser<Mask> {
public static final String[] EXPRESSION_MASK = new String[] { "=<expression>" };
public static final String[] BLOCK_MASK = new String[] { "<block>" };
public static final String[] SIMPLE_MASK = new String[] {
"#existing", "#solid", "#dregion", "#dselection", "#dsel", "#selection", "#region", "#sel", "#xaxis", "#yaxis", "#zaxis", "#id", "#data", "#wall", "#surface",
};
public static final String[] MISC_PATTERNS = new String[] {
"hand", "pos1",
};
public DefaultMaskParser(WorldEdit worldEdit) { public DefaultMaskParser(WorldEdit worldEdit) {
super(worldEdit); super(worldEdit);

View File

@ -1,5 +1,6 @@
package com.sk89q.worldedit.extension.factory; package com.sk89q.worldedit.extension.factory;
import com.boydti.fawe.command.FaweParser;
import com.boydti.fawe.command.SuggestInputParseException; import com.boydti.fawe.command.SuggestInputParseException;
import com.boydti.fawe.object.pattern.*; import com.boydti.fawe.object.pattern.*;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
@ -20,16 +21,14 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.RandomPattern; import com.sk89q.worldedit.function.pattern.RandomPattern;
import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment; import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.world.registry.BundledBlockData; import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
public class HashTagPatternParser extends InputParser<Pattern>{ public class HashTagPatternParser extends FaweParser<Pattern> {
public static final String[] EXPRESSION_PATTERN = new String[] { "=<expression>" }; public static final String[] EXPRESSION_PATTERN = new String[] { "=<expression>" };
@ -53,51 +52,6 @@ public class HashTagPatternParser extends InputParser<Pattern>{
super(worldEdit); super(worldEdit);
} }
private List<String> split(String input, char delim) {
List<String> result = new ArrayList<String>();
int start = 0;
boolean inQuotes = false;
for (int current = 0; current < input.length(); current++) {
if (input.charAt(current) == '\"') inQuotes = !inQuotes; // toggle state
boolean atLastChar = (current == input.length() - 1);
if(atLastChar) result.add(input.substring(start));
else if (input.charAt(current) == delim && !inQuotes) {
String toAdd = input.substring(start, current);
if (toAdd.startsWith("\"")) {
toAdd = toAdd.substring(1, toAdd.length() - 1);
}
result.add(toAdd);
start = current + 1;
}
}
return result;
}
private Pattern catchSuggestion(String currentInput, String nextInput, ParserContext context) throws InputParseException{
try {
return parseFromInput(nextInput, context);
} catch (SuggestInputParseException e) {
e.prepend(currentInput.substring(0, currentInput.length() - nextInput.length()));
throw e;
}
}
public List<String> handleRemainder(String input, String... expected) throws InputParseException {
List<String> remainder = split(input, ':');
int len = remainder.size();
if (len != expected.length - 1) {
if (len <= expected.length - 1 && len != 0) {
if (remainder.get(len - 1).endsWith(":")) {
throw new SuggestInputParseException(null, ALL_PATTERNS).prepend(expected[0] + ":" + input);
}
throw new SuggestInputParseException(null, expected[0] + ":" + input + ":" + StringMan.join(Arrays.copyOfRange(expected, len + 1, 3), ":"));
} else {
throw new SuggestInputParseException(null, StringMan.join(expected, ":"));
}
}
return remainder;
}
@Override @Override
public Pattern parseFromInput(String input, ParserContext context) throws InputParseException { public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
if (input.isEmpty()) { if (input.isEmpty()) {
@ -172,7 +126,7 @@ public class HashTagPatternParser extends InputParser<Pattern>{
return new NoZPattern(catchSuggestion(input, rest, context)); return new NoZPattern(catchSuggestion(input, rest, context));
} }
case "#mask": { case "#mask": {
List<String> split3 = handleRemainder(rest, "#mask", "<mask>", "<pattern-if>", "<pattern-else>"); List<String> split3 = suggestRemaining(rest, "#mask", "<mask>", "<pattern-if>", "<pattern-else>");
Pattern primary = catchSuggestion(input, split3.get(1), context); Pattern primary = catchSuggestion(input, split3.get(1), context);
Pattern secondary = catchSuggestion(input, split3.get(2), context); Pattern secondary = catchSuggestion(input, split3.get(2), context);
PatternExtent extent = new PatternExtent(primary); PatternExtent extent = new PatternExtent(primary);
@ -190,7 +144,7 @@ public class HashTagPatternParser extends InputParser<Pattern>{
} }
case "#offset": case "#offset":
try { try {
List<String> split3 = handleRemainder(rest, "#offset", "<dx>", "<dy>", "<dz>", "<pattern>"); List<String> split3 = suggestRemaining(rest, "#offset", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate()); int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate()); int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate()); int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());
@ -202,7 +156,7 @@ public class HashTagPatternParser extends InputParser<Pattern>{
} }
case "#surfacespread": { case "#surfacespread": {
try { try {
List<String> split3 = handleRemainder(rest, "#surfacespread", "<dx>", "<dy>", "<dz>", "<pattern>"); List<String> split3 = suggestRemaining(rest, "#surfacespread", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate()); int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate()); int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate()); int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());
@ -215,7 +169,7 @@ public class HashTagPatternParser extends InputParser<Pattern>{
} }
case "#solidspread": { case "#solidspread": {
try { try {
List<String> split3 = handleRemainder(rest, "#solidspread", "<dx>", "<dy>", "<dz>", "<pattern>"); List<String> split3 = suggestRemaining(rest, "#solidspread", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate()); int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate()); int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate()); int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());
@ -229,7 +183,7 @@ public class HashTagPatternParser extends InputParser<Pattern>{
case "#randomoffset": case "#randomoffset":
case "#spread": { case "#spread": {
try { try {
List<String> split3 = handleRemainder(rest, "#spread", "<dx>", "<dy>", "<dz>", "<pattern>"); List<String> split3 = suggestRemaining(rest, "#spread", "<dx>", "<dy>", "<dz>", "<pattern>");
int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate()); int x = (int) Math.abs(Expression.compile(split3.get(0)).evaluate());
int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate()); int y = (int) Math.abs(Expression.compile(split3.get(1)).evaluate());
int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate()); int z = (int) Math.abs(Expression.compile(split3.get(2)).evaluate());

View File

@ -356,7 +356,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
@Override @Override
public Iterator<BlockVector> iterator() { public Iterator<BlockVector> iterator() {
if (Settings.HISTORY.COMPRESSION_LEVEL == 9) { if (Settings.HISTORY.COMPRESSION_LEVEL >= 9) {
return iterator_old(); return iterator_old();
} }
final BlockVector v = new BlockVector(0,0,0); final BlockVector v = new BlockVector(0,0,0);

View File

@ -57,6 +57,7 @@ processResources {
shadowJar { shadowJar {
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency(':core')) include(dependency(':core'))
include(dependency('org.yaml:snakeyaml:1.16')) include(dependency('org.yaml:snakeyaml:1.16'))
} }

View File

@ -57,6 +57,7 @@ processResources {
shadowJar { shadowJar {
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency(':core')) include(dependency(':core'))
include(dependency('org.yaml:snakeyaml:1.16')) include(dependency('org.yaml:snakeyaml:1.16'))
} }

View File

@ -48,6 +48,7 @@ processResources {
shadowJar { shadowJar {
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency(':core')) include(dependency(':core'))
include(dependency('org.yaml:snakeyaml:1.16')) include(dependency('org.yaml:snakeyaml:1.16'))
} }

View File

@ -57,6 +57,7 @@ processResources {
shadowJar { shadowJar {
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency(':core')) include(dependency(':core'))
include(dependency('org.yaml:snakeyaml:1.16')) include(dependency('org.yaml:snakeyaml:1.16'))
} }

View File

@ -56,6 +56,7 @@ processResources {
shadowJar { shadowJar {
relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml'
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency(':core')) include(dependency(':core'))
include(dependency('org.yaml:snakeyaml:1.16')) include(dependency('org.yaml:snakeyaml:1.16'))
} }

View File

@ -22,6 +22,7 @@ apply plugin: 'com.github.johnrengelman.shadow'
jar.enabled = false jar.enabled = false
shadowJar { shadowJar {
dependencies { dependencies {
include(dependency('com.github.luben:zstd-jni:1.1.1'))
include(dependency(name: 'worldedit-core-6.1.4-SNAPSHOT-dist')) include(dependency(name: 'worldedit-core-6.1.4-SNAPSHOT-dist'))
include(dependency('com.google.code.gson:gson:2.2.4')) include(dependency('com.google.code.gson:gson:2.2.4'))
include(dependency('org.yaml:snakeyaml:1.16')) include(dependency('org.yaml:snakeyaml:1.16'))