From 3a7d12c7b79d92ca0cd25dbfc4ff70254289cbcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=81=E4=B8=BB?= Date: Wed, 26 Nov 2025 09:05:08 +0800 Subject: [PATCH] Implement !clean command and f affinity --- README.md | 3 +- .../java/emu/nebula/command/CommandArgs.java | 14 ++ .../command/commands/CharacterCommand.java | 7 +- .../nebula/command/commands/CleanCommand.java | 132 ++++++++++++++++++ .../nebula/game/character/GameCharacter.java | 7 +- 5 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 src/main/java/emu/nebula/command/commands/CleanCommand.java diff --git a/README.md b/README.md index f14995e..743339b 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,8 @@ Server commands need to be run in the server console OR in the signature edit me ``` !account {create | delete} [email] (reserved player uid) = Creates or deletes an account. -!char [all | {characterId}] lv(level) a(ascension) s(skill level) t(talent level) = Changes the properties of the targeted characters. +!char [all | {characterId}] lv(level) a(ascension) s(skill level) t(talent level) f(affinity level) = Changes the properties of the targeted characters. +!clean [all | {id} ...] [items|resources] = Removes items/resources from the targeted player. !disc [all | {discId}] lv(level) a(ascension) c(crescendo level) = Changes the properties of the targeted discs. !give [item id] x[amount] = Gives the targeted player an item through the mail. !giveall [characters | discs | materials] = Gives the targeted player items. diff --git a/src/main/java/emu/nebula/command/CommandArgs.java b/src/main/java/emu/nebula/command/CommandArgs.java index 70cf282..aff583e 100644 --- a/src/main/java/emu/nebula/command/CommandArgs.java +++ b/src/main/java/emu/nebula/command/CommandArgs.java @@ -26,6 +26,7 @@ public class CommandArgs { private int advance = -1; private int talent = -1; private int skill = -1; + private int affinity = -1; private Int2IntMap map; private ObjectSet flags; @@ -61,6 +62,9 @@ public class CommandArgs { } else if (arg.startsWith("s")) { // Skill this.skill = Utils.parseSafeInt(arg.substring(1)); it.remove(); + } else if (arg.startsWith("f")) { // Affinity level + this.affinity = Utils.parseSafeInt(arg.substring(1)); + it.remove(); } } else if (arg.startsWith("-")) { // Flag if (this.flags == null) this.flags = new ObjectOpenHashSet<>(); @@ -190,6 +194,16 @@ public class CommandArgs { hasChanged = true; } + + if (this.getAffinity() >= 0) { + int target = this.getAffinity(); + if (target > 50) target = 50; + if (target < 0) target = 0; + if (character.getAffinityLevel() != target) { + character.setAffinityLevel(target); + hasChanged = true; + } + } return hasChanged; } diff --git a/src/main/java/emu/nebula/command/commands/CharacterCommand.java b/src/main/java/emu/nebula/command/commands/CharacterCommand.java index 075502a..b0bf33e 100644 --- a/src/main/java/emu/nebula/command/commands/CharacterCommand.java +++ b/src/main/java/emu/nebula/command/commands/CharacterCommand.java @@ -16,8 +16,8 @@ import emu.nebula.command.CommandHandler; label = "character", aliases = {"c", "char"}, permission = "player.character", - requireTarget = true, - desc = "!c [all | {characterId}] lv(level) a(ascension) s(skill level) t(talent level)" + requireTarget = true, + desc = "!c [all | {characterId}] lv(level) a(ascension) s(skill level) t(talent level) f(affinity level)" ) public class CharacterCommand implements CommandHandler { @@ -51,6 +51,7 @@ public class CharacterCommand implements CommandHandler { // Sanity check if (characters.isEmpty()) { + args.sendMessage("Error: No characters selected"); return; } @@ -72,6 +73,7 @@ public class CharacterCommand implements CommandHandler { } if (modified.isEmpty()) { + args.sendMessage("No changes applied"); return; } @@ -83,5 +85,6 @@ public class CharacterCommand implements CommandHandler { } player.addNextPackage(NetMsgId.chars_final_notify, proto); + args.sendMessage("Updated " + modified.size() + " character(s)"); } } diff --git a/src/main/java/emu/nebula/command/commands/CleanCommand.java b/src/main/java/emu/nebula/command/commands/CleanCommand.java new file mode 100644 index 0000000..3010717 --- /dev/null +++ b/src/main/java/emu/nebula/command/commands/CleanCommand.java @@ -0,0 +1,132 @@ +package emu.nebula.command.commands; + +import emu.nebula.command.Command; +import emu.nebula.command.CommandArgs; +import emu.nebula.command.CommandHandler; +import emu.nebula.data.GameData; +import emu.nebula.data.resources.ItemDef; +import emu.nebula.game.inventory.GameItem; +import emu.nebula.game.inventory.GameResource; +import emu.nebula.game.inventory.ItemParamMap; +import emu.nebula.game.inventory.ItemType; +import emu.nebula.game.player.PlayerChangeInfo; +import emu.nebula.net.NetMsgId; +import emu.nebula.util.Utils; + +import java.util.HashSet; + +@Command( + label = "clean", + aliases = {"cl", "clear"}, + permission = "player.inventory", + requireTarget = true, + desc = "!clean [all | {id} ...] [items|resources]. Removes items/resources from the targeted player." +) +public class CleanCommand implements CommandHandler { + + @Override + public void execute(CommandArgs args) { + var player = args.getTarget(); + var inv = player.getInventory(); + + boolean doItems = true; + boolean doResources = true; + boolean all = false; + + var ids = new HashSet(); + + for (String arg : args.getList()) { + arg = arg.toLowerCase(); + + switch (arg) { + case "items" -> { + doResources = false; + continue; + } + case "resources", "res" -> { + doItems = false; + continue; + } + case "all" -> { + all = true; + continue; + } + } + + int id = Utils.parseSafeInt(arg); + if (id > 0) { + ids.add(id); + } + } + + var change = new PlayerChangeInfo(); + var removeMap = new ItemParamMap(); + + if (all) { + if (doItems) { + for (GameItem item : inv.getItems().values()) { + removeMap.add(item.getItemId(), item.getCount()); + } + } + + if (doResources) { + for (GameResource res : inv.getResources().values()) { + removeMap.add(res.getResourceId(), res.getCount()); + } + } + } else { + for (int id : ids) { + ItemDef data = GameData.getItemDataTable().get(id); + + if (data != null) { + ItemType type = data.getItemType(); + + switch (type) { + case Res -> { + if (doResources) { + int count = inv.getResourceCount(id); + if (count > 0) removeMap.add(id, count); + } + } + case Item -> { + if (doItems) { + int count = inv.getItemCount(id); + if (count > 0) removeMap.add(id, count); + } + } + case Disc, Char, CharacterSkin, Title, Honor -> { + + } + default -> { + if (doItems) { + int count = inv.getItemCount(id); + if (count > 0) { + removeMap.add(id, count); + break; + } + } + if (doResources) { + int count = inv.getResourceCount(id); + if (count > 0) removeMap.add(id, count); + } + } + } + } else { + args.sendMessage("Error: Invalid item id " + id); + } + } + } + + if (!removeMap.isEmpty()) { + change = inv.removeItems(removeMap, change); + } + + if (change.isEmpty()) { + args.sendMessage("No items/resources removed"); + return; + } + + player.addNextPackage(NetMsgId.items_change_notify, change.toProto()); + args.sendMessage("Inventory cleaned"); + } +} diff --git a/src/main/java/emu/nebula/game/character/GameCharacter.java b/src/main/java/emu/nebula/game/character/GameCharacter.java index 66837e8..5f64fea 100644 --- a/src/main/java/emu/nebula/game/character/GameCharacter.java +++ b/src/main/java/emu/nebula/game/character/GameCharacter.java @@ -123,7 +123,12 @@ public class GameCharacter implements GameDatabaseObject { public void setAdvance(int advance) { this.advance = advance; } - + + public void setAffinityLevel(int level) { + this.affinityLevel = Math.max(level, 0); + this.affinityExp = 0; + } + public int getMaxGainableExp() { if (this.getLevel() >= this.getMaxLevel()) { return 0;