diff --git a/build.gradle b/build.gradle index eefef5b48..dd8fa9fa0 100644 --- a/build.gradle +++ b/build.gradle @@ -70,7 +70,7 @@ dependencies { implementation group: 'io.netty', name: 'netty-all', version: '4.1.71.Final' - implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.8' + implementation group: 'com.google.code.gson', name: 'gson', version: '2.9.0' implementation group: 'com.google.protobuf', name: 'protobuf-java', version: '3.18.2' implementation group: 'org.reflections', name: 'reflections', version: '0.10.2' diff --git a/data/TowerSchedule.json b/data/TowerSchedule.json new file mode 100644 index 000000000..b93100645 --- /dev/null +++ b/data/TowerSchedule.json @@ -0,0 +1,5 @@ +{ + "scheduleId" : 1, + "scheduleStartTime" : "2022-05-01T00:00:00+08:00", + "nextScheduleChangeTime" : "2022-05-30T00:00:00+08:00" +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/command/commands/UnlockTowerCommand.java b/src/main/java/emu/grasscutter/command/commands/UnlockTowerCommand.java new file mode 100644 index 000000000..e0fce695c --- /dev/null +++ b/src/main/java/emu/grasscutter/command/commands/UnlockTowerCommand.java @@ -0,0 +1,32 @@ +package emu.grasscutter.command.commands; + +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.tower.TowerLevelRecord; + +import java.util.List; + +import static emu.grasscutter.utils.Language.translate; + +@Command(label = "unlocktower", usage = "unlocktower", aliases = {"ut"}, + description = "Unlock all levels of tower", permission = "player.tower") +public class UnlockTowerCommand implements CommandHandler { + + @Override + public void execute(Player sender, Player targetPlayer, List args) { + unlockFloor(sender, sender.getServer().getTowerScheduleManager() + .getCurrentTowerScheduleData().getEntranceFloorId()); + + unlockFloor(sender, sender.getServer().getTowerScheduleManager() + .getScheduleFloors()); + + CommandHandler.sendMessage(sender, translate("commands.tower.unlock_done")); + } + + public void unlockFloor(Player player, List floors){ + floors.stream() + .filter(id -> !player.getTowerManager().getRecordMap().containsKey(id)) + .forEach(id -> player.getTowerManager().getRecordMap().put(id, new TowerLevelRecord(id))); + } +} diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index f06d1bda6..ac2472192 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -73,6 +73,7 @@ public class GameData { private static final Int2ObjectMap rewardPreviewDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap towerFloorDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap towerLevelDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap towerScheduleDataMap = new Int2ObjectOpenHashMap<>(); // Cache private static Map> fetters = new HashMap<>(); @@ -327,4 +328,7 @@ public class GameData { public static Int2ObjectMap getTowerLevelDataMap(){ return towerLevelDataMap; } + public static Int2ObjectMap getTowerScheduleDataMap(){ + return towerScheduleDataMap; + } } diff --git a/src/main/java/emu/grasscutter/data/def/TowerScheduleData.java b/src/main/java/emu/grasscutter/data/def/TowerScheduleData.java new file mode 100644 index 000000000..017776c06 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/def/TowerScheduleData.java @@ -0,0 +1,70 @@ +package emu.grasscutter.data.def; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +import java.util.List; + +@ResourceType(name = "TowerScheduleExcelConfigData.json") +public class TowerScheduleData extends GameResource { + private int ScheduleId; + private List EntranceFloorId; + private List Schedules; + private int MonthlyLevelConfigId; + @Override + public int getId() { + return ScheduleId; + } + + @Override + public void onLoad() { + super.onLoad(); + this.Schedules = this.Schedules.stream() + .filter(item -> item.getFloorList().size() > 0) + .toList(); + } + + public int getScheduleId() { + return ScheduleId; + } + + public void setScheduleId(int scheduleId) { + ScheduleId = scheduleId; + } + + public List getEntranceFloorId() { + return EntranceFloorId; + } + + public void setEntranceFloorId(List entranceFloorId) { + EntranceFloorId = entranceFloorId; + } + + public List getSchedules() { + return Schedules; + } + + public void setSchedules(List schedules) { + Schedules = schedules; + } + + public int getMonthlyLevelConfigId() { + return MonthlyLevelConfigId; + } + + public void setMonthlyLevelConfigId(int monthlyLevelConfigId) { + MonthlyLevelConfigId = monthlyLevelConfigId; + } + + public static class ScheduleDetail{ + private List FloorList; + + public List getFloorList() { + return FloorList; + } + + public void setFloorList(List floorList) { + FloorList = floorList; + } + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java b/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java index 5b1ff7a30..c480d047f 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java +++ b/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java @@ -12,12 +12,18 @@ public class TowerDungeonSettleListener implements DungeonSettleListener { scene.setAutoCloseTime(Utils.getCurrentSeconds() + 1000); var towerManager = scene.getPlayers().get(0).getTowerManager(); - towerManager.notifyCurLevelRecordChangeWhenDone(); - scene.broadcastPacket(new PacketTowerFloorRecordChangeNotify(towerManager.getCurrentFloorId())); - scene.broadcastPacket(new PacketDungeonSettleNotify(scene.getChallenge(), - true, + towerManager.notifyCurLevelRecordChangeWhenDone(3); + scene.broadcastPacket(new PacketTowerFloorRecordChangeNotify( + towerManager.getCurrentFloorId(), + 3, + towerManager.canEnterScheduleFloor() + )); + + scene.broadcastPacket(new PacketDungeonSettleNotify( + scene.getChallenge(), + towerManager.hasNextFloor(), towerManager.hasNextLevel(), - towerManager.getNextFloorId() + towerManager.hasNextLevel() ? 0 : towerManager.getNextFloorId() )); } diff --git a/src/main/java/emu/grasscutter/game/tower/TowerLevelRecord.java b/src/main/java/emu/grasscutter/game/tower/TowerLevelRecord.java new file mode 100644 index 000000000..5a65f63ed --- /dev/null +++ b/src/main/java/emu/grasscutter/game/tower/TowerLevelRecord.java @@ -0,0 +1,64 @@ +package emu.grasscutter.game.tower; + +import dev.morphia.annotations.Entity; + +import java.util.HashMap; +import java.util.Map; + +@Entity +public class TowerLevelRecord { + /** + * floorId in config + */ + private int floorId; + /** + * LevelId - Stars + */ + private Map passedLevelMap; + + private int floorStarRewardProgress; + + public TowerLevelRecord setLevelStars(int levelId, int stars){ + passedLevelMap.put(levelId, stars); + return this; + } + + public int getStarCount() { + return passedLevelMap.values().stream().mapToInt(Integer::intValue).sum(); + } + + public TowerLevelRecord(){ + + } + + public TowerLevelRecord(int floorId){ + this.floorId = floorId; + this.passedLevelMap = new HashMap<>(); + this.floorStarRewardProgress = 0; + } + + public int getFloorId() { + return floorId; + } + + public void setFloorId(int floorId) { + this.floorId = floorId; + } + + public Map getPassedLevelMap() { + return passedLevelMap; + } + + public void setPassedLevelMap(Map passedLevelMap) { + this.passedLevelMap = passedLevelMap; + } + + public int getFloorStarRewardProgress() { + return floorStarRewardProgress; + } + + public void setFloorStarRewardProgress(int floorStarRewardProgress) { + this.floorStarRewardProgress = floorStarRewardProgress; + } + +} diff --git a/src/main/java/emu/grasscutter/game/tower/TowerManager.java b/src/main/java/emu/grasscutter/game/tower/TowerManager.java index 409549a1f..9346ffead 100644 --- a/src/main/java/emu/grasscutter/game/tower/TowerManager.java +++ b/src/main/java/emu/grasscutter/game/tower/TowerManager.java @@ -9,10 +9,12 @@ import emu.grasscutter.game.dungeons.TowerDungeonSettleListener; import emu.grasscutter.game.player.Player; import emu.grasscutter.server.packet.send.PacketCanUseSkillNotify; import emu.grasscutter.server.packet.send.PacketTowerCurLevelRecordChangeNotify; - import emu.grasscutter.server.packet.send.PacketTowerEnterLevelRsp; +import emu.grasscutter.server.packet.send.PacketTowerLevelStarCondNotify; +import java.util.HashMap; import java.util.List; +import java.util.Map; @Entity public class TowerManager { @@ -26,11 +28,19 @@ public class TowerManager { this.player = player; } + /** + * the floor players chose + */ private int currentFloorId; private int currentLevel; @Transient private int currentLevelId; + /** + * floorId - Record + */ + private Map recordMap; + @Transient private int entryScene; @@ -38,7 +48,26 @@ public class TowerManager { return currentFloorId; } + public int getCurrentLevelId(){ + return this.currentLevelId + currentLevel; + } + + /** + * form 1-3 + */ + public int getCurrentLevel(){ + return currentLevel + 1; + } private static final List towerDungeonSettleListener = List.of(new TowerDungeonSettleListener()); + + public Map getRecordMap() { + if(recordMap == null){ + recordMap = new HashMap<>(); + recordMap.put(1001, new TowerLevelRecord(1001)); + } + return recordMap; + } + public void teamSelect(int floor, List> towerTeams) { var floorData = GameData.getTowerFloorDataMap().get(floor); @@ -54,51 +83,73 @@ public class TowerManager { entryScene = player.getSceneId(); } - player.getTeamManager().setupTemporaryTeam(towerTeams); } public void enterLevel(int enterPointId) { - var levelData = GameData.getTowerLevelDataMap().get(currentLevelId + currentLevel); + var levelData = GameData.getTowerLevelDataMap().get(getCurrentLevelId()); - this.currentLevel++; - var id = levelData.getDungeonId(); + var dungeonId = levelData.getDungeonId(); notifyCurLevelRecordChange(); // use team user choose player.getTeamManager().useTemporaryTeam(0); - player.getServer().getDungeonManager().handoffDungeon(player, id, + player.getServer().getDungeonManager().handoffDungeon(player, dungeonId, towerDungeonSettleListener); // make sure user can exit dungeon correctly player.getScene().setPrevScene(entryScene); player.getScene().setPrevScenePoint(enterPointId); - player.getSession().send(new PacketTowerEnterLevelRsp(currentFloorId, currentLevel)); + player.getSession().send(new PacketTowerEnterLevelRsp(currentFloorId, getCurrentLevel())); // stop using skill player.getSession().send(new PacketCanUseSkillNotify(false)); + // notify the cond of stars + player.getSession().send(new PacketTowerLevelStarCondNotify(currentFloorId, getCurrentLevel())); } public void notifyCurLevelRecordChange(){ - player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, currentLevel)); + player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, getCurrentLevel())); } - public void notifyCurLevelRecordChangeWhenDone(){ - player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, currentLevel + 1)); + public void notifyCurLevelRecordChangeWhenDone(int stars){ + if(!recordMap.containsKey(currentFloorId)){ + recordMap.put(currentFloorId, + new TowerLevelRecord(currentFloorId).setLevelStars(getCurrentLevelId(),stars)); + }else{ + recordMap.put(currentFloorId, + recordMap.get(currentFloorId).setLevelStars(getCurrentLevelId(),stars)); + } + + this.currentLevel++; + + if(!hasNextLevel()){ + // set up the next floor + recordMap.put(getNextFloorId(), new TowerLevelRecord(getNextFloorId())); + player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(getNextFloorId(), 1)); + }else{ + player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, getCurrentLevel())); + } } public boolean hasNextLevel(){ return this.currentLevel < 3; } - public int getNextFloorId() { - if(hasNextLevel()){ - return 0; - } - this.currentFloorId++; - return this.currentFloorId; + return player.getServer().getTowerScheduleManager().getNextFloorId(this.currentFloorId); + } + public boolean hasNextFloor(){ + return player.getServer().getTowerScheduleManager().getNextFloorId(this.currentFloorId) > 0; } public void clearEntry() { this.entryScene = 0; } + + public boolean canEnterScheduleFloor(){ + if(!recordMap.containsKey(player.getServer().getTowerScheduleManager().getLastEntranceFloor())){ + return false; + } + return recordMap.get(player.getServer().getTowerScheduleManager().getLastEntranceFloor()) + .getStarCount() >= 6; + } } diff --git a/src/main/java/emu/grasscutter/game/tower/TowerScheduleConfig.java b/src/main/java/emu/grasscutter/game/tower/TowerScheduleConfig.java new file mode 100644 index 000000000..35afbc7ba --- /dev/null +++ b/src/main/java/emu/grasscutter/game/tower/TowerScheduleConfig.java @@ -0,0 +1,35 @@ +package emu.grasscutter.game.tower; + +import java.util.Date; + +public class TowerScheduleConfig { + private int scheduleId; + + private Date scheduleStartTime; + private Date nextScheduleChangeTime; + + + public int getScheduleId() { + return scheduleId; + } + + public void setScheduleId(int scheduleId) { + this.scheduleId = scheduleId; + } + + public Date getScheduleStartTime() { + return scheduleStartTime; + } + + public void setScheduleStartTime(Date scheduleStartTime) { + this.scheduleStartTime = scheduleStartTime; + } + + public Date getNextScheduleChangeTime() { + return nextScheduleChangeTime; + } + + public void setNextScheduleChangeTime(Date nextScheduleChangeTime) { + this.nextScheduleChangeTime = nextScheduleChangeTime; + } +} diff --git a/src/main/java/emu/grasscutter/game/tower/TowerScheduleManager.java b/src/main/java/emu/grasscutter/game/tower/TowerScheduleManager.java new file mode 100644 index 000000000..33f5c158d --- /dev/null +++ b/src/main/java/emu/grasscutter/game/tower/TowerScheduleManager.java @@ -0,0 +1,75 @@ +package emu.grasscutter.game.tower; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.def.TowerScheduleData; +import emu.grasscutter.server.game.GameServer; + +import java.io.FileReader; +import java.util.List; + +public class TowerScheduleManager { + private final GameServer gameServer; + + public GameServer getGameServer() { + return gameServer; + } + + public TowerScheduleManager(GameServer gameServer) { + this.gameServer = gameServer; + this.load(); + } + + private TowerScheduleConfig towerScheduleConfig; + + public synchronized void load(){ + try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "TowerSchedule.json")) { + towerScheduleConfig = Grasscutter.getGsonFactory().fromJson(fileReader, TowerScheduleConfig.class); + + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load tower schedule config.", e); + } + } + + public TowerScheduleConfig getTowerScheduleConfig() { + return towerScheduleConfig; + } + + public TowerScheduleData getCurrentTowerScheduleData(){ + var data = GameData.getTowerScheduleDataMap().get(towerScheduleConfig.getScheduleId()); + if(data == null){ + Grasscutter.getLogger().error("Could not get current tower schedule data by config:{}", towerScheduleConfig); + } + return data; + } + + public List getScheduleFloors() { + return getCurrentTowerScheduleData().getSchedules().get(0).getFloorList(); + } + + public int getNextFloorId(int floorId){ + var entranceFloors = getCurrentTowerScheduleData().getEntranceFloorId(); + var nextId = 0; + // find in entrance floors first + for(int i=0;i getBlocks() { return blocks; } @@ -237,16 +241,16 @@ public class SceneScriptManager { for (SceneSuite suite : group.suites) { suite.sceneMonsters = new ArrayList<>(suite.monsters.size()); - for (int id : suite.monsters) { - try { - SceneMonster monster = (SceneMonster) map.get(id); - if (monster != null) { - suite.sceneMonsters.add(monster); + suite.monsters.forEach(id -> { + Object objEntry = map.get(id.intValue()); + if (objEntry instanceof Map.Entry monsterEntry) { + Object monster = monsterEntry.getValue(); + if(monster instanceof SceneMonster sceneMonster){ + suite.sceneMonsters.add(sceneMonster); } - } catch (Exception e) { - continue; } - } + }); + suite.sceneGadgets = new ArrayList<>(suite.gadgets.size()); for (int id : suite.gadgets) { try { @@ -320,13 +324,15 @@ public class SceneScriptManager { } public void spawnMonstersInGroup(SceneGroup group, int suiteIndex) { - this.currentGroup = group; - this.monsterSceneLimit = 0; var suite = group.getSuiteByIndex(suiteIndex); if(suite == null){ return; } - suite.sceneMonsters.forEach(mob -> spawnMonstersInGroup(group, mob)); + if(suite.sceneMonsters.size() > 0){ + this.currentGroup = group; + this.monsterSceneLimit = 0; + suite.sceneMonsters.forEach(mob -> spawnMonstersInGroup(group, mob)); + } } public void spawnMonstersInGroup(SceneGroup group) { @@ -401,6 +407,7 @@ public class SceneScriptManager { spawnMonstersInGroup(this.currentGroup, this.currentGroup.monsters.get(this.monsterOrders.poll())); }else if(this.monsterAlive.get() == 0){ // spawn the last turn of monsters + //callEvent(EventType.EVENT_MONSTER_TIDE_DIE, new ScriptArgs()); while(!this.monsterOrders.isEmpty()){ spawnMonstersInGroup(this.currentGroup, this.currentGroup.monsters.get(this.monsterOrders.poll())); } diff --git a/src/main/java/emu/grasscutter/scripts/ScriptLib.java b/src/main/java/emu/grasscutter/scripts/ScriptLib.java index 1b9badc11..1c4bbd0f2 100644 --- a/src/main/java/emu/grasscutter/scripts/ScriptLib.java +++ b/src/main/java/emu/grasscutter/scripts/ScriptLib.java @@ -118,7 +118,7 @@ public class ScriptLib { challengeIndex,groupId,ordersConfigId,tideCount,sceneLimit,param6); SceneGroup group = getSceneScriptManager().getGroupById(groupId); - + if (group == null || group.monsters == null) { return 1; } @@ -136,8 +136,7 @@ public class ScriptLib { if (group == null || group.monsters == null) { return 1; } - - // TODO just spawn all from group for now + this.getSceneScriptManager().spawnMonstersInGroup(group, suite); return 0; @@ -159,7 +158,13 @@ public class ScriptLib { if (group == null || group.monsters == null) { return 1; } - + + if(getSceneScriptManager().getScene().getChallenge() != null && + getSceneScriptManager().getScene().getChallenge().inProgress()) + { + return 0; + } + DungeonChallenge challenge = new DungeonChallenge(getSceneScriptManager().getScene(), group); challenge.setChallengeId(challengeId); challenge.setChallengeIndex(challengeIndex); @@ -249,7 +254,7 @@ public class ScriptLib { var1); return (int) getSceneScriptManager().getScene().getEntities().values().stream() - .filter(e -> e instanceof EntityMonster) + .filter(e -> e instanceof EntityMonster && e.getGroupId() == getSceneScriptManager().getCurrentGroup().id) .count(); } public int SetMonsterBattleByGroup(int var1, int var2, int var3){ @@ -266,13 +271,11 @@ public class ScriptLib { return 0; } // 8-1 - public int GetGroupVariableValueByGroup(int var1, String var2, int var3){ - logger.debug("[LUA] Call GetGroupVariableValueByGroup with {},{},{}", - var1,var2,var3); + public int GetGroupVariableValueByGroup(String name, int groupId){ + logger.debug("[LUA] Call GetGroupVariableValueByGroup with {},{}", + name,groupId); - //TODO - - return getSceneScriptManager().getVariables().getOrDefault(var2, 0); + return getSceneScriptManager().getVariables().getOrDefault(name, 0); } public int SetIsAllowUseSkill(int canUse, int var2){ @@ -299,4 +302,11 @@ public class ScriptLib { return 0; } + public int SetGroupVariableValueByGroup(String key, int value, int groupId){ + logger.debug("[LUA] Call SetGroupVariableValueByGroup with {},{},{}", + key,value,groupId); + + return 0; + } + } diff --git a/src/main/java/emu/grasscutter/server/game/GameServer.java b/src/main/java/emu/grasscutter/server/game/GameServer.java index 7ce8488ef..cb0e4965d 100644 --- a/src/main/java/emu/grasscutter/server/game/GameServer.java +++ b/src/main/java/emu/grasscutter/server/game/GameServer.java @@ -15,6 +15,7 @@ import emu.grasscutter.game.managers.InventoryManager; import emu.grasscutter.game.managers.MultiplayerManager; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.shop.ShopManager; +import emu.grasscutter.game.tower.TowerScheduleManager; import emu.grasscutter.game.world.World; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; @@ -54,6 +55,7 @@ public final class GameServer extends KcpServer { private final DropManager dropManager; private final CombineManger combineManger; + private final TowerScheduleManager towerScheduleManager; public GameServer() { this(new InetSocketAddress( @@ -82,7 +84,7 @@ public final class GameServer extends KcpServer { this.dropManager = new DropManager(this); this.expeditionManager = new ExpeditionManager(this); this.combineManger = new CombineManger(this); - + this.towerScheduleManager = new TowerScheduleManager(this); // Hook into shutdown event. Runtime.getRuntime().addShutdownHook(new Thread(this::onServerShutdown)); } @@ -139,6 +141,10 @@ public final class GameServer extends KcpServer { return this.combineManger; } + public TowerScheduleManager getTowerScheduleManager() { + return towerScheduleManager; + } + public TaskMap getTaskMap() { return this.taskMap; } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerAllDataReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerAllDataReq.java index 2a9ef2004..38462882f 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerAllDataReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerAllDataReq.java @@ -11,7 +11,10 @@ public class HandlerTowerAllDataReq extends PacketHandler { @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - session.send(new PacketTowerAllDataRsp()); + session.send(new PacketTowerAllDataRsp( + session.getServer().getTowerScheduleManager(), + session.getPlayer().getTowerManager() + )); } } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonSettleNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonSettleNotify.java index 479029243..56d844d8d 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonSettleNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonSettleNotify.java @@ -46,7 +46,7 @@ public class PacketDungeonSettleNotify extends BasePacket { .setCount(1000) .build()) ; - if(nextFloorId > 0){ + if(nextFloorId > 0 && canJump){ towerLevelEndNotify.setNextFloorId(nextFloorId); } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerAllDataRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerAllDataRsp.java index d2d2376e6..654aa4a07 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerAllDataRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerAllDataRsp.java @@ -1,37 +1,64 @@ package emu.grasscutter.server.packet.send; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.TowerFloorData; +import emu.grasscutter.game.tower.TowerManager; +import emu.grasscutter.game.tower.TowerScheduleManager; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.TowerAllDataRspOuterClass.TowerAllDataRsp; import emu.grasscutter.net.proto.TowerCurLevelRecordOuterClass.TowerCurLevelRecord; import emu.grasscutter.net.proto.TowerFloorRecordOuterClass.TowerFloorRecord; +import emu.grasscutter.net.proto.TowerLevelRecordOuterClass; +import emu.grasscutter.utils.DateHelper; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; +import java.util.stream.IntStream; public class PacketTowerAllDataRsp extends BasePacket { - public PacketTowerAllDataRsp() { + public PacketTowerAllDataRsp(TowerScheduleManager towerScheduleManager, TowerManager towerManager) { super(PacketOpcodes.TowerAllDataRsp); - var list = GameData.getTowerFloorDataMap().values().stream() - .map(TowerFloorData::getFloorId) - .map(id -> TowerFloorRecord.newBuilder().setFloorId(id).build()) - .collect(Collectors.toList()); + var recordList = towerManager.getRecordMap().values().stream() + .map(rec -> TowerFloorRecord.newBuilder() + .setFloorId(rec.getFloorId()) + .setFloorStarRewardProgress(rec.getFloorStarRewardProgress()) + .putAllPassedLevelMap(rec.getPassedLevelMap()) + .addAllPassedLevelRecordList(buildFromPassedLevelMap(rec.getPassedLevelMap())) + .build() + ) + .toList(); + + var openTimeMap = towerScheduleManager.getScheduleFloors().stream() + .collect(Collectors.toMap(x -> x, + y -> DateHelper.getUnixTime(towerScheduleManager.getTowerScheduleConfig() + .getScheduleStartTime())) + ); TowerAllDataRsp proto = TowerAllDataRsp.newBuilder() - .setTowerScheduleId(29) - .addAllTowerFloorRecordList(list) + .setTowerScheduleId(towerScheduleManager.getCurrentTowerScheduleData().getScheduleId()) + .addAllTowerFloorRecordList(recordList) .setCurLevelRecord(TowerCurLevelRecord.newBuilder().setIsEmpty(true)) - .setNextScheduleChangeTime(Integer.MAX_VALUE) - .putFloorOpenTimeMap(1024, 1630486800) - .putFloorOpenTimeMap(1025, 1630486800) - .putFloorOpenTimeMap(1026, 1630486800) - .putFloorOpenTimeMap(1027, 1630486800) - .setScheduleStartTime(1630486800) + .setScheduleStartTime(DateHelper.getUnixTime(towerScheduleManager.getTowerScheduleConfig() + .getScheduleStartTime())) + .setNextScheduleChangeTime(DateHelper.getUnixTime(towerScheduleManager.getTowerScheduleConfig() + .getNextScheduleChangeTime())) + .putAllFloorOpenTimeMap(openTimeMap) + .setIsFinishedEntranceFloor(towerManager.canEnterScheduleFloor()) .build(); this.setData(proto); } + + private List buildFromPassedLevelMap(Map map){ + return map.entrySet().stream() + .map(item -> TowerLevelRecordOuterClass.TowerLevelRecord.newBuilder() + .setLevelId(item.getKey()) + .addAllSatisfiedCondList(IntStream.range(1, item.getValue() + 1).boxed().toList()) + .build()) + .toList(); + + } + } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java index c0ed414a8..5ab091901 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java @@ -8,13 +8,13 @@ import emu.grasscutter.net.proto.TowerLevelRecordOuterClass.TowerLevelRecord; public class PacketTowerFloorRecordChangeNotify extends BasePacket { - public PacketTowerFloorRecordChangeNotify(int floorId) { + public PacketTowerFloorRecordChangeNotify(int floorId, int stars, boolean canEnterScheduleFloor) { super(PacketOpcodes.TowerFloorRecordChangeNotify); TowerFloorRecordChangeNotify proto = TowerFloorRecordChangeNotify.newBuilder() .addTowerFloorRecordList(TowerFloorRecord.newBuilder() .setFloorId(floorId) - .setFloorStarRewardProgress(3) + .setFloorStarRewardProgress(stars) .addPassedLevelRecordList(TowerLevelRecord.newBuilder() .setLevelId(1) .addSatisfiedCondList(1) @@ -22,7 +22,7 @@ public class PacketTowerFloorRecordChangeNotify extends BasePacket { .addSatisfiedCondList(3) .build()) .build()) - .setIsFinishedEntranceFloor(true) + .setIsFinishedEntranceFloor(canEnterScheduleFloor) .build(); this.setData(proto); diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerLevelStarCondNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerLevelStarCondNotify.java new file mode 100644 index 000000000..c2c301e4e --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerLevelStarCondNotify.java @@ -0,0 +1,32 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerLevelStarCondDataOuterClass.TowerLevelStarCondData; +import emu.grasscutter.net.proto.TowerLevelStarCondNotifyOuterClass.TowerLevelStarCondNotify; + +public class PacketTowerLevelStarCondNotify extends BasePacket { + + public PacketTowerLevelStarCondNotify(int floorId, int levelIndex) { + super(PacketOpcodes.TowerLevelStarCondNotify); + + TowerLevelStarCondNotify proto = TowerLevelStarCondNotify.newBuilder() + .setFloorId(floorId) + .setLevelIndex(levelIndex) + .addCondDataList(TowerLevelStarCondData.newBuilder() + .setCondValue(1) + .build() + ) + .addCondDataList(TowerLevelStarCondData.newBuilder() + .setCondValue(2) + .build() + ) + .addCondDataList(TowerLevelStarCondData.newBuilder() + .setCondValue(3) + .build() + ) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/utils/DateHelper.java b/src/main/java/emu/grasscutter/utils/DateHelper.java index 7005d9457..1f1393760 100644 --- a/src/main/java/emu/grasscutter/utils/DateHelper.java +++ b/src/main/java/emu/grasscutter/utils/DateHelper.java @@ -1,7 +1,7 @@ package emu.grasscutter.utils; -import java.util.Date; import java.util.Calendar; +import java.util.Date; public final class DateHelper { public static Date onlyYearMonthDay(Date now) { @@ -13,4 +13,8 @@ public final class DateHelper { calendar.set(Calendar.MILLISECOND, 0); return calendar.getTime(); } + + public static int getUnixTime(Date localDateTime){ + return (int)(localDateTime.getTime() / 1000L); + } } diff --git a/src/main/resources/languages/en-US.json b/src/main/resources/languages/en-US.json index 9a7485608..4ec17a214 100644 --- a/src/main/resources/languages/en-US.json +++ b/src/main/resources/languages/en-US.json @@ -312,6 +312,9 @@ "success": "Teleported %s to %s, %s, %s in scene %s", "description": "Change the player's position." }, + "tower": { + "unlock_done": "Abyss Corridor's Floors are all unlocked now." + }, "weather": { "usage": "Usage: weather [climateId]", "success": "Changed weather to %s with climate %s",