diff --git a/src/main/java/emu/nebula/game/character/CharacterStorage.java b/src/main/java/emu/nebula/game/character/CharacterStorage.java index 973cef6..4c62776 100644 --- a/src/main/java/emu/nebula/game/character/CharacterStorage.java +++ b/src/main/java/emu/nebula/game/character/CharacterStorage.java @@ -18,6 +18,7 @@ import emu.nebula.game.player.PlayerChangeInfo; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.ints.IntArrayList; import lombok.Getter; import lombok.Setter; @@ -185,6 +186,39 @@ public class CharacterStorage extends PlayerManager { } } + public PlayerChangeInfo claimAllPotentialBookRewards() { + var rewards = new ItemParamMap(); + var received = new IntArrayList(); + + // Collect rewards for every owned character + for (var character : this.getCharacterCollection()) { + var characterReceived = new IntArrayList(); + var characterRewards = character.collectPotentialBookRewards(characterReceived); + + if (characterRewards.isEmpty()) { + continue; + } + + rewards.add(characterRewards); + received.addAll(characterReceived); + + // Save to db + character.save(); + } + + // Sanity check + if (rewards.isEmpty()) { + return null; + } + + // Add all rewards at once so the change info only contains one entry per item + var change = this.getPlayer().getInventory().addItems(rewards); + change.setExtraData(received); + + // Success + return change.setSuccess(true); + } + // Discs public GameDisc getDiscById(int id) { diff --git a/src/main/java/emu/nebula/game/character/GameCharacter.java b/src/main/java/emu/nebula/game/character/GameCharacter.java index bcf49e6..13f3789 100644 --- a/src/main/java/emu/nebula/game/character/GameCharacter.java +++ b/src/main/java/emu/nebula/game/character/GameCharacter.java @@ -42,6 +42,7 @@ import emu.nebula.util.ints.CustomIntArray; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import lombok.Getter; @@ -1003,9 +1004,13 @@ public class GameCharacter implements GameDatabaseObject { return this.receivedPotentialRewards; } - public PlayerChangeInfo claimPotentialBookRewards() { + /** + * Marks this character's claimable potential book rewards as received. + * @param receivedIds List to add the claimed reward ids to + * @return The claimed rewards + */ + protected ItemParamMap collectPotentialBookRewards(IntList receivedIds) { var rewards = new ItemParamMap(); - var received = new IntArrayList(); int potentials = this.getTotalSeenPotentials(); for (var reward : this.getData().getPotentialBookRewards().values()) { @@ -1015,16 +1020,27 @@ public class GameCharacter implements GameDatabaseObject { } // Check if we meet criteria for claiming the reward - if (potentials >= reward.getRequiredPotentials()) { - // Mark as received - this.getReceivedPotentialRewards().add(reward.getId()); - - // Add to lists - received.add(reward.getId()); - rewards.add(reward.getItemId(), reward.getItemQty()); + if (potentials < reward.getRequiredPotentials()) { + continue; } + + // Mark as received + this.getReceivedPotentialRewards().add(reward.getId()); + + // Add to rewards + rewards.add(reward.getItemId(), reward.getItemQty()); + + // Mark as received + receivedIds.add(reward.getId()); } + return rewards; + } + + public PlayerChangeInfo claimPotentialBookRewards() { + var received = new IntArrayList(); + var rewards = this.collectPotentialBookRewards(received); + if (rewards.isEmpty()) { return null; } diff --git a/src/main/java/emu/nebula/server/handlers/HandlerStarTowerBookPotentialRewardReceiveReq.java b/src/main/java/emu/nebula/server/handlers/HandlerStarTowerBookPotentialRewardReceiveReq.java index b7c6e51..4fd2085 100644 --- a/src/main/java/emu/nebula/server/handlers/HandlerStarTowerBookPotentialRewardReceiveReq.java +++ b/src/main/java/emu/nebula/server/handlers/HandlerStarTowerBookPotentialRewardReceiveReq.java @@ -1,5 +1,6 @@ package emu.nebula.server.handlers; +import emu.nebula.game.player.PlayerChangeInfo; import emu.nebula.net.NetHandler; import emu.nebula.net.NetMsgId; import emu.nebula.proto.Public.UI32; @@ -13,17 +14,27 @@ public class HandlerStarTowerBookPotentialRewardReceiveReq extends NetHandler { @Override public byte[] handle(GameSession session, byte[] message) throws Exception { - // Parse character id + // Parse character id, 0 means claim for all characters var req = UI32.parseFrom(message); - var character = session.getPlayer().getCharacters().getCharacterById(req.getValue()); + int charId = req.getValue(); - if (character == null) { - return session.encodeMsg(NetMsgId.star_tower_book_potential_reward_receive_failed_ack); + PlayerChangeInfo change; + + if (charId > 0) { + // Get character + var character = session.getPlayer().getCharacters().getCharacterById(charId); + + if (character == null) { + return session.encodeMsg(NetMsgId.star_tower_book_potential_reward_receive_failed_ack); + } + + // Claim rewards + change = character.claimPotentialBookRewards(); + } else { + // Claim rewards for all characters + change = session.getPlayer().getCharacters().claimAllPotentialBookRewards(); } - // Claim rewards - var change = character.claimPotentialBookRewards(); - if (change == null) { return session.encodeMsg(NetMsgId.star_tower_book_potential_reward_receive_failed_ack); }