implement BattlePass (Except missions) (#1316)

* BattlePass

* BattlePass
This commit is contained in:
诗音澄鸢 镜苑芳依 2022-06-21 22:18:13 +08:00 committed by GitHub
parent c171b5904e
commit b9bf33c2f7
15 changed files with 416 additions and 1 deletions

View File

@ -0,0 +1,23 @@
package emu.grasscutter.command.commands;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.player.Player;
import java.util.List;
@Command(label = "setbp", usage = "", aliases = "bp",permission = "player.setbp", description = "")
public final class SetBPLevelCommand implements CommandHandler {
@Override
public void execute(Player sender, Player targetPlayer, List<String> args) {
if (args.size() < 1) {
CommandHandler.sendMessage(sender , "Need a arg");
return;
}
int level = Integer.parseInt(args.get(0));
sender.getBattlePassManager().addPoint(level);
sender.getBattlePassManager().updateAwardTakenLevel(0);
}
}

View File

@ -94,6 +94,8 @@ public class GameData {
private static final Int2ObjectMap<FurnitureMakeConfigData> furnitureMakeConfigDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<InvestigationMonsterData> investigationMonsterDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<CityData> cityDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<BattlePassMissionExcelConfigData> battlePassMissionExcelConfigDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<BattlePassRewardExcelConfigData> battlePassRewardExcelConfigDataMap = new Int2ObjectOpenHashMap<>();
// Cache
private static Map<Integer, List<Integer>> fetters = new HashMap<>();
@ -416,4 +418,11 @@ public class GameData {
return cityDataMap;
}
public static Int2ObjectMap<BattlePassMissionExcelConfigData> getBattlePassMissionExcelConfigDataMap() {
return battlePassMissionExcelConfigDataMap;
}
public static Int2ObjectMap<BattlePassRewardExcelConfigData> getBattlePassRewardExcelConfigDataMap() {
return battlePassRewardExcelConfigDataMap;
}
}

View File

@ -0,0 +1,29 @@
package emu.grasscutter.data.excels;
import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.ResourceType;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.FieldDefaults;
@ResourceType(name = {"BattlePassMissionExcelConfigData.json"})
@FieldDefaults(level = AccessLevel.PRIVATE)
@Getter
@Setter
public class BattlePassMissionExcelConfigData extends GameResource {
private int addPoint;
private int id;
private int progress;
private String refreshType;
@Override
public void onLoad() {
}
@Override
public int getId() {
return this.id;
}
}

View File

@ -0,0 +1,27 @@
package emu.grasscutter.data.excels;
import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.ResourceType;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@ResourceType(name = "BattlePassRewardExcelConfigData.json")
@Getter
@Setter
public class BattlePassRewardExcelConfigData extends GameResource {
private int indexId;
private int level;
private List<Integer> freeRewardIdList;
private List<Integer> paidRewardIdList;
@Override
public int getId() {
return this.level;
}
@Override
public void onLoad() {
}
}

View File

@ -29,6 +29,9 @@ public class Account {
private List<String> permissions;
private Locale locale;
private int point;
private int awardTakenLevel;
private String banReason;
private int banEndTime;
private int banStartTime;
@ -208,7 +211,23 @@ public class Account {
public boolean removePermission(String permission) {
return this.permissions.remove(permission);
}
public void setPoint(int point) {
this.point = point;
}
public int getPoint() {
return point;
}
public void setAwardTakenLevel(int level) {
this.awardTakenLevel = level;
}
public int getAwardTakenLevel() {
return awardTakenLevel;
}
// TODO make unique
public String generateLoginToken() {
this.token = Utils.bytesToHex(Crypto.createSessionKey(32));

View File

@ -0,0 +1,40 @@
package emu.grasscutter.game.battlepass;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.server.packet.send.PacketBattlePassCurScheduleUpdateNotify;
public class BattlePassManager {
private final Player player;
private int point;
private int awardTakenLevel;
public BattlePassManager(Player player){
this.player = player;
point = player.getAccount().getPoint();
awardTakenLevel = player.getAccount().getAwardTakenLevel();
}
public void addPoint(int point){
this.point += point;
player.getAccount().setPoint(point);
player.getSession().send(new PacketBattlePassCurScheduleUpdateNotify(player.getSession().getPlayer()));
//save the point data
player.getAccount().save();
}
public void updateAwardTakenLevel(int level){
this.awardTakenLevel = level;
player.getAccount().setAwardTakenLevel(awardTakenLevel);
player.getSession().send(new PacketBattlePassCurScheduleUpdateNotify(player.getSession().getPlayer()));
player.getAccount().save();
}
public int getPoint() {
return point;
}
public int getAwardTakenLevel() {
return awardTakenLevel;
}
}

View File

@ -12,6 +12,7 @@ import emu.grasscutter.game.ability.AbilityManager;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.avatar.AvatarProfileData;
import emu.grasscutter.game.avatar.AvatarStorage;
import emu.grasscutter.game.battlepass.BattlePassManager;
import emu.grasscutter.game.entity.EntityMonster;
import emu.grasscutter.game.entity.EntityVehicle;
import emu.grasscutter.game.home.GameHome;
@ -169,6 +170,7 @@ public class Player {
@Transient private DeforestationManager deforestationManager;
@Transient private GameHome home;
@Transient private FurnitureManager furnitureManager;
@Transient private BattlePassManager battlePassManager;
private long springLastUsed;
private HashMap<String, MapMark> mapMarks;
@ -290,6 +292,10 @@ public class Player {
this.account = account;
}
public void setBattlePassManager(Player player){
this.battlePassManager = new BattlePassManager(player);
}
public GameSession getSession() {
return session;
}
@ -1206,6 +1212,10 @@ public class Player {
return furnitureManager;
}
public BattlePassManager getBattlePassManager(){
return battlePassManager;
}
public AbilityManager getAbilityManager() {
return abilityManager;
}
@ -1348,6 +1358,7 @@ public class Player {
session.send(new PacketPlayerStoreNotify(this));
session.send(new PacketAvatarDataNotify(this));
session.send(new PacketFinishedParentQuestNotify(this));
session.send(new PacketBattlePassAllDataNotify(this));
session.send(new PacketQuestListNotify(this));
session.send(new PacketCodexDataFullNotify(this));
session.send(new PacketAllWidgetDataNotify(this));

View File

@ -76,6 +76,7 @@ public class GameSession implements GameSessionManager.KcpChannel {
this.player = player;
this.player.setSession(this);
this.player.setAccount(this.getAccount());
this.player.setBattlePassManager(this.player);;
}
public SessionState getState() {

View File

@ -0,0 +1,25 @@
package emu.grasscutter.server.packet.recv;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.TakeBattlePassMissionPointReqOuterClass;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketBattlePassCurScheduleUpdateNotify;
import emu.grasscutter.server.packet.send.PacketBattlePassMissionUpdateNotify;
import emu.grasscutter.server.packet.send.PacketTakeBattlePassMissionPointRsp;
@Opcodes(PacketOpcodes.TakeBattlePassMissionPointReq)
public class HandlerTakeBattlePassMissionPointReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
var req
= TakeBattlePassMissionPointReqOuterClass.TakeBattlePassMissionPointReq.parseFrom(payload);
session.send(new PacketBattlePassMissionUpdateNotify(req.getMissionIdListList() , session));
session.send(new PacketBattlePassCurScheduleUpdateNotify(session.getPlayer()));
session.send(new PacketTakeBattlePassMissionPointRsp());
}
}

View File

@ -0,0 +1,24 @@
package emu.grasscutter.server.packet.recv;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.TakeBattlePassRewardReqOuterClass;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketTakeBattlePassRewardRsp;
@Opcodes(PacketOpcodes.TakeBattlePassRewardReq)
public class HandlerTakeBattlePassRewardReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
var req
= TakeBattlePassRewardReqOuterClass.TakeBattlePassRewardReq.parseFrom(payload);
//due to the list only have one element, so we can use get(0)
session.send(new PacketTakeBattlePassRewardRsp(req.getTakeOptionListList() , session));
//update the awardTakenLevel
req.getTakeOptionListList().forEach(battlePassRewardTakeOption ->
session.getPlayer().getBattlePassManager().updateAwardTakenLevel(battlePassRewardTakeOption.getTag().getLevel()));
}
}

View File

@ -0,0 +1,63 @@
package emu.grasscutter.server.packet.send;
import emu.grasscutter.data.GameData;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.*;
import java.util.ArrayList;
import java.util.List;
public class PacketBattlePassAllDataNotify extends BasePacket {
public PacketBattlePassAllDataNotify(Player player) {
super(PacketOpcodes.BattlePassAllDataNotify);
var value = player.getBattlePassManager().getPoint();
int level = (int) Math.floor(value / 1000d);
var point = value - level * 1000;
List<BattlePassRewardTagOuterClass.BattlePassRewardTag> rewardTags = new ArrayList<>();
for (int id = 1; id <= player.getAccount().getAwardTakenLevel(); id++)
rewardTags.add(BattlePassRewardTagOuterClass.BattlePassRewardTag.newBuilder()
.setLevel(id)
.setUnlockStatus(BattlePassUnlockStatusOuterClass.BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_FREE)
.setRewardId(1001000 + id)
.build());
var proto
= BattlePassAllDataNotifyOuterClass.BattlePassAllDataNotify.newBuilder();
var missions
= GameData.getBattlePassMissionExcelConfigDataMap();
var curSchedule
= BattlePassScheduleOuterClass.BattlePassSchedule.newBuilder()
.setScheduleId(2700).setLevel(level).setPoint(point).setBeginTime(1653940800).setEndTime(2059483200).addAllRewardTakenList(rewardTags)
.setIsViewed(true).setUnlockStatus(BattlePassUnlockStatusOuterClass.BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_FREE).setCurCyclePoints(0)
.setCurCycle(BattlePassCycleOuterClass.BattlePassCycle.newBuilder().setBeginTime(1653940800).setEndTime(2059483200).setCycleIdx(3).build());
proto.setHaveCurSchedule(true).setCurSchedule(curSchedule);
//TODO: UNFINISHED YET / Need to add mission data --> Hard work
for (var mission : missions.values())
proto.addMissionList(BattlePassMissionOuterClass.BattlePassMission.newBuilder()
.setMissionId(mission.getId())
.setMissionStatus(BattlePassMissionOuterClass.BattlePassMission.MissionStatus.MISSION_STATUS_UNFINISHED)
.setTotalProgress(mission.getProgress())
.setMissionType(
mission.getRefreshType() == null ? 0 :
mission.getRefreshType().equals("BATTLE_PASS_MISSION_REFRESH_SCHEDULE") ? 2 : mission.getRefreshType().contains("CYCLE") ? 1 : 0)
.setRewardBattlePassPoint(mission.getAddPoint())
.build());
setData(proto.build());
}
}

View File

@ -0,0 +1,42 @@
package emu.grasscutter.server.packet.send;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.*;
import java.util.ArrayList;
import java.util.List;
public class PacketBattlePassCurScheduleUpdateNotify extends BasePacket {
public PacketBattlePassCurScheduleUpdateNotify(Player player) {
super(PacketOpcodes.BattlePassCurScheduleUpdateNotify);
var value = player.getBattlePassManager().getPoint();
int level = (int) Math.floor(value / 1000d);
var point = value - level * 1000;
List<BattlePassRewardTagOuterClass.BattlePassRewardTag> rewardTags = new ArrayList<>();
for (int id = 1; id <= player.getAccount().getAwardTakenLevel(); id++)
rewardTags.add(BattlePassRewardTagOuterClass.BattlePassRewardTag.newBuilder()
.setLevel(id)
.setUnlockStatus(BattlePassUnlockStatusOuterClass.BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_FREE)
.setRewardId(1001000 + id)
.build());
var curSchedule
= BattlePassScheduleOuterClass.BattlePassSchedule.newBuilder()
.setScheduleId(2700).setLevel(level).setPoint(point).setBeginTime(1653940800).setEndTime(2059483200).addAllRewardTakenList(rewardTags)
.setIsViewed(true).setUnlockStatus(BattlePassUnlockStatusOuterClass.BattlePassUnlockStatus.BATTLE_PASS_UNLOCK_STATUS_FREE).setCurCyclePoints(0)
.setCurCycle(BattlePassCycleOuterClass.BattlePassCycle.newBuilder().setBeginTime(1653940800).setEndTime(2059483200).setCycleIdx(3).build());
var proto
= BattlePassCurScheduleUpdateNotifyOuterClass.BattlePassCurScheduleUpdateNotify.newBuilder();
proto.setHaveCurSchedule(true).setCurSchedule(curSchedule).build();
setData(proto.build());
}
}

View File

@ -0,0 +1,40 @@
package emu.grasscutter.server.packet.send;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.BattlePassMissionExcelConfigData;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.BattlePassMissionOuterClass;
import emu.grasscutter.net.proto.BattlePassMissionUpdateNotifyOuterClass;
import emu.grasscutter.server.game.GameSession;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import java.util.List;
import java.util.Map;
public class PacketBattlePassMissionUpdateNotify extends BasePacket {
public PacketBattlePassMissionUpdateNotify(List<Integer> missionIdList , GameSession session) {
super(PacketOpcodes.BattlePassMissionUpdateNotify);
var proto
= BattlePassMissionUpdateNotifyOuterClass.BattlePassMissionUpdateNotify.newBuilder();
Map<Integer, BattlePassMissionExcelConfigData> missionMap
= GameData.getBattlePassMissionExcelConfigDataMap();
missionIdList.forEach(missionId -> proto.addMissionList
(BattlePassMissionOuterClass.BattlePassMission.newBuilder().setMissionId(missionId).setMissionStatus
(BattlePassMissionOuterClass.BattlePassMission.MissionStatus.MISSION_STATUS_POINT_TAKEN)
.setTotalProgress(missionMap.get(missionId).getProgress()).setRewardBattlePassPoint(missionMap.get(missionId).getAddPoint()).build()));
var point = session.getPlayer().getBattlePassManager().getPoint();
missionIdList.forEach(missionId
-> session.getPlayer().getBattlePassManager().addPoint(missionMap.get(missionId).getAddPoint()));
Grasscutter.getLogger().info("[PacketBattlePassMissionUpdateNotify] addPoint: {}", session.getPlayer().getBattlePassManager().getPoint() - point);
this.setData(proto.build());
}
}

View File

@ -0,0 +1,13 @@
package emu.grasscutter.server.packet.send;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.TakeBattlePassMissionPointRspOuterClass;
import java.util.List;
public class PacketTakeBattlePassMissionPointRsp extends BasePacket {
public PacketTakeBattlePassMissionPointRsp() {
super(PacketOpcodes.TakeBattlePassMissionPointRsp);
}
}

View File

@ -0,0 +1,49 @@
package emu.grasscutter.server.packet.send;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.excels.BattlePassRewardExcelConfigData;
import emu.grasscutter.data.excels.RewardData;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.BattlePassRewardTakeOptionOuterClass;
import emu.grasscutter.net.proto.ItemParamOuterClass;
import emu.grasscutter.net.proto.TakeBattlePassRewardRspOuterClass;
import emu.grasscutter.server.game.GameSession;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class PacketTakeBattlePassRewardRsp extends BasePacket {
public PacketTakeBattlePassRewardRsp(List<BattlePassRewardTakeOptionOuterClass.BattlePassRewardTakeOption> takeOptionList , GameSession session) {
super(PacketOpcodes.TakeBattlePassRewardRsp);
var proto
= TakeBattlePassRewardRspOuterClass.TakeBattlePassRewardRsp.newBuilder();
Map<Integer , BattlePassRewardExcelConfigData> excelConfigDataMap = GameData.getBattlePassRewardExcelConfigDataMap();
Map<Integer , RewardData> rewardDataMap = GameData.getRewardDataMap();
List<Integer> rewardItemList = new ArrayList<>();
for (var takeOption : takeOptionList) {
for (int level = session.getPlayer().getBattlePassManager().getAwardTakenLevel() + 1 ; level <= takeOption.getTag().getLevel() ; level++){
rewardItemList.addAll(excelConfigDataMap.get(level).getFreeRewardIdList());
rewardItemList.addAll(excelConfigDataMap.get(level).getPaidRewardIdList());
}
for (var rewardItemId : rewardItemList) {
var rewardData = rewardDataMap.get(rewardItemId);
if (rewardData == null) continue;
rewardData.getRewardItemList().forEach(i ->
proto.addItemList(ItemParamOuterClass.ItemParam.newBuilder().setItemId(i.getId()).setCount(i.getCount()).build()));
}
}
proto.addAllTakeOptionList(takeOptionList).build();
setData(proto);
}
}