From 49bcb28e300949f2b6c71132f8698aba1a5eef8f Mon Sep 17 00:00:00 2001 From: Melledy <121644117+Melledy@users.noreply.github.com> Date: Wed, 12 Nov 2025 06:10:47 -0800 Subject: [PATCH] Implement honor --- src/main/java/emu/nebula/data/GameData.java | 1 + .../emu/nebula/data/resources/HonorDef.java | 17 +++++ .../emu/nebula/game/inventory/Inventory.java | 62 ++++++++++++++---- .../java/emu/nebula/game/player/Player.java | 64 +++++++++++++++++-- .../handlers/HandlerPlayerHonorEditReq.java | 43 +++++++++++++ 5 files changed, 171 insertions(+), 16 deletions(-) create mode 100644 src/main/java/emu/nebula/data/resources/HonorDef.java create mode 100644 src/main/java/emu/nebula/server/handlers/HandlerPlayerHonorEditReq.java diff --git a/src/main/java/emu/nebula/data/GameData.java b/src/main/java/emu/nebula/data/GameData.java index 05e3d74..a7bb956 100644 --- a/src/main/java/emu/nebula/data/GameData.java +++ b/src/main/java/emu/nebula/data/GameData.java @@ -42,6 +42,7 @@ public class GameData { @Getter private static DataTable ProductionDataTable = new DataTable<>(); @Getter private static DataTable PlayerHeadDataTable = new DataTable<>(); @Getter private static DataTable titleDataTable = new DataTable<>(); + @Getter private static DataTable honorDataTable = new DataTable<>(); // Shops @Getter private static DataTable MallMonthlyCardDataTable = new DataTable<>(); diff --git a/src/main/java/emu/nebula/data/resources/HonorDef.java b/src/main/java/emu/nebula/data/resources/HonorDef.java new file mode 100644 index 0000000..ed84922 --- /dev/null +++ b/src/main/java/emu/nebula/data/resources/HonorDef.java @@ -0,0 +1,17 @@ +package emu.nebula.data.resources; + +import emu.nebula.data.BaseDef; +import emu.nebula.data.ResourceType; +import lombok.Getter; + +@Getter +@ResourceType(name = "Honor.json") +public class HonorDef extends BaseDef { + private int Id; + private int Type; + + @Override + public int getId() { + return Id; + } +} diff --git a/src/main/java/emu/nebula/game/inventory/Inventory.java b/src/main/java/emu/nebula/game/inventory/Inventory.java index cd4f24a..18f7208 100644 --- a/src/main/java/emu/nebula/game/inventory/Inventory.java +++ b/src/main/java/emu/nebula/game/inventory/Inventory.java @@ -11,6 +11,7 @@ import emu.nebula.database.GameDatabaseObject; import emu.nebula.game.player.PlayerManager; import emu.nebula.net.NetMsgId; import emu.nebula.proto.Notify.Skin; +import emu.nebula.proto.Public.Honor; import emu.nebula.proto.Public.Item; import emu.nebula.proto.Public.Res; import emu.nebula.proto.Public.Title; @@ -34,6 +35,7 @@ public class Inventory extends PlayerManager implements GameDatabaseObject { private IntSet extraSkins; private IntSet headIcons; private IntSet titles; + private IntSet honorList; // Items/resources private transient Int2ObjectMap resources; @@ -53,6 +55,7 @@ public class Inventory extends PlayerManager implements GameDatabaseObject { this.extraSkins = new IntOpenHashSet(); this.headIcons = new IntOpenHashSet(); this.titles = new IntOpenHashSet(); + this.honorList = new IntOpenHashSet(); // Add titles directly this.getTitles().add(player.getTitlePrefix()); @@ -122,10 +125,10 @@ public class Inventory extends PlayerManager implements GameDatabaseObject { return true; } - public void addSkin(int id) { + public boolean addSkin(int id) { // Make sure we are not adding duplicates if (this.getExtraSkins().contains(id)) { - return; + return false; } // Add @@ -139,6 +142,9 @@ public class Inventory extends PlayerManager implements GameDatabaseObject { NetMsgId.character_skin_gain_notify, Skin.newInstance().setNew(UI32.newInstance().setValue(id)) ); + + // Success + return true; } public IntCollection getAllHeadIcons() { @@ -185,10 +191,10 @@ public class Inventory extends PlayerManager implements GameDatabaseObject { return true; } - public void addHeadIcon(int id) { + public boolean addHeadIcon(int id) { // Make sure we are not adding duplicates if (this.getHeadIcons().contains(id)) { - return; + return false; } // Add @@ -196,12 +202,15 @@ public class Inventory extends PlayerManager implements GameDatabaseObject { // Save to database Nebula.getGameDatabase().addToList(this, this.getUid(), "headIcons", id); + + // Success + return true; } - public void addTitle(int id) { + public boolean addTitle(int id) { // Make sure we are not adding duplicates if (this.getTitles().contains(id)) { - return; + return false; } // Add @@ -209,6 +218,25 @@ public class Inventory extends PlayerManager implements GameDatabaseObject { // Save to database Nebula.getGameDatabase().addToList(this, this.getUid(), "titles", id); + + // Success + return true; + } + + public boolean addHonor(int id) { + // Make sure we are not adding duplicates + if (this.getHonorList().contains(id)) { + return false; + } + + // Add + this.getHonorList().add(id); + + // Save to database + Nebula.getGameDatabase().addToList(this, this.getUid(), "honorList", id); + + // Success + return true; } // Resources @@ -387,11 +415,8 @@ public class Inventory extends PlayerManager implements GameDatabaseObject { int titleId = data.getTitleData().getId(); - // Make sure we don't already have this title - if (!this.getTitles().contains(titleId)) { - // Add title - this.addTitle(titleId); - + // Add title + if (this.addTitle(titleId)) { // Add to change info var proto = Title.newInstance() .setTitleId(titleId); @@ -399,6 +424,21 @@ public class Inventory extends PlayerManager implements GameDatabaseObject { change.add(proto); } } + case Honor -> { + // Cannot remove honor title + if (amount <= 0) { + break; + } + + // Add honor title + if (this.addHonor(id)) { + // Add to change info + var proto = Honor.newInstance() + .setNewId(id); + + change.add(proto); + } + } default -> { // Not implemented } diff --git a/src/main/java/emu/nebula/game/player/Player.java b/src/main/java/emu/nebula/game/player/Player.java index cce06a0..8d9b658 100644 --- a/src/main/java/emu/nebula/game/player/Player.java +++ b/src/main/java/emu/nebula/game/player/Player.java @@ -33,6 +33,7 @@ import emu.nebula.proto.PlayerData.DictionaryTab; import emu.nebula.proto.PlayerData.PlayerInfo; import emu.nebula.proto.Public.CharShow; import emu.nebula.proto.Public.Energy; +import emu.nebula.proto.Public.HonorInfo; import emu.nebula.proto.Public.NewbieInfo; import emu.nebula.proto.Public.QuestType; import emu.nebula.proto.Public.Story; @@ -61,11 +62,12 @@ public class Player implements GameDatabaseObject { private int skinId; private int titlePrefix; private int titleSuffix; - private int level; - private int exp; + private int[] honor; private int[] showChars; private int[] boards; + private int level; + private int exp; private int energy; private long energyLastUpdate; @@ -128,11 +130,13 @@ public class Player implements GameDatabaseObject { this.skinId = 10301; this.titlePrefix = 1; this.titleSuffix = 2; + this.honor = new int[3]; + this.showChars = new int[3]; + this.boards = new int[] {410301}; + this.level = 1; this.energy = 240; this.energyLastUpdate = this.createTime; - this.showChars = new int[3]; - this.boards = new int[] {410301}; // Setup inventory this.inventory = new Inventory(this); @@ -218,6 +222,8 @@ public class Player implements GameDatabaseObject { return true; } + // TODO check if title is prefix or suffix + // Set this.titlePrefix = prefix; this.titleSuffix = suffix; @@ -278,11 +284,13 @@ public class Player implements GameDatabaseObject { // Verify that we have the correct characters for (int id : charIds) { - if (id != 0 && !this.getCharacters().hasCharacter(id)) { + if (id != 0 && !getCharacters().hasCharacter(id)) { return false; } } + // TODO check duplicates + // Clear this.showChars[0] = 0; this.showChars[1] = 0; @@ -299,6 +307,39 @@ public class Player implements GameDatabaseObject { // Success return true; } + + public boolean setHonor(RepeatedInt honorIds) { + // Sanity check + if (honorIds.length() > this.getHonor().length) { + return false; + } + + // Verify that we have the honor titles + for (int id : honorIds) { + if (id != 0 && !getInventory().getHonorList().contains(id)) { + System.out.println(id); + return false; + } + } + + // TODO check duplicates + + // Clear + this.honor[0] = 0; + this.honor[1] = 0; + this.honor[2] = 0; + + // Set + for (int i = 0; i < honorIds.length(); i++) { + this.honor[i] = honorIds.get(i); + } + + // Update in database + Nebula.getGameDatabase().update(this, this.getUid(), "honor", this.getHonor()); + + // Success + return true; + } public boolean setBoard(RepeatedInt ids) { // Length check @@ -594,6 +635,19 @@ public class Player implements GameDatabaseObject { acc.addChars(info); } + // Set honor + for (int honorId : this.getHonor()) { + var info = HonorInfo.newInstance(); + + if (honorId != 0) { + info.setId(honorId); + } + + proto.addHonors(info); + } + + this.getInventory().getHonorList().forEach(proto::addHonorList); + // Set world class proto.getMutableWorldClass() .setCur(this.getLevel()) diff --git a/src/main/java/emu/nebula/server/handlers/HandlerPlayerHonorEditReq.java b/src/main/java/emu/nebula/server/handlers/HandlerPlayerHonorEditReq.java new file mode 100644 index 0000000..6b264de --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerPlayerHonorEditReq.java @@ -0,0 +1,43 @@ +package emu.nebula.server.handlers; + +import emu.nebula.net.NetHandler; +import emu.nebula.net.NetMsgId; +import emu.nebula.proto.Notify.HonorChangeNotify; +import emu.nebula.proto.PlayerHonorEdit.PlayerHonorEditReq; +import emu.nebula.proto.Public.HonorInfo; +import emu.nebula.proto.Public.Nil; +import emu.nebula.net.HandlerId; +import emu.nebula.net.GameSession; + +@HandlerId(NetMsgId.player_honor_edit_req) +public class HandlerPlayerHonorEditReq extends NetHandler { + + @Override + public byte[] handle(GameSession session, byte[] message) throws Exception { + // Parse req + var req = PlayerHonorEditReq.parseFrom(message); + + // Set + boolean success = session.getPlayer().setHonor(req.getList()); + + if (!success) { + return session.encodeMsg(NetMsgId.player_honor_edit_failed_ack); + } + + // Send notify message + var proto = HonorChangeNotify.newInstance(); + + for (int id : session.getPlayer().getHonor()) { + proto.addHonors(HonorInfo.newInstance().setId(id)); + } + + session.getPlayer().addNextPackage( + NetMsgId.honor_change_notify, + proto + ); + + // Encode and send + return session.encodeMsg(NetMsgId.player_honor_edit_succeed_ack, Nil.newInstance()); + } + +}