using LiteNetLib; 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 void OnPartyChangeMap(NetPeer peer, int hashKey, byte[] payload) { PartyChangeMapPacket packet = Serializer.Deserialize(new ReadOnlyMemory(payload)); ChannelManager cm = ChannelManager.Instance; int channelId = cm.HasUser(hashKey); if (channelId < 0) { return; } Channel.Channel channel = cm.GetChannel(channelId); // 맵 유효성 체크 if (channel.GetMap(packet.MapId) == null) { Log.Warning("[GameServer] PARTY_CHANGE_MAP 유효하지 않은 맵 HashKey={Key} MapId={MapId}", hashKey, packet.MapId); return; } // 파티 확인 PartyInfo? party = channel.GetPartyManager().GetParty(packet.PartyId); if (party == null) { Log.Warning("[GameServer] PARTY_CHANGE_MAP 파티 없음 HashKey={Key} PartyId={PartyId}", hashKey, packet.PartyId); return; } // 파티원 전체 맵 이동 + 각자에게 알림 foreach (int memberId in party.PartyMemberIds) { Player? memberPlayer = channel.GetPlayer(memberId); if (memberPlayer == null) { continue; } int oldMapId = memberPlayer.CurrentMapId; channel.ChangeMap(memberId, memberPlayer, packet.MapId); 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 = packet.MapId, IsAdd = true, Player = memberInfo }; BroadcastToMap(channelId, packet.MapId, PacketSerializer.Serialize((ushort)PacketCode.CHANGE_MAP, enterNotify), memberPeer); // 본인에게 새 맵 플레이어 목록 전달 ChangeMapPacket response = new() { MapId = packet.MapId }; AMap? newMap = channel.GetMap(packet.MapId); if (newMap != null) { foreach ((int uid, Player player) in newMap.GetUsers()) { if (uid == memberId) { continue; } response.Players.Add(player.ToPlayerInfo()); } } SendTo(memberPeer, PacketSerializer.Serialize((ushort)PacketCode.CHANGE_MAP, response)); } Log.Debug("[GameServer] PARTY_CHANGE_MAP HashKey={Key} PartyId={PartyId} MapId={MapId}", hashKey, packet.PartyId, packet.MapId); } }