Files
a301_mmo_game_server/MMOTestServer/MMOserver/Game/Service/RequestPartyHandler.cs

213 lines
7.7 KiB
C#

using LiteNetLib;
using MMOserver.Game.Channel;
using MMOserver.Game.Party;
using MMOserver.Packet;
using ProtoBuf;
using ServerLib.Packet;
using ServerLib.Service;
namespace MMOserver.Game.Service;
/*
* 파티 요청(추가, 탈퇴, 정보변경) 메시지 핸들러
*/
public partial class GameServer : ServerBase
{
private void OnRequestParty(NetPeer peer, int hashKey, byte[] payload)
{
RequestPartyPacket req = Serializer.Deserialize<RequestPartyPacket>(new ReadOnlyMemory<byte>(payload));
ChannelManager cm = ChannelManager.Instance;
int channelId = cm.HasUser(hashKey);
if (channelId < 0)
{
return;
}
PartyManager pm = cm.GetChannel(channelId).GetPartyManager();
switch (req.Type)
{
case PartyUpdateType.CREATE:
{
if (!pm.CreateParty(hashKey, req.PartyName, out PartyInfo? party))
{
SendError(peer, ErrorCode.PARTY_ALREADY_IN_PARTY);
return;
}
UpdatePartyPacket notify = new()
{
PartyId = party!.PartyId,
Type = PartyUpdateType.CREATE,
LeaderId = party.LeaderId,
PlayerId = hashKey,
PartyName = party.PartyName
};
byte[] data = PacketSerializer.Serialize((ushort)PacketCode.UPDATE_PARTY, notify);
BroadcastToChannel(channelId, data); // 채널 전체 파티 목록 갱신
break;
}
case PartyUpdateType.JOIN:
{
if (!pm.JoinParty(hashKey, req.PartyId, out PartyInfo? party))
{
SendError(peer, ErrorCode.PARTY_JOIN_FAILED);
return;
}
UpdatePartyPacket notify = new()
{
PartyId = party!.PartyId,
Type = PartyUpdateType.JOIN,
LeaderId = party.LeaderId,
PlayerId = hashKey
};
byte[] data = PacketSerializer.Serialize((ushort)PacketCode.UPDATE_PARTY, notify);
BroadcastToChannel(channelId, data); // 채널 전체 파티 목록 갱신
break;
}
case PartyUpdateType.LEAVE:
{
if (!pm.LeaveParty(hashKey, out PartyInfo? party) || party == null)
{
SendError(peer, ErrorCode.PARTY_NOT_IN_PARTY);
return;
}
UpdatePartyPacket notify = new()
{
PartyId = party.PartyId, Type = PartyUpdateType.DELETE, LeaderId = party.LeaderId, PlayerId = hashKey
};
// 파티가 남아있으면 살린다.
if (party.PartyMemberIds.Count > 0)
{
notify.Type = PartyUpdateType.LEAVE;
}
byte[] data = PacketSerializer.Serialize((ushort)PacketCode.UPDATE_PARTY, notify);
BroadcastToChannel(channelId, data); // 채널 전체 파티 목록 갱신 (탈퇴자 포함)
break;
}
case PartyUpdateType.DELETE:
{
if (!pm.DeleteParty(hashKey, req.PartyId, out PartyInfo? party))
{
SendError(peer, ErrorCode.PARTY_DELETE_FAILED);
return;
}
UpdatePartyPacket notify = new()
{
PartyId = party!.PartyId,
Type = PartyUpdateType.DELETE,
LeaderId = party.LeaderId
};
byte[] data = PacketSerializer.Serialize((ushort)PacketCode.UPDATE_PARTY, notify);
BroadcastToChannel(channelId, data); // 채널 전체 파티 목록 갱신
break;
}
case PartyUpdateType.UPDATE:
{
if (!pm.UpdateParty(hashKey, req.PartyId, req.PartyName, out PartyInfo? party))
{
SendError(peer, ErrorCode.PARTY_UPDATE_FAILED);
return;
}
UpdatePartyPacket notify = new()
{
PartyId = req.PartyId,
Type = PartyUpdateType.UPDATE,
LeaderId = party?.LeaderId ?? 0,
PlayerId = hashKey,
PartyName = req.PartyName
};
byte[] data = PacketSerializer.Serialize((ushort)PacketCode.UPDATE_PARTY, notify);
BroadcastToChannel(channelId, data); // 채널 전체 파티 목록 갱신
break;
}
case PartyUpdateType.INVITE:
{
// 리더만 초대 가능
PartyInfo? myParty = pm.GetPartyByPlayer(hashKey);
if (myParty == null || myParty.LeaderId != hashKey)
{
SendError(peer, ErrorCode.PARTY_JOIN_FAILED);
return;
}
if (myParty.GetPartyMemberCount() >= PartyInfo.partyMemberMax)
{
SendError(peer, ErrorCode.PARTY_JOIN_FAILED);
return;
}
// 대상 플레이어가 같은 채널에 있는지 확인
int targetId = req.TargetPlayerId;
Channel.Channel? ch = cm.GetChannel(channelId);
if (ch == null || ch.GetPlayer(targetId) == null)
{
SendError(peer, ErrorCode.PARTY_JOIN_FAILED);
return;
}
// 대상에게 초대 알림 전송
NetPeer? targetPeer = ch.GetPeer(targetId);
if (targetPeer == null)
{
SendError(peer, ErrorCode.PARTY_JOIN_FAILED);
return;
}
UpdatePartyPacket inviteNotify = new()
{
PartyId = myParty.PartyId,
Type = PartyUpdateType.INVITE,
LeaderId = hashKey,
PlayerId = targetId,
PartyName = myParty.PartyName
};
byte[] inviteData = PacketSerializer.Serialize((ushort)PacketCode.UPDATE_PARTY, inviteNotify);
SendTo(targetPeer, inviteData);
break;
}
case PartyUpdateType.KICK:
{
// 리더만 추방 가능
PartyInfo? myParty2 = pm.GetPartyByPlayer(hashKey);
if (myParty2 == null || myParty2.LeaderId != hashKey)
{
SendError(peer, ErrorCode.PARTY_DELETE_FAILED);
return;
}
int kickTarget = req.TargetPlayerId;
if (kickTarget == hashKey)
{
return; // 자기 자신은 추방 불가
}
if (!pm.LeaveParty(kickTarget, out PartyInfo? kickedParty) || kickedParty == null)
{
SendError(peer, ErrorCode.PARTY_NOT_IN_PARTY);
return;
}
UpdatePartyPacket kickNotify = new()
{
PartyId = kickedParty.PartyId,
Type = PartyUpdateType.KICK,
LeaderId = kickedParty.LeaderId,
PlayerId = kickTarget
};
byte[] kickData = PacketSerializer.Serialize((ushort)PacketCode.UPDATE_PARTY, kickNotify);
BroadcastToChannel(channelId, kickData);
break;
}
}
}
}