mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2024-11-28 13:45:36 +01:00
Started work on disk storage for history
This commit is contained in:
parent
d9d806ac4a
commit
3cf106842d
@ -28,6 +28,7 @@ import com.sk89q.worldedit.EditSession;
|
|||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.command.SchematicCommands;
|
import com.sk89q.worldedit.command.SchematicCommands;
|
||||||
import com.sk89q.worldedit.command.ScriptingCommands;
|
import com.sk89q.worldedit.command.ScriptingCommands;
|
||||||
|
import com.sk89q.worldedit.extension.platform.CommandManager;
|
||||||
import com.sk89q.worldedit.function.operation.Operations;
|
import com.sk89q.worldedit.function.operation.Operations;
|
||||||
import com.sk89q.worldedit.function.visitor.BreadthFirstSearch;
|
import com.sk89q.worldedit.function.visitor.BreadthFirstSearch;
|
||||||
import com.sk89q.worldedit.function.visitor.DownwardVisitor;
|
import com.sk89q.worldedit.function.visitor.DownwardVisitor;
|
||||||
@ -212,6 +213,8 @@ public class Fawe {
|
|||||||
NonRisingVisitor.inject();
|
NonRisingVisitor.inject();
|
||||||
RecursiveVisitor.inject();
|
RecursiveVisitor.inject();
|
||||||
RegionVisitor.inject();
|
RegionVisitor.inject();
|
||||||
|
CommandManager.inject();
|
||||||
|
// DispatcherWrapper.inject();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupMemoryListener() {
|
private void setupMemoryListener() {
|
||||||
|
@ -37,4 +37,136 @@ public class FaweCache {
|
|||||||
CACHE_DATA[i] = (byte) k;
|
CACHE_DATA[i] = (byte) k;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean hasData(int id) {
|
||||||
|
switch (id) {
|
||||||
|
case 0:
|
||||||
|
case 2:
|
||||||
|
case 4:
|
||||||
|
case 13:
|
||||||
|
case 14:
|
||||||
|
case 15:
|
||||||
|
case 20:
|
||||||
|
case 21:
|
||||||
|
case 22:
|
||||||
|
case 25:
|
||||||
|
case 30:
|
||||||
|
case 32:
|
||||||
|
case 37:
|
||||||
|
case 39:
|
||||||
|
case 40:
|
||||||
|
case 41:
|
||||||
|
case 42:
|
||||||
|
case 45:
|
||||||
|
case 46:
|
||||||
|
case 47:
|
||||||
|
case 48:
|
||||||
|
case 49:
|
||||||
|
case 51:
|
||||||
|
case 52:
|
||||||
|
case 54:
|
||||||
|
case 56:
|
||||||
|
case 57:
|
||||||
|
case 58:
|
||||||
|
case 60:
|
||||||
|
case 61:
|
||||||
|
case 62:
|
||||||
|
case 7:
|
||||||
|
case 8:
|
||||||
|
case 9:
|
||||||
|
case 10:
|
||||||
|
case 11:
|
||||||
|
case 73:
|
||||||
|
case 74:
|
||||||
|
case 78:
|
||||||
|
case 79:
|
||||||
|
case 80:
|
||||||
|
case 81:
|
||||||
|
case 82:
|
||||||
|
case 83:
|
||||||
|
case 84:
|
||||||
|
case 85:
|
||||||
|
case 87:
|
||||||
|
case 88:
|
||||||
|
case 101:
|
||||||
|
case 102:
|
||||||
|
case 103:
|
||||||
|
case 110:
|
||||||
|
case 112:
|
||||||
|
case 113:
|
||||||
|
case 117:
|
||||||
|
case 121:
|
||||||
|
case 122:
|
||||||
|
case 123:
|
||||||
|
case 124:
|
||||||
|
case 129:
|
||||||
|
case 133:
|
||||||
|
case 138:
|
||||||
|
case 137:
|
||||||
|
case 140:
|
||||||
|
case 165:
|
||||||
|
case 166:
|
||||||
|
case 169:
|
||||||
|
case 170:
|
||||||
|
case 172:
|
||||||
|
case 173:
|
||||||
|
case 174:
|
||||||
|
case 176:
|
||||||
|
case 177:
|
||||||
|
case 181:
|
||||||
|
case 182:
|
||||||
|
case 188:
|
||||||
|
case 189:
|
||||||
|
case 190:
|
||||||
|
case 191:
|
||||||
|
case 192:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasNBT(int id) {
|
||||||
|
switch (id) {
|
||||||
|
case 54:
|
||||||
|
case 130:
|
||||||
|
case 142:
|
||||||
|
case 27:
|
||||||
|
case 137:
|
||||||
|
case 52:
|
||||||
|
case 154:
|
||||||
|
case 84:
|
||||||
|
case 25:
|
||||||
|
case 144:
|
||||||
|
case 138:
|
||||||
|
case 176:
|
||||||
|
case 177:
|
||||||
|
case 63:
|
||||||
|
case 119:
|
||||||
|
case 68:
|
||||||
|
case 323:
|
||||||
|
case 117:
|
||||||
|
case 116:
|
||||||
|
case 28:
|
||||||
|
case 66:
|
||||||
|
case 157:
|
||||||
|
case 61:
|
||||||
|
case 62:
|
||||||
|
case 140:
|
||||||
|
case 146:
|
||||||
|
case 149:
|
||||||
|
case 150:
|
||||||
|
case 158:
|
||||||
|
case 23:
|
||||||
|
case 123:
|
||||||
|
case 124:
|
||||||
|
case 29:
|
||||||
|
case 33:
|
||||||
|
case 151:
|
||||||
|
case 178:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@ import java.util.Map.Entry;
|
|||||||
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.LocalSession;
|
||||||
|
|
||||||
public class Settings {
|
public class Settings {
|
||||||
|
|
||||||
public static int MAX_BLOCKSTATES = 1337;
|
public static int MAX_BLOCKSTATES = 1337;
|
||||||
@ -22,6 +24,7 @@ public class Settings {
|
|||||||
public static List<String> WE_BLACKLIST = Arrays.asList("cs", ".s", "restore", "snapshot", "delchunks", "listchunks");
|
public static List<String> WE_BLACKLIST = Arrays.asList("cs", ".s", "restore", "snapshot", "delchunks", "listchunks");
|
||||||
public static long MEM_FREE = 95;
|
public static long MEM_FREE = 95;
|
||||||
public static boolean ENABLE_HARD_LIMIT = true;
|
public static boolean ENABLE_HARD_LIMIT = true;
|
||||||
|
public static boolean STORE_HISTORY_ON_DISK = true;
|
||||||
|
|
||||||
public static void setup(final File file) {
|
public static void setup(final File file) {
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
@ -45,6 +48,7 @@ public class Settings {
|
|||||||
options.put("max-memory-percent", MEM_FREE);
|
options.put("max-memory-percent", MEM_FREE);
|
||||||
options.put("crash-mitigation", ENABLE_HARD_LIMIT);
|
options.put("crash-mitigation", ENABLE_HARD_LIMIT);
|
||||||
options.put("fix-all-lighting", FIX_ALL_LIGHTING);
|
options.put("fix-all-lighting", FIX_ALL_LIGHTING);
|
||||||
|
options.put("store-history-on-disk", STORE_HISTORY_ON_DISK);
|
||||||
|
|
||||||
for (final Entry<String, Object> node : options.entrySet()) {
|
for (final Entry<String, Object> node : options.entrySet()) {
|
||||||
if (!config.contains(node.getKey())) {
|
if (!config.contains(node.getKey())) {
|
||||||
@ -61,6 +65,9 @@ public class Settings {
|
|||||||
REQUIRE_SELECTION = config.getBoolean("require-selection-in-mask");
|
REQUIRE_SELECTION = config.getBoolean("require-selection-in-mask");
|
||||||
WE_BLACKLIST = config.getStringList("command-blacklist");
|
WE_BLACKLIST = config.getStringList("command-blacklist");
|
||||||
ENABLE_HARD_LIMIT = config.getBoolean("crash-mitigation");
|
ENABLE_HARD_LIMIT = config.getBoolean("crash-mitigation");
|
||||||
|
if (STORE_HISTORY_ON_DISK = config.getBoolean("store-history-on-disk")) {
|
||||||
|
LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
config.save(file);
|
config.save(file);
|
||||||
|
29
src/main/java/com/boydti/fawe/object/NullChangeSet.java
Normal file
29
src/main/java/com/boydti/fawe/object/NullChangeSet.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package com.boydti.fawe.object;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.history.change.Change;
|
||||||
|
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||||
|
|
||||||
|
public class NullChangeSet implements ChangeSet {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(Change change) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Change> backwardIterator() {
|
||||||
|
return new ArrayList<Change>().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Change> forwardIterator() {
|
||||||
|
return new ArrayList<Change>().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.boydti.fawe.object.changeset;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.history.changeset.BlockOptimizedHistory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* History optimized for speed
|
||||||
|
* - Low CPU usage
|
||||||
|
* - High memory usage
|
||||||
|
* - No disk usage
|
||||||
|
*/
|
||||||
|
public class CPUOptimizedHistory extends BlockOptimizedHistory {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,234 @@
|
|||||||
|
package com.boydti.fawe.object.changeset;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
|
import com.boydti.fawe.FaweCache;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.jnbt.NBTOutputStream;
|
||||||
|
import com.sk89q.worldedit.BlockVector;
|
||||||
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
|
import com.sk89q.worldedit.history.change.BlockChange;
|
||||||
|
import com.sk89q.worldedit.history.change.Change;
|
||||||
|
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the change on disk
|
||||||
|
* - High disk usage
|
||||||
|
* - Moderate CPU usage
|
||||||
|
* - Minimal memory usage
|
||||||
|
* - Slow
|
||||||
|
*/
|
||||||
|
public class DiskStorageHistory implements ChangeSet {
|
||||||
|
|
||||||
|
private final File bdFile;
|
||||||
|
private final File nbtFile;
|
||||||
|
private final File anyFile;
|
||||||
|
|
||||||
|
private GZIPOutputStream osBD;
|
||||||
|
private ObjectOutputStream osANY;
|
||||||
|
private NBTOutputStream osNBT;
|
||||||
|
|
||||||
|
private int ox;
|
||||||
|
private int oz;
|
||||||
|
|
||||||
|
private final AtomicInteger size;
|
||||||
|
|
||||||
|
public DiskStorageHistory() {
|
||||||
|
size = new AtomicInteger();
|
||||||
|
UUID uuid = UUID.randomUUID();
|
||||||
|
nbtFile = new File(Fawe.imp().getDirectory(), "history" + File.separator + uuid.toString() + ".nbt");
|
||||||
|
bdFile = new File(Fawe.imp().getDirectory(), "history" + File.separator + uuid.toString() + ".bd");
|
||||||
|
anyFile = new File(Fawe.imp().getDirectory(), "history" + File.separator + uuid.toString() + ".any");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(Change change) {
|
||||||
|
size.incrementAndGet();
|
||||||
|
if ((change instanceof BlockChange)) {
|
||||||
|
add((BlockChange) change);
|
||||||
|
} else {
|
||||||
|
System.out.print("[FAWE] Does not support " + change + " yet! (Please bug Empire92)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() {
|
||||||
|
try {
|
||||||
|
if (osBD != null) {
|
||||||
|
osBD.flush();
|
||||||
|
osBD.close();
|
||||||
|
}
|
||||||
|
if (osANY != null) {
|
||||||
|
osANY.flush();
|
||||||
|
osANY.close();
|
||||||
|
}
|
||||||
|
if (osNBT != null) {
|
||||||
|
osNBT.close();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(BlockChange change) {
|
||||||
|
try {
|
||||||
|
BlockVector loc = change.getPosition();
|
||||||
|
int x = loc.getBlockX();
|
||||||
|
int y = loc.getBlockY();
|
||||||
|
int z = loc.getBlockZ();
|
||||||
|
|
||||||
|
BaseBlock from = change.getPrevious();
|
||||||
|
BaseBlock to = change.getCurrent();
|
||||||
|
|
||||||
|
int idfrom = from.getId();
|
||||||
|
int combinedFrom = (byte) (FaweCache.hasData(idfrom) ? ((idfrom << 4) + from.getData()) : (idfrom << 4));
|
||||||
|
CompoundTag nbtFrom = FaweCache.hasData(idfrom) ? from.getNbtData() : null;
|
||||||
|
|
||||||
|
int idTo = to.getId();
|
||||||
|
int combinedTo = (byte) (FaweCache.hasData(idTo) ? ((idTo << 4) + to.getData()) : (idTo << 4));
|
||||||
|
CompoundTag nbtTo = FaweCache.hasData(idTo) ? to.getNbtData() : null;
|
||||||
|
|
||||||
|
GZIPOutputStream stream = getBAOS(x, y, z);
|
||||||
|
//x
|
||||||
|
stream.write((x - ox) & 0xff);
|
||||||
|
stream.write(((x - ox) >> 8) & 0xff);
|
||||||
|
//z
|
||||||
|
stream.write((z - oz) & 0xff);
|
||||||
|
stream.write(((z - oz) >> 8) & 0xff);
|
||||||
|
//y
|
||||||
|
stream.write((byte) y);
|
||||||
|
//from
|
||||||
|
stream.write((combinedFrom) & 0xff);
|
||||||
|
stream.write(((combinedFrom) >> 8) & 0xff);
|
||||||
|
//to
|
||||||
|
stream.write((combinedTo) & 0xff);
|
||||||
|
stream.write(((combinedTo) >> 8) & 0xff);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [header]
|
||||||
|
* [int x][int z] origin
|
||||||
|
* [contents]
|
||||||
|
* relative: short x,short z,unsigned byte y
|
||||||
|
* from: char
|
||||||
|
* to: char
|
||||||
|
*/
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private GZIPOutputStream getBAOS(int x, int y, int z) throws IOException {
|
||||||
|
if (osBD != null) {
|
||||||
|
return osBD;
|
||||||
|
}
|
||||||
|
bdFile.getParentFile().mkdirs();
|
||||||
|
bdFile.createNewFile();
|
||||||
|
osBD = new GZIPOutputStream(new FileOutputStream(bdFile), true);
|
||||||
|
ox = x;
|
||||||
|
oz = z;
|
||||||
|
osBD.write((ox) & 0xff);
|
||||||
|
osBD.write(((ox) >> 8) & 0xff);
|
||||||
|
osBD.write((oz) & 0xff);
|
||||||
|
osBD.write(((oz) >> 8) & 0xff);
|
||||||
|
return osBD;
|
||||||
|
}
|
||||||
|
|
||||||
|
private NBTOutputStream getNBTOS(int x, int y, int z) throws IOException {
|
||||||
|
if (osNBT != null) {
|
||||||
|
return osNBT;
|
||||||
|
}
|
||||||
|
nbtFile.getParentFile().mkdirs();
|
||||||
|
nbtFile.createNewFile();
|
||||||
|
// osNBT = new FileOutputStream(bdFile);
|
||||||
|
// TODO FIXME
|
||||||
|
return osNBT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("resource")
|
||||||
|
public Iterator<Change> getIterator(final boolean dir) {
|
||||||
|
flush();
|
||||||
|
try {
|
||||||
|
if (bdFile.exists()) {
|
||||||
|
final GZIPInputStream gis = new GZIPInputStream(new FileInputStream(bdFile));
|
||||||
|
gis.skip(4);
|
||||||
|
return new Iterator<Change>() {
|
||||||
|
|
||||||
|
private Change last = read();
|
||||||
|
|
||||||
|
public Change read() {
|
||||||
|
try {
|
||||||
|
int x = gis.read() + (gis.read() << 8) + ox;
|
||||||
|
int z = gis.read() + (gis.read() << 8) + oz;
|
||||||
|
int y = gis.read() & 0xff;
|
||||||
|
int from1 = gis.read();
|
||||||
|
int from2 = gis.read();
|
||||||
|
BaseBlock from = new BaseBlock(((from2 << 4) + (from1 >> 4)), (from1 & 0xf));
|
||||||
|
int to1 = gis.read();
|
||||||
|
int to2 = gis.read();
|
||||||
|
BaseBlock to = new BaseBlock(((to2 << 4) + (to1 >> 4)), (to1 & 0xf));
|
||||||
|
BlockVector position = new BlockVector(x, y, z);
|
||||||
|
return dir ? new BlockChange(position, to, from) : new BlockChange(position, from, to);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
if (last != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
gis.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Change next() {
|
||||||
|
Change tmp = last;
|
||||||
|
last = read();
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
throw new IllegalArgumentException("CANNOT REMIVE");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return new ArrayList<Change>().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Change> backwardIterator() {
|
||||||
|
return getIterator(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Change> forwardIterator() {
|
||||||
|
return getIterator(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
flush();
|
||||||
|
return size.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.boydti.fawe.object.changeset;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.history.change.Change;
|
||||||
|
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ChangeSet optimized for low memory usage
|
||||||
|
* - No disk usage
|
||||||
|
* - High CPU usage
|
||||||
|
* - Low memory usage
|
||||||
|
*/
|
||||||
|
public class MemoryOptimizedHistory implements ChangeSet {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(Change paramChange) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Change> backwardIterator() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Change> forwardIterator() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.boydti.fawe.object;
|
package com.boydti.fawe.object.extent;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.boydti.fawe.object;
|
package com.boydti.fawe.object.extent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
@ -1,10 +1,12 @@
|
|||||||
package com.boydti.fawe.object;
|
package com.boydti.fawe.object.extent;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
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.FawePlayer;
|
||||||
|
import com.boydti.fawe.object.RegionWrapper;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.SetQueue;
|
import com.boydti.fawe.util.SetQueue;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
@ -1,7 +1,10 @@
|
|||||||
package com.boydti.fawe.util;
|
package com.boydti.fawe.object.extent;
|
||||||
|
|
||||||
import com.boydti.fawe.config.BBC;
|
import com.boydti.fawe.config.BBC;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
|
import com.boydti.fawe.util.MemUtil;
|
||||||
|
import com.boydti.fawe.util.Perm;
|
||||||
|
import com.boydti.fawe.util.WEManager;
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
5
src/main/java/com/boydti/fawe/util/FileUtil.java
Normal file
5
src/main/java/com/boydti/fawe/util/FileUtil.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package com.boydti.fawe.util;
|
||||||
|
|
||||||
|
public class FileUtil {
|
||||||
|
|
||||||
|
}
|
@ -7,8 +7,8 @@ import java.util.HashSet;
|
|||||||
import com.boydti.fawe.bukkit.regions.FaweMask;
|
import com.boydti.fawe.bukkit.regions.FaweMask;
|
||||||
import com.boydti.fawe.config.BBC;
|
import com.boydti.fawe.config.BBC;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import com.boydti.fawe.object.NullExtent;
|
|
||||||
import com.boydti.fawe.object.RegionWrapper;
|
import com.boydti.fawe.object.RegionWrapper;
|
||||||
|
import com.boydti.fawe.object.extent.NullExtent;
|
||||||
import com.boydti.fawe.regions.FaweMaskManager;
|
import com.boydti.fawe.regions.FaweMaskManager;
|
||||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
|
@ -42,15 +42,16 @@ import com.boydti.fawe.Fawe;
|
|||||||
import com.boydti.fawe.FaweCache;
|
import com.boydti.fawe.FaweCache;
|
||||||
import com.boydti.fawe.config.BBC;
|
import com.boydti.fawe.config.BBC;
|
||||||
import com.boydti.fawe.object.EditSessionWrapper;
|
import com.boydti.fawe.object.EditSessionWrapper;
|
||||||
import com.boydti.fawe.object.FastWorldEditExtent;
|
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import com.boydti.fawe.object.NullExtent;
|
|
||||||
import com.boydti.fawe.object.ProcessedWEExtent;
|
|
||||||
import com.boydti.fawe.object.RegionWrapper;
|
import com.boydti.fawe.object.RegionWrapper;
|
||||||
|
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
||||||
|
import com.boydti.fawe.object.extent.FastWorldEditExtent;
|
||||||
|
import com.boydti.fawe.object.extent.NullExtent;
|
||||||
|
import com.boydti.fawe.object.extent.ProcessedWEExtent;
|
||||||
|
import com.boydti.fawe.object.extent.SafeExtentWrapper;
|
||||||
import com.boydti.fawe.util.ExtentWrapper;
|
import com.boydti.fawe.util.ExtentWrapper;
|
||||||
import com.boydti.fawe.util.MemUtil;
|
import com.boydti.fawe.util.MemUtil;
|
||||||
import com.boydti.fawe.util.Perm;
|
import com.boydti.fawe.util.Perm;
|
||||||
import com.boydti.fawe.util.SafeExtentWrapper;
|
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import com.boydti.fawe.util.WEManager;
|
import com.boydti.fawe.util.WEManager;
|
||||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||||
@ -100,7 +101,6 @@ import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
|||||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||||
import com.sk89q.worldedit.history.UndoContext;
|
import com.sk89q.worldedit.history.UndoContext;
|
||||||
import com.sk89q.worldedit.history.change.BlockChange;
|
import com.sk89q.worldedit.history.change.BlockChange;
|
||||||
import com.sk89q.worldedit.history.changeset.BlockOptimizedHistory;
|
|
||||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||||
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;
|
||||||
@ -149,7 +149,7 @@ public class EditSession implements Extent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected final World world;
|
protected final World world;
|
||||||
private final ChangeSet changeSet = new BlockOptimizedHistory();
|
private final ChangeSet changeSet;
|
||||||
private final EditSessionWrapper wrapper;
|
private final EditSessionWrapper wrapper;
|
||||||
private MultiStageReorder reorderExtent;
|
private MultiStageReorder reorderExtent;
|
||||||
private @Nullable Extent changeSetExtent;
|
private @Nullable Extent changeSetExtent;
|
||||||
@ -214,6 +214,8 @@ public class EditSession implements Extent {
|
|||||||
this.thread = Fawe.get().getMainThread();
|
this.thread = Fawe.get().getMainThread();
|
||||||
this.world = world;
|
this.world = world;
|
||||||
this.wrapper = Fawe.imp().getEditSessionWrapper(this);
|
this.wrapper = Fawe.imp().getEditSessionWrapper(this);
|
||||||
|
// this.changeSet = new BlockOptimizedHistory();
|
||||||
|
this.changeSet = new DiskStorageHistory();
|
||||||
|
|
||||||
// Invalid; return null extent
|
// Invalid; return null extent
|
||||||
if (world == null) {
|
if (world == null) {
|
||||||
|
@ -1,111 +0,0 @@
|
|||||||
package com.sk89q.worldedit.command;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import com.boydti.fawe.util.TaskManager;
|
|
||||||
import com.sk89q.minecraft.util.commands.CommandException;
|
|
||||||
import com.sk89q.minecraft.util.commands.CommandLocals;
|
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
|
||||||
import com.sk89q.worldedit.extension.platform.CommandManager;
|
|
||||||
import com.sk89q.worldedit.extension.platform.PlatformManager;
|
|
||||||
import com.sk89q.worldedit.util.command.CommandCallable;
|
|
||||||
import com.sk89q.worldedit.util.command.CommandMapping;
|
|
||||||
import com.sk89q.worldedit.util.command.Description;
|
|
||||||
import com.sk89q.worldedit.util.command.Dispatcher;
|
|
||||||
|
|
||||||
public class DispatcherWrapper implements Dispatcher {
|
|
||||||
private final Dispatcher parent;
|
|
||||||
|
|
||||||
public final Dispatcher getParent() {
|
|
||||||
return this.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DispatcherWrapper(final Dispatcher parent) {
|
|
||||||
this.parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerCommand(final CommandCallable callable, final String... alias) {
|
|
||||||
this.parent.registerCommand(callable, alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<CommandMapping> getCommands() {
|
|
||||||
return this.parent.getCommands();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<String> getPrimaryAliases() {
|
|
||||||
return this.parent.getPrimaryAliases();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<String> getAliases() {
|
|
||||||
return this.parent.getAliases();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommandMapping get(final String alias) {
|
|
||||||
return this.parent.get(alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean contains(final String alias) {
|
|
||||||
return this.parent.contains(alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object call(final String arguments, final CommandLocals locals, final String[] parentCommands) throws CommandException {
|
|
||||||
TaskManager.IMP.async(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
DispatcherWrapper.this.parent.call(arguments, locals, parentCommands);
|
|
||||||
} catch (final CommandException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Description getDescription() {
|
|
||||||
return this.parent.getDescription();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean testPermission(final CommandLocals locals) {
|
|
||||||
return this.parent.testPermission(locals);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getSuggestions(final String arguments, final CommandLocals locals) throws CommandException {
|
|
||||||
return this.parent.getSuggestions(arguments, locals);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void inject() {
|
|
||||||
// Delayed injection
|
|
||||||
TaskManager.IMP.task(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
final PlatformManager platform = WorldEdit.getInstance().getPlatformManager();
|
|
||||||
final CommandManager command = platform.getCommandManager();
|
|
||||||
final Class<? extends CommandManager> clazz = command.getClass();
|
|
||||||
final Field field = clazz.getDeclaredField("dispatcher");
|
|
||||||
field.setAccessible(true);
|
|
||||||
final Dispatcher parent = (Dispatcher) field.get(command);
|
|
||||||
final DispatcherWrapper dispatcher = new DispatcherWrapper(parent);
|
|
||||||
field.set(command, dispatcher);
|
|
||||||
} catch (final Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,321 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit team and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sk89q.worldedit.extension.platform;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.sk89q.worldedit.util.command.composition.LegacyCommandAdapter.adapt;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.logging.FileHandler;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import com.boydti.fawe.util.TaskManager;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandException;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandLocals;
|
||||||
|
import com.sk89q.minecraft.util.commands.CommandPermissionsException;
|
||||||
|
import com.sk89q.minecraft.util.commands.WrappedCommandException;
|
||||||
|
import com.sk89q.worldedit.EditSession;
|
||||||
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
|
import com.sk89q.worldedit.LocalSession;
|
||||||
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
|
import com.sk89q.worldedit.command.BiomeCommands;
|
||||||
|
import com.sk89q.worldedit.command.BrushCommands;
|
||||||
|
import com.sk89q.worldedit.command.ChunkCommands;
|
||||||
|
import com.sk89q.worldedit.command.ClipboardCommands;
|
||||||
|
import com.sk89q.worldedit.command.GeneralCommands;
|
||||||
|
import com.sk89q.worldedit.command.GenerationCommands;
|
||||||
|
import com.sk89q.worldedit.command.HistoryCommands;
|
||||||
|
import com.sk89q.worldedit.command.NavigationCommands;
|
||||||
|
import com.sk89q.worldedit.command.RegionCommands;
|
||||||
|
import com.sk89q.worldedit.command.SchematicCommands;
|
||||||
|
import com.sk89q.worldedit.command.ScriptingCommands;
|
||||||
|
import com.sk89q.worldedit.command.SelectionCommands;
|
||||||
|
import com.sk89q.worldedit.command.SnapshotCommands;
|
||||||
|
import com.sk89q.worldedit.command.SnapshotUtilCommands;
|
||||||
|
import com.sk89q.worldedit.command.SuperPickaxeCommands;
|
||||||
|
import com.sk89q.worldedit.command.ToolCommands;
|
||||||
|
import com.sk89q.worldedit.command.ToolUtilCommands;
|
||||||
|
import com.sk89q.worldedit.command.UtilityCommands;
|
||||||
|
import com.sk89q.worldedit.command.WorldEditCommands;
|
||||||
|
import com.sk89q.worldedit.command.argument.ReplaceParser;
|
||||||
|
import com.sk89q.worldedit.command.argument.TreeGeneratorParser;
|
||||||
|
import com.sk89q.worldedit.command.composition.ApplyCommand;
|
||||||
|
import com.sk89q.worldedit.command.composition.DeformCommand;
|
||||||
|
import com.sk89q.worldedit.command.composition.PaintCommand;
|
||||||
|
import com.sk89q.worldedit.command.composition.SelectionCommand;
|
||||||
|
import com.sk89q.worldedit.command.composition.ShapedBrushCommand;
|
||||||
|
import com.sk89q.worldedit.event.platform.CommandEvent;
|
||||||
|
import com.sk89q.worldedit.event.platform.CommandSuggestionEvent;
|
||||||
|
import com.sk89q.worldedit.function.factory.Deform;
|
||||||
|
import com.sk89q.worldedit.function.factory.Deform.Mode;
|
||||||
|
import com.sk89q.worldedit.internal.command.ActorAuthorizer;
|
||||||
|
import com.sk89q.worldedit.internal.command.CommandLoggingHandler;
|
||||||
|
import com.sk89q.worldedit.internal.command.UserCommandCompleter;
|
||||||
|
import com.sk89q.worldedit.internal.command.WorldEditBinding;
|
||||||
|
import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter;
|
||||||
|
import com.sk89q.worldedit.session.request.Request;
|
||||||
|
import com.sk89q.worldedit.util.command.Dispatcher;
|
||||||
|
import com.sk89q.worldedit.util.command.InvalidUsageException;
|
||||||
|
import com.sk89q.worldedit.util.command.composition.ProvidedValue;
|
||||||
|
import com.sk89q.worldedit.util.command.fluent.CommandGraph;
|
||||||
|
import com.sk89q.worldedit.util.command.parametric.ExceptionConverter;
|
||||||
|
import com.sk89q.worldedit.util.command.parametric.LegacyCommandsHandler;
|
||||||
|
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
|
||||||
|
import com.sk89q.worldedit.util.eventbus.Subscribe;
|
||||||
|
import com.sk89q.worldedit.util.formatting.ColorCodeBuilder;
|
||||||
|
import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
|
||||||
|
import com.sk89q.worldedit.util.logging.DynamicStreamHandler;
|
||||||
|
import com.sk89q.worldedit.util.logging.LogFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the registration and invocation of commands.
|
||||||
|
*
|
||||||
|
* <p>This class is primarily for internal usage.</p>
|
||||||
|
*/
|
||||||
|
public final class CommandManager {
|
||||||
|
|
||||||
|
public static final Pattern COMMAND_CLEAN_PATTERN = Pattern.compile("^[/]+");
|
||||||
|
private static final Logger log = Logger.getLogger(CommandManager.class.getCanonicalName());
|
||||||
|
private static final Logger commandLog = Logger.getLogger(CommandManager.class.getCanonicalName() + ".CommandLog");
|
||||||
|
private static final Pattern numberFormatExceptionPattern = Pattern.compile("^For input string: \"(.*)\"$");
|
||||||
|
|
||||||
|
private final WorldEdit worldEdit;
|
||||||
|
private final PlatformManager platformManager;
|
||||||
|
private final Dispatcher dispatcher;
|
||||||
|
private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler();
|
||||||
|
private final ExceptionConverter exceptionConverter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance.
|
||||||
|
*
|
||||||
|
* @param worldEdit the WorldEdit instance
|
||||||
|
*/
|
||||||
|
public CommandManager(final WorldEdit worldEdit, PlatformManager platformManager) {
|
||||||
|
checkNotNull(worldEdit);
|
||||||
|
checkNotNull(platformManager);
|
||||||
|
this.worldEdit = worldEdit;
|
||||||
|
this.platformManager = platformManager;
|
||||||
|
this.exceptionConverter = new WorldEditExceptionConverter(worldEdit);
|
||||||
|
|
||||||
|
// Register this instance for command events
|
||||||
|
worldEdit.getEventBus().register(this);
|
||||||
|
|
||||||
|
// Setup the logger
|
||||||
|
commandLog.addHandler(dynamicHandler);
|
||||||
|
dynamicHandler.setFormatter(new LogFormat());
|
||||||
|
|
||||||
|
// Set up the commands manager
|
||||||
|
ParametricBuilder builder = new ParametricBuilder();
|
||||||
|
builder.setAuthorizer(new ActorAuthorizer());
|
||||||
|
builder.setDefaultCompleter(new UserCommandCompleter(platformManager));
|
||||||
|
builder.addBinding(new WorldEditBinding(worldEdit));
|
||||||
|
builder.addExceptionConverter(exceptionConverter);
|
||||||
|
builder.addInvokeListener(new LegacyCommandsHandler());
|
||||||
|
builder.addInvokeListener(new CommandLoggingHandler(worldEdit, commandLog));
|
||||||
|
|
||||||
|
dispatcher = new CommandGraph().builder(builder).commands().registerMethods(new BiomeCommands(worldEdit)).registerMethods(new ChunkCommands(worldEdit))
|
||||||
|
.registerMethods(new ClipboardCommands(worldEdit)).registerMethods(new GeneralCommands(worldEdit)).registerMethods(new GenerationCommands(worldEdit))
|
||||||
|
.registerMethods(new HistoryCommands(worldEdit)).registerMethods(new NavigationCommands(worldEdit)).registerMethods(new RegionCommands(worldEdit))
|
||||||
|
.registerMethods(new ScriptingCommands(worldEdit)).registerMethods(new SelectionCommands(worldEdit)).registerMethods(new SnapshotUtilCommands(worldEdit))
|
||||||
|
.registerMethods(new ToolUtilCommands(worldEdit)).registerMethods(new ToolCommands(worldEdit)).registerMethods(new UtilityCommands(worldEdit))
|
||||||
|
.register(adapt(new SelectionCommand(new ApplyCommand(new ReplaceParser(), "Set all blocks within selection"), "worldedit.region.set")), "/set").group("worldedit", "we")
|
||||||
|
.describeAs("WorldEdit commands").registerMethods(new WorldEditCommands(worldEdit)).parent().group("schematic", "schem", "/schematic", "/schem")
|
||||||
|
.describeAs("Schematic commands for saving/loading areas").registerMethods(new SchematicCommands(worldEdit)).parent().group("snapshot", "snap")
|
||||||
|
.describeAs("Schematic commands for saving/loading areas").registerMethods(new SnapshotCommands(worldEdit)).parent().group("brush", "br").describeAs("Brushing commands")
|
||||||
|
.registerMethods(new BrushCommands(worldEdit)).register(adapt(new ShapedBrushCommand(new DeformCommand(), "worldedit.brush.deform")), "deform")
|
||||||
|
.register(adapt(new ShapedBrushCommand(new ApplyCommand(new ReplaceParser(), "Set all blocks within region"), "worldedit.brush.set")), "set")
|
||||||
|
.register(adapt(new ShapedBrushCommand(new PaintCommand(), "worldedit.brush.paint")), "paint").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(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()
|
||||||
|
.group("superpickaxe", "pickaxe", "sp").describeAs("Super-pickaxe commands").registerMethods(new SuperPickaxeCommands(worldEdit)).parent().group("tool")
|
||||||
|
.describeAs("Bind functions to held items").registerMethods(new ToolCommands(worldEdit)).parent().graph().getDispatcher();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExceptionConverter getExceptionConverter() {
|
||||||
|
return exceptionConverter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void register(Platform platform) {
|
||||||
|
log.log(Level.FINE, "Registering commands with " + platform.getClass().getCanonicalName());
|
||||||
|
|
||||||
|
LocalConfiguration config = platform.getConfiguration();
|
||||||
|
boolean logging = config.logCommands;
|
||||||
|
String path = config.logFile;
|
||||||
|
|
||||||
|
// Register log
|
||||||
|
if (!logging || path.isEmpty()) {
|
||||||
|
dynamicHandler.setHandler(null);
|
||||||
|
commandLog.setLevel(Level.OFF);
|
||||||
|
} else {
|
||||||
|
File file = new File(config.getWorkingDirectory(), path);
|
||||||
|
commandLog.setLevel(Level.ALL);
|
||||||
|
|
||||||
|
log.log(Level.INFO, "Logging WorldEdit commands to " + file.getAbsolutePath());
|
||||||
|
|
||||||
|
try {
|
||||||
|
dynamicHandler.setHandler(new FileHandler(file.getAbsolutePath(), true));
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.log(Level.WARNING, "Could not use command log file " + path + ": " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
platform.registerCommands(dispatcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unregister() {
|
||||||
|
dynamicHandler.setHandler(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] commandDetection(String[] split) {
|
||||||
|
// Quick script shortcut
|
||||||
|
if (split[0].matches("^[^/].*\\.js$")) {
|
||||||
|
String[] newSplit = new String[split.length + 1];
|
||||||
|
System.arraycopy(split, 0, newSplit, 1, split.length);
|
||||||
|
newSplit[0] = "cs";
|
||||||
|
newSplit[1] = newSplit[1];
|
||||||
|
split = newSplit;
|
||||||
|
}
|
||||||
|
|
||||||
|
String searchCmd = split[0].toLowerCase();
|
||||||
|
|
||||||
|
// Try to detect the command
|
||||||
|
if (!dispatcher.contains(searchCmd)) {
|
||||||
|
if (worldEdit.getConfiguration().noDoubleSlash && dispatcher.contains("/" + searchCmd)) {
|
||||||
|
split[0] = "/" + split[0];
|
||||||
|
} else if (searchCmd.length() >= 2 && searchCmd.charAt(0) == '/' && dispatcher.contains(searchCmd.substring(1))) {
|
||||||
|
split[0] = split[0].substring(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return split;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void handleCommand(final CommandEvent event) {
|
||||||
|
Request.reset();
|
||||||
|
TaskManager.IMP.async(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Actor actor = platformManager.createProxyActor(event.getActor());
|
||||||
|
String[] split = commandDetection(event.getArguments().split(" "));
|
||||||
|
|
||||||
|
// No command found!
|
||||||
|
if (!dispatcher.contains(split[0])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalSession session = worldEdit.getSessionManager().get(actor);
|
||||||
|
LocalConfiguration config = worldEdit.getConfiguration();
|
||||||
|
|
||||||
|
CommandLocals locals = new CommandLocals();
|
||||||
|
locals.put(Actor.class, actor);
|
||||||
|
locals.put("arguments", event.getArguments());
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
try {
|
||||||
|
dispatcher.call(Joiner.on(" ").join(split), locals, new String[0]);
|
||||||
|
} catch (CommandPermissionsException e) {
|
||||||
|
actor.printError("You are not permitted to do that. Are you in the right mode?");
|
||||||
|
} catch (InvalidUsageException e) {
|
||||||
|
if (e.isFullHelpSuggested()) {
|
||||||
|
actor.printRaw(ColorCodeBuilder.asColorCodes(new CommandUsageBox(e.getCommand(), e.getCommandUsed("/", ""), locals)));
|
||||||
|
String message = e.getMessage();
|
||||||
|
if (message != null) {
|
||||||
|
actor.printError(message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String message = e.getMessage();
|
||||||
|
actor.printError(message != null ? message : "The command was not used properly (no more help available).");
|
||||||
|
actor.printError("Usage: " + e.getSimpleUsageString("/"));
|
||||||
|
}
|
||||||
|
} catch (WrappedCommandException e) {
|
||||||
|
Throwable t = e.getCause();
|
||||||
|
actor.printError("Please report this error: [See console]");
|
||||||
|
actor.printRaw(t.getClass().getName() + ": " + t.getMessage());
|
||||||
|
log.log(Level.SEVERE, "An unexpected error while handling a WorldEdit command", t);
|
||||||
|
} catch (CommandException e) {
|
||||||
|
String message = e.getMessage();
|
||||||
|
if (message != null) {
|
||||||
|
actor.printError(e.getMessage());
|
||||||
|
} else {
|
||||||
|
actor.printError("An unknown error has occurred! Please see console.");
|
||||||
|
log.log(Level.SEVERE, "An unknown error occurred", e);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
EditSession editSession = locals.get(EditSession.class);
|
||||||
|
|
||||||
|
if (editSession != null) {
|
||||||
|
session.remember(editSession);
|
||||||
|
editSession.flushQueue();
|
||||||
|
|
||||||
|
if (config.profile) {
|
||||||
|
long time = System.currentTimeMillis() - start;
|
||||||
|
int changed = editSession.getBlockChangeCount();
|
||||||
|
if (time > 0) {
|
||||||
|
double throughput = changed / (time / 1000.0);
|
||||||
|
actor.printDebug((time / 1000.0) + "s elapsed (history: " + changed + " changed; " + Math.round(throughput) + " blocks/sec).");
|
||||||
|
} else {
|
||||||
|
actor.printDebug((time / 1000.0) + "s elapsed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
worldEdit.flushBlockBag(actor, editSession);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void handleCommandSuggestion(CommandSuggestionEvent event) {
|
||||||
|
try {
|
||||||
|
CommandLocals locals = new CommandLocals();
|
||||||
|
locals.put(Actor.class, event.getActor());
|
||||||
|
locals.put("arguments", event.getArguments());
|
||||||
|
event.setSuggestions(dispatcher.getSuggestions(event.getArguments(), locals));
|
||||||
|
} catch (CommandException e) {
|
||||||
|
event.getActor().printError(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the command dispatcher instance.
|
||||||
|
*
|
||||||
|
* @return the command dispatcher
|
||||||
|
*/
|
||||||
|
public Dispatcher getDispatcher() {
|
||||||
|
return dispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Logger getLogger() {
|
||||||
|
return commandLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class<?> inject() {
|
||||||
|
return CommandManager.class;
|
||||||
|
}
|
||||||
|
}
|
@ -37,7 +37,7 @@ import com.sk89q.worldedit.function.operation.RunContext;
|
|||||||
public class EntityVisitor implements Operation {
|
public class EntityVisitor implements Operation {
|
||||||
|
|
||||||
private final EntityFunction function;
|
private final EntityFunction function;
|
||||||
private final int affected = 0;
|
private int affected = 0;
|
||||||
private final Iterator<? extends Entity> iterator;
|
private final Iterator<? extends Entity> iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,7 +66,9 @@ public class EntityVisitor implements Operation {
|
|||||||
@Override
|
@Override
|
||||||
public Operation resume(final RunContext run) throws WorldEditException {
|
public Operation resume(final RunContext run) throws WorldEditException {
|
||||||
while (this.iterator.hasNext()) {
|
while (this.iterator.hasNext()) {
|
||||||
this.function.apply(this.iterator.next());
|
if (this.function.apply(this.iterator.next())) {
|
||||||
|
affected++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ import com.sk89q.worldedit.regions.FlatRegion;
|
|||||||
public class FlatRegionVisitor implements Operation {
|
public class FlatRegionVisitor implements Operation {
|
||||||
|
|
||||||
private final FlatRegionFunction function;
|
private final FlatRegionFunction function;
|
||||||
private final int affected = 0;
|
private int affected = 0;
|
||||||
private final Iterable<Vector2D> iterator;
|
private final Iterable<Vector2D> iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,7 +65,9 @@ public class FlatRegionVisitor implements Operation {
|
|||||||
@Override
|
@Override
|
||||||
public Operation resume(final RunContext run) throws WorldEditException {
|
public Operation resume(final RunContext run) throws WorldEditException {
|
||||||
for (final Vector2D pt : this.iterator) {
|
for (final Vector2D pt : this.iterator) {
|
||||||
this.function.apply(pt);
|
if (this.function.apply(pt)) {
|
||||||
|
affected++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ import com.sk89q.worldedit.regions.Region;
|
|||||||
public class RegionVisitor implements Operation {
|
public class RegionVisitor implements Operation {
|
||||||
|
|
||||||
private final RegionFunction function;
|
private final RegionFunction function;
|
||||||
private final int affected = 0;
|
private int affected = 0;
|
||||||
|
|
||||||
private final Iterator<BlockVector> iterator;
|
private final Iterator<BlockVector> iterator;
|
||||||
|
|
||||||
@ -58,7 +58,9 @@ public class RegionVisitor implements Operation {
|
|||||||
@Override
|
@Override
|
||||||
public Operation resume(final RunContext run) throws WorldEditException {
|
public Operation resume(final RunContext run) throws WorldEditException {
|
||||||
while (this.iterator.hasNext()) {
|
while (this.iterator.hasNext()) {
|
||||||
this.function.apply(this.iterator.next());
|
if (this.function.apply(this.iterator.next())) {
|
||||||
|
affected++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user