feat: marble game entry

This commit is contained in:
Somebody
2025-05-03 15:45:03 +08:00
parent de86bdcce4
commit 5de7dd16a2
53 changed files with 1419 additions and 1 deletions

View File

@@ -0,0 +1,17 @@
namespace EggLink.DanhengServer.Data.Excel;
[ResourceEntity("MarbleMatchInfo.json")]
public class MarbleMatchInfoExcel : ExcelResource
{
public int ID { get; set; }
public override int GetId()
{
return ID;
}
public override void Loaded()
{
GameData.MarbleMatchInfoData.Add(ID, this);
}
}

View File

@@ -0,0 +1,23 @@
namespace EggLink.DanhengServer.Data.Excel;
[ResourceEntity("MarbleSeal.json")]
public class MarbleSealExcel : ExcelResource
{
public int ID { get; set; }
public int Attack { get; set; }
public float MaxSpeed { get; set; }
public float Mass { get; set; }
public int Hp { get; set; }
public int ActionPriority { get; set; }
public float Size { get; set; }
public override int GetId()
{
return ID;
}
public override void Loaded()
{
GameData.MarbleSealData.Add(ID, this);
}
}

View File

@@ -18,6 +18,13 @@ public static class GameData
public static ActivityConfig ActivityConfig { get; set; } = new();
#region Marble
public static Dictionary<int, MarbleMatchInfoExcel> MarbleMatchInfoData { get; private set; } = [];
public static Dictionary<int, MarbleSealExcel> MarbleSealData { get; private set; } = [];
#endregion
#endregion
#region Banners

View File

@@ -0,0 +1,21 @@
namespace EggLink.DanhengServer.Enums.Fight;
public enum MarbleNetWorkMsgEnum
{
None = 0,
PlayerEnter = 1,
PerformanceFinish = 2,
LoadFinish = 3,
SimulateFinish = 4,
Launch = 5,
UseTech = 6,
TechFinish = 7,
Emoji = 8,
SnapShot = 9,
SyncBatch = 10,
GameStart = 11,
SyncNotify = 12,
GameFinish = 13,
SyncSnapShot = 14,
Operation = 15
}

View File

@@ -0,0 +1,12 @@
namespace EggLink.DanhengServer.Enums.Fight;
public enum MarblePlayerPhaseEnum
{
NotEnter = 0,
EnterGame = 1,
LoadFinish = 2,
PerformanceFinish = 3,
Gaming = 4,
Launching = 5,
UseTech = 6
}

View File

