From b0d19e54dbaf9e3f3a2d7ce0a6c511fc870c2aa0 Mon Sep 17 00:00:00 2001 From: GanyusLeftHorn <1244229+GanyusLeftHorn@users.noreply.github.com> Date: Mon, 27 Jun 2022 02:43:51 -0700 Subject: [PATCH] Implement selection chests for BP rewards. --- .../java/emu/grasscutter/GameConstants.java | 1 + .../data/excels/BattlePassRewardData.java | 5 +- .../game/battlepass/BattlePassManager.java | 93 +++++++++++++++---- .../send/PacketTakeBattlePassRewardRsp.java | 18 +++- 4 files changed, 97 insertions(+), 20 deletions(-) diff --git a/src/main/java/emu/grasscutter/GameConstants.java b/src/main/java/emu/grasscutter/GameConstants.java index ef723f81c..970240ed5 100644 --- a/src/main/java/emu/grasscutter/GameConstants.java +++ b/src/main/java/emu/grasscutter/GameConstants.java @@ -22,6 +22,7 @@ public final class GameConstants { public static final int BATTLE_PASS_POINT_PER_LEVEL = 1000; public static final int BATTLE_PASS_POINT_PER_WEEK = 10000; public static final int BATTLE_PASS_LEVEL_PRICE = 150; + public static final int BATTLE_PASS_CURRENT_INDEX = 2; // Default entity ability hashes. public static final String[] DEFAULT_ABILITY_STRINGS = { diff --git a/src/main/java/emu/grasscutter/data/excels/BattlePassRewardData.java b/src/main/java/emu/grasscutter/data/excels/BattlePassRewardData.java index 95ca24a80..e9d5608b3 100644 --- a/src/main/java/emu/grasscutter/data/excels/BattlePassRewardData.java +++ b/src/main/java/emu/grasscutter/data/excels/BattlePassRewardData.java @@ -17,11 +17,12 @@ public class BattlePassRewardData extends GameResource { @Override public int getId() { - return this.level; + // Reward ID is a combination of index and level. + // We do this to get a unique ID. + return this.indexId * 100 + this.level; } @Override public void onLoad() { - } } diff --git a/src/main/java/emu/grasscutter/game/battlepass/BattlePassManager.java b/src/main/java/emu/grasscutter/game/battlepass/BattlePassManager.java index 017d3366d..0748f2882 100644 --- a/src/main/java/emu/grasscutter/game/battlepass/BattlePassManager.java +++ b/src/main/java/emu/grasscutter/game/battlepass/BattlePassManager.java @@ -1,11 +1,9 @@ package emu.grasscutter.game.battlepass; import java.time.DayOfWeek; -import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; -import java.time.temporal.TemporalAdjuster; import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.HashMap; @@ -23,23 +21,23 @@ import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; import emu.grasscutter.data.common.ItemParamData; import emu.grasscutter.data.excels.BattlePassRewardData; +import emu.grasscutter.data.excels.ItemData; import emu.grasscutter.data.excels.RewardData; import emu.grasscutter.database.DatabaseHelper; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.inventory.MaterialType; import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.props.BattlePassMissionRefreshType; import emu.grasscutter.game.props.BattlePassMissionStatus; import emu.grasscutter.game.props.WatcherTriggerType; import emu.grasscutter.net.proto.BattlePassCycleOuterClass.BattlePassCycle; -import emu.grasscutter.net.proto.BattlePassProductOuterClass.BattlePassProduct; -import emu.grasscutter.net.proto.BattlePassRewardTagOuterClass.BattlePassRewardTag; import emu.grasscutter.net.proto.BattlePassUnlockStatusOuterClass.BattlePassUnlockStatus; import emu.grasscutter.net.proto.BattlePassRewardTakeOptionOuterClass.BattlePassRewardTakeOption; import emu.grasscutter.net.proto.BattlePassScheduleOuterClass.BattlePassSchedule; import emu.grasscutter.server.packet.send.PacketBattlePassCurScheduleUpdateNotify; import emu.grasscutter.server.packet.send.PacketBattlePassMissionUpdateNotify; import emu.grasscutter.server.packet.send.PacketTakeBattlePassRewardRsp; -import emu.grasscutter.utils.Utils; + import lombok.Getter; @Entity(value = "battlepass", useDiscriminator = false) @@ -190,9 +188,45 @@ public class BattlePassManager { getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(getPlayer())); } } + + private void takeRewardsFromSelectChest(ItemData rewardItemData, int index, ItemParamData entry, List rewardItems) { + // Sanity checks. + if (rewardItemData.getItemUse().size() < 1) { + return; + } + + // Get possible item choices. + String[] choices = rewardItemData.getItemUse().get(0).getUseParam().get(0).split(","); + if (choices.length < index) { + return; + } + + // Get data for the selected item. + // This depends on the type of chest. + int chosenId = Integer.parseInt(choices[index - 1]); + + // For ITEM_USE_ADD_SELECT_ITEM chests, we can directly add the item specified in the chest's data. + if (rewardItemData.getItemUse().get(0).getUseOp().equals("ITEM_USE_ADD_SELECT_ITEM")) { + GameItem rewardItem = new GameItem(GameData.getItemDataMap().get(chosenId), entry.getItemCount()); + rewardItems.add(rewardItem); + } + // For ITEM_USE_GRANT_SELECT_REWARD chests, we have to again look up reward data. + else if (rewardItemData.getItemUse().get(0).getUseOp().equals("ITEM_USE_GRANT_SELECT_REWARD")) { + RewardData selectedReward = GameData.getRewardDataMap().get(chosenId); + + for (var r : selectedReward.getRewardItemList()) { + GameItem rewardItem = new GameItem(GameData.getItemDataMap().get(r.getItemId()), r.getItemCount()); + rewardItems.add(rewardItem); + } + } + else { + Grasscutter.getLogger().error("Invalid chest type for BP reward."); + } + } public void takeReward(List takeOptionList) { - List rewardList = new ArrayList<>(); + List rewardList = new ArrayList<>(); + // List rewardList = new ArrayList<>(); for (BattlePassRewardTakeOption option : takeOptionList) { // Duplicate check @@ -205,38 +239,63 @@ public class BattlePassManager { continue; } - BattlePassRewardData rewardData = GameData.getBattlePassRewardDataMap().get(option.getTag().getLevel()); + BattlePassRewardData rewardData = GameData.getBattlePassRewardDataMap().get(GameConstants.BATTLE_PASS_CURRENT_INDEX * 100 + option.getTag().getLevel()); // Sanity check with excel data if (rewardData.getFreeRewardIdList().contains(option.getTag().getRewardId())) { - rewardList.add(option.getTag()); + rewardList.add(option); } else if (this.isPaid() && rewardData.getPaidRewardIdList().contains(option.getTag().getRewardId())) { - rewardList.add(option.getTag()); + rewardList.add(option); } + else { + Grasscutter.getLogger().info("Not in rewards list: {}", option.getTag().getRewardId()); + } + + // rewardList.add(new Pair<>(option.getTag(), option.getOptionIdx())); } // Get rewards - List rewardItems = null; + List rewardItems = null; if (rewardList.size() > 0) { + rewardItems = new ArrayList<>(); - for (BattlePassRewardTag tag : rewardList) { + for (var option : rewardList) { + var tag = option.getTag(); + int index = option.getOptionIdx(); + + // Make sure we have reward data. RewardData reward = GameData.getRewardDataMap().get(tag.getRewardId()); + if (reward == null) { + continue; + } - if (reward == null) continue; - + // Add reward items. + for (var entry : reward.getRewardItemList()) { + ItemData rewardItemData = GameData.getItemDataMap().get(entry.getItemId()); + + // Some rewards are chests where the user can select the item they want. + if (rewardItemData.getMaterialType() == MaterialType.MATERIAL_SELECTABLE_CHEST) { + this.takeRewardsFromSelectChest(rewardItemData, index, entry, rewardItems); + } + // All other rewards directly give us the right item. + else { + GameItem rewardItem = new GameItem(rewardItemData, entry.getItemCount()); + rewardItems.add(rewardItem); + } + } + + // Construct the reward and set as taken. BattlePassReward bpReward = new BattlePassReward(tag.getLevel(), tag.getRewardId(), tag.getUnlockStatus() == BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_PAID); this.getTakenRewards().put(bpReward.getRewardId(), bpReward); - - rewardItems.addAll(reward.getRewardItemList()); } // Save to db this.save(); // Add items and send battle pass schedule packet - getPlayer().getInventory().addItemParamDatas(rewardItems); + getPlayer().getInventory().addItems(rewardItems); getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(getPlayer())); } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeBattlePassRewardRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeBattlePassRewardRsp.java index a8ac3a466..551c1082f 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTakeBattlePassRewardRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTakeBattlePassRewardRsp.java @@ -1,6 +1,7 @@ package emu.grasscutter.server.packet.send; import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.BattlePassRewardTakeOptionOuterClass.BattlePassRewardTakeOption; @@ -11,7 +12,7 @@ import emu.grasscutter.server.game.GameSession; import java.util.List; public class PacketTakeBattlePassRewardRsp extends BasePacket { - public PacketTakeBattlePassRewardRsp(List takeOptionList, List rewardItems) { + /*public PacketTakeBattlePassRewardRsp(List takeOptionList, List rewardItems) { super(PacketOpcodes.TakeBattlePassRewardRsp); var proto = TakeBattlePassRewardRsp.newBuilder() @@ -23,6 +24,21 @@ public class PacketTakeBattlePassRewardRsp extends BasePacket { } } + setData(proto); + }*/ + + public PacketTakeBattlePassRewardRsp(List takeOptionList, List rewardItems) { + super(PacketOpcodes.TakeBattlePassRewardRsp); + + var proto = TakeBattlePassRewardRsp.newBuilder() + .addAllTakeOptionList(takeOptionList); + + if (rewardItems != null) { + for (var item : rewardItems) { + proto.addItemList(ItemParam.newBuilder().setItemId(item.getItemId()).setCount(item.getCount())); + } + } + setData(proto); } }