2019-12-17 12:37:59 +00:00
|
|
|
package pw.kaboom.extras.modules.server;
|
2019-07-30 17:14:24 +00:00
|
|
|
|
2021-09-13 19:32:03 +00:00
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.logging.Level;
|
|
|
|
import java.util.logging.Logger;
|
2021-07-09 00:36:46 +00:00
|
|
|
import java.util.regex.Matcher;
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
2020-02-26 22:42:17 +00:00
|
|
|
import org.bukkit.block.CommandBlock;
|
2019-08-02 21:19:56 +00:00
|
|
|
import org.bukkit.command.BlockCommandSender;
|
2019-12-14 18:47:26 +00:00
|
|
|
import org.bukkit.command.CommandSender;
|
2020-08-02 19:48:51 +00:00
|
|
|
import org.bukkit.entity.minecart.CommandMinecart;
|
2019-07-30 17:14:24 +00:00
|
|
|
import org.bukkit.event.EventHandler;
|
|
|
|
import org.bukkit.event.Listener;
|
|
|
|
import org.bukkit.event.server.ServerCommandEvent;
|
2021-09-13 19:32:03 +00:00
|
|
|
import org.bukkit.plugin.java.JavaPlugin;
|
|
|
|
|
|
|
|
import pw.kaboom.extras.Main;
|
2019-07-30 17:14:24 +00:00
|
|
|
|
2019-12-21 14:12:26 +00:00
|
|
|
public final class ServerCommand implements Listener {
|
2022-05-20 03:07:38 +00:00
|
|
|
private static final Pattern AS_AT_PATTERN = Pattern.compile(
|
|
|
|
"\\b(as|at|facing entity) @[ae]\\b");
|
2022-05-20 02:35:48 +00:00
|
|
|
private static final Logger LOGGER = JavaPlugin.getPlugin(Main.class).getLogger();
|
2021-07-09 00:36:46 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
public static boolean checkExecuteCommand(final String cmd) {
|
|
|
|
return ("execute".equalsIgnoreCase(cmd)
|
|
|
|
|| "clone".equalsIgnoreCase(cmd)
|
|
|
|
|| "fill".equalsIgnoreCase(cmd)
|
|
|
|
|| "forceload".equalsIgnoreCase(cmd)
|
|
|
|
|| "kick".equalsIgnoreCase(cmd)
|
|
|
|
|| "locate".equalsIgnoreCase(cmd)
|
|
|
|
|| "locatebiome".equalsIgnoreCase(cmd)
|
|
|
|
|| "me".equalsIgnoreCase(cmd)
|
|
|
|
|| "msg".equalsIgnoreCase(cmd)
|
|
|
|
|| "reload".equalsIgnoreCase(cmd)
|
|
|
|
|| "save-all".equalsIgnoreCase(cmd)
|
|
|
|
|| "say".equalsIgnoreCase(cmd)
|
|
|
|
|| "spreadplayers".equalsIgnoreCase(cmd)
|
|
|
|
|| "stop".equalsIgnoreCase(cmd)
|
|
|
|
|| "summon".equalsIgnoreCase(cmd)
|
|
|
|
|| "teammsg".equalsIgnoreCase(cmd)
|
|
|
|
|| "teleport".equalsIgnoreCase(cmd)
|
|
|
|
|| "tell".equalsIgnoreCase(cmd)
|
|
|
|
|| "tellraw".equalsIgnoreCase(cmd)
|
|
|
|
|| "tm".equalsIgnoreCase(cmd)
|
|
|
|
|| "tp".equalsIgnoreCase(cmd)
|
|
|
|
|| "w".equalsIgnoreCase(cmd)
|
|
|
|
);
|
|
|
|
}
|
2022-08-13 15:26:59 +00:00
|
|
|
|
2022-05-20 03:07:38 +00:00
|
|
|
public static String checkCommand(final CommandSender sender, final String command,
|
|
|
|
final boolean isConsoleCommand) {
|
2022-08-13 15:26:59 +00:00
|
|
|
return checkCommand(sender, command, isConsoleCommand, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String checkCommand(final CommandSender sender, final String command,
|
|
|
|
final boolean isConsoleCommand, int depth) {
|
|
|
|
if (depth > 50) {
|
|
|
|
return "cancel";
|
|
|
|
}
|
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
final String[] arr = command.split(" ");
|
|
|
|
String commandName = arr[0].toLowerCase();
|
2019-12-17 18:23:24 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
if (isConsoleCommand) {
|
|
|
|
commandName = "/" + commandName;
|
|
|
|
} else if (arr.length >= 2 && commandName.equals("/")) {
|
|
|
|
// Command could contain spaces after the slash, e.g. "/ spawn"
|
|
|
|
commandName = "/" + arr[1].toLowerCase();
|
|
|
|
}
|
2019-12-17 18:23:24 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
for (int i = 1; i < arr.length; i++) {
|
|
|
|
if (arr[i].matches("^[+-]?(?:\\d+\\.?\\d*|\\d*\\.?\\d+)[\\r\\n]*$")) {
|
|
|
|
try {
|
|
|
|
int integer = Integer.parseInt(arr[i]);
|
|
|
|
try {
|
|
|
|
if (integer >= Integer.MAX_VALUE) {
|
|
|
|
return "cancel";
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
return "cancel";
|
|
|
|
}
|
2021-04-18 02:25:43 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
// Ignore exception
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-04-18 02:25:43 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
try {
|
|
|
|
switch (commandName) {
|
|
|
|
case "/minecraft:execute":
|
|
|
|
case "/execute":
|
|
|
|
if (arr.length >= 2) {
|
|
|
|
int asAtCount = 0;
|
|
|
|
Matcher asAtMatcher = AS_AT_PATTERN.matcher(command.toLowerCase());
|
|
|
|
while (asAtMatcher.find()) {
|
|
|
|
asAtCount++;
|
|
|
|
}
|
|
|
|
if (asAtCount >= 2) {
|
|
|
|
return "cancel";
|
|
|
|
}
|
2019-12-17 18:23:24 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
for (int i = 1; i < arr.length; i++) {
|
2023-02-25 16:45:50 +00:00
|
|
|
if (!"run".equalsIgnoreCase(arr[i])) {
|
|
|
|
continue;
|
2022-05-20 02:35:48 +00:00
|
|
|
}
|
2023-02-25 16:45:50 +00:00
|
|
|
if (i + 1 == arr.length) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (checkExecuteCommand(arr[i + 1])) {
|
|
|
|
return "cancel";
|
|
|
|
}
|
|
|
|
final String[] executeCommand = Arrays.copyOfRange(
|
|
|
|
arr, i + 1, arr.length);
|
|
|
|
final String result = checkCommand(sender,
|
|
|
|
String.join(" ", executeCommand), true, depth + 1);
|
|
|
|
if (result == null) {
|
|
|
|
continue;
|
|
|
|
} else if (result == "cancel") {
|
|
|
|
return "cancel";
|
|
|
|
}
|
|
|
|
final String pureExecute = String.join(
|
|
|
|
" ", Arrays.copyOfRange(arr, 0, i + 1));
|
|
|
|
final String finalResult = checkCommand(sender,
|
|
|
|
pureExecute + " " + result, isConsoleCommand, depth + 1);
|
|
|
|
if (finalResult == null) {
|
|
|
|
return pureExecute + " " + result;
|
|
|
|
}
|
|
|
|
return finalResult;
|
2022-05-20 02:35:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "/minecraft:fill":
|
|
|
|
case "/fill":
|
|
|
|
if (command.contains("auto")) {
|
|
|
|
return command.replace("auto", "[auto]");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "/minecraft:give":
|
|
|
|
case "/give":
|
|
|
|
if (Double.parseDouble(arr[arr.length - 1]) > 64) {
|
|
|
|
// Limit item count
|
|
|
|
arr[arr.length - 1] = "64";
|
|
|
|
return String.join(" ", arr);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "/minecraft:particle":
|
|
|
|
case "/particle":
|
|
|
|
int[] numArgs = {14, 10};
|
|
|
|
for (int i : numArgs) {
|
|
|
|
if (arr.length < i || arr.length > i + 2) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (Double.parseDouble(arr[i - 1]) > 10) {
|
|
|
|
// Limit particle count
|
|
|
|
arr[i - 1] = "10";
|
|
|
|
return String.join(" ", arr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "/minecraft:spreadplayers":
|
|
|
|
case "/spreadplayers":
|
|
|
|
if (arr.length == 7 && (arr[6].contains("@e") || arr[6].contains("@a"))) {
|
|
|
|
return "cancel";
|
|
|
|
} else if (arr.length >= 5) {
|
|
|
|
if (Double.parseDouble(arr[3]) > 0) {
|
|
|
|
arr[3] = "0";
|
|
|
|
}
|
|
|
|
if (Double.parseDouble(arr[4]) < 8) {
|
|
|
|
arr[4] = "8";
|
|
|
|
}
|
|
|
|
if (Double.parseDouble(arr[4]) > 50) {
|
|
|
|
arr[4] = "50";
|
|
|
|
}
|
|
|
|
return String.join(" ", arr);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "/viaversion:viaver":
|
|
|
|
case "/viaversion:viaversion":
|
|
|
|
case "/viaversion:vvbukkit":
|
|
|
|
case "/viaver":
|
|
|
|
case "/viaversion":
|
|
|
|
case "/vvbukkit":
|
|
|
|
if (arr.length >= 2
|
|
|
|
&& "debug".equalsIgnoreCase(arr[1])) {
|
|
|
|
return "cancel";
|
|
|
|
}
|
|
|
|
break;
|
2022-10-11 19:24:00 +00:00
|
|
|
case "/scissors:scissors":
|
|
|
|
case "/scissors":
|
|
|
|
if(arr.length >= 2
|
|
|
|
&& "reload".equalsIgnoreCase(arr[1])) {
|
|
|
|
return "cancel";
|
|
|
|
}
|
|
|
|
break;
|
2022-05-20 02:35:48 +00:00
|
|
|
case "/geyser-spigot:geyser":
|
|
|
|
case "/geyser":
|
|
|
|
if (arr.length >= 2
|
|
|
|
&& "dump".equalsIgnoreCase(arr[1])) {
|
|
|
|
return "cancel";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} catch (NumberFormatException exception) {
|
|
|
|
// Do nothing
|
|
|
|
}
|
2020-07-15 23:14:59 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
if (command.contains("distance")) {
|
2022-05-20 03:07:38 +00:00
|
|
|
return command.replace("distance=", "]").replace("\"distance\"=", "]")
|
|
|
|
.replace("'distance'=", "]");
|
2022-05-20 02:35:48 +00:00
|
|
|
}
|
2020-07-15 23:14:59 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
return null;
|
|
|
|
}
|
2019-07-30 17:14:24 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
@EventHandler
|
|
|
|
void onServerCommand(final ServerCommandEvent event) {
|
|
|
|
final CommandSender sender = event.getSender();
|
2019-12-14 18:47:26 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
if (sender instanceof BlockCommandSender) {
|
2022-05-20 03:07:38 +00:00
|
|
|
final CommandBlock commandBlock = (CommandBlock) ((BlockCommandSender) sender)
|
|
|
|
.getBlock().getState();
|
2020-02-27 15:08:10 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
commandBlock.setCommand("");
|
|
|
|
commandBlock.update();
|
|
|
|
} else if (sender instanceof CommandMinecart) {
|
|
|
|
final CommandMinecart commandMinecart = (CommandMinecart) sender;
|
2020-08-02 19:48:51 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
commandMinecart.setCommand("");
|
|
|
|
}
|
2019-12-14 18:47:26 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
final String command = event.getCommand();
|
|
|
|
final boolean isConsoleCommand = true;
|
|
|
|
final String checkedCommand = checkCommand(sender, command, isConsoleCommand);
|
2019-12-17 18:23:24 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
if (checkedCommand != null) {
|
|
|
|
if ("cancel".equals(checkedCommand)) {
|
|
|
|
event.setCancelled(true);
|
|
|
|
} else {
|
|
|
|
event.setCommand(checkedCommand);
|
|
|
|
}
|
|
|
|
}
|
2021-01-20 08:12:47 +00:00
|
|
|
|
2022-05-20 02:35:48 +00:00
|
|
|
LOGGER.log(Level.INFO, "Console command: " + command);
|
|
|
|
}
|
2019-07-30 17:14:24 +00:00
|
|
|
}
|