From 968880c320ff2f9bffc31d8d3478ee8405d965b6 Mon Sep 17 00:00:00 2001 From: Melledy <121644117+Melledy@users.noreply.github.com> Date: Fri, 12 Dec 2025 02:06:11 -0800 Subject: [PATCH] Show errors properly if emblem creation/reroll fails --- .../nebula/game/character/GameCharacter.java | 21 +++++++----- .../nebula/server/error/ServerException.java | 33 +++++++++++++++++++ .../handlers/HandlerCharGemGenerateReq.java | 10 ++++-- .../handlers/HandlerCharGemRefreshReq.java | 10 ++++-- 4 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 src/main/java/emu/nebula/server/error/ServerException.java diff --git a/src/main/java/emu/nebula/game/character/GameCharacter.java b/src/main/java/emu/nebula/game/character/GameCharacter.java index 089e967..fba8385 100644 --- a/src/main/java/emu/nebula/game/character/GameCharacter.java +++ b/src/main/java/emu/nebula/game/character/GameCharacter.java @@ -33,6 +33,7 @@ import emu.nebula.proto.Public.CharGemSlot; import emu.nebula.proto.Public.UI32; import emu.nebula.proto.PublicStarTower.StarTowerChar; import emu.nebula.proto.PublicStarTower.StarTowerCharGem; +import emu.nebula.server.error.ServerException; import emu.nebula.util.Bitset; import emu.nebula.util.CustomIntArray; import it.unimi.dsi.fastutil.ints.IntArrayList; @@ -660,16 +661,16 @@ public class GameCharacter implements GameDatabaseObject { return true; } - public synchronized PlayerChangeInfo generateGem(int slotId) { + public synchronized PlayerChangeInfo generateGem(int slotId) throws ServerException { // Get gem slot var slot = this.getGemSlot(slotId); if (slot == null) { - return null; + throw new ServerException(110105, "Emblem slot doesn't exist"); } // Skip if slot is full if (slot.isFull()) { - return null; + throw new ServerException(110105, "Emblem slots are full"); } // Get gem data @@ -678,12 +679,12 @@ public class GameCharacter implements GameDatabaseObject { // Check character level if (this.getLevel() < gemControl.getUnlockLevel()) { - return null; + throw new ServerException(110105, "Trekker needs to be at least level " + gemControl.getUnlockLevel()); } // Make sure the player has the materials to craft the emblem if (!getPlayer().getInventory().hasItem(gemData.getGenerateCostTid(), gemControl.getGeneratenCostQty())) { - return null; + throw new ServerException(119903); } // Generate attributes and create gem @@ -707,10 +708,12 @@ public class GameCharacter implements GameDatabaseObject { } @SuppressWarnings("deprecation") - public synchronized PlayerChangeInfo refreshGem(int slotId, int gemIndex, RepeatedInt lockedAttributes) { + public synchronized PlayerChangeInfo refreshGem(int slotId, int gemIndex, RepeatedInt lockedAttributes) throws ServerException { // Get gem from slot var gem = this.getGemFromSlot(slotId, gemIndex); - if (gem == null) return null; + if (gem == null) { + throw new ServerException(111609); + } // Get gem data var gemData = this.getData().getCharGemData(slotId); @@ -718,12 +721,12 @@ public class GameCharacter implements GameDatabaseObject { // Check character level if (this.getLevel() < gemControl.getUnlockLevel()) { - return null; + throw new ServerException(110105, "Trekker needs to be at least level " + gemControl.getUnlockLevel()); } // Get locked attributes if (lockedAttributes.length() > gemControl.getLockableNum()) { - return null; + throw new ServerException(110105, "You can only lock up to " + gemControl.getLockableNum() + " attributes"); } // Calculate the materials we need diff --git a/src/main/java/emu/nebula/server/error/ServerException.java b/src/main/java/emu/nebula/server/error/ServerException.java new file mode 100644 index 0000000..e52e0a1 --- /dev/null +++ b/src/main/java/emu/nebula/server/error/ServerException.java @@ -0,0 +1,33 @@ +package emu.nebula.server.error; + +import lombok.Getter; +import emu.nebula.proto.Public.Error; + +@Getter +public class ServerException extends Exception { + private static final long serialVersionUID = -8953641375717705518L; + private int code; + private String[] args; + + public ServerException(int code) { + this.code = code; + } + + public ServerException(int code, String... args) { + this.code = code; + this.args = args; + } + + // Proto + + public Error toProto() { + var proto = Error.newInstance() + .setCode(code); + + if (this.args != null) { + proto.addAllArguments(args); + } + + return proto; + } +} diff --git a/src/main/java/emu/nebula/server/handlers/HandlerCharGemGenerateReq.java b/src/main/java/emu/nebula/server/handlers/HandlerCharGemGenerateReq.java index 3f9bfcf..ca4a438 100644 --- a/src/main/java/emu/nebula/server/handlers/HandlerCharGemGenerateReq.java +++ b/src/main/java/emu/nebula/server/handlers/HandlerCharGemGenerateReq.java @@ -4,8 +4,10 @@ import emu.nebula.net.NetHandler; import emu.nebula.net.NetMsgId; import emu.nebula.proto.CharGemGenerate.CharGemGenerateReq; import emu.nebula.proto.CharGemGenerate.CharGemGenerateResp; +import emu.nebula.server.error.ServerException; import emu.nebula.net.HandlerId; import emu.nebula.game.character.CharacterGem; +import emu.nebula.game.player.PlayerChangeInfo; import emu.nebula.net.GameSession; @HandlerId(NetMsgId.char_gem_generate_req) @@ -23,10 +25,12 @@ public class HandlerCharGemGenerateReq extends NetHandler { } // Generate gem - var change = character.generateGem(req.getSlotId()); + PlayerChangeInfo change = null; - if (change == null) { - return session.encodeMsg(NetMsgId.char_gem_generate_failed_ack); + try { + change = character.generateGem(req.getSlotId()); + } catch (ServerException e) { + return session.encodeMsg(NetMsgId.char_gem_generate_failed_ack, e.toProto()); } var gem = (CharacterGem) change.getExtraData(); diff --git a/src/main/java/emu/nebula/server/handlers/HandlerCharGemRefreshReq.java b/src/main/java/emu/nebula/server/handlers/HandlerCharGemRefreshReq.java index 55af244..d7c879e 100644 --- a/src/main/java/emu/nebula/server/handlers/HandlerCharGemRefreshReq.java +++ b/src/main/java/emu/nebula/server/handlers/HandlerCharGemRefreshReq.java @@ -4,8 +4,10 @@ import emu.nebula.net.NetHandler; import emu.nebula.net.NetMsgId; import emu.nebula.proto.CharGemRefresh.CharGemRefreshReq; import emu.nebula.proto.CharGemRefresh.CharGemRefreshResp; +import emu.nebula.server.error.ServerException; import emu.nebula.net.HandlerId; import emu.nebula.game.character.CharacterGem; +import emu.nebula.game.player.PlayerChangeInfo; import emu.nebula.net.GameSession; @HandlerId(NetMsgId.char_gem_refresh_req) @@ -24,10 +26,12 @@ public class HandlerCharGemRefreshReq extends NetHandler { } // Refresh gem attributes - var change = character.refreshGem(req.getSlotId(), req.getGemIndex(), req.getLockAttrs()); + PlayerChangeInfo change = null; - if (change == null) { - return session.encodeMsg(NetMsgId.char_gem_refresh_failed_ack); + try { + change = character.refreshGem(req.getSlotId(), req.getGemIndex(), req.getLockAttrs()); + } catch (ServerException e) { + return session.encodeMsg(NetMsgId.char_gem_refresh_failed_ack, e.toProto()); } var gem = (CharacterGem) change.getExtraData();