mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-20 02:45:52 +01:00
Implement new command system
This commit is contained in:
@@ -5,9 +5,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Command {
|
||||
String label() default "";
|
||||
|
||||
String[] aliases() default "";
|
||||
|
||||
int gmLevel() default 1;
|
||||
|
||||
String helpText() default "";
|
||||
String usage() default "";
|
||||
}
|
||||
|
||||
28
src/main/java/emu/grasscutter/commands/CommandHandler.java
Normal file
28
src/main/java/emu/grasscutter/commands/CommandHandler.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package emu.grasscutter.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.game.GenshinPlayer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CommandHandler {
|
||||
/* Invoked on player execution. */
|
||||
void execute(GenshinPlayer player, List<String> args);
|
||||
/* Invoked on server execution. */
|
||||
void execute(List<String> args);
|
||||
|
||||
/*
|
||||
* Utilities.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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(GenshinPlayer player, String message) {
|
||||
if(player == null) {
|
||||
Grasscutter.getLogger().info(message);
|
||||
} else player.dropMessage(message);
|
||||
}
|
||||
}
|
||||
87
src/main/java/emu/grasscutter/commands/CommandMap.java
Normal file
87
src/main/java/emu/grasscutter/commands/CommandMap.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package emu.grasscutter.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.game.GenshinPlayer;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
public final class CommandMap {
|
||||
public static CommandMap getInstance() {
|
||||
return Grasscutter.getGameServer().getCommandMap();
|
||||
}
|
||||
|
||||
private final Map<String, CommandHandler> commands = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Register a command handler.
|
||||
* @param label The command label.
|
||||
* @param command The command handler.
|
||||
* @return Instance chaining.
|
||||
*/
|
||||
public CommandMap registerCommand(String label, CommandHandler command) {
|
||||
this.commands.put(label, command); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a registered command handler.
|
||||
* @param label The command label.
|
||||
* @return Instance chaining.
|
||||
*/
|
||||
public CommandMap unregisterCommand(String label) {
|
||||
this.commands.remove(label); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(GenshinPlayer player, String rawMessage) {
|
||||
// Remove prefix if present.
|
||||
if(!Character.isLetter(rawMessage.charAt(0)))
|
||||
rawMessage = rawMessage.substring(1);
|
||||
|
||||
// Parse message.
|
||||
String[] split = rawMessage.split(" ");
|
||||
List<String> args = Arrays.asList(split);
|
||||
String label = args.remove(0);
|
||||
|
||||
// Get command handler.
|
||||
CommandHandler handler = this.commands.get(label);
|
||||
if(handler == null) {
|
||||
CommandHandler.sendMessage(player, "Unknown command: " + label); return;
|
||||
}
|
||||
|
||||
// Invoke execute method for handler.
|
||||
if(player == null)
|
||||
handler.execute(args);
|
||||
else handler.execute(player, args);
|
||||
}
|
||||
|
||||
public CommandMap() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public CommandMap(boolean scan) {
|
||||
if(scan) this.scan();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans for all classes annotated with {@link Command} and registers them.
|
||||
*/
|
||||
private void scan() {
|
||||
Reflections reflector = Grasscutter.reflector;
|
||||
Set<?> classes = reflector.getTypesAnnotatedWith(Command.class);
|
||||
classes.forEach(annotated -> {
|
||||
try {
|
||||
Class<?> cls = annotated.getClass();
|
||||
Command cmdData = cls.getAnnotation(Command.class);
|
||||
Object object = cls.getDeclaredConstructors()[0].newInstance();
|
||||
if (object instanceof CommandHandler)
|
||||
this.registerCommand(cmdData.label(), (CommandHandler) object);
|
||||
} catch (Exception ignored) { }
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
package emu.grasscutter.commands;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GenshinData;
|
||||
import emu.grasscutter.data.def.ItemData;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.GenshinPlayer;
|
||||
import emu.grasscutter.game.inventory.GenshinItem;
|
||||
import emu.grasscutter.utils.Crypto;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
|
||||
public class ServerCommands {
|
||||
private static HashMap<String, ServerCommand> list = new HashMap<>();
|
||||
|
||||
static {
|
||||
try {
|
||||
// Look for classes
|
||||
for (Class<?> cls : ServerCommands.class.getDeclaredClasses()) {
|
||||
// Get non abstract classes
|
||||
if (!Modifier.isAbstract(cls.getModifiers())) {
|
||||
String commandName = cls.getSimpleName().toLowerCase();
|
||||
list.put(commandName, (ServerCommand) cls.newInstance());
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void handle(String msg) {
|
||||
String[] split = msg.split(" ");
|
||||
|
||||
// End if invalid
|
||||
if (split.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
String first = split[0].toLowerCase();
|
||||
ServerCommand c = ServerCommands.list.get(first);
|
||||
|
||||
if (c != null) {
|
||||
// Execute
|
||||
int len = Math.min(first.length() + 1, msg.length());
|
||||
c.execute(msg.substring(len));
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class ServerCommand {
|
||||
public abstract void execute(String raw);
|
||||
}
|
||||
|
||||
// ================ Commands ================
|
||||
|
||||
public static class Reload extends ServerCommand {
|
||||
@Override
|
||||
public void execute(String raw) {
|
||||
Grasscutter.getLogger().info("Reloading config.");
|
||||
Grasscutter.loadConfig();
|
||||
Grasscutter.getDispatchServer().loadQueries();
|
||||
Grasscutter.getLogger().info("Reload complete.");
|
||||
}
|
||||
}
|
||||
|
||||
public static class sendMsg extends ServerCommand {
|
||||
@Override
|
||||
public void execute(String raw) {
|
||||
List<String> split = Arrays.asList(raw.split(" "));
|
||||
|
||||
if (split.size() < 2) {
|
||||
Grasscutter.getLogger().error("Invalid amount of args");
|
||||
return;
|
||||
}
|
||||
|
||||
String playerID = split.get(0);
|
||||
String message = split.stream().skip(1).collect(Collectors.joining(" "));
|
||||
|
||||
|
||||
emu.grasscutter.game.Account account = DatabaseHelper.getAccountByPlayerId(Integer.parseInt(playerID));
|
||||
if (account != null) {
|
||||
GenshinPlayer player = Grasscutter.getGameServer().getPlayerById(Integer.parseInt(playerID));
|
||||
if(player != null) {
|
||||
player.dropMessage(message);
|
||||
Grasscutter.getLogger().info(String.format("Successfully sent message to %s: %s", playerID, message));
|
||||
} else {
|
||||
Grasscutter.getLogger().error("Player not online");
|
||||
}
|
||||
} else {
|
||||
Grasscutter.getLogger().error(String.format("Player %s does not exist", playerID));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Account extends ServerCommand {
|
||||
@Override
|
||||
public void execute(String raw) {
|
||||
String[] split = raw.split(" ");
|
||||
|
||||
if (split.length < 2) {
|
||||
Grasscutter.getLogger().error("Invalid amount of args");
|
||||
return;
|
||||
}
|
||||
|
||||
String command = split[0].toLowerCase();
|
||||
String username = split[1];
|
||||
|
||||
switch (command) {
|
||||
case "create":
|
||||
if (split.length < 2) {
|
||||
Grasscutter.getLogger().error("Invalid amount of args");
|
||||
return;
|
||||
}
|
||||
|
||||
int reservedId = 0;
|
||||
try {
|
||||
reservedId = Integer.parseInt(split[2]);
|
||||
} catch (Exception e) {
|
||||
reservedId = 0;
|
||||
}
|
||||
|
||||
emu.grasscutter.game.Account account = DatabaseHelper.createAccountWithId(username, reservedId);
|
||||
if (account != null) {
|
||||
Grasscutter.getLogger().info("Account created" + (reservedId > 0 ? " with an id of " + reservedId : ""));
|
||||
} else {
|
||||
Grasscutter.getLogger().error("Account already exists");
|
||||
}
|
||||
break;
|
||||
case "delete":
|
||||
boolean success = DatabaseHelper.deleteAccount(username);
|
||||
|
||||
if (success) {
|
||||
Grasscutter.getLogger().info("Account deleted");
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case "setpw":
|
||||
case "setpass":
|
||||
case "setpassword":
|
||||
if (split.length < 3) {
|
||||
Grasscutter.getLogger().error("Invalid amount of args");
|
||||
return;
|
||||
}
|
||||
|
||||
account = DatabaseHelper.getAccountByName(username);
|
||||
|
||||
if (account == null) {
|
||||
Grasscutter.getLogger().error("No account found!");
|
||||
return;
|
||||
}
|
||||
|
||||
token = split[2];
|
||||
token = PasswordHelper.hashPassword(token);
|
||||
|
||||
account.setPassword(token);
|
||||
DatabaseHelper.saveAccount(account);
|
||||
|
||||
Grasscutter.getLogger().info("Password set");
|
||||
break;
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user