From 32c70cc83faa80a1c715e6b4fc5438336e49d482 Mon Sep 17 00:00:00 2001 From: Akka <104902222+Akka0@users.noreply.github.com> Date: Thu, 5 May 2022 22:00:11 +0800 Subject: [PATCH 1/6] Support of Enter Room Scene --- proto/PersonalSceneJumpReq.proto | 16 ++++++++ proto/PersonalSceneJumpRsp.proto | 19 ++++++++++ .../grasscutter/data/common/PointData.java | 11 +++++- .../recv/HandlerPersonalSceneJumpReq.java | 38 +++++++++++++++++++ .../send/PacketPersonalSceneJumpRsp.java | 20 ++++++++++ 5 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 proto/PersonalSceneJumpReq.proto create mode 100644 proto/PersonalSceneJumpRsp.proto create mode 100644 src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalSceneJumpReq.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketPersonalSceneJumpRsp.java diff --git a/proto/PersonalSceneJumpReq.proto b/proto/PersonalSceneJumpReq.proto new file mode 100644 index 000000000..cc269f258 --- /dev/null +++ b/proto/PersonalSceneJumpReq.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message PersonalSceneJumpReq { + enum CmdId { + option allow_alias = true; + ENET_CHANNEL_ID = 0; + NONE = 0; + ENET_IS_RELIABLE = 1; + IS_ALLOW_CLIENT = 1; + CMD_ID = 260; + } + + uint32 point_id = 1; +} diff --git a/proto/PersonalSceneJumpRsp.proto b/proto/PersonalSceneJumpRsp.proto new file mode 100644 index 000000000..a91f6b5ca --- /dev/null +++ b/proto/PersonalSceneJumpRsp.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "Vector.proto"; + +message PersonalSceneJumpRsp { + enum CmdId { + option allow_alias = true; + NONE = 0; + ENET_CHANNEL_ID = 0; + ENET_IS_RELIABLE = 1; + CMD_ID = 228; + } + + int32 retcode = 1; + uint32 dest_scene_id = 2; + Vector dest_pos = 3; +} diff --git a/src/main/java/emu/grasscutter/data/common/PointData.java b/src/main/java/emu/grasscutter/data/common/PointData.java index fa3891d7c..492f1fc60 100644 --- a/src/main/java/emu/grasscutter/data/common/PointData.java +++ b/src/main/java/emu/grasscutter/data/common/PointData.java @@ -13,7 +13,8 @@ public class PointData { private Position tranPos; private int[] dungeonIds; private int[] dungeonRandomList; - + + private int tranSceneId; public int getId() { return id; } @@ -38,6 +39,14 @@ public class PointData { return dungeonRandomList; } + public int getTranSceneId() { + return tranSceneId; + } + + public void setTranSceneId(int tranSceneId) { + this.tranSceneId = tranSceneId; + } + public void updateDailyDungeon() { if (getDungeonRandomList() == null) { return; diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalSceneJumpReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalSceneJumpReq.java new file mode 100644 index 000000000..98c6984ee --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerPersonalSceneJumpReq.java @@ -0,0 +1,38 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.custom.ScenePointEntry; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PersonalSceneJumpReqOuterClass.PersonalSceneJumpReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketPersonalSceneJumpRsp; +import emu.grasscutter.utils.Position; + + +@Opcodes(PacketOpcodes.PersonalSceneJumpReq) +public class HandlerPersonalSceneJumpReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + PersonalSceneJumpReq req = PersonalSceneJumpReq.parseFrom(payload); + + // get the scene point + String code = session.getPlayer().getSceneId() + "_" + req.getPointId(); + ScenePointEntry scenePointEntry = GameData.getScenePointEntries().get(code); + + if (scenePointEntry != null) { + float x = scenePointEntry.getPointData().getTranPos().getX(); + float y = scenePointEntry.getPointData().getTranPos().getY(); + float z = scenePointEntry.getPointData().getTranPos().getZ(); + Position pos = new Position(x, y, z); + int sceneId = scenePointEntry.getPointData().getTranSceneId(); + + session.getPlayer().getWorld().transferPlayerToScene(session.getPlayer(), sceneId, pos); + session.send(new PacketPersonalSceneJumpRsp(sceneId, pos)); + } + + } + +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketPersonalSceneJumpRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPersonalSceneJumpRsp.java new file mode 100644 index 000000000..59065b5f8 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPersonalSceneJumpRsp.java @@ -0,0 +1,20 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.PersonalSceneJumpRspOuterClass.PersonalSceneJumpRsp; +import emu.grasscutter.utils.Position; + +public class PacketPersonalSceneJumpRsp extends BasePacket { + + public PacketPersonalSceneJumpRsp(int sceneId, Position pos) { + super(PacketOpcodes.PersonalSceneJumpRsp); + + PersonalSceneJumpRsp proto = PersonalSceneJumpRsp.newBuilder() + .setDestSceneId(sceneId) + .setDestPos(pos.toProto()) + .build(); + + this.setData(proto); + } +} From d32d4014cd9fc09b17d83717b827800c0165494a Mon Sep 17 00:00:00 2001 From: Akka <104902222+Akka0@users.noreply.github.com> Date: Fri, 6 May 2022 14:10:23 +0800 Subject: [PATCH 2/6] Choose Avatar & Enter Tower --- proto/TowerBuffSelectReq.proto | 16 ++++ proto/TowerBuffSelectRsp.proto | 16 ++++ proto/TowerCurLevelRecordChangeNotify.proto | 17 +++++ proto/TowerEnterLevelReq.proto | 16 ++++ proto/TowerEnterLevelRsp.proto | 18 +++++ proto/TowerLevelStarCondData.proto | 9 +++ proto/TowerLevelStarCondNotify.proto | 19 +++++ proto/TowerTeamSelectReq.proto | 19 +++++ proto/TowerTeamSelectRsp.proto | 15 ++++ .../java/emu/grasscutter/data/GameData.java | 11 ++- .../grasscutter/data/def/TowerFloorData.java | 73 +++++++++++++++++++ .../grasscutter/data/def/TowerLevelData.java | 55 ++++++++++++++ .../game/dungeons/DungeonManager.java | 3 +- .../emu/grasscutter/game/player/Player.java | 11 +++ .../emu/grasscutter/game/player/TeamInfo.java | 5 ++ .../grasscutter/game/player/TeamManager.java | 66 ++++++++++++++--- .../grasscutter/game/tower/TowerManager.java | 40 ++++++++++ .../recv/HandlerTowerEnterLevelReq.java | 21 ++++++ .../recv/HandlerTowerTeamSelectReq.java | 26 +++++++ .../packet/send/PacketTowerAllDataRsp.java | 13 +++- .../packet/send/PacketTowerEnterLevelRsp.java | 22 ++++++ .../packet/send/PacketTowerTeamSelectRsp.java | 17 +++++ 22 files changed, 495 insertions(+), 13 deletions(-) create mode 100644 proto/TowerBuffSelectReq.proto create mode 100644 proto/TowerBuffSelectRsp.proto create mode 100644 proto/TowerCurLevelRecordChangeNotify.proto create mode 100644 proto/TowerEnterLevelReq.proto create mode 100644 proto/TowerEnterLevelRsp.proto create mode 100644 proto/TowerLevelStarCondData.proto create mode 100644 proto/TowerLevelStarCondNotify.proto create mode 100644 proto/TowerTeamSelectReq.proto create mode 100644 proto/TowerTeamSelectRsp.proto create mode 100644 src/main/java/emu/grasscutter/data/def/TowerFloorData.java create mode 100644 src/main/java/emu/grasscutter/data/def/TowerLevelData.java create mode 100644 src/main/java/emu/grasscutter/game/tower/TowerManager.java create mode 100644 src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerEnterLevelReq.java create mode 100644 src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerTeamSelectReq.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketTowerEnterLevelRsp.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketTowerTeamSelectRsp.java diff --git a/proto/TowerBuffSelectReq.proto b/proto/TowerBuffSelectReq.proto new file mode 100644 index 000000000..1641b350a --- /dev/null +++ b/proto/TowerBuffSelectReq.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message TowerBuffSelectReq { + enum CmdId { + option allow_alias = true; + ENET_CHANNEL_ID = 0; + NONE = 0; + ENET_IS_RELIABLE = 1; + IS_ALLOW_CLIENT = 1; + CMD_ID = 2424; + } + + uint32 tower_buff_id = 1; +} diff --git a/proto/TowerBuffSelectRsp.proto b/proto/TowerBuffSelectRsp.proto new file mode 100644 index 000000000..7a32a8e1e --- /dev/null +++ b/proto/TowerBuffSelectRsp.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message TowerBuffSelectRsp { + enum CmdId { + option allow_alias = true; + NONE = 0; + ENET_CHANNEL_ID = 0; + ENET_IS_RELIABLE = 1; + CMD_ID = 2491; + } + + int32 retcode = 1; + uint32 tower_buff_id = 2; +} diff --git a/proto/TowerCurLevelRecordChangeNotify.proto b/proto/TowerCurLevelRecordChangeNotify.proto new file mode 100644 index 000000000..fd9f94c97 --- /dev/null +++ b/proto/TowerCurLevelRecordChangeNotify.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "TowerCurLevelRecord.proto"; + +message TowerCurLevelRecordChangeNotify { + enum CmdId { + option allow_alias = true; + NONE = 0; + ENET_CHANNEL_ID = 0; + ENET_IS_RELIABLE = 1; + CMD_ID = 2489; + } + + TowerCurLevelRecord cur_level_record = 1; +} diff --git a/proto/TowerEnterLevelReq.proto b/proto/TowerEnterLevelReq.proto new file mode 100644 index 000000000..551f47729 --- /dev/null +++ b/proto/TowerEnterLevelReq.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message TowerEnterLevelReq { + enum CmdId { + option allow_alias = true; + ENET_CHANNEL_ID = 0; + NONE = 0; + ENET_IS_RELIABLE = 1; + IS_ALLOW_CLIENT = 1; + CMD_ID = 2412; + } + + uint32 enter_point_id = 1; +} diff --git a/proto/TowerEnterLevelRsp.proto b/proto/TowerEnterLevelRsp.proto new file mode 100644 index 000000000..fbcc4067f --- /dev/null +++ b/proto/TowerEnterLevelRsp.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message TowerEnterLevelRsp { + enum CmdId { + option allow_alias = true; + NONE = 0; + ENET_CHANNEL_ID = 0; + ENET_IS_RELIABLE = 1; + CMD_ID = 2426; + } + + int32 retcode = 1; + uint32 floor_id = 2; + uint32 level_index = 3; + repeated uint32 tower_buff_id_list = 4; +} diff --git a/proto/TowerLevelStarCondData.proto b/proto/TowerLevelStarCondData.proto new file mode 100644 index 000000000..d46334422 --- /dev/null +++ b/proto/TowerLevelStarCondData.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message TowerLevelStarCondData { + uint32 star_cond_index = 3; + uint32 cond_value = 4; + bool is_pause = 5; +} diff --git a/proto/TowerLevelStarCondNotify.proto b/proto/TowerLevelStarCondNotify.proto new file mode 100644 index 000000000..e605496fb --- /dev/null +++ b/proto/TowerLevelStarCondNotify.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "TowerLevelStarCondData.proto"; + +message TowerLevelStarCondNotify { + enum CmdId { + option allow_alias = true; + NONE = 0; + ENET_CHANNEL_ID = 0; + ENET_IS_RELIABLE = 1; + CMD_ID = 2492; + } + + uint32 floor_id = 1; + uint32 level_index = 2; + repeated TowerLevelStarCondData cond_data_list = 3; +} diff --git a/proto/TowerTeamSelectReq.proto b/proto/TowerTeamSelectReq.proto new file mode 100644 index 000000000..903968061 --- /dev/null +++ b/proto/TowerTeamSelectReq.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "TowerTeam.proto"; + +message TowerTeamSelectReq { + enum CmdId { + option allow_alias = true; + ENET_CHANNEL_ID = 0; + NONE = 0; + ENET_IS_RELIABLE = 1; + IS_ALLOW_CLIENT = 1; + CMD_ID = 2401; + } + + uint32 floor_id = 1; + repeated TowerTeam tower_team_list = 2; +} diff --git a/proto/TowerTeamSelectRsp.proto b/proto/TowerTeamSelectRsp.proto new file mode 100644 index 000000000..b135e5364 --- /dev/null +++ b/proto/TowerTeamSelectRsp.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +message TowerTeamSelectRsp { + enum CmdId { + option allow_alias = true; + NONE = 0; + ENET_CHANNEL_ID = 0; + ENET_IS_RELIABLE = 1; + CMD_ID = 2494; + } + + int32 retcode = 1; +} diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index e97e1e7de..c267a9b74 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -68,7 +68,9 @@ public class GameData { private static final Int2ObjectMap shopGoodsDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap combineDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap rewardPreviewDataMap = new Int2ObjectOpenHashMap<>(); - + private static final Int2ObjectMap towerFloorDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap towerLevelDataMap = new Int2ObjectOpenHashMap<>(); + // Cache private static Map> fetters = new HashMap<>(); private static Map> shopGoods = new HashMap<>(); @@ -313,4 +315,11 @@ public class GameData { public static Int2ObjectMap getCombineDataMap() { return combineDataMap; } + + public static Int2ObjectMap getTowerFloorDataMap(){ + return towerFloorDataMap; + } + public static Int2ObjectMap getTowerLevelDataMap(){ + return towerLevelDataMap; + } } diff --git a/src/main/java/emu/grasscutter/data/def/TowerFloorData.java b/src/main/java/emu/grasscutter/data/def/TowerFloorData.java new file mode 100644 index 000000000..d9d0082c7 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/def/TowerFloorData.java @@ -0,0 +1,73 @@ +package emu.grasscutter.data.def; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "TowerFloorExcelConfigData.json") +public class TowerFloorData extends GameResource { + + private int FloorId; + private int FloorIndex; + private int LevelId; + private int OverrideMonsterLevel; + private int TeamNum; + private int FloorLevelConfigId; + + @Override + public int getId() { + return this.FloorId; + } + + @Override + public void onLoad() { + super.onLoad(); + } + + public int getFloorId() { + return FloorId; + } + + public void setFloorId(int floorId) { + FloorId = floorId; + } + + public int getFloorIndex() { + return FloorIndex; + } + + public void setFloorIndex(int floorIndex) { + FloorIndex = floorIndex; + } + + public int getLevelId() { + return LevelId; + } + + public void setLevelId(int levelId) { + LevelId = levelId; + } + + public int getOverrideMonsterLevel() { + return OverrideMonsterLevel; + } + + public void setOverrideMonsterLevel(int overrideMonsterLevel) { + OverrideMonsterLevel = overrideMonsterLevel; + } + + public int getTeamNum() { + return TeamNum; + } + + public void setTeamNum(int teamNum) { + TeamNum = teamNum; + } + + public int getFloorLevelConfigId() { + return FloorLevelConfigId; + } + + public void setFloorLevelConfigId(int floorLevelConfigId) { + FloorLevelConfigId = floorLevelConfigId; + } +} diff --git a/src/main/java/emu/grasscutter/data/def/TowerLevelData.java b/src/main/java/emu/grasscutter/data/def/TowerLevelData.java new file mode 100644 index 000000000..6cc45cc06 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/def/TowerLevelData.java @@ -0,0 +1,55 @@ +package emu.grasscutter.data.def; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; + +@ResourceType(name = "TowerLevelExcelConfigData.json") +public class TowerLevelData extends GameResource { + + private int ID; + private int LevelId; + private int LevelIndex; + private int DungeonId; + + @Override + public int getId() { + return this.ID; + } + + @Override + public void onLoad() { + super.onLoad(); + } + + public int getID() { + return ID; + } + + public void setID(int ID) { + this.ID = ID; + } + + public int getLevelId() { + return LevelId; + } + + public void setLevelId(int levelId) { + LevelId = levelId; + } + + public int getLevelIndex() { + return LevelIndex; + } + + public void setLevelIndex(int levelIndex) { + LevelIndex = levelIndex; + } + + public int getDungeonId() { + return DungeonId; + } + + public void setDungeonId(int dungeonId) { + DungeonId = dungeonId; + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java b/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java index c84ef8a22..e858decf8 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java +++ b/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java @@ -75,7 +75,8 @@ public class DungeonManager { prevPos.set(entry.getPointData().getTranPos()); } } - + // clean temp team if it has + player.getTeamManager().cleanTemporaryTeam(); // Transfer player back to world player.getWorld().transferPlayerToScene(player, prevScene, prevPos); player.sendPacket(new BasePacket(PacketOpcodes.PlayerQuitDungeonRsp)); diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index c76f46bf0..9099c04c9 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -26,6 +26,7 @@ import emu.grasscutter.game.props.EntityType; import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.game.shop.ShopLimit; import emu.grasscutter.game.managers.MapMarkManager.*; +import emu.grasscutter.game.tower.TowerManager; import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.World; import emu.grasscutter.net.packet.BasePacket; @@ -88,6 +89,8 @@ public class Player { @Transient private MessageHandler messageHandler; private TeamManager teamManager; + + private TowerManager towerManager; private PlayerGachaInfo gachaInfo; private PlayerProfile playerProfile; private boolean showAvatar; @@ -172,6 +175,7 @@ public class Player { this.nickname = "Traveler"; this.signature = ""; this.teamManager = new TeamManager(this); + this.towerManager = new TowerManager(this); this.birthday = new PlayerBirthday(); this.setProperty(PlayerProperty.PROP_PLAYER_LEVEL, 1); this.setProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE, 1); @@ -384,6 +388,10 @@ public class Player { return this.teamManager; } + public TowerManager getTowerManager() { + return towerManager; + } + public PlayerGachaInfo getGachaInfo() { return gachaInfo; } @@ -1020,6 +1028,9 @@ public class Player { if (this.getProfile().getUid() == 0) { this.getProfile().syncWithCharacter(this); } + if (this.getTowerManager() == null) { + this.towerManager = new TowerManager(this); + } // Check if player object exists in server // TODO - optimize diff --git a/src/main/java/emu/grasscutter/game/player/TeamInfo.java b/src/main/java/emu/grasscutter/game/player/TeamInfo.java index 5c66f1aaa..5794a7913 100644 --- a/src/main/java/emu/grasscutter/game/player/TeamInfo.java +++ b/src/main/java/emu/grasscutter/game/player/TeamInfo.java @@ -18,6 +18,11 @@ public class TeamInfo { this.avatars = new ArrayList<>(Grasscutter.getConfig().getGameServerOptions().MaxAvatarsInTeam); } + public TeamInfo(List avatars) { + this.name = ""; + this.avatars = avatars; + } + public String getName() { return name; } diff --git a/src/main/java/emu/grasscutter/game/player/TeamManager.java b/src/main/java/emu/grasscutter/game/player/TeamManager.java index 666c44dee..4e371b126 100644 --- a/src/main/java/emu/grasscutter/game/player/TeamManager.java +++ b/src/main/java/emu/grasscutter/game/player/TeamManager.java @@ -1,12 +1,6 @@ package emu.grasscutter.game.player; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import dev.morphia.annotations.Entity; import dev.morphia.annotations.Transient; @@ -58,7 +52,13 @@ public class TeamManager { @Transient private final Set gadgets; @Transient private final IntSet teamResonances; @Transient private final IntSet teamResonancesConfig; - + + private int useTemporarilyTeamIndex = -1; + /** + * Temporary Team for tower + */ + private List temporaryTeam; + public TeamManager() { this.mpTeam = new TeamInfo(); this.avatars = new ArrayList<>(); @@ -124,6 +124,10 @@ public class TeamManager { } public TeamInfo getCurrentTeamInfo() { + if (useTemporarilyTeamIndex >= 0 && + useTemporarilyTeamIndex < temporaryTeam.size()){ + return temporaryTeam.get(useTemporarilyTeamIndex); + } if (this.getPlayer().isInMultiplayer()) { return this.getMpTeam(); } @@ -351,7 +355,51 @@ public class TeamManager { // Packet this.updateTeamEntities(new PacketChangeMpTeamAvatarRsp(getPlayer(), teamInfo)); } - + + public void setupTemporaryTeam(List> guidList) { + var team = guidList.stream().map(list -> { + // Sanity checks + if (list.size() == 0 || list.size() > getMaxTeamSize()) { + return null; + } + + // Set team data + LinkedHashSet newTeam = new LinkedHashSet<>(); + for (int i = 0; i < list.size(); i++) { + Avatar avatar = getPlayer().getAvatars().getAvatarByGuid(list.get(i)); + if (avatar == null || newTeam.contains(avatar)) { + // Should never happen + return null; + } + newTeam.add(avatar); + } + + // convert to avatar ids + return newTeam.stream() + .map(Avatar::getAvatarId) + .toList(); + }) + .filter(Objects::nonNull) + .map(TeamInfo::new) + .toList(); + this.temporaryTeam = team; + } + + public void useTemporaryTeam(int index) { + this.useTemporarilyTeamIndex = index; + updateTeamEntities(null); + } + + public void cleanTemporaryTeam() { + // check if using temporary team + if(useTemporarilyTeamIndex < 0){ + return; + } + + this.useTemporarilyTeamIndex = -1; + this.temporaryTeam = null; + updateTeamEntities(null); + } public synchronized void setCurrentTeam(int teamId) { // if (getPlayer().isInMultiplayer()) { diff --git a/src/main/java/emu/grasscutter/game/tower/TowerManager.java b/src/main/java/emu/grasscutter/game/tower/TowerManager.java new file mode 100644 index 000000000..e49a15cc2 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/tower/TowerManager.java @@ -0,0 +1,40 @@ +package emu.grasscutter.game.tower; + +import dev.morphia.annotations.Entity; +import emu.grasscutter.data.GameData; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.packet.send.PacketTowerEnterLevelRsp; + +import java.util.List; + +@Entity +public class TowerManager { + private final Player player; + + public TowerManager(Player player) { + this.player = player; + } + private int currentLevel; + private int currentFloor; + + public void teamSelect(int floor, List> towerTeams) { + var floorData = GameData.getTowerFloorDataMap().get(floor); + + this.currentFloor = floorData.getFloorId(); + this.currentLevel = floorData.getLevelId(); + + player.getTeamManager().setupTemporaryTeam(towerTeams); + } + + + public void enterLevel(int enterPointId) { + var levelData = GameData.getTowerLevelDataMap().get(currentLevel); + var id = levelData.getDungeonId(); + // use team user choose + player.getTeamManager().useTemporaryTeam(0); + player.getServer().getDungeonManager() + .enterDungeon(player, enterPointId, id); + + player.getSession().send(new PacketTowerEnterLevelRsp(currentFloor, currentLevel)); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerEnterLevelReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerEnterLevelReq.java new file mode 100644 index 000000000..163f101ed --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerEnterLevelReq.java @@ -0,0 +1,21 @@ +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.TowerEnterLevelReqOuterClass.TowerEnterLevelReq; +import emu.grasscutter.server.game.GameSession; + +@Opcodes(PacketOpcodes.TowerEnterLevelReq) +public class HandlerTowerEnterLevelReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + TowerEnterLevelReq req = TowerEnterLevelReq.parseFrom(payload); + + //session.send(new PacketTowerCurLevelRecordChangeNotify()); + session.getPlayer().getTowerManager().enterLevel(req.getEnterPointId()); + + //session.send(new PacketTowerLevelStarCondNotify()); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerTeamSelectReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerTeamSelectReq.java new file mode 100644 index 000000000..6e6705379 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerTowerTeamSelectReq.java @@ -0,0 +1,26 @@ +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.TowerTeamOuterClass; +import emu.grasscutter.net.proto.TowerTeamSelectReqOuterClass.TowerTeamSelectReq; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketTowerTeamSelectRsp; + +@Opcodes(PacketOpcodes.TowerTeamSelectReq) +public class HandlerTowerTeamSelectReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + TowerTeamSelectReq req = TowerTeamSelectReq.parseFrom(payload); + + var towerTeams = req.getTowerTeamListList().stream() + .map(TowerTeamOuterClass.TowerTeam::getAvatarGuidListList) + .toList(); + + session.getPlayer().getTowerManager().teamSelect(req.getFloorId(), towerTeams); + + session.send(new PacketTowerTeamSelectRsp()); + } +} 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 2bd1d0171..d2d2376e6 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerAllDataRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerAllDataRsp.java @@ -1,19 +1,28 @@ package emu.grasscutter.server.packet.send; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.def.TowerFloorData; 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 java.util.stream.Collectors; + public class PacketTowerAllDataRsp extends BasePacket { public PacketTowerAllDataRsp() { super(PacketOpcodes.TowerAllDataRsp); - + + var list = GameData.getTowerFloorDataMap().values().stream() + .map(TowerFloorData::getFloorId) + .map(id -> TowerFloorRecord.newBuilder().setFloorId(id).build()) + .collect(Collectors.toList()); + TowerAllDataRsp proto = TowerAllDataRsp.newBuilder() .setTowerScheduleId(29) - .addTowerFloorRecordList(TowerFloorRecord.newBuilder().setFloorId(1001)) + .addAllTowerFloorRecordList(list) .setCurLevelRecord(TowerCurLevelRecord.newBuilder().setIsEmpty(true)) .setNextScheduleChangeTime(Integer.MAX_VALUE) .putFloorOpenTimeMap(1024, 1630486800) diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerEnterLevelRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerEnterLevelRsp.java new file mode 100644 index 000000000..ebb8fb2b2 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerEnterLevelRsp.java @@ -0,0 +1,22 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerEnterLevelRspOuterClass.TowerEnterLevelRsp; + +public class PacketTowerEnterLevelRsp extends BasePacket { + + public PacketTowerEnterLevelRsp(int floorId, int levelIndex) { + super(PacketOpcodes.TowerEnterLevelRsp); + + TowerEnterLevelRsp proto = TowerEnterLevelRsp.newBuilder() + .setFloorId(floorId) + .setLevelIndex(levelIndex) + .addTowerBuffIdList(4) + .addTowerBuffIdList(28) + .addTowerBuffIdList(18) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerTeamSelectRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerTeamSelectRsp.java new file mode 100644 index 000000000..445b707cd --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerTeamSelectRsp.java @@ -0,0 +1,17 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerTeamSelectRspOuterClass.TowerTeamSelectRsp; + +public class PacketTowerTeamSelectRsp extends BasePacket { + + public PacketTowerTeamSelectRsp() { + super(PacketOpcodes.TowerTeamSelectRsp); + + TowerTeamSelectRsp proto = TowerTeamSelectRsp.newBuilder() + .build(); + + this.setData(proto); + } +} From a79e00896cb99b783cb0bcef48a431a26da4cc24 Mon Sep 17 00:00:00 2001 From: Akka <104902222+Akka0@users.noreply.github.com> Date: Fri, 6 May 2022 14:46:10 +0800 Subject: [PATCH 3/6] Add @Transient for temporary team --- src/main/java/emu/grasscutter/game/player/TeamManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/emu/grasscutter/game/player/TeamManager.java b/src/main/java/emu/grasscutter/game/player/TeamManager.java index 4e371b126..8b8a10355 100644 --- a/src/main/java/emu/grasscutter/game/player/TeamManager.java +++ b/src/main/java/emu/grasscutter/game/player/TeamManager.java @@ -53,11 +53,11 @@ public class TeamManager { @Transient private final IntSet teamResonances; @Transient private final IntSet teamResonancesConfig; - private int useTemporarilyTeamIndex = -1; + @Transient private int useTemporarilyTeamIndex = -1; /** * Temporary Team for tower */ - private List temporaryTeam; + @Transient private List temporaryTeam; public TeamManager() { this.mpTeam = new TeamInfo(); From 6144f4712789c35d357daae7003cf3609cb760f6 Mon Sep 17 00:00:00 2001 From: Akka <104902222+Akka0@users.noreply.github.com> Date: Sat, 7 May 2022 00:11:54 +0800 Subject: [PATCH 4/6] Tower Dungeons Handoff between level and floor --- proto/DungeonSettleNotify.proto | 5 ++ proto/TowerFloorRecordChangeNotify.proto | 18 +++++ proto/TowerLevelEndNotify.proto | 26 +++++++ .../dungeons/BasicDungeonSettleListener.java | 14 ++++ .../game/dungeons/DungeonChallenge.java | 19 ++--- .../game/dungeons/DungeonManager.java | 28 ++++++- .../game/dungeons/DungeonSettleListener.java | 7 ++ .../dungeons/TowerDungeonSettleListener.java | 24 ++++++ .../emu/grasscutter/game/player/Player.java | 6 ++ .../grasscutter/game/tower/TowerManager.java | 78 ++++++++++++++++--- .../emu/grasscutter/game/world/Scene.java | 17 +++- .../send/PacketDungeonSettleNotify.java | 41 ++++++++++ ...PacketTowerCurLevelRecordChangeNotify.java | 23 ++++++ .../PacketTowerFloorRecordChangeNotify.java | 30 +++++++ 14 files changed, 306 insertions(+), 30 deletions(-) create mode 100644 proto/TowerFloorRecordChangeNotify.proto create mode 100644 proto/TowerLevelEndNotify.proto create mode 100644 src/main/java/emu/grasscutter/game/dungeons/BasicDungeonSettleListener.java create mode 100644 src/main/java/emu/grasscutter/game/dungeons/DungeonSettleListener.java create mode 100644 src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketTowerCurLevelRecordChangeNotify.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java diff --git a/proto/DungeonSettleNotify.proto b/proto/DungeonSettleNotify.proto index c190b38e7..c48ab8f6f 100644 --- a/proto/DungeonSettleNotify.proto +++ b/proto/DungeonSettleNotify.proto @@ -4,8 +4,13 @@ option java_package = "emu.grasscutter.net.proto"; import "ParamList.proto"; import "StrengthenPointData.proto"; +import "TowerLevelEndNotify.proto"; message DungeonSettleNotify { + oneof Detail { + TowerLevelEndNotify tower_level_end_notify = 101; + // it has more! + } uint32 dungeon_id = 1; bool is_success = 2; repeated uint32 fail_cond_list = 3; diff --git a/proto/TowerFloorRecordChangeNotify.proto b/proto/TowerFloorRecordChangeNotify.proto new file mode 100644 index 000000000..74a7135ec --- /dev/null +++ b/proto/TowerFloorRecordChangeNotify.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; + +import "TowerFloorRecord.proto"; + +message TowerFloorRecordChangeNotify { + enum CmdId { + option allow_alias = true; + NONE = 0; + ENET_CHANNEL_ID = 0; + ENET_IS_RELIABLE = 1; + CMD_ID = 2418; + } + + repeated TowerFloorRecord tower_floor_record_list = 1; + bool is_finished_entrance_floor = 2; +} diff --git a/proto/TowerLevelEndNotify.proto b/proto/TowerLevelEndNotify.proto new file mode 100644 index 000000000..d9f2da543 --- /dev/null +++ b/proto/TowerLevelEndNotify.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; + +option java_package = "emu.grasscutter.net.proto"; +import "ItemParam.proto"; + +message TowerLevelEndNotify { + enum CmdId { + option allow_alias = true; + NONE = 0; + ENET_CHANNEL_ID = 0; + ENET_IS_RELIABLE = 1; + CMD_ID = 2456; + } + + enum ContinueStateType { + CONTINUE_STATE_CAN_NOT_CONTINUE = 0; + CONTINUE_STATE_CAN_ENTER_NEXT_LEVEL = 1; + CONTINUE_STATE_CAN_ENTER_NEXT_FLOOR = 2; + } + + bool is_success = 1; + repeated uint32 finished_star_cond_list = 2; + repeated ItemParam reward_item_list = 3; + uint32 continue_state = 4; + uint32 next_floor_id = 5; +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/BasicDungeonSettleListener.java b/src/main/java/emu/grasscutter/game/dungeons/BasicDungeonSettleListener.java new file mode 100644 index 000000000..5b5e243bd --- /dev/null +++ b/src/main/java/emu/grasscutter/game/dungeons/BasicDungeonSettleListener.java @@ -0,0 +1,14 @@ +package emu.grasscutter.game.dungeons; + +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.server.packet.send.PacketDungeonSettleNotify; +import emu.grasscutter.utils.Utils; + +public class BasicDungeonSettleListener implements DungeonSettleListener { + + @Override + public void onDungeonSettle(Scene scene) { + scene.setAutoCloseTime(Utils.getCurrentSeconds() + 1000); + scene.broadcastPacket(new PacketDungeonSettleNotify(scene.getChallenge())); + } +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java b/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java index b9724f49a..2e07f0058 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java +++ b/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java @@ -1,33 +1,25 @@ package emu.grasscutter.game.dungeons; -import java.util.ArrayList; -import java.util.List; - -import emu.grasscutter.data.GameData; import emu.grasscutter.data.common.ItemParamData; import emu.grasscutter.data.def.DungeonData; -import emu.grasscutter.data.def.MonsterData; import emu.grasscutter.game.entity.EntityMonster; -import emu.grasscutter.game.entity.GameEntity; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.world.Scene; -import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType; import emu.grasscutter.scripts.constants.EventType; import emu.grasscutter.scripts.data.SceneGroup; -import emu.grasscutter.scripts.data.SceneMonster; import emu.grasscutter.scripts.data.ScriptArgs; import emu.grasscutter.server.packet.send.PacketChallengeDataNotify; import emu.grasscutter.server.packet.send.PacketDungeonChallengeBeginNotify; import emu.grasscutter.server.packet.send.PacketDungeonChallengeFinishNotify; -import emu.grasscutter.server.packet.send.PacketDungeonSettleNotify; import emu.grasscutter.server.packet.send.PacketGadgetAutoPickDropInfoNotify; -import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify; -import emu.grasscutter.utils.Utils; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; +import java.util.ArrayList; +import java.util.List; + public class DungeonChallenge { private final Scene scene; private final SceneGroup group; @@ -40,7 +32,7 @@ public class DungeonChallenge { private int score; private int objective = 0; private IntSet rewardedPlayers; - + public DungeonChallenge(Scene scene, SceneGroup group) { this.scene = scene; this.group = group; @@ -129,8 +121,7 @@ public class DungeonChallenge { } private void settle() { - getScene().setAutoCloseTime(Utils.getCurrentSeconds() + 1000); - getScene().broadcastPacket(new PacketDungeonSettleNotify(this)); + getScene().getDungeonSettleObservers().forEach(o -> o.onDungeonSettle(getScene())); getScene().getScriptManager().callEvent(EventType.EVENT_DUNGEON_SETTLE, new ScriptArgs(this.isSuccess() ? 1 : 0)); } diff --git a/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java b/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java index e858decf8..f4b16c811 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java +++ b/src/main/java/emu/grasscutter/game/dungeons/DungeonManager.java @@ -14,9 +14,11 @@ import emu.grasscutter.server.packet.send.PacketDungeonEntryInfoRsp; import emu.grasscutter.server.packet.send.PacketPlayerEnterDungeonRsp; import emu.grasscutter.utils.Position; +import java.util.List; + public class DungeonManager { private final GameServer server; - + private static final BasicDungeonSettleListener basicDungeonSettleObserver = new BasicDungeonSettleListener(); public DungeonManager(GameServer server) { this.server = server; } @@ -49,13 +51,32 @@ public class DungeonManager { int sceneId = data.getSceneId(); player.getScene().setPrevScene(sceneId); - player.getWorld().transferPlayerToScene(player, sceneId, data); + if(player.getWorld().transferPlayerToScene(player, sceneId, data)){ + player.getScene().addDungeonSettleObserver(basicDungeonSettleObserver); + } player.getScene().setPrevScenePoint(pointId); player.sendPacket(new PacketPlayerEnterDungeonRsp(pointId, dungeonId)); return true; } - + + /** + * used in tower dungeons handoff + */ + public boolean handoffDungeon(Player player, int dungeonId, List dungeonSettleListeners) { + DungeonData data = GameData.getDungeonDataMap().get(dungeonId); + + if (data == null) { + return false; + } + Grasscutter.getLogger().info(player.getNickname() + " is trying to enter tower dungeon " + dungeonId); + + if(player.getWorld().transferPlayerToScene(player, data.getSceneId(), data)){ + dungeonSettleListeners.forEach(player.getScene()::addDungeonSettleObserver); + } + return true; + } + public void exitDungeon(Player player) { if (player.getScene().getSceneType() != SceneType.SCENE_DUNGEON) { return; @@ -77,6 +98,7 @@ public class DungeonManager { } // clean temp team if it has player.getTeamManager().cleanTemporaryTeam(); + player.getTowerManager().clearEntry(); // Transfer player back to world player.getWorld().transferPlayerToScene(player, prevScene, prevPos); player.sendPacket(new BasePacket(PacketOpcodes.PlayerQuitDungeonRsp)); diff --git a/src/main/java/emu/grasscutter/game/dungeons/DungeonSettleListener.java b/src/main/java/emu/grasscutter/game/dungeons/DungeonSettleListener.java new file mode 100644 index 000000000..2eb389e05 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/dungeons/DungeonSettleListener.java @@ -0,0 +1,7 @@ +package emu.grasscutter.game.dungeons; + +import emu.grasscutter.game.world.Scene; + +public interface DungeonSettleListener { + void onDungeonSettle(Scene scene); +} diff --git a/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java b/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java new file mode 100644 index 000000000..5b1ff7a30 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java @@ -0,0 +1,24 @@ +package emu.grasscutter.game.dungeons; + +import emu.grasscutter.game.world.Scene; +import emu.grasscutter.server.packet.send.PacketDungeonSettleNotify; +import emu.grasscutter.server.packet.send.PacketTowerFloorRecordChangeNotify; +import emu.grasscutter.utils.Utils; + +public class TowerDungeonSettleListener implements DungeonSettleListener { + + @Override + public void onDungeonSettle(Scene scene) { + 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.hasNextLevel(), + towerManager.getNextFloorId() + )); + + } +} diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index 971fbf2ac..7a09f1ecb 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -25,6 +25,7 @@ import emu.grasscutter.game.managers.MotionManager.MotionManager; import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.props.EntityType; import emu.grasscutter.game.props.PlayerProperty; +import emu.grasscutter.game.props.SceneType; import emu.grasscutter.game.shop.ShopLimit; import emu.grasscutter.game.managers.MapMarkManager.*; import emu.grasscutter.game.tower.TowerManager; @@ -1048,6 +1049,7 @@ public class Player { @PostLoad private void onLoad() { this.getTeamManager().setPlayer(this); + this.getTowerManager().setPlayer(this); } public void save() { @@ -1117,6 +1119,10 @@ public class Player { } public void onLogout() { + // force to leave the dungeon + if(getScene().getSceneType() == SceneType.SCENE_DUNGEON){ + this.getServer().getDungeonManager().exitDungeon(this); + } // Leave world if (this.getWorld() != null) { this.getWorld().removePlayer(this); diff --git a/src/main/java/emu/grasscutter/game/tower/TowerManager.java b/src/main/java/emu/grasscutter/game/tower/TowerManager.java index e49a15cc2..144443c87 100644 --- a/src/main/java/emu/grasscutter/game/tower/TowerManager.java +++ b/src/main/java/emu/grasscutter/game/tower/TowerManager.java @@ -1,40 +1,100 @@ package emu.grasscutter.game.tower; import dev.morphia.annotations.Entity; +import dev.morphia.annotations.Transient; import emu.grasscutter.data.GameData; +import emu.grasscutter.data.def.TowerLevelData; +import emu.grasscutter.game.dungeons.DungeonSettleListener; +import emu.grasscutter.game.dungeons.TowerDungeonSettleListener; import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.packet.send.PacketTowerCurLevelRecordChangeNotify; import emu.grasscutter.server.packet.send.PacketTowerEnterLevelRsp; import java.util.List; @Entity public class TowerManager { - private final Player player; + @Transient + private Player player; public TowerManager(Player player) { this.player = player; } - private int currentLevel; - private int currentFloor; + public void setPlayer(Player player) { + this.player = player; + } + private int currentFloorId; + private int currentLevel; + @Transient + private int currentLevelId; + + @Transient + private int entryScene; + + public int getCurrentFloorId() { + return currentFloorId; + } + + private static final List towerDungeonSettleListener = List.of(new TowerDungeonSettleListener()); public void teamSelect(int floor, List> towerTeams) { var floorData = GameData.getTowerFloorDataMap().get(floor); - this.currentFloor = floorData.getFloorId(); - this.currentLevel = floorData.getLevelId(); + this.currentFloorId = floorData.getFloorId(); + this.currentLevel = 0; + this.currentLevelId = GameData.getTowerLevelDataMap().values().stream() + .filter(x -> x.getLevelId() == floorData.getLevelId() && x.getLevelIndex() == 1) + .findFirst() + .map(TowerLevelData::getID) + .orElse(0); + + if (entryScene == 0){ + entryScene = player.getSceneId(); + } player.getTeamManager().setupTemporaryTeam(towerTeams); } public void enterLevel(int enterPointId) { - var levelData = GameData.getTowerLevelDataMap().get(currentLevel); + var levelData = GameData.getTowerLevelDataMap().get(currentLevelId + currentLevel); + + this.currentLevel++; var id = levelData.getDungeonId(); + + notifyCurLevelRecordChange(); // use team user choose player.getTeamManager().useTemporaryTeam(0); - player.getServer().getDungeonManager() - .enterDungeon(player, enterPointId, id); + player.getServer().getDungeonManager().handoffDungeon(player, id, + towerDungeonSettleListener); - player.getSession().send(new PacketTowerEnterLevelRsp(currentFloor, currentLevel)); + // make sure user can exit dungeon correctly + player.getScene().setPrevScene(entryScene); + player.getScene().setPrevScenePoint(enterPointId); + + player.getSession().send(new PacketTowerEnterLevelRsp(currentFloorId, currentLevel)); + + } + + public void notifyCurLevelRecordChange(){ + player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, currentLevel)); + } + public void notifyCurLevelRecordChangeWhenDone(){ + player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, currentLevel + 1)); + } + public boolean hasNextLevel(){ + return this.currentLevel < 3; + } + + public int getNextFloorId() { + if(hasNextLevel()){ + return 0; + } + this.currentFloorId++; + return this.currentFloorId; + } + + public void clearEntry() { + this.entryScene = 0; } } diff --git a/src/main/java/emu/grasscutter/game/world/Scene.java b/src/main/java/emu/grasscutter/game/world/Scene.java index 7aa4d3f8a..97099c9b9 100644 --- a/src/main/java/emu/grasscutter/game/world/Scene.java +++ b/src/main/java/emu/grasscutter/game/world/Scene.java @@ -1,6 +1,5 @@ package emu.grasscutter.game.world; -import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; import emu.grasscutter.data.GameDepot; import emu.grasscutter.data.def.DungeonData; @@ -8,6 +7,7 @@ import emu.grasscutter.data.def.MonsterData; import emu.grasscutter.data.def.SceneData; import emu.grasscutter.data.def.WorldLevelData; import emu.grasscutter.game.dungeons.DungeonChallenge; +import emu.grasscutter.game.dungeons.DungeonSettleListener; import emu.grasscutter.game.entity.*; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.TeamInfo; @@ -20,11 +20,8 @@ import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType; import emu.grasscutter.scripts.SceneScriptManager; -import emu.grasscutter.scripts.constants.EventType; import emu.grasscutter.scripts.data.SceneBlock; -import emu.grasscutter.scripts.data.SceneGadget; import emu.grasscutter.scripts.data.SceneGroup; -import emu.grasscutter.scripts.data.ScriptArgs; import emu.grasscutter.server.packet.send.PacketAvatarSkillInfoNotify; import emu.grasscutter.server.packet.send.PacketDungeonChallengeFinishNotify; import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; @@ -56,6 +53,7 @@ public class Scene { private SceneScriptManager scriptManager; private DungeonChallenge challenge; + private List dungeonSettleListeners; private DungeonData dungeonData; private int prevScene; // Id of the previous scene private int prevScenePoint; @@ -205,6 +203,17 @@ public class Scene { this.challenge = challenge; } + public void addDungeonSettleObserver(DungeonSettleListener dungeonSettleListener){ + if(dungeonSettleListeners == null){ + dungeonSettleListeners = new ArrayList<>(); + } + dungeonSettleListeners.add(dungeonSettleListener); + } + + public List getDungeonSettleObservers() { + return dungeonSettleListeners; + } + public boolean isInScene(GameEntity entity) { return this.entities.containsKey(entity.getId()); } 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 411be291a..479029243 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonSettleNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDungeonSettleNotify.java @@ -4,6 +4,8 @@ import emu.grasscutter.game.dungeons.DungeonChallenge; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.DungeonSettleNotifyOuterClass.DungeonSettleNotify; +import emu.grasscutter.net.proto.ItemParamOuterClass; +import emu.grasscutter.net.proto.TowerLevelEndNotifyOuterClass.TowerLevelEndNotify; public class PacketDungeonSettleNotify extends BasePacket { @@ -19,4 +21,43 @@ public class PacketDungeonSettleNotify extends BasePacket { this.setData(proto); } + + public PacketDungeonSettleNotify(DungeonChallenge challenge, + boolean canJump, + boolean hasNextLevel, + int nextFloorId + ) { + super(PacketOpcodes.DungeonSettleNotify); + + var continueStatus = TowerLevelEndNotify.ContinueStateType.CONTINUE_STATE_CAN_NOT_CONTINUE_VALUE; + if(challenge.isSuccess() && canJump){ + continueStatus = hasNextLevel ? TowerLevelEndNotify.ContinueStateType.CONTINUE_STATE_CAN_ENTER_NEXT_LEVEL_VALUE + : TowerLevelEndNotify.ContinueStateType.CONTINUE_STATE_CAN_ENTER_NEXT_FLOOR_VALUE; + } + + var towerLevelEndNotify = TowerLevelEndNotify.newBuilder() + .setIsSuccess(challenge.isSuccess()) + .setContinueState(continueStatus) + .addFinishedStarCondList(1) + .addFinishedStarCondList(2) + .addFinishedStarCondList(3) + .addRewardItemList(ItemParamOuterClass.ItemParam.newBuilder() + .setItemId(201) + .setCount(1000) + .build()) + ; + if(nextFloorId > 0){ + towerLevelEndNotify.setNextFloorId(nextFloorId); + } + + DungeonSettleNotify proto = DungeonSettleNotify.newBuilder() + .setDungeonId(challenge.getScene().getDungeonData().getId()) + .setIsSuccess(challenge.isSuccess()) + .setCloseTime(challenge.getScene().getAutoCloseTime()) + .setResult(challenge.isSuccess() ? 1 : 0) + .setTowerLevelEndNotify(towerLevelEndNotify.build()) + .build(); + + this.setData(proto); + } } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerCurLevelRecordChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerCurLevelRecordChangeNotify.java new file mode 100644 index 000000000..fdae92555 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerCurLevelRecordChangeNotify.java @@ -0,0 +1,23 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerCurLevelRecordChangeNotifyOuterClass.TowerCurLevelRecordChangeNotify; +import emu.grasscutter.net.proto.TowerCurLevelRecordOuterClass.TowerCurLevelRecord; + +public class PacketTowerCurLevelRecordChangeNotify extends BasePacket { + + public PacketTowerCurLevelRecordChangeNotify(int curFloorId, int curLevelIndex) { + super(PacketOpcodes.TowerCurLevelRecordChangeNotify); + + TowerCurLevelRecordChangeNotify proto = TowerCurLevelRecordChangeNotify.newBuilder() + .setCurLevelRecord(TowerCurLevelRecord.newBuilder() + .setCurFloorId(curFloorId) + .setCurLevelIndex(curLevelIndex) + // TODO team info + .build()) + .build(); + + this.setData(proto); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java new file mode 100644 index 000000000..c0ed414a8 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketTowerFloorRecordChangeNotify.java @@ -0,0 +1,30 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.TowerFloorRecordChangeNotifyOuterClass.TowerFloorRecordChangeNotify; +import emu.grasscutter.net.proto.TowerFloorRecordOuterClass.TowerFloorRecord; +import emu.grasscutter.net.proto.TowerLevelRecordOuterClass.TowerLevelRecord; + +public class PacketTowerFloorRecordChangeNotify extends BasePacket { + + public PacketTowerFloorRecordChangeNotify(int floorId) { + super(PacketOpcodes.TowerFloorRecordChangeNotify); + + TowerFloorRecordChangeNotify proto = TowerFloorRecordChangeNotify.newBuilder() + .addTowerFloorRecordList(TowerFloorRecord.newBuilder() + .setFloorId(floorId) + .setFloorStarRewardProgress(3) + .addPassedLevelRecordList(TowerLevelRecord.newBuilder() + .setLevelId(1) + .addSatisfiedCondList(1) + .addSatisfiedCondList(2) + .addSatisfiedCondList(3) + .build()) + .build()) + .setIsFinishedEntranceFloor(true) + .build(); + + this.setData(proto); + } +} From 81ca86092c17289f16e63ef52f67e47db444a662 Mon Sep 17 00:00:00 2001 From: Akka <104902222+Akka0@users.noreply.github.com> Date: Sat, 7 May 2022 00:15:23 +0800 Subject: [PATCH 5/6] Add some lua functions --- .../java/emu/grasscutter/scripts/ScriptLib.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/emu/grasscutter/scripts/ScriptLib.java b/src/main/java/emu/grasscutter/scripts/ScriptLib.java index e75920579..941b00b60 100644 --- a/src/main/java/emu/grasscutter/scripts/ScriptLib.java +++ b/src/main/java/emu/grasscutter/scripts/ScriptLib.java @@ -207,4 +207,19 @@ public class ScriptLib { public void PrintContextLog(String msg) { Grasscutter.getLogger().info("[LUA] " + msg); } + + public int TowerCountTimeStatus(int var1, int var2){ + return 0; + } + public int GetGroupMonsterCount(int var1){ + // Maybe... + return GetGroupMonsterCountByGroupId(var1); + } + public int SetMonsterBattleByGroup(int var1, int var2, int var3){ + return 0; + } + + public int CauseDungeonFail(int var1){ + return 0; + } } From 22df34606c41ed81b6a8433377158a1f79a836d3 Mon Sep 17 00:00:00 2001 From: Akka <104902222+Akka0@users.noreply.github.com> Date: Sat, 7 May 2022 00:31:48 +0800 Subject: [PATCH 6/6] a little fix --- src/main/java/emu/grasscutter/game/tower/TowerManager.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/emu/grasscutter/game/tower/TowerManager.java b/src/main/java/emu/grasscutter/game/tower/TowerManager.java index 116861dd8..51f840663 100644 --- a/src/main/java/emu/grasscutter/game/tower/TowerManager.java +++ b/src/main/java/emu/grasscutter/game/tower/TowerManager.java @@ -15,9 +15,7 @@ import java.util.List; @Entity public class TowerManager { - - @Transient private final Player player; - + @Transient private Player player; public TowerManager(Player player) { this.player = player;