SendMailCommand.java 10.7 KB
Newer Older
1
2
package emu.grasscutter.command.commands;

3
import emu.grasscutter.Grasscutter;
4
5
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
Benjamin Elsdon's avatar
Benjamin Elsdon committed
6
import emu.grasscutter.database.DatabaseHelper;
Melledy's avatar
Melledy committed
7
8
import emu.grasscutter.game.mail.Mail;
import emu.grasscutter.game.player.Player;
9
10
import emu.grasscutter.server.packet.send.PacketMailChangeNotify;

11
12
import java.time.Instant;
import java.util.ArrayList;
Benjamin Elsdon's avatar
Benjamin Elsdon committed
13
import java.util.HashMap;
14
import java.util.List;
Benjamin Elsdon's avatar
Benjamin Elsdon committed
15
import java.util.Locale;
16

Benjamin Elsdon's avatar
Benjamin Elsdon committed
17
18
@Command(label = "sendmail", usage = "sendmail <userId|all|help> [templateId]",
        description = "Sends mail to the specified user. The usage of this command changes based on it's composition state.", permission = "server.sendmail")
19
20
public class SendMailCommand implements CommandHandler {

Benjamin Elsdon's avatar
Benjamin Elsdon committed
21
22
23
24
25
26
27
28
    // 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 HashMap<Integer, MailBuilder> mailBeingConstructed = new HashMap<Integer, MailBuilder>();

    // Yes this is awful and I hate it.
29
    @Override
30
    public void execute(Player sender, List<String> args) {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
31
32
33
34
35
36
37
38
39
        int senderId;
        if(sender != null) {
            senderId = sender.getUid();
        } else {
            senderId = -1;
        }

        if (!mailBeingConstructed.containsKey(senderId)) {
            switch (args.size()) {
40
                case 1 -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
41
42
                    MailBuilder mailBuilder;
                    switch (args.get(0).toLowerCase()) {
43
                        case "help" -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
44
45
                            CommandHandler.sendMessage(sender, this.getClass().getAnnotation(Command.class).description() + "\nUsage: " + this.getClass().getAnnotation(Command.class).usage());
                            return;
46
47
48
                        }
                        case "all" -> mailBuilder = new MailBuilder(true, new Mail());
                        default -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
49
50
51
52
53
54
55
                            if (DatabaseHelper.getPlayerById(Integer.parseInt(args.get(0))) != null) {
                                mailBuilder = new MailBuilder(Integer.parseInt(args.get(0)), new Mail());
                                break;
                            } else {
                                CommandHandler.sendMessage(sender, "The user with an id of '" + args.get(0) + "' does not exist");
                                return;
                            }
56
                        }
Benjamin Elsdon's avatar
Benjamin Elsdon committed
57
58
59
                    }
                    mailBeingConstructed.put(senderId, mailBuilder);
                    CommandHandler.sendMessage(sender, "Starting composition of message.\nPlease use `/sendmail <title>` to continue.\nYou can use `/sendmail stop` at any time");
60
61
62
                }
                case 2 -> CommandHandler.sendMessage(sender, "Mail templates coming soon implemented...");
                default -> CommandHandler.sendMessage(sender, "Invalid arguments.\nUsage `/sendmail <userId|all|help> [templateId]`");
Benjamin Elsdon's avatar
Benjamin Elsdon committed
63
64
65
66
67
68
            }
        } else {
            MailBuilder mailBuilder = mailBeingConstructed.get(senderId);

            if (args.size() >= 1) {
                switch (args.get(0).toLowerCase()) {
69
                    case "stop" -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
70
71
72
                        mailBeingConstructed.remove(senderId);
                        CommandHandler.sendMessage(sender, "Message sending cancelled");
                        return;
73
74
                    }
                    case "finish" -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
75
                        if (mailBuilder.constructionStage == 3) {
76
                            if (mailBuilder.sendToAll == false) {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
77
78
79
                                Grasscutter.getGameServer().getPlayerByUid(mailBuilder.recipient, true).sendMail(mailBuilder.mail);
                                CommandHandler.sendMessage(sender, "Message sent to user " + mailBuilder.recipient + "!");
                            } else {
80
                                for (Player player : DatabaseHelper.getAllPlayers()) {
81
                                    Grasscutter.getGameServer().getPlayerByUid(player.getUid(), true).sendMail(mailBuilder.mail);
Benjamin Elsdon's avatar
Benjamin Elsdon committed
82
83
84
85
86
87
88
89
                                }
                                CommandHandler.sendMessage(sender, "Message sent to all users!");
                            }
                            mailBeingConstructed.remove(senderId);
                        } else {
                            CommandHandler.sendMessage(sender, "Message composition not at final stage.\nPlease use `/sendmail " + getConstructionArgs(mailBuilder.constructionStage) + "` or `/sendmail stop` to cancel");
                        }
                        return;
90
91
                    }
                    case "help" -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
92
93
                        CommandHandler.sendMessage(sender, "Please use `/sendmail " + getConstructionArgs(mailBuilder.constructionStage) + "`");
                        return;
94
95
                    }
                    default -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
