From 33babe340554a588f21ee6adc808ce0db99331b2 Mon Sep 17 00:00:00 2001 From: Hiro <84511935+Hiro420@users.noreply.github.com> Date: Sat, 15 Nov 2025 11:29:40 +0200 Subject: [PATCH] fully implement the mail command --- .../nebula/command/commands/MailCommand.java | 142 +++++++++++++++++- 1 file changed, 137 insertions(+), 5 deletions(-) diff --git a/src/main/java/emu/nebula/command/commands/MailCommand.java b/src/main/java/emu/nebula/command/commands/MailCommand.java index 8335df4..45d47f3 100644 --- a/src/main/java/emu/nebula/command/commands/MailCommand.java +++ b/src/main/java/emu/nebula/command/commands/MailCommand.java @@ -1,20 +1,152 @@ package emu.nebula.command.commands; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import emu.nebula.command.Command; import emu.nebula.command.CommandArgs; import emu.nebula.command.CommandHandler; import emu.nebula.game.mail.GameMail; +import emu.nebula.util.Utils; -@Command(label = "mail", aliases = {"m"}, permission = "player.mail", requireTarget = true, desc = "/mail [content]. Sends the targeted player a system mail.") +@Command( + label = "mail", + aliases = {"m"}, + permission = "player.mail", + requireTarget = true, + desc = "/mail \"subject\" \"body\" [itemId xQty | itemId:qty ...]. Sends the targeted player a system mail." +) public class MailCommand implements CommandHandler { + private static final Pattern QUOTED_TEXT = Pattern.compile("\"([^\"]*)\""); + @Override public void execute(CommandArgs args) { - // Setup mail - var mail = new GameMail("System", "Test", "This is a test mail"); + var target = args.getTarget(); + if (target == null) { + args.sendMessage("Error: Targeted player not found or offline"); + return; + } + + String rawInput = args.getRaw() == null ? "" : args.getRaw().trim(); + if (rawInput.isEmpty()) { + sendUsage(args); + return; + } + + Matcher matcher = QUOTED_TEXT.matcher(rawInput); + if (!matcher.find()) { + sendUsage(args); + return; + } + + String subject = matcher.group(1).trim(); + if (!matcher.find()) { + args.sendMessage("Mail body must be wrapped in quotes after the subject."); + return; + } + + String body = matcher.group(1).trim(); + int attachmentStartIndex = matcher.end(); + + if (subject.isEmpty()) { + args.sendMessage("Mail subject cannot be empty."); + return; + } + + if (body.isEmpty()) { + body = " "; // just for safety, so the client won't complain + } + + String author = args.getSender() != null ? args.getSender().getName() : "System"; + var mail = new GameMail(author, subject, body); + + String attachmentSection = rawInput.length() > attachmentStartIndex + ? rawInput.substring(attachmentStartIndex).trim() + : ""; + + parseAttachments(attachmentSection, mail, args); - // Add mail - args.getTarget().getMailbox().sendMail(mail); + target.getMailbox().sendMail(mail); + args.sendMessage("Mail sent to " + target.getName() + " with subject \"" + subject + "\"."); } + private void parseAttachments(String attachmentSection, GameMail mail, CommandArgs args) { + if (attachmentSection == null || attachmentSection.isBlank()) { + return; + } + + Integer pendingItemId = null; + for (String token : attachmentSection.split("\\s+")) { + if (token.isBlank()) { + continue; + } + + if (token.contains(":") || token.contains(",")) { + String[] split = token.split("[:,]", 2); + int itemId = Utils.parseSafeInt(split[0]); + int qty = split.length > 1 ? Utils.parseSafeInt(split[1]) : 1; + addAttachment(mail, args, itemId, qty); + pendingItemId = null; + continue; + } + + if (token.startsWith("x") && token.length() > 1) { + if (pendingItemId == null) { + args.sendMessage("Quantity token '" + token + "' must follow an item id."); + continue; + } + + int qty = Utils.parseSafeInt(token.substring(1)); + addAttachment(mail, args, pendingItemId, qty); + pendingItemId = null; + continue; + } + + if (isIntegerToken(token)) { + if (pendingItemId != null) { + addAttachment(mail, args, pendingItemId, 1); + } + + int itemId = Utils.parseSafeInt(token); + if (itemId <= 0) { + args.sendMessage("Invalid item id '" + token + "'."); + pendingItemId = null; + continue; + } + + pendingItemId = itemId; + continue; + } + + args.sendMessage("Ignoring attachment token '" + token + "'."); + } + + if (pendingItemId != null) { + addAttachment(mail, args, pendingItemId, 1); + } + } + + private void addAttachment(GameMail mail, CommandArgs args, int itemId, int quantity) { + if (itemId <= 0) { + args.sendMessage("Item id must be positive."); + return; + } + + int qty = Math.max(quantity, 1); + mail.addAttachment(itemId, qty); + } + + private boolean isIntegerToken(String token) { + for (int i = 0; i < token.length(); i++) { + if (!Character.isDigit(token.charAt(i))) { + return false; + } + } + return !token.isEmpty(); + } + + private void sendUsage(CommandArgs args) { + args.sendMessage("Usage: /mail \"subject\" \"body\" [itemId xQty | itemId:qty ...]"); + } }