From 05555c684efc71d4b2f3a7007b5da7703a69b12b Mon Sep 17 00:00:00 2001 From: Melledy <121644117+Melledy@users.noreply.github.com> Date: Tue, 18 Nov 2025 03:12:10 -0800 Subject: [PATCH] Implement `!disc` command and improve `!giveall` to apply properties --- .../java/emu/nebula/command/CommandArgs.java | 51 ++++++++++-- .../nebula/command/commands/DiscCommand.java | 82 +++++++++++++++++++ .../command/commands/GiveAllCommand.java | 33 +++++--- .../emu/nebula/game/character/GameDisc.java | 12 +++ 4 files changed, 161 insertions(+), 17 deletions(-) create mode 100644 src/main/java/emu/nebula/command/commands/DiscCommand.java diff --git a/src/main/java/emu/nebula/command/CommandArgs.java b/src/main/java/emu/nebula/command/CommandArgs.java index a2a05e9..70cf282 100644 --- a/src/main/java/emu/nebula/command/CommandArgs.java +++ b/src/main/java/emu/nebula/command/CommandArgs.java @@ -4,6 +4,7 @@ import java.util.List; import emu.nebula.Nebula; import emu.nebula.game.character.GameCharacter; +import emu.nebula.game.character.GameDisc; import emu.nebula.game.player.Player; import emu.nebula.util.Utils; import it.unimi.dsi.fastutil.ints.Int2IntMap; @@ -54,7 +55,7 @@ public class CommandArgs { } else if (arg.startsWith("a")) { // Advance this.advance = Utils.parseSafeInt(arg.substring(1)); it.remove(); - } else if (arg.startsWith("t")) { // Talents + } else if (arg.startsWith("t") || arg.startsWith("c")) { // Talents/Crescendo this.talent = Utils.parseSafeInt(arg.substring(1)); it.remove(); } else if (arg.startsWith("s")) { // Skill @@ -136,15 +137,19 @@ public class CommandArgs { boolean hasChanged = false; // Try to set level - if (this.getLevel() > 0 && character.getLevel() != this.getLevel()) { - character.setLevel(Math.min(this.getLevel(), 90)); + int level = Math.min(this.getLevel(), 90); + + if (level > 0 && character.getLevel() != level) { + character.setLevel(level); character.setAdvance(Utils.getMinAdvanceForLevel(character.getLevel())); hasChanged = true; } // Try to set advance (ascension level) - if (this.getAdvance() >= 0 && character.getAdvance() != this.getAdvance()) { - character.setAdvance(Math.min(this.getAdvance(), 8)); + int advance = Math.min(this.getAdvance(), 8); + + if (advance >= 0 && character.getAdvance() != advance) { + character.setAdvance(advance); hasChanged = true; } @@ -188,4 +193,40 @@ public class CommandArgs { return hasChanged; } + + /** + * Changes the properties of an disc based on the arguments provided + * @param disc The targeted disc to change + * @return A boolean of whether or not any changes were made to the disc + */ + public boolean setProperties(GameDisc disc) { + boolean hasChanged = false; + + // Try to set level + int level = Math.min(this.getLevel(), 90); + + if (level > 0 && disc.getLevel() != level) { + disc.setLevel(level); + disc.setPhase(Utils.getMinAdvanceForLevel(disc.getLevel())); + hasChanged = true; + } + + // Try to set advance (ascension level) + int promotion = Math.min(this.getAdvance(), 8); + + if (promotion >= 0 && disc.getPhase() != promotion) { + disc.setPhase(promotion); + hasChanged = true; + } + + // Calculate how many talent stars we want to set + int star = Math.min(this.getTalent(), 5); + + if (star >= 0 && disc.getStar() != star) { + disc.setStar(star); + hasChanged = true; + } + + return hasChanged; + } } diff --git a/src/main/java/emu/nebula/command/commands/DiscCommand.java b/src/main/java/emu/nebula/command/commands/DiscCommand.java new file mode 100644 index 0000000..3866522 --- /dev/null +++ b/src/main/java/emu/nebula/command/commands/DiscCommand.java @@ -0,0 +1,82 @@ +package emu.nebula.command.commands; + +import emu.nebula.util.Utils; +import emu.nebula.game.character.GameDisc; +import emu.nebula.net.NetMsgId; + +import java.util.ArrayList; +import java.util.HashSet; + +import emu.nebula.command.Command; +import emu.nebula.command.CommandArgs; +import emu.nebula.command.CommandHandler; + +@Command( + label = "disc", + aliases = {"d"}, + permission = "player.character", + requireTarget = true, + desc = "!d [all | {discId}] lv(level) a(ascension) c(crescendo level)" +) +public class DiscCommand implements CommandHandler { + + @Override + public void execute(CommandArgs args) { + // Init + var player = args.getTarget(); + var discs = new HashSet(); + + // Parse args + for (String arg : args.getList()) { + // Lowercase + arg = arg.toLowerCase(); + + // Handle all discs + if (arg.equals("all")) { + discs.addAll(player.getCharacters().getDiscCollection()); + continue; + } + + // Parse disc id + int charId = Utils.parseSafeInt(arg); + + var disc = player.getCharacters().getDiscById(charId); + if (disc == null) { + continue; + } + + discs.add(disc); + } + + // Sanity check + if (discs.isEmpty()) { + return; + } + + // List of modified characters that we send to the client for updates + var modified = new ArrayList(); + + // Modify characters + for (var disc : discs) { + // Apply changes + boolean changed = args.setProperties(disc); + + if (changed) { + // Save to database + disc.save(); + + // Add to modified list + modified.add(disc); + } + } + + if (modified.isEmpty()) { + return; + } + + // Encode and send + for (var disc : modified) { + player.addNextPackage(NetMsgId.disc_reset_notify, disc.toProto()); + } + } +} diff --git a/src/main/java/emu/nebula/command/commands/GiveAllCommand.java b/src/main/java/emu/nebula/command/commands/GiveAllCommand.java index 1856d18..9b0221a 100644 --- a/src/main/java/emu/nebula/command/commands/GiveAllCommand.java +++ b/src/main/java/emu/nebula/command/commands/GiveAllCommand.java @@ -19,7 +19,7 @@ import emu.nebula.net.NetMsgId; aliases = {"ga"}, permission = "player.give", requireTarget = true, - desc = "!ga [characters | discs | materials]. Gives the targeted player items." + desc = "!ga [characters | discs | materials] lv(level) t(talent/crescendo level) s(skill level). Gives the targeted player items." ) public class GiveAllCommand implements CommandHandler { private static Set MATERIAL_ITEM_SUBTYPES = Set.of( @@ -35,12 +35,15 @@ public class GiveAllCommand implements CommandHandler { Player target = args.getTarget(); String type = args.get(0).toLowerCase(); - var items = new ItemParamMap(); + var change = new PlayerChangeInfo(); switch (type) { default -> args.sendMessage("Error: Invalid type"); case "m", "materials", "mats" -> { + // Create items map + var items = new ItemParamMap(); + // Check sub type for (ItemDef data : GameData.getItemDataTable()) { if (!MATERIAL_ITEM_SUBTYPES.contains(data.getItemSubType())) { @@ -78,12 +81,15 @@ public class GiveAllCommand implements CommandHandler { continue; } - // Add - items.add(data.getId(), 1); + // Add to player + var disc = target.getCharacters().addDisc(data.getId()); + + // Set properties + args.setProperties(disc); + + // Add to change info + change.add(disc.toProto()); } - - // Add to target's inventory - target.getInventory().addItems(items, change); // Send message args.sendMessage("Giving " + target.getName() + " all discs"); @@ -101,12 +107,15 @@ public class GiveAllCommand implements CommandHandler { continue; } - // Add - items.add(data.getId(), 1); + // Add to player + var character = target.getCharacters().addCharacter(data.getId()); + + // Set properties + args.setProperties(character); + + // Add to change info + change.add(character.toProto()); } - - // Add to target's inventory - target.getInventory().addItems(items, change); // Send message args.sendMessage("Giving " + target.getName() + " all characters"); diff --git a/src/main/java/emu/nebula/game/character/GameDisc.java b/src/main/java/emu/nebula/game/character/GameDisc.java index 82ef840..96fb475 100644 --- a/src/main/java/emu/nebula/game/character/GameDisc.java +++ b/src/main/java/emu/nebula/game/character/GameDisc.java @@ -70,6 +70,18 @@ public class GameDisc implements GameDatabaseObject { } } + public void setLevel(int level) { + this.level = level; + } + + public void setPhase(int phase) { + this.phase = phase; + } + + public void setStar(int star) { + this.star = star; + } + public SubNoteSkillPromoteGroupDef getSubNoteSkillDef() { int id = (this.getData().getSubNoteSkillGroupId() * 100) + this.getPhase(); return GameData.getSubNoteSkillPromoteGroupDataTable().get(id);