96
                        switch (mailBuilder.constructionStage) {
97
                            case 0 -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
98
99
100
101
                                String title = String.join(" ", args.subList(0, args.size()));
                                mailBuilder.mail.mailContent.title = title;
                                CommandHandler.sendMessage(sender, "Message title set as '" + title + "'.\nUse '/sendmail <content>' to continue.");
                                mailBuilder.constructionStage++;
102
103
                            }
                            case 1 -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
104
105
106
107
                                String contents = String.join(" ", args.subList(0, args.size()));
                                mailBuilder.mail.mailContent.content = contents;
                                CommandHandler.sendMessage(sender, "Message contents set as '" + contents + "'.\nUse '/sendmail <sender>' to continue.");
                                mailBuilder.constructionStage++;
108
109
                            }
                            case 2 -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
110
111
112
113
                                String msgSender = String.join(" ", args.subList(0, args.size()));
                                mailBuilder.mail.mailContent.sender = msgSender;
                                CommandHandler.sendMessage(sender, "Message sender set as '" + msgSender + "'.\nUse '/sendmail <itemId|itemName|finish> [amount] [level]' to continue.");
                                mailBuilder.constructionStage++;
114
115
                            }
                            case 3 -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
116
117
118
                                // Literally just copy-pasted from the give command lol.
                                int item, lvl, amount = 1;
                                switch (args.size()) {
119
                                    default -> { // *No args*
Benjamin Elsdon's avatar
Benjamin Elsdon committed
120
121
                                        CommandHandler.sendMessage(sender, "Usage: give [player] <itemId|itemName> [amount]");
                                        return;
122
123
                                    }
                                    case 1 -> { // <itemId|itemName>
Benjamin Elsdon's avatar
Benjamin Elsdon committed
124
125
126
127
128
129
130
131
                                        try {
                                            item = Integer.parseInt(args.get(0));
                                            lvl = 1;
                                        } catch (NumberFormatException ignored) {
                                            // TODO: Parse from item name using GM Handbook.
                                            CommandHandler.sendMessage(sender, "Invalid item id.");
                                            return;
                                        }
132
133
                                    }
                                    case 2 -> { // <itemId|itemName> [amount]
Benjamin Elsdon's avatar
Benjamin Elsdon committed
134
135
136
                                        lvl = 1;
                                        item = Integer.parseInt(args.get(0));
                                        amount = Integer.parseInt(args.get(1));
137
138
                                    }
                                    case 3 -> { // <itemId|itemName> [amount] [level]
Benjamin Elsdon's avatar
Benjamin Elsdon committed
139
140
141
142
143
144
145
146
147
148
                                        try {
                                            item = Integer.parseInt(args.get(0));
                                            amount = Integer.parseInt(args.get(1));
                                            lvl = Integer.parseInt(args.get(2));

                                        } catch (NumberFormatException ignored) {
                                            // TODO: Parse from item name using GM Handbook.
                                            CommandHandler.sendMessage(sender, "Invalid item or player ID.");
                                            return;
                                        }
149
                                    }
Benjamin Elsdon's avatar
Benjamin Elsdon committed
150
151
152
                                }
                                mailBuilder.mail.itemList.add(new Mail.MailItem(item, amount, lvl));
                                CommandHandler.sendMessage(sender, String.format("Attached %s of %s (level %s) to the message.\nContinue adding more items or use `/sendmail finish` to send the message.", amount, item, lvl));
153
                            }
Benjamin Elsdon's avatar
Benjamin Elsdon committed
154
                        }
155
                    }
Benjamin Elsdon's avatar
Benjamin Elsdon committed
156
157
158
159
160
161
162
                }
            } else {
                CommandHandler.sendMessage(sender, "Invalid arguments \n Please use `/sendmail " + getConstructionArgs(mailBuilder.constructionStage));
            }
        }
    }

163
    private String getConstructionArgs(int stage) {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
164
        switch (stage) {
165
            case 0 -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
166
                return "<title>";
167
168
            }
            case 1 -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
169
                return "<message>";
170
171
            }
            case 2 -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
172
                return "<sender>";
173
174
175

            }
            case 3 -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
176
                return "<itemId|itemName|finish> [amount] [level]";
177
178
            }
            default -> {
Benjamin Elsdon's avatar
Benjamin Elsdon committed
179
180
                Thread.dumpStack();
                return "ERROR: invalid construction stage " + stage + ". Check console for stacktrace.";
181
            }
182
        }
Benjamin Elsdon's avatar
Benjamin Elsdon committed
183
184
185
186
187
188
189
    }

    public static class MailBuilder {
        public int recipient;
        public boolean sendToAll;
        public int constructionStage;
        public Mail mail;
190

Benjamin Elsdon's avatar
Benjamin Elsdon committed
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
        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();
            }
        }
209
210
    }
}