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
|
|
|
*
|
2020-08-25 01:31:47 +00:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU 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.
|
|
|
|
*
|
2020-08-25 01:31:47 +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 General Public License for more details.
|
2014-04-03 02:08:50 +00:00
|
|
|
*
|
2020-08-25 01:31:47 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <https://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;
|
|
|
|
|
2021-07-01 20:16:25 +00:00
|
|
|
import com.fastasyncworldedit.core.Fawe;
|
|
|
|
import com.fastasyncworldedit.core.configuration.Caption;
|
|
|
|
import com.fastasyncworldedit.core.configuration.Settings;
|
2021-07-23 15:48:51 +00:00
|
|
|
import com.fastasyncworldedit.core.function.QuadFunction;
|
2021-07-01 20:16:25 +00:00
|
|
|
import com.fastasyncworldedit.core.util.MainUtil;
|
2021-09-21 13:59:49 +00:00
|
|
|
import com.fastasyncworldedit.core.util.MaskTraverser;
|
2021-07-16 17:48:21 +00:00
|
|
|
import com.fastasyncworldedit.core.util.TaskManager;
|
2021-07-01 20:16:25 +00:00
|
|
|
import com.fastasyncworldedit.core.util.image.ImageUtil;
|
2021-07-24 15:34:05 +00:00
|
|
|
import com.fastasyncworldedit.core.util.task.DelegateConsumer;
|
2020-01-03 21:05:25 +00:00
|
|
|
import com.google.common.base.Function;
|
2018-12-23 16:19:33 +00:00
|
|
|
import com.sk89q.worldedit.EditSession;
|
2019-07-06 00:46:48 +00:00
|
|
|
import com.sk89q.worldedit.IncompleteRegionException;
|
2018-12-23 16:19:33 +00:00
|
|
|
import com.sk89q.worldedit.LocalConfiguration;
|
|
|
|
import com.sk89q.worldedit.LocalSession;
|
2019-07-06 00:46:48 +00:00
|
|
|
import com.sk89q.worldedit.MaxChangedBlocksException;
|
2018-12-23 16:19:33 +00:00
|
|
|
import com.sk89q.worldedit.WorldEdit;
|
|
|
|
import com.sk89q.worldedit.WorldEditException;
|
2020-12-16 19:23:41 +00:00
|
|
|
import com.sk89q.worldedit.command.argument.HeightConverter;
|
2019-07-06 00:46:48 +00:00
|
|
|
import com.sk89q.worldedit.command.util.CommandPermissions;
|
|
|
|
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
|
2014-07-16 02:47:47 +00:00
|
|
|
import com.sk89q.worldedit.command.util.CreatureButcher;
|
|
|
|
import com.sk89q.worldedit.command.util.EntityRemover;
|
2019-07-06 00:46:48 +00:00
|
|
|
import com.sk89q.worldedit.command.util.Logging;
|
|
|
|
import com.sk89q.worldedit.command.util.PrintCommandHelp;
|
2020-07-14 02:50:59 +00:00
|
|
|
import com.sk89q.worldedit.command.util.WorldEditAsyncCommandBuilder;
|
2014-07-16 02:47:47 +00:00
|
|
|
import com.sk89q.worldedit.entity.Entity;
|
2019-11-20 00:11:54 +00:00
|
|
|
import com.sk89q.worldedit.entity.Player;
|
2014-06-28 00:55:39 +00:00
|
|
|
import com.sk89q.worldedit.extension.platform.Actor;
|
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;
|
2019-07-06 00:46:48 +00:00
|
|
|
import com.sk89q.worldedit.function.EntityFunction;
|
2020-07-14 02:50:59 +00:00
|
|
|
import com.sk89q.worldedit.function.mask.BlockTypeMask;
|
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;
|
2019-11-14 17:25:17 +00:00
|
|
|
import com.sk89q.worldedit.internal.annotation.Direction;
|
2020-12-16 19:23:41 +00:00
|
|
|
import com.sk89q.worldedit.internal.annotation.VertHeight;
|
2019-11-20 00:11:54 +00:00
|
|
|
import com.sk89q.worldedit.internal.expression.EvaluationException;
|
2014-07-03 10:34:19 +00:00
|
|
|
import com.sk89q.worldedit.internal.expression.Expression;
|
|
|
|
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
2018-12-23 16:19:33 +00:00
|
|
|
import com.sk89q.worldedit.math.BlockVector3;
|
2020-12-16 19:23:41 +00:00
|
|
|
import com.sk89q.worldedit.math.Vector2;
|
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;
|
2019-07-06 00:46:48 +00:00
|
|
|
import com.sk89q.worldedit.util.formatting.component.SubtleFormat;
|
2019-10-23 14:35:04 +00:00
|
|
|
import com.sk89q.worldedit.util.formatting.text.Component;
|
2019-07-06 00:46:48 +00:00
|
|
|
import com.sk89q.worldedit.util.formatting.text.TextComponent;
|
|
|
|
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
2014-04-05 09:59:38 +00:00
|
|
|
import com.sk89q.worldedit.world.World;
|
2018-07-30 13:26:06 +00:00
|
|
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
2020-07-14 02:50:59 +00:00
|
|
|
import org.enginehub.piston.annotation.Command;
|
|
|
|
import org.enginehub.piston.annotation.CommandContainer;
|
|
|
|
import org.enginehub.piston.annotation.param.Arg;
|
|
|
|
import org.enginehub.piston.annotation.param.ArgFlag;
|
|
|
|
import org.enginehub.piston.annotation.param.Switch;
|
|
|
|
import org.enginehub.piston.exception.StopExecutionException;
|
|
|
|
|
2021-07-24 15:34:05 +00:00
|
|
|
import javax.imageio.ImageIO;
|
2019-07-06 00:46:48 +00:00
|
|
|
import java.awt.RenderingHints;
|
2018-09-06 20:40:13 +00:00
|
|
|
import java.awt.image.BufferedImage;
|
2018-08-12 14:03:07 +00:00
|
|
|
import java.io.File;
|
2018-09-06 20:40:13 +00:00
|
|
|
import java.io.IOException;
|
2018-08-12 14:03:07 +00:00
|
|
|
import java.net.URI;
|
2018-09-06 20:40:13 +00:00
|
|
|
import java.nio.file.Files;
|
2020-07-14 02:50:59 +00:00
|
|
|
import java.text.DecimalFormat;
|
2019-07-06 00:46:48 +00:00
|
|
|
import java.text.NumberFormat;
|
2020-01-26 18:01:16 +00:00
|
|
|
import java.util.AbstractMap.SimpleEntry;
|
2019-07-06 00:46:48 +00:00
|
|
|
import java.util.ArrayList;
|
2019-10-23 14:35:04 +00:00
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.LinkedList;
|
2018-09-06 20:40:13 +00:00
|
|
|
import java.util.List;
|
2019-07-06 00:46:48 +00:00
|
|
|
import java.util.Locale;
|
2019-10-23 14:35:04 +00:00
|
|
|
import java.util.Map;
|
2019-07-06 00:46:48 +00:00
|
|
|
import java.util.UUID;
|
2018-08-12 14:03:07 +00:00
|
|
|
import java.util.function.Consumer;
|
2019-07-06 00:46:48 +00:00
|
|
|
import java.util.function.Supplier;
|
2020-01-26 18:01:16 +00:00
|
|
|
import java.util.stream.Collectors;
|
2020-07-14 02:50:59 +00:00
|
|
|
|
|
|
|
import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT;
|
2018-08-12 14:03:07 +00:00
|
|
|
|
2014-04-03 02:08:50 +00:00
|
|
|
/**
|
|
|
|
* Utility commands.
|
|
|
|
*/
|
2020-10-05 17:41:41 +00:00
|
|
|
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
|
2019-07-06 00:46:48 +00:00
|
|
|
public class UtilityCommands {
|
2019-06-12 21:12:12 +00:00
|
|
|
|
2019-04-03 11:28:57 +00:00
|
|
|
private final WorldEdit we;
|
|
|
|
|
2014-04-03 02:08:50 +00:00
|
|
|
public UtilityCommands(WorldEdit we) {
|
2019-04-03 11:28:57 +00:00
|
|
|
this.we = we;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
2019-10-30 11:58:21 +00:00
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "/macro",
|
|
|
|
desc = "Generate or run a macro"
|
2019-10-30 11:58:21 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.macro")
|
2021-09-28 14:59:52 +00:00
|
|
|
public void macro(Actor actor, LocalSession session, String name, String argument) throws IOException {
|
2019-10-30 11:58:21 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-04-03 02:08:50 +00:00
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "/heightmapinterface",
|
|
|
|
aliases = {"/hmi", "hmi"},
|
|
|
|
desc = "Generate the heightmap interface: https://github.com/IntellectualSites/HeightMap"
|
2018-09-06 20:40:13 +00:00
|
|
|
)
|
2018-10-04 18:42:43 +00:00
|
|
|
@CommandPermissions("fawe.admin")
|
2021-07-24 15:34:05 +00:00
|
|
|
public void heightmapInterface(
|
2021-09-28 14:59:52 +00:00
|
|
|
Actor actor,
|
2021-07-24 15:34:05 +00:00
|
|
|
@Arg(name = "min", desc = "int", def = "100") int min,
|
|
|
|
@Arg(name = "max", desc = "int", def = "200") int max
|
|
|
|
) throws IOException {
|
2021-09-28 14:59:52 +00:00
|
|
|
actor.print(TextComponent.of("Please wait while we generate the minified heightmaps."));
|
2021-12-22 19:58:23 +00:00
|
|
|
File srcFolder = MainUtil.getFile(Fawe.platform().getDirectory(), Settings.settings().PATHS.HEIGHTMAP);
|
2018-09-06 20:40:13 +00:00
|
|
|
|
2021-12-22 19:58:23 +00:00
|
|
|
File webSrc = new File(Fawe.platform().getDirectory(), "web" + File.separator + "heightmap");
|
2018-09-06 20:40:13 +00:00
|
|
|
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<>();
|
2019-03-28 19:02:37 +00:00
|
|
|
MainUtil.iterateFiles(srcFolder, file -> {
|
2020-10-05 17:41:41 +00:00
|
|
|
switch (file.getName().substring(file.getName().lastIndexOf('.')).toLowerCase(Locale.ROOT)) {
|
2019-03-28 19:02:37 +00:00
|
|
|
case ".png":
|
|
|
|
case ".jpeg":
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
String name = file.getAbsolutePath().substring(sub);
|
2020-10-05 17:41:41 +00:00
|
|
|
if (name.startsWith(File.separator)) {
|
|
|
|
name = name.replaceFirst(java.util.regex.Pattern.quote(File.separator), "");
|
|
|
|
}
|
2019-03-28 19:02:37 +00:00
|
|
|
BufferedImage img = MainUtil.readImage(file);
|
2021-07-24 15:34:05 +00:00
|
|
|
BufferedImage minImg = ImageUtil.getScaledInstance(
|
|
|
|
img,
|
|
|
|
min,
|
|
|
|
min,
|
|
|
|
RenderingHints.VALUE_INTERPOLATION_BILINEAR,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
BufferedImage maxImg = max == -1 ? img : ImageUtil.getScaledInstance(
|
|
|
|
img,
|
|
|
|
max,
|
|
|
|
max,
|
|
|
|
RenderingHints.VALUE_INTERPOLATION_BILINEAR,
|
|
|
|
true
|
|
|
|
);
|
2021-09-28 14:59:52 +00:00
|
|
|
actor.print(TextComponent.of(String.format("Writing %s", name)));
|
2019-03-28 19:02:37 +00:00
|
|
|
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);
|
2018-09-06 20:40:13 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
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");
|
2021-09-28 14:59:52 +00:00
|
|
|
actor.print(TextComponent.of(String.format("Writing %s", configFile)));
|
2018-09-06 20:40:13 +00:00
|
|
|
Files.write(configFile.toPath(), config.toString().getBytes());
|
2021-09-28 14:59:52 +00:00
|
|
|
actor.print(TextComponent.of("Done! See: `FastAsyncWorldEdit/web/heightmap`"));
|
2018-09-06 20:40:13 +00:00
|
|
|
}
|
|
|
|
|
2018-08-24 09:33:52 +00:00
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "/cancel",
|
|
|
|
aliases = {"fcancel"},
|
|
|
|
desc = "Cancel your current command"
|
2018-08-24 09:33:52 +00:00
|
|
|
)
|
2020-01-05 06:35:19 +00:00
|
|
|
@CommandPermissions(value = "fawe.cancel", queued = false)
|
2021-10-04 12:34:40 +00:00
|
|
|
public void cancel(Player player) {
|
|
|
|
int cancelled = player.cancel(false);
|
|
|
|
player.print(Caption.of("fawe.cancel.count", cancelled));
|
2018-08-24 09:33:52 +00:00
|
|
|
}
|
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "/fill",
|
|
|
|
desc = "Fill a hole"
|
2019-11-19 21:23:47 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.fill")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int fill(
|
|
|
|
Actor actor, LocalSession session, EditSession editSession,
|
|
|
|
@Arg(desc = "The blocks to fill with")
|
|
|
|
Pattern pattern,
|
|
|
|
//FAWE start - we take an expression over a double
|
|
|
|
@Arg(desc = "The radius to fill in")
|
|
|
|
Expression radiusExp,
|
|
|
|
//FAWE end
|
|
|
|
@Arg(desc = "The depth to fill", def = "1")
|
|
|
|
int depth,
|
|
|
|
@Arg(desc = "The direction to move", def = "down")
|
|
|
|
@Direction BlockVector3 direction
|
|
|
|
) throws WorldEditException, EvaluationException {
|
2021-07-23 15:48:51 +00:00
|
|
|
//FAWE start
|
2019-08-06 20:18:44 +00:00
|
|
|
double radius = radiusExp.evaluate();
|
2021-07-23 15:48:51 +00:00
|
|
|
//FAWE end
|
2019-07-25 18:44:10 +00:00
|
|
|
radius = Math.max(1, radius);
|
2019-06-12 21:12:12 +00:00
|
|
|
we.checkMaxRadius(radius);
|
2019-07-25 18:44:10 +00:00
|
|
|
depth = Math.max(1, depth);
|
2019-07-06 00:46:48 +00:00
|
|
|
|
2019-09-03 17:40:20 +00:00
|
|
|
BlockVector3 pos = session.getPlacementPosition(actor);
|
2019-07-06 00:46:48 +00:00
|
|
|
int affected = editSession.fillDirection(pos, pattern, radius, depth, direction);
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of("worldedit.fill.created", TextComponent.of(affected)));
|
2019-07-06 00:46:48 +00:00
|
|
|
return affected;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
2019-07-06 00:46:48 +00:00
|
|
|
/*
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
name = "masks",
|
|
|
|
desc = "View help about masks",
|
2019-07-17 05:43:18 +00:00
|
|
|
descFooter = "Masks determine if a block can be placed\n" +
|
2019-07-06 00:46:48 +00:00
|
|
|
" - Use [brackets] for arguments\n" +
|
|
|
|
" - Use , to OR multiple\n" +
|
|
|
|
" - Use & to AND multiple\n" +
|
2019-11-11 21:02:28 +00:00
|
|
|
"e.g., >[stone,dirt],#light[0][5],$jungle\n" +
|
2019-07-06 00:46:48 +00:00
|
|
|
"More Info: https://git.io/v9r4K"
|
|
|
|
)
|
2019-07-18 17:10:04 +00:00
|
|
|
@CommandQueued(false)
|
2019-07-06 00:46:48 +00:00
|
|
|
@CommandPermissions("worldedit.masks")
|
2019-07-18 20:03:27 +00:00
|
|
|
public void masks(Player player, LocalSession session, InjectedValueAccess args) throws WorldEditException {
|
2019-07-06 00:46:48 +00:00
|
|
|
displayModifierHelp(player, DefaultMaskParser.class, args);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
|
|
|
name = "transforms",
|
|
|
|
desc = "View help about transforms",
|
2019-07-17 05:43:18 +00:00
|
|
|
descFooter = "Transforms modify how a block is placed\n" +
|
2019-07-06 00:46:48 +00:00
|
|
|
" - Use [brackets] for arguments\n" +
|
|
|
|
" - Use , to OR multiple\n" +
|
|
|
|
" - Use & to AND multiple\n" +
|
|
|
|
"More Info: https://git.io/v9KHO",
|
|
|
|
)
|
2019-07-18 17:10:04 +00:00
|
|
|
@CommandQueued(false)
|
2019-07-06 00:46:48 +00:00
|
|
|
@CommandPermissions("worldedit.transforms")
|
2019-07-18 20:03:27 +00:00
|
|
|
public void transforms(Player player, LocalSession session, InjectedValueAccess args) throws WorldEditException {
|
2019-07-06 00:46:48 +00:00
|
|
|
displayModifierHelp(player, DefaultTransformParser.class, args);
|
|
|
|
}
|
|
|
|
|
2019-07-18 20:03:27 +00:00
|
|
|
private void displayModifierHelp(Player player, Class<? extends FaweParser> clazz, InjectedValueAccess args) {
|
2019-07-06 00:46:48 +00:00
|
|
|
FaweParser parser = FaweAPI.getParser(clazz);
|
|
|
|
if (args.argsLength() == 0) {
|
|
|
|
String base = getCommand().aliases()[0];
|
|
|
|
UsageMessage msg = new UsageMessage(getCallable(), "/" + 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, player, getCommand().aliases()[0] + " ", parser.getDispatcher());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "/fillr",
|
|
|
|
desc = "Fill a hole recursively"
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.fill.recursive")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int fillr(
|
|
|
|
Actor actor, LocalSession session, EditSession editSession,
|
|
|
|
@Arg(desc = "The blocks to fill with")
|
|
|
|
Pattern pattern,
|
|
|
|
//FAWE start - we take an expression over a double
|
|
|
|
@Arg(desc = "The radius to fill in")
|
|
|
|
Expression radiusExp,
|
|
|
|
//FAWE end
|
|
|
|
@Arg(desc = "The depth to fill", def = "")
|
|
|
|
Integer depth
|
|
|
|
) throws WorldEditException {
|
2021-07-23 15:48:51 +00:00
|
|
|
//FAWE start
|
2019-08-06 20:18:44 +00:00
|
|
|
double radius = radiusExp.evaluate();
|
2021-07-23 15:48:51 +00:00
|
|
|
//FAWE end
|
2019-07-25 18:44:10 +00:00
|
|
|
radius = Math.max(1, radius);
|
2019-07-06 00:46:48 +00:00
|
|
|
we.checkMaxRadius(radius);
|
|
|
|
depth = depth == null ? Integer.MAX_VALUE : Math.max(1, depth);
|
2019-06-12 21:12:12 +00:00
|
|
|
we.checkMaxRadius(radius);
|
2019-07-06 00:46:48 +00:00
|
|
|
|
2019-09-03 17:40:20 +00:00
|
|
|
BlockVector3 pos = session.getPlacementPosition(actor);
|
2019-07-06 00:46:48 +00:00
|
|
|
int affected = editSession.fillXZ(pos, pattern, radius, depth, true);
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of("worldedit.fillr.created", TextComponent.of(affected)));
|
2019-07-06 00:46:48 +00:00
|
|
|
return affected;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "/drain",
|
|
|
|
desc = "Drain a pool"
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.drain")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int drain(
|
|
|
|
Actor actor, LocalSession session, EditSession editSession,
|
|
|
|
//FAWE start - we take an expression over a double
|
|
|
|
@Arg(desc = "The radius to drain")
|
|
|
|
Expression radiusExp,
|
|
|
|
//FAWE end
|
|
|
|
@Switch(name = 'w', desc = "Also un-waterlog blocks")
|
|
|
|
boolean waterlogged,
|
|
|
|
//FAWE start
|
|
|
|
@Switch(name = 'p', desc = "Also remove water plants")
|
|
|
|
boolean plants
|
|
|
|
) throws WorldEditException {
|
|
|
|
//FAWE end
|
2019-08-06 20:18:44 +00:00
|
|
|
double radius = radiusExp.evaluate();
|
2019-07-25 18:44:10 +00:00
|
|
|
radius = Math.max(0, radius);
|
2019-06-12 21:12:12 +00:00
|
|
|
we.checkMaxRadius(radius);
|
2020-07-03 13:01:16 +00:00
|
|
|
int affected = editSession.drainArea(session.getPlacementPosition(actor), radius, waterlogged, plants);
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of("worldedit.drain.drained", TextComponent.of(affected)));
|
2019-07-06 00:46:48 +00:00
|
|
|
return affected;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "fixlava",
|
|
|
|
aliases = {"/fixlava"},
|
|
|
|
desc = "Fix lava to be stationary"
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.fixlava")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int fixLava(
|
|
|
|
Actor actor, LocalSession session, EditSession editSession,
|
|
|
|
@Arg(desc = "The radius to fix in")
|
|
|
|
double radius
|
|
|
|
) throws WorldEditException {
|
2019-07-25 18:44:10 +00:00
|
|
|
radius = Math.max(0, radius);
|
2019-06-12 21:12:12 +00:00
|
|
|
we.checkMaxRadius(radius);
|
2019-09-03 17:40:20 +00:00
|
|
|
int affected = editSession.fixLiquid(session.getPlacementPosition(actor), radius, BlockTypes.LAVA);
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of("worldedit.fixlava.fixed", TextComponent.of(affected)));
|
2019-07-06 00:46:48 +00:00
|
|
|
return affected;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "fixwater",
|
|
|
|
aliases = {"/fixwater"},
|
|
|
|
desc = "Fix water to be stationary"
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.fixwater")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int fixWater(
|
|
|
|
Actor actor, LocalSession session, EditSession editSession,
|
|
|
|
@Arg(desc = "The radius to fix in")
|
|
|
|
double radius
|
|
|
|
) throws WorldEditException {
|
2019-07-23 02:22:32 +00:00
|
|
|
radius = Math.max(0, radius);
|
2019-06-12 21:12:12 +00:00
|
|
|
we.checkMaxRadius(radius);
|
2019-09-03 17:40:20 +00:00
|
|
|
int affected = editSession.fixLiquid(session.getPlacementPosition(actor), radius, BlockTypes.WATER);
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of("worldedit.fixwater.fixed", TextComponent.of(affected)));
|
2019-07-06 00:46:48 +00:00
|
|
|
return affected;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "removeabove",
|
|
|
|
aliases = {"/removeabove"},
|
|
|
|
desc = "Remove blocks above your head."
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.removeabove")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int removeAbove(
|
|
|
|
Actor actor, World world, LocalSession session, EditSession editSession,
|
|
|
|
@Arg(desc = "The apothem of the square to remove from", def = "1")
|
|
|
|
int size,
|
|
|
|
@Arg(desc = "The maximum height above you to remove from", def = "")
|
|
|
|
Integer height
|
|
|
|
) throws WorldEditException {
|
2019-09-03 17:40:20 +00:00
|
|
|
size = Math.max(1, size);
|
|
|
|
we.checkMaxRadius(size);
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2021-09-08 15:39:43 +00:00
|
|
|
height = height != null
|
|
|
|
? Math.min((world.getMaxY() - world.getMinY() + 1), height + 1)
|
|
|
|
: (world.getMaxY() - world.getMinY() + 1);
|
2019-09-03 17:40:20 +00:00
|
|
|
int affected = editSession.removeAbove(session.getPlacementPosition(actor), size, height);
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of("worldedit.removeabove.removed", TextComponent.of(affected)));
|
2019-07-06 00:46:48 +00:00
|
|
|
return affected;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "removebelow",
|
|
|
|
aliases = {"/removebelow"},
|
|
|
|
desc = "Remove blocks below you."
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.removebelow")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int removeBelow(
|
|
|
|
Actor actor, World world, LocalSession session, EditSession editSession,
|
|
|
|
@Arg(desc = "The apothem of the square to remove from", def = "1")
|
|
|
|
int size,
|
|
|
|
@Arg(desc = "The maximum height below you to remove from", def = "")
|
|
|
|
Integer height
|
|
|
|
) throws WorldEditException {
|
2019-09-03 17:40:20 +00:00
|
|
|
size = Math.max(1, size);
|
|
|
|
we.checkMaxRadius(size);
|
2019-07-06 00:46:48 +00:00
|
|
|
|
2021-09-08 15:39:43 +00:00
|
|
|
height = height != null
|
|
|
|
? Math.min((world.getMaxY() - world.getMinY() + 1), height + 1)
|
|
|
|
: (world.getMaxY() - world.getMinY() + 1);
|
2019-09-03 17:40:20 +00:00
|
|
|
int affected = editSession.removeBelow(session.getPlacementPosition(actor), size, height);
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of("worldedit.removebelow.removed", TextComponent.of(affected)));
|
2019-07-06 00:46:48 +00:00
|
|
|
return affected;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "removenear",
|
|
|
|
aliases = {"/removenear"},
|
|
|
|
desc = "Remove blocks near you."
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.removenear")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int removeNear(
|
|
|
|
Actor actor, LocalSession session, EditSession editSession,
|
|
|
|
@Arg(desc = "The mask of blocks to remove")
|
|
|
|
Mask mask,
|
|
|
|
@Arg(desc = "The radius of the square to remove from", def = "50")
|
|
|
|
int radius
|
|
|
|
) throws WorldEditException {
|
2021-07-24 14:47:22 +00:00
|
|
|
//FAWE start > the mask will have been initialised with a WorldWrapper extent (very bad/slow)
|
2021-09-21 13:59:49 +00:00
|
|
|
new MaskTraverser(mask).setNewExtent(editSession);
|
2021-07-24 14:47:22 +00:00
|
|
|
//FAWE end
|
2019-07-25 18:44:10 +00:00
|
|
|
radius = Math.max(1, radius);
|
2019-07-06 00:46:48 +00:00
|
|
|
we.checkMaxRadius(radius);
|
2019-06-12 21:12:12 +00:00
|
|
|
|
2019-09-03 17:40:20 +00:00
|
|
|
int affected = editSession.removeNear(session.getPlacementPosition(actor), mask, radius);
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of("worldedit.removenear.removed", TextComponent.of(affected)));
|
2019-07-06 00:46:48 +00:00
|
|
|
return affected;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "replacenear",
|
|
|
|
aliases = {"/replacenear"},
|
|
|
|
desc = "Replace nearby blocks"
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.replacenear")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int replaceNear(
|
|
|
|
Actor actor, World world, LocalSession session, EditSession editSession,
|
|
|
|
@Arg(desc = "The radius of the square to remove in")
|
|
|
|
int radius,
|
|
|
|
@Arg(desc = "The mask matching blocks to remove", def = "")
|
|
|
|
Mask from,
|
|
|
|
@Arg(desc = "The pattern of blocks to replace with")
|
|
|
|
Pattern to
|
|
|
|
) throws WorldEditException {
|
2021-07-24 14:47:22 +00:00
|
|
|
//FAWE start > the mask will have been initialised with a WorldWrapper extent (very bad/slow)
|
2021-09-21 13:59:49 +00:00
|
|
|
new MaskTraverser(from).setNewExtent(editSession);
|
2021-07-24 14:47:22 +00:00
|
|
|
//FAWE end
|
2019-07-25 18:44:10 +00:00
|
|
|
radius = Math.max(1, radius);
|
2019-07-06 00:46:48 +00:00
|
|
|
we.checkMaxRadius(radius);
|
|
|
|
|
2019-09-03 17:40:20 +00:00
|
|
|
BlockVector3 base = session.getPlacementPosition(actor);
|
2019-07-06 00:46:48 +00:00
|
|
|
BlockVector3 min = base.subtract(radius, radius, radius);
|
|
|
|
BlockVector3 max = base.add(radius, radius, radius);
|
2019-09-03 17:40:20 +00:00
|
|
|
Region region = new CuboidRegion(world, min, max);
|
2019-06-12 21:12:12 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
if (from == null) {
|
|
|
|
from = new ExistingBlockMask(editSession);
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
2019-07-06 00:46:48 +00:00
|
|
|
int affected = editSession.replaceBlocks(region, from, to);
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of("worldedit.replacenear.replaced", TextComponent.of(affected)));
|
2019-07-06 00:46:48 +00:00
|
|
|
return affected;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
2020-12-16 19:23:41 +00:00
|
|
|
|
2014-04-03 02:08:50 +00:00
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "snow",
|
|
|
|
aliases = {"/snow"},
|
|
|
|
desc = "Simulates snow"
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.snow")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int snow(
|
|
|
|
Actor actor, LocalSession session, EditSession editSession,
|
|
|
|
@Arg(desc = "The radius of the cylinder to snow in", def = "10")
|
|
|
|
double size,
|
|
|
|
@Arg(
|
|
|
|
desc = "The height of the cylinder to snow in",
|
|
|
|
def = HeightConverter.DEFAULT_VALUE
|
|
|
|
)
|
|
|
|
@VertHeight
|
|
|
|
int height,
|
|
|
|
@Switch(name = 's', desc = "Stack snow layers")
|
|
|
|
boolean stack
|
|
|
|
) throws WorldEditException {
|
2019-09-03 17:40:20 +00:00
|
|
|
size = Math.max(1, size);
|
2020-12-16 19:23:41 +00:00
|
|
|
height = Math.max(1, height);
|
2019-09-03 17:40:20 +00:00
|
|
|
we.checkMaxRadius(size);
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2020-12-16 19:23:41 +00:00
|
|
|
BlockVector3 position = session.getPlacementPosition(actor);
|
|
|
|
|
2021-07-24 15:34:05 +00:00
|
|
|
CylinderRegion region = new CylinderRegion(
|
|
|
|
position,
|
|
|
|
Vector2.at(size, size),
|
|
|
|
position.getBlockY() - height,
|
|
|
|
position.getBlockY() + height
|
|
|
|
);
|
2020-12-16 19:23:41 +00:00
|
|
|
int affected = editSession.simulateSnow(region, stack);
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of(
|
2021-07-24 15:34:05 +00:00
|
|
|
"worldedit.snow.created", TextComponent.of(affected)
|
2020-12-16 19:23:41 +00:00
|
|
|
));
|
2019-07-06 00:46:48 +00:00
|
|
|
return affected;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "thaw",
|
|
|
|
aliases = {"/thaw"},
|
|
|
|
desc = "Thaws the area"
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.thaw")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int thaw(
|
|
|
|
Actor actor, LocalSession session, EditSession editSession,
|
|
|
|
@Arg(desc = "The radius of the cylinder to thaw in", def = "10")
|
|
|
|
double size,
|
|
|
|
@Arg(
|
|
|
|
desc = "The height of the cylinder to thaw in",
|
|
|
|
def = HeightConverter.DEFAULT_VALUE
|
|
|
|
)
|
|
|
|
@VertHeight
|
|
|
|
int height
|
|
|
|
) throws WorldEditException {
|
2019-09-03 17:40:20 +00:00
|
|
|
size = Math.max(1, size);
|
2020-12-16 19:23:41 +00:00
|
|
|
height = Math.max(1, height);
|
2019-09-03 17:40:20 +00:00
|
|
|
we.checkMaxRadius(size);
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2020-12-16 19:23:41 +00:00
|
|
|
int affected = editSession.thaw(session.getPlacementPosition(actor), size, height);
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of(
|
2021-07-24 15:34:05 +00:00
|
|
|
"worldedit.thaw.removed", TextComponent.of(affected)
|
2020-12-16 19:23:41 +00:00
|
|
|
));
|
2019-07-06 00:46:48 +00:00
|
|
|
return affected;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "green",
|
|
|
|
aliases = {"/green"},
|
|
|
|
desc = "Converts dirt to grass blocks in the area"
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.green")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int green(
|
|
|
|
Actor actor, LocalSession session, EditSession editSession,
|
|
|
|
@Arg(desc = "The radius of the cylinder to convert in", def = "10")
|
|
|
|
double size,
|
|
|
|
@Arg(
|
|
|
|
desc = "The height of the cylinder to convert in",
|
|
|
|
def = HeightConverter.DEFAULT_VALUE
|
|
|
|
)
|
|
|
|
@VertHeight
|
|
|
|
int height,
|
|
|
|
@Switch(name = 'f', desc = "Also convert coarse dirt")
|
|
|
|
boolean convertCoarse
|
|
|
|
) throws WorldEditException {
|
2019-09-03 17:40:20 +00:00
|
|
|
size = Math.max(1, size);
|
2020-12-16 19:23:41 +00:00
|
|
|
height = Math.max(1, height);
|
2019-09-03 17:40:20 +00:00
|
|
|
we.checkMaxRadius(size);
|
2019-07-06 00:46:48 +00:00
|
|
|
final boolean onlyNormalDirt = !convertCoarse;
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2020-12-16 19:23:41 +00:00
|
|
|
final int affected = editSession.green(
|
2021-07-24 15:34:05 +00:00
|
|
|
session.getPlacementPosition(actor), size, height, onlyNormalDirt
|
2020-12-16 19:23:41 +00:00
|
|
|
);
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of(
|
2021-07-24 15:34:05 +00:00
|
|
|
"worldedit.green.changed", TextComponent.of(affected)
|
2020-12-16 19:23:41 +00:00
|
|
|
));
|
2019-07-06 00:46:48 +00:00
|
|
|
return affected;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "extinguish",
|
|
|
|
aliases = {"/ex", "/ext", "/extinguish", "ex", "ext"},
|
|
|
|
desc = "Extinguish nearby fire"
|
2019-07-06 00:46:48 +00:00
|
|
|
)
|
2014-04-03 02:08:50 +00:00
|
|
|
@CommandPermissions("worldedit.extinguish")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int extinguish(
|
|
|
|
Actor actor, LocalSession session, EditSession editSession,
|
|
|
|
@Arg(desc = "The radius of the square to remove in", def = "")
|
|
|
|
Integer radius
|
|
|
|
) throws WorldEditException {
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2019-06-12 21:12:12 +00:00
|
|
|
LocalConfiguration config = we.getConfiguration();
|
2014-04-03 02:08:50 +00:00
|
|
|
|
|
|
|
int defaultRadius = config.maxRadius != -1 ? Math.min(40, config.maxRadius) : 40;
|
2019-07-25 18:44:10 +00:00
|
|
|
int size = radius != null ? Math.max(1, radius) : defaultRadius;
|
2019-06-12 21:12:12 +00:00
|
|
|
we.checkMaxRadius(size);
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2019-04-26 02:36:22 +00:00
|
|
|
Mask mask = new BlockTypeMask(editSession, BlockTypes.FIRE);
|
2019-09-03 17:40:20 +00:00
|
|
|
int affected = editSession.removeNear(session.getPlacementPosition(actor), mask, size);
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of("worldedit.extinguish.removed", TextComponent.of(affected)));
|
2019-10-13 11:47:26 +00:00
|
|
|
return affected;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "butcher",
|
|
|
|
aliases = {"/butcher"},
|
|
|
|
desc = "Kill all or nearby mobs"
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.butcher")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int butcher(
|
|
|
|
Actor actor,
|
|
|
|
@Arg(desc = "Radius to kill mobs in", def = "")
|
|
|
|
Integer radius,
|
|
|
|
@Switch(name = 'p', desc = "Also kill pets")
|
|
|
|
boolean killPets,
|
|
|
|
@Switch(name = 'n', desc = "Also kill NPCs")
|
|
|
|
boolean killNpcs,
|
|
|
|
@Switch(name = 'g', desc = "Also kill golems")
|
|
|
|
boolean killGolems,
|
|
|
|
@Switch(name = 'a', desc = "Also kill animals")
|
|
|
|
boolean killAnimals,
|
|
|
|
@Switch(name = 'b', desc = "Also kill ambient mobs")
|
|
|
|
boolean killAmbient,
|
|
|
|
@Switch(name = 't', desc = "Also kill mobs with name tags")
|
|
|
|
boolean killWithName,
|
|
|
|
@Switch(name = 'f', desc = "Also kill all friendly mobs (Applies the flags `-abgnpt`)")
|
|
|
|
boolean killFriendly,
|
|
|
|
@Switch(name = 'r', desc = "Also destroy armor stands")
|
|
|
|
boolean killArmorStands,
|
|
|
|
@Switch(name = 'w', desc = "Also kill water mobs")
|
|
|
|
boolean killWater
|
|
|
|
) throws WorldEditException {
|
2019-06-12 21:12:12 +00:00
|
|
|
LocalConfiguration config = we.getConfiguration();
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2019-07-06 00:46:48 +00:00
|
|
|
if (radius == null) {
|
|
|
|
radius = config.butcherDefaultRadius;
|
|
|
|
} else if (radius < -1) {
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of("worldedit.butcher.explain-all"));
|
2019-07-06 00:46:48 +00:00
|
|
|
return 0;
|
|
|
|
} else if (radius == -1) {
|
|
|
|
if (config.butcherMaxRadius != -1) {
|
|
|
|
radius = config.butcherMaxRadius;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
}
|
2019-07-06 00:46:48 +00:00
|
|
|
if (config.butcherMaxRadius != -1) {
|
|
|
|
radius = Math.min(radius, config.butcherMaxRadius);
|
|
|
|
}
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2014-07-16 02:47:47 +00:00
|
|
|
CreatureButcher flags = new CreatureButcher(actor);
|
2021-07-24 15:34:05 +00:00
|
|
|
flags.or(
|
|
|
|
CreatureButcher.Flags.FRIENDLY,
|
|
|
|
killFriendly
|
|
|
|
); // No permission check here. Flags will instead be filtered by the subsequent calls.
|
2019-07-06 00:46:48 +00:00
|
|
|
flags.or(CreatureButcher.Flags.PETS, killPets, "worldedit.butcher.pets");
|
|
|
|
flags.or(CreatureButcher.Flags.NPCS, killNpcs, "worldedit.butcher.npcs");
|
|
|
|
flags.or(CreatureButcher.Flags.GOLEMS, killGolems, "worldedit.butcher.golems");
|
|
|
|
flags.or(CreatureButcher.Flags.ANIMALS, killAnimals, "worldedit.butcher.animals");
|
|
|
|
flags.or(CreatureButcher.Flags.AMBIENT, killAmbient, "worldedit.butcher.ambient");
|
|
|
|
flags.or(CreatureButcher.Flags.TAGGED, killWithName, "worldedit.butcher.tagged");
|
|
|
|
flags.or(CreatureButcher.Flags.ARMOR_STAND, killArmorStands, "worldedit.butcher.armorstands");
|
2020-11-13 20:46:11 +00:00
|
|
|
flags.or(CreatureButcher.Flags.WATER, killWater, "worldedit.butcher.water");
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2021-07-23 15:48:51 +00:00
|
|
|
//FAWE start - run this sync
|
2021-07-16 17:48:21 +00:00
|
|
|
int finalRadius = radius;
|
2021-12-22 19:58:23 +00:00
|
|
|
int killed = TaskManager.taskManager().sync(() -> killMatchingEntities(finalRadius, actor, flags::createFunction));
|
2021-07-23 15:48:51 +00:00
|
|
|
//FAWE end
|
2014-07-16 02:47:47 +00:00
|
|
|
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of(
|
2019-10-27 05:29:40 +00:00
|
|
|
"worldedit.butcher.killed",
|
2019-10-13 11:47:26 +00:00
|
|
|
TextComponent.of(killed),
|
|
|
|
TextComponent.of(radius)
|
|
|
|
));
|
2014-04-03 02:08:50 +00:00
|
|
|
|
2019-07-06 00:46:48 +00:00
|
|
|
return killed;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "remove",
|
|
|
|
aliases = {"rem", "rement", "/remove", "/rem", "/rement"},
|
|
|
|
desc = "Remove all entities of a type"
|
2014-04-03 02:08:50 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.remove")
|
|
|
|
@Logging(PLACEMENT)
|
2021-07-24 15:34:05 +00:00
|
|
|
public int remove(
|
|
|
|
Actor actor,
|
|
|
|
@Arg(desc = "The type of entity to remove")
|
|
|
|
EntityRemover remover,
|
|
|
|
@Arg(desc = "The radius of the cuboid to remove from")
|
|
|
|
int radius
|
|
|
|
) throws WorldEditException {
|
2014-04-03 02:08:50 +00:00
|
|
|
if (radius < -1) {
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of("worldedit.remove.explain-all"));
|
2019-07-06 00:46:48 +00:00
|
|
|
return 0;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
2021-07-23 15:48:51 +00:00
|
|
|
//FAWE start - run this sync
|
2021-12-22 19:58:23 +00:00
|
|
|
int removed = TaskManager.taskManager().sync(() -> killMatchingEntities(radius, actor, remover::createFunction));
|
2021-07-23 15:48:51 +00:00
|
|
|
//FAWE end
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of("worldedit.remove.removed", TextComponent.of(removed)));
|
2019-07-06 00:46:48 +00:00
|
|
|
return removed;
|
|
|
|
}
|
2014-07-16 02:47:47 +00:00
|
|
|
|
2020-01-03 17:02:18 +00:00
|
|
|
private int killMatchingEntities(Integer radius, Actor actor, Supplier<EntityFunction> func) throws IncompleteRegionException,
|
2020-02-06 21:33:31 +00:00
|
|
|
MaxChangedBlocksException {
|
2020-01-03 17:02:18 +00:00
|
|
|
List<EntityVisitor> visitors = new ArrayList<>();
|
|
|
|
|
|
|
|
LocalSession session = we.getSessionManager().get(actor);
|
|
|
|
BlockVector3 center = session.getPlacementPosition(actor);
|
|
|
|
EditSession editSession = session.createEditSession(actor);
|
|
|
|
List<? extends Entity> entities;
|
|
|
|
if (radius >= 0) {
|
|
|
|
CylinderRegion region = CylinderRegion.createRadius(editSession, center, radius);
|
|
|
|
entities = editSession.getEntities(region);
|
|
|
|
} else {
|
|
|
|
entities = editSession.getEntities();
|
|
|
|
}
|
|
|
|
visitors.add(new EntityVisitor(entities.iterator(), func.get()));
|
|
|
|
|
|
|
|
int killed = 0;
|
|
|
|
for (EntityVisitor visitor : visitors) {
|
|
|
|
Operations.completeLegacy(visitor);
|
|
|
|
killed += visitor.getAffected();
|
|
|
|
}
|
|
|
|
|
|
|
|
session.remember(editSession);
|
2021-07-23 15:48:51 +00:00
|
|
|
editSession.close();
|
2020-01-03 17:02:18 +00:00
|
|
|
return killed;
|
|
|
|
}
|
|
|
|
|
2019-10-13 11:47:26 +00:00
|
|
|
private DecimalFormat formatForLocale(Locale locale) {
|
|
|
|
DecimalFormat format = (DecimalFormat) NumberFormat.getInstance(locale);
|
|
|
|
format.applyPattern("#,##0.#####");
|
|
|
|
return format;
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|
|
|
|
|
2014-07-03 10:34:19 +00:00
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "/calculate",
|
|
|
|
aliases = {"/calc", "/eval", "/evaluate", "/solve"},
|
|
|
|
desc = "Evaluate a mathematical expression"
|
2014-07-03 10:34:19 +00:00
|
|
|
)
|
2015-12-21 21:14:44 +00:00
|
|
|
@CommandPermissions("worldedit.calc")
|
2021-07-24 15:34:05 +00:00
|
|
|
public void calc(
|
|
|
|
Actor actor,
|
|
|
|
@Arg(desc = "Expression to evaluate", variable = true)
|
|
|
|
List<String> input
|
|
|
|
) {
|
2019-07-06 00:46:48 +00:00
|
|
|
Expression expression;
|
2014-07-03 10:34:19 +00:00
|
|
|
try {
|
2019-07-06 00:46:48 +00:00
|
|
|
expression = Expression.compile(String.join(" ", input));
|
2014-07-03 10:34:19 +00:00
|
|
|
} catch (ExpressionException e) {
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of(
|
2020-11-13 21:35:53 +00:00
|
|
|
"worldedit.calc.invalid.with-error",
|
|
|
|
TextComponent.of(String.join(" ", input)),
|
|
|
|
TextComponent.of(e.getMessage())
|
|
|
|
));
|
2019-07-06 00:46:48 +00:00
|
|
|
return;
|
2014-07-03 10:34:19 +00:00
|
|
|
}
|
2019-06-13 14:17:37 +00:00
|
|
|
WorldEditAsyncCommandBuilder.createAndSendMessage(actor, () -> {
|
|
|
|
double result = expression.evaluate(
|
|
|
|
new double[]{}, WorldEdit.getInstance().getSessionManager().get(actor).getTimeout());
|
2019-10-13 11:47:26 +00:00
|
|
|
String formatted = Double.isNaN(result) ? "NaN" : formatForLocale(actor.getLocale()).format(result);
|
2020-01-03 17:02:18 +00:00
|
|
|
return SubtleFormat.wrap(input + " = ").append(TextComponent.of(formatted, TextColor.LIGHT_PURPLE));
|
2019-11-16 12:37:14 +00:00
|
|
|
}, (Component) null);
|
2014-07-03 10:34:19 +00:00
|
|
|
}
|
|
|
|
|
2020-02-06 21:33:31 +00:00
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "/help",
|
|
|
|
desc = "Displays help for WorldEdit commands"
|
2020-02-06 21:33:31 +00:00
|
|
|
)
|
|
|
|
@CommandPermissions("worldedit.help")
|
2021-07-24 15:34:05 +00:00
|
|
|
public void help(
|
|
|
|
Actor actor,
|
|
|
|
@Switch(name = 's', desc = "List sub-commands of the given command, if applicable")
|
|
|
|
boolean listSubCommands,
|
|
|
|
@ArgFlag(name = 'p', desc = "The page to retrieve", def = "1")
|
|
|
|
int page,
|
|
|
|
@Arg(desc = "The command to retrieve help for", def = "", variable = true)
|
|
|
|
List<String> command
|
|
|
|
) throws WorldEditException {
|
2020-02-06 21:33:31 +00:00
|
|
|
PrintCommandHelp.help(command, page, listSubCommands,
|
2021-07-24 15:34:05 +00:00
|
|
|
we.getPlatformManager().getPlatformCommandManager().getCommandManager(), actor, "//help"
|
|
|
|
);
|
2020-02-06 21:33:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-07-23 15:48:51 +00:00
|
|
|
//FAWE start
|
2014-04-03 02:08:50 +00:00
|
|
|
@Command(
|
2021-07-24 15:34:05 +00:00
|
|
|
name = "/confirm",
|
|
|
|
desc = "Confirm a command"
|
2018-08-12 14:03:07 +00:00
|
|
|
)
|
2020-01-05 06:35:19 +00:00
|
|
|
@CommandPermissions(value = "fawe.confirm", queued = false)
|
2021-09-28 14:59:52 +00:00
|
|
|
public void confirm(Actor actor) throws WorldEditException {
|
|
|
|
if (!actor.confirm()) {
|
|
|
|
actor.print(Caption.of("fawe.worldedit.utility.nothing.confirmed"));
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-23 14:35:04 +00:00
|
|
|
public static List<Map.Entry<URI, String>> filesToEntry(final File root, final List<File> files, final UUID uuid) {
|
2020-01-26 18:01:16 +00:00
|
|
|
return files.stream()
|
2021-07-24 15:34:05 +00:00
|
|
|
.map(input -> { // Keep this functional, as transform is evaluated lazily
|
|
|
|
URI uri = input.toURI();
|
|
|
|
String path = getPath(root, input, uuid);
|
|
|
|
return new SimpleEntry<>(uri, path);
|
|
|
|
}).collect(Collectors.toList());
|
2019-10-23 14:35:04 +00:00
|
|
|
}
|
|
|
|
|
2021-07-24 15:34:05 +00:00
|
|
|
public enum URIType {
|
2019-10-23 14:35:04 +00:00
|
|
|
URL,
|
|
|
|
FILE,
|
|
|
|
DIRECTORY,
|
|
|
|
OTHER
|
|
|
|
}
|
|
|
|
|
2021-07-24 15:34:05 +00:00
|
|
|
public static List<Component> entryToComponent(
|
|
|
|
File root,
|
|
|
|
List<Map.Entry<URI, String>> entries,
|
|
|
|
Function<URI, Boolean> isLoaded,
|
|
|
|
QuadFunction<String, String, URIType, Boolean, Component> adapter
|
|
|
|
) {
|
2020-01-26 18:01:16 +00:00
|
|
|
return entries.stream().map(input -> {
|
2019-10-23 14:35:04 +00:00
|
|
|
URI uri = input.getKey();
|
|
|
|
String path = input.getValue();
|
|
|
|
|
|
|
|
boolean url = false;
|
|
|
|
boolean loaded = isLoaded.apply(uri);
|
|
|
|
|
|
|
|
URIType type = URIType.FILE;
|
|
|
|
|
|
|
|
String name = path;
|
|
|
|
String uriStr = uri.toString();
|
|
|
|
if (uriStr.startsWith("file:/")) {
|
|
|
|
File file = new File(uri.getPath());
|
|
|
|
name = file.getName();
|
|
|
|
if (file.isDirectory()) {
|
|
|
|
type = URIType.DIRECTORY;
|
|
|
|
} else {
|
2020-10-05 17:41:41 +00:00
|
|
|
if (name.indexOf('.') != -1) {
|
2020-01-26 18:01:16 +00:00
|
|
|
name = name.substring(0, name.lastIndexOf('.'));
|
2020-10-05 17:41:41 +00:00
|
|
|
}
|
2019-07-25 18:44:10 +00:00
|
|
|
}
|
2019-10-23 14:35:04 +00:00
|
|
|
try {
|
|
|
|
if (!MainUtil.isInSubDirectory(root, file)) {
|
2020-01-26 18:01:16 +00:00
|
|
|
throw new RuntimeException(
|
2021-07-24 15:34:05 +00:00
|
|
|
new StopExecutionException(TextComponent.of("Invalid path")));
|
2019-10-23 14:35:04 +00:00
|
|
|
}
|
2020-10-05 17:41:41 +00:00
|
|
|
} catch (IOException ignored) {
|
2019-10-23 14:35:04 +00:00
|
|
|
}
|
|
|
|
} else if (uriStr.startsWith("http://") || uriStr.startsWith("https://")) {
|
|
|
|
type = URIType.URL;
|
|
|
|
} else {
|
|
|
|
type = URIType.OTHER;
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
2019-10-23 14:35:04 +00:00
|
|
|
|
|
|
|
return adapter.apply(name, path, type, loaded);
|
2020-01-26 18:01:16 +00:00
|
|
|
}).collect(Collectors.toList());
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
2014-07-01 04:56:05 +00:00
|
|
|
|
2021-07-24 15:34:05 +00:00
|
|
|
public static List<File> getFiles(
|
|
|
|
File dir,
|
|
|
|
Actor actor,
|
|
|
|
List<String> args,
|
|
|
|
String formatName,
|
|
|
|
boolean playerFolder,
|
|
|
|
boolean oldFirst,
|
|
|
|
boolean newFirst
|
|
|
|
) {
|
2019-10-23 14:35:04 +00:00
|
|
|
List<File> fileList = new LinkedList<>();
|
|
|
|
getFiles(dir, actor, args, formatName, playerFolder, fileList::add);
|
2014-07-01 04:56:05 +00:00
|
|
|
|
2018-08-12 14:03:07 +00:00
|
|
|
if (fileList.isEmpty()) {
|
2021-04-05 17:54:49 +00:00
|
|
|
actor.print(Caption.of("fawe.worldedit.schematic.schematic.none"));
|
2019-10-23 14:35:04 +00:00
|
|
|
return Collections.emptyList();
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
|
|
|
|
2019-07-28 19:26:44 +00:00
|
|
|
final int sortType = oldFirst ? -1 : newFirst ? 1 : 0;
|
2018-08-12 14:03:07 +00:00
|
|
|
// cleanup file list
|
2019-03-28 19:02:37 +00:00
|
|
|
fileList.sort((f1, f2) -> {
|
|
|
|
boolean dir1 = f1.isDirectory();
|
|
|
|
boolean dir2 = f2.isDirectory();
|
2020-10-05 17:41:41 +00:00
|
|
|
if (dir1 != dir2) {
|
2019-03-28 19:02:37 +00:00
|
|
|
return dir1 ? -1 : 1;
|
2020-10-05 17:41:41 +00:00
|
|
|
}
|
2019-03-28 19:02:37 +00:00
|
|
|
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
|
|
|
}
|
2019-03-28 19:02:37 +00:00
|
|
|
} else {
|
|
|
|
res = Long.compare(f1.lastModified(), f2.lastModified()); // use date if there is a flag
|
2020-10-05 17:41:41 +00:00
|
|
|
if (sortType == 1) {
|
2019-03-28 19:02:37 +00:00
|
|
|
res = -res; // flip date for newest first instead of oldest first
|
2020-10-05 17:41:41 +00:00
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
2019-03-28 19:02:37 +00:00
|
|
|
return res;
|
2018-08-12 14:03:07 +00:00
|
|
|
});
|
|
|
|
|
2019-10-23 14:35:04 +00:00
|
|
|
return fileList;
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
|
|
|
|
2021-07-24 15:34:05 +00:00
|
|
|
public static void getFiles(
|
|
|
|
File dir,
|
|
|
|
Actor actor,
|
|
|
|
List<String> args,
|
|
|
|
String formatName,
|
|
|
|
boolean playerFolder,
|
|
|
|
Consumer<File> forEachFile
|
|
|
|
) {
|
2018-08-12 14:03:07 +00:00
|
|
|
Consumer<File> rootFunction = forEachFile;
|
2019-07-20 05:32:15 +00:00
|
|
|
//schem list all <path>
|
2018-08-12 14:03:07 +00:00
|
|
|
|
2019-07-28 19:26:44 +00:00
|
|
|
int len = args.size();
|
2018-08-12 14:03:07 +00:00
|
|
|
List<String> filters = new ArrayList<>();
|
|
|
|
|
|
|
|
String dirFilter = File.separator;
|
|
|
|
|
|
|
|
boolean listMine = false;
|
2021-12-22 19:58:23 +00:00
|
|
|
boolean listGlobal = !Settings.settings().PATHS.PER_PLAYER_SCHEMATICS;
|
2018-08-12 14:03:07 +00:00
|
|
|
if (len > 0) {
|
2020-01-26 18:01:16 +00:00
|
|
|
for (String arg : args) {
|
2020-10-05 17:41:41 +00:00
|
|
|
switch (arg.toLowerCase(Locale.ROOT)) {
|
2018-08-12 14:03:07 +00:00
|
|
|
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;
|
2020-01-26 18:01:16 +00:00
|
|
|
boolean exists =
|
2021-07-24 15:34:05 +00:00
|
|
|
new File(dir, newDirFilter).exists() || playerFolder && MainUtil
|
|
|
|
.resolveRelative(
|
|
|
|
new File(dir, actor.getUniqueId() + newDirFilter)).exists();
|
2018-08-12 14:03:07 +00:00
|
|
|
if (!exists) {
|
|
|
|
arg = arg.substring(0, arg.length() - File.separator.length());
|
|
|
|
if (arg.length() > 3 && arg.length() <= 16) {
|
2021-12-22 19:58:23 +00:00
|
|
|
UUID fromName = Fawe.platform().getUUID(arg);
|
2018-08-12 14:03:07 +00:00
|
|
|
if (fromName != null) {
|
|
|
|
newDirFilter = dirFilter + fromName + File.separator;
|
|
|
|
listGlobal = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dirFilter = newDirFilter;
|
2020-01-26 18:01:16 +00:00
|
|
|
} else {
|
2018-08-12 14:03:07 +00:00
|
|
|
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
|
|
|
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) {
|
2020-10-05 17:41:41 +00:00
|
|
|
if (cf.isFormat(file)) {
|
|
|
|
super.accept(file);
|
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
forEachFile = new DelegateConsumer<File>(forEachFile) {
|
|
|
|
@Override
|
|
|
|
public void accept(File file) {
|
2020-10-05 17:41:41 +00:00
|
|
|
if (!file.toString().endsWith(".cached")) {
|
|
|
|
super.accept(file);
|
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
if (playerFolder) {
|
|
|
|
if (listMine) {
|
|
|
|
File playerDir = MainUtil.resolveRelative(new File(dir, actor.getUniqueId() + dirFilter));
|
2020-10-05 17:41:41 +00:00
|
|
|
if (playerDir.exists()) {
|
|
|
|
allFiles(playerDir.listFiles(), false, forEachFile);
|
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
|
|
|
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()) {
|
2019-10-23 14:35:04 +00:00
|
|
|
UUID.fromString(f.getName());
|
2018-08-12 14:03:07 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-11-17 18:20:00 +00:00
|
|
|
} catch (IllegalArgumentException ignored) {
|
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
super.accept(f);
|
|
|
|
}
|
|
|
|
};
|
2020-10-05 17:41:41 +00:00
|
|
|
if (rel.exists()) {
|
|
|
|
allFiles(rel.listFiles(), false, forEachFile);
|
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
File rel = MainUtil.resolveRelative(new File(dir, dirFilter));
|
2020-10-05 17:41:41 +00:00
|
|
|
if (rel.exists()) {
|
|
|
|
allFiles(rel.listFiles(), false, forEachFile);
|
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
|
|
|
if (!filters.isEmpty() && !toFilter.isEmpty()) {
|
|
|
|
List<File> result = filter(toFilter, filters);
|
2020-10-05 17:41:41 +00:00
|
|
|
for (File file : result) {
|
|
|
|
rootFunction.accept(file);
|
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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++) {
|
2020-10-05 17:41:41 +00:00
|
|
|
String normalized = fileList.get(i).getName().toLowerCase(Locale.ROOT);
|
|
|
|
if (normalized.startsWith("../")) {
|
|
|
|
normalized = normalized.substring(3);
|
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
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) {
|
2020-10-05 17:41:41 +00:00
|
|
|
if (fileList.isEmpty()) {
|
|
|
|
return fileList;
|
|
|
|
}
|
|
|
|
String lowerFilter = filter.toLowerCase(Locale.ROOT).replace("/", File.separator);
|
2018-08-12 14:03:07 +00:00
|
|
|
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++) {
|
2020-10-05 17:41:41 +00:00
|
|
|
if (normalizedNames[i].startsWith(lowerFilter)) {
|
|
|
|
newList.add(fileList.get(i));
|
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
|
|
|
if (newList.isEmpty()) {
|
|
|
|
for (int i = 0; i < normalizedNames.length; i++) {
|
2020-10-05 17:41:41 +00:00
|
|
|
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) {
|
2021-12-22 19:58:23 +00:00
|
|
|
UUID fromName = Fawe.platform().getUUID(checkName);
|
2018-08-12 14:03:07 +00:00
|
|
|
if (fromName != null) {
|
2020-10-05 17:41:41 +00:00
|
|
|
lowerFilter = filter.replaceFirst(checkName, fromName.toString()).toLowerCase(Locale.ROOT);
|
2018-08-12 14:03:07 +00:00
|
|
|
for (int i = 0; i < normalizedNames.length; i++) {
|
2020-10-05 17:41:41 +00:00
|
|
|
if (normalizedNames[i].startsWith(lowerFilter)) {
|
|
|
|
newList.add(fileList.get(i));
|
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
}
|
|
|
|
}
|
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) {
|
2020-10-05 17:41:41 +00:00
|
|
|
if (files == null || files.length == 0) {
|
|
|
|
return;
|
|
|
|
}
|
2018-08-12 14:03:07 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2019-10-23 14:35:04 +00:00
|
|
|
public static String getPath(File root, File file, UUID uuid) {
|
2018-08-12 14:03:07 +00:00
|
|
|
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();
|
|
|
|
}
|
2021-07-23 15:48:51 +00:00
|
|
|
//FAWE end
|
2014-06-27 23:03:29 +00:00
|
|
|
|
2014-04-03 02:08:50 +00:00
|
|
|
}
|