mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-27 07:34:27 +00:00
Implement dungeon entry
This commit is contained in:
parent
472e771dc8
commit
17addc1522
8
proto/PlayerEnterDungeonReq.proto
Normal file
8
proto/PlayerEnterDungeonReq.proto
Normal file
@ -0,0 +1,8 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option java_package = "emu.grasscutter.net.proto";
|
||||
|
||||
message PlayerEnterDungeonReq {
|
||||
uint32 point_id = 1;
|
||||
uint32 dungeon_id = 2;
|
||||
}
|
9
proto/PlayerEnterDungeonRsp.proto
Normal file
9
proto/PlayerEnterDungeonRsp.proto
Normal file
@ -0,0 +1,9 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option java_package = "emu.grasscutter.net.proto";
|
||||
|
||||
message PlayerEnterDungeonRsp {
|
||||
int32 retcode = 1;
|
||||
uint32 point_id = 2;
|
||||
uint32 dungeon_id = 3;
|
||||
}
|
8
proto/PlayerQuitDungeonReq.proto
Normal file
8
proto/PlayerQuitDungeonReq.proto
Normal file
@ -0,0 +1,8 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option java_package = "emu.grasscutter.net.proto";
|
||||
|
||||
message PlayerQuitDungeonReq {
|
||||
uint32 point_id = 1;
|
||||
bool is_quit_immediately = 2;
|
||||
}
|
8
proto/PlayerQuitDungeonRsp.proto
Normal file
8
proto/PlayerQuitDungeonRsp.proto
Normal file
@ -0,0 +1,8 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option java_package = "emu.grasscutter.net.proto";
|
||||
|
||||
message PlayerQuitDungeonRsp {
|
||||
int32 retcode = 1;
|
||||
uint32 point_id = 2;
|
||||
}
|
@ -61,6 +61,7 @@ public class GameData {
|
||||
private static final Int2ObjectMap<FetterCharacterCardData> fetterCharacterCardDataMap = new Int2ObjectOpenHashMap<>();
|
||||
private static final Int2ObjectMap<RewardData> rewardDataMap = new Int2ObjectOpenHashMap<>();
|
||||
private static final Int2ObjectMap<WorldLevelData> worldLevelDataMap = new Int2ObjectOpenHashMap<>();
|
||||
private static final Int2ObjectMap<DungeonData> dungeonDataMap = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
// Cache
|
||||
private static Map<Integer, List<Integer>> fetters = new HashMap<>();
|
||||
@ -98,6 +99,11 @@ public class GameData {
|
||||
return scenePointEntries;
|
||||
}
|
||||
|
||||
// TODO optimize
|
||||
public static ScenePointEntry getScenePointEntryById(int sceneId, int pointId) {
|
||||
return getScenePointEntries().get(sceneId + "_" + pointId);
|
||||
}
|
||||
|
||||
public static Int2ObjectMap<AvatarData> getAvatarDataMap() {
|
||||
return avatarDataMap;
|
||||
}
|
||||
@ -265,4 +271,8 @@ public class GameData {
|
||||
public static Int2ObjectMap<WorldLevelData> getWorldLevelDataMap() {
|
||||
return worldLevelDataMap;
|
||||
}
|
||||
|
||||
public static Int2ObjectMap<DungeonData> getDungeonDataMap() {
|
||||
return dungeonDataMap;
|
||||
}
|
||||
}
|
||||
|
@ -164,6 +164,7 @@ public class ResourceLoader {
|
||||
|
||||
for (Map.Entry<String, JsonElement> entry : config.points.entrySet()) {
|
||||
PointData pointData = Grasscutter.getGsonFactory().fromJson(entry.getValue(), PointData.class);
|
||||
pointData.setId(Integer.parseInt(entry.getKey()));
|
||||
|
||||
ScenePointEntry sl = new ScenePointEntry(sceneId + "_" + entry.getKey(), pointData);
|
||||
scenePointList.add(sl);
|
||||
|
@ -1,43 +1,30 @@
|
||||
package emu.grasscutter.data.common;
|
||||
|
||||
public class PointData {
|
||||
private pos tranPos;
|
||||
import emu.grasscutter.utils.Position;
|
||||
|
||||
public pos getTranPos() {
|
||||
public class PointData {
|
||||
private int id;
|
||||
private String $type;
|
||||
private Position tranPos;
|
||||
private int[] dungeonIds;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return $type;
|
||||
}
|
||||
|
||||
public Position getTranPos() {
|
||||
return tranPos;
|
||||
}
|
||||
|
||||
public void setTranPos(pos tranPos) {
|
||||
this.tranPos = tranPos;
|
||||
}
|
||||
|
||||
public class pos {
|
||||
private float x;
|
||||
private float y;
|
||||
private float z;
|
||||
|
||||
public float getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setX(float x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public float getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public void setY(float y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public float getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public void setZ(float z) {
|
||||
this.z = z;
|
||||
}
|
||||
public int[] getDungeonIds() {
|
||||
return dungeonIds;
|
||||
}
|
||||
}
|
||||
|
28
src/main/java/emu/grasscutter/data/def/DungeonData.java
Normal file
28
src/main/java/emu/grasscutter/data/def/DungeonData.java
Normal file
@ -0,0 +1,28 @@
|
||||
package emu.grasscutter.data.def;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.GameResource;
|
||||
import emu.grasscutter.data.ResourceType;
|
||||
|
||||
import emu.grasscutter.game.props.SceneType;
|
||||
|
||||
@ResourceType(name = "DungeonExcelConfigData.json")
|
||||
public class DungeonData extends GameResource {
|
||||
private int Id;
|
||||
private int SceneId;
|
||||
private String InvolveType; // TODO enum
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.Id;
|
||||
}
|
||||
|
||||
public int getSceneId() {
|
||||
return SceneId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
|
||||
}
|
||||
}
|
@ -9,16 +9,17 @@ import emu.grasscutter.game.props.SceneType;
|
||||
@ResourceType(name = "SceneExcelConfigData.json")
|
||||
public class SceneData extends GameResource {
|
||||
private int Id;
|
||||
private SceneType SceneType;
|
||||
private SceneType Type;
|
||||
private String ScriptData;
|
||||
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.Id;
|
||||
}
|
||||
|
||||
public SceneType getSceneType() {
|
||||
return SceneType;
|
||||
return Type;
|
||||
}
|
||||
|
||||
public String getScriptData() {
|
||||
|
@ -1,6 +1,18 @@
|
||||
package emu.grasscutter.game.dungeons;
|
||||
|
||||
import emu.grasscutter.GameConstants;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.custom.ScenePointEntry;
|
||||
import emu.grasscutter.data.def.DungeonData;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.SceneType;
|
||||
import emu.grasscutter.net.packet.BasePacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.server.game.GameServer;
|
||||
import emu.grasscutter.server.packet.send.PacketDungeonEntryInfoRsp;
|
||||
import emu.grasscutter.server.packet.send.PacketPlayerEnterDungeonRsp;
|
||||
import emu.grasscutter.utils.Position;
|
||||
|
||||
public class DungeonManager {
|
||||
private final GameServer server;
|
||||
@ -12,4 +24,55 @@ public class DungeonManager {
|
||||
public GameServer getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
public void getEntryInfo(Player player, int pointId) {
|
||||
ScenePointEntry entry = GameData.getScenePointEntryById(player.getScene().getId(), pointId);
|
||||
|
||||
if (entry == null || entry.getPointData().getDungeonIds() == null) {
|
||||
// Error
|
||||
player.sendPacket(new PacketDungeonEntryInfoRsp());
|
||||
return;
|
||||
}
|
||||
|
||||
player.sendPacket(new PacketDungeonEntryInfoRsp(player, entry.getPointData()));
|
||||
}
|
||||
|
||||
public void enterDungeon(Player player, int pointId, int dungeonId) {
|
||||
DungeonData data = GameData.getDungeonDataMap().get(dungeonId);
|
||||
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int sceneId = data.getSceneId();
|
||||
|
||||
player.getWorld().transferPlayerToScene(player, sceneId, data);
|
||||
|
||||
player.sendPacket(new PacketPlayerEnterDungeonRsp(pointId, dungeonId));
|
||||
}
|
||||
|
||||
public void exitDungeon(Player player) {
|
||||
if (player.getScene().getSceneType() != SceneType.SCENE_DUNGEON) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get previous scene
|
||||
int prevScene = player.getScene().getPrevScene() > 0 ? player.getScene().getPrevScene() : 3;
|
||||
|
||||
// Get previous position
|
||||
DungeonData dungeonData = player.getScene().getDungeonData();
|
||||
Position prevPos = new Position(GameConstants.START_POSITION);
|
||||
|
||||
if (dungeonData != null) {
|
||||
ScenePointEntry entry = GameData.getScenePointEntryById(prevScene, dungeonData.getId());
|
||||
|
||||
if (entry != null) {
|
||||
prevPos.set(entry.getPointData().getTranPos());
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer player back to world
|
||||
player.getWorld().transferPlayerToScene(player, prevScene, prevPos);
|
||||
player.sendPacket(new BasePacket(PacketOpcodes.PlayerQuitDungeonRsp));
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ 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;
|
||||
import emu.grasscutter.data.def.MonsterData;
|
||||
import emu.grasscutter.data.def.SceneData;
|
||||
import emu.grasscutter.data.def.WorldLevelData;
|
||||
@ -42,6 +43,9 @@ public class Scene {
|
||||
private ClimateType climate;
|
||||
private int weather;
|
||||
|
||||
private DungeonData dungeonData;
|
||||
private int prevScene; // Id of the previous scene
|
||||
|
||||
public Scene(World world, SceneData sceneData) {
|
||||
this.world = world;
|
||||
this.sceneData = sceneData;
|
||||
@ -50,6 +54,7 @@ public class Scene {
|
||||
|
||||
this.time = 8 * 60;
|
||||
this.climate = ClimateType.CLIMATE_SUNNY;
|
||||
this.prevScene = 3;
|
||||
|
||||
this.spawnedEntities = new HashSet<>();
|
||||
this.deadSpawnedEntities = new HashSet<>();
|
||||
@ -111,6 +116,14 @@ public class Scene {
|
||||
this.weather = weather;
|
||||
}
|
||||
|
||||
public int getPrevScene() {
|
||||
return prevScene;
|
||||
}
|
||||
|
||||
public void setPrevScene(int prevScene) {
|
||||
this.prevScene = prevScene;
|
||||
}
|
||||
|
||||
public boolean dontDestroyWhenEmpty() {
|
||||
return dontDestroyWhenEmpty;
|
||||
}
|
||||
@ -127,6 +140,17 @@ public class Scene {
|
||||
return deadSpawnedEntities;
|
||||
}
|
||||
|
||||
public DungeonData getDungeonData() {
|
||||
return dungeonData;
|
||||
}
|
||||
|
||||
public void setDungeonData(DungeonData dungeonData) {
|
||||
if (this.dungeonData != null || this.getSceneType() != SceneType.SCENE_DUNGEON || dungeonData.getSceneId() != this.getId()) {
|
||||
return;
|
||||
}
|
||||
this.dungeonData = dungeonData;
|
||||
}
|
||||
|
||||
public boolean isInScene(GameEntity entity) {
|
||||
return this.entities.containsKey(entity.getId());
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import emu.grasscutter.game.props.EntityIdType;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.props.LifeState;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.def.DungeonData;
|
||||
import emu.grasscutter.data.def.SceneData;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.entity.EntityClientGadget;
|
||||
@ -212,6 +213,14 @@ public class World implements Iterable<Player> {
|
||||
}
|
||||
|
||||
public boolean transferPlayerToScene(Player player, int sceneId, Position pos) {
|
||||
return transferPlayerToScene(player, sceneId, null, pos);
|
||||
}
|
||||
|
||||
public boolean transferPlayerToScene(Player player, int sceneId, DungeonData data) {
|
||||
return transferPlayerToScene(player, sceneId, data, null);
|
||||
}
|
||||
|
||||
public boolean transferPlayerToScene(Player player, int sceneId, DungeonData dungeonData, Position pos) {
|
||||
if (GameData.getSceneDataMap().get(sceneId) == null) {
|
||||
return false;
|
||||
}
|
||||
@ -230,19 +239,39 @@ public class World implements Iterable<Player> {
|
||||
}
|
||||
|
||||
Scene newScene = this.getSceneById(sceneId);
|
||||
newScene.setDungeonData(dungeonData);
|
||||
newScene.addPlayer(player);
|
||||
|
||||
// Dungeon
|
||||
if (dungeonData != null) {
|
||||
// TODO set position
|
||||
}
|
||||
|
||||
// Set player position
|
||||
if (pos != null) {
|
||||
player.getPos().set(pos);
|
||||
} else {
|
||||
pos = player.getPos();
|
||||
}
|
||||
|
||||
if (oldScene != null) {
|
||||
newScene.setPrevScene(oldScene.getId());
|
||||
oldScene.setDontDestroyWhenEmpty(false);
|
||||
}
|
||||
|
||||
// Teleport packet
|
||||
if (oldScene == newScene) {
|
||||
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.ENTER_GOTO, EnterReason.TransPoint, sceneId, pos));
|
||||
} else {
|
||||
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.ENTER_JUMP, EnterReason.TransPoint, sceneId, pos));
|
||||
// Get enter types
|
||||
EnterType enterType = EnterType.ENTER_JUMP;
|
||||
EnterReason enterReason = EnterReason.TransPoint;
|
||||
|
||||
if (dungeonData != null) {
|
||||
enterType = EnterType.ENTER_DUNGEON;
|
||||
enterReason = EnterReason.DungeonEnter;
|
||||
} else if (oldScene == newScene) {
|
||||
enterType = EnterType.ENTER_GOTO;
|
||||
}
|
||||
|
||||
// Teleport packet
|
||||
player.sendPacket(new PacketPlayerEnterSceneNotify(player, enterType, enterReason, sceneId, pos));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package emu.grasscutter.server.packet.recv;
|
||||
|
||||
import emu.grasscutter.net.packet.Opcodes;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.DungeonEntryInfoReqOuterClass.DungeonEntryInfoReq;
|
||||
import emu.grasscutter.net.packet.PacketHandler;
|
||||
import emu.grasscutter.server.game.GameSession;
|
||||
|
||||
@ -10,7 +11,9 @@ public class HandlerDungeonEntryInfoReq extends PacketHandler {
|
||||
|
||||
@Override
|
||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||
DungeonEntryInfoReq req = DungeonEntryInfoReq.parseFrom(payload);
|
||||
|
||||
session.getServer().getDungeonManager().getEntryInfo(session.getPlayer(), req.getPointId());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
package emu.grasscutter.server.packet.recv;
|
||||
|
||||
import emu.grasscutter.net.packet.Opcodes;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.PlayerEnterDungeonReqOuterClass.PlayerEnterDungeonReq;
|
||||
import emu.grasscutter.net.packet.PacketHandler;
|
||||
import emu.grasscutter.server.game.GameSession;
|
||||
|
||||
@Opcodes(PacketOpcodes.PlayerEnterDungeonReq)
|
||||
public class HandlerPlayerEnterDungeonReq extends PacketHandler {
|
||||
|
||||
@Override
|
||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||
// Auto template
|
||||
PlayerEnterDungeonReq req = PlayerEnterDungeonReq.parseFrom(payload);
|
||||
|
||||
session.getServer().getDungeonManager().enterDungeon(session.getPlayer(), req.getPointId(), req.getDungeonId());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package emu.grasscutter.server.packet.recv;
|
||||
|
||||
import emu.grasscutter.net.packet.Opcodes;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.packet.PacketHandler;
|
||||
import emu.grasscutter.server.game.GameSession;
|
||||
|
||||
@Opcodes(PacketOpcodes.PlayerQuitDungeonReq)
|
||||
public class HandlerPlayerQuitDungeonReq extends PacketHandler {
|
||||
|
||||
@Override
|
||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||
session.getPlayer().getServer().getDungeonManager().exitDungeon(session.getPlayer());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package emu.grasscutter.server.packet.send;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import emu.grasscutter.data.common.PointData;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.net.packet.BasePacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.DungeonEntryInfoOuterClass.DungeonEntryInfo;
|
||||
import emu.grasscutter.net.proto.DungeonEntryInfoRspOuterClass.DungeonEntryInfoRsp;
|
||||
|
||||
public class PacketDungeonEntryInfoRsp extends BasePacket {
|
||||
|
||||
public PacketDungeonEntryInfoRsp(Player player, PointData pointData) {
|
||||
super(PacketOpcodes.DungeonEntryInfoRsp);
|
||||
|
||||
DungeonEntryInfoRsp.Builder proto = DungeonEntryInfoRsp.newBuilder()
|
||||
.setPointId(pointData.getId());
|
||||
|
||||
for (int dungeonId : pointData.getDungeonIds()) {
|
||||
DungeonEntryInfo info = DungeonEntryInfo.newBuilder().setDungeonId(dungeonId).build();
|
||||
proto.addDungeonEntryList(info);
|
||||
}
|
||||
|
||||
this.setData(proto);
|
||||
}
|
||||
|
||||
public PacketDungeonEntryInfoRsp() {
|
||||
super(PacketOpcodes.DungeonEntryInfoRsp);
|
||||
|
||||
DungeonEntryInfoRsp proto = DungeonEntryInfoRsp.newBuilder()
|
||||
.setRetcode(1)
|
||||
.build();
|
||||
|
||||
this.setData(proto);
|
||||
}
|
||||
}
|
@ -7,7 +7,5 @@ public class PacketPathfindingEnterSceneRsp extends BasePacket {
|
||||
|
||||
public PacketPathfindingEnterSceneRsp(int clientSequence) {
|
||||
super(PacketOpcodes.PathfindingEnterSceneRsp);
|
||||
|
||||
this.buildHeader(clientSequence);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
package emu.grasscutter.server.packet.send;
|
||||
|
||||
import emu.grasscutter.net.packet.BasePacket;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.PlayerEnterDungeonRspOuterClass.PlayerEnterDungeonRsp;
|
||||
|
||||
public class PacketPlayerEnterDungeonRsp extends BasePacket {
|
||||
|
||||
public PacketPlayerEnterDungeonRsp(int pointId, int dungeonId) {
|
||||
super(PacketOpcodes.PlayerEnterDungeonRsp);
|
||||
|
||||
PlayerEnterDungeonRsp proto = PlayerEnterDungeonRsp.newBuilder()
|
||||
.setPointId(pointId)
|
||||
.setDungeonId(dungeonId)
|
||||
.build();
|
||||
|
||||
this.setData(proto);
|
||||
}
|
||||
}
|
@ -65,6 +65,7 @@ public final class Utils {
|
||||
|
||||
private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray();
|
||||
public static String bytesToHex(byte[] bytes) {
|
||||
if (bytes == null) return "";
|
||||
char[] hexChars = new char[bytes.length * 2];
|
||||
for (int j = 0; j < bytes.length; j++) {
|
||||
int v = bytes[j] & 0xFF;
|
||||
|
Loading…
Reference in New Issue
Block a user