feat : 채팅 기증 추가, 귓속말은 대상이 id라는 문제 있음 <= 현재는 그대로 둔다

This commit is contained in:
qornwh1
2026-03-09 08:51:50 +09:00
parent 5df664e05b
commit de4e344cdb
3 changed files with 140 additions and 3 deletions

View File

@@ -27,6 +27,7 @@ public class GameServer : ServerBase
[(ushort)PacketCode.ACTION_PLAYER] = OnActionPlayer, [(ushort)PacketCode.ACTION_PLAYER] = OnActionPlayer,
[(ushort)PacketCode.STATE_PLAYER] = OnStatePlayer, [(ushort)PacketCode.STATE_PLAYER] = OnStatePlayer,
[(ushort)PacketCode.REQUEST_PARTY] = OnRequestParty, [(ushort)PacketCode.REQUEST_PARTY] = OnRequestParty,
[(ushort)PacketCode.CHAT] = OnChat,
}; };
userUuidGenerator = new UuidGenerator(); userUuidGenerator = new UuidGenerator();
} }
@@ -182,7 +183,14 @@ public class GameServer : ServerBase
{ {
if (packetHandlers.TryGetValue(type, out Action<NetPeer, int, byte[]>? handler)) if (packetHandlers.TryGetValue(type, out Action<NetPeer, int, byte[]>? handler))
{ {
handler(peer, hashKey, payload); try
{
handler(peer, hashKey, payload);
}
catch (Exception ex)
{
Log.Error(ex, "[GameServer] 패킷 처리 중 예외 Type={Type} HashKey={Key}", type, hashKey);
}
} }
else else
{ {
@@ -201,7 +209,7 @@ public class GameServer : ServerBase
{ {
ChannelInfo info = new ChannelInfo(); ChannelInfo info = new ChannelInfo();
info.ChannelId = channel.ChannelId; info.ChannelId = channel.ChannelId;
info.ChannelUserConut = channel.UserCount; info.ChannelUserCount = channel.UserCount;
info.ChannelUserMax = channel.UserCountMax; info.ChannelUserMax = channel.UserCountMax;
loadChannelPacket.Channels.Add(info); loadChannelPacket.Channels.Add(info);
} }
@@ -564,6 +572,75 @@ public class GameServer : ServerBase
} }
} }
private void OnChat(NetPeer peer, int hashKey, byte[] payload)
{
ChatPacket req = Serializer.Deserialize<ChatPacket>(new ReadOnlyMemory<byte>(payload));
ChannelManager cm = ChannelManager.Instance;
int channelId = cm.HasUser(hashKey);
if (channelId < 0)
{
return;
}
Player? sender = cm.GetChannel(channelId).GetPlayer(hashKey);
if (sender == null)
{
return;
}
// 서버에서 발신자 정보 채워줌 (클라 위조 방지)
ChatPacket res = new ChatPacket
{
Type = req.Type,
SenderId = sender.PlayerId,
SenderNickname = sender.Nickname,
TargetId = req.TargetId,
Message = req.Message,
};
byte[] data = PacketSerializer.Serialize<ChatPacket>((ushort)PacketCode.CHAT, res);
switch (req.Type)
{
case ChatType.GLOBAL:
// 채널 내 모든 유저 (자신 포함)
BroadcastToChannel(channelId, data);
Log.Debug("[Chat] GLOBAL HashKey={Key} Message={Msg}", hashKey, req.Message);
break;
case ChatType.PARTY:
// 파티 멤버에게만 (자신 포함)
PartyManager pm = cm.GetChannel(channelId).GetPartyManager();
PartyInfo? party = pm.GetPartyByPlayer(hashKey);
if (party == null)
{
Log.Warning("[Chat] PARTY 파티 없음 HashKey={Key}", hashKey);
return;
}
BroadcastToUsers(party.PartyMemberIds, data);
Log.Debug("[Chat] PARTY HashKey={Key} PartyId={PartyId} Message={Msg}", hashKey, party.PartyId, req.Message);
break;
case ChatType.WHISPER:
// 대상 + 발신자에게만
if (sessions.TryGetValue(req.TargetId, out NetPeer? targetPeer))
{
SendTo(targetPeer, data);
}
else
{
Log.Warning("[Chat] WHISPER 대상 없음 HashKey={Key} TargetId={TargetId}", hashKey, req.TargetId);
}
// 자신에게도 전송 (귓말 확인용)
SendTo(peer, data);
Log.Debug("[Chat] WHISPER HashKey={Key} TargetId={TargetId} Message={Msg}", hashKey, req.TargetId, req.Message);
break;
}
}
private void SendError(NetPeer peer, ErrorCode code) private void SendError(NetPeer peer, ErrorCode code)
{ {
ErrorPacket err = new ErrorPacket { Code = code }; ErrorPacket err = new ErrorPacket { Code = code };

View File

@@ -185,7 +185,7 @@ public class ChannelInfo
} }
[ProtoMember(2)] [ProtoMember(2)]
public int ChannelUserConut public int ChannelUserCount
{ {
get; get;
set; set;
@@ -579,6 +579,63 @@ public class RequestPartyPacket
} // CREATE 시 사용 } // CREATE 시 사용
} }
// ============================================================
// 채팅
// ============================================================
public enum ChatType
{
GLOBAL, // 전체 채널
PARTY, // 파티원
WHISPER // 귓말
}
// CHAT (클라 -> 서버 & 서버 -> 클라)
// 클라->서버: Type, TargetId(WHISPER 시), Message
// 서버->클라: Type, SenderId, SenderNickname, TargetId(WHISPER 시), Message
[ProtoContract]
public class ChatPacket
{
[ProtoMember(1)]
public ChatType Type
{
get;
set;
}
[ProtoMember(2)]
public int SenderId
{
get;
set;
} // 서버에서 채워줌
[ProtoMember(3)]
public string SenderNickname
{
get;
set;
} // 서버에서 채워줌
[ProtoMember(4)]
public int TargetId
{
get;
set;
} // WHISPER일 때 대상 PlayerId
[ProtoMember(5)]
public string Message
{
get;
set;
}
}
// ============================================================
// 파티
// ============================================================
// UPDATE_PARTY (서버 -> 클라) - 파티 생성/삭제: LeaderId 사용 / 파티원 추가/제거: PlayerId 사용 // UPDATE_PARTY (서버 -> 클라) - 파티 생성/삭제: LeaderId 사용 / 파티원 추가/제거: PlayerId 사용
[ProtoContract] [ProtoContract]
public class UpdatePartyPacket public class UpdatePartyPacket

View File

@@ -54,6 +54,9 @@ public enum PacketCode : ushort
// 파티 참가/탈퇴/생성/해산 요청 (클라 -> 서버) // 파티 참가/탈퇴/생성/해산 요청 (클라 -> 서버)
REQUEST_PARTY, REQUEST_PARTY,
// 채팅 (클라 -> 서버 & 서버 -> 클라) - GLOBAL / PARTY / WHISPER
CHAT,
// 요청 실패 응답 (서버 -> 클라) // 요청 실패 응답 (서버 -> 클라)
ERROR = 9999 ERROR = 9999
} }