Commit bb84432b authored by AnimeGitB's avatar AnimeGitB Committed by Luke H-W
Browse files

Add maximum level/refinement/rank to clear command

parent fbf80e71
package emu.grasscutter.command.commands; package emu.grasscutter.command.commands;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.command.Command; import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler; import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.GameItem;
...@@ -9,97 +8,113 @@ import emu.grasscutter.game.inventory.ItemType; ...@@ -9,97 +8,113 @@ import emu.grasscutter.game.inventory.ItemType;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import java.util.List; 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> [lv<max level>] [r<max refinement>] [<max rarity>*]",
@Command(label = "clear", usage = "clear <all|wp|art|mat>", //Merged /clearartifacts and /clearweapons to /clear <args> [uid]
description = "commands.clear.description", description = "commands.clear.description",
aliases = {"clear"}, permission = "player.clearinv", permissionTargeted = "player.clearinv.others") aliases = {"clear"}, permission = "player.clearinv", permissionTargeted = "player.clearinv.others")
public final class ClearCommand implements CommandHandler { 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 @Override
public void execute(Player sender, Player targetPlayer, List<String> args) { 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) { if (args.size() < 1) {
CommandHandler.sendMessage(sender, translate(sender, "commands.clear.command_usage")); CommandHandler.sendTranslatedMessage(sender, "commands.clear.command_usage");
return; return;
} }
Inventory playerInventory = targetPlayer.getInventory();
List<GameItem> toDelete = null; String playerString = targetPlayer.getNickname(); // Should probably be UID instead but whatever
switch (args.get(0)) { switch (args.get(0)) {
case "wp" -> { case "wp" -> {
toDelete = playerInventory.getItems().values().stream() playerInventory.removeItems(getWeapons(playerInventory, param).toList());
.filter(item -> item.getItemType() == ItemType.ITEM_WEAPON) CommandHandler.sendTranslatedMessage(sender, "commands.clear.weapons", playerString);
.filter(item -> !item.isLocked() && !item.isEquipped())
.toList();
CommandHandler.sendMessage(sender, translate(sender, "commands.clear.weapons", targetPlayer.getNickname()));
} }
case "art" -> { case "art" -> {
toDelete = playerInventory.getItems().values().stream() playerInventory.removeItems(getRelics(playerInventory, param).toList());
.filter(item -> item.getItemType() == ItemType.ITEM_RELIQUARY) CommandHandler.sendTranslatedMessage(sender, "commands.clear.artifacts", playerString);
.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()));
} }
case "mat" -> { case "mat" -> {
toDelete = playerInventory.getItems().values().stream() playerInventory.removeItems(getOther(ItemType.ITEM_MATERIAL, playerInventory, param).toList());
.filter(item -> item.getItemType() == ItemType.ITEM_MATERIAL) CommandHandler.sendTranslatedMessage(sender, "commands.clear.materials", playerString);
.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()));
} }
case "all" -> { case "all" -> {
toDelete = playerInventory.getItems().values().stream() playerInventory.removeItems(getRelics(playerInventory, param).toList());
.filter(item1 -> item1.getItemType() == ItemType.ITEM_RELIQUARY) CommandHandler.sendTranslatedMessage(sender, "commands.clear.artifacts", playerString);
.filter(item1 -> item1.getLevel() == 1 && item1.getExp() == 0) playerInventory.removeItems(getWeapons(playerInventory, param).toList());
.filter(item1 -> !item1.isLocked() && !item1.isEquipped()) CommandHandler.sendTranslatedMessage(sender, "commands.clear.weapons", playerString);
.toList(); playerInventory.removeItems(getOther(ItemType.ITEM_MATERIAL, playerInventory, param).toList());
CommandHandler.sendMessage(sender, translate(sender, "commands.clear.artifacts", targetPlayer.getNickname())); CommandHandler.sendTranslatedMessage(sender, "commands.clear.materials", playerString);
playerInventory.removeItems(toDelete); playerInventory.removeItems(getOther(ItemType.ITEM_FURNITURE, playerInventory, param).toList());
CommandHandler.sendTranslatedMessage(sender, "commands.clear.furniture", playerString);
toDelete = playerInventory.getItems().values().stream() playerInventory.removeItems(getOther(ItemType.ITEM_DISPLAY, playerInventory, param).toList());
.filter(item2 -> item2.getItemType() == ItemType.ITEM_MATERIAL) CommandHandler.sendTranslatedMessage(sender, "commands.clear.displays", playerString);
.filter(item2 -> !item2.isLocked() && !item2.isEquipped()) playerInventory.removeItems(getOther(ItemType.ITEM_VIRTUAL, playerInventory, param).toList());
.toList(); CommandHandler.sendTranslatedMessage(sender, "commands.clear.virtuals", playerString);
playerInventory.removeItems(toDelete); CommandHandler.sendTranslatedMessage(sender, "commands.clear.everything", playerString);
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()));
} }
} }
if (toDelete != null) {
playerInventory.removeItems(toDelete);
}
} }
} }
...@@ -126,7 +126,7 @@ ...@@ -126,7 +126,7 @@
"description": "Send announcement to all online players, or manage server's announcement" "description": "Send announcement to all online players, or manage server's announcement"
}, },
"clear": { "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.", "weapons": "Cleared weapons for %s.",
"artifacts": "Cleared artifacts for %s.", "artifacts": "Cleared artifacts for %s.",
"materials": "Cleared materials for %s.", "materials": "Cleared materials for %s.",
...@@ -134,7 +134,7 @@ ...@@ -134,7 +134,7 @@
"displays": "Cleared displays for %s.", "displays": "Cleared displays for %s.",
"virtuals": "Cleared virtuals for %s.", "virtuals": "Cleared virtuals for %s.",
"everything": "Cleared everything 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": { "coop": {
"usage": "Usage: coop [host UID]", "usage": "Usage: coop [host UID]",
......
...@@ -118,7 +118,7 @@ ...@@ -118,7 +118,7 @@
"description": "Modifica las cuentas de usuario" "description": "Modifica las cuentas de usuario"
}, },
"clear": { "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.", "weapons": "Eliminadas las armas para %s.",
"artifacts": "Eliminados los artefactos para %s.", "artifacts": "Eliminados los artefactos para %s.",
"materials": "Eliminados los materiales para %s.", "materials": "Eliminados los materiales para %s.",
......
...@@ -119,7 +119,7 @@ ...@@ -119,7 +119,7 @@
"description": "Modifie les comptes utilisateurs" "description": "Modifie les comptes utilisateurs"
}, },
"clear": { "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.", "weapons": "Les armes de %s ont été supprimés.",
"artifacts": "Les artéfacts 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.", "materials": "Les matériaux de %s ont été supprimés.",
......
...@@ -111,7 +111,7 @@ ...@@ -111,7 +111,7 @@
"command_usage": "Użycie: account <create|delete> <nazwa> [uid]" "command_usage": "Użycie: account <create|delete> <nazwa> [uid]"
}, },
"clear": { "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.", "weapons": "Wyczyszczono bronie dla %s.",
"artifacts": "Wyczyszczono artefakty dla %s.", "artifacts": "Wyczyszczono artefakty dla %s.",
"materials": "Wyczyszczono materiały dla %s.", "materials": "Wyczyszczono materiały dla %s.",
......
...@@ -118,7 +118,7 @@ ...@@ -118,7 +118,7 @@
"description": "Modificați conturile de utilizator" "description": "Modificați conturile de utilizator"
}, },
"clear": { "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.", "weapons": "Arme șterse pentru %s.",
"artifacts": "Artefacte șterse pentru %s.", "artifacts": "Artefacte șterse pentru %s.",
"materials": "Materiale șterse pentru %s.", "materials": "Materiale șterse pentru %s.",
......
...@@ -131,7 +131,7 @@ ...@@ -131,7 +131,7 @@
"description": "Изменяет текущую сцену" "description": "Изменяет текущую сцену"
}, },
"clear": { "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.", "weapons": "Удалены оружия у %s.",
"artifacts": "Удалены артефакты у %s.", "artifacts": "Удалены артефакты у %s.",
"materials": "Удалены материалы у %s.", "materials": "Удалены материалы у %s.",
......
...@@ -126,7 +126,7 @@ ...@@ -126,7 +126,7 @@
"description": "向所有在线玩家发送公告,或者管理服务器的公告" "description": "向所有在线玩家发送公告,或者管理服务器的公告"
}, },
"clear": { "clear": {
"command_usage": "用法:clear <all|wp|art|mat>\nall: 所有, wp: 武器, art: 圣遗物, mat: 材料", "command_usage": "用法:clear <all|wp|art|mat> [lv<max level>] [r<max refinement>] [<max rarity>*]\nall: 所有, wp: 武器, art: 圣遗物, mat: 材料",
"weapons": "已清除 %s 的武器。", "weapons": "已清除 %s 的武器。",
"artifacts": "已清除 %s 的圣遗物。", "artifacts": "已清除 %s 的圣遗物。",
"materials": "已清除 %s 的材料。", "materials": "已清除 %s 的材料。",
......
...@@ -117,7 +117,7 @@ ...@@ -117,7 +117,7 @@
"description": "建立或刪除帳號。" "description": "建立或刪除帳號。"
}, },
"clear": { "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 的武器清空。", "weapons": "已將 %s 的武器清空。",
"artifacts": "已將 %s 的聖遺物清空。", "artifacts": "已將 %s 的聖遺物清空。",
"materials": "已將 %s 的材料清空。", "materials": "已將 %s 的材料清空。",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment