feat : GameServer 패킷 메시지 단위 분할 / 플레이어 정보 변환 기능 변경
This commit is contained in:
169
MMOTestServer/MMOserver/Game/Service/IntoBossRaidHandler.cs
Normal file
169
MMOTestServer/MMOserver/Game/Service/IntoBossRaidHandler.cs
Normal file
@@ -0,0 +1,169 @@
|
||||
using LiteNetLib;
|
||||
using MMOserver.Api;
|
||||
using MMOserver.Game.Channel;
|
||||
using MMOserver.Game.Channel.Maps;
|
||||
using MMOserver.Game.Party;
|
||||
using MMOserver.Packet;
|
||||
using ProtoBuf;
|
||||
using Serilog;
|
||||
using ServerLib.Packet;
|
||||
using ServerLib.Service;
|
||||
|
||||
namespace MMOserver.Game.Service;
|
||||
|
||||
/*
|
||||
* 보스레이드 접속 메시지 핸들러
|
||||
*/
|
||||
public partial class GameServer : ServerBase
|
||||
{
|
||||
private async void OnIntoBossRaid(NetPeer peer, int hashKey, byte[] payload)
|
||||
{
|
||||
try
|
||||
{
|
||||
IntoBossRaidPacket packet = Serializer.Deserialize<IntoBossRaidPacket>(new ReadOnlyMemory<byte>(payload));
|
||||
|
||||
ChannelManager cm = ChannelManager.Instance;
|
||||
int channelId = cm.HasUser(hashKey);
|
||||
if (channelId < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Channel.Channel channel = cm.GetChannel(channelId);
|
||||
|
||||
// 파티 조회
|
||||
PartyInfo? party = channel.GetPartyManager().GetPartyByPlayer(hashKey);
|
||||
if (party == null)
|
||||
{
|
||||
Log.Warning("[GameServer] INTO_BOSS_RAID 파티 없음 HashKey={Key}", hashKey);
|
||||
SendTo(peer, PacketSerializer.Serialize((ushort)PacketCode.INTO_BOSS_RAID,
|
||||
new IntoBossRaidPacket { RaidId = packet.RaidId, IsSuccess = false, Reason = "파티에 속해있지 않습니다." }));
|
||||
return;
|
||||
}
|
||||
|
||||
// 파티장만 요청 가능
|
||||
if (party.LeaderId != hashKey)
|
||||
{
|
||||
Log.Warning("[GameServer] INTO_BOSS_RAID 파티장 아님 HashKey={Key} LeaderId={LeaderId}", hashKey, party.LeaderId);
|
||||
SendTo(peer, PacketSerializer.Serialize((ushort)PacketCode.INTO_BOSS_RAID,
|
||||
new IntoBossRaidPacket { RaidId = packet.RaidId, IsSuccess = false, Reason = "파티장만 보스 레이드를 시작할 수 있습니다." }));
|
||||
return;
|
||||
}
|
||||
|
||||
// API로 접속 체크
|
||||
List<string> userNames = new List<string>();
|
||||
foreach (int memberId in party.PartyMemberIds)
|
||||
{
|
||||
Player? memberPlayer = channel.GetPlayer(memberId);
|
||||
if (memberPlayer != null)
|
||||
{
|
||||
userNames.Add(memberPlayer.Nickname);
|
||||
}
|
||||
}
|
||||
|
||||
BossRaidResult? result = await RestApi.Instance.BossRaidAccessAsync(userNames, packet.RaidId);
|
||||
|
||||
// await 이후 — 공유 자원 접근 보호
|
||||
lock (sessionLock)
|
||||
{
|
||||
// 입장 실패
|
||||
if (result == null || result.BossId <= 0)
|
||||
{
|
||||
SendTo(peer,
|
||||
PacketSerializer.Serialize((ushort)PacketCode.INTO_BOSS_RAID,
|
||||
new IntoBossRaidPacket { RaidId = -1, IsSuccess = false, Reason = "보스 레이드 방을 배정받지 못했습니다. 잠시 후 다시 시도해주세요." }));
|
||||
|
||||
Log.Debug("[GameServer] INTO_BOSS_RAID HashKey={Key} PartyId={PartyId} AssignedRaidMapId={RaidId} Failed", hashKey,
|
||||
party.PartyId, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
// await 이후 상태 재검증
|
||||
channelId = cm.HasUser(hashKey);
|
||||
if (channelId < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
channel = cm.GetChannel(channelId);
|
||||
party = channel.GetPartyManager().GetPartyByPlayer(hashKey);
|
||||
if (party == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 레이드 맵 할당 (미사용 맵 탐색 → 없으면 동적 생성)
|
||||
int assignedRaidMapId = channel.GetOrCreateAvailableRaidMap();
|
||||
|
||||
// 진행중 맵으로 등록
|
||||
channel.AddInstanceMap(assignedRaidMapId);
|
||||
|
||||
// 파티원 전체 레이드 맵으로 이동 + 각자에게 알림
|
||||
foreach (int memberId in party.PartyMemberIds)
|
||||
{
|
||||
Player? memberPlayer = channel.GetPlayer(memberId);
|
||||
if (memberPlayer == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 이전 맵 캐싱 (레이드 종료 후 복귀용)
|
||||
memberPlayer.PreviousMapId = memberPlayer.CurrentMapId;
|
||||
|
||||
int oldMapId = memberPlayer.CurrentMapId;
|
||||
channel.ChangeMap(memberId, memberPlayer, assignedRaidMapId);
|
||||
|
||||
if (!sessions.TryGetValue(memberId, out NetPeer? memberPeer))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
PlayerInfo memberInfo = memberPlayer.ToPlayerInfo();
|
||||
|
||||
// 기존 맵 유저들에게 퇴장 알림
|
||||
ChangeMapPacket exitNotify = new() { MapId = oldMapId, IsAdd = false, Player = memberInfo };
|
||||
BroadcastToMap(channelId, oldMapId, PacketSerializer.Serialize((ushort)PacketCode.CHANGE_MAP, exitNotify));
|
||||
|
||||
// 새 맵 유저들에게 입장 알림 (본인 제외)
|
||||
ChangeMapPacket enterNotify = new() { MapId = assignedRaidMapId, IsAdd = true, Player = memberInfo };
|
||||
BroadcastToMap(channelId, assignedRaidMapId, PacketSerializer.Serialize((ushort)PacketCode.CHANGE_MAP, enterNotify),
|
||||
memberPeer);
|
||||
|
||||
// 본인에게 새 맵 플레이어 목록 전달
|
||||
ChangeMapPacket response = new() { MapId = assignedRaidMapId };
|
||||
AMap? raidMap = channel.GetMap(assignedRaidMapId);
|
||||
if (raidMap != null)
|
||||
{
|
||||
foreach ((int uid, Player channelPlayer) in raidMap.GetUsers())
|
||||
{
|
||||
if (uid != memberId)
|
||||
{
|
||||
response.Players.Add(channelPlayer.ToPlayerInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SendTo(memberPeer, PacketSerializer.Serialize((ushort)PacketCode.CHANGE_MAP, response));
|
||||
|
||||
// 각 파티원에게 레이드 입장 결과 전달 (Session, Token 포함)
|
||||
SendTo(memberPeer,
|
||||
PacketSerializer.Serialize((ushort)PacketCode.INTO_BOSS_RAID,
|
||||
new IntoBossRaidPacket
|
||||
{
|
||||
RaidId = assignedRaidMapId, IsSuccess = true, Session = result.SessionName,
|
||||
Token = result.Tokens != null && result.Tokens.TryGetValue(memberPlayer.Nickname, out string? memberToken)
|
||||
? memberToken
|
||||
: ""
|
||||
}));
|
||||
}
|
||||
|
||||
Log.Debug("[GameServer] INTO_BOSS_RAID HashKey={Key} PartyId={PartyId} AssignedRaidMapId={RaidId}", hashKey, party.PartyId,
|
||||
assignedRaidMapId);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Warning($"[GameServer] Error : {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user