From a80302cdcd41da9494bc30546bf5881b3a3457e5 Mon Sep 17 00:00:00 2001
From: AnimeGitB <AnimeGitB@bigblueball.in>
Date: Sat, 2 Jul 2022 18:08:41 +0930
Subject: [PATCH] Fix commands in party chat, re-add optional positional item
 quantity to give command, error out and print usage if excess arguments given
 to give command

---
 .../command/commands/GiveCommand.java         | 44 +++++++++++------
 .../game/managers/chat/ChatManager.java       | 47 +++++++++++--------
 2 files changed, 56 insertions(+), 35 deletions(-)

diff --git a/src/main/java/emu/grasscutter/command/commands/GiveCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveCommand.java
index 70ebd69b..74d36e93 100644
--- a/src/main/java/emu/grasscutter/command/commands/GiveCommand.java
+++ b/src/main/java/emu/grasscutter/command/commands/GiveCommand.java
@@ -114,17 +114,26 @@ public final class GiveCommand implements CommandHandler {
             default:
                 try {
                     param.id = Integer.parseInt(id);
-                    param.data = GameData.getItemDataMap().get(param.id);
-                    if ((param.id > 10_000_000) && (param.id < 12_000_000))
-                        param.avatarData = GameData.getAvatarDataMap().get(param.id);
-                    else if ((param.id > 1000) && (param.id < 1100))
-                        param.avatarData = GameData.getAvatarDataMap().get(param.id - 1000 + 10_000_000);
-                    isRelic = ((param.data != null) && (param.data.getItemType() == ItemType.ITEM_RELIQUARY));
                 } catch (NumberFormatException e) {
                     // TODO: Parse from item name using GM Handbook.
                     CommandHandler.sendTranslatedMessage(sender, "commands.generic.invalid.itemId");
                     throw e;
                 }
+                param.data = GameData.getItemDataMap().get(param.id);
+                if ((param.id > 10_000_000) && (param.id < 12_000_000))
+                    param.avatarData = GameData.getAvatarDataMap().get(param.id);
+                else if ((param.id > 1000) && (param.id < 1100))
+                    param.avatarData = GameData.getAvatarDataMap().get(param.id - 1000 + 10_000_000);
+                isRelic = ((param.data != null) && (param.data.getItemType() == ItemType.ITEM_RELIQUARY));
+
+                if (!isRelic && !args.isEmpty() && (param.amount == 1)) {  // A concession for the people that truly hate [x<amount>].
+                    try {
+                        param.amount = Integer.parseInt(args.remove(0));
+                    } catch (NumberFormatException e) {
+                        CommandHandler.sendTranslatedMessage(sender, "commands.generic.invalid.amount");
+                        throw e;
+                    }
+                }
         }
 
         if (param.amount < 1) param.amount = 1;
@@ -137,19 +146,24 @@ public final class GiveCommand implements CommandHandler {
             param.lvl += 1;
             if (illegalRelicIds.contains(param.id))
                 CommandHandler.sendTranslatedMessage(sender, "commands.give.illegal_relic");
-            } else {
+        } else {
             // Suitable for Avatars and Weapons
             if (param.lvl < 1) param.lvl = 1;
             if (param.lvl > 90) param.lvl = 90;
         }
 
-        if (isRelic && !args.isEmpty()) {
-            try {
-                parseRelicArgs(param, args);
-            } catch (IllegalArgumentException e) {
-                CommandHandler.sendTranslatedMessage(sender, "commands.execution.argument_error");
-                CommandHandler.sendTranslatedMessage(sender, "commands.give.usage_relic");
-                throw e;
+        if (!args.isEmpty()) {
+            if (isRelic) {
+                try {
+                    parseRelicArgs(param, args);
+                } catch (IllegalArgumentException e) {
+                    CommandHandler.sendTranslatedMessage(sender, "commands.execution.argument_error");
+                    CommandHandler.sendTranslatedMessage(sender, "commands.give.usage_relic");
+                    throw e;
+                }
+            } else {
+                CommandHandler.sendTranslatedMessage(sender, "commands.give.usage");
+                throw new IllegalArgumentException();
             }
         }
 
@@ -216,8 +230,8 @@ public final class GiveCommand implements CommandHandler {
             }
         } catch (IllegalArgumentException ignored) {
                 return;
-            }
         }
