2014-04-03 02:08:50 +00:00
|
|
|
/*
|
2014-04-04 22:03:18 +00:00
|
|
|
* WorldEdit, a Minecraft world manipulation toolkit
|
|
|
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
|
|
|
* Copyright (C) WorldEdit team and contributors
|
2014-04-03 02:08:50 +00:00
|
|
|
*
|
2014-04-04 22:03:18 +00:00
|
|
|
* 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
|
2014-04-03 02:08:50 +00:00
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
2014-04-04 22:03:18 +00:00
|
|
|
* 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.
|
2014-04-03 02:08:50 +00:00
|
|
|
*
|
2014-04-04 22:03:18 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
2014-04-03 02:08:50 +00:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2014-04-04 22:03:18 +00:00
|
|
|
*/
|
2014-04-03 02:08:50 +00:00
|
|
|
|
|
|
|
package com.sk89q.worldedit.command;
|
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.boydti.fawe.Fawe;
|
|
|
|
import com.boydti.fawe.FaweAPI;
|
|
|
|
import com.boydti.fawe.command.FaweParser;
|
|
|
|
import com.boydti.fawe.config.BBC;
|
|
|
|
import com.boydti.fawe.config.Commands;
|
|
|
|
import com.boydti.fawe.config.Settings;
|
|
|
|
import com.boydti.fawe.object.DelegateConsumer;
|
|
|
|
import com.boydti.fawe.object.FaweLimit;
|
|
|
|
import com.boydti.fawe.object.FawePlayer;
|
2018-09-06 20:40:13 +00:00
|
|
|
import com.boydti.fawe.object.RunnableVal;
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.boydti.fawe.object.RunnableVal3;
|
|
|
|
import com.boydti.fawe.util.MainUtil;
|
|
|
|
import com.boydti.fawe.util.MathMan;
|
|
|
|
import com.boydti.fawe.util.StringMan;
|
|
|
|
import com.boydti.fawe.util.chat.Message;
|
|
|
|
import com.boydti.fawe.util.chat.UsageMessage;
|
|
|
|
import com.boydti.fawe.util.gui.FormBuilder;
|
2018-09-06 20:40:13 +00:00
|
|
|
import com.boydti.fawe.util.image.ImageUtil;
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.sk89q.minecraft.util.commands.*;
|
|
|
|
import com.sk89q.worldedit.*;
|
2018-08-10 10:29:06 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.sk89q.worldedit.world.block.BlockState;
|
2018-12-23 16:19:33 +00:00
|
|
|
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
|
|
|
|
|
|
|
|
import com.google.common.base.Joiner;
|
|
|
|
import com.sk89q.minecraft.util.commands.Command;
|
|
|
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
|
|
|
import com.sk89q.minecraft.util.commands.CommandException;
|
|
|
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
|
|
|
import com.sk89q.minecraft.util.commands.Logging;
|
|
|
|
import com.sk89q.worldedit.EditSession;
|
|
|
|
import com.sk89q.worldedit.LocalConfiguration;
|
|
|
|
import com.sk89q.worldedit.LocalSession;
|
|
|
|
import com.sk89q.worldedit.WorldEdit;
|
|
|
|
import com.sk89q.worldedit.WorldEditException;
|
2014-07-16 02:47:47 +00:00
|
|
|
import com.sk89q.worldedit.command.util.CreatureButcher;
|
|
|
|
import com.sk89q.worldedit.command.util.EntityRemover;
|
|
|
|
import com.sk89q.worldedit.entity.Entity;
|
2014-06-28 00:55:39 +00:00
|
|
|
import com.sk89q.worldedit.entity.Player;
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.sk89q.worldedit.event.platform.CommandEvent;
|
|
|
|
import com.sk89q.worldedit.extension.factory.DefaultTransformParser;
|
2018-12-23 08:56:26 +00:00
|
|
|
import com.sk89q.worldedit.extension.factory.parser.mask.DefaultMaskParser;
|
|
|
|
import com.sk89q.worldedit.extension.factory.parser.pattern.ClipboardPatternParser;
|
|
|
|
import com.sk89q.worldedit.extension.factory.parser.pattern.DefaultPatternParser;
|
2014-06-28 00:55:39 +00:00
|
|
|
import com.sk89q.worldedit.extension.platform.Actor;
|
2014-07-16 02:47:47 +00:00
|
|
|
import com.sk89q.worldedit.extension.platform.Capability;
|
2014-07-01 06:17:44 +00:00
|
|
|
import com.sk89q.worldedit.extension.platform.CommandManager;
|
2014-07-16 02:47:47 +00:00
|
|
|
import com.sk89q.worldedit.extension.platform.Platform;
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
|
2019-01-31 15:08:58 +00:00
|
|
|
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
|
|
|
import com.sk89q.worldedit.function.mask.Mask;
|
2014-07-16 02:47:47 +00:00
|
|
|
import com.sk89q.worldedit.function.operation.Operations;
|
2018-06-15 05:41:37 +00:00
|
|
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
2014-07-16 02:47:47 +00:00
|
|
|
import com.sk89q.worldedit.function.visitor.EntityVisitor;
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.sk89q.worldedit.internal.annotation.Direction;
|
2014-07-03 10:34:19 +00:00
|
|
|
import com.sk89q.worldedit.internal.expression.Expression;
|
|
|
|
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
|
|
|
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
|
2018-12-23 16:19:33 +00:00
|
|
|
import com.sk89q.worldedit.math.BlockVector3;
|
2014-04-03 02:08:50 +00:00
|
|
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
2014-07-16 02:47:47 +00:00
|
|
|
import com.sk89q.worldedit.regions.CylinderRegion;
|
2014-04-03 02:08:50 +00:00
|
|
|
import com.sk89q.worldedit.regions.Region;
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.sk89q.worldedit.util.command.*;
|
|
|
|
import com.sk89q.worldedit.util.command.binding.Range;
|
2014-07-03 10:34:19 +00:00
|
|
|
import com.sk89q.worldedit.util.command.binding.Text;
|
2018-08-12 14:03:07 +00:00
|
|
|
import com.sk89q.worldedit.util.command.parametric.Optional;
|
|
|
|
import com.sk89q.worldedit.util.command.parametric.ParameterData;
|
2014-04-05 09:59:38 +00:00
|
|
|
import com.sk89q.worldedit.world.World;
|
2018-12-27 00:39:10 +00:00
|
|
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
2018-07-30 13:26:06 +00:00
|
|
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2018-09-06 20:40:13 +00:00
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
import java.awt.*;
|
|
|
|
import java.awt.image.BufferedImage;
|
2018-08-12 14:03:07 +00:00
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileFilter;
|
2018-09-06 20:40:13 +00:00
|
|
|
import java.io.IOException;
|
2018-08-12 14:03:07 +00:00
|
|
|
import java.lang.reflect.Type;
|
|
|
|
import java.net.URI;
|
2018-09-06 20:40:13 +00:00
|
|
|
import java.nio.file.Files;
|
2018-08-12 14:03:07 +00:00
|
|
|
import java.util.*;
|
2018-09-06 20:40:13 +00:00
|
|
|
import java.util.List;
|
2018-08-12 14:03:07 +00:00
|
|
|
import java.util.concurrent.*;
|
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
import java.util.function.Consumer;
|
|
|
|
|
|
|
|
|
|
|
|
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
|
2014-04-03 02:08:50 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Utility commands.
|
|
|
|
*/
|
2018-08-12 14:03:07 +00:00
|
|
|
@Command(aliases = {}, desc = "Various utility commands: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Utilities)")
|
|
|
|
public class UtilityCommands extends MethodCommands {
|
2014-04-03 02:08:50 +00:00
|
|
|
public UtilityCommands(WorldEdit we) {
|
2018-08-12 14:03:07 +00:00
|
|
|
super(we);
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"patterns"},
|
|
|
|
usage = "[page=1|search|pattern]",
|
|
|
|
desc = "View help about patterns",
|
|
|
|
help = "Patterns determine what blocks are placed\n" +
|
|
|
|
" - Use [brackets] for arguments\n" +
|
|
|
|
" - Use , to OR multiple\n" +
|
|
|
|
"e.g. #surfacespread[10][#existing],andesite\n" +
|
2018-08-24 09:33:52 +00:00
|
|
|
"More Info: https://git.io/vSPmA",
|
|
|
|
queued = false
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
2018-08-12 14:03:07 +00:00
|
|
|
public void patterns(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
2018-12-23 08:56:26 +00:00
|
|
|
displayModifierHelp(player, DefaultPatternParser.class, args);
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
@Command(
|
|
|
|
aliases = {"masks"},
|
|
|
|
usage = "[page=1|search|mask]",
|
|
|
|
desc = "View help about masks",
|
|
|
|
help = "Masks determine if a block can be placed\n" +
|
|
|
|
" - Use [brackets] for arguments\n" +
|
|
|
|
" - Use , to OR multiple\n" +
|
|
|
|
" - Use & to AND multiple\n" +
|
|
|
|
"e.g. >[stone,dirt],#light[0][5],$jungle\n" +
|
2018-08-24 09:33:52 +00:00
|
|
|
"More Info: https://git.io/v9r4K",
|
|
|
|
queued = false
|
2018-08-12 14:03:07 +00:00
|
|
|
)
|
|
|
|
public void masks(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
|
|
|
displayModifierHelp(player, DefaultMaskParser.class, args);
|
|
|
|
}
|
2018-06-15 05:41:37 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
@Command(
|
|
|
|
aliases = {"transforms"},
|
|
|
|
usage = "[page=1|search|transform]",
|
|
|
|
desc = "View help about transforms",
|
|
|
|
help = "Transforms modify how a block is placed\n" +
|
|
|
|
" - Use [brackets] for arguments\n" +
|
|
|
|
" - Use , to OR multiple\n" +
|
|
|
|
" - Use & to AND multiple\n" +
|
2018-08-24 09:33:52 +00:00
|
|
|
"More Info: https://git.io/v9KHO",
|
|
|
|
queued = false
|
2018-08-12 14:03:07 +00:00
|
|
|
)
|
|
|
|
public void transforms(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
|
|
|
displayModifierHelp(player, DefaultTransformParser.class, args);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void displayModifierHelp(Player player, Class<? extends FaweParser> clazz, CommandContext args) {
|
|
|
|
FaweParser parser = FaweAPI.getParser(clazz);
|
|
|
|
if (args.argsLength() == 0) {
|
|
|
|
String base = getCommand().aliases()[0];
|
|
|
|
UsageMessage msg = new UsageMessage(getCallable(), (WorldEdit.getInstance().getConfiguration().noDoubleSlash ? "" : "/") + base, args.getLocals());
|
|
|
|
msg.newline().paginate(base, 0, 1).send(player);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (parser != null) {
|
|
|
|
CommandMapping mapping = parser.getDispatcher().get(args.getString(0));
|
|
|
|
if (mapping != null) {
|
|
|
|
new UsageMessage(mapping.getCallable(), args.getString(0), args.getLocals()) {
|
|
|
|
@Override
|
|
|
|
public String separateArg(String arg) {
|
|
|
|
return "&7[" + arg + "&7]";
|
|
|
|
}
|
|
|
|
}.send(player);
|
|
|
|
} else {
|
|
|
|
UtilityCommands.help(args, worldEdit, player, getCommand().aliases()[0] + " ", parser.getDispatcher());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2018-09-06 20:40:13 +00:00
|
|
|
@Command(
|
|
|
|
aliases = {"/heightmapinterface"},
|
2018-09-07 15:09:31 +00:00
|
|
|
desc = "Generate the heightmap interface: https://github.com/boy0001/HeightMap"
|
2018-09-06 20:40:13 +00:00
|
|
|
)
|
2018-10-04 18:42:43 +00:00
|
|
|
@CommandPermissions("fawe.admin")
|
2018-09-06 20:45:19 +00:00
|
|
|
public void heightmapInterface(FawePlayer player, @Optional("100") int min, @Optional("200") int max) throws IOException {
|
2018-09-06 20:40:13 +00:00
|
|
|
player.sendMessage("Please wait while we generate the minified heightmaps.");
|
|
|
|
File srcFolder = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.HEIGHTMAP);
|
|
|
|
|
|
|
|
File webSrc = new File(Fawe.imp().getDirectory(), "web" + File.separator + "heightmap");
|
|
|
|
File minImages = new File(webSrc, "images" + File.separator + "min");
|
|
|
|
File maxImages = new File(webSrc, "images" + File.separator + "max");
|
|
|
|
final int sub = srcFolder.getAbsolutePath().length();
|
|
|
|
List<String> images = new ArrayList<>();
|
|
|
|
MainUtil.iterateFiles(srcFolder, new Consumer<File>() {
|
|
|
|
@Override
|
|
|
|
public void accept(File file) {
|
|
|
|
switch (file.getName().substring(file.getName().lastIndexOf('.')).toLowerCase()) {
|
|
|
|
case ".png":
|
|
|
|
case ".jpeg":
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
String name = file.getAbsolutePath().substring(sub);
|
|
|
|
if (name.startsWith(File.separator)) name = name.replaceFirst(java.util.regex.Pattern.quote(File.separator), "");
|
|
|
|
BufferedImage img = MainUtil.readImage(file);
|
|
|
|
BufferedImage minImg = ImageUtil.getScaledInstance(img, min, min, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true);
|
2018-09-07 15:09:31 +00:00
|
|
|
BufferedImage maxImg = max == -1 ? img : ImageUtil.getScaledInstance(img, max, max, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true);
|
2018-09-06 20:40:13 +00:00
|
|
|
player.sendMessage("Writing " + name);
|
|
|
|
File minFile = new File(minImages, name);
|
|
|
|
File maxFile = new File(maxImages, name);
|
|
|
|
minFile.getParentFile().mkdirs();
|
|
|
|
maxFile.getParentFile().mkdirs();
|
|
|
|
ImageIO.write(minImg, "png", minFile);
|
|
|
|
ImageIO.write(maxImg, "png", maxFile);
|
|
|
|
images.add(name);
|
|
|
|
} catch (IOException e) {
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
StringBuilder config = new StringBuilder();
|
|
|
|
config.append("var images = [\n");
|
|
|
|
for (String image : images) {
|
|
|
|
config.append('"' + image.replace(File.separator, "/") + "\",\n");
|
|
|
|
}
|
|
|
|
config.append("];\n");
|
|
|
|
config.append("// The low res images (they should all be the same size)\n");
|
|
|
|
config.append("var src_min = \"images/min/\";\n");
|
|
|
|
config.append("// The max resolution images (Use the same if there are no higher resolution ones available)\n");
|
|
|
|
config.append("var src_max = \"images/max/\";\n");
|
|
|
|
config.append("// The local source for the image (used in commands)\n");
|
|
|
|
config.append("var src_local = \"file://\";\n");
|
|
|
|
File configFile = new File(webSrc, "config.js");
|
|
|
|
player.sendMessage("Writing " + configFile);
|
|
|
|
Files.write(configFile.toPath(), config.toString().getBytes());
|
|
|
|
player.sendMessage("Done! See: `FastAsyncWorldEdit/web/heightmap`");
|
|
|
|
}
|
|
|
|
|
2018-08-24 09:33:52 +00:00
|
|
|
@Command(
|
|
|
|
aliases = {"/cancel", "fcancel"},
|
|
|
|
desc = "Cancel your current command",
|
|
|
|
max = 0,
|
|
|
|
queued = false
|
|
|
|
)
|
|
|
|
public void cancel(FawePlayer player) {
|
|
|
|
int cancelled = player.cancel(false);
|
|
|
|
BBC.WORLDEDIT_CANCEL_COUNT.send(player, cancelled);
|
|
|
|
}
|
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
@Command(
|
|
|
|
aliases = {"/fill"},
|
|
|
|
usage = "<pattern> <radius> [depth] [direction]",
|
|
|
|
desc = "Fill a hole",
|
|
|
|
min = 2,
|
|
|
|
max = 4
|
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.fill")
|
|
|
|
@Logging(PLACEMENT)
|
2019-01-09 07:13:44 +00:00
|
|
|
public void fill(Player player, LocalSession session, EditSession editSession, Pattern pattern, double radius, @Optional("1") double depth, @Optional("down") @Direction BlockVector3 direction) throws WorldEditException {
|
2018-08-12 14:03:07 +00:00
|
|
|
worldEdit.checkMaxRadius(radius);
|
2019-01-09 07:13:44 +00:00
|
|
|
BlockVector3 pos = session.getPlacementPosition(player);
|
2018-08-12 14:03:07 +00:00
|
|
|
int affected;
|
|
|
|
affected = editSession.fillDirection(pos, pattern, radius, (int) depth, direction);
|
|
|
|
player.print(BBC.getPrefix() + affected + " block(s) have been created.");
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"/fillr"},
|
|
|
|
usage = "<pattern> <radius> [depth]",
|
|
|
|
desc = "Fill a hole recursively",
|
|
|
|
min = 2,
|
|
|
|
max = 3
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.fill.recursive")
|
|
|
|
@Logging(PLACEMENT)
|
2018-08-12 14:03:07 +00:00
|
|
|
public void fillr(Player player, LocalSession session, EditSession editSession, Pattern pattern, double radius, @Optional("-1") double depth) throws WorldEditException {
|
|
|
|
worldEdit.checkMaxRadius(radius);
|
2019-01-09 07:13:44 +00:00
|
|
|
BlockVector3 pos = session.getPlacementPosition(player);
|
2018-08-12 14:03:07 +00:00
|
|
|
if (depth == -1) depth = Integer.MAX_VALUE;
|
|
|
|
int affected = editSession.fillXZ(pos, pattern, radius, (int) depth, true);
|
|
|
|
player.print(BBC.getPrefix() + affected + " block(s) have been created.");
|
2019-01-09 07:13:44 +00:00
|
|
|
//=======
|
|
|
|
// public void fillr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
|
|
|
//
|
|
|
|
// ParserContext context = new ParserContext();
|
|
|
|
// context.setActor(player);
|
|
|
|
// context.setWorld(player.getWorld());
|
|
|
|
// context.setSession(session);
|
|
|
|
// Pattern pattern = we.getPatternFactory().parseFromInput(args.getString(0), context);
|
|
|
|
//
|
|
|
|
// double radius = Math.max(1, args.getDouble(1));
|
|
|
|
// we.checkMaxRadius(radius);
|
|
|
|
// int depth = args.argsLength() > 2 ? Math.max(1, args.getInteger(2)) : Integer.MAX_VALUE;
|
|
|
|
//
|
|
|
|
// BlockVector3 pos = session.getPlacementPosition(player);
|
|
|
|
// int affected = 0;
|
|
|
|
// if (pattern instanceof BlockPattern) {
|
|
|
|
// affected = editSession.fillXZ(pos, ((BlockPattern) pattern).getBlock(), radius, depth, true);
|
|
|
|
// } else {
|
|
|
|
// affected = editSession.fillXZ(pos, pattern, radius, depth, true);
|
|
|
|
// }
|
|
|
|
// player.print(affected + " block(s) have been created.");
|
|
|
|
//>>>>>>> 399e0ad5... Refactor vector system to be cleaner
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"/drain"},
|
|
|
|
usage = "<radius>",
|
|
|
|
desc = "Drain a pool",
|
|
|
|
min = 1,
|
|
|
|
max = 1
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.drain")
|
|
|
|
@Logging(PLACEMENT)
|
2018-08-12 14:03:07 +00:00
|
|
|
public void drain(Player player, LocalSession session, EditSession editSession, double radius) throws WorldEditException {
|
|
|
|
worldEdit.checkMaxRadius(radius);
|
2014-04-03 02:08:50 +00:00
|
|
|
int affected = editSession.drainArea(
|
|
|
|
session.getPlacementPosition(player), radius);
|
2018-08-12 14:03:07 +00:00
|
|
|
player.print(BBC.getPrefix() + affected + " block(s) have been changed.");
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"/fixlava", "fixlava"},
|
|
|
|
usage = "<radius>",
|
|
|
|
desc = "Fix lava to be stationary",
|
|
|
|
min = 1,
|
|
|
|
max = 1
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.fixlava")
|
|
|
|
@Logging(PLACEMENT)
|
2018-08-12 14:03:07 +00:00
|
|
|
public void fixLava(Player player, LocalSession session, EditSession editSession, double radius) throws WorldEditException {
|
|
|
|
worldEdit.checkMaxRadius(radius);
|
|
|
|
int affected = editSession.fixLiquid(
|
2018-10-13 08:50:13 +00:00
|
|
|
session.getPlacementPosition(player), radius, BlockTypes.LAVA.toMask(editSession), BlockTypes.LAVA.getDefaultState());
|
2018-08-12 14:03:07 +00:00
|
|
|
player.print(BBC.getPrefix() + affected + " block(s) have been changed.");
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"/fixwater", "fixwater"},
|
|
|
|
usage = "<radius>",
|
|
|
|
desc = "Fix water to be stationary",
|
|
|
|
min = 1,
|
|
|
|
max = 1
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.fixwater")
|
|
|
|
@Logging(PLACEMENT)
|
2018-08-12 14:03:07 +00:00
|
|
|
public void fixWater(Player player, LocalSession session, EditSession editSession, double radius) throws WorldEditException {
|
|
|
|
worldEdit.checkMaxRadius(radius);
|
|
|
|
int affected = editSession.fixLiquid(
|
2018-10-13 08:50:13 +00:00
|
|
|
session.getPlacementPosition(player), radius, BlockTypes.WATER.toMask(editSession), BlockTypes.WATER.getDefaultState());
|
2018-08-12 14:03:07 +00:00
|
|
|
player.print(BBC.getPrefix() + affected + " block(s) have been changed.");
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"/removeabove", "removeabove"},
|
|
|
|
usage = "[size] [height]",
|
|
|
|
desc = "Remove blocks above your head.",
|
|
|
|
min = 0,
|
|
|
|
max = 2
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.removeabove")
|
|
|
|
@Logging(PLACEMENT)
|
2018-08-12 14:03:07 +00:00
|
|
|
public void removeAbove(Player player, LocalSession session, EditSession editSession, @Optional("1") double size, @Optional("256") double height) throws WorldEditException {
|
|
|
|
worldEdit.checkMaxRadius(size);
|
|
|
|
int affected = editSession.removeAbove(session.getPlacementPosition(player), (int) size, (int) height);
|
|
|
|
player.print(BBC.getPrefix() + affected + " block(s) have been removed.");
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"/removebelow", "removebelow"},
|
|
|
|
usage = "[size] [height]",
|
|
|
|
desc = "Remove blocks below you.",
|
|
|
|
min = 0,
|
|
|
|
max = 2
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.removebelow")
|
|
|
|
@Logging(PLACEMENT)
|
2018-08-12 14:03:07 +00:00
|
|
|
public void removeBelow(Player player, LocalSession session, EditSession editSession, @Optional("1") double size, @Optional("256") double height) throws WorldEditException {
|
|
|
|
worldEdit.checkMaxRadius(size);
|
|
|
|
int affected = editSession.removeBelow(session.getPlacementPosition(player), (int) size, (int) height);
|
|
|
|
player.print(BBC.getPrefix() + affected + " block(s) have been removed.");
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"/removenear", "removenear"},
|
|
|
|
usage = "<block> [size]",
|
|
|
|
desc = "Remove blocks near you.",
|
|
|
|
min = 1,
|
|
|
|
max = 2
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.removenear")
|
|
|
|
@Logging(PLACEMENT)
|
2018-08-12 14:03:07 +00:00
|
|
|
public void removeNear(Player player, LocalSession session, EditSession editSession, Mask mask, @Optional("50") double size) throws WorldEditException {
|
|
|
|
worldEdit.checkMaxRadius(size);
|
2018-12-29 07:47:57 +00:00
|
|
|
size = Math.max(1, size);
|
2018-08-12 14:03:07 +00:00
|
|
|
int affected = editSession.removeNear(session.getPlacementPosition(player), mask, (int) size);
|
|
|
|
player.print(BBC.getPrefix() + affected + " block(s) have been removed.");
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"/replacenear", "replacenear"},
|
|
|
|
usage = "<size> <from-id> <to-id>",
|
|
|
|
desc = "Replace nearby blocks",
|
|
|
|
flags = "f",
|
|
|
|
min = 3,
|
|
|
|
max = 3
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.replacenear")
|
|
|
|
@Logging(PLACEMENT)
|
2018-08-12 14:03:07 +00:00
|
|
|
public void replaceNear(Player player, LocalSession session, EditSession editSession, double size, @Optional Mask from, Pattern to) throws WorldEditException {
|
|
|
|
if (from == null) {
|
|
|
|
from = new ExistingBlockMask(editSession);
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
2018-12-23 16:19:33 +00:00
|
|
|
|
|
|
|
BlockVector3 base = session.getPlacementPosition(player);
|
2019-01-09 07:13:44 +00:00
|
|
|
BlockVector3 min = base.subtract((int)size, (int)size, (int)size);
|
|
|
|
BlockVector3 max = base.add((int)size, (int)size, (int)size);
|
2014-04-03 02:08:50 +00:00
|
|
|
Region region = new CuboidRegion(player.getWorld(), min, max);
|
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
int affected = editSession.replaceBlocks(region, from, to);
|
|
|
|
BBC.VISITOR_BLOCK.send(player, affected);
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"/snow", "snow"},
|
|
|
|
usage = "[radius]",
|
|
|
|
desc = "Simulates snow",
|
|
|
|
min = 0,
|
|
|
|
max = 1
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.snow")
|
|
|
|
@Logging(PLACEMENT)
|
2014-06-28 08:01:49 +00:00
|
|
|
public void snow(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
2014-04-03 02:08:50 +00:00
|
|
|
|
|
|
|
double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10;
|
|
|
|
|
|
|
|
int affected = editSession.simulateSnow(session.getPlacementPosition(player), size);
|
2018-08-12 14:03:07 +00:00
|
|
|
player.print(BBC.getPrefix() + affected + " surfaces covered. Let it snow~");
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"/thaw", "thaw"},
|
|
|
|
usage = "[radius]",
|
|
|
|
desc = "Thaws the area",
|
|
|
|
min = 0,
|
|
|
|
max = 1
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.thaw")
|
|
|
|
@Logging(PLACEMENT)
|
2014-06-28 08:01:49 +00:00
|
|
|
public void thaw(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
2014-04-03 02:08:50 +00:00
|
|
|
|
|
|
|
double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10;
|
|
|
|
|
|
|
|
int affected = editSession.thaw(session.getPlacementPosition(player), size);
|
2018-08-12 14:03:07 +00:00
|
|
|
player.print(BBC.getPrefix() + affected + " surfaces thawed.");
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"/green", "green"},
|
|
|
|
usage = "[radius]",
|
|
|
|
desc = "Greens the area",
|
|
|
|
flags = "f",
|
|
|
|
min = 0,
|
|
|
|
max = 1
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.green")
|
|
|
|
@Logging(PLACEMENT)
|
2014-06-28 08:01:49 +00:00
|
|
|
public void green(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
2014-04-03 02:08:50 +00:00
|
|
|
|
|
|
|
final double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10;
|
|
|
|
final boolean onlyNormalDirt = !args.hasFlag('f');
|
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
final int affected = editSession.green(session.getPlacementPosition(player), size);
|
|
|
|
player.print(BBC.getPrefix() + affected + " surfaces greened.");
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"/ex", "/ext", "/extinguish", "ex", "ext", "extinguish"},
|
2014-04-03 02:08:50 +00:00
|
|
|
usage = "[radius]",
|
|
|
|
desc = "Extinguish nearby fire",
|
|
|
|
min = 0,
|
|
|
|
max = 1
|
2018-08-12 14:03:07 +00:00
|
|
|
)
|
2014-04-03 02:08:50 +00:00
|
|
|
@CommandPermissions("worldedit.extinguish")
|
|
|
|
@Logging(PLACEMENT)
|
2014-06-28 08:01:49 +00:00
|
|
|
public void extinguish(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
LocalConfiguration config = worldEdit.getConfiguration();
|
2014-04-03 02:08:50 +00:00
|
|
|
|
|
|
|
int defaultRadius = config.maxRadius != -1 ? Math.min(40, config.maxRadius) : 40;
|
|
|
|
int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0))
|
|
|
|
: defaultRadius;
|
2018-08-12 14:03:07 +00:00
|
|
|
worldEdit.checkMaxRadius(size);
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
int affected = editSession.removeNear(session.getPlacementPosition(player), BlockTypes.FIRE.toMask(editSession), size);
|
|
|
|
player.print(BBC.getPrefix() + affected + " block(s) have been removed.");
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"butcher"},
|
|
|
|
usage = "[radius]",
|
|
|
|
flags = "plangbtfr",
|
|
|
|
desc = "Kill all or nearby mobs",
|
|
|
|
help =
|
|
|
|
"Kills nearby mobs, based on radius, if none is given uses default in configuration.\n" +
|
|
|
|
"Flags:\n" +
|
|
|
|
" -p also kills pets.\n" +
|
|
|
|
" -n also kills NPCs.\n" +
|
|
|
|
" -g also kills Golems.\n" +
|
|
|
|
" -a also kills animals.\n" +
|
|
|
|
" -b also kills ambient mobs.\n" +
|
|
|
|
" -t also kills mobs with name tags.\n" +
|
|
|
|
" -f compounds all previous flags.\n" +
|
|
|
|
" -r also destroys armor stands.\n" +
|
|
|
|
" -l currently does nothing.",
|
|
|
|
min = 0,
|
|
|
|
max = 1
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.butcher")
|
|
|
|
@Logging(PLACEMENT)
|
2014-07-01 22:04:30 +00:00
|
|
|
public void butcher(Actor actor, CommandContext args) throws WorldEditException {
|
2018-08-12 14:03:07 +00:00
|
|
|
LocalConfiguration config = worldEdit.getConfiguration();
|
2014-07-01 22:04:30 +00:00
|
|
|
Player player = actor instanceof Player ? (Player) actor : null;
|
2014-04-03 02:08:50 +00:00
|
|
|
|
|
|
|
// technically the default can be larger than the max, but that's not my problem
|
|
|
|
int radius = config.butcherDefaultRadius;
|
|
|
|
|
|
|
|
// there might be a better way to do this but my brain is fried right now
|
|
|
|
if (args.argsLength() > 0) { // user inputted radius, override the default
|
|
|
|
radius = args.getInteger(0);
|
2016-04-26 23:40:25 +00:00
|
|
|
if (radius < -1) {
|
|
|
|
actor.printError("Use -1 to remove all mobs in loaded chunks");
|
|
|
|
return;
|
|
|
|
}
|
2014-04-03 02:08:50 +00:00
|
|
|
if (config.butcherMaxRadius != -1) { // clamp if there is a max
|
|
|
|
if (radius == -1) {
|
|
|
|
radius = config.butcherMaxRadius;
|
|
|
|
} else { // Math.min does not work if radius is -1 (actually highest possible value)
|
|
|
|
radius = Math.min(radius, config.butcherMaxRadius);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-16 02:47:47 +00:00
|
|
|
CreatureButcher flags = new CreatureButcher(actor);
|
|
|
|
flags.fromCommand(args);
|
|
|
|
|
2019-02-16 02:46:10 +00:00
|
|
|
List<EntityVisitor> visitors = new ArrayList<>();
|
2014-07-16 02:47:47 +00:00
|
|
|
LocalSession session = null;
|
|
|
|
EditSession editSession = null;
|
|
|
|
|
2014-06-28 00:55:39 +00:00
|
|
|
if (player != null) {
|
2018-08-12 14:03:07 +00:00
|
|
|
session = worldEdit.getSessionManager().get(player);
|
2018-12-23 16:19:33 +00:00
|
|
|
BlockVector3 center = session.getPlacementPosition(player);
|
2014-07-16 02:47:47 +00:00
|
|
|
editSession = session.createEditSession(player);
|
|
|
|
List<? extends Entity> entities;
|
|
|
|
if (radius >= 0) {
|
|
|
|
CylinderRegion region = CylinderRegion.createRadius(editSession, center, radius);
|
|
|
|
entities = editSession.getEntities(region);
|
|
|
|
} else {
|
|
|
|
entities = editSession.getEntities();
|
|
|
|
}
|
2018-06-19 00:53:15 +00:00
|
|
|
visitors.add(new EntityVisitor(entities.iterator(), flags.createFunction()));
|
2014-04-03 02:08:50 +00:00
|
|
|
} else {
|
2018-08-12 14:03:07 +00:00
|
|
|
Platform platform = worldEdit.getPlatformManager().queryCapability(Capability.WORLD_EDITING);
|
2014-07-16 02:47:47 +00:00
|
|
|
for (World world : platform.getWorlds()) {
|
|
|
|
List<? extends Entity> entities = world.getEntities();
|
2018-06-19 00:53:15 +00:00
|
|
|
visitors.add(new EntityVisitor(entities.iterator(), flags.createFunction()));
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-16 02:47:47 +00:00
|
|
|
int killed = 0;
|
|
|
|
for (EntityVisitor visitor : visitors) {
|
|
|
|
Operations.completeLegacy(visitor);
|
|
|
|
killed += visitor.getAffected();
|
|
|
|
}
|
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
BBC.KILL_SUCCESS.send(actor, killed, radius);
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2014-07-16 02:47:47 +00:00
|
|
|
if (editSession != null) {
|
|
|
|
session.remember(editSession);
|
|
|
|
editSession.flushQueue();
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"remove", "rem", "rement"},
|
|
|
|
usage = "<type> <radius>",
|
|
|
|
desc = "Remove all entities of a type",
|
|
|
|
min = 2,
|
|
|
|
max = 2
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.remove")
|
|
|
|
@Logging(PLACEMENT)
|
2014-07-16 02:47:47 +00:00
|
|
|
public void remove(Actor actor, CommandContext args) throws WorldEditException, CommandException {
|
2014-04-03 02:08:50 +00:00
|
|
|
String typeStr = args.getString(0);
|
|
|
|
int radius = args.getInteger(1);
|
2014-07-16 02:47:47 +00:00
|
|
|
Player player = actor instanceof Player ? (Player) actor : null;
|
2014-04-03 02:08:50 +00:00
|
|
|
|
|
|
|
if (radius < -1) {
|
2014-06-28 00:55:39 +00:00
|
|
|
actor.printError("Use -1 to remove all entities in loaded chunks");
|
2014-04-03 02:08:50 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-07-16 02:47:47 +00:00
|
|
|
EntityRemover remover = new EntityRemover();
|
|
|
|
remover.fromString(typeStr);
|
|
|
|
|
2019-02-16 02:46:10 +00:00
|
|
|
List<EntityVisitor> visitors = new ArrayList<>();
|
2014-07-16 02:47:47 +00:00
|
|
|
LocalSession session = null;
|
|
|
|
EditSession editSession = null;
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2014-06-28 00:55:39 +00:00
|
|
|
if (player != null) {
|
2018-08-12 14:03:07 +00:00
|
|
|
session = worldEdit.getSessionManager().get(player);
|
2018-12-23 16:19:33 +00:00
|
|
|
BlockVector3 center = session.getPlacementPosition(player);
|
2014-07-16 02:47:47 +00:00
|
|
|
editSession = session.createEditSession(player);
|
|
|
|
List<? extends Entity> entities;
|
|
|
|
if (radius >= 0) {
|
|
|
|
CylinderRegion region = CylinderRegion.createRadius(editSession, center, radius);
|
|
|
|
entities = editSession.getEntities(region);
|
|
|
|
} else {
|
|
|
|
entities = editSession.getEntities();
|
|
|
|
}
|
2018-06-19 00:53:15 +00:00
|
|
|
visitors.add(new EntityVisitor(entities.iterator(), remover.createFunction()));
|
2014-04-03 02:08:50 +00:00
|
|
|
} else {
|
2018-08-12 14:03:07 +00:00
|
|
|
Platform platform = worldEdit.getPlatformManager().queryCapability(Capability.WORLD_EDITING);
|
2014-07-16 02:47:47 +00:00
|
|
|
for (World world : platform.getWorlds()) {
|
|
|
|
List<? extends Entity> entities = world.getEntities();
|
2018-06-19 00:53:15 +00:00
|
|
|
visitors.add(new EntityVisitor(entities.iterator(), remover.createFunction()));
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
}
|
2014-07-16 02:47:47 +00:00
|
|
|
|
|
|
|
int removed = 0;
|
|
|
|
for (EntityVisitor visitor : visitors) {
|
|
|
|
Operations.completeLegacy(visitor);
|
|
|
|
removed += visitor.getAffected();
|
|
|
|
}
|
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
BBC.KILL_SUCCESS.send(actor, removed, radius);
|
2014-07-16 02:47:47 +00:00
|
|
|
|
|
|
|
if (editSession != null) {
|
|
|
|
session.remember(editSession);
|
|
|
|
editSession.flushQueue();
|
|
|
|
}
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
2014-07-03 10:34:19 +00:00
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"/calc", "/calculate", "/eval", "/evaluate", "/solve"},
|
|
|
|
usage = "<expression>",
|
|
|
|
desc = "Evaluate a mathematical expression"
|
2014-07-03 10:34:19 +00:00
|
|
|
)
|
2015-12-21 21:14:44 +00:00
|
|
|
@CommandPermissions("worldedit.calc")
|
2018-08-12 14:03:07 +00:00
|
|
|
public void calc(final Actor actor, @Text String input) throws CommandException {
|
2014-07-03 10:34:19 +00:00
|
|
|
try {
|
2018-08-12 14:03:07 +00:00
|
|
|
FaweLimit limit = FawePlayer.wrap(actor).getLimit();
|
|
|
|
final Expression expression = Expression.compile(input);
|
|
|
|
|
|
|
|
ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
|
|
Future<Double> futureResult = executor.submit(new Callable<Double>() {
|
|
|
|
@Override
|
|
|
|
public Double call() throws Exception {
|
|
|
|
|
|
|
|
return expression.evaluate();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
Double result = Double.NaN;
|
|
|
|
try {
|
|
|
|
result = futureResult.get(limit.MAX_EXPRESSION_MS, TimeUnit.MILLISECONDS);
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
} catch (ExecutionException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
} catch (TimeoutException e) {
|
|
|
|
futureResult.cancel(true);
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
|
|
|
|
executor.shutdownNow();
|
|
|
|
actor.print(BBC.getPrefix() + "= " + result);
|
2014-07-03 10:34:19 +00:00
|
|
|
} catch (EvaluationException e) {
|
|
|
|
actor.printError(String.format(
|
|
|
|
"'%s' could not be parsed as a valid expression", input));
|
|
|
|
} catch (ExpressionException e) {
|
|
|
|
actor.printError(String.format(
|
|
|
|
"'%s' could not be evaluated (error: %s)", input, e.getMessage()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-03 02:08:50 +00:00
|
|
|
@Command(
|
2018-08-12 14:03:07 +00:00
|
|
|
aliases = {"/confirm"},
|
|
|
|
desc = "Confirm a command"
|
|
|
|
)
|
|
|
|
public void confirm(FawePlayer fp) throws WorldEditException {
|
|
|
|
if (!fp.confirm()) {
|
|
|
|
BBC.NOTHING_CONFIRMED.send(fp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
aliases = {"/help"},
|
|
|
|
usage = "[<command>]",
|
|
|
|
desc = "Displays help for WorldEdit commands",
|
|
|
|
min = 0,
|
2018-08-24 09:33:52 +00:00
|
|
|
max = -1,
|
|
|
|
queued = false
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
2014-06-28 00:55:39 +00:00
|
|
|
public void help(Actor actor, CommandContext args) throws WorldEditException {
|
2018-08-12 14:03:07 +00:00
|
|
|
help(args, worldEdit, actor);
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
protected static CommandMapping detectCommand(Dispatcher dispatcher, String command, boolean isRootLevel) {
|
2014-07-01 04:56:05 +00:00
|
|
|
CommandMapping mapping;
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2014-07-01 04:56:05 +00:00
|
|
|
// First try the command as entered
|
|
|
|
mapping = dispatcher.get(command);
|
|
|
|
if (mapping != null) {
|
|
|
|
return mapping;
|
|
|
|
}
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2014-07-01 04:56:05 +00:00
|
|
|
// Then if we're looking at root commands and the user didn't use
|
|
|
|
// any slashes, let's try double slashes and then single slashes.
|
|
|
|
// However, be aware that there exists different single slash
|
|
|
|
// and double slash commands in WorldEdit
|
|
|
|
if (isRootLevel && !command.contains("/")) {
|
|
|
|
mapping = dispatcher.get("//" + command);
|
|
|
|
if (mapping != null) {
|
|
|
|
return mapping;
|
|
|
|
}
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2014-07-01 04:56:05 +00:00
|
|
|
mapping = dispatcher.get("/" + command);
|
|
|
|
if (mapping != null) {
|
|
|
|
return mapping;
|
|
|
|
}
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
2014-07-01 04:56:05 +00:00
|
|
|
return null;
|
|
|
|
}
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
public static void list(File dir, Actor actor, CommandContext args, @Range(min = 0) int page, String formatName, boolean playerFolder, String onClickCmd) {
|
|
|
|
list(dir, actor, args, page, -1, formatName, playerFolder, new RunnableVal3<Message, URI, String>() {
|
|
|
|
@Override
|
|
|
|
public void run(Message m, URI uri, String fileName) {
|
|
|
|
m.text(BBC.SCHEMATIC_LIST_ELEM, fileName, "");
|
|
|
|
if (onClickCmd != null) m.cmdTip(onClickCmd + " " + fileName);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2014-07-01 04:56:05 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
public static void list(File dir, Actor actor, CommandContext args, @Range(min = 0) int page, int perPage, String formatName, boolean playerFolder, RunnableVal3<Message, URI, String> eachMsg) {
|
|
|
|
AtomicInteger pageInt = new AtomicInteger(page);
|
|
|
|
List<File> fileList = new ArrayList<>();
|
|
|
|
if (perPage == -1) perPage = actor instanceof Player ? 12 : 20; // More pages for console
|
|
|
|
page = getFiles(dir, actor, args, page, perPage, formatName, playerFolder, file -> fileList.add(file));
|
2014-07-01 04:56:05 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
if (fileList.isEmpty()) {
|
|
|
|
BBC.SCHEMATIC_NONE.send(actor);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pageCount = (fileList.size() + perPage - 1) / perPage;
|
|
|
|
if (page < 1) {
|
|
|
|
BBC.SCHEMATIC_PAGE.send(actor, ">0");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (page > pageCount) {
|
|
|
|
BBC.SCHEMATIC_PAGE.send(actor, "<" + (pageCount + 1));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
final int sortType = args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0;
|
|
|
|
// cleanup file list
|
|
|
|
Collections.sort(fileList, new Comparator<File>() {
|
|
|
|
@Override
|
|
|
|
public int compare(File f1, File f2) {
|
|
|
|
boolean dir1 = f1.isDirectory();
|
|
|
|
boolean dir2 = f2.isDirectory();
|
|
|
|
if (dir1 != dir2) return dir1 ? -1 : 1;
|
|
|
|
int res;
|
|
|
|
if (sortType == 0) { // use name by default
|
|
|
|
int p = f1.getParent().compareTo(f2.getParent());
|
|
|
|
if (p == 0) { // same parent, compare names
|
|
|
|
res = f1.getName().compareTo(f2.getName());
|
|
|
|
} else { // different parent, sort by that
|
|
|
|
res = p;
|
|
|
|
}
|
2014-07-01 04:56:05 +00:00
|
|
|
} else {
|
2018-08-12 14:03:07 +00:00
|
|
|
res = Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); // use date if there is a flag
|
|
|
|
if (sortType == 1) res = -res; // flip date for newest first instead of oldest first
|
2014-07-01 04:56:05 +00:00
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
int offset = (page - 1) * perPage;
|
2014-07-01 04:56:05 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
int limit = Math.min(offset + perPage, fileList.size());
|
|
|
|
|
|
|
|
String fullArgs = (String) args.getLocals().get("arguments");
|
|
|
|
String baseCmd = null;
|
|
|
|
if (fullArgs != null) {
|
|
|
|
baseCmd = fullArgs.endsWith(" " + page) ? fullArgs.substring(0, fullArgs.length() - (" " + page).length()) : fullArgs;
|
|
|
|
}
|
|
|
|
Message m = new Message(BBC.SCHEMATIC_LIST, page, pageCount);
|
|
|
|
|
|
|
|
UUID uuid = playerFolder ? actor.getUniqueId() : null;
|
|
|
|
for (int i = offset; i < limit; i++) {
|
|
|
|
m.newline();
|
|
|
|
File file = fileList.get(i);
|
|
|
|
eachMsg.run(m, file.toURI(), getPath(dir, file, uuid));
|
|
|
|
}
|
|
|
|
if (baseCmd != null) {
|
|
|
|
m.newline().paginate(baseCmd, page, pageCount);
|
|
|
|
}
|
|
|
|
m.send(actor);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int getFiles(File dir, Actor actor, CommandContext args, @Range(min = 0) int page, int perPage, String formatName, boolean playerFolder, Consumer<File> forEachFile) {
|
|
|
|
Consumer<File> rootFunction = forEachFile;
|
|
|
|
|
|
|
|
int len = args.argsLength();
|
|
|
|
List<String> filters = new ArrayList<>();
|
|
|
|
|
|
|
|
String dirFilter = File.separator;
|
|
|
|
|
|
|
|
boolean listMine = false;
|
|
|
|
boolean listGlobal = !Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS;
|
|
|
|
if (len > 0) {
|
|
|
|
int max = len;
|
|
|
|
if (MathMan.isInteger(args.getString(len - 1))) {
|
|
|
|
page = args.getInteger(--len);
|
2014-07-01 04:56:05 +00:00
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
String arg = args.getString(i);
|
|
|
|
switch (arg.toLowerCase()) {
|
|
|
|
case "me":
|
|
|
|
case "mine":
|
|
|
|
case "local":
|
|
|
|
case "private":
|
|
|
|
listMine = true;
|
|
|
|
break;
|
|
|
|
case "public":
|
|
|
|
case "global":
|
|
|
|
listGlobal = true;
|
|
|
|
break;
|
|
|
|
case "all":
|
|
|
|
listMine = true;
|
|
|
|
listGlobal = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (arg.endsWith("/") || arg.endsWith(File.separator)) {
|
|
|
|
arg = arg.replace("/", File.separator);
|
|
|
|
String newDirFilter = dirFilter + arg;
|
|
|
|
boolean exists = new File(dir, newDirFilter).exists() || playerFolder && MainUtil.resolveRelative(new File(dir, actor.getUniqueId() + newDirFilter)).exists();
|
|
|
|
if (!exists) {
|
|
|
|
arg = arg.substring(0, arg.length() - File.separator.length());
|
|
|
|
if (arg.length() > 3 && arg.length() <= 16) {
|
|
|
|
UUID fromName = Fawe.imp().getUUID(arg);
|
|
|
|
if (fromName != null) {
|
|
|
|
newDirFilter = dirFilter + fromName + File.separator;
|
|
|
|
listGlobal = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dirFilter = newDirFilter;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
filters.add(arg);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!listMine && !listGlobal) {
|
|
|
|
listMine = true;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
FileFilter ignoreUUIDs = f -> {
|
|
|
|
try {
|
|
|
|
if (f.isDirectory()) {
|
|
|
|
UUID uuid = UUID.fromString(f.getName());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} catch (IllegalArgumentException exception) {}
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
List<File> toFilter = new ArrayList<>();
|
|
|
|
if (!filters.isEmpty()) {
|
|
|
|
forEachFile = new DelegateConsumer<File>(forEachFile) {
|
|
|
|
@Override
|
|
|
|
public void accept(File file) {
|
|
|
|
toFilter.add(file);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (formatName != null) {
|
2019-01-31 15:08:58 +00:00
|
|
|
final ClipboardFormat cf = ClipboardFormats.findByAlias(formatName);
|
2018-08-12 14:03:07 +00:00
|
|
|
forEachFile = new DelegateConsumer<File>(forEachFile) {
|
|
|
|
@Override
|
|
|
|
public void accept(File file) {
|
|
|
|
if (cf.isFormat(file)) super.accept(file);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
forEachFile = new DelegateConsumer<File>(forEachFile) {
|
|
|
|
@Override
|
|
|
|
public void accept(File file) {
|
|
|
|
if (!file.toString().endsWith(".cached")) super.accept(file);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
if (playerFolder) {
|
|
|
|
if (listMine) {
|
|
|
|
File playerDir = MainUtil.resolveRelative(new File(dir, actor.getUniqueId() + dirFilter));
|
|
|
|
if (playerDir.exists()) allFiles(playerDir.listFiles(), false, forEachFile);
|
|
|
|
}
|
|
|
|
if (listGlobal) {
|
|
|
|
File rel = MainUtil.resolveRelative(new File(dir, dirFilter));
|
|
|
|
forEachFile = new DelegateConsumer<File>(forEachFile) {
|
|
|
|
@Override
|
|
|
|
public void accept(File f) {
|
|
|
|
try {
|
|
|
|
if (f.isDirectory()) {
|
|
|
|
UUID uuid = UUID.fromString(f.getName());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} catch (IllegalArgumentException exception) {}
|
|
|
|
super.accept(f);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if (rel.exists()) allFiles(rel.listFiles(), false, forEachFile);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
File rel = MainUtil.resolveRelative(new File(dir, dirFilter));
|
|
|
|
if (rel.exists()) allFiles(rel.listFiles(), false, forEachFile);
|
|
|
|
}
|
|
|
|
if (!filters.isEmpty() && !toFilter.isEmpty()) {
|
|
|
|
List<File> result = filter(toFilter, filters);
|
|
|
|
for (File file : result) rootFunction.accept(file);
|
|
|
|
}
|
|
|
|
return page;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static List<File> filter(List<File> fileList, List<String> filters) {
|
|
|
|
|
|
|
|
String[] normalizedNames = new String[fileList.size()];
|
|
|
|
for (int i = 0; i < fileList.size(); i++) {
|
|
|
|
String normalized = fileList.get(i).getName().toLowerCase();
|
|
|
|
if (normalized.startsWith("../")) normalized = normalized.substring(3);
|
|
|
|
normalizedNames[i] = normalized.replace("/", File.separator);
|
|
|
|
}
|
2014-07-01 04:56:05 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
for (String filter : filters) {
|
|
|
|
if (fileList.isEmpty()) return fileList;
|
|
|
|
String lowerFilter = filter.toLowerCase().replace("/", File.separator);
|
|
|
|
List<File> newList = new ArrayList<>();
|
2014-07-01 04:56:05 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
for (int i = 0; i < normalizedNames.length; i++) {
|
|
|
|
if (normalizedNames[i].startsWith(lowerFilter)) newList.add(fileList.get(i));
|
|
|
|
}
|
|
|
|
if (newList.isEmpty()) {
|
|
|
|
for (int i = 0; i < normalizedNames.length; i++) {
|
|
|
|
if (normalizedNames[i].contains(lowerFilter)) newList.add(fileList.get(i));
|
2014-07-01 04:56:05 +00:00
|
|
|
}
|
2014-06-27 23:03:29 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
if (newList.isEmpty()) {
|
|
|
|
String checkName = filter.replace("\\", "/").split("/")[0];
|
|
|
|
if (checkName.length() > 3 && checkName.length() <= 16) {
|
|
|
|
UUID fromName = Fawe.imp().getUUID(checkName);
|
|
|
|
if (fromName != null) {
|
|
|
|
lowerFilter = filter.replaceFirst(checkName, fromName.toString()).toLowerCase();
|
|
|
|
for (int i = 0; i < normalizedNames.length; i++) {
|
|
|
|
if (normalizedNames[i].startsWith(lowerFilter)) newList.add(fileList.get(i));
|
|
|
|
}
|
|
|
|
}
|
2014-07-01 04:56:05 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
|
|
|
fileList = newList;
|
|
|
|
}
|
|
|
|
return fileList;
|
|
|
|
}
|
2014-07-01 04:56:05 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
public static void allFiles(File[] files, boolean recursive, Consumer<File> task) {
|
|
|
|
if (files == null || files.length == 0) return;
|
|
|
|
for (File f : files) {
|
|
|
|
if (f.isDirectory()) {
|
|
|
|
if (recursive) {
|
|
|
|
allFiles(f.listFiles(), recursive, task);
|
|
|
|
} else {
|
|
|
|
task.accept(f);
|
|
|
|
}
|
2014-07-01 04:56:05 +00:00
|
|
|
} else {
|
2018-08-12 14:03:07 +00:00
|
|
|
task.accept(f);
|
2014-07-01 04:56:05 +00:00
|
|
|
}
|
2014-06-27 23:03:29 +00:00
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private static String getPath(File root, File file, UUID uuid) {
|
|
|
|
File dir;
|
|
|
|
if (uuid != null) {
|
|
|
|
dir = new File(root, uuid.toString());
|
|
|
|
} else {
|
|
|
|
dir = root;
|
|
|
|
}
|
|
|
|
|
2019-01-31 15:08:58 +00:00
|
|
|
ClipboardFormat format = ClipboardFormats.findByFile(file);
|
2018-08-12 14:03:07 +00:00
|
|
|
URI relative = dir.toURI().relativize(file.toURI());
|
|
|
|
StringBuilder name = new StringBuilder();
|
|
|
|
if (relative.isAbsolute()) {
|
|
|
|
relative = root.toURI().relativize(file.toURI());
|
|
|
|
name.append(".." + File.separator);
|
|
|
|
}
|
|
|
|
name.append(relative.getPath());
|
|
|
|
return name.toString();
|
|
|
|
}
|
2014-06-27 23:03:29 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
public static void help(CommandContext args, WorldEdit we, Actor actor) {
|
|
|
|
help(args, we, actor, "/", null);
|
|
|
|
}
|
2014-07-01 04:56:05 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
@Command(
|
|
|
|
aliases = {"/gui"},
|
|
|
|
desc = "Open the GUI"
|
|
|
|
)
|
|
|
|
@Logging(PLACEMENT)
|
|
|
|
public void gui(Actor actor, FawePlayer fp, LocalSession session, CommandContext args) throws WorldEditException, CommandException {
|
|
|
|
FormBuilder gui = Fawe.imp().getFormBuilder();
|
|
|
|
if (gui == null) throw new CommandException("Only supported on Pocket Edition");
|
2014-07-01 04:56:05 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
Dispatcher callable = worldEdit.getPlatformManager().getCommandManager().getDispatcher();
|
|
|
|
CommandLocals locals = args.getLocals();
|
2014-07-01 04:56:05 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
String prefix = Commands.getAlias(UtilityCommands.class, "/gui");
|
2014-07-01 04:56:05 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
// TODO sort commands by most used
|
2014-07-01 04:56:05 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
new HelpBuilder(callable, args, prefix, Integer.MAX_VALUE) {
|
|
|
|
@Override
|
|
|
|
public void displayFailure(String message) {
|
|
|
|
gui.setTitle("Error");
|
|
|
|
gui.addLabel(message);
|
|
|
|
}
|
2014-07-01 04:56:05 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
@Override
|
|
|
|
public void displayUsage(CommandCallable callable, String commandString) {
|
|
|
|
gui.setTitle(commandString);
|
|
|
|
|
|
|
|
if (callable instanceof Dispatcher) {
|
|
|
|
Dispatcher dispathcer = (Dispatcher) callable;
|
|
|
|
dispathcer.getCommands();
|
|
|
|
gui.addLabel("Dispatcher not implemented for " + commandString);
|
|
|
|
} else {
|
|
|
|
Description cmdDesc = callable.getDescription();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<Parameter> params = cmdDesc.getParameters();
|
|
|
|
String[] suggested = new String[params.size()];
|
|
|
|
if (cmdDesc.getUsage() != null) {
|
|
|
|
String[] usageArgs = cmdDesc.getUsage().split(" ", params.size());
|
|
|
|
for (int i = 0; i < usageArgs.length; i++) {
|
|
|
|
String arg = usageArgs[i];
|
|
|
|
String[] splitSug = arg.split("=");
|
|
|
|
if (splitSug.length == 2) {
|
|
|
|
suggested[i] = splitSug[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = 0 ; i < params.size(); i++) {
|
|
|
|
String[] def = params.get(i).getDefaultValue();
|
|
|
|
if (def != null && def.length != 0) {
|
|
|
|
suggested[i] = def[0];
|
|
|
|
}
|
2014-07-01 04:56:05 +00:00
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
|
|
|
|
String help = cmdDesc.getHelp();
|
|
|
|
if (help == null || help.isEmpty()) help = cmdDesc.getDescription();
|
|
|
|
|
|
|
|
gui.addLabel(BBC.color("&2" + help + "\n"));
|
|
|
|
|
|
|
|
List<String> flags = new ArrayList<>();
|
|
|
|
|
|
|
|
for (int i = 0; i < params.size(); i++) {
|
|
|
|
Parameter param = params.get(i);
|
|
|
|
String name = param.getName();
|
|
|
|
boolean optional = param.isValueFlag() || param.isOptional();
|
|
|
|
String[] def = param.getDefaultValue();
|
|
|
|
|
|
|
|
if (param.getFlag() != null) {
|
|
|
|
flags.add("-" + param.getFlag() + " ");
|
|
|
|
} else {
|
|
|
|
flags.add("");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (param instanceof ParameterData) {
|
|
|
|
ParameterData pd = (ParameterData) param;
|
|
|
|
Type type = pd.getType();
|
|
|
|
String suggestion = suggested[i];
|
|
|
|
|
|
|
|
String color = optional ? "3" : "c";
|
|
|
|
StringBuilder label = new StringBuilder(BBC.color("&" + color + name + ": "));
|
|
|
|
// if (suggested[i] != null) label.append(" e.g. " + suggestion);
|
|
|
|
Range range = MainUtil.getOf(pd.getModifiers(), Range.class);
|
|
|
|
double min = 0;
|
|
|
|
double max = 100;
|
|
|
|
if (range != null) {
|
|
|
|
min = range.min();
|
|
|
|
max = range.max();
|
|
|
|
} else {
|
|
|
|
SuggestedRange suggestedRange = MainUtil.getOf(pd.getModifiers(), SuggestedRange.class);
|
|
|
|
if (suggestedRange != null) {
|
|
|
|
min = suggestedRange.min();
|
|
|
|
max = suggestedRange.max();
|
|
|
|
} else if (name.equalsIgnoreCase("radius") || name.equalsIgnoreCase("size")) {
|
|
|
|
max = WorldEdit.getInstance().getConfiguration().maxBrushRadius;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int step = 1;
|
|
|
|
Step stepSizeAnn = MainUtil.getOf(pd.getModifiers(), Step.class);
|
|
|
|
if (stepSizeAnn != null) {
|
|
|
|
double stepVal = stepSizeAnn.value();
|
|
|
|
step = Math.max(1, (int) stepVal);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
BaseBiome
|
|
|
|
Vector
|
|
|
|
Vector2D
|
|
|
|
*/
|
|
|
|
|
|
|
|
switch (type.getTypeName()) {
|
|
|
|
case "double":
|
|
|
|
case "java.lang.Double": {
|
|
|
|
double value = suggestion != null ? Double.parseDouble(suggestion) : min;
|
|
|
|
gui.addSlider("\n" + label.toString(), min, max, 1, value);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case "int":
|
|
|
|
case "java.lang.Integer": {
|
|
|
|
int value = suggestion != null ? Integer.parseInt(suggestion) : (int) min;
|
|
|
|
gui.addSlider("\n" + label.toString(), min, max, 1, value);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case "boolean":
|
|
|
|
case "java.lang.Boolean": {
|
|
|
|
boolean value = suggestion != null ? Boolean.parseBoolean(suggestion) : false;
|
|
|
|
gui.addToggle(label.toString(), value);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case "com.sk89q.worldedit.patterns.Pattern": {
|
|
|
|
gui.addInput("\n" + label.toString(), "stone", "wood");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case "com.sk89q.worldedit.blocks.BaseBlock": {
|
|
|
|
gui.addInput("\n" + label.toString(), "stone", "wood");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case "com.sk89q.worldedit.function.mask.Mask": {
|
|
|
|
gui.addInput("\n" + label.toString(), "stone", "wood");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
case "java.lang.String": {
|
|
|
|
// TODO
|
|
|
|
// clipboard
|
|
|
|
// schematic
|
|
|
|
// image
|
|
|
|
if (suggestion == null) suggestion = "";
|
|
|
|
gui.addInput("\n" + label.toString(), suggestion, suggestion);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw new UnsupportedOperationException("Unsupported callable: " + callable.getClass() + " | " + param.getClass());
|
|
|
|
}
|
2014-07-01 04:56:05 +00:00
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
|
|
|
|
gui.setResponder(new Consumer<Map<Integer, Object>>() {
|
|
|
|
@Override
|
|
|
|
public void accept(Map<Integer, Object> response) {
|
|
|
|
int index = 0;
|
|
|
|
StringBuilder command = new StringBuilder(commandString);
|
|
|
|
for (Map.Entry<Integer, Object> arg : response.entrySet()) {
|
|
|
|
String argValue = arg.getValue().toString();
|
|
|
|
String flag = flags.get(index);
|
|
|
|
if (!flag.isEmpty()) {
|
|
|
|
if (argValue.equalsIgnoreCase("false")) continue;
|
|
|
|
if (argValue.equalsIgnoreCase("true")) argValue = "";
|
|
|
|
}
|
|
|
|
command.append(" " + flag + argValue);
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
CommandEvent event = new CommandEvent(actor, command.toString());
|
|
|
|
CommandManager.getInstance().handleCommand(event);
|
|
|
|
}
|
|
|
|
});
|
2014-07-01 04:56:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
@Override
|
|
|
|
public void displayCategories(Map<String, Map<CommandMapping, String>> categories) {
|
|
|
|
gui.setTitle(BBC.HELP_HEADER_CATEGORIES.s());
|
|
|
|
List<String> categoryList = new ArrayList<>();
|
|
|
|
for (Map.Entry<String, Map<CommandMapping, String>> categoryEntry : categories.entrySet()) {
|
|
|
|
String category = categoryEntry.getKey();
|
|
|
|
categoryList.add(category);
|
|
|
|
Map<CommandMapping, String> commandMap = categoryEntry.getValue();
|
|
|
|
int size = commandMap.size();
|
|
|
|
|
|
|
|
String plural = size == 1 ? "command" : "commands";
|
|
|
|
gui.addButton(BBC.HELP_ITEM_ALLOWED.f(category, "(" + size + " " + plural + ")"), null);
|
|
|
|
}
|
|
|
|
|
|
|
|
gui.setResponder(new Consumer<Map<Integer, Object>>() {
|
|
|
|
@Override
|
|
|
|
public void accept(Map<Integer, Object> response) {
|
|
|
|
if (response.isEmpty()) {
|
|
|
|
// ??
|
|
|
|
throw new IllegalArgumentException("No response for categories");
|
|
|
|
} else {
|
|
|
|
Map.Entry<Integer, Object> clicked = response.entrySet().iterator().next();
|
|
|
|
String category = categoryList.get(clicked.getKey());
|
|
|
|
String arguments = prefix + " " + category;
|
|
|
|
CommandEvent event = new CommandEvent(actor, arguments);
|
|
|
|
CommandManager.getInstance().handleCommand(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void displayCommands(Map<CommandMapping, String> commandMap, String visited, int page, int pageTotal, int effectiveLength) {
|
|
|
|
gui.setTitle(BBC.HELP_HEADER_SUBCOMMANDS.s());
|
|
|
|
|
|
|
|
String baseCommand = prefix;
|
|
|
|
if (effectiveLength > 0) baseCommand += " " + args.getString(0, effectiveLength - 1);
|
|
|
|
|
|
|
|
CommandLocals locals = args.getLocals();
|
|
|
|
if (!visited.isEmpty()) {
|
|
|
|
visited = visited + " ";
|
|
|
|
}
|
|
|
|
|
|
|
|
List<String> commands = new ArrayList<>();
|
|
|
|
|
|
|
|
for (Map.Entry<CommandMapping, String> cmdEntry : commandMap.entrySet()) {
|
|
|
|
CommandMapping mapping = cmdEntry.getKey();
|
|
|
|
String subPrefix = cmdEntry.getValue();
|
|
|
|
|
|
|
|
StringBuilder helpCmd = new StringBuilder();
|
|
|
|
helpCmd.append(prefix);
|
|
|
|
helpCmd.append(" ");
|
|
|
|
helpCmd.append(subPrefix);
|
|
|
|
CommandCallable c = mapping.getCallable();
|
|
|
|
helpCmd.append(visited);
|
|
|
|
helpCmd.append(mapping.getPrimaryAlias());
|
|
|
|
String s2 = mapping.getDescription().getDescription();
|
|
|
|
if (c.testPermission(locals)) {
|
|
|
|
// gui.addLabel(s2);
|
|
|
|
gui.addButton(helpCmd.toString(), null);
|
|
|
|
commands.add(helpCmd.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gui.setResponder(new Consumer<Map<Integer, Object>>() {
|
|
|
|
@Override
|
|
|
|
public void accept(Map<Integer, Object> response) {
|
|
|
|
if (response.isEmpty()) {
|
|
|
|
// ??
|
|
|
|
throw new IllegalArgumentException("No response for command list: " + prefix);
|
|
|
|
} else {
|
|
|
|
Map.Entry<Integer, Object> clicked = response.entrySet().iterator().next();
|
|
|
|
int index = clicked.getKey();
|
|
|
|
String cmd = commands.get(index);
|
|
|
|
CommandEvent event = new CommandEvent(actor, cmd);
|
|
|
|
CommandManager.getInstance().handleCommand(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}.run();
|
|
|
|
|
|
|
|
gui.display(fp);
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
2014-07-29 18:04:04 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
public static void help(CommandContext args, WorldEdit we, Actor actor, String prefix, CommandCallable callable) {
|
|
|
|
final int perPage = actor instanceof Player ? 12 : 20; // More pages for console
|
|
|
|
|
|
|
|
HelpBuilder builder = new HelpBuilder(callable, args, prefix, perPage) {
|
|
|
|
@Override
|
|
|
|
public void displayFailure(String message) {
|
|
|
|
actor.printError(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void displayUsage(CommandCallable callable, String command) {
|
|
|
|
new UsageMessage(callable, command).send(actor);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void displayCategories(Map<String, Map<CommandMapping, String>> categories) {
|
|
|
|
Message msg = new Message();
|
|
|
|
msg.prefix().text(BBC.HELP_HEADER_CATEGORIES).newline();
|
|
|
|
boolean first = true;
|
|
|
|
for (Map.Entry<String, Map<CommandMapping, String>> entry : categories.entrySet()) {
|
|
|
|
String s1 = Commands.getAlias(UtilityCommands.class, "/help") + " " + entry.getKey();
|
|
|
|
String s2 = entry.getValue().size() + "";
|
|
|
|
msg.text(BBC.HELP_ITEM_ALLOWED, "&a" + s1, s2);
|
|
|
|
msg.tooltip(StringMan.join(entry.getValue().keySet(), ", ", cm -> cm.getPrimaryAlias()));
|
|
|
|
msg.command(s1);
|
|
|
|
msg.newline();
|
|
|
|
}
|
|
|
|
msg.text(BBC.HELP_FOOTER).link("https://git.io/vSKE5").newline();
|
|
|
|
msg.paginate((prefix.equals("/") ? Commands.getAlias(UtilityCommands.class, "/help") : prefix), 0, 1);
|
|
|
|
msg.send(actor);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void displayCommands(Map<CommandMapping, String> commandMap, String visited, int page, int pageTotal, int effectiveLength) {
|
|
|
|
Message msg = new Message();
|
|
|
|
msg.prefix().text(BBC.HELP_HEADER, page + 1, pageTotal).newline();
|
|
|
|
|
|
|
|
CommandLocals locals = args.getLocals();
|
|
|
|
|
|
|
|
if (!visited.isEmpty()) {
|
|
|
|
visited = visited + " ";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add each command
|
|
|
|
for (Map.Entry<CommandMapping, String> cmdEntry : commandMap.entrySet()) {
|
|
|
|
CommandMapping mapping = cmdEntry.getKey();
|
|
|
|
String subPrefix = cmdEntry.getValue();
|
|
|
|
|
|
|
|
StringBuilder s1 = new StringBuilder();
|
|
|
|
s1.append(prefix);
|
|
|
|
s1.append(subPrefix);
|
|
|
|
CommandCallable c = mapping.getCallable();
|
|
|
|
s1.append(visited);
|
|
|
|
s1.append(mapping.getPrimaryAlias());
|
|
|
|
String s2 = mapping.getDescription().getDescription();
|
|
|
|
if (c.testPermission(locals)) {
|
|
|
|
msg.text(BBC.HELP_ITEM_ALLOWED, s1, s2);
|
|
|
|
String helpCmd = (prefix.equals("/") ? Commands.getAlias(UtilityCommands.class, "/help") + " " : "") + s1;
|
|
|
|
msg.cmdTip(helpCmd);
|
|
|
|
msg.newline();
|
|
|
|
} else {
|
|
|
|
msg.text(BBC.HELP_ITEM_DENIED, s1, s2).newline();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (args.argsLength() == 0) {
|
|
|
|
msg.text(BBC.HELP_FOOTER).newline();
|
|
|
|
}
|
|
|
|
String baseCommand = (prefix.equals("/") ? Commands.getAlias(UtilityCommands.class, "/help") : prefix);
|
|
|
|
if (effectiveLength > 0) baseCommand += " " + args.getString(0, effectiveLength - 1);
|
|
|
|
msg.paginate(baseCommand, page + 1, pageTotal);
|
|
|
|
|
|
|
|
msg.send(actor);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
builder.run();
|
|
|
|
}
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|