mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2026-02-06 18:17:00 +01:00
Run Spotless on src/main
This commit is contained in:
@@ -1,28 +1,28 @@
|
||||
package emu.grasscutter.command;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Command {
|
||||
String label() default "";
|
||||
|
||||
String[] aliases() default {};
|
||||
|
||||
String[] usage() default {""};
|
||||
|
||||
String permission() default "";
|
||||
|
||||
String permissionTargeted() default "";
|
||||
|
||||
TargetRequirement targetRequirement() default TargetRequirement.ONLINE;
|
||||
|
||||
boolean threading() default false;
|
||||
|
||||
enum TargetRequirement {
|
||||
NONE, // targetPlayer is not required
|
||||
OFFLINE, // targetPlayer must be offline
|
||||
PLAYER, // targetPlayer can be online or offline
|
||||
ONLINE // targetPlayer must be online
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Command {
|
||||
String label() default "";
|
||||
|
||||
String[] aliases() default {};
|
||||
|
||||
String[] usage() default {""};
|
||||
|
||||
String permission() default "";
|
||||
|
||||
String permissionTargeted() default "";
|
||||
|
||||
TargetRequirement targetRequirement() default TargetRequirement.ONLINE;
|
||||
|
||||
boolean threading() default false;
|
||||
|
||||
enum TargetRequirement {
|
||||
NONE, // targetPlayer is not required
|
||||
OFFLINE, // targetPlayer must be offline
|
||||
PLAYER, // targetPlayer can be online or offline
|
||||
ONLINE // targetPlayer must be online
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,90 +1,88 @@
|
||||
package emu.grasscutter.command;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.event.game.ReceiveCommandFeedbackEvent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
public interface CommandHandler {
|
||||
|
||||
/**
|
||||
* Send a message to the target.
|
||||
*
|
||||
* @param player The player to send the message to, or null for the server console.
|
||||
* @param message The message to send.
|
||||
*/
|
||||
static void sendMessage(Player player, String message) {
|
||||
// Call command feedback event.
|
||||
ReceiveCommandFeedbackEvent event = new ReceiveCommandFeedbackEvent(player, message);
|
||||
event.call();
|
||||
if (event.isCanceled()) { // If event is not cancelled, continue.
|
||||
return;
|
||||
}
|
||||
|
||||
// Send message to target.
|
||||
if (player == null) {
|
||||
Grasscutter.getLogger().info(event.getMessage());
|
||||
} else {
|
||||
player.dropMessage(event.getMessage().replace("\n\t", "\n\n"));
|
||||
}
|
||||
}
|
||||
|
||||
static void sendTranslatedMessage(Player player, String messageKey, Object... args) {
|
||||
sendMessage(player, translate(player, messageKey, args));
|
||||
}
|
||||
|
||||
default String getUsageString(Player player, String... args) {
|
||||
Command annotation = this.getClass().getAnnotation(Command.class);
|
||||
String usage_prefix = translate(player, "commands.execution.usage_prefix");
|
||||
String command = annotation.label();
|
||||
for (String alias : annotation.aliases()) {
|
||||
if (alias.length() < command.length())
|
||||
command = alias;
|
||||
}
|
||||
if (player != null) {
|
||||
command = "/" + command;
|
||||
}
|
||||
String target = switch (annotation.targetRequirement()) {
|
||||
case NONE -> "";
|
||||
case OFFLINE -> "@<UID> "; // TODO: make translation keys for offline and online players
|
||||
case ONLINE ->
|
||||
(player == null) ? "@<UID> " : "[@<UID>] "; // TODO: make translation keys for offline and online players
|
||||
case PLAYER -> (player == null) ? "@<UID> " : "[@<UID>] ";
|
||||
};
|
||||
String[] usages = annotation.usage();
|
||||
StringJoiner joiner = new StringJoiner("\n\t");
|
||||
for (String usage : usages)
|
||||
joiner.add(usage_prefix + command + " " + target + usage);
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
default void sendUsageMessage(Player player, String... args) {
|
||||
sendMessage(player, getUsageString(player, args));
|
||||
}
|
||||
|
||||
default String getLabel() {
|
||||
return this.getClass().getAnnotation(Command.class).label();
|
||||
}
|
||||
|
||||
default String getDescriptionKey() {
|
||||
Command annotation = this.getClass().getAnnotation(Command.class);
|
||||
return "commands.%s.description".formatted(annotation.label());
|
||||
}
|
||||
|
||||
default String getDescriptionString(Player player) {
|
||||
return translate(player, getDescriptionKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player/console invokes a command.
|
||||
*
|
||||
* @param sender The player/console that invoked the command.
|
||||
* @param args The arguments to the command.
|
||||
*/
|
||||
default void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.event.game.ReceiveCommandFeedbackEvent;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
public interface CommandHandler {
|
||||
|
||||
/**
|
||||
* Send a message to the target.
|
||||
*
|
||||
* @param player The player to send the message to, or null for the server console.
|
||||
* @param message The message to send.
|
||||
*/
|
||||
static void sendMessage(Player player, String message) {
|
||||
// Call command feedback event.
|
||||
ReceiveCommandFeedbackEvent event = new ReceiveCommandFeedbackEvent(player, message);
|
||||
event.call();
|
||||
if (event.isCanceled()) { // If event is not cancelled, continue.
|
||||
return;
|
||||
}
|
||||
|
||||
// Send message to target.
|
||||
if (player == null) {
|
||||
Grasscutter.getLogger().info(event.getMessage());
|
||||
} else {
|
||||
player.dropMessage(event.getMessage().replace("\n\t", "\n\n"));
|
||||
}
|
||||
}
|
||||
|
||||
static void sendTranslatedMessage(Player player, String messageKey, Object... args) {
|
||||
sendMessage(player, translate(player, messageKey, args));
|
||||
}
|
||||
|
||||
default String getUsageString(Player player, String... args) {
|
||||
Command annotation = this.getClass().getAnnotation(Command.class);
|
||||
String usage_prefix = translate(player, "commands.execution.usage_prefix");
|
||||
String command = annotation.label();
|
||||
for (String alias : annotation.aliases()) {
|
||||
if (alias.length() < command.length()) command = alias;
|
||||
}
|
||||
if (player != null) {
|
||||
command = "/" + command;
|
||||
}
|
||||
String target =
|
||||
switch (annotation.targetRequirement()) {
|
||||
case NONE -> "";
|
||||
case OFFLINE -> "@<UID> "; // TODO: make translation keys for offline and online players
|
||||
case ONLINE -> (player == null)
|
||||
? "@<UID> "
|
||||
: "[@<UID>] "; // TODO: make translation keys for offline and online players
|
||||
case PLAYER -> (player == null) ? "@<UID> " : "[@<UID>] ";
|
||||
};
|
||||
String[] usages = annotation.usage();
|
||||
StringJoiner joiner = new StringJoiner("\n\t");
|
||||
for (String usage : usages) joiner.add(usage_prefix + command + " " + target + usage);
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
default void sendUsageMessage(Player player, String... args) {
|
||||
sendMessage(player, getUsageString(player, args));
|
||||
}
|
||||
|
||||
default String getLabel() {
|
||||
return this.getClass().getAnnotation(Command.class).label();
|
||||
}
|
||||
|
||||
default String getDescriptionKey() {
|
||||
Command annotation = this.getClass().getAnnotation(Command.class);
|
||||
return "commands.%s.description".formatted(annotation.label());
|
||||
}
|
||||
|
||||
default String getDescriptionString(Player player) {
|
||||
return translate(player, getDescriptionKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player/console invokes a command.
|
||||
*
|
||||
* @param sender The player/console that invoked the command.
|
||||
* @param args The arguments to the command.
|
||||
*/
|
||||
default void execute(Player sender, Player targetPlayer, List<String> args) {}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,57 @@
|
||||
package emu.grasscutter.command;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class CommandHelpers {
|
||||
public static final Pattern lvlRegex = Pattern.compile("(?<!\\w)l(?:vl?)?(\\d+)"); // Java doesn't have raw string literals :(
|
||||
public static final Pattern amountRegex = Pattern.compile("((?<=(?<!\\w)x)\\d+|\\d+(?=x)(?!x\\d))");
|
||||
public static final Pattern refineRegex = Pattern.compile("(?<!\\w)r(\\d+)");
|
||||
public static final Pattern rankRegex = Pattern.compile("(\\d+)\\*");
|
||||
public static final Pattern constellationRegex = Pattern.compile("(?<!\\w)c(\\d+)");
|
||||
public static final Pattern skillLevelRegex = Pattern.compile("sl(\\d+)");
|
||||
public static final Pattern stateRegex = Pattern.compile("state(\\d+)");
|
||||
public static final Pattern blockRegex = Pattern.compile("blk(\\d+)");
|
||||
public static final Pattern groupRegex = Pattern.compile("grp(\\d+)");
|
||||
public static final Pattern configRegex = Pattern.compile("cfg(\\d+)");
|
||||
public static final Pattern hpRegex = Pattern.compile("(?<!\\w)hp(\\d+)");
|
||||
public static final Pattern maxHPRegex = Pattern.compile("maxhp(\\d+)");
|
||||
public static final Pattern atkRegex = Pattern.compile("atk(\\d+)");
|
||||
public static final Pattern defRegex = Pattern.compile("def(\\d+)");
|
||||
public static final Pattern aiRegex = Pattern.compile("ai(\\d+)");
|
||||
|
||||
public static int matchIntOrNeg(Pattern pattern, String arg) {
|
||||
Matcher match = pattern.matcher(arg);
|
||||
if (match.find()) {
|
||||
return Integer.parseInt(match.group(1)); // This should be exception-safe as only \d+ can be passed to it (i.e. non-empty string of pure digits)
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static <T> List<String> parseIntParameters(List<String> args, @Nonnull T params, Map<Pattern, BiConsumer<T, Integer>> map) {
|
||||
args.removeIf(arg -> {
|
||||
var argL = arg.toLowerCase();
|
||||
boolean deleteArg = false;
|
||||
for (var entry : map.entrySet()) {
|
||||
int argNum = matchIntOrNeg(entry.getKey(), argL);
|
||||
if (argNum != -1) {
|
||||
entry.getValue().accept(params, argNum);
|
||||
deleteArg = true;
|
||||
}
|
||||
}
|
||||
return deleteArg;
|
||||
});
|
||||
return args;
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class CommandHelpers {
|
||||
public static final Pattern lvlRegex =
|
||||
Pattern.compile("(?<!\\w)l(?:vl?)?(\\d+)"); // Java doesn't have raw string literals :(
|
||||
public static final Pattern amountRegex =
|
||||
Pattern.compile("((?<=(?<!\\w)x)\\d+|\\d+(?=x)(?!x\\d))");
|
||||
public static final Pattern refineRegex = Pattern.compile("(?<!\\w)r(\\d+)");
|
||||
public static final Pattern rankRegex = Pattern.compile("(\\d+)\\*");
|
||||
public static final Pattern constellationRegex = Pattern.compile("(?<!\\w)c(\\d+)");
|
||||
public static final Pattern skillLevelRegex = Pattern.compile("sl(\\d+)");
|
||||
public static final Pattern stateRegex = Pattern.compile("state(\\d+)");
|
||||
public static final Pattern blockRegex = Pattern.compile("blk(\\d+)");
|
||||
public static final Pattern groupRegex = Pattern.compile("grp(\\d+)");
|
||||
public static final Pattern configRegex = Pattern.compile("cfg(\\d+)");
|
||||
public static final Pattern hpRegex = Pattern.compile("(?<!\\w)hp(\\d+)");
|
||||
public static final Pattern maxHPRegex = Pattern.compile("maxhp(\\d+)");
|
||||
public static final Pattern atkRegex = Pattern.compile("atk(\\d+)");
|
||||
public static final Pattern defRegex = Pattern.compile("def(\\d+)");
|
||||
public static final Pattern aiRegex = Pattern.compile("ai(\\d+)");
|
||||
|
||||
public static int matchIntOrNeg(Pattern pattern, String arg) {
|
||||
Matcher match = pattern.matcher(arg);
|
||||
if (match.find()) {
|
||||
return Integer.parseInt(
|
||||
match.group(
|
||||
1)); // This should be exception-safe as only \d+ can be passed to it (i.e. non-empty
|
||||
// string of pure digits)
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static <T> List<String> parseIntParameters(
|
||||
List<String> args, @Nonnull T params, Map<Pattern, BiConsumer<T, Integer>> map) {
|
||||
args.removeIf(
|
||||
arg -> {
|
||||
var argL = arg.toLowerCase();
|
||||
boolean deleteArg = false;
|
||||
for (var entry : map.entrySet()) {
|
||||
int argNum = matchIntOrNeg(entry.getKey(), argL);
|
||||
if (argNum != -1) {
|
||||
entry.getValue().accept(params, argNum);
|
||||
deleteArg = true;
|
||||
}
|
||||
}
|
||||
return deleteArg;
|
||||
});
|
||||
return args;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,330 +1,354 @@
|
||||
package emu.grasscutter.command;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.SERVER;
|
||||
|
||||
@SuppressWarnings({"UnusedReturnValue", "unused"})
|
||||
public final class CommandMap {
|
||||
private static final int INVALID_UID = Integer.MIN_VALUE;
|
||||
private static final String consoleId = "console";
|
||||
private final Map<String, CommandHandler> commands = new TreeMap<>();
|
||||
private final Map<String, CommandHandler> aliases = new TreeMap<>();
|
||||
private final Map<String, Command> annotations = new TreeMap<>();
|
||||
private final Object2IntMap<String> targetPlayerIds = new Object2IntOpenHashMap<>();
|
||||
|
||||
public CommandMap() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public CommandMap(boolean scan) {
|
||||
if (scan) this.scan();
|
||||
}
|
||||
|
||||
public static CommandMap getInstance() {
|
||||
return Grasscutter.getCommandMap();
|
||||
}
|
||||
|
||||
private static int getUidFromString(String input) {
|
||||
try {
|
||||
return Integer.parseInt(input);
|
||||
} catch (NumberFormatException ignored) {
|
||||
var account = DatabaseHelper.getAccountByName(input);
|
||||
if (account == null) return INVALID_UID;
|
||||
var player = DatabaseHelper.getPlayerByAccount(account);
|
||||
if (player == null) return INVALID_UID;
|
||||
// We will be immediately fetching the player again after this,
|
||||
// but offline vs online Player safety is more important than saving a lookup
|
||||
return player.getUid();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a command handler.
|
||||
*
|
||||
* @param label The command label.
|
||||
* @param command The command handler.
|
||||
* @return Instance chaining.
|
||||
*/
|
||||
public CommandMap registerCommand(String label, CommandHandler command) {
|
||||
Grasscutter.getLogger().debug("Registered command: " + label);
|
||||
label = label.toLowerCase();
|
||||
|
||||
// Get command data.
|
||||
Command annotation = command.getClass().getAnnotation(Command.class);
|
||||
this.annotations.put(label, annotation);
|
||||
this.commands.put(label, command);
|
||||
|
||||
// Register aliases.
|
||||
for (String alias : annotation.aliases()) {
|
||||
this.aliases.put(alias, command);
|
||||
this.annotations.put(alias, annotation);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a registered command handler.
|
||||
*
|
||||
* @param label The command label.
|
||||
* @return Instance chaining.
|
||||
*/
|
||||
public CommandMap unregisterCommand(String label) {
|
||||
Grasscutter.getLogger().debug("Unregistered command: " + label);
|
||||
|
||||
CommandHandler handler = this.commands.get(label);
|
||||
if (handler == null) return this;
|
||||
|
||||
Command annotation = handler.getClass().getAnnotation(Command.class);
|
||||
this.annotations.remove(label);
|
||||
this.commands.remove(label);
|
||||
|
||||
// Unregister aliases.
|
||||
for (String alias : annotation.aliases()) {
|
||||
this.aliases.remove(alias);
|
||||
this.annotations.remove(alias);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<Command> getAnnotationsAsList() {
|
||||
return new ArrayList<>(this.annotations.values());
|
||||
}
|
||||
|
||||
public Map<String, Command> getAnnotations() {
|
||||
return new LinkedHashMap<>(this.annotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all registered commands.
|
||||
*
|
||||
* @return All command handlers as a list.
|
||||
*/
|
||||
public List<CommandHandler> getHandlersAsList() {
|
||||
return new ArrayList<>(this.commands.values());
|
||||
}
|
||||
|
||||
public Map<String, CommandHandler> getHandlers() {
|
||||
return this.commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a handler by label/alias.
|
||||
*
|
||||
* @param label The command label.
|
||||
* @return The command handler.
|
||||
*/
|
||||
public CommandHandler getHandler(String label) {
|
||||
CommandHandler handler = this.commands.get(label);
|
||||
if (handler == null) {
|
||||
// Try getting by alias
|
||||
handler = this.aliases.get(label);
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
private Player getTargetPlayer(String playerId, Player player, Player targetPlayer, List<String> args) {
|
||||
// Top priority: If any @UID argument is present, override targetPlayer with it.
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
String arg = args.get(i);
|
||||
if (arg.startsWith("@")) {
|
||||
arg = args.remove(i).substring(1);
|
||||
if (arg.equals("")) {
|
||||
// This is a special case to target nothing, distinct from failing to assign a target.
|
||||
// This is specifically to allow in-game players to run a command without targeting themselves or anyone else.
|
||||
return null;
|
||||
}
|
||||
int uid = getUidFromString(arg);
|
||||
if (uid == INVALID_UID) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.generic.invalid.uid");
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
targetPlayer = Grasscutter.getGameServer().getPlayerByUid(uid, true);
|
||||
if (targetPlayer == null) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error");
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return targetPlayer;
|
||||
}
|
||||
}
|
||||
|
||||
// Next priority: If we invoked with a target, use that.
|
||||
// By default, this only happens when you message another player in-game with a command.
|
||||
if (targetPlayer != null) {
|
||||
return targetPlayer;
|
||||
}
|
||||
|
||||
// Next priority: Use previously-set target. (see /target [[@]UID])
|
||||
if (targetPlayerIds.containsKey(playerId)) {
|
||||
targetPlayer = Grasscutter.getGameServer().getPlayerByUid(targetPlayerIds.getInt(playerId), true);
|
||||
// We check every time in case the target is deleted after being targeted
|
||||
if (targetPlayer == null) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error");
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return targetPlayer;
|
||||
}
|
||||
|
||||
// Lowest priority: Target the player invoking the command. In the case of the console, this will return null.
|
||||
return player;
|
||||
}
|
||||
|
||||
private boolean setPlayerTarget(String playerId, Player player, String targetUid) {
|
||||
if (targetUid.equals("")) { // Clears the default targetPlayer.
|
||||
targetPlayerIds.removeInt(playerId);
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.clear_target");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Sets default targetPlayer to the UID provided.
|
||||
int uid = getUidFromString(targetUid);
|
||||
if (uid == INVALID_UID) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.generic.invalid.uid");
|
||||
return false;
|
||||
}
|
||||
Player targetPlayer = Grasscutter.getGameServer().getPlayerByUid(uid, true);
|
||||
if (targetPlayer == null) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error");
|
||||
return false;
|
||||
}
|
||||
|
||||
targetPlayerIds.put(playerId, uid);
|
||||
String target = uid + " (" + targetPlayer.getAccount().getUsername() + ")";
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.set_target", target);
|
||||
CommandHandler.sendTranslatedMessage(player, targetPlayer.isOnline() ? "commands.execution.set_target_online" : "commands.execution.set_target_offline", target);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke a command handler with the given arguments.
|
||||
*
|
||||
* @param player The player invoking the command or null for the server console.
|
||||
* @param rawMessage The messaged used to invoke the command.
|
||||
*/
|
||||
public void invoke(Player player, Player targetPlayer, String rawMessage) {
|
||||
// The console outputs in-game command. [{Account Username} (Player UID: {Player Uid})]
|
||||
if (SERVER.logCommands) {
|
||||
if (player != null) {
|
||||
Grasscutter.getLogger().info("Command used by [" + player.getAccount().getUsername() + " (Player UID: " + player.getUid() + ")]: " + rawMessage);
|
||||
} else {
|
||||
Grasscutter.getLogger().info("Command used by server console: " + rawMessage);
|
||||
}
|
||||
}
|
||||
|
||||
rawMessage = rawMessage.trim();
|
||||
if (rawMessage.length() == 0) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.generic.not_specified");
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse message.
|
||||
String[] split = rawMessage.split(" ");
|
||||
String label = split[0].toLowerCase();
|
||||
List<String> args = new ArrayList<>(Arrays.asList(split).subList(1, split.length));
|
||||
String playerId = (player == null) ? consoleId : player.getAccount().getId();
|
||||
|
||||
// Check for special cases - currently only target command.
|
||||
if (label.startsWith("@")) { // @[UID]
|
||||
this.setPlayerTarget(playerId, player, label.substring(1));
|
||||
return;
|
||||
} else if (label.equalsIgnoreCase("target")) { // target [[@]UID]
|
||||
if (args.size() > 0) {
|
||||
String targetUidStr = args.get(0);
|
||||
if (targetUidStr.startsWith("@")) {
|
||||
targetUidStr = targetUidStr.substring(1);
|
||||
}
|
||||
this.setPlayerTarget(playerId, player, targetUidStr);
|
||||
return;
|
||||
} else {
|
||||
this.setPlayerTarget(playerId, player, "");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get command handler.
|
||||
CommandHandler handler = this.getHandler(label);
|
||||
|
||||
// Check if the handler is null.
|
||||
if (handler == null) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.generic.unknown_command", label);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the command's annotation.
|
||||
Command annotation = this.annotations.get(label);
|
||||
|
||||
// Resolve targetPlayer
|
||||
try {
|
||||
targetPlayer = getTargetPlayer(playerId, player, targetPlayer, args);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for permissions.
|
||||
if (!Grasscutter.getPermissionHandler().checkPermission(player, targetPlayer, annotation.permission(), this.annotations.get(label).permissionTargeted())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if command has unfulfilled constraints on targetPlayer
|
||||
Command.TargetRequirement targetRequirement = annotation.targetRequirement();
|
||||
if (targetRequirement != Command.TargetRequirement.NONE) {
|
||||
if (targetPlayer == null) {
|
||||
handler.sendUsageMessage(player);
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((targetRequirement == Command.TargetRequirement.ONLINE) && !targetPlayer.isOnline()) {
|
||||
handler.sendUsageMessage(player);
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target_online");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((targetRequirement == Command.TargetRequirement.OFFLINE) && targetPlayer.isOnline()) {
|
||||
handler.sendUsageMessage(player);
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target_offline");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy player and handler to final properties.
|
||||
final Player targetPlayerF = targetPlayer; // Is there a better way to do this?
|
||||
final CommandHandler handlerF = handler; // Is there a better way to do this?
|
||||
|
||||
// Invoke execute method for handler.
|
||||
Runnable runnable = () -> handlerF.execute(player, targetPlayerF, args);
|
||||
if (annotation.threading()) {
|
||||
new Thread(runnable).start();
|
||||
} else {
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans for all classes annotated with {@link Command} and registers them.
|
||||
*/
|
||||
private void scan() {
|
||||
Reflections reflector = Grasscutter.reflector;
|
||||
Set<Class<?>> classes = reflector.getTypesAnnotatedWith(Command.class);
|
||||
|
||||
classes.forEach(annotated -> {
|
||||
try {
|
||||
Command cmdData = annotated.getAnnotation(Command.class);
|
||||
Object object = annotated.getDeclaredConstructor().newInstance();
|
||||
if (object instanceof CommandHandler)
|
||||
this.registerCommand(cmdData.label(), (CommandHandler) object);
|
||||
else Grasscutter.getLogger().error("Class " + annotated.getName() + " is not a CommandHandler!");
|
||||
} catch (Exception exception) {
|
||||
Grasscutter.getLogger().error("Failed to register command handler for " + annotated.getSimpleName(), exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.SERVER;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import java.util.*;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
@SuppressWarnings({"UnusedReturnValue", "unused"})
|
||||
public final class CommandMap {
|
||||
private static final int INVALID_UID = Integer.MIN_VALUE;
|
||||
private static final String consoleId = "console";
|
||||
private final Map<String, CommandHandler> commands = new TreeMap<>();
|
||||
private final Map<String, CommandHandler> aliases = new TreeMap<>();
|
||||
private final Map<String, Command> annotations = new TreeMap<>();
|
||||
private final Object2IntMap<String> targetPlayerIds = new Object2IntOpenHashMap<>();
|
||||
|
||||
public CommandMap() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public CommandMap(boolean scan) {
|
||||
if (scan) this.scan();
|
||||
}
|
||||
|
||||
public static CommandMap getInstance() {
|
||||
return Grasscutter.getCommandMap();
|
||||
}
|
||||
|
||||
private static int getUidFromString(String input) {
|
||||
try {
|
||||
return Integer.parseInt(input);
|
||||
} catch (NumberFormatException ignored) {
|
||||
var account = DatabaseHelper.getAccountByName(input);
|
||||
if (account == null) return INVALID_UID;
|
||||
var player = DatabaseHelper.getPlayerByAccount(account);
|
||||
if (player == null) return INVALID_UID;
|
||||
// We will be immediately fetching the player again after this,
|
||||
// but offline vs online Player safety is more important than saving a lookup
|
||||
return player.getUid();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a command handler.
|
||||
*
|
||||
* @param label The command label.
|
||||
* @param command The command handler.
|
||||
* @return Instance chaining.
|
||||
*/
|
||||
public CommandMap registerCommand(String label, CommandHandler command) {
|
||||
Grasscutter.getLogger().debug("Registered command: " + label);
|
||||
label = label.toLowerCase();
|
||||
|
||||
// Get command data.
|
||||
Command annotation = command.getClass().getAnnotation(Command.class);
|
||||
this.annotations.put(label, annotation);
|
||||
this.commands.put(label, command);
|
||||
|
||||
// Register aliases.
|
||||
for (String alias : annotation.aliases()) {
|
||||
this.aliases.put(alias, command);
|
||||
this.annotations.put(alias, annotation);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a registered command handler.
|
||||
*
|
||||
* @param label The command label.
|
||||
* @return Instance chaining.
|
||||
*/
|
||||
public CommandMap unregisterCommand(String label) {
|
||||
Grasscutter.getLogger().debug("Unregistered command: " + label);
|
||||
|
||||
CommandHandler handler = this.commands.get(label);
|
||||
if (handler == null) return this;
|
||||
|
||||
Command annotation = handler.getClass().getAnnotation(Command.class);
|
||||
this.annotations.remove(label);
|
||||
this.commands.remove(label);
|
||||
|
||||
// Unregister aliases.
|
||||
for (String alias : annotation.aliases()) {
|
||||
this.aliases.remove(alias);
|
||||
this.annotations.remove(alias);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<Command> getAnnotationsAsList() {
|
||||
return new ArrayList<>(this.annotations.values());
|
||||
}
|
||||
|
||||
public Map<String, Command> getAnnotations() {
|
||||
return new LinkedHashMap<>(this.annotations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all registered commands.
|
||||
*
|
||||
* @return All command handlers as a list.
|
||||
*/
|
||||
public List<CommandHandler> getHandlersAsList() {
|
||||
return new ArrayList<>(this.commands.values());
|
||||
}
|
||||
|
||||
public Map<String, CommandHandler> getHandlers() {
|
||||
return this.commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a handler by label/alias.
|
||||
*
|
||||
* @param label The command label.
|
||||
* @return The command handler.
|
||||
*/
|
||||
public CommandHandler getHandler(String label) {
|
||||
CommandHandler handler = this.commands.get(label);
|
||||
if (handler == null) {
|
||||
// Try getting by alias
|
||||
handler = this.aliases.get(label);
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
private Player getTargetPlayer(
|
||||
String playerId, Player player, Player targetPlayer, List<String> args) {
|
||||
// Top priority: If any @UID argument is present, override targetPlayer with it.
|
||||
for (int i = 0; i < args.size(); i++) {
|
||||
String arg = args.get(i);
|
||||
if (arg.startsWith("@")) {
|
||||
arg = args.remove(i).substring(1);
|
||||
if (arg.equals("")) {
|
||||
// This is a special case to target nothing, distinct from failing to assign a target.
|
||||
// This is specifically to allow in-game players to run a command without targeting
|
||||
// themselves or anyone else.
|
||||
return null;
|
||||
}
|
||||
int uid = getUidFromString(arg);
|
||||
if (uid == INVALID_UID) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.generic.invalid.uid");
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
targetPlayer = Grasscutter.getGameServer().getPlayerByUid(uid, true);
|
||||
if (targetPlayer == null) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error");
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return targetPlayer;
|
||||
}
|
||||
}
|
||||
|
||||
// Next priority: If we invoked with a target, use that.
|
||||
// By default, this only happens when you message another player in-game with a command.
|
||||
if (targetPlayer != null) {
|
||||
return targetPlayer;
|
||||
}
|
||||
|
||||
// Next priority: Use previously-set target. (see /target [[@]UID])
|
||||
if (targetPlayerIds.containsKey(playerId)) {
|
||||
targetPlayer =
|
||||
Grasscutter.getGameServer().getPlayerByUid(targetPlayerIds.getInt(playerId), true);
|
||||
// We check every time in case the target is deleted after being targeted
|
||||
if (targetPlayer == null) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error");
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return targetPlayer;
|
||||
}
|
||||
|
||||
// Lowest priority: Target the player invoking the command. In the case of the console, this
|
||||
// will return null.
|
||||
return player;
|
||||
}
|
||||
|
||||
private boolean setPlayerTarget(String playerId, Player player, String targetUid) {
|
||||
if (targetUid.equals("")) { // Clears the default targetPlayer.
|
||||
targetPlayerIds.removeInt(playerId);
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.clear_target");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Sets default targetPlayer to the UID provided.
|
||||
int uid = getUidFromString(targetUid);
|
||||
if (uid == INVALID_UID) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.generic.invalid.uid");
|
||||
return false;
|
||||
}
|
||||
Player targetPlayer = Grasscutter.getGameServer().getPlayerByUid(uid, true);
|
||||
if (targetPlayer == null) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.player_exist_error");
|
||||
return false;
|
||||
}
|
||||
|
||||
targetPlayerIds.put(playerId, uid);
|
||||
String target = uid + " (" + targetPlayer.getAccount().getUsername() + ")";
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.set_target", target);
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
player,
|
||||
targetPlayer.isOnline()
|
||||
? "commands.execution.set_target_online"
|
||||
: "commands.execution.set_target_offline",
|
||||
target);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke a command handler with the given arguments.
|
||||
*
|
||||
* @param player The player invoking the command or null for the server console.
|
||||
* @param rawMessage The messaged used to invoke the command.
|
||||
*/
|
||||
public void invoke(Player player, Player targetPlayer, String rawMessage) {
|
||||
// The console outputs in-game command. [{Account Username} (Player UID: {Player Uid})]
|
||||
if (SERVER.logCommands) {
|
||||
if (player != null) {
|
||||
Grasscutter.getLogger()
|
||||
.info(
|
||||
"Command used by ["
|
||||
+ player.getAccount().getUsername()
|
||||
+ " (Player UID: "
|
||||
+ player.getUid()
|
||||
+ ")]: "
|
||||
+ rawMessage);
|
||||
} else {
|
||||
Grasscutter.getLogger().info("Command used by server console: " + rawMessage);
|
||||
}
|
||||
}
|
||||
|
||||
rawMessage = rawMessage.trim();
|
||||
if (rawMessage.length() == 0) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.generic.not_specified");
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse message.
|
||||
String[] split = rawMessage.split(" ");
|
||||
String label = split[0].toLowerCase();
|
||||
List<String> args = new ArrayList<>(Arrays.asList(split).subList(1, split.length));
|
||||
String playerId = (player == null) ? consoleId : player.getAccount().getId();
|
||||
|
||||
// Check for special cases - currently only target command.
|
||||
if (label.startsWith("@")) { // @[UID]
|
||||
this.setPlayerTarget(playerId, player, label.substring(1));
|
||||
return;
|
||||
} else if (label.equalsIgnoreCase("target")) { // target [[@]UID]
|
||||
if (args.size() > 0) {
|
||||
String targetUidStr = args.get(0);
|
||||
if (targetUidStr.startsWith("@")) {
|
||||
targetUidStr = targetUidStr.substring(1);
|
||||
}
|
||||
this.setPlayerTarget(playerId, player, targetUidStr);
|
||||
return;
|
||||
} else {
|
||||
this.setPlayerTarget(playerId, player, "");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get command handler.
|
||||
CommandHandler handler = this.getHandler(label);
|
||||
|
||||
// Check if the handler is null.
|
||||
if (handler == null) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.generic.unknown_command", label);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the command's annotation.
|
||||
Command annotation = this.annotations.get(label);
|
||||
|
||||
// Resolve targetPlayer
|
||||
try {
|
||||
targetPlayer = getTargetPlayer(playerId, player, targetPlayer, args);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for permissions.
|
||||
if (!Grasscutter.getPermissionHandler()
|
||||
.checkPermission(
|
||||
player,
|
||||
targetPlayer,
|
||||
annotation.permission(),
|
||||
this.annotations.get(label).permissionTargeted())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if command has unfulfilled constraints on targetPlayer
|
||||
Command.TargetRequirement targetRequirement = annotation.targetRequirement();
|
||||
if (targetRequirement != Command.TargetRequirement.NONE) {
|
||||
if (targetPlayer == null) {
|
||||
handler.sendUsageMessage(player);
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((targetRequirement == Command.TargetRequirement.ONLINE) && !targetPlayer.isOnline()) {
|
||||
handler.sendUsageMessage(player);
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target_online");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((targetRequirement == Command.TargetRequirement.OFFLINE) && targetPlayer.isOnline()) {
|
||||
handler.sendUsageMessage(player);
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.execution.need_target_offline");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy player and handler to final properties.
|
||||
final Player targetPlayerF = targetPlayer; // Is there a better way to do this?
|
||||
final CommandHandler handlerF = handler; // Is there a better way to do this?
|
||||
|
||||
// Invoke execute method for handler.
|
||||
Runnable runnable = () -> handlerF.execute(player, targetPlayerF, args);
|
||||
if (annotation.threading()) {
|
||||
new Thread(runnable).start();
|
||||
} else {
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
|
||||
/** Scans for all classes annotated with {@link Command} and registers them. */
|
||||
private void scan() {
|
||||
Reflections reflector = Grasscutter.reflector;
|
||||
Set<Class<?>> classes = reflector.getTypesAnnotatedWith(Command.class);
|
||||
|
||||
classes.forEach(
|
||||
annotated -> {
|
||||
try {
|
||||
Command cmdData = annotated.getAnnotation(Command.class);
|
||||
Object object = annotated.getDeclaredConstructor().newInstance();
|
||||
if (object instanceof CommandHandler)
|
||||
this.registerCommand(cmdData.label(), (CommandHandler) object);
|
||||
else
|
||||
Grasscutter.getLogger()
|
||||
.error("Class " + annotated.getName() + " is not a CommandHandler!");
|
||||
} catch (Exception exception) {
|
||||
Grasscutter.getLogger()
|
||||
.error(
|
||||
"Failed to register command handler for " + annotated.getSimpleName(),
|
||||
exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,33 @@
|
||||
package emu.grasscutter.command;
|
||||
|
||||
import emu.grasscutter.game.Account;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
public class DefaultPermissionHandler implements PermissionHandler {
|
||||
@Override
|
||||
public boolean EnablePermissionCommand() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkPermission(Player player, Player targetPlayer, String permissionNode, String permissionNodeTargeted) {
|
||||
if (player == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Account account = player.getAccount();
|
||||
if (player != targetPlayer) { // Additional permission required for targeting another player
|
||||
if (!permissionNodeTargeted.isEmpty() && !account.hasPermission(permissionNodeTargeted)) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.generic.permission_error");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!permissionNode.isEmpty() && !account.hasPermission(permissionNode)) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.generic.permission_error");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command;
|
||||
|
||||
import emu.grasscutter.game.Account;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
public class DefaultPermissionHandler implements PermissionHandler {
|
||||
@Override
|
||||
public boolean EnablePermissionCommand() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkPermission(
|
||||
Player player, Player targetPlayer, String permissionNode, String permissionNodeTargeted) {
|
||||
if (player == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Account account = player.getAccount();
|
||||
if (player != targetPlayer) { // Additional permission required for targeting another player
|
||||
if (!permissionNodeTargeted.isEmpty() && !account.hasPermission(permissionNodeTargeted)) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.generic.permission_error");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!permissionNode.isEmpty() && !account.hasPermission(permissionNode)) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.generic.permission_error");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package emu.grasscutter.command;
|
||||
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
public interface PermissionHandler {
|
||||
boolean EnablePermissionCommand();
|
||||
|
||||
boolean checkPermission(Player player, Player targetPlayer, String permissionNode, String permissionNodeTargeted);
|
||||
}
|
||||
package emu.grasscutter.command;
|
||||
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
public interface PermissionHandler {
|
||||
boolean EnablePermissionCommand();
|
||||
|
||||
boolean checkPermission(
|
||||
Player player, Player targetPlayer, String permissionNode, String permissionNodeTargeted);
|
||||
}
|
||||
|
||||
@@ -1,139 +1,145 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import at.favre.lib.crypto.bcrypt.BCrypt;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.config.Configuration;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.Account;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(
|
||||
label = "account",
|
||||
usage = {
|
||||
"create <username> [<UID>]", // Only with EXPERIMENTAL_RealPassword == false
|
||||
"delete <username>",
|
||||
"create <username> <password> [<UID>]", // Only with EXPERIMENTAL_RealPassword == true
|
||||
"resetpass <username> <password>"}, // Only with EXPERIMENTAL_RealPassword == true
|
||||
targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class AccountCommand implements CommandHandler {
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (sender != null) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.console_execute_error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.size() < 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
String action = args.get(0);
|
||||
String username = args.get(1);
|
||||
|
||||
switch (action) {
|
||||
default:
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
case "create":
|
||||
int uid = 0;
|
||||
String password = "";
|
||||
|
||||
if (Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) {
|
||||
if (args.size() < 3) {
|
||||
CommandHandler.sendMessage(sender, "EXPERIMENTAL_RealPassword requires a password argument");
|
||||
CommandHandler.sendMessage(sender, "Usage: account create <username> <password> [uid]");
|
||||
return;
|
||||
}
|
||||
password = args.get(2);
|
||||
|
||||
if (args.size() == 4) {
|
||||
try {
|
||||
uid = Integer.parseInt(args.get(3));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.account.invalid"));
|
||||
if (Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) {
|
||||
CommandHandler.sendMessage(sender, "EXPERIMENTAL_RealPassword requires argument 2 to be a password, not a uid");
|
||||
CommandHandler.sendMessage(sender, "Usage: account create <username> <password> [uid]");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (args.size() > 2) {
|
||||
try {
|
||||
uid = Integer.parseInt(args.get(2));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.account.invalid"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emu.grasscutter.game.Account account = DatabaseHelper.createAccountWithUid(username, uid);
|
||||
if (account == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.account.exists"));
|
||||
return;
|
||||
} else {
|
||||
if (Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) {
|
||||
account.setPassword(BCrypt.withDefaults().hashToString(12, password.toCharArray()));
|
||||
}
|
||||
account.addPermission("*");
|
||||
account.save(); // Save account to database.
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.account.create", account.getReservedPlayerUid()));
|
||||
}
|
||||
return;
|
||||
case "delete":
|
||||
// Get the account we want to delete.
|
||||
Account toDelete = DatabaseHelper.getAccountByName(username);
|
||||
|
||||
if (toDelete == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.account.no_account"));
|
||||
return;
|
||||
}
|
||||
|
||||
DatabaseHelper.deleteAccount(toDelete);
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.account.delete"));
|
||||
return;
|
||||
case "resetpass":
|
||||
if (!Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) {
|
||||
CommandHandler.sendMessage(sender, "resetpass requires EXPERIMENTAL_RealPassword to be true.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.size() != 3) {
|
||||
CommandHandler.sendMessage(sender, "Invalid Args");
|
||||
CommandHandler.sendMessage(sender, "Usage: account resetpass <username> <password>");
|
||||
return;
|
||||
}
|
||||
|
||||
Account toUpdate = DatabaseHelper.getAccountByName(username);
|
||||
|
||||
if (toUpdate == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.account.no_account"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure player can't stay logged in with old password.
|
||||
kickAccount(toUpdate);
|
||||
|
||||
toUpdate.setPassword(BCrypt.withDefaults().hashToString(12, args.get(2).toCharArray()));
|
||||
toUpdate.save();
|
||||
CommandHandler.sendMessage(sender, "Password Updated.");
|
||||
}
|
||||
}
|
||||
|
||||
private void kickAccount(Account account) {
|
||||
Player player = Grasscutter.getGameServer().getPlayerByAccountId(account.getId());
|
||||
if (player != null) {
|
||||
player.getSession().close();
|
||||
}
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import at.favre.lib.crypto.bcrypt.BCrypt;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.config.Configuration;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.Account;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "account",
|
||||
usage = {
|
||||
"create <username> [<UID>]", // Only with EXPERIMENTAL_RealPassword == false
|
||||
"delete <username>",
|
||||
"create <username> <password> [<UID>]", // Only with EXPERIMENTAL_RealPassword == true
|
||||
"resetpass <username> <password>"
|
||||
}, // Only with EXPERIMENTAL_RealPassword == true
|
||||
targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class AccountCommand implements CommandHandler {
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (sender != null) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.console_execute_error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.size() < 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
String action = args.get(0);
|
||||
String username = args.get(1);
|
||||
|
||||
switch (action) {
|
||||
default:
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
case "create":
|
||||
int uid = 0;
|
||||
String password = "";
|
||||
|
||||
if (Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) {
|
||||
if (args.size() < 3) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, "EXPERIMENTAL_RealPassword requires a password argument");
|
||||
CommandHandler.sendMessage(sender, "Usage: account create <username> <password> [uid]");
|
||||
return;
|
||||
}
|
||||
password = args.get(2);
|
||||
|
||||
if (args.size() == 4) {
|
||||
try {
|
||||
uid = Integer.parseInt(args.get(3));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.account.invalid"));
|
||||
if (Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) {
|
||||
CommandHandler.sendMessage(
|
||||
sender,
|
||||
"EXPERIMENTAL_RealPassword requires argument 2 to be a password, not a uid");
|
||||
CommandHandler.sendMessage(
|
||||
sender, "Usage: account create <username> <password> [uid]");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (args.size() > 2) {
|
||||
try {
|
||||
uid = Integer.parseInt(args.get(2));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.account.invalid"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emu.grasscutter.game.Account account = DatabaseHelper.createAccountWithUid(username, uid);
|
||||
if (account == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.account.exists"));
|
||||
return;
|
||||
} else {
|
||||
if (Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) {
|
||||
account.setPassword(BCrypt.withDefaults().hashToString(12, password.toCharArray()));
|
||||
}
|
||||
account.addPermission("*");
|
||||
account.save(); // Save account to database.
|
||||
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.account.create", account.getReservedPlayerUid()));
|
||||
}
|
||||
return;
|
||||
case "delete":
|
||||
// Get the account we want to delete.
|
||||
Account toDelete = DatabaseHelper.getAccountByName(username);
|
||||
|
||||
if (toDelete == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.account.no_account"));
|
||||
return;
|
||||
}
|
||||
|
||||
DatabaseHelper.deleteAccount(toDelete);
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.account.delete"));
|
||||
return;
|
||||
case "resetpass":
|
||||
if (!Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, "resetpass requires EXPERIMENTAL_RealPassword to be true.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.size() != 3) {
|
||||
CommandHandler.sendMessage(sender, "Invalid Args");
|
||||
CommandHandler.sendMessage(sender, "Usage: account resetpass <username> <password>");
|
||||
return;
|
||||
}
|
||||
|
||||
Account toUpdate = DatabaseHelper.getAccountByName(username);
|
||||
|
||||
if (toUpdate == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.account.no_account"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure player can't stay logged in with old password.
|
||||
kickAccount(toUpdate);
|
||||
|
||||
toUpdate.setPassword(BCrypt.withDefaults().hashToString(12, args.get(2).toCharArray()));
|
||||
toUpdate.save();
|
||||
CommandHandler.sendMessage(sender, "Password Updated.");
|
||||
}
|
||||
}
|
||||
|
||||
private void kickAccount(Account account) {
|
||||
Player player = Grasscutter.getGameServer().getPlayerByAccountId(account.getId());
|
||||
if (player != null) {
|
||||
player.getSession().close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,133 +1,158 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.AchievementData;
|
||||
import emu.grasscutter.game.achievement.AchievementControlReturns;
|
||||
import emu.grasscutter.game.achievement.Achievements;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@Command(
|
||||
label = "achievement",
|
||||
usage = {"(grant|revoke) <achievementId>", "progress <achievementId> <progress>", "grantall", "revokeall"},
|
||||
aliases = {"am"},
|
||||
permission = "player.achievement",
|
||||
permissionTargeted = "player.achievement.others",
|
||||
targetRequirement = Command.TargetRequirement.PLAYER,
|
||||
threading = true)
|
||||
public class AchievementCommand implements CommandHandler {
|
||||
private static void sendSuccessMessage(Player sender, String cmd, Object... args) {
|
||||
CommandHandler.sendTranslatedMessage(sender, AchievementControlReturns.Return.SUCCESS.getKey() + cmd, args);
|
||||
}
|
||||
|
||||
private static Optional<Integer> parseInt(String s) {
|
||||
try {
|
||||
return Optional.of(Integer.parseInt(s));
|
||||
} catch (NumberFormatException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private static void grantAll(Player sender, Player targetPlayer, Achievements achievements) {
|
||||
var counter = new AtomicInteger();
|
||||
GameData.getAchievementDataMap().values().stream()
|
||||
.filter(AchievementData::isUsed)
|
||||
.filter(AchievementData::isParent)
|
||||
.forEach(data -> {
|
||||
var success = achievements.grant(data.getId());
|
||||
if (success.getRet() == AchievementControlReturns.Return.SUCCESS) {
|
||||
counter.addAndGet(success.getChangedAchievementStatusNum());
|
||||
}
|
||||
});
|
||||
|
||||
sendSuccessMessage(sender, "grantall", counter.intValue(), targetPlayer.getNickname());
|
||||
}
|
||||
|
||||
private static void revokeAll(Player sender, Player targetPlayer, Achievements achievements) {
|
||||
var counter = new AtomicInteger();
|
||||
GameData.getAchievementDataMap().values().stream()
|
||||
.filter(AchievementData::isUsed)
|
||||
.filter(AchievementData::isParent)
|
||||
.forEach(data -> {
|
||||
var success = achievements.revoke(data.getId());
|
||||
if (success.getRet() == AchievementControlReturns.Return.SUCCESS) {
|
||||
counter.addAndGet(success.getChangedAchievementStatusNum());
|
||||
}
|
||||
});
|
||||
|
||||
sendSuccessMessage(sender, "revokeall", counter.intValue(), targetPlayer.getNickname());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 1) {
|
||||
this.sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
var command = args.remove(0).toLowerCase();
|
||||
var achievements = Achievements.getByPlayer(targetPlayer);
|
||||
switch (command) {
|
||||
case "grant" -> this.grant(sender, targetPlayer, achievements, args);
|
||||
case "revoke" -> this.revoke(sender, targetPlayer, achievements, args);
|
||||
case "progress" -> this.progress(sender, targetPlayer, achievements, args);
|
||||
case "grantall" -> grantAll(sender, targetPlayer, achievements);
|
||||
case "revokeall" -> revokeAll(sender, targetPlayer, achievements);
|
||||
default -> this.sendUsageMessage(sender);
|
||||
}
|
||||
}
|
||||
|
||||
private void grant(Player sender, Player targetPlayer, Achievements achievements, List<String> args) {
|
||||
if (args.size() < 1) {
|
||||
this.sendUsageMessage(sender);
|
||||
}
|
||||
|
||||
parseInt(args.remove(0)).ifPresentOrElse(integer -> {
|
||||
var ret = achievements.grant(integer);
|
||||
switch (ret.getRet()) {
|
||||
case SUCCESS -> sendSuccessMessage(sender, "grant", targetPlayer.getNickname());
|
||||
case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(sender, ret.getRet().getKey());
|
||||
case ALREADY_ACHIEVED ->
|
||||
CommandHandler.sendTranslatedMessage(sender, ret.getRet().getKey(), targetPlayer.getNickname());
|
||||
}
|
||||
}, () -> this.sendUsageMessage(sender));
|
||||
}
|
||||
|
||||
private void revoke(Player sender, Player targetPlayer, Achievements achievements, List<String> args) {
|
||||
if (args.size() < 1) {
|
||||
this.sendUsageMessage(sender);
|
||||
}
|
||||
|
||||
parseInt(args.remove(0)).ifPresentOrElse(integer -> {
|
||||
var ret = achievements.revoke(integer);
|
||||
switch (ret.getRet()) {
|
||||
case SUCCESS -> sendSuccessMessage(sender, "revoke", targetPlayer.getNickname());
|
||||
case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(sender, ret.getRet().getKey());
|
||||
case NOT_YET_ACHIEVED ->
|
||||
CommandHandler.sendTranslatedMessage(sender, ret.getRet().getKey(), targetPlayer.getNickname());
|
||||
}
|
||||
}, () -> this.sendUsageMessage(sender));
|
||||
}
|
||||
|
||||
private void progress(Player sender, Player targetPlayer, Achievements achievements, List<String> args) {
|
||||
if (args.size() < 2) {
|
||||
this.sendUsageMessage(sender);
|
||||
}
|
||||
|
||||
parseInt(args.remove(0)).ifPresentOrElse(integer -> {
|
||||
parseInt(args.remove(0)).ifPresentOrElse(progress -> {
|
||||
var ret = achievements.progress(integer, progress);
|
||||
switch (ret.getRet()) {
|
||||
case SUCCESS ->
|
||||
sendSuccessMessage(sender, "progress", targetPlayer.getNickname(), integer, progress);
|
||||
case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(sender, ret.getRet().getKey());
|
||||
}
|
||||
}, () -> this.sendUsageMessage(sender));
|
||||
}, () -> this.sendUsageMessage(sender));
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.AchievementData;
|
||||
import emu.grasscutter.game.achievement.AchievementControlReturns;
|
||||
import emu.grasscutter.game.achievement.Achievements;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@Command(
|
||||
label = "achievement",
|
||||
usage = {
|
||||
"(grant|revoke) <achievementId>",
|
||||
"progress <achievementId> <progress>",
|
||||
"grantall",
|
||||
"revokeall"
|
||||
},
|
||||
aliases = {"am"},
|
||||
permission = "player.achievement",
|
||||
permissionTargeted = "player.achievement.others",
|
||||
targetRequirement = Command.TargetRequirement.PLAYER,
|
||||
threading = true)
|
||||
public class AchievementCommand implements CommandHandler {
|
||||
private static void sendSuccessMessage(Player sender, String cmd, Object... args) {
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, AchievementControlReturns.Return.SUCCESS.getKey() + cmd, args);
|
||||
}
|
||||
|
||||
private static Optional<Integer> parseInt(String s) {
|
||||
try {
|
||||
return Optional.of(Integer.parseInt(s));
|
||||
} catch (NumberFormatException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private static void grantAll(Player sender, Player targetPlayer, Achievements achievements) {
|
||||
var counter = new AtomicInteger();
|
||||
GameData.getAchievementDataMap().values().stream()
|
||||
.filter(AchievementData::isUsed)
|
||||
.filter(AchievementData::isParent)
|
||||
.forEach(
|
||||
data -> {
|
||||
var success = achievements.grant(data.getId());
|
||||
if (success.getRet() == AchievementControlReturns.Return.SUCCESS) {
|
||||
counter.addAndGet(success.getChangedAchievementStatusNum());
|
||||
}
|
||||
});
|
||||
|
||||
sendSuccessMessage(sender, "grantall", counter.intValue(), targetPlayer.getNickname());
|
||||
}
|
||||
|
||||
private static void revokeAll(Player sender, Player targetPlayer, Achievements achievements) {
|
||||
var counter = new AtomicInteger();
|
||||
GameData.getAchievementDataMap().values().stream()
|
||||
.filter(AchievementData::isUsed)
|
||||
.filter(AchievementData::isParent)
|
||||
.forEach(
|
||||
data -> {
|
||||
var success = achievements.revoke(data.getId());
|
||||
if (success.getRet() == AchievementControlReturns.Return.SUCCESS) {
|
||||
counter.addAndGet(success.getChangedAchievementStatusNum());
|
||||
}
|
||||
});
|
||||
|
||||
sendSuccessMessage(sender, "revokeall", counter.intValue(), targetPlayer.getNickname());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 1) {
|
||||
this.sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
var command = args.remove(0).toLowerCase();
|
||||
var achievements = Achievements.getByPlayer(targetPlayer);
|
||||
switch (command) {
|
||||
case "grant" -> this.grant(sender, targetPlayer, achievements, args);
|
||||
case "revoke" -> this.revoke(sender, targetPlayer, achievements, args);
|
||||
case "progress" -> this.progress(sender, targetPlayer, achievements, args);
|
||||
case "grantall" -> grantAll(sender, targetPlayer, achievements);
|
||||
case "revokeall" -> revokeAll(sender, targetPlayer, achievements);
|
||||
default -> this.sendUsageMessage(sender);
|
||||
}
|
||||
}
|
||||
|
||||
private void grant(
|
||||
Player sender, Player targetPlayer, Achievements achievements, List<String> args) {
|
||||
if (args.size() < 1) {
|
||||
this.sendUsageMessage(sender);
|
||||
}
|
||||
|
||||
parseInt(args.remove(0))
|
||||
.ifPresentOrElse(
|
||||
integer -> {
|
||||
var ret = achievements.grant(integer);
|
||||
switch (ret.getRet()) {
|
||||
case SUCCESS -> sendSuccessMessage(sender, "grant", targetPlayer.getNickname());
|
||||
case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(
|
||||
sender, ret.getRet().getKey());
|
||||
case ALREADY_ACHIEVED -> CommandHandler.sendTranslatedMessage(
|
||||
sender, ret.getRet().getKey(), targetPlayer.getNickname());
|
||||
}
|
||||
},
|
||||
() -> this.sendUsageMessage(sender));
|
||||
}
|
||||
|
||||
private void revoke(
|
||||
Player sender, Player targetPlayer, Achievements achievements, List<String> args) {
|
||||
if (args.size() < 1) {
|
||||
this.sendUsageMessage(sender);
|
||||
}
|
||||
|
||||
parseInt(args.remove(0))
|
||||
.ifPresentOrElse(
|
||||
integer -> {
|
||||
var ret = achievements.revoke(integer);
|
||||
switch (ret.getRet()) {
|
||||
case SUCCESS -> sendSuccessMessage(sender, "revoke", targetPlayer.getNickname());
|
||||
case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(
|
||||
sender, ret.getRet().getKey());
|
||||
case NOT_YET_ACHIEVED -> CommandHandler.sendTranslatedMessage(
|
||||
sender, ret.getRet().getKey(), targetPlayer.getNickname());
|
||||
}
|
||||
},
|
||||
() -> this.sendUsageMessage(sender));
|
||||
}
|
||||
|
||||
private void progress(
|
||||
Player sender, Player targetPlayer, Achievements achievements, List<String> args) {
|
||||
if (args.size() < 2) {
|
||||
this.sendUsageMessage(sender);
|
||||
}
|
||||
|
||||
parseInt(args.remove(0))
|
||||
.ifPresentOrElse(
|
||||
integer -> {
|
||||
parseInt(args.remove(0))
|
||||
.ifPresentOrElse(
|
||||
progress -> {
|
||||
var ret = achievements.progress(integer, progress);
|
||||
switch (ret.getRet()) {
|
||||
case SUCCESS -> sendSuccessMessage(
|
||||
sender, "progress", targetPlayer.getNickname(), integer, progress);
|
||||
case ACHIEVEMENT_NOT_FOUND -> CommandHandler.sendTranslatedMessage(
|
||||
sender, ret.getRet().getKey());
|
||||
}
|
||||
},
|
||||
() -> this.sendUsageMessage(sender));
|
||||
},
|
||||
() -> this.sendUsageMessage(sender));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +1,78 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.packet.send.PacketServerAnnounceNotify;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "announce",
|
||||
usage = {"<content>", "refresh", "(tpl|revoke) <templateId>"},
|
||||
permission = "server.announce",
|
||||
aliases = {"a"},
|
||||
targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class AnnounceCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
var manager = Grasscutter.getGameServer().getAnnouncementSystem();
|
||||
if (args.size() < 1) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args.get(0)) {
|
||||
case "tpl":
|
||||
if (args.size() < 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
var templateId = Integer.parseInt(args.get(1));
|
||||
var tpl = manager.getAnnounceConfigItemMap().get(templateId);
|
||||
if (tpl == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.announce.not_found", templateId));
|
||||
return;
|
||||
}
|
||||
|
||||
manager.broadcast(Collections.singletonList(tpl));
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.announce.send_success", tpl.getTemplateId()));
|
||||
break;
|
||||
|
||||
case "refresh":
|
||||
var num = manager.refresh();
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.announce.refresh_success", num));
|
||||
break;
|
||||
|
||||
case "revoke":
|
||||
if (args.size() < 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
var templateId1 = Integer.parseInt(args.get(1));
|
||||
manager.revoke(templateId1);
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.announce.revoke_done", templateId1));
|
||||
break;
|
||||
|
||||
default:
|
||||
var id = new Random().nextInt(10000, 99999);
|
||||
var text = String.join(" ", args);
|
||||
manager.getOnlinePlayers().forEach(i -> i.sendPacket(new PacketServerAnnounceNotify(text, id)));
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.announce.send_success", id));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.packet.send.PacketServerAnnounceNotify;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
@Command(
|
||||
label = "announce",
|
||||
usage = {"<content>", "refresh", "(tpl|revoke) <templateId>"},
|
||||
permission = "server.announce",
|
||||
aliases = {"a"},
|
||||
targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class AnnounceCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
var manager = Grasscutter.getGameServer().getAnnouncementSystem();
|
||||
if (args.size() < 1) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args.get(0)) {
|
||||
case "tpl":
|
||||
if (args.size() < 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
var templateId = Integer.parseInt(args.get(1));
|
||||
var tpl = manager.getAnnounceConfigItemMap().get(templateId);
|
||||
if (tpl == null) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.announce.not_found", templateId));
|
||||
return;
|
||||
}
|
||||
|
||||
manager.broadcast(Collections.singletonList(tpl));
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.announce.send_success", tpl.getTemplateId()));
|
||||
break;
|
||||
|
||||
case "refresh":
|
||||
var num = manager.refresh();
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.announce.refresh_success", num));
|
||||
break;
|
||||
|
||||
case "revoke":
|
||||
if (args.size() < 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
var templateId1 = Integer.parseInt(args.get(1));
|
||||
manager.revoke(templateId1);
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.announce.revoke_done", templateId1));
|
||||
break;
|
||||
|
||||
default:
|
||||
var id = new Random().nextInt(10000, 99999);
|
||||
var text = String.join(" ", args);
|
||||
manager
|
||||
.getOnlinePlayers()
|
||||
.forEach(i -> i.sendPacket(new PacketServerAnnounceNotify(text, id)));
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.announce.send_success", id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,64 +1,62 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.Account;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.game.GameSession;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "ban",
|
||||
usage = {"[<time> [<reason>]]"},
|
||||
permission = "server.ban",
|
||||
targetRequirement = Command.TargetRequirement.PLAYER
|
||||
)
|
||||
public final class BanCommand implements CommandHandler {
|
||||
|
||||
private boolean banAccount(Player targetPlayer, int time, String reason) {
|
||||
Account account = targetPlayer.getAccount();
|
||||
|
||||
if (account == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
account.setBanReason(reason);
|
||||
account.setBanEndTime(time);
|
||||
account.setBanStartTime((int) System.currentTimeMillis() / 1000);
|
||||
account.setBanned(true);
|
||||
account.save();
|
||||
|
||||
GameSession session = targetPlayer.getSession();
|
||||
if (session != null) {
|
||||
session.close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
int time = 2051190000;
|
||||
String reason = "Reason not specified.";
|
||||
|
||||
switch (args.size()) {
|
||||
case 2:
|
||||
reason = args.get(1); // Fall-through
|
||||
case 1:
|
||||
try {
|
||||
time = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.ban.invalid_time");
|
||||
return;
|
||||
} // Fall-through, unimportant
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (banAccount(targetPlayer, time, reason)) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.ban.success");
|
||||
} else {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.ban.failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.Account;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.game.GameSession;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "ban",
|
||||
usage = {"[<time> [<reason>]]"},
|
||||
permission = "server.ban",
|
||||
targetRequirement = Command.TargetRequirement.PLAYER)
|
||||
public final class BanCommand implements CommandHandler {
|
||||
|
||||
private boolean banAccount(Player targetPlayer, int time, String reason) {
|
||||
Account account = targetPlayer.getAccount();
|
||||
|
||||
if (account == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
account.setBanReason(reason);
|
||||
account.setBanEndTime(time);
|
||||
account.setBanStartTime((int) System.currentTimeMillis() / 1000);
|
||||
account.setBanned(true);
|
||||
account.save();
|
||||
|
||||
GameSession session = targetPlayer.getSession();
|
||||
if (session != null) {
|
||||
session.close();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
int time = 2051190000;
|
||||
String reason = "Reason not specified.";
|
||||
|
||||
switch (args.size()) {
|
||||
case 2:
|
||||
reason = args.get(1); // Fall-through
|
||||
case 1:
|
||||
try {
|
||||
time = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.ban.invalid_time");
|
||||
return;
|
||||
} // Fall-through, unimportant
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (banAccount(targetPlayer, time, reason)) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.ban.success");
|
||||
} else {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.ban.failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,103 +1,105 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.inventory.GameItem;
|
||||
import emu.grasscutter.game.inventory.Inventory;
|
||||
import emu.grasscutter.game.inventory.ItemType;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static emu.grasscutter.command.CommandHelpers.*;
|
||||
|
||||
@Command(
|
||||
label = "clear",
|
||||
usage = {"(all|wp|art|mat) [lv<max level>] [r<max refinement>] [<max rarity>*]"},
|
||||
permission = "player.clearinv",
|
||||
permissionTargeted = "player.clearinv.others")
|
||||
public final class ClearCommand implements CommandHandler {
|
||||
|
||||
private static final Map<Pattern, BiConsumer<ClearItemParameters, Integer>> intCommandHandlers = Map.ofEntries(
|
||||
Map.entry(lvlRegex, ClearItemParameters::setLvl),
|
||||
Map.entry(refineRegex, ClearItemParameters::setRefinement),
|
||||
Map.entry(rankRegex, ClearItemParameters::setRank)
|
||||
);
|
||||
|
||||
private Stream<GameItem> getOther(ItemType type, Inventory playerInventory, ClearItemParameters param) {
|
||||
return playerInventory.getItems().values().stream()
|
||||
.filter(item -> item.getItemType() == type)
|
||||
.filter(item -> item.getItemData().getRankLevel() <= param.rank)
|
||||
.filter(item -> !item.isLocked() && !item.isEquipped());
|
||||
}
|
||||
|
||||
private Stream<GameItem> getWeapons(Inventory playerInventory, ClearItemParameters param) {
|
||||
return getOther(ItemType.ITEM_WEAPON, playerInventory, param)
|
||||
.filter(item -> item.getLevel() <= param.lvl)
|
||||
.filter(item -> item.getRefinement() < param.refinement);
|
||||
}
|
||||
|
||||
private Stream<GameItem> getRelics(Inventory playerInventory, ClearItemParameters param) {
|
||||
return getOther(ItemType.ITEM_RELIQUARY, playerInventory, param)
|
||||
.filter(item -> item.getLevel() <= param.lvl + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
Inventory playerInventory = targetPlayer.getInventory();
|
||||
ClearItemParameters param = new ClearItemParameters();
|
||||
|
||||
// Extract any tagged int arguments (e.g. "lv90", "x100", "r5")
|
||||
parseIntParameters(args, param, intCommandHandlers);
|
||||
|
||||
if (args.size() < 1) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
String playerString = targetPlayer.getNickname(); // Should probably be UID instead but whatever
|
||||
switch (args.get(0)) {
|
||||
case "wp" -> {
|
||||
playerInventory.removeItems(getWeapons(playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.weapons", playerString);
|
||||
}
|
||||
case "art" -> {
|
||||
playerInventory.removeItems(getRelics(playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.artifacts", playerString);
|
||||
}
|
||||
case "mat" -> {
|
||||
playerInventory.removeItems(getOther(ItemType.ITEM_MATERIAL, playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.materials", playerString);
|
||||
}
|
||||
case "all" -> {
|
||||
playerInventory.removeItems(getRelics(playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.artifacts", playerString);
|
||||
playerInventory.removeItems(getWeapons(playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.weapons", playerString);
|
||||
playerInventory.removeItems(getOther(ItemType.ITEM_MATERIAL, playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.materials", playerString);
|
||||
playerInventory.removeItems(getOther(ItemType.ITEM_FURNITURE, playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.furniture", playerString);
|
||||
playerInventory.removeItems(getOther(ItemType.ITEM_DISPLAY, playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.displays", playerString);
|
||||
playerInventory.removeItems(getOther(ItemType.ITEM_VIRTUAL, playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.virtuals", playerString);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.everything", playerString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClearItemParameters {
|
||||
@Setter
|
||||
public int lvl = 1;
|
||||
@Setter
|
||||
public int refinement = 1;
|
||||
@Setter
|
||||
public int rank = 4;
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.command.CommandHelpers.*;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.inventory.GameItem;
|
||||
import emu.grasscutter.game.inventory.Inventory;
|
||||
import emu.grasscutter.game.inventory.ItemType;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
import lombok.Setter;
|
||||
|
||||
@Command(
|
||||
label = "clear",
|
||||
usage = {"(all|wp|art|mat) [lv<max level>] [r<max refinement>] [<max rarity>*]"},
|
||||
permission = "player.clearinv",
|
||||
permissionTargeted = "player.clearinv.others")
|
||||
public final class ClearCommand implements CommandHandler {
|
||||
|
||||
private static final Map<Pattern, BiConsumer<ClearItemParameters, Integer>> intCommandHandlers =
|
||||
Map.ofEntries(
|
||||
Map.entry(lvlRegex, ClearItemParameters::setLvl),
|
||||
Map.entry(refineRegex, ClearItemParameters::setRefinement),
|
||||
Map.entry(rankRegex, ClearItemParameters::setRank));
|
||||
|
||||
private Stream<GameItem> getOther(
|
||||
ItemType type, Inventory playerInventory, ClearItemParameters param) {
|
||||
return playerInventory.getItems().values().stream()
|
||||
.filter(item -> item.getItemType() == type)
|
||||
.filter(item -> item.getItemData().getRankLevel() <= param.rank)
|
||||
.filter(item -> !item.isLocked() && !item.isEquipped());
|
||||
}
|
||||
|
||||
private Stream<GameItem> getWeapons(Inventory playerInventory, ClearItemParameters param) {
|
||||
return getOther(ItemType.ITEM_WEAPON, playerInventory, param)
|
||||
.filter(item -> item.getLevel() <= param.lvl)
|
||||
.filter(item -> item.getRefinement() < param.refinement);
|
||||
}
|
||||
|
||||
private Stream<GameItem> getRelics(Inventory playerInventory, ClearItemParameters param) {
|
||||
return getOther(ItemType.ITEM_RELIQUARY, playerInventory, param)
|
||||
.filter(item -> item.getLevel() <= param.lvl + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
Inventory playerInventory = targetPlayer.getInventory();
|
||||
ClearItemParameters param = new ClearItemParameters();
|
||||
|
||||
// Extract any tagged int arguments (e.g. "lv90", "x100", "r5")
|
||||
parseIntParameters(args, param, intCommandHandlers);
|
||||
|
||||
if (args.size() < 1) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
String playerString = targetPlayer.getNickname(); // Should probably be UID instead but whatever
|
||||
switch (args.get(0)) {
|
||||
case "wp" -> {
|
||||
playerInventory.removeItems(getWeapons(playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.weapons", playerString);
|
||||
}
|
||||
case "art" -> {
|
||||
playerInventory.removeItems(getRelics(playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.artifacts", playerString);
|
||||
}
|
||||
case "mat" -> {
|
||||
playerInventory.removeItems(
|
||||
getOther(ItemType.ITEM_MATERIAL, playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.materials", playerString);
|
||||
}
|
||||
case "all" -> {
|
||||
playerInventory.removeItems(getRelics(playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.artifacts", playerString);
|
||||
playerInventory.removeItems(getWeapons(playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.weapons", playerString);
|
||||
playerInventory.removeItems(
|
||||
getOther(ItemType.ITEM_MATERIAL, playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.materials", playerString);
|
||||
playerInventory.removeItems(
|
||||
getOther(ItemType.ITEM_FURNITURE, playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.furniture", playerString);
|
||||
playerInventory.removeItems(
|
||||
getOther(ItemType.ITEM_DISPLAY, playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.displays", playerString);
|
||||
playerInventory.removeItems(
|
||||
getOther(ItemType.ITEM_VIRTUAL, playerInventory, param).toList());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.virtuals", playerString);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.clear.everything", playerString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClearItemParameters {
|
||||
@Setter public int lvl = 1;
|
||||
@Setter public int refinement = 1;
|
||||
@Setter public int rank = 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +1,57 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Command(label = "coop", usage = {"[<host UID>]"}, permission = "server.coop", permissionTargeted = "server.coop.others")
|
||||
public final class CoopCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
Player host = sender;
|
||||
switch (args.size()) {
|
||||
case 0: // Summon target to self
|
||||
if (sender == null) { // Console doesn't have a self to summon to
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 1: // Summon target to argument
|
||||
try {
|
||||
int hostId = Integer.parseInt(args.get(0));
|
||||
host = Grasscutter.getGameServer().getPlayerByUid(hostId);
|
||||
if (host == null) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.execution.player_offline_error");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.invalid.uid");
|
||||
return;
|
||||
}
|
||||
default:
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
// There's no target==host check but this just places them in multiplayer in their own world which seems fine.
|
||||
if (targetPlayer.isInMultiplayer()) {
|
||||
targetPlayer.getServer().getMultiplayerSystem().leaveCoop(targetPlayer);
|
||||
}
|
||||
host.getServer().getMultiplayerSystem().applyEnterMp(targetPlayer, host.getUid());
|
||||
targetPlayer.getServer().getMultiplayerSystem().applyEnterMpReply(host, targetPlayer.getUid(), true);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.coop.success", targetPlayer.getNickname(), host.getNickname());
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "coop",
|
||||
usage = {"[<host UID>]"},
|
||||
permission = "server.coop",
|
||||
permissionTargeted = "server.coop.others")
|
||||
public final class CoopCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
Player host = sender;
|
||||
switch (args.size()) {
|
||||
case 0: // Summon target to self
|
||||
if (sender == null) { // Console doesn't have a self to summon to
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 1: // Summon target to argument
|
||||
try {
|
||||
int hostId = Integer.parseInt(args.get(0));
|
||||
host = Grasscutter.getGameServer().getPlayerByUid(hostId);
|
||||
if (host == null) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.execution.player_offline_error");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.invalid.uid");
|
||||
return;
|
||||
}
|
||||
default:
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
// There's no target==host check but this just places them in multiplayer in their own world
|
||||
// which seems fine.
|
||||
if (targetPlayer.isInMultiplayer()) {
|
||||
targetPlayer.getServer().getMultiplayerSystem().leaveCoop(targetPlayer);
|
||||
}
|
||||
host.getServer().getMultiplayerSystem().applyEnterMp(targetPlayer, host.getUid());
|
||||
targetPlayer
|
||||
.getServer()
|
||||
.getMultiplayerSystem()
|
||||
.applyEnterMpReply(host, targetPlayer.getUid(), true);
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.coop.success", targetPlayer.getNickname(), host.getNickname());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,50 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "enter_dungeon", aliases = {"enterdungeon", "dungeon"}, usage = {"<dungeonId>"}, permission = "player.enterdungeon", permissionTargeted = "player.enterdungeon.others")
|
||||
public final class EnterDungeonCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 1) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int dungeonId = Integer.parseInt(args.get(0));
|
||||
if (dungeonId == targetPlayer.getSceneId()) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.enter_dungeon.in_dungeon_error"));
|
||||
return;
|
||||
}
|
||||
|
||||
boolean result = targetPlayer.getServer().getDungeonSystem().enterDungeon(targetPlayer.getSession().getPlayer(), 0, dungeonId);
|
||||
|
||||
if (!result) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.enter_dungeon.not_found_error"));
|
||||
} else {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.enter_dungeon.changed", dungeonId));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
sendUsageMessage(sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "enter_dungeon",
|
||||
aliases = {"enterdungeon", "dungeon"},
|
||||
usage = {"<dungeonId>"},
|
||||
permission = "player.enterdungeon",
|
||||
permissionTargeted = "player.enterdungeon.others")
|
||||
public final class EnterDungeonCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 1) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int dungeonId = Integer.parseInt(args.get(0));
|
||||
if (dungeonId == targetPlayer.getSceneId()) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.enter_dungeon.in_dungeon_error"));
|
||||
return;
|
||||
}
|
||||
|
||||
boolean result =
|
||||
targetPlayer
|
||||
.getServer()
|
||||
.getDungeonSystem()
|
||||
.enterDungeon(targetPlayer.getSession().getPlayer(), 0, dungeonId);
|
||||
|
||||
if (!result) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.enter_dungeon.not_found_error"));
|
||||
} else {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.enter_dungeon.changed", dungeonId));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
sendUsageMessage(sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,44 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "heal", aliases = {"h"}, permission = "player.heal", permissionTargeted = "player.heal.others")
|
||||
public final class HealCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
targetPlayer.getTeamManager().getActiveTeam().forEach(entity -> {
|
||||
boolean isAlive = entity.isAlive();
|
||||
entity.setFightProperty(
|
||||
FightProperty.FIGHT_PROP_CUR_HP,
|
||||
entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP)
|
||||
);
|
||||
entity.getWorld().broadcastPacket(new PacketAvatarFightPropUpdateNotify(entity.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP));
|
||||
if (!isAlive) {
|
||||
entity.getWorld().broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar()));
|
||||
}
|
||||
});
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.heal.success"));
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "heal",
|
||||
aliases = {"h"},
|
||||
permission = "player.heal",
|
||||
permissionTargeted = "player.heal.others")
|
||||
public final class HealCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
targetPlayer
|
||||
.getTeamManager()
|
||||
.getActiveTeam()
|
||||
.forEach(
|
||||
entity -> {
|
||||
boolean isAlive = entity.isAlive();
|
||||
entity.setFightProperty(
|
||||
FightProperty.FIGHT_PROP_CUR_HP,
|
||||
entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP));
|
||||
entity
|
||||
.getWorld()
|
||||
.broadcastPacket(
|
||||
new PacketAvatarFightPropUpdateNotify(
|
||||
entity.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP));
|
||||
if (!isAlive) {
|
||||
entity
|
||||
.getWorld()
|
||||
.broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar()));
|
||||
}
|
||||
});
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.heal.success"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,83 +1,92 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.command.CommandMap;
|
||||
import emu.grasscutter.game.Account;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "help", usage = {"[<command>]"}, targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class HelpCommand implements CommandHandler {
|
||||
private final boolean SHOW_COMMANDS_WITHOUT_PERMISSIONS = false; // TODO: Make this into a server config key
|
||||
|
||||
private String createCommand(Player player, CommandHandler command, List<String> args) {
|
||||
StringBuilder builder = new StringBuilder(command.getLabel())
|
||||
.append(" - ")
|
||||
.append(command.getDescriptionString(player))
|
||||
.append("\n\t")
|
||||
.append(command.getUsageString(player, args.toArray(new String[0])));
|
||||
|
||||
Command annotation = command.getClass().getAnnotation(Command.class);
|
||||
if (annotation.aliases().length > 0) {
|
||||
builder.append("\n\t").append(translate(player, "commands.help.aliases"));
|
||||
for (String alias : annotation.aliases()) {
|
||||
builder.append(alias).append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
builder.append("\n\t").append(translate(player, "commands.help.tip_need_permission"));
|
||||
if (!annotation.permission().isEmpty()) {
|
||||
builder.append(annotation.permission());
|
||||
} else {
|
||||
builder.append(translate(player, "commands.help.tip_need_no_permission"));
|
||||
}
|
||||
|
||||
if (!annotation.permissionTargeted().isEmpty()) {
|
||||
String permissionTargeted = annotation.permissionTargeted();
|
||||
builder.append(" ").append(translate(player, "commands.help.tip_permission_targeted", permissionTargeted));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, Player targetPlayer, List<String> args) {
|
||||
Account account = (player == null) ? null : player.getAccount();
|
||||
var commandMap = CommandMap.getInstance();
|
||||
List<String> commands = new ArrayList<>();
|
||||
List<String> commands_no_permission = new ArrayList<>();
|
||||
if (args.isEmpty()) {
|
||||
commandMap.getHandlers().forEach((key, command) -> {
|
||||
Command annotation = command.getClass().getAnnotation(Command.class);
|
||||
if (player == null || account.hasPermission(annotation.permission())) {
|
||||
commands.add(createCommand(player, command, args));
|
||||
} else if (SHOW_COMMANDS_WITHOUT_PERMISSIONS) {
|
||||
commands_no_permission.add(createCommand(player, command, args));
|
||||
}
|
||||
});
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.help.available_commands");
|
||||
} else {
|
||||
String command_str = args.remove(0).toLowerCase();
|
||||
CommandHandler command = commandMap.getHandler(command_str);
|
||||
if (command == null) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.generic.command_exist_error");
|
||||
CommandHandler.sendMessage(player, "Command: " + command_str);
|
||||
return;
|
||||
} else {
|
||||
Command annotation = command.getClass().getAnnotation(Command.class);
|
||||
if (player == null || account.hasPermission(annotation.permission())) {
|
||||
commands.add(createCommand(player, command, args));
|
||||
} else {
|
||||
commands_no_permission.add(createCommand(player, command, args));
|
||||
}
|
||||
}
|
||||
}
|
||||
final String suf = "\n\t" + translate(player, "commands.help.warn_player_has_no_permission");
|
||||
commands.forEach(s -> CommandHandler.sendMessage(player, s));
|
||||
commands_no_permission.forEach(s -> CommandHandler.sendMessage(player, s + suf));
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.command.CommandMap;
|
||||
import emu.grasscutter.game.Account;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "help",
|
||||
usage = {"[<command>]"},
|
||||
targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class HelpCommand implements CommandHandler {
|
||||
private final boolean SHOW_COMMANDS_WITHOUT_PERMISSIONS =
|
||||
false; // TODO: Make this into a server config key
|
||||
|
||||
private String createCommand(Player player, CommandHandler command, List<String> args) {
|
||||
StringBuilder builder =
|
||||
new StringBuilder(command.getLabel())
|
||||
.append(" - ")
|
||||
.append(command.getDescriptionString(player))
|
||||
.append("\n\t")
|
||||
.append(command.getUsageString(player, args.toArray(new String[0])));
|
||||
|
||||
Command annotation = command.getClass().getAnnotation(Command.class);
|
||||
if (annotation.aliases().length > 0) {
|
||||
builder.append("\n\t").append(translate(player, "commands.help.aliases"));
|
||||
for (String alias : annotation.aliases()) {
|
||||
builder.append(alias).append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
builder.append("\n\t").append(translate(player, "commands.help.tip_need_permission"));
|
||||
if (!annotation.permission().isEmpty()) {
|
||||
builder.append(annotation.permission());
|
||||
} else {
|
||||
builder.append(translate(player, "commands.help.tip_need_no_permission"));
|
||||
}
|
||||
|
||||
if (!annotation.permissionTargeted().isEmpty()) {
|
||||
String permissionTargeted = annotation.permissionTargeted();
|
||||
builder
|
||||
.append(" ")
|
||||
.append(translate(player, "commands.help.tip_permission_targeted", permissionTargeted));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player player, Player targetPlayer, List<String> args) {
|
||||
Account account = (player == null) ? null : player.getAccount();
|
||||
var commandMap = CommandMap.getInstance();
|
||||
List<String> commands = new ArrayList<>();
|
||||
List<String> commands_no_permission = new ArrayList<>();
|
||||
if (args.isEmpty()) {
|
||||
commandMap
|
||||
.getHandlers()
|
||||
.forEach(
|
||||
(key, command) -> {
|
||||
Command annotation = command.getClass().getAnnotation(Command.class);
|
||||
if (player == null || account.hasPermission(annotation.permission())) {
|
||||
commands.add(createCommand(player, command, args));
|
||||
} else if (SHOW_COMMANDS_WITHOUT_PERMISSIONS) {
|
||||
commands_no_permission.add(createCommand(player, command, args));
|
||||
}
|
||||
});
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.help.available_commands");
|
||||
} else {
|
||||
String command_str = args.remove(0).toLowerCase();
|
||||
CommandHandler command = commandMap.getHandler(command_str);
|
||||
if (command == null) {
|
||||
CommandHandler.sendTranslatedMessage(player, "commands.generic.command_exist_error");
|
||||
CommandHandler.sendMessage(player, "Command: " + command_str);
|
||||
return;
|
||||
} else {
|
||||
Command annotation = command.getClass().getAnnotation(Command.class);
|
||||
if (player == null || account.hasPermission(annotation.permission())) {
|
||||
commands.add(createCommand(player, command, args));
|
||||
} else {
|
||||
commands_no_permission.add(createCommand(player, command, args));
|
||||
}
|
||||
}
|
||||
}
|
||||
final String suf = "\n\t" + translate(player, "commands.help.warn_player_has_no_permission");
|
||||
commands.forEach(s -> CommandHandler.sendMessage(player, s));
|
||||
commands_no_permission.forEach(s -> CommandHandler.sendMessage(player, s + suf));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Command(label = "kick", aliases = {"restart"}, permissionTargeted = "server.kick")
|
||||
public final class KickCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (sender != null) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.kick.player_kick_player",
|
||||
sender.getUid(), sender.getAccount().getUsername(),
|
||||
targetPlayer.getUid(), targetPlayer.getAccount().getUsername());
|
||||
} else {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.kick.server_kick_player",
|
||||
targetPlayer.getUid(), targetPlayer.getAccount().getUsername());
|
||||
}
|
||||
|
||||
targetPlayer.getSession().close();
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "kick",
|
||||
aliases = {"restart"},
|
||||
permissionTargeted = "server.kick")
|
||||
public final class KickCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (sender != null) {
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender,
|
||||
"commands.kick.player_kick_player",
|
||||
sender.getUid(),
|
||||
sender.getAccount().getUsername(),
|
||||
targetPlayer.getUid(),
|
||||
targetPlayer.getAccount().getUsername());
|
||||
} else {
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender,
|
||||
"commands.kick.server_kick_player",
|
||||
targetPlayer.getUid(),
|
||||
targetPlayer.getAccount().getUsername());
|
||||
}
|
||||
|
||||
targetPlayer.getSession().close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +1,54 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.entity.EntityMonster;
|
||||
import emu.grasscutter.game.entity.GameEntity;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "killall", usage = {"[<sceneId>]"}, permission = "server.killall", permissionTargeted = "server.killall.others")
|
||||
public final class KillAllCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
Scene scene = targetPlayer.getScene();
|
||||
try {
|
||||
switch (args.size()) {
|
||||
case 0: // *No args*
|
||||
break;
|
||||
case 1: // [sceneId]
|
||||
scene = targetPlayer.getWorld().getSceneById(Integer.parseInt(args.get(0)));
|
||||
break;
|
||||
default:
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.execution.argument_error"));
|
||||
}
|
||||
if (scene == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.killall.scene_not_found_in_player_world"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Separate into list to avoid concurrency issue
|
||||
final Scene sceneF = scene;
|
||||
List<GameEntity> toKill = sceneF.getEntities().values().stream()
|
||||
.filter(entity -> entity instanceof EntityMonster)
|
||||
.toList();
|
||||
toKill.forEach(entity -> sceneF.killEntity(entity, 0));
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.killall.kill_monsters_in_scene", toKill.size(), scene.getId()));
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.entity.EntityMonster;
|
||||
import emu.grasscutter.game.entity.GameEntity;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "killall",
|
||||
usage = {"[<sceneId>]"},
|
||||
permission = "server.killall",
|
||||
permissionTargeted = "server.killall.others")
|
||||
public final class KillAllCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
Scene scene = targetPlayer.getScene();
|
||||
try {
|
||||
switch (args.size()) {
|
||||
case 0: // *No args*
|
||||
break;
|
||||
case 1: // [sceneId]
|
||||
scene = targetPlayer.getWorld().getSceneById(Integer.parseInt(args.get(0)));
|
||||
break;
|
||||
default:
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.execution.argument_error"));
|
||||
}
|
||||
if (scene == null) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.killall.scene_not_found_in_player_world"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Separate into list to avoid concurrency issue
|
||||
final Scene sceneF = scene;
|
||||
List<GameEntity> toKill =
|
||||
sceneF.getEntities().values().stream()
|
||||
.filter(entity -> entity instanceof EntityMonster)
|
||||
.toList();
|
||||
toKill.forEach(entity -> sceneF.killEntity(entity, 0));
|
||||
CommandHandler.sendMessage(
|
||||
sender,
|
||||
translate(sender, "commands.killall.kill_monsters_in_scene", toKill.size(), scene.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,41 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.props.LifeState;
|
||||
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "killCharacter", aliases = {"suicide", "kill"}, permission = "player.killcharacter", permissionTargeted = "player.killcharacter.others")
|
||||
public final class KillCharacterCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
EntityAvatar entity = targetPlayer.getTeamManager().getCurrentAvatarEntity();
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0f);
|
||||
// Packets
|
||||
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP));
|
||||
entity.getWorld().broadcastPacket(new PacketLifeStateChangeNotify(0, entity, LifeState.LIFE_DEAD));
|
||||
// remove
|
||||
targetPlayer.getScene().removeEntity(entity);
|
||||
entity.onDeath(0);
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.killCharacter.success", targetPlayer.getNickname()));
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.props.LifeState;
|
||||
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "killCharacter",
|
||||
aliases = {"suicide", "kill"},
|
||||
permission = "player.killcharacter",
|
||||
permissionTargeted = "player.killcharacter.others")
|
||||
public final class KillCharacterCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
EntityAvatar entity = targetPlayer.getTeamManager().getCurrentAvatarEntity();
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0f);
|
||||
// Packets
|
||||
entity
|
||||
.getWorld()
|
||||
.broadcastPacket(
|
||||
new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP));
|
||||
entity
|
||||
.getWorld()
|
||||
.broadcastPacket(new PacketLifeStateChangeNotify(0, entity, LifeState.LIFE_DEAD));
|
||||
// remove
|
||||
targetPlayer.getScene().removeEntity(entity);
|
||||
entity.onDeath(0);
|
||||
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.killCharacter.success", targetPlayer.getNickname()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,53 +1,58 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "language", usage = {"[<language code>]"}, aliases = {"lang"}, targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class LanguageCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.isEmpty()) {
|
||||
String curLangCode = null;
|
||||
if (sender != null) {
|
||||
curLangCode = Utils.getLanguageCode(sender.getAccount().getLocale());
|
||||
} else {
|
||||
curLangCode = Grasscutter.getLanguage().getLanguageCode();
|
||||
}
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.language.current_language", curLangCode));
|
||||
return;
|
||||
}
|
||||
|
||||
String langCode = args.get(0);
|
||||
|
||||
var languageInst = Grasscutter.getLanguage(langCode);
|
||||
var actualLangCode = languageInst.getLanguageCode();
|
||||
var locale = Locale.forLanguageTag(actualLangCode);
|
||||
if (sender != null) {
|
||||
var account = sender.getAccount();
|
||||
account.setLocale(locale);
|
||||
account.save();
|
||||
} else {
|
||||
Grasscutter.setLanguage(languageInst);
|
||||
var config = Grasscutter.getConfig();
|
||||
config.language.language = locale;
|
||||
Grasscutter.saveConfig(config);
|
||||
}
|
||||
|
||||
if (!langCode.equals(actualLangCode)) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.language.language_not_found", langCode));
|
||||
}
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.language.language_changed", actualLangCode));
|
||||
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@Command(
|
||||
label = "language",
|
||||
usage = {"[<language code>]"},
|
||||
aliases = {"lang"},
|
||||
targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class LanguageCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.isEmpty()) {
|
||||
String curLangCode = null;
|
||||
if (sender != null) {
|
||||
curLangCode = Utils.getLanguageCode(sender.getAccount().getLocale());
|
||||
} else {
|
||||
curLangCode = Grasscutter.getLanguage().getLanguageCode();
|
||||
}
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.language.current_language", curLangCode));
|
||||
return;
|
||||
}
|
||||
|
||||
String langCode = args.get(0);
|
||||
|
||||
var languageInst = Grasscutter.getLanguage(langCode);
|
||||
var actualLangCode = languageInst.getLanguageCode();
|
||||
var locale = Locale.forLanguageTag(actualLangCode);
|
||||
if (sender != null) {
|
||||
var account = sender.getAccount();
|
||||
account.setLocale(locale);
|
||||
account.save();
|
||||
} else {
|
||||
Grasscutter.setLanguage(languageInst);
|
||||
var config = Grasscutter.getConfig();
|
||||
config.language.language = locale;
|
||||
Grasscutter.saveConfig(config);
|
||||
}
|
||||
|
||||
if (!langCode.equals(actualLangCode)) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.language.language_not_found", langCode));
|
||||
}
|
||||
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.language.language_changed", actualLangCode));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,53 +1,56 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "list", aliases = {"players"}, usage = {"[<UID>]"}, targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class ListCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
Map<Integer, Player> playersMap = Grasscutter.getGameServer().getPlayers();
|
||||
boolean needUID = false;
|
||||
|
||||
if (args.size() > 0) {
|
||||
needUID = args.get(0).equals("uid");
|
||||
}
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.list.success", playersMap.size()));
|
||||
|
||||
if (playersMap.size() != 0) {
|
||||
StringBuilder playerSet = new StringBuilder();
|
||||
boolean finalNeedUID = needUID;
|
||||
|
||||
playersMap.values().forEach(player -> {
|
||||
playerSet.append(player.getNickname());
|
||||
|
||||
if (finalNeedUID) {
|
||||
if (sender != null) {
|
||||
playerSet.append(" <color=green>(")
|
||||
.append(player.getUid())
|
||||
.append(")</color>");
|
||||
} else {
|
||||
playerSet.append(" (")
|
||||
.append(player.getUid())
|
||||
.append(")");
|
||||
}
|
||||
}
|
||||
|
||||
playerSet.append(", ");
|
||||
});
|
||||
|
||||
String players = playerSet.toString();
|
||||
CommandHandler.sendMessage(sender, players.substring(0, players.length() - 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Command(
|
||||
label = "list",
|
||||
aliases = {"players"},
|
||||
usage = {"[<UID>]"},
|
||||
targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class ListCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
Map<Integer, Player> playersMap = Grasscutter.getGameServer().getPlayers();
|
||||
boolean needUID = false;
|
||||
|
||||
if (args.size() > 0) {
|
||||
needUID = args.get(0).equals("uid");
|
||||
}
|
||||
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.list.success", playersMap.size()));
|
||||
|
||||
if (playersMap.size() != 0) {
|
||||
StringBuilder playerSet = new StringBuilder();
|
||||
boolean finalNeedUID = needUID;
|
||||
|
||||
playersMap
|
||||
.values()
|
||||
.forEach(
|
||||
player -> {
|
||||
playerSet.append(player.getNickname());
|
||||
|
||||
if (finalNeedUID) {
|
||||
if (sender != null) {
|
||||
playerSet.append(" <color=green>(").append(player.getUid()).append(")</color>");
|
||||
} else {
|
||||
playerSet.append(" (").append(player.getUid()).append(")");
|
||||
}
|
||||
}
|
||||
|
||||
playerSet.append(", ");
|
||||
});
|
||||
|
||||
String players = playerSet.toString();
|
||||
CommandHandler.sendMessage(sender, players.substring(0, players.length() - 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +1,74 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.Command.TargetRequirement;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.Account;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "permission", usage = {
|
||||
"add <permission>",
|
||||
"remove <permission>",
|
||||
"clear",
|
||||
"list"
|
||||
}, permission = "permission", targetRequirement = TargetRequirement.PLAYER)
|
||||
public final class PermissionCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.isEmpty() || args.size() > 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Grasscutter.getPermissionHandler().EnablePermissionCommand()) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.permission_error");
|
||||
return;
|
||||
}
|
||||
|
||||
String action = args.get(0);
|
||||
String permission = "";
|
||||
if (args.size() > 1) {
|
||||
permission = args.get(1);
|
||||
}
|
||||
|
||||
Account account = targetPlayer.getAccount();
|
||||
if (account == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.permission.account_error"));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
default:
|
||||
sendUsageMessage(sender);
|
||||
break;
|
||||
case "add":
|
||||
if (permission.isEmpty()) {
|
||||
sendUsageMessage(sender);
|
||||
} else if (account.addPermission(permission)) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.permission.add"));
|
||||
} else CommandHandler.sendMessage(sender, translate(sender, "commands.permission.has_error"));
|
||||
break;
|
||||
case "remove":
|
||||
if (account.removePermission(permission)) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.permission.remove"));
|
||||
} else CommandHandler.sendMessage(sender, translate(sender, "commands.permission.not_have_error"));
|
||||
break;
|
||||
case "clear":
|
||||
account.clearPermission();
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.permission.remove"));
|
||||
break;
|
||||
case "list":
|
||||
CommandHandler.sendMessage(sender, String.join("\n", account.getPermissions()));
|
||||
break;
|
||||
}
|
||||
|
||||
account.save();
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.Command.TargetRequirement;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.Account;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "permission",
|
||||
usage = {"add <permission>", "remove <permission>", "clear", "list"},
|
||||
permission = "permission",
|
||||
targetRequirement = TargetRequirement.PLAYER)
|
||||
public final class PermissionCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.isEmpty() || args.size() > 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Grasscutter.getPermissionHandler().EnablePermissionCommand()) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.permission_error");
|
||||
return;
|
||||
}
|
||||
|
||||
String action = args.get(0);
|
||||
String permission = "";
|
||||
if (args.size() > 1) {
|
||||
permission = args.get(1);
|
||||
}
|
||||
|
||||
Account account = targetPlayer.getAccount();
|
||||
if (account == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.permission.account_error"));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
default:
|
||||
sendUsageMessage(sender);
|
||||
break;
|
||||
case "add":
|
||||
if (permission.isEmpty()) {
|
||||
sendUsageMessage(sender);
|
||||
} else if (account.addPermission(permission)) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.permission.add"));
|
||||
} else
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.permission.has_error"));
|
||||
break;
|
||||
case "remove":
|
||||
if (account.removePermission(permission)) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.permission.remove"));
|
||||
} else
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.permission.not_have_error"));
|
||||
break;
|
||||
case "clear":
|
||||
account.clearPermission();
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.permission.remove"));
|
||||
break;
|
||||
case "list":
|
||||
CommandHandler.sendMessage(sender, String.join("\n", account.getPermissions()));
|
||||
break;
|
||||
}
|
||||
|
||||
account.save();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,29 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.utils.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Command(label = "position", aliases = {"pos"})
|
||||
public final class PositionCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
Position pos = targetPlayer.getPosition();
|
||||
Position rot = targetPlayer.getRotation();
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.position.success",
|
||||
pos.getX(), pos.getY(), pos.getZ(), rot.getX(), rot.getY(), rot.getZ(), targetPlayer.getSceneId());
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "position",
|
||||
aliases = {"pos"})
|
||||
public final class PositionCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
Position pos = targetPlayer.getPosition();
|
||||
Position rot = targetPlayer.getRotation();
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender,
|
||||
"commands.position.success",
|
||||
pos.getX(),
|
||||
pos.getY(),
|
||||
pos.getZ(),
|
||||
rot.getX(),
|
||||
rot.getY(),
|
||||
rot.getZ(),
|
||||
targetPlayer.getSceneId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,64 +1,64 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.quest.GameQuest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "quest",
|
||||
aliases = {"q"},
|
||||
usage = {"(add|finish) [<questId>]"},
|
||||
permission = "player.quest",
|
||||
permissionTargeted = "player.quest.others")
|
||||
public final class QuestCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() != 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
String cmd = args.get(0).toLowerCase();
|
||||
int questId;
|
||||
|
||||
try {
|
||||
questId = Integer.parseInt(args.get(1));
|
||||
} catch (Exception e) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.quest.invalid_id"));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case "add" -> {
|
||||
GameQuest quest = targetPlayer.getQuestManager().addQuest(questId);
|
||||
|
||||
if (quest != null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.quest.added", questId));
|
||||
return;
|
||||
}
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.quest.not_found"));
|
||||
}
|
||||
case "finish" -> {
|
||||
GameQuest quest = targetPlayer.getQuestManager().getQuestById(questId);
|
||||
|
||||
if (quest == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.quest.not_found"));
|
||||
return;
|
||||
}
|
||||
|
||||
quest.finish();
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.quest.finished", questId));
|
||||
}
|
||||
default -> {
|
||||
sendUsageMessage(sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.quest.GameQuest;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "quest",
|
||||
aliases = {"q"},
|
||||
usage = {"(add|finish) [<questId>]"},
|
||||
permission = "player.quest",
|
||||
permissionTargeted = "player.quest.others")
|
||||
public final class QuestCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() != 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
String cmd = args.get(0).toLowerCase();
|
||||
int questId;
|
||||
|
||||
try {
|
||||
questId = Integer.parseInt(args.get(1));
|
||||
} catch (Exception e) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.quest.invalid_id"));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case "add" -> {
|
||||
GameQuest quest = targetPlayer.getQuestManager().addQuest(questId);
|
||||
|
||||
if (quest != null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.quest.added", questId));
|
||||
return;
|
||||
}
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.quest.not_found"));
|
||||
}
|
||||
case "finish" -> {
|
||||
GameQuest quest = targetPlayer.getQuestManager().getQuestById(questId);
|
||||
|
||||
if (quest == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.quest.not_found"));
|
||||
return;
|
||||
}
|
||||
|
||||
quest.finish();
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.quest.finished", questId));
|
||||
}
|
||||
default -> {
|
||||
sendUsageMessage(sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "reload", permission = "server.reload", targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class ReloadCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.reload.reload_start"));
|
||||
|
||||
Grasscutter.loadConfig();
|
||||
Grasscutter.loadLanguage();
|
||||
Grasscutter.getGameServer().getGachaSystem().load();
|
||||
Grasscutter.getGameServer().getDropSystem().load();
|
||||
Grasscutter.getGameServer().getShopSystem().load();
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.reload.reload_done"));
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "reload",
|
||||
permission = "server.reload",
|
||||
targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class ReloadCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.reload.reload_start"));
|
||||
|
||||
Grasscutter.loadConfig();
|
||||
Grasscutter.loadLanguage();
|
||||
Grasscutter.getGameServer().getGachaSystem().load();
|
||||
Grasscutter.getGameServer().getDropSystem().load();
|
||||
Grasscutter.getGameServer().getShopSystem().load();
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.reload.reload_done"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +1,43 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(
|
||||
label = "resetConst",
|
||||
aliases = {"resetconstellation"},
|
||||
usage = "[all]",
|
||||
permission = "player.resetconstellation",
|
||||
permissionTargeted = "player.resetconstellation.others")
|
||||
public final class ResetConstCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() > 0 && args.get(0).equalsIgnoreCase("all")) {
|
||||
targetPlayer.getAvatars().forEach(this::resetConstellation);
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.resetConst.reset_all"));
|
||||
} else {
|
||||
EntityAvatar entity = targetPlayer.getTeamManager().getCurrentAvatarEntity();
|
||||
if (entity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Avatar avatar = entity.getAvatar();
|
||||
this.resetConstellation(avatar);
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.resetConst.success", avatar.getAvatarData().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
private void resetConstellation(Avatar avatar) {
|
||||
avatar.forceConstellationLevel(-1);
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "resetConst",
|
||||
aliases = {"resetconstellation"},
|
||||
usage = "[all]",
|
||||
permission = "player.resetconstellation",
|
||||
permissionTargeted = "player.resetconstellation.others")
|
||||
public final class ResetConstCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() > 0 && args.get(0).equalsIgnoreCase("all")) {
|
||||
targetPlayer.getAvatars().forEach(this::resetConstellation);
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.resetConst.reset_all"));
|
||||
} else {
|
||||
EntityAvatar entity = targetPlayer.getTeamManager().getCurrentAvatarEntity();
|
||||
if (entity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Avatar avatar = entity.getAvatar();
|
||||
this.resetConstellation(avatar);
|
||||
|
||||
CommandHandler.sendMessage(
|
||||
sender,
|
||||
translate(sender, "commands.resetConst.success", avatar.getAvatarData().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
private void resetConstellation(Avatar avatar) {
|
||||
avatar.forceConstellationLevel(-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "resetShopLimit", aliases = {"resetshop"}, permission = "server.resetshop", permissionTargeted = "server.resetshop.others")
|
||||
public final class ResetShopLimitCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
targetPlayer.getShopLimit().forEach(x -> x.setNextRefreshTime(0));
|
||||
targetPlayer.save();
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.resetShopLimit.success"));
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "resetShopLimit",
|
||||
aliases = {"resetshop"},
|
||||
permission = "server.resetshop",
|
||||
permissionTargeted = "server.resetshop.others")
|
||||
public final class ResetShopLimitCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
targetPlayer.getShopLimit().forEach(x -> x.setNextRefreshTime(0));
|
||||
targetPlayer.save();
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.resetShopLimit.success"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,202 +1,241 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.mail.Mail;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Command(
|
||||
label = "sendMail",
|
||||
usage = {"(<userId>|all) [<templateId>]", "help"},
|
||||
permission = "server.sendmail",
|
||||
targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class SendMailCommand implements CommandHandler {
|
||||
|
||||
// TODO: You should be able to do /sendmail and then just send subsequent messages until you finish
|
||||
// However, due to the current nature of the command system, I don't think this is possible without rewriting
|
||||
// the command system (again). For now this will do
|
||||
|
||||
// Key = User that is constructing the mail.
|
||||
private static final HashMap<Integer, MailBuilder> mailBeingConstructed = new HashMap<Integer, MailBuilder>();
|
||||
|
||||
// Yes this is awful and I hate it.
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
int senderId;
|
||||
if (sender != null) {
|
||||
senderId = sender.getUid();
|
||||
} else {
|
||||
senderId = -1;
|
||||
}
|
||||
|
||||
if (!mailBeingConstructed.containsKey(senderId)) {
|
||||
switch (args.size()) {
|
||||
case 1 -> {
|
||||
MailBuilder mailBuilder;
|
||||
switch (args.get(0).toLowerCase()) {
|
||||
case "help" -> {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
case "all" -> mailBuilder = new MailBuilder(true, new Mail());
|
||||
default -> {
|
||||
if (DatabaseHelper.getPlayerByUid(Integer.parseInt(args.get(0))) != null) {
|
||||
mailBuilder = new MailBuilder(Integer.parseInt(args.get(0)), new Mail());
|
||||
} else {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.user_not_exist", args.get(0)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
mailBeingConstructed.put(senderId, mailBuilder);
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.start_composition"));
|
||||
}
|
||||
case 2 -> CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.templates"));
|
||||
default -> CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.invalid_arguments"));
|
||||
}
|
||||
} else {
|
||||
MailBuilder mailBuilder = mailBeingConstructed.get(senderId);
|
||||
|
||||
if (args.size() >= 1) {
|
||||
switch (args.get(0).toLowerCase()) {
|
||||
case "stop" -> {
|
||||
mailBeingConstructed.remove(senderId);
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.send_cancel"));
|
||||
}
|
||||
case "finish" -> {
|
||||
if (mailBuilder.constructionStage == 3) {
|
||||
if (!mailBuilder.sendToAll) {
|
||||
Grasscutter.getGameServer().getPlayerByUid(mailBuilder.recipient, true).sendMail(mailBuilder.mail);
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.send_done", mailBuilder.recipient));
|
||||
} else {
|
||||
DatabaseHelper.getByGameClass(Player.class).forEach(player -> {
|
||||
var onlinePlayer = Grasscutter.getGameServer().getPlayerByUid(player.getUid(), false);
|
||||
Objects.requireNonNullElse(onlinePlayer, player).sendMail(mailBuilder.mail);
|
||||
});
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.send_all_done"));
|
||||
}
|
||||
mailBeingConstructed.remove(senderId);
|
||||
} else {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.not_composition_end", getConstructionArgs(mailBuilder.constructionStage, sender)));
|
||||
}
|
||||
}
|
||||
case "help" -> {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.please_use", getConstructionArgs(mailBuilder.constructionStage, sender)));
|
||||
}
|
||||
default -> {
|
||||
switch (mailBuilder.constructionStage) {
|
||||
case 0 -> {
|
||||
String title = String.join(" ", args.subList(0, args.size()));
|
||||
mailBuilder.mail.mailContent.title = title;
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.set_title", title));
|
||||
mailBuilder.constructionStage++;
|
||||
}
|
||||
case 1 -> {
|
||||
String contents = String.join(" ", args.subList(0, args.size()));
|
||||
mailBuilder.mail.mailContent.content = contents;
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.set_contents", contents));
|
||||
mailBuilder.constructionStage++;
|
||||
}
|
||||
case 2 -> {
|
||||
String msgSender = String.join(" ", args.subList(0, args.size()));
|
||||
mailBuilder.mail.mailContent.sender = msgSender;
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.set_message_sender", msgSender));
|
||||
mailBuilder.constructionStage++;
|
||||
}
|
||||
case 3 -> {
|
||||
int item;
|
||||
int lvl = 1;
|
||||
int amount = 1;
|
||||
int refinement = 0;
|
||||
switch (args.size()) {
|
||||
case 4: // <itemId|itemName> [amount] [level] [refinement] // TODO: this requires Mail support but there's no harm leaving it here for now
|
||||
try {
|
||||
refinement = Integer.parseInt(args.get(3));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemRefinement"));
|
||||
return;
|
||||
} // Fallthrough
|
||||
case 3: // <itemId|itemName> [amount] [level]
|
||||
try {
|
||||
lvl = Integer.parseInt(args.get(2));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemLevel"));
|
||||
return;
|
||||
} // Fallthrough
|
||||
case 2: // <itemId|itemName> [amount]
|
||||
try {
|
||||
amount = Integer.parseInt(args.get(1));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.amount"));
|
||||
return;
|
||||
} // Fallthrough
|
||||
case 1: // <itemId|itemName>
|
||||
try {
|
||||
item = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException ignored) {
|
||||
// TODO: Parse from item name using GM Handbook.
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemId"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default: // *No args*
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.sendMail.give_usage");
|
||||
return;
|
||||
}
|
||||
mailBuilder.mail.itemList.add(new Mail.MailItem(item, amount, lvl));
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.send", amount, item, lvl));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.invalid_arguments_please_use", getConstructionArgs(mailBuilder.constructionStage, sender)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getConstructionArgs(int stage, Player sender) {
|
||||
return switch (stage) {
|
||||
case 0 -> translate(sender, "commands.sendMail.title");
|
||||
case 1 -> translate(sender, "commands.sendMail.message");
|
||||
case 2 -> translate(sender, "commands.sendMail.sender");
|
||||
case 3 -> translate(sender, "commands.sendMail.arguments");
|
||||
default -> translate(sender, "commands.sendMail.error", stage);
|
||||
};
|
||||
}
|
||||
|
||||
public static class MailBuilder {
|
||||
public int recipient;
|
||||
public boolean sendToAll;
|
||||
public int constructionStage;
|
||||
public Mail mail;
|
||||
|
||||
public MailBuilder(int recipient, Mail mail) {
|
||||
this.recipient = recipient;
|
||||
this.sendToAll = false;
|
||||
this.constructionStage = 0;
|
||||
this.mail = mail;
|
||||
}
|
||||
|
||||
public MailBuilder(boolean sendToAll, Mail mail) {
|
||||
if (sendToAll) {
|
||||
this.recipient = 0;
|
||||
this.sendToAll = true;
|
||||
this.constructionStage = 0;
|
||||
this.mail = mail;
|
||||
} else {
|
||||
Grasscutter.getLogger().error("Please use MailBuilder(int, mail) when not sending to all");
|
||||
Thread.dumpStack();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.mail.Mail;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Command(
|
||||
label = "sendMail",
|
||||
usage = {"(<userId>|all) [<templateId>]", "help"},
|
||||
permission = "server.sendmail",
|
||||
targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class SendMailCommand implements CommandHandler {
|
||||
|
||||
// TODO: You should be able to do /sendmail and then just send subsequent messages until you
|
||||
// finish
|
||||
// However, due to the current nature of the command system, I don't think this is possible
|
||||
// without rewriting
|
||||
// the command system (again). For now this will do
|
||||
|
||||
// Key = User that is constructing the mail.
|
||||
private static final HashMap<Integer, MailBuilder> mailBeingConstructed =
|
||||
new HashMap<Integer, MailBuilder>();
|
||||
|
||||
// Yes this is awful and I hate it.
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
int senderId;
|
||||
if (sender != null) {
|
||||
senderId = sender.getUid();
|
||||
} else {
|
||||
senderId = -1;
|
||||
}
|
||||
|
||||
if (!mailBeingConstructed.containsKey(senderId)) {
|
||||
switch (args.size()) {
|
||||
case 1 -> {
|
||||
MailBuilder mailBuilder;
|
||||
switch (args.get(0).toLowerCase()) {
|
||||
case "help" -> {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
case "all" -> mailBuilder = new MailBuilder(true, new Mail());
|
||||
default -> {
|
||||
if (DatabaseHelper.getPlayerByUid(Integer.parseInt(args.get(0))) != null) {
|
||||
mailBuilder = new MailBuilder(Integer.parseInt(args.get(0)), new Mail());
|
||||
} else {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.sendMail.user_not_exist", args.get(0)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
mailBeingConstructed.put(senderId, mailBuilder);
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.sendMail.start_composition"));
|
||||
}
|
||||
case 2 -> CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.sendMail.templates"));
|
||||
default -> CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.sendMail.invalid_arguments"));
|
||||
}
|
||||
} else {
|
||||
MailBuilder mailBuilder = mailBeingConstructed.get(senderId);
|
||||
|
||||
if (args.size() >= 1) {
|
||||
switch (args.get(0).toLowerCase()) {
|
||||
case "stop" -> {
|
||||
mailBeingConstructed.remove(senderId);
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.sendMail.send_cancel"));
|
||||
}
|
||||
case "finish" -> {
|
||||
if (mailBuilder.constructionStage == 3) {
|
||||
if (!mailBuilder.sendToAll) {
|
||||
Grasscutter.getGameServer()
|
||||
.getPlayerByUid(mailBuilder.recipient, true)
|
||||
.sendMail(mailBuilder.mail);
|
||||
CommandHandler.sendMessage(
|
||||
sender,
|
||||
translate(sender, "commands.sendMail.send_done", mailBuilder.recipient));
|
||||
} else {
|
||||
DatabaseHelper.getByGameClass(Player.class)
|
||||
.forEach(
|
||||
player -> {
|
||||
var onlinePlayer =
|
||||
Grasscutter.getGameServer().getPlayerByUid(player.getUid(), false);
|
||||
Objects.requireNonNullElse(onlinePlayer, player)
|
||||
.sendMail(mailBuilder.mail);
|
||||
});
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.sendMail.send_all_done"));
|
||||
}
|
||||
mailBeingConstructed.remove(senderId);
|
||||
} else {
|
||||
CommandHandler.sendMessage(
|
||||
sender,
|
||||
translate(
|
||||
sender,
|
||||
"commands.sendMail.not_composition_end",
|
||||
getConstructionArgs(mailBuilder.constructionStage, sender)));
|
||||
}
|
||||
}
|
||||
case "help" -> {
|
||||
CommandHandler.sendMessage(
|
||||
sender,
|
||||
translate(
|
||||
sender,
|
||||
"commands.sendMail.please_use",
|
||||
getConstructionArgs(mailBuilder.constructionStage, sender)));
|
||||
}
|
||||
default -> {
|
||||
switch (mailBuilder.constructionStage) {
|
||||
case 0 -> {
|
||||
String title = String.join(" ", args.subList(0, args.size()));
|
||||
mailBuilder.mail.mailContent.title = title;
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.sendMail.set_title", title));
|
||||
mailBuilder.constructionStage++;
|
||||
}
|
||||
case 1 -> {
|
||||
String contents = String.join(" ", args.subList(0, args.size()));
|
||||
mailBuilder.mail.mailContent.content = contents;
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.sendMail.set_contents", contents));
|
||||
mailBuilder.constructionStage++;
|
||||
}
|
||||
case 2 -> {
|
||||
String msgSender = String.join(" ", args.subList(0, args.size()));
|
||||
mailBuilder.mail.mailContent.sender = msgSender;
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.sendMail.set_message_sender", msgSender));
|
||||
mailBuilder.constructionStage++;
|
||||
}
|
||||
case 3 -> {
|
||||
int item;
|
||||
int lvl = 1;
|
||||
int amount = 1;
|
||||
int refinement = 0;
|
||||
switch (args.size()) {
|
||||
case 4: // <itemId|itemName> [amount] [level] [refinement] // TODO: this requires
|
||||
// Mail support but there's no harm leaving it here for now
|
||||
try {
|
||||
refinement = Integer.parseInt(args.get(3));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.generic.invalid.itemRefinement"));
|
||||
return;
|
||||
} // Fallthrough
|
||||
case 3: // <itemId|itemName> [amount] [level]
|
||||
try {
|
||||
lvl = Integer.parseInt(args.get(2));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.generic.invalid.itemLevel"));
|
||||
return;
|
||||
} // Fallthrough
|
||||
case 2: // <itemId|itemName> [amount]
|
||||
try {
|
||||
amount = Integer.parseInt(args.get(1));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.generic.invalid.amount"));
|
||||
return;
|
||||
} // Fallthrough
|
||||
case 1: // <itemId|itemName>
|
||||
try {
|
||||
item = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException ignored) {
|
||||
// TODO: Parse from item name using GM Handbook.
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.generic.invalid.itemId"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default: // *No args*
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.sendMail.give_usage");
|
||||
return;
|
||||
}
|
||||
mailBuilder.mail.itemList.add(new Mail.MailItem(item, amount, lvl));
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.sendMail.send", amount, item, lvl));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CommandHandler.sendMessage(
|
||||
sender,
|
||||
translate(
|
||||
sender,
|
||||
"commands.sendMail.invalid_arguments_please_use",
|
||||
getConstructionArgs(mailBuilder.constructionStage, sender)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getConstructionArgs(int stage, Player sender) {
|
||||
return switch (stage) {
|
||||
case 0 -> translate(sender, "commands.sendMail.title");
|
||||
case 1 -> translate(sender, "commands.sendMail.message");
|
||||
case 2 -> translate(sender, "commands.sendMail.sender");
|
||||
case 3 -> translate(sender, "commands.sendMail.arguments");
|
||||
default -> translate(sender, "commands.sendMail.error", stage);
|
||||
};
|
||||
}
|
||||
|
||||
public static class MailBuilder {
|
||||
public int recipient;
|
||||
public boolean sendToAll;
|
||||
public int constructionStage;
|
||||
public Mail mail;
|
||||
|
||||
public MailBuilder(int recipient, Mail mail) {
|
||||
this.recipient = recipient;
|
||||
this.sendToAll = false;
|
||||
this.constructionStage = 0;
|
||||
this.mail = mail;
|
||||
}
|
||||
|
||||
public MailBuilder(boolean sendToAll, Mail mail) {
|
||||
if (sendToAll) {
|
||||
this.recipient = 0;
|
||||
this.sendToAll = true;
|
||||
this.constructionStage = 0;
|
||||
this.mail = mail;
|
||||
} else {
|
||||
Grasscutter.getLogger().error("Please use MailBuilder(int, mail) when not sending to all");
|
||||
Thread.dumpStack();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +1,37 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.Command.TargetRequirement;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "sendMessage",
|
||||
aliases = {"say", "sendservmsg", "sendservermessage", "b", "broadcast"},
|
||||
usage = {"<message>"},
|
||||
permission = "server.sendmessage",
|
||||
permissionTargeted = "server.sendmessage.others",
|
||||
targetRequirement = TargetRequirement.NONE)
|
||||
public final class SendMessageCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() == 0) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
String message = String.join(" ", args);
|
||||
|
||||
if (targetPlayer == null) {
|
||||
for (Player p : Grasscutter.getGameServer().getPlayers().values()) {
|
||||
CommandHandler.sendMessage(p, message);
|
||||
}
|
||||
} else {
|
||||
CommandHandler.sendMessage(targetPlayer, message);
|
||||
}
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.sendMessage.success");
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.Command.TargetRequirement;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "sendMessage",
|
||||
aliases = {"say", "sendservmsg", "sendservermessage", "b", "broadcast"},
|
||||
usage = {"<message>"},
|
||||
permission = "server.sendmessage",
|
||||
permissionTargeted = "server.sendmessage.others",
|
||||
targetRequirement = TargetRequirement.NONE)
|
||||
public final class SendMessageCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() == 0) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
String message = String.join(" ", args);
|
||||
|
||||
if (targetPlayer == null) {
|
||||
for (Player p : Grasscutter.getGameServer().getPlayers().values()) {
|
||||
CommandHandler.sendMessage(p, message);
|
||||
}
|
||||
} else {
|
||||
CommandHandler.sendMessage(targetPlayer, message);
|
||||
}
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.sendMessage.success");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,88 +1,92 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.game.world.World;
|
||||
import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify;
|
||||
import emu.grasscutter.utils.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "setConst",
|
||||
aliases = {"setconstellation"},
|
||||
usage = {"<constellation level> [all]"},
|
||||
permission = "player.setconstellation",
|
||||
permissionTargeted = "player.setconstellation.others")
|
||||
public final class SetConstCommand implements CommandHandler {
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 1) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int constLevel = Integer.parseInt(args.get(0));
|
||||
// Check if level is out of range
|
||||
if (constLevel < -1 || constLevel > 6) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.setConst.range_error");
|
||||
return;
|
||||
}
|
||||
// If it's either empty or anything else other than "all" just do normal setConstellation
|
||||
if (args.size() == 1) {
|
||||
EntityAvatar entity = targetPlayer.getTeamManager().getCurrentAvatarEntity();
|
||||
if (entity == null) return;
|
||||
Avatar avatar = entity.getAvatar();
|
||||
this.setConstellation(targetPlayer, avatar, constLevel);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.setConst.success", avatar.getAvatarData().getName(), constLevel);
|
||||
return;
|
||||
}
|
||||
// Check if there's an additional argument which is "all", if it does then go setAllConstellation
|
||||
if (args.size() > 1 && args.get(1).equalsIgnoreCase("all")) {
|
||||
this.setAllConstellation(targetPlayer, constLevel);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.setConst.successall", constLevel);
|
||||
} else sendUsageMessage(sender);
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.setConst.level_error");
|
||||
}
|
||||
}
|
||||
|
||||
private void setConstellation(Player player, Avatar avatar, int constLevel) {
|
||||
int currentConstLevel = avatar.getCoreProudSkillLevel();
|
||||
avatar.forceConstellationLevel(constLevel);
|
||||
|
||||
// force player to reload scene when necessary
|
||||
if (constLevel < currentConstLevel) {
|
||||
this.reloadScene(player);
|
||||
}
|
||||
|
||||
// ensure that all changes are visible to the player
|
||||
avatar.recalcConstellations();
|
||||
avatar.recalcStats(true);
|
||||
avatar.save();
|
||||
}
|
||||
|
||||
private void setAllConstellation(Player player, int constLevel) {
|
||||
player.getAvatars().forEach(avatar -> {
|
||||
avatar.forceConstellationLevel(constLevel);
|
||||
avatar.recalcConstellations();
|
||||
avatar.recalcStats(true);
|
||||
avatar.save();
|
||||
});
|
||||
// Just reload scene once, shorter than having to check for each constLevel < currentConstLevel
|
||||
this.reloadScene(player);
|
||||
}
|
||||
|
||||
private void reloadScene(Player player) {
|
||||
World world = player.getWorld();
|
||||
Scene scene = player.getScene();
|
||||
Position pos = player.getPosition();
|
||||
world.transferPlayerToScene(player, 1, pos);
|
||||
world.transferPlayerToScene(player, scene.getId(), pos);
|
||||
scene.broadcastPacket(new PacketSceneEntityAppearNotify(player));
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.game.world.World;
|
||||
import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "setConst",
|
||||
aliases = {"setconstellation"},
|
||||
usage = {"<constellation level> [all]"},
|
||||
permission = "player.setconstellation",
|
||||
permissionTargeted = "player.setconstellation.others")
|
||||
public final class SetConstCommand implements CommandHandler {
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 1) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int constLevel = Integer.parseInt(args.get(0));
|
||||
// Check if level is out of range
|
||||
if (constLevel < -1 || constLevel > 6) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.setConst.range_error");
|
||||
return;
|
||||
}
|
||||
// If it's either empty or anything else other than "all" just do normal setConstellation
|
||||
if (args.size() == 1) {
|
||||
EntityAvatar entity = targetPlayer.getTeamManager().getCurrentAvatarEntity();
|
||||
if (entity == null) return;
|
||||
Avatar avatar = entity.getAvatar();
|
||||
this.setConstellation(targetPlayer, avatar, constLevel);
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.setConst.success", avatar.getAvatarData().getName(), constLevel);
|
||||
return;
|
||||
}
|
||||
// Check if there's an additional argument which is "all", if it does then go
|
||||
// setAllConstellation
|
||||
if (args.size() > 1 && args.get(1).equalsIgnoreCase("all")) {
|
||||
this.setAllConstellation(targetPlayer, constLevel);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.setConst.successall", constLevel);
|
||||
} else sendUsageMessage(sender);
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.setConst.level_error");
|
||||
}
|
||||
}
|
||||
|
||||
private void setConstellation(Player player, Avatar avatar, int constLevel) {
|
||||
int currentConstLevel = avatar.getCoreProudSkillLevel();
|
||||
avatar.forceConstellationLevel(constLevel);
|
||||
|
||||
// force player to reload scene when necessary
|
||||
if (constLevel < currentConstLevel) {
|
||||
this.reloadScene(player);
|
||||
}
|
||||
|
||||
// ensure that all changes are visible to the player
|
||||
avatar.recalcConstellations();
|
||||
avatar.recalcStats(true);
|
||||
avatar.save();
|
||||
}
|
||||
|
||||
private void setAllConstellation(Player player, int constLevel) {
|
||||
player
|
||||
.getAvatars()
|
||||
.forEach(
|
||||
avatar -> {
|
||||
avatar.forceConstellationLevel(constLevel);
|
||||
avatar.recalcConstellations();
|
||||
avatar.recalcStats(true);
|
||||
avatar.save();
|
||||
});
|
||||
// Just reload scene once, shorter than having to check for each constLevel < currentConstLevel
|
||||
this.reloadScene(player);
|
||||
}
|
||||
|
||||
private void reloadScene(Player player) {
|
||||
World world = player.getWorld();
|
||||
Scene scene = player.getScene();
|
||||
Position pos = player.getPosition();
|
||||
world.transferPlayerToScene(player, 1, pos);
|
||||
world.transferPlayerToScene(player, scene.getId(), pos);
|
||||
scene.broadcastPacket(new PacketSceneEntityAppearNotify(player));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarFetterDataNotify;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(
|
||||
label = "setFetterLevel",
|
||||
usage = {"<level>"},
|
||||
aliases = {"setfetterlvl", "setfriendship"},
|
||||
permission = "player.setfetterlevel",
|
||||
permissionTargeted = "player.setfetterlevel.others")
|
||||
public final class SetFetterLevelCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() != 1) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int fetterLevel = Integer.parseInt(args.get(0));
|
||||
if (fetterLevel < 0 || fetterLevel > 10) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.setFetterLevel.range_error"));
|
||||
return;
|
||||
}
|
||||
Avatar avatar = targetPlayer.getTeamManager().getCurrentAvatarEntity().getAvatar();
|
||||
|
||||
avatar.setFetterLevel(fetterLevel);
|
||||
if (fetterLevel != 10) {
|
||||
avatar.setFetterExp(GameData.getAvatarFetterLevelDataMap().get(fetterLevel).getExp());
|
||||
}
|
||||
avatar.save();
|
||||
|
||||
targetPlayer.sendPacket(new PacketAvatarFetterDataNotify(avatar));
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.setFetterLevel.success", fetterLevel));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.setFetterLevel.level_error"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.packet.send.PacketAvatarFetterDataNotify;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "setFetterLevel",
|
||||
usage = {"<level>"},
|
||||
aliases = {"setfetterlvl", "setfriendship"},
|
||||
permission = "player.setfetterlevel",
|
||||
permissionTargeted = "player.setfetterlevel.others")
|
||||
public final class SetFetterLevelCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() != 1) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int fetterLevel = Integer.parseInt(args.get(0));
|
||||
if (fetterLevel < 0 || fetterLevel > 10) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.setFetterLevel.range_error"));
|
||||
return;
|
||||
}
|
||||
Avatar avatar = targetPlayer.getTeamManager().getCurrentAvatarEntity().getAvatar();
|
||||
|
||||
avatar.setFetterLevel(fetterLevel);
|
||||
if (fetterLevel != 10) {
|
||||
avatar.setFetterExp(GameData.getAvatarFetterLevelDataMap().get(fetterLevel).getExp());
|
||||
}
|
||||
avatar.save();
|
||||
|
||||
targetPlayer.sendPacket(new PacketAvatarFetterDataNotify(avatar));
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.setFetterLevel.success", fetterLevel));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.setFetterLevel.level_error"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,250 +1,279 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.tower.TowerLevelRecord;
|
||||
import emu.grasscutter.server.packet.send.PacketOpenStateChangeNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketSceneAreaUnlockNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketScenePointUnlockNotify;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Command(label = "setProp", aliases = {"prop"}, usage = {"<prop> <value>"}, permission = "player.setprop", permissionTargeted = "player.setprop.others")
|
||||
public final class SetPropCommand implements CommandHandler {
|
||||
// List of map areas. Unfortunately, there is no readily available source for them in excels or bins.
|
||||
private static final List<Integer> sceneAreas = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32, 100, 101, 102, 103, 200, 210, 300, 400, 401, 402, 403);
|
||||
Map<String, Prop> props;
|
||||
|
||||
public SetPropCommand() {
|
||||
this.props = new HashMap<>();
|
||||
// Full PlayerProperty enum that won't be advertised but can be used by devs
|
||||
for (PlayerProperty prop : PlayerProperty.values()) {
|
||||
String name = prop.toString().substring(5); // PROP_EXP -> EXP
|
||||
String key = name.toLowerCase(); // EXP -> exp
|
||||
this.props.put(key, new Prop(name, prop));
|
||||
}
|
||||
// Add special props
|
||||
Prop worldlevel = new Prop("World Level", PlayerProperty.PROP_PLAYER_WORLD_LEVEL, PseudoProp.WORLD_LEVEL);
|
||||
this.props.put("worldlevel", worldlevel);
|
||||
this.props.put("wl", worldlevel);
|
||||
|
||||
Prop abyss = new Prop("Tower Level", PseudoProp.TOWER_LEVEL);
|
||||
this.props.put("abyss", abyss);
|
||||
this.props.put("abyssfloor", abyss);
|
||||
this.props.put("ut", abyss);
|
||||
this.props.put("tower", abyss);
|
||||
this.props.put("towerlevel", abyss);
|
||||
this.props.put("unlocktower", abyss);
|
||||
|
||||
Prop bplevel = new Prop("BP Level", PseudoProp.BP_LEVEL);
|
||||
this.props.put("bplevel", bplevel);
|
||||
this.props.put("bp", bplevel);
|
||||
this.props.put("battlepass", bplevel);
|
||||
|
||||
Prop godmode = new Prop("GodMode", PseudoProp.GOD_MODE);
|
||||
this.props.put("godmode", godmode);
|
||||
this.props.put("god", godmode);
|
||||
|
||||
Prop nostamina = new Prop("UnlimitedStamina", PseudoProp.UNLIMITED_STAMINA);
|
||||
this.props.put("unlimitedstamina", nostamina);
|
||||
this.props.put("us", nostamina);
|
||||
this.props.put("nostamina", nostamina);
|
||||
this.props.put("nostam", nostamina);
|
||||
this.props.put("ns", nostamina);
|
||||
|
||||
Prop unlimitedenergy = new Prop("UnlimitedEnergy", PseudoProp.UNLIMITED_ENERGY);
|
||||
this.props.put("unlimitedenergy", unlimitedenergy);
|
||||
this.props.put("ue", unlimitedenergy);
|
||||
|
||||
Prop setopenstate = new Prop("SetOpenstate", PseudoProp.SET_OPENSTATE);
|
||||
this.props.put("setopenstate", setopenstate);
|
||||
this.props.put("so", setopenstate);
|
||||
|
||||
Prop unsetopenstate = new Prop("UnsetOpenstate", PseudoProp.UNSET_OPENSTATE);
|
||||
this.props.put("unsetopenstate", unsetopenstate);
|
||||
this.props.put("uo", unsetopenstate);
|
||||
|
||||
Prop unlockmap = new Prop("UnlockMap", PseudoProp.UNLOCK_MAP);
|
||||
this.props.put("unlockmap", unlockmap);
|
||||
this.props.put("um", unlockmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() != 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
String propStr = args.get(0).toLowerCase();
|
||||
String valueStr = args.get(1).toLowerCase();
|
||||
int value;
|
||||
|
||||
if (!props.containsKey(propStr)) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
value = switch (valueStr.toLowerCase()) {
|
||||
case "on", "true" -> 1;
|
||||
case "off", "false" -> 0;
|
||||
case "toggle" -> -1;
|
||||
default -> Integer.parseInt(valueStr);
|
||||
};
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.execution.argument_error");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean success = false;
|
||||
Prop prop = props.get(propStr);
|
||||
|
||||
success = switch (prop.pseudoProp) {
|
||||
case WORLD_LEVEL -> targetPlayer.setWorldLevel(value);
|
||||
case BP_LEVEL -> targetPlayer.getBattlePassManager().setLevel(value);
|
||||
case TOWER_LEVEL -> this.setTowerLevel(sender, targetPlayer, value);
|
||||
case GOD_MODE, UNLIMITED_STAMINA, UNLIMITED_ENERGY ->
|
||||
this.setBool(sender, targetPlayer, prop.pseudoProp, value);
|
||||
case SET_OPENSTATE -> this.setOpenState(targetPlayer, value, 1);
|
||||
case UNSET_OPENSTATE -> this.setOpenState(targetPlayer, value, 0);
|
||||
case UNLOCK_MAP -> unlockMap(targetPlayer);
|
||||
default -> targetPlayer.setProperty(prop.prop, value);
|
||||
};
|
||||
|
||||
if (success) {
|
||||
if (targetPlayer == sender) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.set_to", prop.name, valueStr);
|
||||
} else {
|
||||
String uidStr = targetPlayer.getAccount().getId();
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.set_for_to", prop.name, uidStr, valueStr);
|
||||
}
|
||||
} else {
|
||||
if (prop.prop != PlayerProperty.PROP_NONE) { // PseudoProps need to do their own error messages
|
||||
int min = targetPlayer.getPropertyMin(prop.prop);
|
||||
int max = targetPlayer.getPropertyMax(prop.prop);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.invalid.value_between", prop.name, min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean setTowerLevel(Player sender, Player targetPlayer, int topFloor) {
|
||||
List<Integer> floorIds = targetPlayer.getServer().getTowerSystem().getAllFloors();
|
||||
if (topFloor < 0 || topFloor > floorIds.size()) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.invalid.value_between", "Tower Level", 0, floorIds.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<Integer, TowerLevelRecord> recordMap = targetPlayer.getTowerManager().getRecordMap();
|
||||
// Add records for each unlocked floor
|
||||
for (int floor : floorIds.subList(0, topFloor)) {
|
||||
if (!recordMap.containsKey(floor)) {
|
||||
recordMap.put(floor, new TowerLevelRecord(floor));
|
||||
}
|
||||
}
|
||||
// Remove records for each floor past our target
|
||||
for (int floor : floorIds.subList(topFloor, floorIds.size())) {
|
||||
recordMap.remove(floor);
|
||||
}
|
||||
// Six stars required on Floor 8 to unlock Floor 9+
|
||||
if (topFloor > 8) {
|
||||
recordMap.get(floorIds.get(7)).setLevelStars(0, 6); // levelIds seem to start at 1 for Floor 1 Chamber 1, so this doesn't get shown at all
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean setBool(Player sender, Player targetPlayer, PseudoProp pseudoProp, int value) {
|
||||
boolean enabled = switch (pseudoProp) {
|
||||
case GOD_MODE -> targetPlayer.inGodmode();
|
||||
case UNLIMITED_STAMINA -> targetPlayer.getUnlimitedStamina();
|
||||
case UNLIMITED_ENERGY -> !targetPlayer.getEnergyManager().getEnergyUsage();
|
||||
default -> false;
|
||||
};
|
||||
enabled = switch (value) {
|
||||
case -1 -> !enabled;
|
||||
case 0 -> false;
|
||||
default -> true;
|
||||
};
|
||||
|
||||
switch (pseudoProp) {
|
||||
case GOD_MODE:
|
||||
targetPlayer.setGodmode(enabled);
|
||||
break;
|
||||
case UNLIMITED_STAMINA:
|
||||
targetPlayer.setUnlimitedStamina(enabled);
|
||||
break;
|
||||
case UNLIMITED_ENERGY:
|
||||
targetPlayer.getEnergyManager().setEnergyUsage(!enabled);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean setOpenState(Player targetPlayer, int state, int value) {
|
||||
targetPlayer.sendPacket(new PacketOpenStateChangeNotify(state, value));
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean unlockMap(Player targetPlayer) {
|
||||
// Unlock.
|
||||
GameData.getScenePointsPerScene().forEach((sceneId, scenePoints) -> {
|
||||
// Unlock trans points.
|
||||
targetPlayer.getUnlockedScenePoints(sceneId).addAll(scenePoints);
|
||||
|
||||
// Unlock map areas.
|
||||
targetPlayer.getUnlockedSceneAreas(sceneId).addAll(sceneAreas);
|
||||
});
|
||||
|
||||
// Send notify.
|
||||
int playerScene = targetPlayer.getSceneId();
|
||||
targetPlayer.sendPacket(new PacketScenePointUnlockNotify(playerScene, targetPlayer.getUnlockedScenePoints(playerScene)));
|
||||
targetPlayer.sendPacket(new PacketSceneAreaUnlockNotify(playerScene, targetPlayer.getUnlockedSceneAreas(playerScene)));
|
||||
return true;
|
||||
}
|
||||
|
||||
enum PseudoProp {
|
||||
NONE,
|
||||
WORLD_LEVEL,
|
||||
TOWER_LEVEL,
|
||||
BP_LEVEL,
|
||||
GOD_MODE,
|
||||
UNLIMITED_STAMINA,
|
||||
UNLIMITED_ENERGY,
|
||||
SET_OPENSTATE,
|
||||
UNSET_OPENSTATE,
|
||||
UNLOCK_MAP
|
||||
}
|
||||
|
||||
static class Prop {
|
||||
String name;
|
||||
PlayerProperty prop;
|
||||
PseudoProp pseudoProp;
|
||||
|
||||
public Prop(PlayerProperty prop) {
|
||||
this(prop.toString(), prop, PseudoProp.NONE);
|
||||
}
|
||||
|
||||
public Prop(String name) {
|
||||
this(name, PlayerProperty.PROP_NONE, PseudoProp.NONE);
|
||||
}
|
||||
|
||||
public Prop(String name, PseudoProp pseudoProp) {
|
||||
this(name, PlayerProperty.PROP_NONE, pseudoProp);
|
||||
}
|
||||
|
||||
public Prop(String name, PlayerProperty prop) {
|
||||
this(name, prop, PseudoProp.NONE);
|
||||
}
|
||||
|
||||
public Prop(String name, PlayerProperty prop, PseudoProp pseudoProp) {
|
||||
this.name = name;
|
||||
this.prop = prop;
|
||||
this.pseudoProp = pseudoProp;
|
||||
}
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.game.tower.TowerLevelRecord;
|
||||
import emu.grasscutter.server.packet.send.PacketOpenStateChangeNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketSceneAreaUnlockNotify;
|
||||
import emu.grasscutter.server.packet.send.PacketScenePointUnlockNotify;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Command(
|
||||
label = "setProp",
|
||||
aliases = {"prop"},
|
||||
usage = {"<prop> <value>"},
|
||||
permission = "player.setprop",
|
||||
permissionTargeted = "player.setprop.others")
|
||||
public final class SetPropCommand implements CommandHandler {
|
||||
// List of map areas. Unfortunately, there is no readily available source for them in excels or
|
||||
// bins.
|
||||
private static final List<Integer> sceneAreas =
|
||||
List.of(
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
|
||||
28, 29, 32, 100, 101, 102, 103, 200, 210, 300, 400, 401, 402, 403);
|
||||
Map<String, Prop> props;
|
||||
|
||||
public SetPropCommand() {
|
||||
this.props = new HashMap<>();
|
||||
// Full PlayerProperty enum that won't be advertised but can be used by devs
|
||||
for (PlayerProperty prop : PlayerProperty.values()) {
|
||||
String name = prop.toString().substring(5); // PROP_EXP -> EXP
|
||||
String key = name.toLowerCase(); // EXP -> exp
|
||||
this.props.put(key, new Prop(name, prop));
|
||||
}
|
||||
// Add special props
|
||||
Prop worldlevel =
|
||||
new Prop("World Level", PlayerProperty.PROP_PLAYER_WORLD_LEVEL, PseudoProp.WORLD_LEVEL);
|
||||
this.props.put("worldlevel", worldlevel);
|
||||
this.props.put("wl", worldlevel);
|
||||
|
||||
Prop abyss = new Prop("Tower Level", PseudoProp.TOWER_LEVEL);
|
||||
this.props.put("abyss", abyss);
|
||||
this.props.put("abyssfloor", abyss);
|
||||
this.props.put("ut", abyss);
|
||||
this.props.put("tower", abyss);
|
||||
this.props.put("towerlevel", abyss);
|
||||
this.props.put("unlocktower", abyss);
|
||||
|
||||
Prop bplevel = new Prop("BP Level", PseudoProp.BP_LEVEL);
|
||||
this.props.put("bplevel", bplevel);
|
||||
this.props.put("bp", bplevel);
|
||||
this.props.put("battlepass", bplevel);
|
||||
|
||||
Prop godmode = new Prop("GodMode", PseudoProp.GOD_MODE);
|
||||
this.props.put("godmode", godmode);
|
||||
this.props.put("god", godmode);
|
||||
|
||||
Prop nostamina = new Prop("UnlimitedStamina", PseudoProp.UNLIMITED_STAMINA);
|
||||
this.props.put("unlimitedstamina", nostamina);
|
||||
this.props.put("us", nostamina);
|
||||
this.props.put("nostamina", nostamina);
|
||||
this.props.put("nostam", nostamina);
|
||||
this.props.put("ns", nostamina);
|
||||
|
||||
Prop unlimitedenergy = new Prop("UnlimitedEnergy", PseudoProp.UNLIMITED_ENERGY);
|
||||
this.props.put("unlimitedenergy", unlimitedenergy);
|
||||
this.props.put("ue", unlimitedenergy);
|
||||
|
||||
Prop setopenstate = new Prop("SetOpenstate", PseudoProp.SET_OPENSTATE);
|
||||
this.props.put("setopenstate", setopenstate);
|
||||
this.props.put("so", setopenstate);
|
||||
|
||||
Prop unsetopenstate = new Prop("UnsetOpenstate", PseudoProp.UNSET_OPENSTATE);
|
||||
this.props.put("unsetopenstate", unsetopenstate);
|
||||
this.props.put("uo", unsetopenstate);
|
||||
|
||||
Prop unlockmap = new Prop("UnlockMap", PseudoProp.UNLOCK_MAP);
|
||||
this.props.put("unlockmap", unlockmap);
|
||||
this.props.put("um", unlockmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() != 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
String propStr = args.get(0).toLowerCase();
|
||||
String valueStr = args.get(1).toLowerCase();
|
||||
int value;
|
||||
|
||||
if (!props.containsKey(propStr)) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
value =
|
||||
switch (valueStr.toLowerCase()) {
|
||||
case "on", "true" -> 1;
|
||||
case "off", "false" -> 0;
|
||||
case "toggle" -> -1;
|
||||
default -> Integer.parseInt(valueStr);
|
||||
};
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.execution.argument_error");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean success = false;
|
||||
Prop prop = props.get(propStr);
|
||||
|
||||
success =
|
||||
switch (prop.pseudoProp) {
|
||||
case WORLD_LEVEL -> targetPlayer.setWorldLevel(value);
|
||||
case BP_LEVEL -> targetPlayer.getBattlePassManager().setLevel(value);
|
||||
case TOWER_LEVEL -> this.setTowerLevel(sender, targetPlayer, value);
|
||||
case GOD_MODE, UNLIMITED_STAMINA, UNLIMITED_ENERGY -> this.setBool(
|
||||
sender, targetPlayer, prop.pseudoProp, value);
|
||||
case SET_OPENSTATE -> this.setOpenState(targetPlayer, value, 1);
|
||||
case UNSET_OPENSTATE -> this.setOpenState(targetPlayer, value, 0);
|
||||
case UNLOCK_MAP -> unlockMap(targetPlayer);
|
||||
default -> targetPlayer.setProperty(prop.prop, value);
|
||||
};
|
||||
|
||||
if (success) {
|
||||
if (targetPlayer == sender) {
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.generic.set_to", prop.name, valueStr);
|
||||
} else {
|
||||
String uidStr = targetPlayer.getAccount().getId();
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.generic.set_for_to", prop.name, uidStr, valueStr);
|
||||
}
|
||||
} else {
|
||||
if (prop.prop
|
||||
!= PlayerProperty.PROP_NONE) { // PseudoProps need to do their own error messages
|
||||
int min = targetPlayer.getPropertyMin(prop.prop);
|
||||
int max = targetPlayer.getPropertyMax(prop.prop);
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.generic.invalid.value_between", prop.name, min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean setTowerLevel(Player sender, Player targetPlayer, int topFloor) {
|
||||
List<Integer> floorIds = targetPlayer.getServer().getTowerSystem().getAllFloors();
|
||||
if (topFloor < 0 || topFloor > floorIds.size()) {
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.generic.invalid.value_between", "Tower Level", 0, floorIds.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<Integer, TowerLevelRecord> recordMap = targetPlayer.getTowerManager().getRecordMap();
|
||||
// Add records for each unlocked floor
|
||||
for (int floor : floorIds.subList(0, topFloor)) {
|
||||
if (!recordMap.containsKey(floor)) {
|
||||
recordMap.put(floor, new TowerLevelRecord(floor));
|
||||
}
|
||||
}
|
||||
// Remove records for each floor past our target
|
||||
for (int floor : floorIds.subList(topFloor, floorIds.size())) {
|
||||
recordMap.remove(floor);
|
||||
}
|
||||
// Six stars required on Floor 8 to unlock Floor 9+
|
||||
if (topFloor > 8) {
|
||||
recordMap
|
||||
.get(floorIds.get(7))
|
||||
.setLevelStars(
|
||||
0,
|
||||
6); // levelIds seem to start at 1 for Floor 1 Chamber 1, so this doesn't get shown at
|
||||
// all
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean setBool(Player sender, Player targetPlayer, PseudoProp pseudoProp, int value) {
|
||||
boolean enabled =
|
||||
switch (pseudoProp) {
|
||||
case GOD_MODE -> targetPlayer.inGodmode();
|
||||
case UNLIMITED_STAMINA -> targetPlayer.getUnlimitedStamina();
|
||||
case UNLIMITED_ENERGY -> !targetPlayer.getEnergyManager().getEnergyUsage();
|
||||
default -> false;
|
||||
};
|
||||
enabled =
|
||||
switch (value) {
|
||||
case -1 -> !enabled;
|
||||
case 0 -> false;
|
||||
default -> true;
|
||||
};
|
||||
|
||||
switch (pseudoProp) {
|
||||
case GOD_MODE:
|
||||
targetPlayer.setGodmode(enabled);
|
||||
break;
|
||||
case UNLIMITED_STAMINA:
|
||||
targetPlayer.setUnlimitedStamina(enabled);
|
||||
break;
|
||||
case UNLIMITED_ENERGY:
|
||||
targetPlayer.getEnergyManager().setEnergyUsage(!enabled);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean setOpenState(Player targetPlayer, int state, int value) {
|
||||
targetPlayer.sendPacket(new PacketOpenStateChangeNotify(state, value));
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean unlockMap(Player targetPlayer) {
|
||||
// Unlock.
|
||||
GameData.getScenePointsPerScene()
|
||||
.forEach(
|
||||
(sceneId, scenePoints) -> {
|
||||
// Unlock trans points.
|
||||
targetPlayer.getUnlockedScenePoints(sceneId).addAll(scenePoints);
|
||||
|
||||
// Unlock map areas.
|
||||
targetPlayer.getUnlockedSceneAreas(sceneId).addAll(sceneAreas);
|
||||
});
|
||||
|
||||
// Send notify.
|
||||
int playerScene = targetPlayer.getSceneId();
|
||||
targetPlayer.sendPacket(
|
||||
new PacketScenePointUnlockNotify(
|
||||
playerScene, targetPlayer.getUnlockedScenePoints(playerScene)));
|
||||
targetPlayer.sendPacket(
|
||||
new PacketSceneAreaUnlockNotify(
|
||||
playerScene, targetPlayer.getUnlockedSceneAreas(playerScene)));
|
||||
return true;
|
||||
}
|
||||
|
||||
enum PseudoProp {
|
||||
NONE,
|
||||
WORLD_LEVEL,
|
||||
TOWER_LEVEL,
|
||||
BP_LEVEL,
|
||||
GOD_MODE,
|
||||
UNLIMITED_STAMINA,
|
||||
UNLIMITED_ENERGY,
|
||||
SET_OPENSTATE,
|
||||
UNSET_OPENSTATE,
|
||||
UNLOCK_MAP
|
||||
}
|
||||
|
||||
static class Prop {
|
||||
String name;
|
||||
PlayerProperty prop;
|
||||
PseudoProp pseudoProp;
|
||||
|
||||
public Prop(PlayerProperty prop) {
|
||||
this(prop.toString(), prop, PseudoProp.NONE);
|
||||
}
|
||||
|
||||
public Prop(String name) {
|
||||
this(name, PlayerProperty.PROP_NONE, PseudoProp.NONE);
|
||||
}
|
||||
|
||||
public Prop(String name, PseudoProp pseudoProp) {
|
||||
this(name, PlayerProperty.PROP_NONE, pseudoProp);
|
||||
}
|
||||
|
||||
public Prop(String name, PlayerProperty prop) {
|
||||
this(name, prop, PseudoProp.NONE);
|
||||
}
|
||||
|
||||
public Prop(String name, PlayerProperty prop, PseudoProp pseudoProp) {
|
||||
this.name = name;
|
||||
this.prop = prop;
|
||||
this.pseudoProp = pseudoProp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,184 +1,190 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Command(
|
||||
label = "setStats",
|
||||
aliases = {"stats", "stat"},
|
||||
usage = {
|
||||
"[set] <stat> <value>",
|
||||
"(lock|freeze) <stat> [<value>]", // Can lock to current value
|
||||
"(unlock|unfreeze) <stat>"},
|
||||
permission = "player.setstats",
|
||||
permissionTargeted = "player.setstats.others")
|
||||
public final class SetStatsCommand implements CommandHandler {
|
||||
private final Map<String, Stat> stats;
|
||||
|
||||
public SetStatsCommand() {
|
||||
this.stats = new HashMap<>();
|
||||
for (String key : FightProperty.getShortNames()) {
|
||||
this.stats.put(key, new Stat(FightProperty.getPropByShortName(key)));
|
||||
}
|
||||
// Full FightProperty enum that won't be advertised but can be used by devs
|
||||
// They have a prefix to avoid the "hp" clash
|
||||
for (FightProperty prop : FightProperty.values()) {
|
||||
String name = prop.toString().substring(10); // FIGHT_PROP_BASE_HP -> _BASE_HP
|
||||
String key = name.toLowerCase(); // _BASE_HP -> _base_hp
|
||||
name = name.substring(1); // _BASE_HP -> BASE_HP
|
||||
this.stats.put(key, new Stat(name, prop));
|
||||
}
|
||||
|
||||
// Compatibility aliases
|
||||
this.stats.put("mhp", this.stats.get("maxhp"));
|
||||
this.stats.put("hp", this.stats.get("_cur_hp")); // Overrides FIGHT_PROP_HP
|
||||
this.stats.put("atk", this.stats.get("_cur_attack")); // Overrides FIGHT_PROP_ATTACK
|
||||
this.stats.put("def", this.stats.get("_cur_defense")); // Overrides FIGHT_PROP_DEFENSE
|
||||
this.stats.put("atkb", this.stats.get("_base_attack")); // This doesn't seem to get used to recalculate ATK, so it's only useful for stuff like Bennett's buff.
|
||||
this.stats.put("eanemo", this.stats.get("anemo%"));
|
||||
this.stats.put("ecryo", this.stats.get("cryo%"));
|
||||
this.stats.put("edendro", this.stats.get("dendro%"));
|
||||
this.stats.put("edend", this.stats.get("dendro%"));
|
||||
this.stats.put("eelectro", this.stats.get("electro%"));
|
||||
this.stats.put("eelec", this.stats.get("electro%"));
|
||||
this.stats.put("ethunder", this.stats.get("electro%"));
|
||||
this.stats.put("egeo", this.stats.get("geo%"));
|
||||
this.stats.put("ehydro", this.stats.get("hydro%"));
|
||||
this.stats.put("epyro", this.stats.get("pyro%"));
|
||||
this.stats.put("ephys", this.stats.get("phys%"));
|
||||
}
|
||||
|
||||
public static float parsePercent(String input) throws NumberFormatException {
|
||||
if (input.endsWith("%")) {
|
||||
return Float.parseFloat(input.substring(0, input.length() - 1)) / 100f;
|
||||
} else {
|
||||
return Float.parseFloat(input);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
String statStr = null;
|
||||
String valueStr;
|
||||
float value = 0f;
|
||||
|
||||
if (args.size() < 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the action and stat
|
||||
String arg0 = args.remove(0).toLowerCase();
|
||||
Action action = switch (arg0) {
|
||||
default -> {
|
||||
statStr = arg0;
|
||||
yield Action.ACTION_SET;
|
||||
} // Implicit set command
|
||||
case "set" -> Action.ACTION_SET; // Explicit set command
|
||||
case "lock", "freeze" -> Action.ACTION_LOCK;
|
||||
case "unlock", "unfreeze" -> Action.ACTION_UNLOCK;
|
||||
};
|
||||
if (statStr == null) {
|
||||
statStr = args.remove(0).toLowerCase();
|
||||
}
|
||||
if (!stats.containsKey(statStr)) {
|
||||
sendUsageMessage(sender); // Invalid stat or action
|
||||
return;
|
||||
}
|
||||
Stat stat = stats.get(statStr);
|
||||
EntityAvatar entity = targetPlayer.getTeamManager().getCurrentAvatarEntity();
|
||||
Avatar avatar = entity.getAvatar();
|
||||
|
||||
// Get the value if the action requires it
|
||||
try {
|
||||
switch (action) {
|
||||
case ACTION_LOCK:
|
||||
if (args.isEmpty()) { // Lock to current value
|
||||
value = avatar.getFightProperty(stat.prop);
|
||||
break;
|
||||
} // Else fall-through and lock to supplied value
|
||||
case ACTION_SET:
|
||||
value = parsePercent(args.remove(0));
|
||||
break;
|
||||
case ACTION_UNLOCK:
|
||||
break;
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.invalid.statValue");
|
||||
return;
|
||||
} catch (IndexOutOfBoundsException ignored) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.isEmpty()) { // Leftover arguments!
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case ACTION_SET:
|
||||
entity.setFightProperty(stat.prop, value);
|
||||
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, stat.prop));
|
||||
break;
|
||||
case ACTION_LOCK:
|
||||
avatar.getFightPropOverrides().put(stat.prop.getId(), value);
|
||||
avatar.recalcStats();
|
||||
break;
|
||||
case ACTION_UNLOCK:
|
||||
avatar.getFightPropOverrides().remove(stat.prop.getId());
|
||||
avatar.recalcStats();
|
||||
break;
|
||||
}
|
||||
|
||||
// Report action
|
||||
if (FightProperty.isPercentage(stat.prop)) {
|
||||
valueStr = String.format("%.1f%%", value * 100f);
|
||||
} else {
|
||||
valueStr = String.format("%.0f", value);
|
||||
}
|
||||
if (targetPlayer == sender) {
|
||||
CommandHandler.sendTranslatedMessage(sender, action.messageKeySelf, stat.name, valueStr);
|
||||
} else {
|
||||
String uidStr = targetPlayer.getAccount().getId();
|
||||
CommandHandler.sendTranslatedMessage(sender, action.messageKeyOther, stat.name, uidStr, valueStr);
|
||||
}
|
||||
}
|
||||
|
||||
private enum Action {
|
||||
ACTION_SET("commands.generic.set_to", "commands.generic.set_for_to"),
|
||||
ACTION_LOCK("commands.setStats.locked_to", "commands.setStats.locked_for_to"),
|
||||
ACTION_UNLOCK("commands.setStats.unlocked", "commands.setStats.unlocked_for");
|
||||
public final String messageKeySelf;
|
||||
public final String messageKeyOther;
|
||||
|
||||
Action(String messageKeySelf, String messageKeyOther) {
|
||||
this.messageKeySelf = messageKeySelf;
|
||||
this.messageKeyOther = messageKeyOther;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Stat {
|
||||
String name;
|
||||
FightProperty prop;
|
||||
|
||||
public Stat(FightProperty prop) {
|
||||
this.name = prop.toString();
|
||||
this.prop = prop;
|
||||
}
|
||||
|
||||
public Stat(String name, FightProperty prop) {
|
||||
this.name = name;
|
||||
this.prop = prop;
|
||||
}
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Command(
|
||||
label = "setStats",
|
||||
aliases = {"stats", "stat"},
|
||||
usage = {
|
||||
"[set] <stat> <value>",
|
||||
"(lock|freeze) <stat> [<value>]", // Can lock to current value
|
||||
"(unlock|unfreeze) <stat>"
|
||||
},
|
||||
permission = "player.setstats",
|
||||
permissionTargeted = "player.setstats.others")
|
||||
public final class SetStatsCommand implements CommandHandler {
|
||||
private final Map<String, Stat> stats;
|
||||
|
||||
public SetStatsCommand() {
|
||||
this.stats = new HashMap<>();
|
||||
for (String key : FightProperty.getShortNames()) {
|
||||
this.stats.put(key, new Stat(FightProperty.getPropByShortName(key)));
|
||||
}
|
||||
// Full FightProperty enum that won't be advertised but can be used by devs
|
||||
// They have a prefix to avoid the "hp" clash
|
||||
for (FightProperty prop : FightProperty.values()) {
|
||||
String name = prop.toString().substring(10); // FIGHT_PROP_BASE_HP -> _BASE_HP
|
||||
String key = name.toLowerCase(); // _BASE_HP -> _base_hp
|
||||
name = name.substring(1); // _BASE_HP -> BASE_HP
|
||||
this.stats.put(key, new Stat(name, prop));
|
||||
}
|
||||
|
||||
// Compatibility aliases
|
||||
this.stats.put("mhp", this.stats.get("maxhp"));
|
||||
this.stats.put("hp", this.stats.get("_cur_hp")); // Overrides FIGHT_PROP_HP
|
||||
this.stats.put("atk", this.stats.get("_cur_attack")); // Overrides FIGHT_PROP_ATTACK
|
||||
this.stats.put("def", this.stats.get("_cur_defense")); // Overrides FIGHT_PROP_DEFENSE
|
||||
this.stats.put(
|
||||
"atkb",
|
||||
this.stats.get(
|
||||
"_base_attack")); // This doesn't seem to get used to recalculate ATK, so it's only
|
||||
// useful for stuff like Bennett's buff.
|
||||
this.stats.put("eanemo", this.stats.get("anemo%"));
|
||||
this.stats.put("ecryo", this.stats.get("cryo%"));
|
||||
this.stats.put("edendro", this.stats.get("dendro%"));
|
||||
this.stats.put("edend", this.stats.get("dendro%"));
|
||||
this.stats.put("eelectro", this.stats.get("electro%"));
|
||||
this.stats.put("eelec", this.stats.get("electro%"));
|
||||
this.stats.put("ethunder", this.stats.get("electro%"));
|
||||
this.stats.put("egeo", this.stats.get("geo%"));
|
||||
this.stats.put("ehydro", this.stats.get("hydro%"));
|
||||
this.stats.put("epyro", this.stats.get("pyro%"));
|
||||
this.stats.put("ephys", this.stats.get("phys%"));
|
||||
}
|
||||
|
||||
public static float parsePercent(String input) throws NumberFormatException {
|
||||
if (input.endsWith("%")) {
|
||||
return Float.parseFloat(input.substring(0, input.length() - 1)) / 100f;
|
||||
} else {
|
||||
return Float.parseFloat(input);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
String statStr = null;
|
||||
String valueStr;
|
||||
float value = 0f;
|
||||
|
||||
if (args.size() < 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the action and stat
|
||||
String arg0 = args.remove(0).toLowerCase();
|
||||
Action action =
|
||||
switch (arg0) {
|
||||
default -> {
|
||||
statStr = arg0;
|
||||
yield Action.ACTION_SET;
|
||||
} // Implicit set command
|
||||
case "set" -> Action.ACTION_SET; // Explicit set command
|
||||
case "lock", "freeze" -> Action.ACTION_LOCK;
|
||||
case "unlock", "unfreeze" -> Action.ACTION_UNLOCK;
|
||||
};
|
||||
if (statStr == null) {
|
||||
statStr = args.remove(0).toLowerCase();
|
||||
}
|
||||
if (!stats.containsKey(statStr)) {
|
||||
sendUsageMessage(sender); // Invalid stat or action
|
||||
return;
|
||||
}
|
||||
Stat stat = stats.get(statStr);
|
||||
EntityAvatar entity = targetPlayer.getTeamManager().getCurrentAvatarEntity();
|
||||
Avatar avatar = entity.getAvatar();
|
||||
|
||||
// Get the value if the action requires it
|
||||
try {
|
||||
switch (action) {
|
||||
case ACTION_LOCK:
|
||||
if (args.isEmpty()) { // Lock to current value
|
||||
value = avatar.getFightProperty(stat.prop);
|
||||
break;
|
||||
} // Else fall-through and lock to supplied value
|
||||
case ACTION_SET:
|
||||
value = parsePercent(args.remove(0));
|
||||
break;
|
||||
case ACTION_UNLOCK:
|
||||
break;
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.invalid.statValue");
|
||||
return;
|
||||
} catch (IndexOutOfBoundsException ignored) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.isEmpty()) { // Leftover arguments!
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case ACTION_SET:
|
||||
entity.setFightProperty(stat.prop, value);
|
||||
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, stat.prop));
|
||||
break;
|
||||
case ACTION_LOCK:
|
||||
avatar.getFightPropOverrides().put(stat.prop.getId(), value);
|
||||
avatar.recalcStats();
|
||||
break;
|
||||
case ACTION_UNLOCK:
|
||||
avatar.getFightPropOverrides().remove(stat.prop.getId());
|
||||
avatar.recalcStats();
|
||||
break;
|
||||
}
|
||||
|
||||
// Report action
|
||||
if (FightProperty.isPercentage(stat.prop)) {
|
||||
valueStr = String.format("%.1f%%", value * 100f);
|
||||
} else {
|
||||
valueStr = String.format("%.0f", value);
|
||||
}
|
||||
if (targetPlayer == sender) {
|
||||
CommandHandler.sendTranslatedMessage(sender, action.messageKeySelf, stat.name, valueStr);
|
||||
} else {
|
||||
String uidStr = targetPlayer.getAccount().getId();
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, action.messageKeyOther, stat.name, uidStr, valueStr);
|
||||
}
|
||||
}
|
||||
|
||||
private enum Action {
|
||||
ACTION_SET("commands.generic.set_to", "commands.generic.set_for_to"),
|
||||
ACTION_LOCK("commands.setStats.locked_to", "commands.setStats.locked_for_to"),
|
||||
ACTION_UNLOCK("commands.setStats.unlocked", "commands.setStats.unlocked_for");
|
||||
public final String messageKeySelf;
|
||||
public final String messageKeyOther;
|
||||
|
||||
Action(String messageKeySelf, String messageKeyOther) {
|
||||
this.messageKeySelf = messageKeySelf;
|
||||
this.messageKeyOther = messageKeyOther;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Stat {
|
||||
String name;
|
||||
FightProperty prop;
|
||||
|
||||
public Stat(FightProperty prop) {
|
||||
this.name = prop.toString();
|
||||
this.prop = prop;
|
||||
}
|
||||
|
||||
public Stat(String name, FightProperty prop) {
|
||||
this.name = name;
|
||||
this.prop = prop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,217 +1,217 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.GadgetData;
|
||||
import emu.grasscutter.data.excels.ItemData;
|
||||
import emu.grasscutter.data.excels.MonsterData;
|
||||
import emu.grasscutter.game.entity.*;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.EntityType;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static emu.grasscutter.command.CommandHelpers.*;
|
||||
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(
|
||||
label = "spawn",
|
||||
aliases = {"drop", "s"},
|
||||
usage = {
|
||||
"<itemId> [x<amount>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>",
|
||||
"<gadgetId> [x<amount>] [state<state>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>",
|
||||
"<monsterId> [x<amount>] [lv<level>] [ai<aiId>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>"},
|
||||
permission = "server.spawn",
|
||||
permissionTargeted = "server.spawn.others")
|
||||
public final class SpawnCommand implements CommandHandler {
|
||||
private static final Map<Pattern, BiConsumer<SpawnParameters, Integer>> intCommandHandlers = Map.ofEntries(
|
||||
Map.entry(lvlRegex, SpawnParameters::setLvl),
|
||||
Map.entry(amountRegex, SpawnParameters::setAmount),
|
||||
Map.entry(stateRegex, SpawnParameters::setState),
|
||||
Map.entry(blockRegex, SpawnParameters::setBlockId),
|
||||
Map.entry(groupRegex, SpawnParameters::setGroupId),
|
||||
Map.entry(configRegex, SpawnParameters::setConfigId),
|
||||
Map.entry(maxHPRegex, SpawnParameters::setMaxHP),
|
||||
Map.entry(hpRegex, SpawnParameters::setHp),
|
||||
Map.entry(defRegex, SpawnParameters::setDef),
|
||||
Map.entry(atkRegex, SpawnParameters::setAtk),
|
||||
Map.entry(aiRegex, SpawnParameters::setAi)
|
||||
);
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
SpawnParameters param = new SpawnParameters();
|
||||
|
||||
parseIntParameters(args, param, intCommandHandlers);
|
||||
|
||||
// At this point, first remaining argument MUST be the id and the rest the pos
|
||||
if (args.size() < 1) {
|
||||
sendUsageMessage(sender); // Reachable if someone does `/give lv90` or similar
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
switch (args.size()) {
|
||||
case 4:
|
||||
try {
|
||||
float x, y, z;
|
||||
x = Float.parseFloat(args.get(1));
|
||||
y = Float.parseFloat(args.get(2));
|
||||
z = Float.parseFloat(args.get(3));
|
||||
param.pos = new Position(x, y, z);
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.execution.argument_error"));
|
||||
} // Fallthrough
|
||||
case 1:
|
||||
try {
|
||||
param.id = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.entityId"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
MonsterData monsterData = GameData.getMonsterDataMap().get(param.id);
|
||||
GadgetData gadgetData = GameData.getGadgetDataMap().get(param.id);
|
||||
ItemData itemData = GameData.getItemDataMap().get(param.id);
|
||||
if (monsterData == null && gadgetData == null && itemData == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.entityId"));
|
||||
return;
|
||||
}
|
||||
|
||||
param.scene = targetPlayer.getScene();
|
||||
|
||||
if (param.scene.getEntities().size() + param.amount > GAME_OPTIONS.sceneEntityLimit) {
|
||||
param.amount = Math.max(Math.min(GAME_OPTIONS.sceneEntityLimit - param.scene.getEntities().size(), param.amount), 0);
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.spawn.limit_reached", param.amount));
|
||||
if (param.amount <= 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
double maxRadius = Math.sqrt(param.amount * 0.2 / Math.PI);
|
||||
if (param.pos == null) {
|
||||
param.pos = targetPlayer.getPosition();
|
||||
}
|
||||
|
||||
for (int i = 0; i < param.amount; i++) {
|
||||
Position pos = GetRandomPositionInCircle(param.pos, maxRadius).addY(3);
|
||||
GameEntity entity = null;
|
||||
if (itemData != null) {
|
||||
entity = createItem(itemData, param, pos);
|
||||
}
|
||||
if (gadgetData != null) {
|
||||
pos.addY(-3);
|
||||
entity = createGadget(gadgetData, param, pos, targetPlayer);
|
||||
}
|
||||
if (monsterData != null) {
|
||||
entity = createMonster(monsterData, param, pos);
|
||||
}
|
||||
applyCommonParameters(entity, param);
|
||||
|
||||
param.scene.addEntity(entity);
|
||||
}
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.spawn.success", param.amount, param.id));
|
||||
}
|
||||
|
||||
private EntityItem createItem(ItemData itemData, SpawnParameters param, Position pos) {
|
||||
return new EntityItem(param.scene, null, itemData, pos, 1, true);
|
||||
}
|
||||
|
||||
private EntityMonster createMonster(MonsterData monsterData, SpawnParameters param, Position pos) {
|
||||
var entity = new EntityMonster(param.scene, monsterData, pos, param.lvl);
|
||||
if (param.ai != -1) {
|
||||
entity.setAiId(param.ai);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
private EntityBaseGadget createGadget(GadgetData gadgetData, SpawnParameters param, Position pos, Player targetPlayer) {
|
||||
EntityBaseGadget entity;
|
||||
if (gadgetData.getType() == EntityType.Vehicle) {
|
||||
entity = new EntityVehicle(param.scene, targetPlayer, param.id, 0, pos, targetPlayer.getRotation());
|
||||
} else {
|
||||
entity = new EntityGadget(param.scene, param.id, pos, targetPlayer.getRotation());
|
||||
if (param.state != -1) {
|
||||
((EntityGadget) entity).setState(param.state);
|
||||
}
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
private void applyCommonParameters(GameEntity entity, SpawnParameters param) {
|
||||
if (param.blockId != -1) {
|
||||
entity.setBlockId(param.blockId);
|
||||
}
|
||||
if (param.groupId != -1) {
|
||||
entity.setGroupId(param.groupId);
|
||||
}
|
||||
if (param.configId != -1) {
|
||||
entity.setConfigId(param.configId);
|
||||
}
|
||||
if (param.maxHP != -1) {
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_MAX_HP, param.maxHP);
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, param.maxHP);
|
||||
}
|
||||
if (param.hp != -1) {
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, param.hp == 0 ? Float.MAX_VALUE : param.hp);
|
||||
}
|
||||
if (param.atk != -1) {
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_ATTACK, param.atk);
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_ATTACK, param.atk);
|
||||
}
|
||||
if (param.def != -1) {
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_DEFENSE, param.def);
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_DEFENSE, param.def);
|
||||
}
|
||||
}
|
||||
|
||||
private Position GetRandomPositionInCircle(Position origin, double radius) {
|
||||
Position target = origin.clone();
|
||||
double angle = Math.random() * 360;
|
||||
double r = Math.sqrt(Math.random() * radius * radius);
|
||||
target.addX((float) (r * Math.cos(angle))).addZ((float) (r * Math.sin(angle)));
|
||||
return target;
|
||||
}
|
||||
|
||||
private static class SpawnParameters {
|
||||
@Setter
|
||||
public int id;
|
||||
@Setter
|
||||
public int lvl = 1;
|
||||
@Setter
|
||||
public int amount = 1;
|
||||
@Setter
|
||||
public int blockId = -1;
|
||||
@Setter
|
||||
public int groupId = -1;
|
||||
@Setter
|
||||
public int configId = -1;
|
||||
@Setter
|
||||
public int state = -1;
|
||||
@Setter
|
||||
public int hp = -1;
|
||||
@Setter
|
||||
public int maxHP = -1;
|
||||
@Setter
|
||||
public int atk = -1;
|
||||
@Setter
|
||||
public int def = -1;
|
||||
@Setter
|
||||
public int ai = -1;
|
||||
@Setter
|
||||
public Position pos = null;
|
||||
public Scene scene = null;
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.command.CommandHelpers.*;
|
||||
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.GadgetData;
|
||||
import emu.grasscutter.data.excels.ItemData;
|
||||
import emu.grasscutter.data.excels.MonsterData;
|
||||
import emu.grasscutter.game.entity.*;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.EntityType;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.world.Scene;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.regex.Pattern;
|
||||
import lombok.Setter;
|
||||
|
||||
@Command(
|
||||
label = "spawn",
|
||||
aliases = {"drop", "s"},
|
||||
usage = {
|
||||
"<itemId> [x<amount>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>",
|
||||
"<gadgetId> [x<amount>] [state<state>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>",
|
||||
"<monsterId> [x<amount>] [lv<level>] [ai<aiId>] [maxhp<maxhp>] [hp<hp>(0 for infinite)] [atk<atk>] [def<def>] [blk<blockId>] [grp<groupId>] [cfg<configId>] <x> <y> <z>"
|
||||
},
|
||||
permission = "server.spawn",
|
||||
permissionTargeted = "server.spawn.others")
|
||||
public final class SpawnCommand implements CommandHandler {
|
||||
private static final Map<Pattern, BiConsumer<SpawnParameters, Integer>> intCommandHandlers =
|
||||
Map.ofEntries(
|
||||
Map.entry(lvlRegex, SpawnParameters::setLvl),
|
||||
Map.entry(amountRegex, SpawnParameters::setAmount),
|
||||
Map.entry(stateRegex, SpawnParameters::setState),
|
||||
Map.entry(blockRegex, SpawnParameters::setBlockId),
|
||||
Map.entry(groupRegex, SpawnParameters::setGroupId),
|
||||
Map.entry(configRegex, SpawnParameters::setConfigId),
|
||||
Map.entry(maxHPRegex, SpawnParameters::setMaxHP),
|
||||
Map.entry(hpRegex, SpawnParameters::setHp),
|
||||
Map.entry(defRegex, SpawnParameters::setDef),
|
||||
Map.entry(atkRegex, SpawnParameters::setAtk),
|
||||
Map.entry(aiRegex, SpawnParameters::setAi));
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
SpawnParameters param = new SpawnParameters();
|
||||
|
||||
parseIntParameters(args, param, intCommandHandlers);
|
||||
|
||||
// At this point, first remaining argument MUST be the id and the rest the pos
|
||||
if (args.size() < 1) {
|
||||
sendUsageMessage(sender); // Reachable if someone does `/give lv90` or similar
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
switch (args.size()) {
|
||||
case 4:
|
||||
try {
|
||||
float x, y, z;
|
||||
x = Float.parseFloat(args.get(1));
|
||||
y = Float.parseFloat(args.get(2));
|
||||
z = Float.parseFloat(args.get(3));
|
||||
param.pos = new Position(x, y, z);
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.execution.argument_error"));
|
||||
} // Fallthrough
|
||||
case 1:
|
||||
try {
|
||||
param.id = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.generic.invalid.entityId"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
MonsterData monsterData = GameData.getMonsterDataMap().get(param.id);
|
||||
GadgetData gadgetData = GameData.getGadgetDataMap().get(param.id);
|
||||
ItemData itemData = GameData.getItemDataMap().get(param.id);
|
||||
if (monsterData == null && gadgetData == null && itemData == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.entityId"));
|
||||
return;
|
||||
}
|
||||
|
||||
param.scene = targetPlayer.getScene();
|
||||
|
||||
if (param.scene.getEntities().size() + param.amount > GAME_OPTIONS.sceneEntityLimit) {
|
||||
param.amount =
|
||||
Math.max(
|
||||
Math.min(
|
||||
GAME_OPTIONS.sceneEntityLimit - param.scene.getEntities().size(), param.amount),
|
||||
0);
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.spawn.limit_reached", param.amount));
|
||||
if (param.amount <= 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
double maxRadius = Math.sqrt(param.amount * 0.2 / Math.PI);
|
||||
if (param.pos == null) {
|
||||
param.pos = targetPlayer.getPosition();
|
||||
}
|
||||
|
||||
for (int i = 0; i < param.amount; i++) {
|
||||
Position pos = GetRandomPositionInCircle(param.pos, maxRadius).addY(3);
|
||||
GameEntity entity = null;
|
||||
if (itemData != null) {
|
||||
entity = createItem(itemData, param, pos);
|
||||
}
|
||||
if (gadgetData != null) {
|
||||
pos.addY(-3);
|
||||
entity = createGadget(gadgetData, param, pos, targetPlayer);
|
||||
}
|
||||
if (monsterData != null) {
|
||||
entity = createMonster(monsterData, param, pos);
|
||||
}
|
||||
applyCommonParameters(entity, param);
|
||||
|
||||
param.scene.addEntity(entity);
|
||||
}
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.spawn.success", param.amount, param.id));
|
||||
}
|
||||
|
||||
private EntityItem createItem(ItemData itemData, SpawnParameters param, Position pos) {
|
||||
return new EntityItem(param.scene, null, itemData, pos, 1, true);
|
||||
}
|
||||
|
||||
private EntityMonster createMonster(
|
||||
MonsterData monsterData, SpawnParameters param, Position pos) {
|
||||
var entity = new EntityMonster(param.scene, monsterData, pos, param.lvl);
|
||||
if (param.ai != -1) {
|
||||
entity.setAiId(param.ai);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
private EntityBaseGadget createGadget(
|
||||
GadgetData gadgetData, SpawnParameters param, Position pos, Player targetPlayer) {
|
||||
EntityBaseGadget entity;
|
||||
if (gadgetData.getType() == EntityType.Vehicle) {
|
||||
entity =
|
||||
new EntityVehicle(
|
||||
param.scene, targetPlayer, param.id, 0, pos, targetPlayer.getRotation());
|
||||
} else {
|
||||
entity = new EntityGadget(param.scene, param.id, pos, targetPlayer.getRotation());
|
||||
if (param.state != -1) {
|
||||
((EntityGadget) entity).setState(param.state);
|
||||
}
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
private void applyCommonParameters(GameEntity entity, SpawnParameters param) {
|
||||
if (param.blockId != -1) {
|
||||
entity.setBlockId(param.blockId);
|
||||
}
|
||||
if (param.groupId != -1) {
|
||||
entity.setGroupId(param.groupId);
|
||||
}
|
||||
if (param.configId != -1) {
|
||||
entity.setConfigId(param.configId);
|
||||
}
|
||||
if (param.maxHP != -1) {
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_MAX_HP, param.maxHP);
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_BASE_HP, param.maxHP);
|
||||
}
|
||||
if (param.hp != -1) {
|
||||
entity.setFightProperty(
|
||||
FightProperty.FIGHT_PROP_CUR_HP, param.hp == 0 ? Float.MAX_VALUE : param.hp);
|
||||
}
|
||||
if (param.atk != -1) {
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_ATTACK, param.atk);
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_ATTACK, param.atk);
|
||||
}
|
||||
if (param.def != -1) {
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_DEFENSE, param.def);
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_DEFENSE, param.def);
|
||||
}
|
||||
}
|
||||
|
||||
private Position GetRandomPositionInCircle(Position origin, double radius) {
|
||||
Position target = origin.clone();
|
||||
double angle = Math.random() * 360;
|
||||
double r = Math.sqrt(Math.random() * radius * radius);
|
||||
target.addX((float) (r * Math.cos(angle))).addZ((float) (r * Math.sin(angle)));
|
||||
return target;
|
||||
}
|
||||
|
||||
private static class SpawnParameters {
|
||||
@Setter public int id;
|
||||
@Setter public int lvl = 1;
|
||||
@Setter public int amount = 1;
|
||||
@Setter public int blockId = -1;
|
||||
@Setter public int groupId = -1;
|
||||
@Setter public int configId = -1;
|
||||
@Setter public int state = -1;
|
||||
@Setter public int hp = -1;
|
||||
@Setter public int maxHP = -1;
|
||||
@Setter public int atk = -1;
|
||||
@Setter public int def = -1;
|
||||
@Setter public int ai = -1;
|
||||
@Setter public Position pos = null;
|
||||
public Scene scene = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "stop", aliases = {"shutdown"}, permission = "server.stop", targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class StopCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
CommandHandler.sendMessage(null, translate("commands.stop.success"));
|
||||
for (Player p : Grasscutter.getGameServer().getPlayers().values()) {
|
||||
CommandHandler.sendMessage(p, translate(p, "commands.stop.success"));
|
||||
}
|
||||
|
||||
System.exit(1000);
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "stop",
|
||||
aliases = {"shutdown"},
|
||||
permission = "server.stop",
|
||||
targetRequirement = Command.TargetRequirement.NONE)
|
||||
public final class StopCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
CommandHandler.sendMessage(null, translate("commands.stop.success"));
|
||||
for (Player p : Grasscutter.getGameServer().getPlayers().values()) {
|
||||
CommandHandler.sendMessage(p, translate(p, "commands.stop.success"));
|
||||
}
|
||||
|
||||
System.exit(1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,120 +1,129 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.AvatarSkillDepotData;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.utils.Language;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "talent",
|
||||
usage = {"set <talentId> <level>", "(n|e|q|all) <level>", "getid"},
|
||||
permission = "player.settalent",
|
||||
permissionTargeted = "player.settalent.others")
|
||||
public final class TalentCommand implements CommandHandler {
|
||||
private void setTalentLevel(Player sender, Avatar avatar, int skillId, int newLevel) {
|
||||
if (avatar.setSkillLevel(skillId, newLevel)) {
|
||||
long nameHash = GameData.getAvatarSkillDataMap().get(skillId).getNameTextMapHash();
|
||||
var name = Language.getTextMapKey(nameHash);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.set_id", skillId, name, newLevel);
|
||||
} else {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.out_of_range");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 1) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
Avatar avatar = targetPlayer.getTeamManager().getCurrentAvatarEntity().getAvatar();
|
||||
AvatarSkillDepotData skillDepot = avatar.getSkillDepot();
|
||||
if (skillDepot == null) { // Avatars without skill depots aren't a suitable target even with manual skillId specified
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_skill_id");
|
||||
return;
|
||||
}
|
||||
int skillId = 0;
|
||||
int newLevel = -1;
|
||||
|
||||
String cmdSwitch = args.get(0).toLowerCase();
|
||||
switch (cmdSwitch) {
|
||||
default -> {
|
||||
sendUsageMessage(sender);
|
||||
}
|
||||
case "set" -> {
|
||||
if (args.size() < 3) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
skillId = Integer.parseInt(args.get(1));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_skill_id");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
newLevel = Integer.parseInt(args.get(2));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_level");
|
||||
return;
|
||||
}
|
||||
|
||||
setTalentLevel(sender, avatar, skillId, newLevel);
|
||||
}
|
||||
case "n", "e", "q" -> {
|
||||
if (args.size() < 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
newLevel = Integer.parseInt(args.get(1));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_level");
|
||||
return;
|
||||
}
|
||||
|
||||
skillId = switch (cmdSwitch) {
|
||||
default -> skillDepot.getSkills().get(0);
|
||||
case "e" -> skillDepot.getSkills().get(1);
|
||||
case "q" -> skillDepot.getEnergySkill();
|
||||
};
|
||||
setTalentLevel(sender, avatar, skillId, newLevel);
|
||||
}
|
||||
case "all" -> {
|
||||
if (args.size() < 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
newLevel = Integer.parseInt(args.get(1));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_level");
|
||||
return;
|
||||
}
|
||||
// This stops setTalentLevel from outputting 3 "levels out of range" messages
|
||||
if (newLevel < 1 || newLevel > 15) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.out_of_range");
|
||||
return;
|
||||
}
|
||||
int finalNewLevel = newLevel;
|
||||
skillDepot.getSkillsAndEnergySkill().forEach(id -> setTalentLevel(sender, avatar, id, finalNewLevel));
|
||||
}
|
||||
case "getid" -> {
|
||||
var map = GameData.getAvatarSkillDataMap();
|
||||
skillDepot.getSkillsAndEnergySkill().forEach(id -> {
|
||||
var talent = map.get(id);
|
||||
if (talent == null) return;
|
||||
var talentName = Language.getTextMapKey(talent.getNameTextMapHash());
|
||||
var talentDesc = Language.getTextMapKey(talent.getDescTextMapHash());
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.id_desc", id, talentName, talentDesc);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.AvatarSkillDepotData;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.utils.Language;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "talent",
|
||||
usage = {"set <talentId> <level>", "(n|e|q|all) <level>", "getid"},
|
||||
permission = "player.settalent",
|
||||
permissionTargeted = "player.settalent.others")
|
||||
public final class TalentCommand implements CommandHandler {
|
||||
private void setTalentLevel(Player sender, Avatar avatar, int skillId, int newLevel) {
|
||||
if (avatar.setSkillLevel(skillId, newLevel)) {
|
||||
long nameHash = GameData.getAvatarSkillDataMap().get(skillId).getNameTextMapHash();
|
||||
var name = Language.getTextMapKey(nameHash);
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.talent.set_id", skillId, name, newLevel);
|
||||
} else {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.out_of_range");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 1) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
Avatar avatar = targetPlayer.getTeamManager().getCurrentAvatarEntity().getAvatar();
|
||||
AvatarSkillDepotData skillDepot = avatar.getSkillDepot();
|
||||
if (skillDepot
|
||||
== null) { // Avatars without skill depots aren't a suitable target even with manual skillId
|
||||
// specified
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_skill_id");
|
||||
return;
|
||||
}
|
||||
int skillId = 0;
|
||||
int newLevel = -1;
|
||||
|
||||
String cmdSwitch = args.get(0).toLowerCase();
|
||||
switch (cmdSwitch) {
|
||||
default -> {
|
||||
sendUsageMessage(sender);
|
||||
}
|
||||
case "set" -> {
|
||||
if (args.size() < 3) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
skillId = Integer.parseInt(args.get(1));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_skill_id");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
newLevel = Integer.parseInt(args.get(2));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_level");
|
||||
return;
|
||||
}
|
||||
|
||||
setTalentLevel(sender, avatar, skillId, newLevel);
|
||||
}
|
||||
case "n", "e", "q" -> {
|
||||
if (args.size() < 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
newLevel = Integer.parseInt(args.get(1));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_level");
|
||||
return;
|
||||
}
|
||||
|
||||
skillId =
|
||||
switch (cmdSwitch) {
|
||||
default -> skillDepot.getSkills().get(0);
|
||||
case "e" -> skillDepot.getSkills().get(1);
|
||||
case "q" -> skillDepot.getEnergySkill();
|
||||
};
|
||||
setTalentLevel(sender, avatar, skillId, newLevel);
|
||||
}
|
||||
case "all" -> {
|
||||
if (args.size() < 2) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
newLevel = Integer.parseInt(args.get(1));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.invalid_level");
|
||||
return;
|
||||
}
|
||||
// This stops setTalentLevel from outputting 3 "levels out of range" messages
|
||||
if (newLevel < 1 || newLevel > 15) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.talent.out_of_range");
|
||||
return;
|
||||
}
|
||||
int finalNewLevel = newLevel;
|
||||
skillDepot
|
||||
.getSkillsAndEnergySkill()
|
||||
.forEach(id -> setTalentLevel(sender, avatar, id, finalNewLevel));
|
||||
}
|
||||
case "getid" -> {
|
||||
var map = GameData.getAvatarSkillDataMap();
|
||||
skillDepot
|
||||
.getSkillsAndEnergySkill()
|
||||
.forEach(
|
||||
id -> {
|
||||
var talent = map.get(id);
|
||||
if (talent == null) return;
|
||||
var talentName = Language.getTextMapKey(talent.getNameTextMapHash());
|
||||
var talentDesc = Language.getTextMapKey(talent.getDescTextMapHash());
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.talent.id_desc", id, talentName, talentDesc);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,258 +1,268 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.packet.send.PacketChangeMpTeamAvatarRsp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
||||
|
||||
@Command(
|
||||
label = "team",
|
||||
usage = {"add <avatarId,...>", "(remove|set) [index|first|last|index-index,...]"},
|
||||
permission = "player.team",
|
||||
permissionTargeted = "player.team.others")
|
||||
public final class TeamCommand implements CommandHandler {
|
||||
private static final int BASE_AVATARID = 10000000;
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.isEmpty()) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args.get(0)) {
|
||||
case "add":
|
||||
if (!addCommand(sender, targetPlayer, args)) return;
|
||||
break;
|
||||
|
||||
case "remove":
|
||||
if (!removeCommand(sender, targetPlayer, args)) return;
|
||||
break;
|
||||
|
||||
case "set":
|
||||
if (!setCommand(sender, targetPlayer, args)) return;
|
||||
break;
|
||||
|
||||
default:
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_usage");
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
targetPlayer.getTeamManager().updateTeamEntities(
|
||||
new PacketChangeMpTeamAvatarRsp(targetPlayer, targetPlayer.getTeamManager().getCurrentTeamInfo()));
|
||||
}
|
||||
|
||||
private boolean addCommand(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 2) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_usage");
|
||||
sendUsageMessage(sender);
|
||||
return false;
|
||||
}
|
||||
|
||||
int index = -1;
|
||||
if (args.size() > 2) {
|
||||
try {
|
||||
index = Integer.parseInt(args.get(2)) - 1;
|
||||
if (index < 0) index = 0;
|
||||
} catch (Exception e) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_index");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var avatarIds = args.get(1).split(",");
|
||||
var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars();
|
||||
|
||||
if (currentTeamAvatars.size() + avatarIds.length > GAME_OPTIONS.avatarLimits.singlePlayerTeam) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.add_too_much", GAME_OPTIONS.avatarLimits.singlePlayerTeam);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var avatarId : avatarIds) {
|
||||
int id = Integer.parseInt(avatarId);
|
||||
if (!addAvatar(sender, targetPlayer, id, index))
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.failed_to_add_avatar", avatarId);
|
||||
if (index > 0) ++index;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean removeCommand(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 2) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_usage");
|
||||
sendUsageMessage(sender);
|
||||
return false;
|
||||
}
|
||||
|
||||
var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars();
|
||||
var avatarCount = currentTeamAvatars.size();
|
||||
|
||||
var metaIndexList = args.get(1).split(",");
|
||||
var indexes = new HashSet<Integer>();
|
||||
var ignoreList = new ArrayList<Integer>();
|
||||
for (var metaIndex : metaIndexList) {
|
||||
// step 1: parse metaIndex to indexes
|
||||
var subIndexes = transformToIndexes(metaIndex, avatarCount);
|
||||
if (subIndexes == null) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.failed_to_parse_index", metaIndex);
|
||||
continue;
|
||||
}
|
||||
|
||||
// step 2: get all of the avatar id through indexes
|
||||
for (var avatarIndex : subIndexes) {
|
||||
try {
|
||||
indexes.add(currentTeamAvatars.get(avatarIndex - 1));
|
||||
} catch (Exception e) {
|
||||
ignoreList.add(avatarIndex);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// step 3: check if user remove all of the avatar
|
||||
if (indexes.size() >= avatarCount) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.remove_too_much");
|
||||
return false;
|
||||
}
|
||||
|
||||
// step 4: hint user for ignore index
|
||||
if (!ignoreList.isEmpty()) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.ignore_index", ignoreList);
|
||||
}
|
||||
|
||||
// step 5: remove
|
||||
currentTeamAvatars.removeAll(indexes);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean setCommand(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 3) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_usage");
|
||||
sendUsageMessage(sender);
|
||||
return false;
|
||||
}
|
||||
|
||||
var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars();
|
||||
|
||||
int index;
|
||||
try {
|
||||
index = Integer.parseInt(args.get(1)) - 1;
|
||||
if (index < 0) index = 0;
|
||||
} catch (Exception e) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.failed_to_parse_index", args.get(1));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index + 1 > currentTeamAvatars.size()) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.index_out_of_range");
|
||||
return false;
|
||||
}
|
||||
|
||||
int avatarId;
|
||||
try {
|
||||
avatarId = Integer.parseInt(args.get(2));
|
||||
} catch (Exception e) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.failed_parse_avatar_id", args.get(2));
|
||||
return false;
|
||||
}
|
||||
if (avatarId < BASE_AVATARID) {
|
||||
avatarId += BASE_AVATARID;
|
||||
}
|
||||
|
||||
if (currentTeamAvatars.contains(avatarId)) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.avatar_already_in_team", avatarId);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!targetPlayer.getAvatars().hasAvatar(avatarId)) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.avatar_not_found", avatarId);
|
||||
return false;
|
||||
}
|
||||
|
||||
currentTeamAvatars.set(index, avatarId);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean addAvatar(Player sender, Player targetPlayer, int avatarId, int index) {
|
||||
if (avatarId < BASE_AVATARID) {
|
||||
avatarId += BASE_AVATARID;
|
||||
}
|
||||
var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars();
|
||||
if (currentTeamAvatars.contains(avatarId)) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.avatar_already_in_team", avatarId);
|
||||
return false;
|
||||
}
|
||||
if (!targetPlayer.getAvatars().hasAvatar(avatarId)) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.avatar_not_found", avatarId);
|
||||
return false;
|
||||
}
|
||||
if (index < 0) {
|
||||
currentTeamAvatars.add(avatarId);
|
||||
} else {
|
||||
currentTeamAvatars.add(index, avatarId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private List<Integer> transformToIndexes(String metaIndexes, int listLength) {
|
||||
// step 1: check if metaIndexes is a special constants
|
||||
if (metaIndexes.equals("first")) {
|
||||
return List.of(1);
|
||||
} else if (metaIndexes.equals("last")) {
|
||||
return List.of(listLength);
|
||||
}
|
||||
|
||||
// step 2: check if metaIndexes is a range
|
||||
if (metaIndexes.contains("-")) {
|
||||
var range = metaIndexes.split("-");
|
||||
if (range.length < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int min, max;
|
||||
try {
|
||||
min = switch (range[0]) {
|
||||
case "first" -> 1;
|
||||
case "last" -> listLength;
|
||||
default -> Integer.parseInt(range[0]);
|
||||
};
|
||||
|
||||
max = switch (range[1]) {
|
||||
case "first" -> 1;
|
||||
case "last" -> listLength;
|
||||
default -> Integer.parseInt(range[1]);
|
||||
};
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (min > max) {
|
||||
min ^= max;
|
||||
max ^= min;
|
||||
min ^= max;
|
||||
}
|
||||
|
||||
var indexes = new ArrayList<Integer>();
|
||||
for (int i = min; i <= max; ++i) {
|
||||
indexes.add(i);
|
||||
}
|
||||
return indexes;
|
||||
}
|
||||
|
||||
// step 3: index is a value, simply return
|
||||
try {
|
||||
int index = Integer.parseInt(metaIndexes);
|
||||
return List.of(index);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.packet.send.PacketChangeMpTeamAvatarRsp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "team",
|
||||
usage = {"add <avatarId,...>", "(remove|set) [index|first|last|index-index,...]"},
|
||||
permission = "player.team",
|
||||
permissionTargeted = "player.team.others")
|
||||
public final class TeamCommand implements CommandHandler {
|
||||
private static final int BASE_AVATARID = 10000000;
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.isEmpty()) {
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (args.get(0)) {
|
||||
case "add":
|
||||
if (!addCommand(sender, targetPlayer, args)) return;
|
||||
break;
|
||||
|
||||
case "remove":
|
||||
if (!removeCommand(sender, targetPlayer, args)) return;
|
||||
break;
|
||||
|
||||
case "set":
|
||||
if (!setCommand(sender, targetPlayer, args)) return;
|
||||
break;
|
||||
|
||||
default:
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_usage");
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
targetPlayer
|
||||
.getTeamManager()
|
||||
.updateTeamEntities(
|
||||
new PacketChangeMpTeamAvatarRsp(
|
||||
targetPlayer, targetPlayer.getTeamManager().getCurrentTeamInfo()));
|
||||
}
|
||||
|
||||
private boolean addCommand(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 2) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_usage");
|
||||
sendUsageMessage(sender);
|
||||
return false;
|
||||
}
|
||||
|
||||
int index = -1;
|
||||
if (args.size() > 2) {
|
||||
try {
|
||||
index = Integer.parseInt(args.get(2)) - 1;
|
||||
if (index < 0) index = 0;
|
||||
} catch (Exception e) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_index");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var avatarIds = args.get(1).split(",");
|
||||
var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars();
|
||||
|
||||
if (currentTeamAvatars.size() + avatarIds.length > GAME_OPTIONS.avatarLimits.singlePlayerTeam) {
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.team.add_too_much", GAME_OPTIONS.avatarLimits.singlePlayerTeam);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var avatarId : avatarIds) {
|
||||
int id = Integer.parseInt(avatarId);
|
||||
if (!addAvatar(sender, targetPlayer, id, index))
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.team.failed_to_add_avatar", avatarId);
|
||||
if (index > 0) ++index;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean removeCommand(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 2) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_usage");
|
||||
sendUsageMessage(sender);
|
||||
return false;
|
||||
}
|
||||
|
||||
var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars();
|
||||
var avatarCount = currentTeamAvatars.size();
|
||||
|
||||
var metaIndexList = args.get(1).split(",");
|
||||
var indexes = new HashSet<Integer>();
|
||||
var ignoreList = new ArrayList<Integer>();
|
||||
for (var metaIndex : metaIndexList) {
|
||||
// step 1: parse metaIndex to indexes
|
||||
var subIndexes = transformToIndexes(metaIndex, avatarCount);
|
||||
if (subIndexes == null) {
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.team.failed_to_parse_index", metaIndex);
|
||||
continue;
|
||||
}
|
||||
|
||||
// step 2: get all of the avatar id through indexes
|
||||
for (var avatarIndex : subIndexes) {
|
||||
try {
|
||||
indexes.add(currentTeamAvatars.get(avatarIndex - 1));
|
||||
} catch (Exception e) {
|
||||
ignoreList.add(avatarIndex);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// step 3: check if user remove all of the avatar
|
||||
if (indexes.size() >= avatarCount) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.remove_too_much");
|
||||
return false;
|
||||
}
|
||||
|
||||
// step 4: hint user for ignore index
|
||||
if (!ignoreList.isEmpty()) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.ignore_index", ignoreList);
|
||||
}
|
||||
|
||||
// step 5: remove
|
||||
currentTeamAvatars.removeAll(indexes);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean setCommand(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 3) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.invalid_usage");
|
||||
sendUsageMessage(sender);
|
||||
return false;
|
||||
}
|
||||
|
||||
var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars();
|
||||
|
||||
int index;
|
||||
try {
|
||||
index = Integer.parseInt(args.get(1)) - 1;
|
||||
if (index < 0) index = 0;
|
||||
} catch (Exception e) {
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.team.failed_to_parse_index", args.get(1));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index + 1 > currentTeamAvatars.size()) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.index_out_of_range");
|
||||
return false;
|
||||
}
|
||||
|
||||
int avatarId;
|
||||
try {
|
||||
avatarId = Integer.parseInt(args.get(2));
|
||||
} catch (Exception e) {
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.team.failed_parse_avatar_id", args.get(2));
|
||||
return false;
|
||||
}
|
||||
if (avatarId < BASE_AVATARID) {
|
||||
avatarId += BASE_AVATARID;
|
||||
}
|
||||
|
||||
if (currentTeamAvatars.contains(avatarId)) {
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.team.avatar_already_in_team", avatarId);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!targetPlayer.getAvatars().hasAvatar(avatarId)) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.avatar_not_found", avatarId);
|
||||
return false;
|
||||
}
|
||||
|
||||
currentTeamAvatars.set(index, avatarId);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean addAvatar(Player sender, Player targetPlayer, int avatarId, int index) {
|
||||
if (avatarId < BASE_AVATARID) {
|
||||
avatarId += BASE_AVATARID;
|
||||
}
|
||||
var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars();
|
||||
if (currentTeamAvatars.contains(avatarId)) {
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.team.avatar_already_in_team", avatarId);
|
||||
return false;
|
||||
}
|
||||
if (!targetPlayer.getAvatars().hasAvatar(avatarId)) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.team.avatar_not_found", avatarId);
|
||||
return false;
|
||||
}
|
||||
if (index < 0) {
|
||||
currentTeamAvatars.add(avatarId);
|
||||
} else {
|
||||
currentTeamAvatars.add(index, avatarId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private List<Integer> transformToIndexes(String metaIndexes, int listLength) {
|
||||
// step 1: check if metaIndexes is a special constants
|
||||
if (metaIndexes.equals("first")) {
|
||||
return List.of(1);
|
||||
} else if (metaIndexes.equals("last")) {
|
||||
return List.of(listLength);
|
||||
}
|
||||
|
||||
// step 2: check if metaIndexes is a range
|
||||
if (metaIndexes.contains("-")) {
|
||||
var range = metaIndexes.split("-");
|
||||
if (range.length < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int min, max;
|
||||
try {
|
||||
min =
|
||||
switch (range[0]) {
|
||||
case "first" -> 1;
|
||||
case "last" -> listLength;
|
||||
default -> Integer.parseInt(range[0]);
|
||||
};
|
||||
|
||||
max =
|
||||
switch (range[1]) {
|
||||
case "first" -> 1;
|
||||
case "last" -> listLength;
|
||||
default -> Integer.parseInt(range[1]);
|
||||
};
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (min > max) {
|
||||
min ^= max;
|
||||
max ^= min;
|
||||
min ^= max;
|
||||
}
|
||||
|
||||
var indexes = new ArrayList<Integer>();
|
||||
for (int i = min; i <= max; ++i) {
|
||||
indexes.add(i);
|
||||
}
|
||||
return indexes;
|
||||
}
|
||||
|
||||
// step 3: index is a value, simply return
|
||||
try {
|
||||
int index = Integer.parseInt(metaIndexes);
|
||||
return List.of(index);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,36 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "teleportAll", aliases = {"tpall"}, permission = "player.tpall", permissionTargeted = "player.tpall.others")
|
||||
public final class TeleportAllCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (!targetPlayer.getWorld().isMultiplayer()) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.teleportAll.error"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (Player player : targetPlayer.getWorld().getPlayers()) {
|
||||
if (player.equals(targetPlayer))
|
||||
continue;
|
||||
|
||||
player.getWorld().transferPlayerToScene(player, targetPlayer.getSceneId(), TeleportType.COMMAND, targetPlayer.getPosition());
|
||||
}
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.teleportAll.success"));
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "teleportAll",
|
||||
aliases = {"tpall"},
|
||||
permission = "player.tpall",
|
||||
permissionTargeted = "player.tpall.others")
|
||||
public final class TeleportAllCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (!targetPlayer.getWorld().isMultiplayer()) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.teleportAll.error"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (Player player : targetPlayer.getWorld().getPlayers()) {
|
||||
if (player.equals(targetPlayer)) continue;
|
||||
|
||||
player
|
||||
.getWorld()
|
||||
.transferPlayerToScene(
|
||||
player, targetPlayer.getSceneId(), TeleportType.COMMAND, targetPlayer.getPosition());
|
||||
}
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.teleportAll.success"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,68 +1,78 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType;
|
||||
import emu.grasscutter.utils.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "teleport", aliases = {"tp"}, usage = {"<x> <y> <z> [sceneId]"}, permission = "player.teleport", permissionTargeted = "player.teleport.others")
|
||||
public final class TeleportCommand implements CommandHandler {
|
||||
|
||||
private float parseRelative(String input, Float current) { // TODO: Maybe this will be useful elsewhere later
|
||||
if (input.contains("~")) { // Relative
|
||||
if (!input.equals("~")) { // Relative with offset
|
||||
current += Float.parseFloat(input.replace("~", ""));
|
||||
} // Else no offset, no modification
|
||||
} else { // Absolute
|
||||
current = Float.parseFloat(input);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
Position pos = targetPlayer.getPosition();
|
||||
float x = pos.getX();
|
||||
float y = pos.getY();
|
||||
float z = pos.getZ();
|
||||
int sceneId = targetPlayer.getSceneId();
|
||||
|
||||
switch (args.size()) {
|
||||
case 4:
|
||||
try {
|
||||
sceneId = Integer.parseInt(args.get(3));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.execution.argument_error"));
|
||||
} // Fallthrough
|
||||
case 3:
|
||||
try {
|
||||
x = this.parseRelative(args.get(0), x);
|
||||
y = this.parseRelative(args.get(1), y);
|
||||
z = this.parseRelative(args.get(2), z);
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.invalid_position"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
this.sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
Position target_pos = new Position(x, y, z);
|
||||
boolean result = targetPlayer.getWorld().transferPlayerToScene(targetPlayer, sceneId, TeleportType.COMMAND, target_pos);
|
||||
|
||||
if (!result) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.exists_error"));
|
||||
} else {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.success",
|
||||
targetPlayer.getNickname(), x, y, z, sceneId)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType;
|
||||
import emu.grasscutter.utils.Position;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "teleport",
|
||||
aliases = {"tp"},
|
||||
usage = {"<x> <y> <z> [sceneId]"},
|
||||
permission = "player.teleport",
|
||||
permissionTargeted = "player.teleport.others")
|
||||
public final class TeleportCommand implements CommandHandler {
|
||||
|
||||
private float parseRelative(
|
||||
String input, Float current) { // TODO: Maybe this will be useful elsewhere later
|
||||
if (input.contains("~")) { // Relative
|
||||
if (!input.equals("~")) { // Relative with offset
|
||||
current += Float.parseFloat(input.replace("~", ""));
|
||||
} // Else no offset, no modification
|
||||
} else { // Absolute
|
||||
current = Float.parseFloat(input);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
Position pos = targetPlayer.getPosition();
|
||||
float x = pos.getX();
|
||||
float y = pos.getY();
|
||||
float z = pos.getZ();
|
||||
int sceneId = targetPlayer.getSceneId();
|
||||
|
||||
switch (args.size()) {
|
||||
case 4:
|
||||
try {
|
||||
sceneId = Integer.parseInt(args.get(3));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.execution.argument_error"));
|
||||
} // Fallthrough
|
||||
case 3:
|
||||
try {
|
||||
x = this.parseRelative(args.get(0), x);
|
||||
y = this.parseRelative(args.get(1), y);
|
||||
z = this.parseRelative(args.get(2), z);
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.teleport.invalid_position"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
this.sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
|
||||
Position target_pos = new Position(x, y, z);
|
||||
boolean result =
|
||||
targetPlayer
|
||||
.getWorld()
|
||||
.transferPlayerToScene(targetPlayer, sceneId, TeleportType.COMMAND, target_pos);
|
||||
|
||||
if (!result) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.teleport.exists_error"));
|
||||
} else {
|
||||
CommandHandler.sendMessage(
|
||||
sender,
|
||||
translate(
|
||||
sender, "commands.teleport.success", targetPlayer.getNickname(), x, y, z, sceneId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +1,39 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.Account;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "unban",
|
||||
permission = "server.ban",
|
||||
targetRequirement = Command.TargetRequirement.PLAYER
|
||||
)
|
||||
public final class UnBanCommand implements CommandHandler {
|
||||
|
||||
private boolean unBanAccount(Player targetPlayer) {
|
||||
Account account = targetPlayer.getAccount();
|
||||
|
||||
if (account == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
account.setBanReason(null);
|
||||
account.setBanEndTime(0);
|
||||
account.setBanStartTime(0);
|
||||
account.setBanned(false);
|
||||
account.save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (unBanAccount(targetPlayer)) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.unban.success");
|
||||
} else {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.unban.failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.Account;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "unban",
|
||||
permission = "server.ban",
|
||||
targetRequirement = Command.TargetRequirement.PLAYER)
|
||||
public final class UnBanCommand implements CommandHandler {
|
||||
|
||||
private boolean unBanAccount(Player targetPlayer) {
|
||||
Account account = targetPlayer.getAccount();
|
||||
|
||||
if (account == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
account.setBanReason(null);
|
||||
account.setBanEndTime(0);
|
||||
account.setBanStartTime(0);
|
||||
account.setBanned(false);
|
||||
account.save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (unBanAccount(targetPlayer)) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.unban.success");
|
||||
} else {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.unban.failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,43 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.player.PlayerProgressManager;
|
||||
import emu.grasscutter.server.packet.send.PacketOpenStateChangeNotify;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "unlockall", usage = {""}, permission = "player.unlockall", permissionTargeted = "player.unlockall.others")
|
||||
public final class UnlockAllCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
Map<Integer, Integer> changed = new HashMap<>();
|
||||
|
||||
for (var state : GameData.getOpenStateList()) {
|
||||
// Don't unlock blacklisted open states.
|
||||
if (PlayerProgressManager.BLACKLIST_OPEN_STATES.contains(state.getId())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (targetPlayer.getProgressManager().getOpenState(state.getId()) == 0) {
|
||||
targetPlayer.getOpenStates().put(state.getId(), 1);
|
||||
changed.put(state.getId(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
targetPlayer.sendPacket(new PacketOpenStateChangeNotify(changed));
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.unlockall.success", targetPlayer.getNickname()));
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.player.PlayerProgressManager;
|
||||
import emu.grasscutter.server.packet.send.PacketOpenStateChangeNotify;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Command(
|
||||
label = "unlockall",
|
||||
usage = {""},
|
||||
permission = "player.unlockall",
|
||||
permissionTargeted = "player.unlockall.others")
|
||||
public final class UnlockAllCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
Map<Integer, Integer> changed = new HashMap<>();
|
||||
|
||||
for (var state : GameData.getOpenStateList()) {
|
||||
// Don't unlock blacklisted open states.
|
||||
if (PlayerProgressManager.BLACKLIST_OPEN_STATES.contains(state.getId())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (targetPlayer.getProgressManager().getOpenState(state.getId()) == 0) {
|
||||
targetPlayer.getOpenStates().put(state.getId(), 1);
|
||||
changed.put(state.getId(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
targetPlayer.sendPacket(new PacketOpenStateChangeNotify(changed));
|
||||
|
||||
CommandHandler.sendMessage(
|
||||
sender, translate(sender, "commands.unlockall.success", targetPlayer.getNickname()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,52 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.ClimateType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Command(label = "weather", aliases = {"w"}, usage = {"weather [<weatherId>] [<climateType>]"}, permission = "player.weather", permissionTargeted = "player.weather.others")
|
||||
public final class WeatherCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
int weatherId = targetPlayer.getWeatherId();
|
||||
ClimateType climate = ClimateType.CLIMATE_NONE; // Sending ClimateType.CLIMATE_NONE to Scene.setWeather will use the default climate for that weather
|
||||
|
||||
if (args.isEmpty()) {
|
||||
climate = targetPlayer.getClimate();
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.weather.status", weatherId, climate.getShortName());
|
||||
return;
|
||||
}
|
||||
|
||||
for (String arg : args) {
|
||||
ClimateType c = ClimateType.getTypeByShortName(arg.toLowerCase());
|
||||
if (c != ClimateType.CLIMATE_NONE) {
|
||||
climate = c;
|
||||
} else {
|
||||
try {
|
||||
weatherId = Integer.parseInt(arg);
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.invalid.id");
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
targetPlayer.setWeather(weatherId, climate);
|
||||
climate = targetPlayer.getClimate(); // Might be different to what we set
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.weather.success", weatherId, climate.getShortName());
|
||||
}
|
||||
}
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.ClimateType;
|
||||
import java.util.List;
|
||||
|
||||
@Command(
|
||||
label = "weather",
|
||||
aliases = {"w"},
|
||||
usage = {"weather [<weatherId>] [<climateType>]"},
|
||||
permission = "player.weather",
|
||||
permissionTargeted = "player.weather.others")
|
||||
public final class WeatherCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
int weatherId = targetPlayer.getWeatherId();
|
||||
ClimateType climate =
|
||||
ClimateType
|
||||
.CLIMATE_NONE; // Sending ClimateType.CLIMATE_NONE to Scene.setWeather will use the
|
||||
// default climate for that weather
|
||||
|
||||
if (args.isEmpty()) {
|
||||
climate = targetPlayer.getClimate();
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.weather.status", weatherId, climate.getShortName());
|
||||
return;
|
||||
}
|
||||
|
||||
for (String arg : args) {
|
||||
ClimateType c = ClimateType.getTypeByShortName(arg.toLowerCase());
|
||||
if (c != ClimateType.CLIMATE_NONE) {
|
||||
climate = c;
|
||||
} else {
|
||||
try {
|
||||
weatherId = Integer.parseInt(arg);
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.invalid.id");
|
||||
sendUsageMessage(sender);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
targetPlayer.setWeather(weatherId, climate);
|
||||
climate = targetPlayer.getClimate(); // Might be different to what we set
|
||||
CommandHandler.sendTranslatedMessage(
|
||||
sender, "commands.weather.success", weatherId, climate.getShortName());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user