@@ -126,7 +126,7 @@ public class FriendManager(PlayerInstance player) : BasePlayerManager(player)
}
// receive message
var recvPlayer = Listener.GetActiveConnection(recvUid)?.Player!;
var recvPlayer = Listener.GetActiveConnection(recvUid)?.Player;
if (recvPlayer != null)
{
await recvPlayer.FriendManager!.ReceiveMessage(sendUid, recvUid, message, extraId);
@@ -148,6 +148,19 @@ public class FriendManager(PlayerInstance player) : BasePlayerManager(player)
}
}
public async ValueTask SendInviteMessage(int sendUid, int recvUid, LobbyInviteInfo info)
{
var proto = new PacketRevcMsgScNotify((uint)recvUid, (uint)sendUid, info);
await Player.SendPacket(proto);
// receive message
var recvPlayer = Listener.GetActiveConnection(recvUid)?.Player;
if (recvPlayer != null)
{
await recvPlayer.FriendManager!.ReceiveInviteMessage(sendUid, recvUid, info);
}
}
public async ValueTask ReceiveMessage(int sendUid, int recvUid, string? message = null, int? extraId = null)
{
var data = new FriendChatData
@@ -176,6 +189,13 @@ public class FriendManager(PlayerInstance player) : BasePlayerManager(player)
await Player.SendPacket(proto);
}
public async ValueTask ReceiveInviteMessage(int sendUid, int recvUid, LobbyInviteInfo info)
{
var proto = new PacketRevcMsgScNotify((uint)recvUid, (uint)sendUid, info);
await Player.SendPacket(proto);
}
public List<ChatMessageData> GetHistoryInfo(int uid)
{
if (!FriendData.ChatHistory.TryGetValue(uid, out var history)) return [];

View File

@@ -0,0 +1,113 @@
using EggLink.DanhengServer.GameServer.Game.Lobby.Player;
using EggLink.DanhengServer.GameServer.Game.Player;
using EggLink.DanhengServer.GameServer.Server;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Lobby;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Multiplayer;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.Lobby;
public class LobbyRoomInstance(PlayerInstance owner, long roomId, FightGameMode gameMode, int lobbyMode)
{
public long RoomId { get; set; } = roomId;
public FightGameMode GameMode { get; set; } = gameMode;
public List<LobbyPlayerInstance> Players { get; set; } = [];
public int LobbyMode { get; set; } = lobbyMode;
public bool IsInGame { get; set; }
public async ValueTask BroadCastToRoom(BasePacket packet)
{
foreach (var player in Players)
{
await player.Player.SendPacket(packet);
}
}
public async ValueTask AddPlayer(PlayerInstance player, List<int> sealList, LobbyCharacterType characterType)
{
await AddPlayer(new LobbyPlayerInstance(player, characterType)
{
EquippedSealList = sealList
});
}
public async ValueTask AddPlayer(LobbyPlayerInstance player)
{
if (Players.Any(x => x.Player.Uid == player.Player.Uid)) return;
await BroadCastToRoom(new PacketLobbySyncInfoScNotify(player.Player.Uid, this, LobbyModifyType.JoinLobby));
Players.Add(player);
}
public async ValueTask RemovePlayer(int uid)
{
var remove = Players.RemoveAll(x => x.Player.Uid == uid);
if (remove == 0) return;
await BroadCastToRoom(new PacketLobbySyncInfoScNotify(uid, this, LobbyModifyType.QuitLobby));
if (Players.Count == 0)
{
// remove from manager
ServerUtils.LobbyServerManager.RemoveLobbyRoom(RoomId);
}
}
public async ValueTask<Retcode> LobbyStartFight()
{
// check status
if (IsInGame)
return Retcode.RetLobbyRoomPalyerFighting;
if (Players.Count(x => x.CharacterType != LobbyCharacterType.LobbyCharacterWatcher) != 2)
return Retcode.RetLobbyRoomPalyerNotReady;
if (Players.Any(x =>
x.CharacterType == LobbyCharacterType.LobbyCharacterMember &&
x.CharacterStatus != LobbyCharacterStatus.Ready)) return Retcode.RetLobbyRoomPalyerNotReady;
if (Players.Any(x =>
x.CharacterType != LobbyCharacterType.LobbyCharacterWatcher &&
x.EquippedSealList.Count != 3)) return Retcode.RetLobbyRoomPalyerNotReady;
var leader = Players.Find(x => x.CharacterType == LobbyCharacterType.LobbyCharacterLeader);
if (leader == null) return Retcode.RetLobbyRoomPalyerFighting;
// start fight
foreach (var instance in Players)
{
instance.CharacterStatus = LobbyCharacterStatus.LobbyStartFight;
}
await BroadCastToRoom(new PacketLobbySyncInfoScNotify(leader.Player.Uid, this, LobbyModifyType.LobbyStartFight));
return Retcode.RetSucc;
}
public async ValueTask<Retcode> StartFight()
{
// alrdy check status in lobby start fight
if (IsInGame)
return Retcode.RetLobbyRoomPalyerFighting;
// create fight room
var fightRoom = ServerUtils.MultiPlayerGameServerManager.CreateRoom(this);
if (fightRoom == null) return Retcode.RetLobbyRoomNotExist;
IsInGame = true;
await BroadCastToRoom(new PacketMultiplayerFightGameStartScNotify(fightRoom));
// start fight
foreach (var instance in Players)
{
instance.CharacterStatus = LobbyCharacterStatus.Fighting;
}
await BroadCastToRoom(new PacketLobbySyncInfoScNotify(0, this, LobbyModifyType.FightStart));
return Retcode.RetSucc;
}
public LobbyPlayerInstance? GetPlayerByUid(int uid)
{
var player = Players.FirstOrDefault(x => x.Player.Uid == uid);
return player;
}
}

View File

@@ -0,0 +1,42 @@
using EggLink.DanhengServer.GameServer.Game.Player;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Lobby;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.Lobby;
/// <summary>
/// Server Manager:
/// a manager would be only initialized when the server is started
/// </summary>
public class LobbyServerManager
{
public long CurLobbyRoomId { get; set; }
public Dictionary<long, LobbyRoomInstance> LobbyRoomInstances { get; set; } = [];
public async ValueTask<LobbyRoomInstance> CreateLobbyRoom(PlayerInstance ownerPlayer, int lobbyMode, List<int> sealList)
{
var roomId = ++CurLobbyRoomId;
var room = new LobbyRoomInstance(ownerPlayer, roomId, FightGameMode.Marble, lobbyMode);
LobbyRoomInstances.Add(roomId, room);
await room.AddPlayer(ownerPlayer, sealList, LobbyCharacterType.LobbyCharacterLeader);
return room;
}
public void RemoveLobbyRoom(long roomId)
{
LobbyRoomInstances.Remove(roomId, out _);
}
public LobbyRoomInstance? GetPlayerJoinedRoom(int uid)
{
foreach (var room in LobbyRoomInstances.Values)
{
if (room.Players.Any(x => x.Player.Uid == uid))
{
return room;
}
}
return null;
}
}

View File

@@ -0,0 +1,33 @@
using EggLink.DanhengServer.GameServer.Game.Player;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.Lobby.Player;
public class LobbyPlayerInstance(PlayerInstance player, LobbyCharacterType characterType)
{
public PlayerInstance Player { get; } = player;
public List<int> EquippedSealList { get; set; } = [];
public LobbyCharacterType CharacterType { get; set; } = characterType;
public LobbyCharacterStatus CharacterStatus { get; set; } = LobbyCharacterStatus.Idle;
public LobbyBasicInfo ToProto()
{
return new LobbyBasicInfo
{
PlayerLobbyInfo = new LobbyPlayerInfo
{
CharacterType = CharacterType,
Status = CharacterStatus
},
StageInfo = new LobbyGameInfo
{
LobbyMarbleInfo = new LobbyMarbleInfo
{
LobbySealList = { EquippedSealList.Select(x => (uint)x) },
Rank = 1
}
},
BasicInfo = Player.Data.ToLobbyProto()
};
}
}

View File

@@ -0,0 +1,20 @@
using EggLink.DanhengServer.GameServer.Game.Lobby.Player;
using EggLink.DanhengServer.GameServer.Server;
using EggLink.DanhengServer.Kcp;
namespace EggLink.DanhengServer.GameServer.Game.MultiPlayer;
public abstract class BaseGamePlayerInstance(LobbyPlayerInstance lobby)
{
public LobbyPlayerInstance LobbyPlayer { get; } = lobby;
public bool EnterGame { get; set; }
public Connection? Connection { get; set; }
public async ValueTask SendPacket(BasePacket packet)
{
if (Connection == null) return;
if (!Connection.IsOnline) return;
await Connection.SendPacket(packet);
}
}

View File

@@ -0,0 +1,26 @@
using EggLink.DanhengServer.GameServer.Game.Lobby;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.MultiPlayer;
public abstract class BaseMultiPlayerGameRoomInstance(long roomId, LobbyRoomInstance parentLobby)
{
public FightGameMode GameMode { get; } = parentLobby.GameMode;
public long RoomId { get; } = roomId;
public LobbyRoomInstance ParentLobby { get; } = parentLobby;
public List<BaseGamePlayerInstance> Players { get; } = [];
public BaseGamePlayerInstance? GetPlayerById(int uid)
{
return Players.FirstOrDefault(player => player.LobbyPlayer.Player.Uid == uid);
}
public FightSessionInfo ToSessionInfo()
{
return new FightSessionInfo
{
SessionGameMode = GameMode,
SessionRoomId = (ulong)RoomId
};
}
}

View File

@@ -0,0 +1,64 @@
using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.Enums.Fight;
using EggLink.DanhengServer.GameServer.Game.Lobby.Player;
using EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame.Seal;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame;
public class MarbleGamePlayerInstance : BaseGamePlayerInstance
{
public Dictionary<int, MarbleGameSealInstance> SealList { get; set; } = [];
public MarbleTeamType TeamType { get; set; }
public MarblePlayerPhaseEnum Phase { get; set; } = MarblePlayerPhaseEnum.NotEnter;
public int CurItemId { get; set; }
public int Score { get; set; }
public HashSet<int> AllowMoveSealList { get; set; } = [];
public MarbleGamePlayerInstance(LobbyPlayerInstance lobby, MarbleTeamType type) : base(lobby)
{
TeamType = type;
CurItemId = TeamType == MarbleTeamType.TeamA ? 200 : 300;
var posXBaseValue = TeamType == MarbleTeamType.TeamA ? -1 : 1;
var index = 0;
foreach (var seal in lobby.EquippedSealList)
{
if (!GameData.MarbleSealData.TryGetValue(seal, out var marbleSeal)) continue;
var posY = (index - 1) * 1.5f;
var posX = posXBaseValue * (Math.Abs(index - 1) * 0.5f + 2);
var rotX = posXBaseValue * -1f;
AllowMoveSealList.Add(CurItemId);
SealList.Add(CurItemId, new MarbleGameSealInstance(CurItemId++, seal)
{
Position = new MarbleSealVector
{
X = posX,
Y = posY
},
Rotation = new MarbleSealVector
{
X = rotX
},
Attack = marbleSeal.Attack,
CurHp = marbleSeal.Hp,
MaxHp = marbleSeal.Hp,
Size = marbleSeal.Size,
Mass = marbleSeal.Mass,
MaxSpeed = marbleSeal.MaxSpeed
});
index++;
}
}
public void ChangeRound()
{
foreach (var instance in SealList.Values)
{
AllowMoveSealList.Add(instance.Id);
}
}
}

View File

@@ -0,0 +1,135 @@
using EggLink.DanhengServer.Enums.Fight;
using EggLink.DanhengServer.GameServer.Game.Lobby;
using EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame.Seal;
using EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame.Sync;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Fight;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame;
public class MarbleGameRoomInstance : BaseMultiPlayerGameRoomInstance
{
public MarbleTeamType CurMoveTeamType { get; set; }
public int CurRound { get; set; }
public MarbleGameRoomInstance(long roomId, LobbyRoomInstance parentLobby) : base(roomId, parentLobby)
{
// random move team type
CurMoveTeamType = (MarbleTeamType)Random.Shared.Next(1, 3);
// set player
foreach (var player in parentLobby.Players)
{
Players.Add(new MarbleGamePlayerInstance(player, (MarbleTeamType)(parentLobby.Players.IndexOf(
player) + 1)));
}
}
public async ValueTask BroadCastToRoom(BasePacket packet)
{
foreach (var player in Players)
{
await player.SendPacket(packet);
}
}
public async ValueTask EnterGame(int uid)
{
var player = GetPlayerById(uid);
if (player == null) return;
player.EnterGame = true;
if (player is MarbleGamePlayerInstance marblePlayer)
{
marblePlayer.Phase = MarblePlayerPhaseEnum.EnterGame;
}
if (Players.All(x => x.EnterGame))
{
// send basic info
await BroadCastToRoom(new PacketFightGeneralScNotify(MarbleNetWorkMsgEnum.SyncBatch,
MarbleNetWorkMsgEnum.GameStart, this));
}
}
#region Handler
public async ValueTask HandleGeneralRequest(MarbleGamePlayerInstance player, uint msgType, byte[] reqData)
{
var messageType = (MarbleNetWorkMsgEnum)msgType;
switch (messageType)
{
case MarbleNetWorkMsgEnum.LoadFinish:
await LoadFinish(player);
break;
case MarbleNetWorkMsgEnum.PerformanceFinish:
await PerformanceFinish(player);
break;
default:
break;
}
}
public async ValueTask LoadFinish(MarbleGamePlayerInstance player)
{
player.Phase = MarblePlayerPhaseEnum.LoadFinish;
if (Players.OfType<MarbleGamePlayerInstance>().ToList().All(x => x.Phase == MarblePlayerPhaseEnum.LoadFinish))
{
// next phase (performance)
await BroadCastToRoom(new PacketFightGeneralScNotify(MarbleNetWorkMsgEnum.SyncBatch,
[new MarblePerformanceSyncData(MarbleNetWorkMsgEnum.SyncNotify)]));
}
}
public async ValueTask PerformanceFinish(MarbleGamePlayerInstance player)
{
player.Phase = MarblePlayerPhaseEnum.PerformanceFinish;
if (Players.OfType<MarbleGamePlayerInstance>().ToList().All(x => x.Phase == MarblePlayerPhaseEnum.PerformanceFinish))
{
// next phase (round start)
await RoundStart();
}
}
#endregion
#region Round
public async ValueTask RoundStart()
{
CurRound++;
foreach (var player in Players.OfType<MarbleGamePlayerInstance>())
{
player.ChangeRound();
}
await BroadCastToRoom(new PacketFightGeneralScNotify(MarbleNetWorkMsgEnum.SyncBatch,
[
new MarbleGameInfoSyncData(MarbleNetWorkMsgEnum.SyncNotify, MarbleSyncType.RoundStart, this,
Players.OfType<MarbleGamePlayerInstance>().SelectMany(x => x.SealList.Values)
.Select(x => new MarbleGameSealSyncData(x, MarbleFrameType.RoundStart)).ToList())
]));
}
#endregion
public MarbleGameInfo ToProto()
{
return new MarbleGameInfo
{
LobbyBasicInfo = { ParentLobby.Players.Select(x => x.ToProto()) },
CurActionTeamType = CurMoveTeamType,
LevelId = (uint)Random.Shared.Next(100, 103),
TeamAPlayer = (uint)Players[0].LobbyPlayer.Player.Uid,
TeamBPlayer = (uint)Players[1].LobbyPlayer.Player.Uid,
TeamARank = 1,
TeamBRank = 1,
TeamASealList = { (Players[0] as MarbleGamePlayerInstance)!.SealList.Select(x => (uint)x.Value.SealId) },
TeamBSealList = { (Players[1] as MarbleGamePlayerInstance)!.SealList.Select(x => (uint)x.Value.SealId) },
PlayerAScore = (uint)(Players[0] as MarbleGamePlayerInstance)!.Score,
PlayerBScore = (uint)(Players[1] as MarbleGamePlayerInstance)!.Score,
ControlByServer = true
};
}
}

View File

@@ -0,0 +1,34 @@
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame.Seal;
public class MarbleGameSealInstance(int itemId, int sealId)
{
public int Id { get; set; } = itemId;
public int SealId { get; set; } = sealId;
public int CurHp { get; set; }
public int MaxHp { get; set; }
public int Attack { get; set; }
public float Mass { get; set; }
public float MaxSpeed { get; set; }
public float Size { get; set; }
public bool OnStage { get; set; }
public MarbleSealVector Position { get; set; } = new();
public MarbleSealVector Rotation { get; set; } = new();
public MarbleGameSealInstance Clone()
{
return new MarbleGameSealInstance(Id, SealId)
{
CurHp = CurHp,
MaxHp = MaxHp,
Attack = Attack,
Size = Size,
Mass = Mass,
MaxSpeed = MaxSpeed,
OnStage = OnStage,
Position = Position.Clone(),
Rotation = Rotation.Clone()
};
}
}

View File

@@ -0,0 +1,24 @@
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame.Seal;
public class MarbleGameSealSyncData(MarbleGameSealInstance inst, MarbleFrameType frameType)
{
public MarbleGameSealInstance Instance { get; set; } = inst.Clone();
public MarbleGameSyncData ToProto()
{
return new MarbleGameSyncData
{
Attack = Instance.Attack,
Id = (uint)Instance.Id,
Hp = Instance.CurHp,
MaxHp = Instance.MaxHp,
SealPosition = Instance.Position,
SealRotation = Instance.Rotation,
SealOnStage = Instance.OnStage,
SealSize = Instance.Size,
FrameType = frameType
};
}
}

View File

@@ -0,0 +1,10 @@
using EggLink.DanhengServer.Enums.Fight;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame.Sync;
public abstract class MarbleGameBaseSyncData(MarbleNetWorkMsgEnum type)
{
public MarbleNetWorkMsgEnum MessageType { get; set; } = type;
public abstract MarbleGameSyncInfo ToProto();
}

View File

@@ -0,0 +1,18 @@
using EggLink.DanhengServer.Enums.Fight;
using EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame.Seal;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame.Sync;
public class MarbleGameInfoSyncData(MarbleNetWorkMsgEnum type, MarbleSyncType syncType, MarbleGameRoomInstance room, List<MarbleGameSealSyncData> syncDatas) : MarbleGameBaseSyncData(type)
{public override MarbleGameSyncInfo ToProto()
{
return new MarbleGameSyncInfo
{
MarbleSyncType = syncType,
CurRound = (uint)room.CurRound,
AllowedMoveSealList = { (room.Players[(int)room.CurMoveTeamType - 1] as MarbleGamePlayerInstance)!.AllowMoveSealList.Select(x => (uint)x) },
MarbleGameSyncData = { syncDatas.Select(x => x.ToProto()) }
};
}
}

View File

@@ -0,0 +1,15 @@
using EggLink.DanhengServer.Enums.Fight;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame.Sync;
public class MarblePerformanceSyncData(MarbleNetWorkMsgEnum type) : MarbleGameBaseSyncData(type)
{
public override MarbleGameSyncInfo ToProto()
{
return new MarbleGameSyncInfo
{
MarbleSyncType = MarbleSyncType.Performance
};
}
}

View File

@@ -0,0 +1,39 @@
using EggLink.DanhengServer.GameServer.Game.Lobby;
using EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Game.MultiPlayer;
public class MultiPlayerGameServerManager
{
public Dictionary<long, BaseMultiPlayerGameRoomInstance> Rooms { get; } = [];
public long CurRoomId { get; set; }
public BaseMultiPlayerGameRoomInstance? CreateRoom(LobbyRoomInstance lobbyRoom)
{
if (lobbyRoom.GameMode != FightGameMode.Marble) return null;
var roomId = ++CurRoomId;
var room = new MarbleGameRoomInstance(roomId, lobbyRoom);
Rooms.Add(roomId, room);
return room;
}
public void RemoveRoom(long roomId)
{
Rooms.Remove(roomId, out _);
}
public BaseMultiPlayerGameRoomInstance? GetPlayerJoinedRoom(int uid)
{
foreach (var room in Rooms.Values)
{
if (room.Players.Any(x => x.LobbyPlayer.Player.Uid == uid))
{
return room;
}
}
return null;
}
}

View File

@@ -1,6 +1,7 @@
using System.Buffers;
using System.Net;
using System.Reflection;
using EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame;
using EggLink.DanhengServer.GameServer.Game.Player;
using EggLink.DanhengServer.GameServer.Server.Packet;
using EggLink.DanhengServer.Kcp;
@@ -17,6 +18,8 @@ public class Connection(KcpConversation conversation, IPEndPoint remote) : Danhe
private static readonly Logger Logger = new("GameServer");
public PlayerInstance? Player { get; set; }
public MarbleGameRoomInstance? MarbleRoom { get; set; }
public MarbleGamePlayerInstance? MarblePlayer { get; set; }
public override async void Start()
{

View File

@@ -18,5 +18,7 @@ public class HandlerSendMsgCsReq : Handler
else if (req.MessageType == MsgType.Emoji)
await connection.Player!.FriendManager!.SendMessage(connection.Player!.Uid, (int)req.TargetList[0], null,
(int)req.ExtraId);
else if (req.MessageType == MsgType.Invite)
await connection.Player!.FriendManager!.SendInviteMessage(connection.Player!.Uid, (int)req.TargetList[0], req.InviteInfo);
}
}

View File

@@ -0,0 +1,63 @@
using EggLink.DanhengServer.GameServer.Game.MultiPlayer;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Fight;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Util.Security;
using EggLink.DanhengServer.Util;
using System.Security.Cryptography;
using EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Fight;
[Opcode(CmdIds.FightEnterCsReq)]
public class HandlerFightEnterCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
var req = FightEnterCsReq.Parser.ParseFrom(data);
if (!ServerUtils.MultiPlayerGameServerManager.Rooms.TryGetValue((long)req.EnterRoomId, out var room))
{
await connection.SendPacket(new PacketFightEnterScRsp(Retcode.RetFightRoomNotExist));
connection.Stop();
return;
}
if (room is not MarbleGameRoomInstance marbleGame)
{
await connection.SendPacket(new PacketFightEnterScRsp(Retcode.RetFightRoomNotExist));
connection.Stop();
return;
}
var player = room.GetPlayerById((int)req.Uid);
if (player is not MarbleGamePlayerInstance marble)
{
await connection.SendPacket(new PacketFightEnterScRsp(Retcode.RetFightRoomNotExist));
connection.Stop();
return;
}
connection.MarblePlayer = marble;
marble.Connection = connection;
connection.MarbleRoom = marbleGame;
if (ConfigManager.Config.GameServer.UsePacketEncryption)
{
var tempRandom = new MT19937((ulong)DateTimeOffset.Now.ToUnixTimeSeconds());
connection.ClientSecretKeySeed = tempRandom.NextUInt64();
}
connection.State = SessionStateEnum.ACTIVE;
connection.DebugFile = Path.Combine(ConfigManager.Config.Path.LogPath, "Debug/", $"{req.Uid}/",
$"Debug-{DateTime.Now:yyyy-MM-dd HH-mm-ss}-FightGame.log");
await connection.SendPacket(new PacketFightEnterScRsp(connection.ClientSecretKeySeed));
if (ConfigManager.Config.GameServer.UsePacketEncryption)
{
connection.XorKey = Crypto.GenerateXorKey(connection.ClientSecretKeySeed);
}
await marbleGame.EnterGame(player.LobbyPlayer.Player.Uid);
}
}

View File

@@ -0,0 +1,25 @@
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Fight;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Fight;
[Opcode(CmdIds.FightGeneralCsReq)]
public class HandlerFightGeneralCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
var req = FightGeneralCsReq.Parser.ParseFrom(data);
if (connection.MarbleRoom == null || connection.MarblePlayer == null)
{
await connection.SendPacket(new PacketFightGeneralScRsp(Retcode.RetFightRoomNotExist));
return;
}
await connection.MarbleRoom.HandleGeneralRequest(connection.MarblePlayer, req.NetworkMsgType,
req.FightGeneralInfo?.ToByteArray() ?? []);
await connection.SendPacket(new PacketFightGeneralScRsp(req.NetworkMsgType));
}
}

View File

@@ -0,0 +1,16 @@
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Fight;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Fight;
[Opcode(CmdIds.FightHeartBeatCsReq)]
public class HandlerFightHeartBeatCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
var req = FightHeartBeatCsReq.Parser.ParseFrom(data);
await connection.SendPacket(new PacketFightHeartBeatScRsp(req.ClientTimeMs));
}
}

View File

@@ -0,0 +1,27 @@
using EggLink.DanhengServer.GameServer.Game.Lobby;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Lobby;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Lobby;
[Opcode(CmdIds.LobbyCreateCsReq)]
public class HandlerLobbyCreateCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
var req = LobbyCreateCsReq.Parser.ParseFrom(data);
if (req.FightGameMode != FightGameMode.Marble)
{
await connection.SendPacket(new PacketLobbyCreateScRsp(Retcode.RetTimeout));
return;
}
var lobbyMode = req.LobbyMode;
var marbleList = req.LobbyGameInfo.LobbyMarbleInfo.LobbySealList.Select(x => (int)x).ToList();
var room = await ServerUtils.LobbyServerManager.CreateLobbyRoom(connection.Player!, (int)lobbyMode, marbleList);
await connection.SendPacket(new PacketLobbyCreateScRsp(room));
}
}

View File

@@ -0,0 +1,40 @@
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Lobby;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Lobby;
[Opcode(CmdIds.LobbyJoinCsReq)]
public class HandlerLobbyJoinCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
var req = LobbyJoinCsReq.Parser.ParseFrom(data);
var room = ServerUtils.LobbyServerManager.LobbyRoomInstances.GetValueOrDefault((long)req.RoomId);
if (room == null)
{
await connection.SendPacket(new PacketLobbyJoinScRsp(Retcode.RetLobbyRoomNotExist));
return;
}
if (room.Players.Count >= 2)
{
await connection.SendPacket(new PacketLobbyJoinScRsp(Retcode.RetLobbyRoomPalyerFull));
return;
}
var player = room.GetPlayerByUid(connection.Player!.Uid);
if (player != null)
{
await connection.SendPacket(new PacketLobbyJoinScRsp(Retcode.RetLobbyRoomPalyerFull));
return;
}
await room.AddPlayer(connection.Player!, req.LobbyGameInfo.LobbyMarbleInfo.LobbySealList.Select(x => (int)x).ToList(),
LobbyCharacterType.LobbyCharacterMember);
await connection.SendPacket(new PacketLobbyJoinScRsp(room));
}
}

View File

@@ -0,0 +1,39 @@
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Lobby;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Lobby;
[Opcode(CmdIds.LobbyModifyPlayerInfoCsReq)]
public class HandlerLobbyModifyPlayerInfoCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
var req = LobbyModifyPlayerInfoCsReq.Parser.ParseFrom(data);
var room = ServerUtils.LobbyServerManager.GetPlayerJoinedRoom(connection.Player!.Uid);
if (room == null)
{
await connection.SendPacket(new PacketLobbyModifyPlayerInfoScRsp(Retcode.RetLobbyRoomNotExist));
return;
}
var player = room.GetPlayerByUid(connection.Player.Uid);
if (player == null)
{
await connection.SendPacket(new PacketLobbyModifyPlayerInfoScRsp(Retcode.RetLobbyRoomNotExist));
return;
}
player.EquippedSealList = req.LobbyGameInfo.LobbyMarbleInfo.LobbySealList.Select(x => (int)x).ToList();
player.CharacterStatus = req.Type switch
{
LobbyModifyType.Ready => LobbyCharacterStatus.Ready,
LobbyModifyType.Operating => LobbyCharacterStatus.Operating,
_ => player.CharacterStatus
};
await room.BroadCastToRoom(new PacketLobbySyncInfoScNotify(player.Player.Uid, room, req.Type));
await connection.SendPacket(new PacketLobbyModifyPlayerInfoScRsp(Retcode.RetSucc));
}
}

View File

@@ -0,0 +1,22 @@
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Lobby;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Lobby;
[Opcode(CmdIds.LobbyQuitCsReq)]
public class HandlerLobbyQuitCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
var room = ServerUtils.LobbyServerManager.GetPlayerJoinedRoom(connection.Player!.Uid);
if (room == null)
{
await connection.SendPacket(new PacketLobbyQuitScRsp(Retcode.RetLobbyRoomNotExist));
return;
}
await room.RemovePlayer(connection.Player.Uid);
await connection.SendPacket(new PacketLobbyQuitScRsp(Retcode.RetSucc));
}
}

View File

@@ -0,0 +1,24 @@
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Lobby;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Lobby;
[Opcode(CmdIds.LobbyStartFightCsReq)]
public class HandlerLobbyStartFightCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
var room = ServerUtils.LobbyServerManager.GetPlayerJoinedRoom(connection.Player!.Uid);
if (room == null)
{
await connection.SendPacket(new PacketLobbyStartFightScRsp(Retcode.RetLobbyRoomNotExist));
return;
}
var code = await room.LobbyStartFight();
await connection.SendPacket(new PacketLobbyStartFightScRsp(code));
await room.StartFight();
}
}

View File

@@ -0,0 +1,13 @@
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Marble;
using EggLink.DanhengServer.Kcp;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Marble;
[Opcode(CmdIds.MarbleGetDataCsReq)]
public class HandlerMarbleGetDataCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
await connection.SendPacket(new PacketMarbleGetDataScRsp());
}
}

View File

@@ -0,0 +1,16 @@
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Marble;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Marble;
[Opcode(CmdIds.MarbleLevelFinishCsReq)]
public class HandlerMarbleLevelFinishCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
var req = MarbleLevelFinishCsReq.Parser.ParseFrom(data);
await connection.SendPacket(new PacketMarbleLevelFinishScRsp(req.MarbleLevelId));
}
}

View File

@@ -0,0 +1,16 @@
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Marble;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Marble;
[Opcode(CmdIds.MarbleUpdateShownSealCsReq)]
public class HandlerMarbleUpdateShownSealCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
var req = MarbleUpdateShownSealCsReq.Parser.ParseFrom(data);
await connection.SendPacket(new PacketMarbleUpdateShownSealScRsp(req.UpdateSealList));
}
}

View File

@@ -0,0 +1,13 @@
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Match;
using EggLink.DanhengServer.Kcp;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Match;
[Opcode(CmdIds.GetCrossInfoCsReq)]
public class HandlerGetCrossInfoCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
await connection.SendPacket(new PacketGetCrossInfoScRsp());
}
}

View File

@@ -0,0 +1,21 @@
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Multiplayer;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.Multiplayer;
[Opcode(CmdIds.MultiplayerGetFightGateCsReq)]
public class HandlerMultiplayerGetFightGateCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
var room = ServerUtils.MultiPlayerGameServerManager.GetPlayerJoinedRoom(connection.Player!.Uid);
if (room == null)
{
await connection.SendPacket(new PacketMultiplayerGetFightGateScRsp(Retcode.RetFightRoomNotExist));
return;
}
await connection.SendPacket(new PacketMultiplayerGetFightGateScRsp(room));
}
}

View File

@@ -7,6 +7,12 @@ public class HandlerPlayerLogoutCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
var room = ServerUtils.LobbyServerManager.GetPlayerJoinedRoom(connection.Player!.Uid);
if (room != null)
{
await room.RemovePlayer(connection.Player.Uid);
}
await connection.SendPacket(CmdIds.PlayerLogoutScRsp);
connection.Stop();
}

View File

@@ -32,4 +32,18 @@ public class PacketRevcMsgScNotify : BasePacket
SetData(proto);
}
public PacketRevcMsgScNotify(uint toUid, uint fromUid, LobbyInviteInfo info) : base(CmdIds.RevcMsgScNotify)
{
var proto = new RevcMsgScNotify
{
ChatType = ChatType.Private,
SourceUid = fromUid,
TargetUid = toUid,
InviteInfo = info,
MessageType = MsgType.Invite
};
SetData(proto);
}
}

View File

@@ -0,0 +1,29 @@
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Util;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Fight;
public class PacketFightEnterScRsp : BasePacket
{
public PacketFightEnterScRsp(Retcode code) : base(CmdIds.FightEnterScRsp)
{
var proto = new FightEnterScRsp
{
Retcode = (uint)code
};
SetData(proto);
}
public PacketFightEnterScRsp(ulong keySeed) : base(CmdIds.FightEnterScRsp)
{
var proto = new FightEnterScRsp
{
SecretKeySeed = keySeed,
ServerTimestampMs = (ulong)Extensions.GetUnixMs()
};
SetData(proto);
}
}

View File

@@ -0,0 +1,46 @@
using EggLink.DanhengServer.Enums.Fight;
using EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame;
using EggLink.DanhengServer.GameServer.Game.MultiPlayer.MarbleGame.Sync;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Fight;
public class PacketFightGeneralScNotify : BasePacket
{
public PacketFightGeneralScNotify(MarbleNetWorkMsgEnum msgType, MarbleNetWorkMsgEnum syncType, MarbleGameRoomInstance game) : base(CmdIds.FightGeneralScNotify)
{
var proto = new FightGeneralScNotify
{
NetworkMsgType = (uint)msgType,
FightGeneralInfo = new FightGeneralServerInfo
{
FightGameInfo = { new FightGameInfo
{
MarbleGameInfo = game.ToProto(),
GameMessageType = (uint)syncType
} }
}
};
SetData(proto);
}
public PacketFightGeneralScNotify(MarbleNetWorkMsgEnum msgType, List<MarbleGameBaseSyncData> sync) : base(CmdIds.FightGeneralScNotify)
{
var proto = new FightGeneralScNotify
{
NetworkMsgType = (uint)msgType,
FightGeneralInfo = new FightGeneralServerInfo
{
FightGameInfo = { sync.Select(x => new FightGameInfo
{
GameMessageType = (uint)x.MessageType,
MarbleGameSyncInfo = x.ToProto()
}) }
}
};
SetData(proto);
}
}

View File

@@ -0,0 +1,27 @@
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Fight;
public class PacketFightGeneralScRsp : BasePacket
{
public PacketFightGeneralScRsp(uint networkType) : base(CmdIds.FightGeneralScRsp)
{
var proto = new FightGeneralScRsp
{
NetworkMsgType = networkType
};
SetData(proto);
}
public PacketFightGeneralScRsp(Retcode code) : base(CmdIds.FightGeneralScRsp)
{
var proto = new FightGeneralScRsp
{
Retcode = (uint)code
};
SetData(proto);
}
}

View File

@@ -0,0 +1,19 @@
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Util;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Fight;
public class PacketFightHeartBeatScRsp : BasePacket
{
public PacketFightHeartBeatScRsp(ulong clientTime) : base(CmdIds.FightHeartBeatScRsp)
{
var proto = new FightHeartBeatScRsp
{
ServerTimeMs = (ulong)Extensions.GetUnixMs(),
ClientTimeMs = clientTime
};
SetData(proto);
}
}

View File

@@ -0,0 +1,31 @@
using EggLink.DanhengServer.GameServer.Game.Lobby;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Lobby;
public class PacketLobbyCreateScRsp : BasePacket
{
public PacketLobbyCreateScRsp(LobbyRoomInstance room) : base(CmdIds.LobbyCreateScRsp)
{
var proto = new LobbyCreateScRsp
{
RoomId = (ulong)room.RoomId,
FightGameMode = room.GameMode,
LobbyBasicInfo = { room.Players.Select(x => x.ToProto()) },
LobbyMode = (uint)room.LobbyMode
};
SetData(proto);
}
public PacketLobbyCreateScRsp(Retcode retCode) : base(CmdIds.LobbyCreateScRsp)
{
var proto = new LobbyCreateScRsp
{
Retcode = (uint)retCode
};
SetData(proto);
}
}

View File

@@ -0,0 +1,31 @@
using EggLink.DanhengServer.GameServer.Game.Lobby;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Lobby;
public class PacketLobbyJoinScRsp : BasePacket
{
public PacketLobbyJoinScRsp(Retcode retcode) : base(CmdIds.LobbyJoinScRsp)
{
var proto = new LobbyJoinScRsp
{
Retcode = (uint)retcode
};
SetData(proto);
}
public PacketLobbyJoinScRsp(LobbyRoomInstance room) : base(CmdIds.LobbyJoinScRsp)
{
var proto = new LobbyJoinScRsp
{
RoomId = (ulong)room.RoomId,
FightGameMode = room.GameMode,
LobbyBasicInfo = { room.Players.Select(x => x.ToProto()) },
LobbyMode = (uint)room.LobbyMode
};
SetData(proto);
}
}

