feat : 보스 레이드 입장 메시지 기능 추가
This commit is contained in:
@@ -16,6 +16,12 @@ public class Channel
|
||||
// 채널 맵 관리
|
||||
private readonly Dictionary<int, AMap> maps = new();
|
||||
|
||||
// 진행중 채널 맵 관리
|
||||
private readonly Dictionary<int, AMap> useInstanceMaps = new();
|
||||
|
||||
// 동적 레이드 맵 할당용 ID 카운터 (사전 생성 10개 이후부터 시작)
|
||||
private int nextDynamicRaidMapId = 1011;
|
||||
|
||||
// 파티
|
||||
private readonly PartyManager partyManager = new();
|
||||
|
||||
@@ -29,7 +35,7 @@ public class Channel
|
||||
maps.Add(1, new Robby(1));
|
||||
|
||||
// 인던
|
||||
int defaultValue = 10;
|
||||
int defaultValue = 1000;
|
||||
for (int i = 1; i <= 10; i++)
|
||||
{
|
||||
maps.Add(i + defaultValue, new BossInstance(i + defaultValue));
|
||||
@@ -152,9 +158,47 @@ public class Channel
|
||||
return map;
|
||||
}
|
||||
|
||||
// 사용 가능한 레이드 맵 ID 반환
|
||||
// 기존 맵(1001~) 중 미사용 탐색 → 없으면 동적 생성 후 반환
|
||||
public int GetOrCreateAvailableRaidMap()
|
||||
{
|
||||
// 기존 맵 중 미사용 탐색
|
||||
foreach (int mapId in maps.Keys)
|
||||
{
|
||||
if (mapId >= 1001 && !useInstanceMaps.ContainsKey(mapId))
|
||||
{
|
||||
return mapId;
|
||||
}
|
||||
}
|
||||
|
||||
// 모두 사용 중 → 동적 생성
|
||||
int newMapId = nextDynamicRaidMapId++;
|
||||
BossInstance newMap = new(newMapId);
|
||||
maps.Add(newMapId, newMap);
|
||||
|
||||
return newMapId;
|
||||
}
|
||||
|
||||
// 레이드 맵 사용 시작 (진행중 목록에 등록)
|
||||
public void AddInstanceMap(int mapId)
|
||||
{
|
||||
if (maps.TryGetValue(mapId, out AMap? map))
|
||||
{
|
||||
useInstanceMaps[mapId] = map;
|
||||
}
|
||||
}
|
||||
|
||||
// 레이드 맵 사용 종료 (진행중 목록에서 제거)
|
||||
public void RemoveInstanceMap(int mapId)
|
||||
{
|
||||
useInstanceMaps.Remove(mapId);
|
||||
}
|
||||
|
||||
// 파티매니저 가져옴
|
||||
public PartyManager GetPartyManager()
|
||||
{
|
||||
return partyManager;
|
||||
}
|
||||
|
||||
// TODO : 채널 가져오기
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ public class GameServer : ServerBase
|
||||
[(ushort)PacketCode.STATE_PLAYER] = OnStatePlayer,
|
||||
[(ushort)PacketCode.CHANGE_MAP] = OnChangeMap,
|
||||
[(ushort)PacketCode.PARTY_CHANGE_MAP] = OnPartyChangeMap,
|
||||
[(ushort)PacketCode.INTO_BOSS_RAID] = OnIntoBossRaid,
|
||||
[(ushort)PacketCode.REQUEST_PARTY] = OnRequestParty,
|
||||
[(ushort)PacketCode.CHAT] = OnChat
|
||||
};
|
||||
@@ -102,6 +103,7 @@ public class GameServer : ServerBase
|
||||
{
|
||||
AccTokenPacket accTokenPacket = Serializer.Deserialize<AccTokenPacket>(new ReadOnlyMemory<byte>(payload));
|
||||
string token = accTokenPacket.Token;
|
||||
string username = "";
|
||||
tokenHash.TryGetValue(token, out int hashKey);
|
||||
if (hashKey <= 1000)
|
||||
{
|
||||
@@ -119,7 +121,7 @@ public class GameServer : ServerBase
|
||||
else
|
||||
{
|
||||
// 신규 연결: 웹서버에 JWT 검증 요청
|
||||
string? username = await RestApi.Instance.VerifyTokenAsync(token);
|
||||
username = await RestApi.Instance.VerifyTokenAsync(token);
|
||||
if (username == null)
|
||||
{
|
||||
Log.Warning("[Server] 토큰 검증 실패 - 연결 거부 PeerId={Id}", peer.Id);
|
||||
@@ -133,6 +135,11 @@ public class GameServer : ServerBase
|
||||
|
||||
peer.Tag = new Session(hashKey, peer);
|
||||
((Session)peer.Tag).Token = token;
|
||||
if (username.Length > 0)
|
||||
{
|
||||
((Session)peer.Tag).UserName = username;
|
||||
}
|
||||
|
||||
sessions[hashKey] = peer;
|
||||
tokenHash[token] = hashKey;
|
||||
pendingPeers.Remove(peer.Id);
|
||||
@@ -451,7 +458,7 @@ public class GameServer : ServerBase
|
||||
{
|
||||
HashKey = hashKey,
|
||||
PlayerId = hashKey,
|
||||
Nickname = hashKey.ToString()
|
||||
Nickname = ((Session)peer.Tag).UserName
|
||||
};
|
||||
|
||||
// 채널에 추가
|
||||
@@ -481,12 +488,16 @@ public class GameServer : ServerBase
|
||||
{
|
||||
foreach (var (userId, p) in initMap.GetUsers())
|
||||
{
|
||||
if (userId == hashKey) continue;
|
||||
if (userId == hashKey)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
response.Players.Add(ToPlayerInfo(p));
|
||||
}
|
||||
}
|
||||
SendTo(peer, PacketSerializer.Serialize((ushort)PacketCode.CHANGE_MAP, response));
|
||||
|
||||
SendTo(peer, PacketSerializer.Serialize((ushort)PacketCode.CHANGE_MAP, response));
|
||||
}
|
||||
|
||||
private void OnIntoChannelParty(NetPeer peer, int hashKey, byte[] payload)
|
||||
@@ -1026,6 +1037,121 @@ public class GameServer : ServerBase
|
||||
Log.Debug("[GameServer] PARTY_CHANGE_MAP HashKey={Key} PartyId={PartyId} MapId={MapId}", hashKey, packet.PartyId, packet.MapId);
|
||||
}
|
||||
|
||||
private async void OnIntoBossRaid(NetPeer peer, int hashKey, byte[] payload)
|
||||
{
|
||||
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 }));
|
||||
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 }));
|
||||
return;
|
||||
}
|
||||
|
||||
// API로 접속 체크
|
||||
List<string> userNames = new List<string>();
|
||||
foreach (int memberId in party.PartyMemberIds)
|
||||
{
|
||||
userNames.Add(channel.GetPlayer(memberId).Nickname);
|
||||
}
|
||||
|
||||
bool? result = await RestApi.Instance.BossRaidAccesssAsync(userNames, 1);
|
||||
|
||||
// 입장 실패
|
||||
if (result.Value == false)
|
||||
{
|
||||
SendTo(peer,
|
||||
PacketSerializer.Serialize((ushort)PacketCode.INTO_BOSS_RAID,
|
||||
new IntoBossRaidPacket { RaidId = -1, IsSuccess = false }));
|
||||
|
||||
Log.Debug("[GameServer] INTO_BOSS_RAID HashKey={Key} PartyId={PartyId} AssignedRaidMapId={RaidId} Failed", hashKey,
|
||||
party.PartyId, -1);
|
||||
}
|
||||
|
||||
// 레이드 맵 할당 (미사용 맵 탐색 → 없으면 동적 생성)
|
||||
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 = ToPlayerInfo(memberPlayer);
|
||||
|
||||
// 기존 맵 유저들에게 퇴장 알림
|
||||
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 p) in raidMap.GetUsers())
|
||||
{
|
||||
if (uid != memberId)
|
||||
{
|
||||
response.Players.Add(ToPlayerInfo(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SendTo(memberPeer, PacketSerializer.Serialize((ushort)PacketCode.CHANGE_MAP, response));
|
||||
}
|
||||
|
||||
// 파티장에게 입장 성공 응답 (할당된 실제 레이드 맵 ID 전달)
|
||||
SendTo(peer,
|
||||
PacketSerializer.Serialize((ushort)PacketCode.INTO_BOSS_RAID,
|
||||
new IntoBossRaidPacket { RaidId = assignedRaidMapId, IsSuccess = true }));
|
||||
|
||||
Log.Debug("[GameServer] INTO_BOSS_RAID HashKey={Key} PartyId={PartyId} AssignedRaidMapId={RaidId}", hashKey, party.PartyId,
|
||||
assignedRaidMapId);
|
||||
}
|
||||
|
||||
// 채널 퇴장/연결 해제 시 파티 자동 탈퇴 처리
|
||||
private void HandlePartyLeaveOnExit(int channelId, int hashKey)
|
||||
{
|
||||
|
||||
@@ -81,4 +81,11 @@ public class Player
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
// 레이드 입장 전 이전 맵 ID (레이드 종료 후 복귀용, 서버 캐싱)
|
||||
public int PreviousMapId
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user