Various minor changes

This commit is contained in:
MattBDev 2020-03-03 21:41:51 -05:00
parent e2d7a5918d
commit b818c03f84
9 changed files with 15 additions and 680 deletions

View File

@ -13,25 +13,9 @@ public class DBHandler {
public final static DBHandler IMP = new DBHandler();
private Map<String, RollbackDatabase> databases = new ConcurrentHashMap<>(8, 0.9f, 1);
private Map<World, RollbackDatabase> databases = new ConcurrentHashMap<>(8, 0.9f, 1);
public RollbackDatabase getDatabase(World world) {
String worldName = world.getName();
RollbackDatabase database = databases.get(worldName);
if (database != null) {
return database;
}
try {
database = new RollbackDatabase(world);
databases.put(worldName, database);
return database;
} catch (Throwable e) {
log.error("No JDBC driver found!\n TODO: Bundle driver with FAWE (or disable database)", e);
return null;
}
}
public RollbackDatabase getDatabase(String world) {
RollbackDatabase database = databases.get(world);
if (database != null) {
return database;
@ -41,8 +25,9 @@ public class DBHandler {
databases.put(world, database);
return database;
} catch (Throwable e) {
e.printStackTrace();
log.error("No JDBC driver found!", e);
return null;
}
}
}

View File

@ -1,7 +1,6 @@
package com.boydti.fawe.database;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory;
import com.boydti.fawe.object.collection.YieldIterable;
@ -36,7 +35,6 @@ public class RollbackDatabase extends AsyncNotifyQueue {
private final String prefix;
private final File dbLocation;
private final String worldName;
private final World world;
private Connection connection;
@ -56,14 +54,9 @@ public class RollbackDatabase extends AsyncNotifyQueue {
private ConcurrentLinkedQueue<RollbackOptimizedHistory> historyChanges = new ConcurrentLinkedQueue<>();
public RollbackDatabase(String world) throws SQLException, ClassNotFoundException {
this(FaweAPI.getWorld(world));
}
public RollbackDatabase(World world) throws SQLException, ClassNotFoundException {
RollbackDatabase(World world) throws SQLException, ClassNotFoundException {
super((t, e) -> e.printStackTrace());
this.prefix = "";
this.worldName = world.getName();
this.world = world;
this.dbLocation = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.HISTORY + File.separator + world.getName() + File.separator + "summary.db");
connection = openConnection();
@ -180,7 +173,6 @@ public class RollbackDatabase extends AsyncNotifyQueue {
int count = 0;
String stmtStr = ascending ? uuid == null ? GET_EDITS_ASC : GET_EDITS_USER_ASC :
uuid == null ? GET_EDITS : GET_EDITS_USER;
// `time`>? AND `x2`>=? AND `x1`<=? AND `z2`>=? AND `z1`<=? AND `y2`>=? AND `y1`<=? AND `player`=? ORDER BY `time` DESC, `id` DESC"
try (PreparedStatement stmt = connection.prepareStatement(stmtStr)) {
stmt.setInt(1, (int) (minTime / 1000));
stmt.setInt(2, pos1.getBlockX());
@ -200,10 +192,7 @@ public class RollbackDatabase extends AsyncNotifyQueue {
do {
count++;
Supplier<RollbackOptimizedHistory> history = create(result);
// if (history.getBDFile().exists())
{
yieldIterable.accept(history);
}
yieldIterable.accept(history);
} while (result.next());
}
if (delete && uuid != null) {

View File

@ -1,20 +0,0 @@
package com.boydti.fawe.object.brush;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.command.tool.brush.Brush;
public abstract class AbstractBrush implements Brush {
private BrushTool tool;
public AbstractBrush(BrushTool tool) {
this.tool = tool;
}
public void setTool(BrushTool tool) {
this.tool = tool;
}
public BrushTool getTool() {
return tool;
}
}

View File

@ -46,23 +46,17 @@ public class StencilBrush extends HeightBrush {
} else {
add = 0;
}
double scale = (yscale / sizeDouble) * (maxY + 1);
final HeightMap map = getHeightMap();
map.setSize(size);
int cutoff = onlyWhite ? maxY : 0;
final SolidBlockMask solid = new SolidBlockMask(editSession);
final AdjacentAnyMask adjacent = new AdjacentAnyMask(Masks.negate(solid));
// BlockVector3 pos = player.getLocation();
Location loc = editSession.getPlayer().getLocation();
float yaw = loc.getYaw();
float pitch = loc.getPitch();
AffineTransform transform = new AffineTransform().rotateY((-yaw) % 360).rotateX(pitch - 90).inverse();
double scale = (yscale / sizeDouble) * (maxY + 1);
RecursiveVisitor visitor = new RecursiveVisitor(new AbstractExtentMask(editSession) {
private final MutableVector3 mutable = new MutableVector3();
@Override
@ -96,8 +90,4 @@ public class StencilBrush extends HeightBrush {
visitor.visit(position);
Operations.completeBlindly(visitor);
}
private void apply(double val) {
}
}

View File

@ -37,12 +37,10 @@ public class SurfaceSpline implements Brush {
if (path.isEmpty() || !pos.equals(path.get(path.size() - 1))) {
int max = editSession.getNearestSurfaceTerrainBlock(pos.getBlockX(), pos.getBlockZ(), pos.getBlockY(), 0, editSession.getMaxY());
if (max == -1) return;
// pos.mutY(max);
path.add(BlockVector3.at(pos.getBlockX(), max, pos.getBlockZ()));
editSession.getPlayer().print(TranslatableComponent.of("fawe.worldedit.brush.spline.primary.2"));
editSession.getPlayer().printInfo(TranslatableComponent.of("fawe.worldedit.brush.spline.primary.2"));
if (!vis) return;
}
LocalBlockVectorSet vset = new LocalBlockVectorSet();
final List<Node> nodes = new ArrayList<>(path.size());
final KochanekBartelsInterpolation interpol = new KochanekBartelsInterpolation();
@ -56,6 +54,7 @@ public class SurfaceSpline implements Brush {
MutableBlockVector3 mutable = MutableBlockVector3.at(0, 0, 0);
interpol.setNodes(nodes);
final double splinelength = interpol.arcLength(0, 1);
LocalBlockVectorSet vset = new LocalBlockVectorSet();
for (double loop = 0; loop <= 1; loop += 1D / splinelength / quality) {
final Vector3 tipv = interpol.getPosition(loop);
final int tipx = MathMan.roundInt(tipv.getX());
@ -93,6 +92,6 @@ public class SurfaceSpline implements Brush {
editSession.setBlocks(newSet, pattern);
if (!vis) path.clear();
}
editSession.getPlayer().print(TranslatableComponent.of("fawe.worldedit.brush.spline.secondary"));
editSession.getPlayer().printInfo(TranslatableComponent.of("fawe.worldedit.brush.spline.secondary"));
}
}

View File

@ -228,9 +228,6 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor {
public abstract Iterator<Change> getIterator(boolean redo);
public void delete() {
}
public EditSession toEditSession(Player player) {
return toEditSession(player, null);
}

View File

@ -1,539 +0,0 @@
package com.boydti.fawe.util.task;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.beta.IQueueExtent;
import com.boydti.fawe.beta.implementation.queue.QueueHandler;
import com.boydti.fawe.object.Metadatable;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.util.TaskManager;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;
public class TaskBuilder extends Metadatable {
private final ForkJoinPool pool = new ForkJoinPool();
private final ArrayDeque<RunnableTask> tasks;
private Object result = null;
private Thread.UncaughtExceptionHandler handler;
public TaskBuilder() {
this(null);
}
public TaskBuilder(Thread.UncaughtExceptionHandler handler) {
tasks = new ArrayDeque<>();
this.handler = handler;
}
public TaskBuilder async(Task task) {
tasks.add(RunnableTask.adapt(task, TaskType.ASYNC));
return this;
}
public TaskBuilder async(ReceiveTask<Object> task) {
tasks.add(RunnableTask.adapt(task, TaskType.ASYNC));
return this;
}
public TaskBuilder async(ReturnTask task) {
tasks.add(RunnableTask.adapt(task, TaskType.ASYNC));
return this;
}
public TaskBuilder async(Runnable task) {
tasks.add(RunnableTask.adapt(task, TaskType.ASYNC));
return this;
}
public TaskBuilder sync(Task task) {
tasks.add(RunnableTask.adapt(task, TaskType.SYNC));
return this;
}
public TaskBuilder sync(ReceiveTask<Object> task) {
tasks.add(RunnableTask.adapt(task, TaskType.SYNC));
return this;
}
public TaskBuilder sync(ReturnTask task) {
tasks.add(RunnableTask.adapt(task, TaskType.SYNC));
return this;
}
public TaskBuilder sync(Runnable task) {
tasks.add(RunnableTask.adapt(task, TaskType.SYNC));
return this;
}
public TaskBuilder delay(int ticks) {
tasks.add(RunnableDelayedTask.adapt(ticks));
return this;
}
public TaskBuilder delay(DelayedTask task) {
tasks.add(RunnableDelayedTask.adapt(task));
return this;
}
/**
* Run some sync tasks in parallel<br>
* - All sync parallel tasks, which occur directly after each other will be run at the same time
*
* @param run
* @return this
*/
public TaskBuilder syncParallel(Runnable run) {
tasks.add(RunnableTask.adapt(run, TaskType.SYNC_PARALLEL));
return this;
}
public TaskBuilder syncParallel(Task run) {
tasks.add(RunnableTask.adapt(run, TaskType.SYNC_PARALLEL));
return this;
}
public TaskBuilder syncParallel(ReceiveTask<Object> run) {
tasks.add(RunnableTask.adapt(run, TaskType.SYNC_PARALLEL));
return this;
}
public TaskBuilder syncParallel(ReturnTask run) {
tasks.add(RunnableTask.adapt(run, TaskType.SYNC_PARALLEL));
return this;
}
/**
* Run some async tasks in parallel<br>
* - All async parallel tasks which occur directly after each other will be run at the same time
*
* @param run
* @return this
*/
public TaskBuilder asyncParallel(Runnable run) {
tasks.add(RunnableTask.adapt(run, TaskType.ASYNC_PARALLEL));
return this;
}
public TaskBuilder asyncParallel(Task run) {
tasks.add(RunnableTask.adapt(run, TaskType.ASYNC_PARALLEL));
return this;
}
public TaskBuilder asyncParallel(ReceiveTask<Object> run) {
tasks.add(RunnableTask.adapt(run, TaskType.ASYNC_PARALLEL));
return this;
}
public TaskBuilder asyncParallel(ReturnTask run) {
tasks.add(RunnableTask.adapt(run, TaskType.ASYNC_PARALLEL));
return this;
}
/**
* Run a split task when the server has free time<br>
* - i.e. To maintain high tps
* - Use the split() method within task execution
* - FAWE will be able to pause execution at these points
*
* @param run
* @return this
*/
public TaskBuilder syncWhenFree(SplitTask run) {
tasks.add(run);
return this;
}
public TaskBuilder syncWhenFree(Task run) {
tasks.add(RunnableTask.adapt(run, TaskType.SYNC_WHEN_FREE));
return this;
}
public TaskBuilder syncWhenFree(ReceiveTask<Object> run) {
tasks.add(RunnableTask.adapt(run, TaskType.SYNC_WHEN_FREE));
return this;
}
public TaskBuilder syncWhenFree(ReturnTask run) {
tasks.add(RunnableTask.adapt(run, TaskType.SYNC_WHEN_FREE));
return this;
}
public TaskBuilder abortIfTrue(Task<Boolean, Object> run) {
tasks.add(RunnableTask.adapt(run, TaskType.ABORT));
return this;
}
public TaskBuilder abortIfTrue(final Runnable run) {
tasks.add(RunnableTask.adapt((Task<Boolean, Boolean>) previous -> {
if (previous == Boolean.TRUE) run.run();
return previous == Boolean.TRUE;
}, TaskType.ABORT));
return this;
}
public TaskBuilder abortIfNull(final Runnable run) {
tasks.add(RunnableTask.adapt((Task<Boolean, Object>) previous -> {
if (previous == null) run.run();
return previous == null;
}, TaskType.ABORT));
return this;
}
public TaskBuilder abortIfEqual(final Runnable run, final Object other) {
tasks.add(RunnableTask.adapt((Task<Boolean, Object>) previous -> {
if (Objects.equals(previous, other)) run.run();
return Objects.equals(previous, other);
}, TaskType.ABORT));
return this;
}
public TaskBuilder abortIfNotEqual(final Runnable run, final Object other) {
tasks.add(RunnableTask.adapt((Task<Boolean, Object>) previous -> {
if (!Objects.equals(previous, other)) run.run();
return !Objects.equals(previous, other);
}, TaskType.ABORT));
return this;
}
/**
* Have all async tasks run on a new thread<br>
* - As opposed to trying to use the current thread
*/
public void buildAsync() {
TaskManager.IMP.async(this::build);
}
/**
* Begins execution of the tasks<br>
* - The builder will attempt to run on the current thread if possible
*/
public void build() {
RunnableTask peek;
while ((peek = tasks.peek()) != null) {
try {
switch (peek.type) {
case DELAY:
DelayedTask task = (DelayedTask) tasks.poll();
RunnableTask next = tasks.peek();
if (next != null) {
switch (next.type) {
case SYNC:
case ABORT:
case SYNC_PARALLEL:
TaskManager.IMP.later(this::build, task.getDelay(result));
return;
default:
TaskManager.IMP.laterAsync(this::build, task.getDelay(result));
return;
}
}
return;
case SYNC:
case SYNC_PARALLEL:
if (!Fawe.isMainThread()) {
TaskManager.IMP.sync(new RunnableVal() {
@Override
public void run(Object value) {
build();
}
});
return;
}
break;
case SYNC_WHEN_FREE:
case ASYNC:
case ASYNC_PARALLEL:
if (Fawe.isMainThread()) {
TaskManager.IMP.async(this::build);
return;
}
break;
}
RunnableTask task = tasks.poll();
task.value = result;
switch (task.type) {
case ABORT:
if (((Task<Boolean, Object>) task).run(result)) {
return;
}
break;
case SYNC:
result = task.exec(result);
break;
case SYNC_WHEN_FREE:
if (task instanceof SplitTask) {
SplitTask splitTask = (SplitTask) task;
result = splitTask.execSplit(result);
} else {
result = TaskManager.IMP.syncWhenFree(task);
}
break;
case ASYNC:
result = task.exec(result);
continue;
case SYNC_PARALLEL:
case ASYNC_PARALLEL:
final ArrayList<RunnableTask> parallel = new ArrayList<>();
parallel.add(task);
RunnableTask next = tasks.peek();
while (next != null && next.type == task.type) {
parallel.add(next);
tasks.poll();
next = tasks.peek();
}
for (RunnableTask current : parallel) {
pool.submit(current);
}
pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
result = null;
for (RunnableTask current : parallel) {
if (current.value != null) {
result = current.value;
}
}
break;
}
if (task.isAborted()) {
return;
}
} catch (TaskAbortException abort) {
return;
} catch (Throwable e1) {
if (handler != null) {
try {
handler.uncaughtException(Thread.currentThread(), e1);
} catch (Throwable e2) {
e1.printStackTrace();
e2.printStackTrace();
}
}
return;
}
}
}
public static final class TaskAbortException extends RuntimeException {
@Override
public Throwable fillInStackTrace() {
return this;
}
}
private IQueueExtent queue;
private long last;
private long start;
private Object asyncWaitLock = new Object();
private Object syncWaitLock = new Object();
private boolean finished;
private static abstract class RunnableTask<T> extends RunnableVal<T> {
public final TaskType type;
private boolean aborted;
public RunnableTask(TaskType type) {
this.type = type;
}
public void abortNextTasks() {
this.aborted = true;
}
public boolean isAborted() {
return aborted;
}
public static RunnableTask adapt(final Task task, TaskType type) {
return new RunnableTask(type) {
@Override
public Object exec(Object previous) {
return task.run(previous);
}
};
}
public static RunnableTask adapt(final ReturnTask task, TaskType type) {
return new RunnableTask(type) {
@Override
public Object exec(Object previous) {
return task.run();
}
};
}
public static RunnableTask adapt(final ReceiveTask<Object> task, TaskType type) {
return new RunnableTask(type) {
@Override
public Object exec(Object previous) {
task.run(previous);
return null;
}
};
}
public static RunnableTask adapt(final Runnable run, TaskType type) {
return new RunnableTask(type) {
@Override
public Object exec(Object previous) {
if (run instanceof RunnableVal) {
((RunnableVal) run).value = this.value;
return this.value = ((RunnableVal) run).runAndGet();
}
run.run();
return null;
}
};
}
public abstract T exec(Object previous);
@Override
public final void run(T value) {
this.value = exec(value);
}
}
private static abstract class RunnableDelayedTask extends RunnableTask {
public RunnableDelayedTask(TaskType type) {
super(type);
}
@Override
public Object exec(Object previous) {
return previous;
}
public abstract int delay(Object previous);
public static RunnableDelayedTask adapt(final DelayedTask task) {
return new RunnableDelayedTask(TaskType.DELAY) {
@Override
public int delay(Object previous) {
return task.getDelay(previous);
}
};
}
public static RunnableDelayedTask adapt(final int time) {
return new RunnableDelayedTask(TaskType.DELAY) {
@Override
public int delay(Object previous) {
return time;
}
};
}
}
public static abstract class SplitTask<T> extends RunnableTask<T> {
private final long allocation;
private final QueueHandler queue;
private long last;
private long start;
private Object asyncWaitLock = new Object();
private Object syncWaitLock = new Object();
private boolean finished;
private boolean waitingAsync = true;
private boolean waitingSync = false;
public SplitTask() {
this(20);
}
public SplitTask(long allocation) {
super(TaskType.SYNC_WHEN_FREE);
this.allocation = allocation;
this.queue = Fawe.get().getQueueHandler();
}
public Object execSplit(final T previous) {
this.value = previous;
final Thread thread = new Thread(() -> {
try {
synchronized (asyncWaitLock) {
asyncWaitLock.notifyAll();
asyncWaitLock.wait(Long.MAX_VALUE);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
exec(previous);
finished = true;
waitingAsync = true;
waitingSync = false;
synchronized (syncWaitLock) {
syncWaitLock.notifyAll();
}
});
try {
synchronized (asyncWaitLock) {
thread.start();
asyncWaitLock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
while (thread.isAlive()) {
TaskManager.IMP.syncWhenFree(new RunnableVal<T>() {
@Override
public void run(Object ignore) {
queue.startSet(true);
start = System.currentTimeMillis();
try {
if (!finished) {
synchronized (asyncWaitLock) {
while (!waitingAsync) asyncWaitLock.wait(1);
asyncWaitLock.notifyAll();
}
waitingSync = true;
synchronized (syncWaitLock) {
syncWaitLock.notifyAll();
syncWaitLock.wait();
}
waitingSync = false;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
queue.endSet(true);
}
});
}
return this.value;
}
public void split() {
long now = System.currentTimeMillis();
if (now - start > allocation) {
try {
synchronized (syncWaitLock) {
while (!waitingSync) syncWaitLock.wait(1);
syncWaitLock.notifyAll();
}
waitingAsync = true;
synchronized (asyncWaitLock) {
asyncWaitLock.notifyAll();
asyncWaitLock.wait();
}
waitingAsync = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private enum TaskType {
SYNC,
ASYNC,
SYNC_PARALLEL,
ASYNC_PARALLEL,
SYNC_WHEN_FREE,
DELAY,
ABORT
}
}

View File

@ -42,6 +42,8 @@ import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.extent.EditSessionEvent;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.Watchdog;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.ChangeSetExtent;
import com.sk89q.worldedit.extent.Extent;
@ -195,8 +197,6 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
@SuppressWarnings("ProtectedField")
protected final World world;
private final String worldName;
private boolean wrapped;
private final FaweLimit originalLimit;
private final FaweLimit limit;
private final Player player;
@ -212,6 +212,8 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
private Extent bypassAll;
private final int maxY;
private final List<WatchdogTickingExtent> watchdogExtents = new ArrayList<>(2);
@Deprecated
public EditSession(EventBus bus, World world, @Nullable Player player,
@ -247,8 +249,6 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
public EditSession(EditSessionBuilder builder) {
super(builder.compile().getExtent());
this.world = builder.getWorld();
this.worldName = world.getName();
this.wrapped = builder.isWrapped();
this.bypassHistory = builder.getBypassHistory();
this.bypassAll = builder.getBypassAll();
this.originalLimit = builder.getLimit();
@ -317,11 +317,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
public Extent getBypassAll() {
return bypassAll;
}
public Extent getBypassHistory() {
return bypassHistory;
}
private final List<WatchdogTickingExtent> watchdogExtents = new ArrayList<>(2);
public void setExtent(AbstractDelegateExtent extent) {
new ExtentTraverser(this).setNext(extent);
@ -483,7 +481,6 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
public void addTransform(ResettableExtent transform) {
checkNotNull(transform);
wrapped = true;
transform.setExtent(getExtent());
new ExtentTraverser(this).setNext(transform);
}

View File

@ -449,70 +449,7 @@ public class SchematicCommands {
actor.printInfo(TextComponent.of(builder.toString()));
}
}
/*
@Command(
name = "show",
desc = "Show a schematic",
descFooter = "List all schematics in the schematics directory\n" +
" -f <format> restricts by format\n"
)
@CommandPermissions("worldedit.schematic.show")
public void show(Player player, InjectedValueAccess args, @Switch(name='f', desc = "") String formatName) {
FawePlayer fp = FawePlayer.wrap(player);
if (args.argsLength() == 0) {
if (fp.getSession().getVirtualWorld() != null) fp.setVirtualWorld(null);
else {
player.print(TranslatableComponent.of("fawe.error.command.syntax" , "/" + Commands.getAlias(SchematicCommands.class, "schematic") + " " + getCommand().aliases()[0] + " " + getCommand().usage()));
}
return;
}
LocalConfiguration config = worldEdit.getConfiguration();
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
try {
SchemVis visExtent = new SchemVis(fp);
LongAdder count = new LongAdder();
UtilityCommands.getFiles(dir, player, args, 0, Character.MAX_VALUE, formatName, Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS, file -> {
if (file.isFile()) {
try {
visExtent.add(file);
count.add(1);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
long total = count.longValue();
if (total == 0) {
if (args.getJoinedStrings(0).toLowerCase().startsWith("all")) {
player.print(TranslatableComponent.of("fawe.worldedit.schematic.schematic.none"))
} else {
String joined = args.getJoinedStrings(0);
String cmd = "/" + Commands.getAlias(SchematicCommands.class, "schematic") + " " + getCommand().aliases()[0] + " all " + joined;
player.print(TranslatableComponent.of("fawe.worldedit.help.help.suggest" , joined, cmd));
}
return;
}
visExtent.bind();
visExtent.update();
String cmdPrefix = "/" + (config.noDoubleSlash ? "" : "/");
String cmdShow = Commands.getAlias(ClipboardCommands.class, "schematic") + " " + Commands.getAlias(ClipboardCommands.class, "show");
fp.print(TranslatableComponent.of("fawe.worldedit.schematic.schematic.show" , count.longValue(), args.getJoinedStrings(0), cmdShow));
if (fp.getSession().getExistingClipboard() != null) {
String cmd = cmdPrefix + Commands.getAlias(ClipboardCommands.class, "clearclipboard");
fp.print(TranslatableComponent.of("fawe.worldedit.schematic.schematic.prompt.clear" , cmd));
}
} catch (Throwable e) {
fp.setVirtualWorld(null);
throw e;
}
}
*/
@Command(
name = "list",
aliases = {"all", "ls"},