Fix command confirmation session

This commit is contained in:
Jesse Boyd 2018-09-08 09:10:36 +10:00
parent ffa9eace6f
commit 277ff8f787
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
7 changed files with 106 additions and 56 deletions

View File

@ -9,11 +9,13 @@ import com.boydti.fawe.object.brush.visualization.VirtualWorld;
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.task.SimpleAsyncNotifyQueue;
import com.boydti.fawe.object.task.ThrowableSupplier;
import com.boydti.fawe.regions.FaweMaskManager;
import com.boydti.fawe.util.*;
import com.boydti.fawe.wrappers.FakePlayer;
import com.boydti.fawe.wrappers.LocationMaskedPlayerWrapper;
import com.boydti.fawe.wrappers.PlayerWrapper;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.command.tool.BrushTool;
@ -159,14 +161,30 @@ public abstract class FawePlayer<T> extends Metadatable {
return cancelled;
}
private void setConfirmTask(@Nullable Runnable task, String command) {
setMeta("cmdConfirm", task == null ? new CommandEvent(getPlayer(), command) : task);
private void setConfirmTask(@Nullable Runnable task, CommandContext context, String command) {
if (task != null) {
Runnable newTask = new Runnable() {
@Override
public void run() {
CommandManager.getInstance().handleCommandTask(new ThrowableSupplier<Throwable>() {
@Override
public Object get() throws Throwable {
task.run();
return null;
}
}, context.getLocals());
}
};
setMeta("cmdConfirm", newTask);
} else {
setMeta("cmdConfirm", new CommandEvent(getPlayer(), command));
}
}
public void checkConfirmation(@Nullable Runnable task, String command, int times, int limit) throws RegionOperationException {
public void checkConfirmation(@Nullable Runnable task, String command, int times, int limit, CommandContext context) throws RegionOperationException {
if (command != null && !getMeta("cmdConfirmRunning", false)) {
if (times > limit) {
setConfirmTask(task, command);
setConfirmTask(task, context, command);
String volume = "<unspecified>";
throw new RegionOperationException(BBC.WORLDEDIT_CANCEL_REASON_CONFIRM.f(0, times, command, volume));
}
@ -174,11 +192,11 @@ public abstract class FawePlayer<T> extends Metadatable {
if (task != null) task.run();
}
public void checkConfirmationRadius(@Nullable Runnable task, String command, int radius) throws RegionOperationException {
public void checkConfirmationRadius(@Nullable Runnable task, String command, int radius, CommandContext context) throws RegionOperationException {
if (command != null && !getMeta("cmdConfirmRunning", false)) {
if (radius > 0) {
if (radius > 448) {
setConfirmTask(task, command);
setConfirmTask(task, context, command);
long volume = (long) (Math.PI * ((double) radius * radius));
throw new RegionOperationException(BBC.WORLDEDIT_CANCEL_REASON_CONFIRM.f(0, radius, command, NumberFormat.getNumberInstance().format(volume)));
}
@ -187,14 +205,14 @@ public abstract class FawePlayer<T> extends Metadatable {
if (task != null) task.run();
}
public void checkConfirmationStack(@Nullable Runnable task, String command, Region region, int times) throws RegionOperationException {
public void checkConfirmationStack(@Nullable Runnable task, String command, Region region, int times, CommandContext context) throws RegionOperationException {
if (command != null && !getMeta("cmdConfirmRunning", false)) {
if (region != null) {
Vector min = region.getMinimumPoint().toBlockVector();
Vector max = region.getMaximumPoint().toBlockVector();
long area = (long) ((max.getX() - min.getX()) * (max.getZ() - min.getZ() + 1)) * times;
if (area > 2 << 18) {
setConfirmTask(task, command);
setConfirmTask(task, context, command);
long volume = (long) max.subtract(min).add(Vector.ONE).volume() * times;
throw new RegionOperationException(BBC.WORLDEDIT_CANCEL_REASON_CONFIRM.f(min, max, command, NumberFormat.getNumberInstance().format(volume)));
}
@ -203,14 +221,14 @@ public abstract class FawePlayer<T> extends Metadatable {
if (task != null) task.run();
}
public void checkConfirmationRegion(@Nullable Runnable task, String command, Region region) throws RegionOperationException {
public void checkConfirmationRegion(@Nullable Runnable task, String command, Region region, CommandContext context) throws RegionOperationException {
if (command != null && !getMeta("cmdConfirmRunning", false)) {
if (region != null) {
Vector min = region.getMinimumPoint().toBlockVector();
Vector max = region.getMaximumPoint().toBlockVector();
long area = (long) ((max.getX() - min.getX()) * (max.getZ() - min.getZ() + 1));
if (area > 2 << 18) {
setConfirmTask(task, command);
setConfirmTask(task, context, command);
long volume = (long) max.subtract(min).add(Vector.ONE).volume();
throw new RegionOperationException(BBC.WORLDEDIT_CANCEL_REASON_CONFIRM.f(min, max, command, NumberFormat.getNumberInstance().format(volume)));
}

View File

@ -0,0 +1,5 @@
package com.boydti.fawe.object.task;
public interface ThrowableSupplier<T extends Throwable> {
Object get() throws T;
}

View File

@ -182,7 +182,7 @@ public class ClipboardCommands extends MethodCommands {
if (!FawePlayer.wrap(player).hasPermission("fawe.tips")) {
BBC.TIP_PASTE.or(BBC.TIP_DOWNLOAD, BBC.TIP_ROTATE, BBC.TIP_COPYPASTE, BBC.TIP_REPLACE_MARKER, BBC.TIP_COPY_PATTERN).send(player);
}
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -275,7 +275,7 @@ public class ClipboardCommands extends MethodCommands {
BBC.COMMAND_CUT_SLOW.send(player, region.getArea());
if (!FawePlayer.wrap(player).hasPermission("fawe.tips")) BBC.TIP_LAZYCUT.send(player);
}, getArguments(context), region);
}, getArguments(context), region, context);
}

View File

@ -92,7 +92,7 @@ public class GenerationCommands extends MethodCommands {
CavesGen gen = new CavesGen(size, frequency, rarity, minY, maxY, systemFrequency, individualRarity, pocketChance, pocketMin, pocketMax);
editSession.generate(region, gen);
BBC.VISITOR_BLOCK.send(fp, editSession.getBlockChangeCount());
}, getArguments(context), region);
}, getArguments(context), region, context);
}
// public void addOre(Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws WorldEditException {
@ -110,7 +110,7 @@ public class GenerationCommands extends MethodCommands {
player.checkConfirmationRegion(() -> {
editSession.addOres(region, mask);
BBC.VISITOR_BLOCK.send(player, editSession.getBlockChangeCount());
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -174,7 +174,7 @@ public class GenerationCommands extends MethodCommands {
player.checkConfirmationRegion(() -> {
editSession.addOre(region, mask, material, size, freq, rarity, minY, maxY);
BBC.VISITOR_BLOCK.send(player, editSession.getBlockChangeCount());
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -198,7 +198,7 @@ public class GenerationCommands extends MethodCommands {
fp.checkConfirmationRadius(() -> {
int affected = editSession.makeHollowCylinder(pos, pattern, radius.getX(), radius.getZ(), Math.min(256, height), thickness - 1);
BBC.VISITOR_BLOCK.send(fp, affected);
}, getArguments(context), (int) max);
}, getArguments(context), (int) max, context);
}
@Command(
@ -223,7 +223,7 @@ public class GenerationCommands extends MethodCommands {
fp.checkConfirmationRadius(() -> {
int affected = editSession.makeCylinder(pos, pattern, radius.getX(), radius.getZ(), Math.min(256, height), !hollow);
BBC.VISITOR_BLOCK.send(fp, affected);
}, getArguments(context), (int) max);
}, getArguments(context), (int) max, context);
}
@Command(
@ -268,7 +268,7 @@ public class GenerationCommands extends MethodCommands {
int affected = editSession.makeSphere(finalPos, pattern, radius.getX(), radius.getY(), radius.getZ(), !hollow);
player.findFreePosition();
BBC.VISITOR_BLOCK.send(fp, affected);
}, getArguments(context), (int) max);
}, getArguments(context), (int) max, context);
}
@Command(
@ -331,7 +331,7 @@ public class GenerationCommands extends MethodCommands {
int affected = editSession.makePyramid(pos, pattern, size, !hollow);
player.findFreePosition();
BBC.VISITOR_BLOCK.send(fp, affected);
}, getArguments(context), size);
}, getArguments(context), size, context);
}
@Command(
@ -399,7 +399,7 @@ public class GenerationCommands extends MethodCommands {
} catch (ExpressionException e) {
fp.sendMessage(BBC.getPrefix() + e.getMessage());
}
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -466,6 +466,6 @@ public class GenerationCommands extends MethodCommands {
} catch (ExpressionException e) {
fp.sendMessage(BBC.getPrefix() + e.getMessage());
}
}, getArguments(context), region);
}, getArguments(context), region, context);
}
}

View File

@ -247,7 +247,7 @@ public class HistoryCommands extends MethodCommands {
break;
}
}
}, getArguments(context), times, 50);
}, getArguments(context), times, 50, context);
}
@Command(

View File

@ -288,7 +288,7 @@ public class RegionCommands extends MethodCommands {
int blocksChanged = editSession.drawSpline(pattern, vectors, 0, 0, 0, 10, thickness, !shell);
BBC.VISITOR_BLOCK.send(player, blocksChanged);
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -307,7 +307,7 @@ public class RegionCommands extends MethodCommands {
BBC.VISITOR_BLOCK.send(player, affected);
if (!player.hasPermission("fawe.tips"))
BBC.TIP_REPLACE_ID.or(BBC.TIP_REPLACE_LIGHT, BBC.TIP_REPLACE_MARKER, BBC.TIP_TAB_COMPLETE, BBC.TIP_REPLACE_REGEX, BBC.TIP_REPLACE_REGEX_2, BBC.TIP_REPLACE_REGEX_3, BBC.TIP_REPLACE_REGEX_4, BBC.TIP_REPLACE_REGEX_5).send(player);
}, getArguments(context), region);
}, getArguments(context), region, context);
}
// Compatibility for SKCompat
@ -334,7 +334,7 @@ public class RegionCommands extends MethodCommands {
if (!player.hasPermission("fawe.tips"))
BBC.TIP_FAST.or(BBC.TIP_CANCEL, BBC.TIP_MASK, BBC.TIP_MASK_ANGLE, BBC.TIP_SET_LINEAR, BBC.TIP_SURFACE_SPREAD, BBC.TIP_SET_HAND).send(player);
}
}, getArguments(context), selection);
}, getArguments(context), selection, context);
}
@Command(
@ -350,7 +350,7 @@ public class RegionCommands extends MethodCommands {
player.checkConfirmationRegion(() -> {
int affected = editSession.overlayCuboidBlocks(region, pattern);
BBC.VISITOR_BLOCK.send(player, affected);
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -385,7 +385,7 @@ public class RegionCommands extends MethodCommands {
affected++;
}
BBC.VISITOR_BLOCK.send(player, affected);
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -415,7 +415,7 @@ public class RegionCommands extends MethodCommands {
player.checkConfirmationRegion(() -> {
int affected = editSession.naturalizeCuboidBlocks(region);
BBC.VISITOR_BLOCK.send(player, affected);
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -431,7 +431,7 @@ public class RegionCommands extends MethodCommands {
player.checkConfirmationRegion(() -> {
int affected = editSession.makeWalls(region, pattern);
BBC.VISITOR_BLOCK.send(player, affected);
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -447,7 +447,7 @@ public class RegionCommands extends MethodCommands {
player.checkConfirmationRegion(() -> {
int affected = editSession.makeCuboidFaces(region, pattern);
BBC.VISITOR_BLOCK.send(player, affected);
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -481,7 +481,7 @@ public class RegionCommands extends MethodCommands {
} catch (Throwable e) {
throw new RuntimeException(e);
}
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -559,7 +559,7 @@ public class RegionCommands extends MethodCommands {
}
BBC.VISITOR_BLOCK.send(player, affected);
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -583,7 +583,7 @@ public class RegionCommands extends MethodCommands {
player.checkConfirmationRegion(() -> {
int affected = editSession.fall(region, !notFullHeight, replace);
BBC.VISITOR_BLOCK.send(player, affected);
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -629,7 +629,7 @@ public class RegionCommands extends MethodCommands {
}
BBC.VISITOR_BLOCK.send(player, affected);
}, getArguments(context), region, count);
}, getArguments(context), region, count, context);
}
@Command(
@ -681,7 +681,7 @@ public class RegionCommands extends MethodCommands {
} catch (ExpressionException e) {
fp.sendMessage(BBC.getPrefix() + e.getMessage());
}
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -697,19 +697,19 @@ public class RegionCommands extends MethodCommands {
)
@CommandPermissions("worldedit.regen")
@Logging(REGION)
public void regenerateChunk(FawePlayer player, LocalSession session, EditSession editSession, @Selection Region region, CommandContext args) throws WorldEditException {
public void regenerateChunk(FawePlayer player, LocalSession session, EditSession editSession, @Selection Region region, CommandContext context) throws WorldEditException {
player.checkConfirmationRegion(() -> {
Mask mask = session.getMask();
Mask sourceMask = session.getSourceMask();
session.setMask((Mask) null);
session.setSourceMask((Mask) null);
BaseBiome biome = null;
if (args.argsLength() >= 1) {
if (context.argsLength() >= 1) {
BiomeRegistry biomeRegistry = worldEdit.getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry();
List<BaseBiome> knownBiomes = biomeRegistry.getBiomes();
biome = Biomes.findBiomeByName(knownBiomes, args.getString(0), biomeRegistry);
biome = Biomes.findBiomeByName(knownBiomes, context.getString(0), biomeRegistry);
}
Long seed = args.argsLength() != 2 || !MathMan.isInteger(args.getString(1)) ? null : Long.parseLong(args.getString(1));
Long seed = context.argsLength() != 2 || !MathMan.isInteger(context.getString(1)) ? null : Long.parseLong(context.getString(1));
editSession.regenerate(region, biome, seed);
session.setMask(mask);
session.setSourceMask(mask);
@ -724,7 +724,7 @@ public class RegionCommands extends MethodCommands {
} else {
BBC.COMMAND_REGEN_2.send(player);
}
}, getArguments(args), region);
}, getArguments(context), region, context);
}
@ -750,7 +750,7 @@ public class RegionCommands extends MethodCommands {
player.checkConfirmationRegion(() -> {
int affected = editSession.hollowOutRegion(region, thickness, pattern);
BBC.VISITOR_BLOCK.send(player, affected);
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@Command(
@ -773,7 +773,7 @@ public class RegionCommands extends MethodCommands {
Operations.completeLegacy(visitor);
BBC.COMMAND_TREE.send(player, ground.getAffected());
}, getArguments(context), region);
}, getArguments(context), region, context);
}
@ -795,7 +795,7 @@ public class RegionCommands extends MethodCommands {
Operations.completeLegacy(visitor);
BBC.COMMAND_FLORA.send(player, ground.getAffected());
}, getArguments(context), region);
}, getArguments(context), region, context);
}

View File

@ -27,6 +27,7 @@ import com.boydti.fawe.command.PatternBinding;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.object.task.ThrowableSupplier;
import com.boydti.fawe.util.StringMan;
import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.util.chat.UsageMessage;
@ -60,6 +61,7 @@ import com.sk89q.worldedit.util.eventbus.Subscribe;
import com.sk89q.worldedit.util.logging.DynamicStreamHandler;
import com.sk89q.worldedit.util.logging.LogFormat;
import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
@ -67,6 +69,7 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -375,6 +378,8 @@ public final class CommandManager {
throw new IllegalArgumentException("FAWE doesn't support: " + actor);
}
final Set<String> failedPermissions = new LinkedHashSet<>();
locals.put("failed_permissions", failedPermissions);
locals.put(LocalSession.class, session);
if (actor instanceof Player) {
Player player = (Player) actor;
Player unwrapped = LocationMaskedPlayerWrapper.unwrap(player);
@ -399,10 +404,28 @@ public final class CommandManager {
}
};
}
Request.reset();
locals.put(Actor.class, actor);
final Actor finalActor = actor;
locals.put("arguments", args);
ThrowableSupplier<Throwable> task = new ThrowableSupplier<Throwable>() {
@Override
public Object get() throws Throwable {
return dispatcher.call(Joiner.on(" ").join(split), locals, new String[0]);
}
};
handleCommandTask(task, locals, actor, session, failedPermissions, fp);
}
public Object handleCommandTask(ThrowableSupplier<Throwable> task, CommandLocals locals) {
return handleCommandTask(task, locals, null, null, null, null);
}
private Object handleCommandTask(ThrowableSupplier<Throwable> task, CommandLocals locals, @Nullable Actor actor, @Nullable LocalSession session, @Nullable Set<String> failedPermissions, @Nullable FawePlayer fp) {
Request.reset();
if (actor == null) actor = locals.get(Actor.class);
if (session == null) session = locals.get(LocalSession.class);
long start = System.currentTimeMillis();
try {
// This is a bit of a hack, since the call method can only throw CommandExceptions
@ -410,8 +433,8 @@ public final class CommandManager {
// exceptions without writing a hook into every dispatcher, we need to unwrap these
// exceptions and rethrow their converted form, if their is one.
try {
Request.request().setActor(finalActor);
Object result = dispatcher.call(Joiner.on(" ").join(split), locals, new String[0]);
Request.request().setActor(actor);
return task.get();
} catch (Throwable t) {
// Use the exception converter to convert the exception if any of its causes
// can be converted, otherwise throw the original exception
@ -424,28 +447,31 @@ public final class CommandManager {
throw next;
}
} catch (CommandPermissionsException e) {
BBC.NO_PERM.send(finalActor, StringMan.join(failedPermissions, " "));
if (failedPermissions == null) failedPermissions = (Set<String>) locals.get("failed_permissions");
if (failedPermissions != null) BBC.NO_PERM.send(actor, StringMan.join(failedPermissions, " "));
} catch (InvalidUsageException e) {
if (e.isFullHelpSuggested()) {
CommandCallable cmd = e.getCommand();
if (cmd instanceof Dispatcher) {
try {
CommandContext context = new CommandContext(("ignoreThis " + Joiner.on(" ").join(split)).split(" "), new HashSet<>(), false, locals);
String args = locals.get("arguments") + "";
CommandContext context = new CommandContext(("ignoreThis " + args).split(" "), new HashSet<>(), false, locals);
UtilityCommands.help(context, worldEdit, actor);
} catch (CommandException e1) {
e1.printStackTrace();
}
} else {
if (fp == null) fp = FawePlayer.wrap(actor);
new UsageMessage(cmd, e.getCommandUsed((WorldEdit.getInstance().getConfiguration().noDoubleSlash ? "" : "/"), ""), locals).send(fp);
}
String message = e.getMessage();
if (message != null) {
finalActor.printError(message);
actor.printError(message);
}
} else {
String message = e.getMessage();
finalActor.printRaw(BBC.getPrefix() + (message != null ? message : "The command was not used properly (no more help available)."));
BBC.COMMAND_SYNTAX.send(finalActor, e.getSimpleUsageString("/"));
actor.printRaw(BBC.getPrefix() + (message != null ? message : "The command was not used properly (no more help available)."));
BBC.COMMAND_SYNTAX.send(actor, e.getSimpleUsageString("/"));
}
} catch (CommandException e) {
String message = e.getMessage();
@ -459,25 +485,26 @@ public final class CommandManager {
Exception faweException = FaweException.get(e);
String message = e.getMessage();
if (faweException != null) {
BBC.WORLDEDIT_CANCEL_REASON.send(finalActor, faweException.getMessage());
BBC.WORLDEDIT_CANCEL_REASON.send(actor, faweException.getMessage());
} else {
finalActor.printError("There was an error handling a FAWE command: [See console]");
finalActor.printRaw(e.getClass().getName() + ": " + e.getMessage());
actor.printError("There was an error handling a FAWE command: [See console]");
actor.printRaw(e.getClass().getName() + ": " + e.getMessage());
log.log(Level.SEVERE, "An unexpected error occurred while handling a FAWE command", e);
}
} finally {
final EditSession editSession = locals.get(EditSession.class);
if (editSession != null) {
editSession.flushQueue();
worldEdit.flushBlockBag(finalActor, editSession);
worldEdit.flushBlockBag(locals.get(Actor.class), editSession);
session.remember(editSession);
final long time = System.currentTimeMillis() - start;
if (time > 1000) {
BBC.ACTION_COMPLETE.send(finalActor, (time / 1000d));
BBC.ACTION_COMPLETE.send(actor, (time / 1000d));
}
Request.reset();
}
}
return null;
}
@Subscribe