Format code [skip actions]

This commit is contained in:
github-actions
2023-05-11 02:23:43 +00:00
Unverified
parent f51fd55cb5
commit f9906c4492
730 changed files with 29212 additions and 29159 deletions
@@ -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,88 +1,88 @@
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) {}
}
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,354 +1,354 @@
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);
}
});
}
}
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,33 +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,10 +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);
}
@@ -47,7 +47,7 @@ public final class AccountCommand implements CommandHandler {
if (Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) {
if (args.size() < 3) {
CommandHandler.sendMessage(
sender, "EXPERIMENTAL_RealPassword requires a password argument");
sender, "EXPERIMENTAL_RealPassword requires a password argument");
CommandHandler.sendMessage(sender, "Usage: account create <username> <password> [uid]");
return;
}
@@ -60,10 +60,10 @@ public final class AccountCommand implements CommandHandler {
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");
sender,
"EXPERIMENTAL_RealPassword requires argument 2 to be a password, not a uid");
CommandHandler.sendMessage(
sender, "Usage: account create <username> <password> [uid]");
sender, "Usage: account create <username> <password> [uid]");
}
return;
}
@@ -90,7 +90,7 @@ public final class AccountCommand implements CommandHandler {
account.save(); // Save account to database.
CommandHandler.sendMessage(
sender, translate(sender, "commands.account.create", account.getReservedPlayerUid()));
sender, translate(sender, "commands.account.create", account.getReservedPlayerUid()));
}
}
case "delete" -> {
@@ -106,7 +106,7 @@ public final class AccountCommand implements CommandHandler {
case "resetpass" -> {
if (!Configuration.ACCOUNT.EXPERIMENTAL_RealPassword) {
CommandHandler.sendMessage(
sender, "resetpass requires EXPERIMENTAL_RealPassword to be true.");
sender, "resetpass requires EXPERIMENTAL_RealPassword to be true.");
return;
}
if (args.size() != 3) {
@@ -128,23 +128,27 @@ public final class AccountCommand implements CommandHandler {
}
case "list" -> {
CommandHandler.sendMessage(sender, "Note: This command might take a while to complete.");
CommandHandler.sendMessage(sender,
"Accounts: \n" + DatabaseManager.getAccountDatastore()
.find(Account.class).stream()
.map(acc -> "%s: %s (%s)".formatted(
acc.getId(), acc.getUsername(),
acc.getReservedPlayerUid() == 0 ?
this.getPlayerUid(acc) :
acc.getReservedPlayerUid()))
.collect(Collectors.joining("\n"))
);
CommandHandler.sendMessage(
sender,
"Accounts: \n"
+ DatabaseManager.getAccountDatastore().find(Account.class).stream()
.map(
acc ->
"%s: %s (%s)"
.formatted(
acc.getId(),
acc.getUsername(),
acc.getReservedPlayerUid() == 0
? this.getPlayerUid(acc)
: acc.getReservedPlayerUid()))
.collect(Collectors.joining("\n")));
}
}
}
/**
* Returns the UID of the player associated with the given account.
* If the player is not found, returns "no UID".
* Returns the UID of the player associated with the given account. If the player is not found,
* returns "no UID".
*
* @param account The account to get the UID of.
* @return The UID of the player associated with the given account.
@@ -1,78 +1,78 @@
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));
}
}
}
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,62 +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,105 +1,105 @@
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;
}
}
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,57 +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,50 +1,50 @@
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);
}
}
}
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,11 +1,14 @@
package emu.grasscutter.command.commands;
import static emu.grasscutter.GameConstants.*;
import static emu.grasscutter.command.CommandHelpers.*;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.GameDepot;
import emu.grasscutter.data.excels.avatar.AvatarData;
import emu.grasscutter.data.excels.ItemData;
import emu.grasscutter.data.excels.avatar.AvatarData;
import emu.grasscutter.data.excels.reliquary.ReliquaryAffixData;
import emu.grasscutter.data.excels.reliquary.ReliquaryMainPropData;
import emu.grasscutter.game.avatar.Avatar;
@@ -14,45 +17,50 @@ import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.utils.SparseSet;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.regex.Pattern;
import static emu.grasscutter.GameConstants.*;
import static emu.grasscutter.command.CommandHelpers.*;
import lombok.Setter;
@Command(
label = "give",
aliases = {"g", "item", "giveitem"},
usage = {
"(<itemId>|<avatarId>|all|weapons|mats|avatars) [lv<level>] [r<refinement>] [x<amount>] [c<constellation>] [sl<skilllevel>]",
"<artifactId> [lv<level>] [x<amount>] [<mainPropId>] [<appendPropId>[,<times>]]..."},
permission = "player.give",
permissionTargeted = "player.give.others",
threading = true)
label = "give",
aliases = {"g", "item", "giveitem"},
usage = {
"(<itemId>|<avatarId>|all|weapons|mats|avatars) [lv<level>] [r<refinement>] [x<amount>] [c<constellation>] [sl<skilllevel>]",
"<artifactId> [lv<level>] [x<amount>] [<mainPropId>] [<appendPropId>[,<times>]]..."
},
permission = "player.give",
permissionTargeted = "player.give.others",
threading = true)
public final class GiveCommand implements CommandHandler {
private static final Map<Pattern, BiConsumer<GiveItemParameters, Integer>> intCommandHandlers = Map.ofEntries(
Map.entry(lvlRegex, GiveItemParameters::setLvl),
Map.entry(refineRegex, GiveItemParameters::setRefinement),
Map.entry(amountRegex, GiveItemParameters::setAmount),
Map.entry(constellationRegex, GiveItemParameters::setConstellation),
Map.entry(skillLevelRegex, GiveItemParameters::setSkillLevel)
);
private static final Map<Pattern, BiConsumer<GiveItemParameters, Integer>> intCommandHandlers =
Map.ofEntries(
Map.entry(lvlRegex, GiveItemParameters::setLvl),
Map.entry(refineRegex, GiveItemParameters::setRefinement),
Map.entry(amountRegex, GiveItemParameters::setAmount),
Map.entry(constellationRegex, GiveItemParameters::setConstellation),
Map.entry(skillLevelRegex, GiveItemParameters::setSkillLevel));
private static Avatar makeAvatar(GiveItemParameters param) {
return makeAvatar(param.avatarData, param.lvl, Avatar.getMinPromoteLevel(param.lvl), param.constellation, param.skillLevel);
return makeAvatar(
param.avatarData,
param.lvl,
Avatar.getMinPromoteLevel(param.lvl),
param.constellation,
param.skillLevel);
}
private static Avatar makeAvatar(AvatarData avatarData, int level, int promoteLevel, int constellation, int skillLevel) {
private static Avatar makeAvatar(
AvatarData avatarData, int level, int promoteLevel, int constellation, int skillLevel) {
Avatar avatar = new Avatar(avatarData);
avatar.setLevel(level);
avatar.setPromoteLevel(promoteLevel);
avatar.getSkillDepot().getSkillsAndEnergySkill().forEach(id -> avatar.setSkillLevel(id, skillLevel));
avatar
.getSkillDepot()
.getSkillsAndEnergySkill()
.forEach(id -> avatar.setSkillLevel(id, skillLevel));
avatar.forceConstellationLevel(constellation);
avatar.recalcStats(true);
avatar.save();
@@ -62,12 +70,16 @@ public final class GiveCommand implements CommandHandler {
private static void giveAllAvatars(Player player, GiveItemParameters param) {
int promoteLevel = Avatar.getMinPromoteLevel(param.lvl);
if (param.constellation < 0 || param.constellation > 6)
param.constellation = 6; // constellation's default is -1 so if no parameters set for constellations it'll automatically be 6
param.constellation =
6; // constellation's default is -1 so if no parameters set for constellations it'll
// automatically be 6
for (AvatarData avatarData : GameData.getAvatarDataMap().values()) {
int id = avatarData.getId();
if (id < 10000002 || id >= 11000000) continue; // Exclude test avatars
// Don't try to add each avatar to the current team
player.addAvatar(makeAvatar(avatarData, param.lvl, promoteLevel, param.constellation, param.skillLevel), false);
player.addAvatar(
makeAvatar(avatarData, param.lvl, promoteLevel, param.constellation, param.skillLevel),
false);
}
}
@@ -76,8 +88,7 @@ public final class GiveCommand implements CommandHandler {
int totalExp = 0;
if (param.data.getItemType() == ItemType.ITEM_WEAPON) {
int rankLevel = param.data.getRankLevel();
for (int i = 1; i < param.lvl; i++)
totalExp += GameData.getWeaponExpRequired(rankLevel, i);
for (int i = 1; i < param.lvl; i++) totalExp += GameData.getWeaponExpRequired(rankLevel, i);
}
List<GameItem> items = new ArrayList<>(param.amount);
@@ -87,7 +98,7 @@ public final class GiveCommand implements CommandHandler {
if (item.getItemType() == ItemType.ITEM_WEAPON) {
item.setPromoteLevel(promoteLevel);
item.setTotalExp(totalExp);
item.setRefinement(param.refinement - 1); // Actual refinement data is 0..4 not 1..5
item.setRefinement(param.refinement - 1); // Actual refinement data is 0..4 not 1..5
}
items.add(item);
}
@@ -98,8 +109,7 @@ public final class GiveCommand implements CommandHandler {
param.lvl = Math.min(param.lvl, param.data.getMaxLevel());
int rank = param.data.getRankLevel();
int totalExp = 0;
for (int i = 1; i < param.lvl; i++)
totalExp += GameData.getRelicExpRequired(rank, i);
for (int i = 1; i < param.lvl; i++) totalExp += GameData.getRelicExpRequired(rank, i);
List<GameItem> items = new ArrayList<>(param.amount);
for (int i = 0; i < param.amount; i++) {
@@ -108,8 +118,8 @@ public final class GiveCommand implements CommandHandler {
item.setLevel(param.lvl);
item.setTotalExp(totalExp);
int numAffixes = param.data.getAppendPropNum() + (param.lvl - 1) / 4;
if (param.mainPropId > 0) // Keep random mainProp if we didn't specify one
item.setMainPropId(param.mainPropId);
if (param.mainPropId > 0) // Keep random mainProp if we didn't specify one
item.setMainPropId(param.mainPropId);
if (param.appendPropIdList != null) {
item.getAppendPropIdList().clear();
item.getAppendPropIdList().addAll(param.appendPropIdList);
@@ -121,15 +131,17 @@ public final class GiveCommand implements CommandHandler {
return items;
}
private static int getArtifactMainProp(ItemData itemData, FightProperty prop) throws IllegalArgumentException {
private static int getArtifactMainProp(ItemData itemData, FightProperty prop)
throws IllegalArgumentException {
if (prop != FightProperty.FIGHT_PROP_NONE)
for (ReliquaryMainPropData data : GameDepot.getRelicMainPropList(itemData.getMainPropDepotId()))
if (data.getWeight() > 0 && data.getFightProp() == prop)
return data.getId();
for (ReliquaryMainPropData data :
GameDepot.getRelicMainPropList(itemData.getMainPropDepotId()))
if (data.getWeight() > 0 && data.getFightProp() == prop) return data.getId();
throw new IllegalArgumentException();
}
private static List<Integer> getArtifactAffixes(ItemData itemData, FightProperty prop) throws IllegalArgumentException {
private static List<Integer> getArtifactAffixes(ItemData itemData, FightProperty prop)
throws IllegalArgumentException {
if (prop == FightProperty.FIGHT_PROP_NONE) {
throw new IllegalArgumentException();
}
@@ -142,7 +154,8 @@ public final class GiveCommand implements CommandHandler {
return affixes;
}
private static int getAppendPropId(String substatText, ItemData itemData) throws IllegalArgumentException {
private static int getAppendPropId(String substatText, ItemData itemData)
throws IllegalArgumentException {
// If the given substat text is an integer, we just use that as the append prop ID.
try {
return Integer.parseInt(substatText);
@@ -159,19 +172,21 @@ public final class GiveCommand implements CommandHandler {
substatTier = Integer.parseInt(substatArgs[1]);
}
List<Integer> substats = getArtifactAffixes(itemData, FightProperty.getPropByShortName(substatType));
List<Integer> substats =
getArtifactAffixes(itemData, FightProperty.getPropByShortName(substatType));
if (substats.isEmpty()) {
throw new IllegalArgumentException();
}
substatTier -= 1; // 1-indexed to 0-indexed
substatTier -= 1; // 1-indexed to 0-indexed
substatTier = Math.min(Math.max(0, substatTier), substats.size() - 1);
return substats.get(substatTier);
}
}
private static void parseRelicArgs(GiveItemParameters param, List<String> args) throws IllegalArgumentException {
private static void parseRelicArgs(GiveItemParameters param, List<String> args)
throws IllegalArgumentException {
// Get the main stat from the arguments.
// If the given argument is an integer, we use that.
// If not, we check if the argument string is in the main prop map.
@@ -181,7 +196,8 @@ public final class GiveCommand implements CommandHandler {
param.mainPropId = Integer.parseInt(mainPropIdString);
} catch (NumberFormatException ignored) {
// This can in turn throw an exception which we don't want to catch here.
param.mainPropId = getArtifactMainProp(param.data, FightProperty.getPropByShortName(mainPropIdString));
param.mainPropId =
getArtifactMainProp(param.data, FightProperty.getPropByShortName(mainPropIdString));
}
// Get substats.
@@ -219,7 +235,7 @@ public final class GiveCommand implements CommandHandler {
List<GameItem> itemList = new ArrayList<>();
for (ItemData itemdata : GameData.getItemDataMap().values()) {
int id = itemdata.getId();
if (id < 100_000) continue; // Nothing meaningful below this
if (id < 100_000) continue; // Nothing meaningful below this
if (ILLEGAL_ITEMS.contains(id)) continue;
if (itemdata.isEquip()) continue;
@@ -239,7 +255,7 @@ public final class GiveCommand implements CommandHandler {
List<GameItem> itemList = new ArrayList<>();
for (ItemData itemdata : GameData.getItemDataMap().values()) {
int id = itemdata.getId();
if (id < 11100 || id > 16000) continue; // All extant weapons are within this range
if (id < 11100 || id > 16000) continue; // All extant weapons are within this range
if (ILLEGAL_WEAPONS.contains(id)) continue;
if (!itemdata.isEquip()) continue;
if (itemdata.getItemType() != ItemType.ITEM_WEAPON) continue;
@@ -262,7 +278,8 @@ public final class GiveCommand implements CommandHandler {
giveAllWeapons(player, param);
}
private GiveItemParameters parseArgs(Player sender, List<String> args) throws IllegalArgumentException {
private GiveItemParameters parseArgs(Player sender, List<String> args)
throws IllegalArgumentException {
GiveItemParameters param = new GiveItemParameters();
// Extract any tagged arguments (e.g. "lv90", "x100", "r5")
@@ -270,7 +287,7 @@ public final class GiveCommand implements CommandHandler {
// At this point, first remaining argument MUST be itemId/avatarId
if (args.size() < 1) {
sendUsageMessage(sender); // Reachable if someone does `/give lv90` or similar
sendUsageMessage(sender); // Reachable if someone does `/give lv90` or similar
throw new IllegalArgumentException();
}
String id = args.remove(0);
@@ -304,7 +321,9 @@ public final class GiveCommand implements CommandHandler {
param.avatarData = GameData.getAvatarDataMap().get(param.id - 1000 + 10_000_000);
isRelic = ((param.data != null) && (param.data.getItemType() == ItemType.ITEM_RELIQUARY));
if (!isRelic && !args.isEmpty() && (param.amount == 1)) { // A concession for the people that truly hate [x<amount>].
if (!isRelic
&& !args.isEmpty()
&& (param.amount == 1)) { // A concession for the people that truly hate [x<amount>].
try {
param.amount = Integer.parseInt(args.remove(0));
} catch (NumberFormatException e) {
@@ -382,7 +401,8 @@ public final class GiveCommand implements CommandHandler {
if (param.avatarData != null) {
Avatar avatar = makeAvatar(param);
targetPlayer.addAvatar(avatar);
CommandHandler.sendTranslatedMessage(sender, "commands.give.given_avatar", param.id, param.lvl, targetPlayer.getUid());
CommandHandler.sendTranslatedMessage(
sender, "commands.give.given_avatar", param.id, param.lvl, targetPlayer.getUid());
return;
}
// If it's not an avatar, it needs to be a valid item
@@ -393,16 +413,34 @@ public final class GiveCommand implements CommandHandler {
switch (param.data.getItemType()) {
case ITEM_WEAPON:
targetPlayer.getInventory().addItems(makeUnstackableItems(param), ActionReason.SubfieldDrop);
CommandHandler.sendTranslatedMessage(sender, "commands.give.given_with_level_and_refinement", param.id, param.lvl, param.refinement, param.amount, targetPlayer.getUid());
targetPlayer
.getInventory()
.addItems(makeUnstackableItems(param), ActionReason.SubfieldDrop);
CommandHandler.sendTranslatedMessage(
sender,
"commands.give.given_with_level_and_refinement",
param.id,
param.lvl,
param.refinement,
param.amount,
targetPlayer.getUid());
return;
case ITEM_RELIQUARY:
targetPlayer.getInventory().addItems(makeArtifacts(param), ActionReason.SubfieldDrop);
CommandHandler.sendTranslatedMessage(sender, "commands.give.given_level", param.id, param.lvl, param.amount, targetPlayer.getUid());
CommandHandler.sendTranslatedMessage(
sender,
"commands.give.given_level",
param.id,
param.lvl,
param.amount,
targetPlayer.getUid());
return;
default:
targetPlayer.getInventory().addItem(new GameItem(param.data, param.amount), ActionReason.SubfieldDrop);
CommandHandler.sendTranslatedMessage(sender, "commands.give.given", param.amount, param.id, targetPlayer.getUid());
targetPlayer
.getInventory()
.addItem(new GameItem(param.data, param.amount), ActionReason.SubfieldDrop);
CommandHandler.sendTranslatedMessage(
sender, "commands.give.given", param.amount, param.id, targetPlayer.getUid());
}
} catch (IllegalArgumentException ignored) {
}
@@ -418,16 +456,11 @@ public final class GiveCommand implements CommandHandler {
private static class GiveItemParameters {
public int id;
@Setter
public int lvl = 0;
@Setter
public int amount = 1;
@Setter
public int refinement = 1;
@Setter
public int constellation = -1;
@Setter
public int skillLevel = 1;
@Setter public int lvl = 0;
@Setter public int amount = 1;
@Setter public int refinement = 1;
@Setter public int constellation = -1;
@Setter public int skillLevel = 1;
public int mainPropId = -1;
public List<Integer> appendPropIdList;
public ItemData data;
@@ -1,44 +1,44 @@
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"));
}
}
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,92 +1,92 @@
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));
}
}
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,34 +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,54 +1,54 @@
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()));
}
}
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,41 +1,41 @@
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()));
}
}
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,58 +1,58 @@
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));
}
}
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,56 +1,56 @@
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));
}
}
}
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,74 +1,74 @@
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();
}
}
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,29 +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,43 +1,43 @@
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);
}
}
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,23 +1,23 @@
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"));
}
}
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,241 +1,241 @@
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();
}
}
}
}
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,37 +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,92 +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 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"));
}
}
}
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,27 +1,27 @@
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);
}
}
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,268 +1,268 @@
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;
}
}
}
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,36 +1,36 @@
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"));
}
}
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,78 +1,78 @@
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));
}
}
}
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,39 +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,43 +1,43 @@
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()));
}
}
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,52 +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());
}
}