mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-30 18:42:12 +00:00
Send Mail Command!
Almost done! Wooooo!
This commit is contained in:
parent
254a779bf7
commit
ae190f3fa0
@ -3,30 +3,202 @@ package emu.grasscutter.command.commands;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.GenshinPlayer;
|
||||
import emu.grasscutter.game.Mail;
|
||||
import emu.grasscutter.server.packet.send.PacketMailChangeNotify;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
@Command(label = "sendmail", usage = "sendmail")
|
||||
@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")
|
||||
public 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 HashMap<Integer, MailBuilder> mailBeingConstructed = new HashMap<Integer, MailBuilder>();
|
||||
|
||||
// Yes this is awful and I hate it.
|
||||
@Override
|
||||
public void execute(GenshinPlayer sender, List<String> args) {
|
||||
// This is literally so I can receive mail for some reason.
|
||||
if(sender == null) {
|
||||
// This is my uuid in my test server. This is just for testing.
|
||||
// If someone pulled this please put your uuid to receive mail using /sendmail
|
||||
// until I actually make a proper /sendmail command.
|
||||
sender = Grasscutter.getGameServer().getPlayerByUid(7006);
|
||||
int senderId;
|
||||
if(sender != null) {
|
||||
senderId = sender.getUid();
|
||||
} else {
|
||||
senderId = -1;
|
||||
}
|
||||
sender.sendMail(new Mail(new Mail.MailContent("Test", "This is a test"),
|
||||
new ArrayList<Mail.MailItem>(){{add(new Mail.MailItem(23411 ));}},
|
||||
Instant.now().getEpochSecond() + 4000));
|
||||
|
||||
sender.dropMessage("Check your inbox");
|
||||
if (!mailBeingConstructed.containsKey(senderId)) {
|
||||
switch (args.size()) {
|
||||
case 1:
|
||||
MailBuilder mailBuilder;
|
||||
switch (args.get(0).toLowerCase()) {
|
||||
case "help":
|
||||
CommandHandler.sendMessage(sender, this.getClass().getAnnotation(Command.class).description() + "\nUsage: " + this.getClass().getAnnotation(Command.class).usage());
|
||||
return;
|
||||
case "all":
|
||||
mailBuilder = new MailBuilder(true, new Mail());
|
||||
break;
|
||||
default:
|
||||
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;
|
||||
}
|
||||
}
|
||||
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");
|
||||
break;
|
||||
case 2:
|
||||
CommandHandler.sendMessage(sender, "Mail templates coming soon implemented...");
|
||||
return;
|
||||
default:
|
||||
CommandHandler.sendMessage(sender, "Invalid arguments.\nUsage `/sendmail <userId|all|help> [templateId]`");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
MailBuilder mailBuilder = mailBeingConstructed.get(senderId);
|
||||
|
||||
if (args.size() >= 1) {
|
||||
switch (args.get(0).toLowerCase()) {
|
||||
case "stop":
|
||||
mailBeingConstructed.remove(senderId);
|
||||
CommandHandler.sendMessage(sender, "Message sending cancelled");
|
||||
return;
|
||||
case "finish":
|
||||
if (mailBuilder.constructionStage == 3) {
|
||||
if(mailBuilder.sendToAll == false) {
|
||||
Grasscutter.getGameServer().getPlayerByUid(mailBuilder.recipient, true).sendMail(mailBuilder.mail);
|
||||
CommandHandler.sendMessage(sender, "Message sent to user " + mailBuilder.recipient + "!");
|
||||
} else {
|
||||
// TODO: More testing required. This probably won't work for online players if DatabaseHelper.getPlayerById(string) didn't work.
|
||||
for (GenshinPlayer player : DatabaseHelper.getAllPlayers()) {
|
||||
player.sendMail(mailBuilder.mail);
|
||||
}
|
||||
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;
|
||||
case "help":
|
||||
CommandHandler.sendMessage(sender, "Please use `/sendmail " + getConstructionArgs(mailBuilder.constructionStage) + "`");
|
||||
return;
|
||||
default:
|
||||
switch (mailBuilder.constructionStage) {
|
||||
case 0:
|
||||
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++;
|
||||
break;
|
||||
case 1:
|
||||
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++;
|
||||
break;
|
||||
case 2:
|
||||
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++;
|
||||
break;
|
||||
case 3:
|
||||
// Literally just copy-pasted from the give command lol.
|
||||
int item, lvl, amount = 1;
|
||||
switch (args.size()) {
|
||||
default: // *No args*
|
||||
CommandHandler.sendMessage(sender, "Usage: give [player] <itemId|itemName> [amount]");
|
||||
return;
|
||||
case 1: // <itemId|itemName>
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case 2: // <itemId|itemName> [amount]
|
||||
lvl = 1;
|
||||
item = Integer.parseInt(args.get(0));
|
||||
amount = Integer.parseInt(args.get(1));
|
||||
break;
|
||||
case 3: // <itemId|itemName> [amount] [level]
|
||||
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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
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));
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
CommandHandler.sendMessage(sender, "Invalid arguments \n Please use `/sendmail " + getConstructionArgs(mailBuilder.constructionStage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getConstructionArgs(int stage) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
return "<title>";
|
||||
case 1:
|
||||
return "<message>";
|
||||
case 2:
|
||||
return "<sender>";
|
||||
case 3:
|
||||
return "<itemId|itemName|finish> [amount] [level]";
|
||||
default:
|
||||
Thread.dumpStack();
|
||||
return "ERROR: invalid construction stage " + stage + ". Check console for stacktrace.";
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,6 +90,10 @@ public final class DatabaseHelper {
|
||||
return DatabaseManager.getDatastore().find(Account.class).filter(Filters.eq("username", username)).delete().getDeletedCount() > 0;
|
||||
}
|
||||
|
||||
public static List<GenshinPlayer> getAllPlayers() {
|
||||
return DatabaseManager.getDatastore().find(GenshinPlayer.class).stream().toList();
|
||||
}
|
||||
|
||||
public static GenshinPlayer getPlayerById(int id) {
|
||||
return DatabaseManager.getDatastore().find(GenshinPlayer.class).filter(Filters.eq("_id", id)).first();
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import java.util.*;
|
||||
import dev.morphia.annotations.*;
|
||||
import emu.grasscutter.GenshinConstants;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GenshinData;
|
||||
import emu.grasscutter.data.def.PlayerLevelData;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
@ -603,10 +604,13 @@ public class GenshinPlayer {
|
||||
public List<Mail> getAllMail() { return this.mail; }
|
||||
|
||||
public void sendMail(Mail message) {
|
||||
this.mail.add(message);
|
||||
message._id = this.mail.size() + 1;
|
||||
this.mail.add(message);
|
||||
this.save();
|
||||
Grasscutter.getLogger().info("Message sent to user [" + this.getUid() + ":" + this.getNickname() + "]!");
|
||||
if(this.getSession() != null) {
|
||||
this.sendPacket(new PacketMailChangeNotify(this, message));
|
||||
} // TODO: setup a way for the mail notification to show up when someone receives mail when they were offline
|
||||
}
|
||||
|
||||
public boolean deleteMail(int mailId) {
|
||||
|
@ -20,15 +20,7 @@ public class Mail {
|
||||
public int stateValue;
|
||||
|
||||
public Mail() {
|
||||
_id = 1;
|
||||
mailContent = new MailContent("No title set...", "No content set...");
|
||||
itemList = new ArrayList<>();
|
||||
sendTime = 0;
|
||||
expireTime = 0;
|
||||
importance = 0; // Starred mail, 0 = No star, 1 = Star.
|
||||
isRead = true;
|
||||
isAttachmentGot = true;
|
||||
stateValue = 1; // Different mailboxes, 1 = Default, 3 = Gift-box.
|
||||
this(new MailContent(), new ArrayList<MailItem>(), (int) Instant.now().getEpochSecond() + 604800); // TODO: add expire time to send mail command
|
||||
}
|
||||
|
||||
public Mail(MailContent mailContent, List<MailItem> itemList, long expireTime) {
|
||||
@ -49,10 +41,10 @@ public class Mail {
|
||||
this.itemList = itemList;
|
||||
this.sendTime = (int) Instant.now().getEpochSecond();
|
||||
this.expireTime = expireTime;
|
||||
this.importance = importance;
|
||||
this.importance = importance; // Starred mail, 0 = No star, 1 = Star.
|
||||
this.isRead = false;
|
||||
this.isAttachmentGot = false;
|
||||
this.stateValue = state;
|
||||
this.stateValue = state; // Different mailboxes, 1 = Default, 3 = Gift-box.
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
|
@ -13,7 +13,6 @@ public class HandlerGetMailItemReq extends PacketHandler {
|
||||
|
||||
@Override
|
||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||
Grasscutter.getLogger().info("Mail Item Req");
|
||||
GetMailItemReqOuterClass.GetMailItemReq req = GetMailItemReqOuterClass.GetMailItemReq.parseFrom(payload);
|
||||
session.send(new PacketGetMailItemRsp(session.getPlayer(), req.getMailIdListList()));
|
||||
}
|
||||
|
@ -39,9 +39,13 @@ public class PacketGetAllMailRsp extends GenshinPacket {
|
||||
List<MailData> mailDataList = new ArrayList<MailData>();
|
||||
|
||||
for (Mail message : player.getAllMail()) {
|
||||
|
||||
if(message.stateValue == 1) { // Make sure it isn't a gift
|
||||
if (message.expireTime < Instant.now().getEpochSecond()) { // Make sure the message isn't expired (The game won't show expired mail, but I don't want to send unnecessary information).
|
||||
Grasscutter.getLogger().info("a");
|
||||
if (message.expireTime > (int) Instant.now().getEpochSecond()) { // Make sure the message isn't expired (The game won't show expired mail, but I don't want to send unnecessary information).
|
||||
Grasscutter.getLogger().info("b");
|
||||
if(mailDataList.size() <= 1000) { // Make sure that there isn't over 1000 messages in the mailbox. (idk what will happen if there is but the game probably won't like it.)
|
||||
Grasscutter.getLogger().info("c");
|
||||
MailTextContent.Builder mailTextContent = MailTextContent.newBuilder();
|
||||
mailTextContent.setTitle(message.mailContent.title);
|
||||
mailTextContent.setContent(message.mailContent.content);
|
||||
|
Loading…
Reference in New Issue
Block a user