View File

@@ -0,0 +1,17 @@
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Lobby;
public class PacketLobbyModifyPlayerInfoScRsp : BasePacket
{
public PacketLobbyModifyPlayerInfoScRsp(Retcode code) : base(CmdIds.LobbyModifyPlayerInfoScRsp)
{
var proto = new LobbyModifyPlayerInfoScRsp
{
Retcode = (uint)code
};
SetData(proto);
}
}

View File

@@ -0,0 +1,17 @@
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Lobby;
public class PacketLobbyQuitScRsp : BasePacket
{
public PacketLobbyQuitScRsp(Retcode code) : base(CmdIds.LobbyQuitScRsp)
{
var proto = new LobbyModifyPlayerInfoScRsp
{
Retcode = (uint)code
};
SetData(proto);
}
}

View File

@@ -0,0 +1,17 @@
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Lobby;
public class PacketLobbyStartFightScRsp : BasePacket
{
public PacketLobbyStartFightScRsp(Retcode code) : base(CmdIds.LobbyStartFightScRsp)
{
var proto = new LobbyStartFightScRsp
{
Retcode = (uint)code
};
SetData(proto);
}
}

View File

@@ -0,0 +1,21 @@
using EggLink.DanhengServer.GameServer.Game.Lobby;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Lobby;
public class PacketLobbySyncInfoScNotify : BasePacket
{
public PacketLobbySyncInfoScNotify(int uid, LobbyRoomInstance room, LobbyModifyType modifyType) : base(
CmdIds.LobbySyncInfoScNotify)
{
var proto = new LobbySyncInfoScNotify
{
LobbyBasicInfo = { room.Players.Select(x => x.ToProto()) },
Uid = (uint)uid,
Type = modifyType
};
SetData(proto);
}
}

View File

@@ -0,0 +1,19 @@
using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Marble;
public class PacketMarbleGetDataScRsp : BasePacket
{
public PacketMarbleGetDataScRsp() : base(CmdIds.MarbleGetDataScRsp)
{
var proto = new MarbleGetDataScRsp
{
OwnedSealList = { GameData.MarbleSealData.Keys.Select(x => (uint)x) },
MarbleFinishLevelIdList = { GameData.MarbleMatchInfoData.Keys.Select(x => (uint)x) }
};
SetData(proto);
}
}

View File

@@ -0,0 +1,17 @@
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Marble;
public class PacketMarbleLevelFinishScRsp : BasePacket
{
public PacketMarbleLevelFinishScRsp(uint levelId) : base(CmdIds.MarbleLevelFinishScRsp)
{
var proto = new MarbleLevelFinishScRsp
{
MarbleLevelId = levelId
};
SetData(proto);
}
}

View File

@@ -0,0 +1,17 @@
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Marble;
public class PacketMarbleUpdateShownSealScRsp : BasePacket
{
public PacketMarbleUpdateShownSealScRsp(ICollection<uint> sealList) : base(CmdIds.MarbleUpdateShownSealScRsp)
{
var proto = new MarbleUpdateShownSealScRsp
{
UpdateSealList = { sealList }
};
SetData(proto);
}
}

View File

@@ -0,0 +1,17 @@
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Match;
public class PacketGetCrossInfoScRsp : BasePacket
{
public PacketGetCrossInfoScRsp() : base(CmdIds.GetCrossInfoScRsp)
{
var proto = new GetCrossInfoScRsp
{
FightGameMode = FightGameMode.Marble
};
SetData(proto);
}
}

View File

@@ -0,0 +1,19 @@
using EggLink.DanhengServer.GameServer.Game.MultiPlayer;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Multiplayer;
public class PacketMultiplayerFightGameStartScNotify : BasePacket
{
public PacketMultiplayerFightGameStartScNotify(BaseMultiPlayerGameRoomInstance room) : base(CmdIds.MultiplayerFightGameStartScNotify)
{
var proto = new MultiplayerFightGameStartScNotify
{
SessionInfo = room.ToSessionInfo(),
LobbyBasicInfo = { room.ParentLobby.Players.Select(x => x.ToProto()) }
};
SetData(proto);
}
}

View File

@@ -0,0 +1,31 @@
using EggLink.DanhengServer.GameServer.Game.MultiPlayer;
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Util;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Multiplayer;
public class PacketMultiplayerGetFightGateScRsp : BasePacket
{
public PacketMultiplayerGetFightGateScRsp(Retcode code) : base(CmdIds.MultiplayerGetFightGateScRsp)
{
var proto = new MultiplayerGetFightGateScRsp
{
Retcode = (uint)code
};
SetData(proto);
}
public PacketMultiplayerGetFightGateScRsp(BaseMultiPlayerGameRoomInstance room) : base(CmdIds.MultiplayerGetFightGateScRsp)
{
var proto = new MultiplayerGetFightGateScRsp
{
GateRoomId = (ulong)room.RoomId,
Ip = ConfigManager.Config.GameServer.PublicAddress,
Port = ConfigManager.Config.GameServer.Port
};
SetData(proto);
}
}

View File

@@ -0,0 +1,10 @@
using EggLink.DanhengServer.GameServer.Game.Lobby;
using EggLink.DanhengServer.GameServer.Game.MultiPlayer;
namespace EggLink.DanhengServer.GameServer.Server;
public static class ServerUtils
{
public static LobbyServerManager LobbyServerManager { get; set; } = new();
public static MultiPlayerGameServerManager MultiPlayerGameServerManager { get; set; } = new();
}