2022-06-21 22:18:13 +08:00
|
|
|
package emu.grasscutter.game.battlepass;
|
|
|
|
|
2022-06-27 00:54:17 -07:00
|
|
|
import java.time.DayOfWeek;
|
|
|
|
import java.time.LocalDate;
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
import java.time.ZoneId;
|
|
|
|
import java.time.temporal.TemporalAdjusters;
|
2022-06-24 01:12:52 -07:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
|
2022-06-21 07:59:10 -07:00
|
|
|
import org.bson.types.ObjectId;
|
|
|
|
|
|
|
|
import dev.morphia.annotations.Entity;
|
|
|
|
import dev.morphia.annotations.Id;
|
|
|
|
import dev.morphia.annotations.Indexed;
|
2022-06-24 01:12:52 -07:00
|
|
|
import emu.grasscutter.GameConstants;
|
2022-06-26 17:57:34 -07:00
|
|
|
import emu.grasscutter.Grasscutter;
|
2022-06-24 01:12:52 -07:00
|
|
|
import emu.grasscutter.data.GameData;
|
|
|
|
import emu.grasscutter.data.common.ItemParamData;
|
|
|
|
import emu.grasscutter.data.excels.BattlePassRewardData;
|
2022-06-27 02:43:51 -07:00
|
|
|
import emu.grasscutter.data.excels.ItemData;
|
2022-06-24 01:12:52 -07:00
|
|
|
import emu.grasscutter.data.excels.RewardData;
|
2022-06-21 07:59:10 -07:00
|
|
|
import emu.grasscutter.database.DatabaseHelper;
|
2022-06-27 02:43:51 -07:00
|
|
|
import emu.grasscutter.game.inventory.GameItem;
|
|
|
|
import emu.grasscutter.game.inventory.MaterialType;
|
2022-07-18 20:42:22 -07:00
|
|
|
import emu.grasscutter.game.player.BasePlayerDataManager;
|
2022-06-21 22:18:13 +08:00
|
|
|
import emu.grasscutter.game.player.Player;
|
2022-06-24 07:34:24 -07:00
|
|
|
import emu.grasscutter.game.props.BattlePassMissionRefreshType;
|
2022-06-24 01:12:52 -07:00
|
|
|
import emu.grasscutter.game.props.BattlePassMissionStatus;
|
|
|
|
import emu.grasscutter.game.props.WatcherTriggerType;
|
|
|
|
import emu.grasscutter.net.proto.BattlePassCycleOuterClass.BattlePassCycle;
|
|
|
|
import emu.grasscutter.net.proto.BattlePassUnlockStatusOuterClass.BattlePassUnlockStatus;
|
|
|
|
import emu.grasscutter.net.proto.BattlePassRewardTakeOptionOuterClass.BattlePassRewardTakeOption;
|
|
|
|
import emu.grasscutter.net.proto.BattlePassScheduleOuterClass.BattlePassSchedule;
|
2022-06-21 22:18:13 +08:00
|
|
|
import emu.grasscutter.server.packet.send.PacketBattlePassCurScheduleUpdateNotify;
|
2022-06-24 01:12:52 -07:00
|
|
|
import emu.grasscutter.server.packet.send.PacketBattlePassMissionUpdateNotify;
|
|
|
|
import emu.grasscutter.server.packet.send.PacketTakeBattlePassRewardRsp;
|
2022-06-27 02:43:51 -07:00
|
|
|
|
2022-06-25 02:04:29 +09:30
|
|
|
import lombok.Getter;
|
2022-06-21 22:18:13 +08:00
|
|
|
|
2022-06-21 07:59:10 -07:00
|
|
|
@Entity(value = "battlepass", useDiscriminator = false)
|
2022-07-18 20:42:22 -07:00
|
|
|
public class BattlePassManager extends BasePlayerDataManager {
|
2022-06-25 02:04:29 +09:30
|
|
|
@Id @Getter private ObjectId id;
|
2022-06-21 07:59:10 -07:00
|
|
|
|
|
|
|
@Indexed private int ownerUid;
|
2022-06-25 02:04:29 +09:30
|
|
|
@Getter private int point;
|
|
|
|
@Getter private int cyclePoints; // Weekly maximum cap
|
|
|
|
@Getter private int level;
|
2022-06-24 01:12:52 -07:00
|
|
|
|
2022-06-25 02:04:29 +09:30
|
|
|
@Getter private boolean viewed;
|
2022-06-26 17:57:34 -07:00
|
|
|
private boolean paid;
|
2022-06-24 01:12:52 -07:00
|
|
|
|
|
|
|
private Map<Integer, BattlePassMission> missions;
|
|
|
|
private Map<Integer, BattlePassReward> takenRewards;
|
2022-06-21 07:59:10 -07:00
|
|
|
|
|
|
|
@Deprecated // Morphia only
|
|
|
|
public BattlePassManager() {}
|
2022-06-21 22:18:13 +08:00
|
|
|
|
2022-06-21 07:59:10 -07:00
|
|
|
public BattlePassManager(Player player) {
|
2022-07-18 20:42:22 -07:00
|
|
|
super(player);
|
2022-06-21 07:59:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setPlayer(Player player) {
|
|
|
|
this.player = player;
|
|
|
|
this.ownerUid = player.getUid();
|
|
|
|
}
|
|
|
|
|
2022-06-24 01:12:52 -07:00
|
|
|
public void updateViewed() {
|
|
|
|
this.viewed = true;
|
2022-06-21 22:18:13 +08:00
|
|
|
}
|
|
|
|
|
2022-06-25 02:04:29 +09:30
|
|
|
public boolean setLevel(int level) {
|
|
|
|
if (level >= 0 && level <= GameConstants.BATTLE_PASS_MAX_LEVEL) {
|
|
|
|
this.level = level;
|
|
|
|
this.point = 0;
|
|
|
|
this.player.sendPacket(new PacketBattlePassCurScheduleUpdateNotify(this.player));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2022-06-24 01:12:52 -07:00
|
|
|
}
|
|
|
|
|
2022-06-25 02:04:29 +09:30
|
|
|
public void addPoints(int points){
|
|
|
|
this.addPointsDirectly(points, false);
|
2022-06-24 01:12:52 -07:00
|
|
|
|
2022-06-25 02:04:29 +09:30
|
|
|
this.player.sendPacket(new PacketBattlePassCurScheduleUpdateNotify(player));
|
2022-06-21 07:59:10 -07:00
|
|
|
this.save();
|
2022-06-21 22:18:13 +08:00
|
|
|
}
|
|
|
|
|
2022-06-25 02:04:29 +09:30
|
|
|
public void addPointsDirectly(int points, boolean isWeekly) {
|
|
|
|
int amount = points;
|
2022-06-24 07:34:24 -07:00
|
|
|
|
|
|
|
if (isWeekly) {
|
|
|
|
amount = Math.min(amount, GameConstants.BATTLE_PASS_POINT_PER_WEEK - this.cyclePoints);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (amount <= 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.point += amount;
|
|
|
|
this.cyclePoints += amount;
|
2022-06-24 01:12:52 -07:00
|
|
|
|
|
|
|
if (this.point >= GameConstants.BATTLE_PASS_POINT_PER_LEVEL && this.getLevel() < GameConstants.BATTLE_PASS_MAX_LEVEL) {
|
2022-06-25 02:04:29 +09:30
|
|
|
int levelups = Math.floorDiv(this.point, GameConstants.BATTLE_PASS_POINT_PER_LEVEL);
|
2022-06-24 01:12:52 -07:00
|
|
|
|
|
|
|
// Make sure player cant go above max BP level
|
|
|
|
levelups = Math.min(levelups, GameConstants.BATTLE_PASS_MAX_LEVEL - levelups);
|
|
|
|
|
|
|
|
// Set new points after level up
|
|
|
|
this.point = this.point - (levelups * GameConstants.BATTLE_PASS_POINT_PER_LEVEL);
|
|
|
|
this.level += levelups;
|
|
|
|
}
|
2022-06-21 22:18:13 +08:00
|
|
|
}
|
2022-06-21 07:59:10 -07:00
|
|
|
|
2022-06-24 01:12:52 -07:00
|
|
|
public Map<Integer, BattlePassMission> getMissions() {
|
|
|
|
if (this.missions == null) this.missions = new HashMap<>();
|
|
|
|
return this.missions;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Will return a new empty mission if the mission id is not found
|
|
|
|
public BattlePassMission loadMissionById(int id) {
|
|
|
|
return getMissions().computeIfAbsent(id, i -> new BattlePassMission(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean hasMission(int id) {
|
|
|
|
return getMissions().containsKey(id);
|
|
|
|
}
|
|
|
|
|
2022-06-26 17:57:34 -07:00
|
|
|
public boolean isPaid() {
|
|
|
|
// ToDo: Change this when we actually support unlocking "paid" BP.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-06-24 01:12:52 -07:00
|
|
|
public Map<Integer, BattlePassReward> getTakenRewards() {
|
|
|
|
if (this.takenRewards == null) this.takenRewards = new HashMap<>();
|
|
|
|
return this.takenRewards;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mission triggers
|
|
|
|
public void triggerMission(WatcherTriggerType triggerType) {
|
|
|
|
getPlayer().getServer().getBattlePassMissionManager().triggerMission(getPlayer(), triggerType);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void triggerMission(WatcherTriggerType triggerType, int param, int progress) {
|
|
|
|
getPlayer().getServer().getBattlePassMissionManager().triggerMission(getPlayer(), triggerType, param, progress);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handlers
|
|
|
|
public void takeMissionPoint(List<Integer> missionIdList) {
|
|
|
|
// Obvious exploit check
|
|
|
|
if (missionIdList.size() > GameData.getBattlePassMissionDataMap().size()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
List<BattlePassMission> updatedMissions = new ArrayList<>(missionIdList.size());
|
|
|
|
|
|
|
|
for (int id : missionIdList) {
|
|
|
|
// Skip if we dont have this mission
|
|
|
|
if (!this.hasMission(id)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
BattlePassMission mission = this.loadMissionById(id);
|
|
|
|
|
|
|
|
if (mission.getData() == null) {
|
|
|
|
this.getMissions().remove(mission.getId());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Take reward
|
|
|
|
if (mission.getStatus() == BattlePassMissionStatus.MISSION_STATUS_FINISHED) {
|
2022-06-24 07:43:43 -07:00
|
|
|
this.addPointsDirectly(mission.getData().getAddPoint(), mission.getData().isCycleRefresh());
|
2022-06-24 01:12:52 -07:00
|
|
|
mission.setStatus(BattlePassMissionStatus.MISSION_STATUS_POINT_TAKEN);
|
|
|
|
|
|
|
|
updatedMissions.add(mission);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (updatedMissions.size() > 0) {
|
|
|
|
// Save to db
|
|
|
|
this.save();
|
|
|
|
|
|
|
|
// Packet
|
|
|
|
getPlayer().sendPacket(new PacketBattlePassMissionUpdateNotify(updatedMissions));
|
|
|
|
getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(getPlayer()));
|
|
|
|
}
|
|
|
|
}
|
2022-06-27 02:43:51 -07:00
|
|
|
|
|
|
|
private void takeRewardsFromSelectChest(ItemData rewardItemData, int index, ItemParamData entry, List<GameItem> 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.");
|
|
|
|
}
|
|
|
|
}
|
2022-06-24 01:12:52 -07:00
|
|
|
|
|
|
|
public void takeReward(List<BattlePassRewardTakeOption> takeOptionList) {
|
2022-06-27 02:43:51 -07:00
|
|
|
List<BattlePassRewardTakeOption> rewardList = new ArrayList<>();
|
2022-06-24 01:12:52 -07:00
|
|
|
|
|
|
|
for (BattlePassRewardTakeOption option : takeOptionList) {
|
|
|
|
// Duplicate check
|
|
|
|
if (option.getTag().getRewardId() == 0 || getTakenRewards().containsKey(option.getTag().getRewardId())) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Level check
|
|
|
|
if (option.getTag().getLevel() > this.getLevel()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-06-27 02:43:51 -07:00
|
|
|
BattlePassRewardData rewardData = GameData.getBattlePassRewardDataMap().get(GameConstants.BATTLE_PASS_CURRENT_INDEX * 100 + option.getTag().getLevel());
|
2022-06-24 01:12:52 -07:00
|
|
|
|
|
|
|
// Sanity check with excel data
|
|
|
|
if (rewardData.getFreeRewardIdList().contains(option.getTag().getRewardId())) {
|
2022-06-27 02:43:51 -07:00
|
|
|
rewardList.add(option);
|
2022-06-24 01:12:52 -07:00
|
|
|
} else if (this.isPaid() && rewardData.getPaidRewardIdList().contains(option.getTag().getRewardId())) {
|
2022-06-27 02:43:51 -07:00
|
|
|
rewardList.add(option);
|
2022-06-24 01:12:52 -07:00
|
|
|
}
|
2022-06-27 02:43:51 -07:00
|
|
|
else {
|
|
|
|
Grasscutter.getLogger().info("Not in rewards list: {}", option.getTag().getRewardId());
|
|
|
|
}
|
2022-06-24 01:12:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get rewards
|
2022-06-27 02:43:51 -07:00
|
|
|
List<GameItem> rewardItems = null;
|
2022-06-24 01:12:52 -07:00
|
|
|
|
|
|
|
if (rewardList.size() > 0) {
|
2022-06-27 02:43:51 -07:00
|
|
|
|
2022-06-24 01:12:52 -07:00
|
|
|
rewardItems = new ArrayList<>();
|
|
|
|
|
2022-06-27 02:43:51 -07:00
|
|
|
for (var option : rewardList) {
|
|
|
|
var tag = option.getTag();
|
|
|
|
int index = option.getOptionIdx();
|
|
|
|
|
|
|
|
// Make sure we have reward data.
|
2022-06-24 01:12:52 -07:00
|
|
|
RewardData reward = GameData.getRewardDataMap().get(tag.getRewardId());
|
2022-06-27 02:43:51 -07:00
|
|
|
if (reward == null) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-06-24 01:12:52 -07:00
|
|
|
|
2022-06-27 02:43:51 -07:00
|
|
|
// 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.
|
2022-06-24 01:12:52 -07:00
|
|
|
BattlePassReward bpReward = new BattlePassReward(tag.getLevel(), tag.getRewardId(), tag.getUnlockStatus() == BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_PAID);
|
|
|
|
this.getTakenRewards().put(bpReward.getRewardId(), bpReward);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save to db
|
|
|
|
this.save();
|
|
|
|
|
|
|
|
// Add items and send battle pass schedule packet
|
2022-06-27 02:43:51 -07:00
|
|
|
getPlayer().getInventory().addItems(rewardItems);
|
2022-06-24 01:12:52 -07:00
|
|
|
getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(getPlayer()));
|
|
|
|
}
|
|
|
|
|
|
|
|
getPlayer().sendPacket(new PacketTakeBattlePassRewardRsp(takeOptionList, rewardItems));
|
|
|
|
}
|
|
|
|
|
|
|
|
public int buyLevels(int buyLevel) {
|
|
|
|
int boughtLevels = Math.min(buyLevel, GameConstants.BATTLE_PASS_MAX_LEVEL - buyLevel);
|
|
|
|
|
|
|
|
if (boughtLevels > 0) {
|
|
|
|
int price = GameConstants.BATTLE_PASS_LEVEL_PRICE * boughtLevels;
|
|
|
|
|
|
|
|
if (getPlayer().getPrimogems() < price) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.level += boughtLevels;
|
|
|
|
this.save();
|
|
|
|
|
|
|
|
getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(getPlayer()));
|
|
|
|
}
|
|
|
|
|
|
|
|
return boughtLevels;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void resetDailyMissions() {
|
2022-06-27 00:54:17 -07:00
|
|
|
var resetMissions = new ArrayList<BattlePassMission>();
|
|
|
|
|
|
|
|
for (var mission : this.missions.values()) {
|
|
|
|
if (mission.getData().getRefreshType() == null || mission.getData().getRefreshType() == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_DAILY) {
|
|
|
|
mission.setStatus(BattlePassMissionStatus.MISSION_STATUS_UNFINISHED);
|
|
|
|
mission.setProgress(0);
|
|
|
|
|
|
|
|
resetMissions.add(mission);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.getPlayer().sendPacket(new PacketBattlePassMissionUpdateNotify(resetMissions));
|
|
|
|
this.getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(this.getPlayer()));
|
2022-06-24 01:12:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
public void resetWeeklyMissions() {
|
2022-06-27 00:54:17 -07:00
|
|
|
var resetMissions = new ArrayList<BattlePassMission>();
|
|
|
|
|
|
|
|
for (var mission : this.missions.values()) {
|
|
|
|
if (mission.getData().getRefreshType() == BattlePassMissionRefreshType.BATTLE_PASS_MISSION_REFRESH_CYCLE_CROSS_SCHEDULE) {
|
|
|
|
mission.setStatus(BattlePassMissionStatus.MISSION_STATUS_UNFINISHED);
|
|
|
|
mission.setProgress(0);
|
|
|
|
|
|
|
|
resetMissions.add(mission);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.getPlayer().sendPacket(new PacketBattlePassMissionUpdateNotify(resetMissions));
|
|
|
|
this.getPlayer().sendPacket(new PacketBattlePassCurScheduleUpdateNotify(this.getPlayer()));
|
2022-06-24 01:12:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
public BattlePassSchedule getScheduleProto() {
|
2022-06-26 03:05:08 -07:00
|
|
|
var currentDate = LocalDate.now();
|
|
|
|
var nextSundayDate = (currentDate.getDayOfWeek() == DayOfWeek.SUNDAY)
|
|
|
|
? currentDate
|
|
|
|
: LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
|
2022-06-27 00:54:17 -07:00
|
|
|
var nextSundayTime = LocalDateTime.of(nextSundayDate.getYear(), nextSundayDate.getMonthValue(), nextSundayDate.getDayOfMonth(), 23, 59, 59);
|
|
|
|
|
2022-06-24 01:12:52 -07:00
|
|
|
BattlePassSchedule.Builder schedule = BattlePassSchedule.newBuilder()
|
|
|
|
.setScheduleId(2700)
|
|
|
|
.setLevel(this.getLevel())
|
|
|
|
.setPoint(this.getPoint())
|
|
|
|
.setBeginTime(0)
|
|
|
|
.setEndTime(2059483200)
|
|
|
|
.setIsViewed(this.isViewed())
|
|
|
|
.setUnlockStatus(this.isPaid() ? BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_PAID : BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_FREE)
|
2022-06-26 17:57:34 -07:00
|
|
|
.setJPFMGBEBBBJ(2) // Not bought on Playstation.
|
|
|
|
.setCurCyclePoints(this.getCyclePoints())
|
2022-06-27 00:54:17 -07:00
|
|
|
.setCurCycle(BattlePassCycle.newBuilder()
|
|
|
|
.setBeginTime(0)
|
|
|
|
.setEndTime((int)nextSundayTime.atZone(ZoneId.systemDefault()).toEpochSecond())
|
|
|
|
.setCycleIdx(3)
|
|
|
|
);
|
2022-06-24 01:12:52 -07:00
|
|
|
|
|
|
|
for (BattlePassReward reward : getTakenRewards().values()) {
|
|
|
|
schedule.addRewardTakenList(reward.toProto());
|
|
|
|
}
|
|
|
|
|
|
|
|
return schedule.build();
|
|
|
|
}
|
|
|
|
|
2022-06-21 07:59:10 -07:00
|
|
|
public void save() {
|
|
|
|
DatabaseHelper.saveBattlePass(this);
|
2022-06-21 22:18:13 +08:00
|
|
|
}
|
|
|
|
}
|