From bb84432b4ca24fe3b77e5aa44844b7a1af230e23 Mon Sep 17 00:00:00 2001 From: AnimeGitB <AnimeGitB@bigblueball.in> Date: Sat, 9 Jul 2022 19:56:39 +0930 Subject: [PATCH] Add maximum level/refinement/rank to clear command --- .../command/commands/ClearCommand.java | 159 ++++++++++-------- src/main/resources/languages/en-US.json | 4 +- src/main/resources/languages/es-ES.json | 2 +- src/main/resources/languages/fr-FR.json | 2 +- src/main/resources/languages/pl-PL.json | 2 +- src/main/resources/languages/ro-RO.json | 2 +- src/main/resources/languages/ru-RU.json | 2 +- src/main/resources/languages/zh-CN.json | 2 +- src/main/resources/languages/zh-TW.json | 2 +- 9 files changed, 96 insertions(+), 81 deletions(-) diff --git a/src/main/java/emu/grasscutter/command/commands/ClearCommand.java b/src/main/java/emu/grasscutter/command/commands/ClearCommand.java index d2895745..041c2900 100644 --- a/src/main/java/emu/grasscutter/command/commands/ClearCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ClearCommand.java @@ -1,6 +1,5 @@ package emu.grasscutter.command.commands; -import emu.grasscutter.Grasscutter; import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandHandler; import emu.grasscutter.game.inventory.GameItem; @@ -9,97 +8,113 @@ import emu.grasscutter.game.inventory.ItemType; import emu.grasscutter.game.player.Player; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Stream; -import static emu.grasscutter.utils.Language.translate; - -@Command(label = "clear", usage = "clear <all|wp|art|mat>", //Merged /clearartifacts and /clearweapons to /clear <args> [uid] +@Command(label = "clear", usage = "clear <all|wp|art|mat> [lv<max level>] [r<max refinement>] [<max rarity>*]", description = "commands.clear.description", aliases = {"clear"}, permission = "player.clearinv", permissionTargeted = "player.clearinv.others") public final class ClearCommand implements CommandHandler { + private static Pattern lvlRegex = Pattern.compile("l(?:vl?)?(\\d+)"); // Java doesn't have raw string literals :( + private static Pattern refineRegex = Pattern.compile("r(\\d+)"); + private static Pattern rankRegex = Pattern.compile("(\\d+)\\*"); + + private static int matchIntOrNeg(Pattern pattern, String arg) { + Matcher match = pattern.matcher(arg); + if (match.find()) { + return Integer.parseInt(match.group(1)); // This should be exception-safe as only \d+ can be passed to it (i.e. non-empty string of pure digits) + } + return -1; + } + + private static class ClearItemParameters { + public int lvl = 1; + public int refinement = 1; + public int rank = 4; + }; + + private Stream<GameItem> getOther(ItemType type, Inventory playerInventory, ClearItemParameters param) { + return playerInventory.getItems().values().stream() + .filter(item -> item.getItemType() == type) + .filter(item -> item.getItemData().getRankLevel() <= param.rank) + .filter(item -> !item.isLocked() && !item.isEquipped()); + } + + private Stream<GameItem> getWeapons(Inventory playerInventory, ClearItemParameters param) { + return getOther(ItemType.ITEM_WEAPON, playerInventory, param) + .filter(item -> item.getLevel() <= param.lvl) + .filter(item -> item.getRefinement() < param.refinement); + } + + private Stream<GameItem> getRelics(Inventory playerInventory, ClearItemParameters param) { + return getOther(ItemType.ITEM_RELIQUARY, playerInventory, param) + .filter(item -> item.getLevel() <= param.lvl + 1); + } @Override public void execute(Player sender, Player targetPlayer, List<String> args) { + Inventory playerInventory = targetPlayer.getInventory(); + ClearItemParameters param = new ClearItemParameters(); + + // Extract any tagged arguments (e.g. "lv90", "x100", "r5") + for (int i = args.size() - 1; i >= 0; i--) { // Reverse iteration as we are deleting elements + String arg = args.get(i).toLowerCase(); + boolean deleteArg = false; + int argNum; + // Note that a single argument can actually match all of these, e.g. "lv90r5*" + if ((argNum = matchIntOrNeg(lvlRegex, arg)) != -1) { + param.lvl = argNum; + deleteArg = true; + } + if ((argNum = matchIntOrNeg(refineRegex, arg)) != -1) { + param.refinement = argNum; + deleteArg = true; + } + if ((argNum = matchIntOrNeg(rankRegex, arg)) != -1) { + param.rank = argNum; + deleteArg = true; + } + if (deleteArg) { + args.remove(i); + } + } + if (args.size() < 1) { - CommandHandler.sendMessage(sender, translate(sender, "commands.clear.command_usage")); + CommandHandler.sendTranslatedMessage(sender, "commands.clear.command_usage"); return; } - Inventory playerInventory = targetPlayer.getInventory(); - List<GameItem> toDelete = null; - + + String playerString = targetPlayer.getNickname(); // Should probably be UID instead but whatever switch (args.get(0)) { case "wp" -> { - toDelete = playerInventory.getItems().values().stream() - .filter(item -> item.getItemType() == ItemType.ITEM_WEAPON) - .filter(item -> !item.isLocked() && !item.isEquipped()) - .toList(); - CommandHandler.sendMessage(sender, translate(sender, "commands.clear.weapons", targetPlayer.getNickname())); + playerInventory.removeItems(getWeapons(playerInventory, param).toList()); + CommandHandler.sendTranslatedMessage(sender, "commands.clear.weapons", playerString); } case "art" -> { - toDelete = playerInventory.getItems().values().stream() - .filter(item -> item.getItemType() == ItemType.ITEM_RELIQUARY) - .filter(item -> item.getLevel() == 1 && item.getExp() == 0) - .filter(item -> !item.isLocked() && !item.isEquipped()) - .toList(); - CommandHandler.sendMessage(sender, translate(sender, "commands.clear.artifacts", targetPlayer.getNickname())); + playerInventory.removeItems(getRelics(playerInventory, param).toList()); + CommandHandler.sendTranslatedMessage(sender, "commands.clear.artifacts", playerString); } case "mat" -> { - toDelete = playerInventory.getItems().values().stream() - .filter(item -> item.getItemType() == ItemType.ITEM_MATERIAL) - .filter(item -> item.getLevel() == 1 && item.getExp() == 0) - .filter(item -> !item.isLocked() && !item.isEquipped()) - .toList(); - CommandHandler.sendMessage(sender, translate(sender, "commands.clear.materials", targetPlayer.getNickname())); + playerInventory.removeItems(getOther(ItemType.ITEM_MATERIAL, playerInventory, param).toList()); + CommandHandler.sendTranslatedMessage(sender, "commands.clear.materials", playerString); } case "all" -> { - toDelete = playerInventory.getItems().values().stream() - .filter(item1 -> item1.getItemType() == ItemType.ITEM_RELIQUARY) - .filter(item1 -> item1.getLevel() == 1 && item1.getExp() == 0) - .filter(item1 -> !item1.isLocked() && !item1.isEquipped()) - .toList(); - CommandHandler.sendMessage(sender, translate(sender, "commands.clear.artifacts", targetPlayer.getNickname())); - playerInventory.removeItems(toDelete); - - toDelete = playerInventory.getItems().values().stream() - .filter(item2 -> item2.getItemType() == ItemType.ITEM_MATERIAL) - .filter(item2 -> !item2.isLocked() && !item2.isEquipped()) - .toList(); - playerInventory.removeItems(toDelete); - CommandHandler.sendMessage(sender, translate(sender, "commands.clear.materials", targetPlayer.getNickname())); - - toDelete = playerInventory.getItems().values().stream() - .filter(item3 -> item3.getItemType() == ItemType.ITEM_WEAPON) - .filter(item3 -> item3.getLevel() == 1 && item3.getExp() == 0) - .filter(item3 -> !item3.isLocked() && !item3.isEquipped()) - .toList(); - playerInventory.removeItems(toDelete); - CommandHandler.sendMessage(sender, translate(sender, "commands.clear.weapons", targetPlayer.getNickname())); - - toDelete = playerInventory.getItems().values().stream() - .filter(item4 -> item4.getItemType() == ItemType.ITEM_FURNITURE) - .filter(item4 -> !item4.isLocked() && !item4.isEquipped()) - .toList(); - playerInventory.removeItems(toDelete); - CommandHandler.sendMessage(sender, translate(sender, "commands.clear.furniture", targetPlayer.getNickname())); - - toDelete = playerInventory.getItems().values().stream() - .filter(item5 -> item5.getItemType() == ItemType.ITEM_DISPLAY) - .filter(item5 -> !item5.isLocked() && !item5.isEquipped()) - .toList(); - playerInventory.removeItems(toDelete); - CommandHandler.sendMessage(sender, translate(sender, "commands.clear.displays", targetPlayer.getNickname())); - - toDelete = playerInventory.getItems().values().stream() - .filter(item6 -> item6.getItemType() == ItemType.ITEM_VIRTUAL) - .filter(item6 -> !item6.isLocked() && !item6.isEquipped()) - .toList(); - CommandHandler.sendMessage(sender, translate(sender, "commands.clear.virtuals", targetPlayer.getNickname())); - CommandHandler.sendMessage(sender, translate(sender, "commands.clear.everything", targetPlayer.getNickname())); + playerInventory.removeItems(getRelics(playerInventory, param).toList()); + CommandHandler.sendTranslatedMessage(sender, "commands.clear.artifacts", playerString); + playerInventory.removeItems(getWeapons(playerInventory, param).toList()); + CommandHandler.sendTranslatedMessage(sender, "commands.clear.weapons", playerString); + playerInventory.removeItems(getOther(ItemType.ITEM_MATERIAL, playerInventory, param).toList()); + CommandHandler.sendTranslatedMessage(sender, "commands.clear.materials", playerString); + playerInventory.removeItems(getOther(ItemType.ITEM_FURNITURE, playerInventory, param).toList()); + CommandHandler.sendTranslatedMessage(sender, "commands.clear.furniture", playerString); + playerInventory.removeItems(getOther(ItemType.ITEM_DISPLAY, playerInventory, param).toList()); + CommandHandler.sendTranslatedMessage(sender, "commands.clear.displays", playerString); + playerInventory.removeItems(getOther(ItemType.ITEM_VIRTUAL, playerInventory, param).toList()); + CommandHandler.sendTranslatedMessage(sender, "commands.clear.virtuals", playerString); + CommandHandler.sendTranslatedMessage(sender, "commands.clear.everything", playerString); } } - - if (toDelete != null) { - playerInventory.removeItems(toDelete); - } } } diff --git a/src/main/resources/languages/en-US.json b/src/main/resources/languages/en-US.json index d2629d52..6dc5a0c4 100644 --- a/src/main/resources/languages/en-US.json +++ b/src/main/resources/languages/en-US.json @@ -126,7 +126,7 @@ "description": "Send announcement to all online players, or manage server's announcement" }, "clear": { - "command_usage": "Usage: clear <all|wp|art|mat>", + "command_usage": "Usage: clear <all|wp|art|mat> [lv<max level>] [r<max refinement>] [<max rarity>*]", "weapons": "Cleared weapons for %s.", "artifacts": "Cleared artifacts for %s.", "materials": "Cleared materials for %s.", @@ -134,7 +134,7 @@ "displays": "Cleared displays for %s.", "virtuals": "Cleared virtuals for %s.", "everything": "Cleared everything for %s.", - "description": "Deletes unequipped unlocked items, including yellow rarity ones from your inventory" + "description": "Deletes unequipped unlocked items from your inventory. Defaults to 4* level 1 refinement 1 or lower, but can be set higher." }, "coop": { "usage": "Usage: coop [host UID]", diff --git a/src/main/resources/languages/es-ES.json b/src/main/resources/languages/es-ES.json index c1124078..4e807991 100644 --- a/src/main/resources/languages/es-ES.json +++ b/src/main/resources/languages/es-ES.json @@ -118,7 +118,7 @@ "description": "Modifica las cuentas de usuario" }, "clear": { - "command_usage": "Uso: clear <all|wp|art|mat>", + "command_usage": "Uso: clear <all|wp|art|mat> [lv<max level>] [r<max refinement>] [<max rarity>*]", "weapons": "Eliminadas las armas para %s.", "artifacts": "Eliminados los artefactos para %s.", "materials": "Eliminados los materiales para %s.", diff --git a/src/main/resources/languages/fr-FR.json b/src/main/resources/languages/fr-FR.json index 91391520..75cf5133 100644 --- a/src/main/resources/languages/fr-FR.json +++ b/src/main/resources/languages/fr-FR.json @@ -119,7 +119,7 @@ "description": "Modifie les comptes utilisateurs" }, "clear": { - "command_usage": "Usage: clear <all|wp|art|mat>", + "command_usage": "Usage: clear <all|wp|art|mat> [lv<max level>] [r<max refinement>] [<max rarity>*]", "weapons": "Les armes de %s ont 茅t茅 supprim茅s.", "artifacts": "Les art茅facts de %s ont 茅t茅 supprim茅s.", "materials": "Les mat茅riaux de %s ont 茅t茅 supprim茅s.", diff --git a/src/main/resources/languages/pl-PL.json b/src/main/resources/languages/pl-PL.json index 3a0509ec..edc44465 100644 --- a/src/main/resources/languages/pl-PL.json +++ b/src/main/resources/languages/pl-PL.json @@ -111,7 +111,7 @@ "command_usage": "U偶ycie: account <create|delete> <nazwa> [uid]" }, "clear": { - "command_usage": "U偶ycie: clear <all|wp|art|mat>", + "command_usage": "U偶ycie: clear <all|wp|art|mat> [lv<max level>] [r<max refinement>] [<max rarity>*]", "weapons": "Wyczyszczono bronie dla %s.", "artifacts": "Wyczyszczono artefakty dla %s.", "materials": "Wyczyszczono materia艂y dla %s.", diff --git a/src/main/resources/languages/ro-RO.json b/src/main/resources/languages/ro-RO.json index 6e35cb99..09a34f57 100644 --- a/src/main/resources/languages/ro-RO.json +++ b/src/main/resources/languages/ro-RO.json @@ -118,7 +118,7 @@ "description": "Modifica葲i conturile de utilizator" }, "clear": { - "command_usage": "Utilizare: clear <all|wp|art|mat>", + "command_usage": "Utilizare: clear <all|wp|art|mat> [lv<max level>] [r<max refinement>] [<max rarity>*]", "weapons": "Arme 葯terse pentru %s.", "artifacts": "Artefacte 葯terse pentru %s.", "materials": "Materiale 葯terse pentru %s.", diff --git a/src/main/resources/languages/ru-RU.json b/src/main/resources/languages/ru-RU.json index 6e75e4b4..b1117acc 100644 --- a/src/main/resources/languages/ru-RU.json +++ b/src/main/resources/languages/ru-RU.json @@ -131,7 +131,7 @@ "description": "袠蟹屑械薪褟械褌 褌械泻褍褖褍褞 褋褑械薪褍" }, "clear": { - "command_usage": "袩褉懈屑械薪械薪懈械: clear <all|wp|art|mat>", + "command_usage": "袩褉懈屑械薪械薪懈械: clear <all|wp|art|mat> [lv<max level>] [r<max refinement>] [<max rarity>*]", "weapons": "校写邪谢械薪褘 芯褉褍卸懈褟 褍 %s.", "artifacts": "校写邪谢械薪褘 邪褉褌械褎邪泻褌褘 褍 %s.", "materials": "校写邪谢械薪褘 屑邪褌械褉懈邪谢褘 褍 %s.", diff --git a/src/main/resources/languages/zh-CN.json b/src/main/resources/languages/zh-CN.json index c2a2eee6..9eaf00a9 100644 --- a/src/main/resources/languages/zh-CN.json +++ b/src/main/resources/languages/zh-CN.json @@ -126,7 +126,7 @@ "description": "鍚戞墍鏈夊湪绾跨帺瀹跺彂閫佸叕鍛婏紝鎴栬€呯鐞嗘湇鍔″櫒鐨勫叕鍛�" }, "clear": { - "command_usage": "鐢ㄦ硶锛歝lear <all|wp|art|mat>\nall: 鎵€鏈�, wp: 姝﹀櫒, art: 鍦i仐鐗�, mat: 鏉愭枡", + "command_usage": "鐢ㄦ硶锛歝lear <all|wp|art|mat> [lv<max level>] [r<max refinement>] [<max rarity>*]\nall: 鎵€鏈�, wp: 姝﹀櫒, art: 鍦i仐鐗�, mat: 鏉愭枡", "weapons": "宸叉竻闄� %s 鐨勬鍣ㄣ€�", "artifacts": "宸叉竻闄� %s 鐨勫湥閬楃墿銆�", "materials": "宸叉竻闄� %s 鐨勬潗鏂欍€�", diff --git a/src/main/resources/languages/zh-TW.json b/src/main/resources/languages/zh-TW.json index da4b1e01..1d2dbb57 100644 --- a/src/main/resources/languages/zh-TW.json +++ b/src/main/resources/languages/zh-TW.json @@ -117,7 +117,7 @@ "description": "寤虹珛鎴栧埅闄ゅ赋铏熴€�" }, "clear": { - "command_usage": "鐢ㄦ硶锛� clear <all|wp|art|mat>", + "command_usage": "鐢ㄦ硶锛� clear <all|wp|art|mat> [lv<max level>] [r<max refinement>] [<max rarity>*]", "weapons": "宸插皣 %s 鐨勬鍣ㄦ竻绌恒€�", "artifacts": "宸插皣 %s 鐨勮仏閬虹墿娓呯┖銆�", "materials": "宸插皣 %s 鐨勬潗鏂欐竻绌恒€�", -- GitLab