CommandMap.java 3.88 KB
Newer Older
KingRainbow44's avatar
KingRainbow44 committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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) {
24
25
26
27
28
29
30
31
32
        Grasscutter.getLogger().debug("Registered command: " + label);
        
        Command annotation = command.getClass().getAnnotation(Command.class);
        if(annotation.aliases().length > 0) {
            for (String alias : annotation.aliases())
                this.commands.put(alias, command);
        } this.commands.put(label, command);
        
        return this;
KingRainbow44's avatar
KingRainbow44 committed
33
34
35
36
37
38
39
40
    }

    /**
     * Removes a registered command handler.
     * @param label The command label.
     * @return Instance chaining.
     */
    public CommandMap unregisterCommand(String label) {
41
42
43
44
45
46
47
48
49
50
51
        Grasscutter.getLogger().debug("Unregistered command: " + label);
        CommandHandler handler = this.commands.get(label);
        if(handler == null) return this;
        
        Command annotation = handler.getClass().getAnnotation(Command.class);
        if(annotation.aliases().length > 0) {
            for (String alias : annotation.aliases())
                this.commands.remove(alias);
        } this.commands.remove(label); 
        
        return this;
KingRainbow44's avatar
KingRainbow44 committed
52
53
54
55
56
57
58
59
    }

    /**
     * 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) {
60
61
62
63
64
        rawMessage = rawMessage.trim();
        if(rawMessage.length() == 0) {
            CommandHandler.sendMessage(player, "No command specified.");
        }
        
KingRainbow44's avatar
KingRainbow44 committed
65
66
67
68
69
70
        // Remove prefix if present.
        if(!Character.isLetter(rawMessage.charAt(0)))
            rawMessage = rawMessage.substring(1);
        
        // Parse message.
        String[] split = rawMessage.split(" ");
71
        List<String> args = new LinkedList<>(Arrays.asList(split));
KingRainbow44's avatar
KingRainbow44 committed
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
        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;
99
        Set<Class<?>> classes = reflector.getTypesAnnotatedWith(Command.class);
KingRainbow44's avatar
KingRainbow44 committed
100
101
        classes.forEach(annotated -> {
            try {
102
103
                Command cmdData = annotated.getAnnotation(Command.class);
                Object object = annotated.newInstance();
KingRainbow44's avatar
KingRainbow44 committed
104
105
                if (object instanceof CommandHandler)
                    this.registerCommand(cmdData.label(), (CommandHandler) object);
106
107
108
109
                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);
            }
KingRainbow44's avatar
KingRainbow44 committed
110
111
112
        });
    }
}