+    }
 
     private static Avatar makeAvatar(GiveItemParameters param) {
         return makeAvatar(param.avatarData, param.lvl, Avatar.getMinPromoteLevel(param.lvl), 0);
diff --git a/src/main/java/emu/grasscutter/game/managers/chat/ChatManager.java b/src/main/java/emu/grasscutter/game/managers/chat/ChatManager.java
index ba5fa4d0..d63592a8 100644
--- a/src/main/java/emu/grasscutter/game/managers/chat/ChatManager.java
+++ b/src/main/java/emu/grasscutter/game/managers/chat/ChatManager.java
@@ -7,14 +7,15 @@ import emu.grasscutter.server.game.GameServer;
 import emu.grasscutter.server.packet.send.PacketPlayerChatNotify;
 import emu.grasscutter.server.packet.send.PacketPrivateChatNotify;
 
-import java.util.Arrays;
-import java.util.List;
+import java.util.regex.Pattern;
 
 public class ChatManager implements ChatManagerHandler {
-	static final List<Character> PREFIXES = Arrays.asList('/', '!');
-	
+	static final String PREFIXES = "[/!]";
+	static final Pattern RE_PREFIXES = Pattern.compile(PREFIXES);
+	static final Pattern RE_COMMANDS = Pattern.compile("\n" + PREFIXES);
+
 	private final GameServer server;
-	
+
 	public ChatManager(GameServer server) {
 		this.server = server;
 	}
@@ -23,56 +24,62 @@ public class ChatManager implements ChatManagerHandler {
 		return server;
 	}
 
+	private boolean tryInvokeCommand(Player sender, Player target, String rawMessage) {
+		if (!RE_PREFIXES.matcher(rawMessage.substring(0, 1)).matches())
+			return false;
+		for (String line : rawMessage.substring(1).split("\n[/!]"))
+			CommandMap.getInstance().invoke(sender, target, line);
+		return true;
+	}
+
 	public void sendPrivateMessage(Player player, int targetUid, String message) {
 		// Sanity checks
 		if (message == null || message.length() == 0) {
 			return;
 		}
-		
+
 		// Get target
 		Player target = getServer().getPlayerByUid(targetUid);
-				
+
 		// Check if command
-		if (PREFIXES.contains(message.charAt(0))) {
-			CommandMap.getInstance().invoke(player, target, message.substring(1));
+		if (tryInvokeCommand(player, target, message)) {
 			return;
 		}
-		
+
 		if (target == null) {
 			return;
 		}
-		
+
 		// Create chat packet
 		BasePacket packet = new PacketPrivateChatNotify(player.getUid(), target.getUid(), message);
-		
+
 		player.sendPacket(packet);
 		target.sendPacket(packet);
 	}
-	
+
 	public void sendPrivateMessage(Player player, int targetUid, int emote) {
 		// Get target
 		Player target = getServer().getPlayerByUid(targetUid);
-		
+
 		if (target == null) {
 			return;
 		}
-		
+
 		// Create chat packet
 		BasePacket packet = new PacketPrivateChatNotify(player.getUid(), target.getUid(), emote);
-		
+
 		player.sendPacket(packet);
 		target.sendPacket(packet);
 	}
-	
+
 	public void sendTeamMessage(Player player, int channel, String message) {
 		// Sanity checks
 		if (message == null || message.length() == 0) {
 			return;
 		}
-				
+
 		// Check if command
-		if (PREFIXES.contains(message.charAt(0))) {
-			CommandMap.getInstance().invoke(player, null, message);
+		if (tryInvokeCommand(player, null, message)) {
 			return;
 		}
 
-- 
GitLab