213 lines
7.7 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|