Files
a301_mmo_game_server/MMOTestServer/MMOserver/Packet/PacketBody.cs
tolelom 53eabe2f3d fix: MMO 서버 버그 수정 및 안정성 개선 (20건)
- VerifyTokenAsync 인증 우회 차단 (빈 문자열→null 반환)
- HandleAuth/OnIntoBossRaid async void→async Task 전환
- await 후 스레드 안전성 확보 (sessionLock 도입)
- 보스레이드 파티원 세션/토큰 개별 전달 (tokens Dictionary 타입 수정)
- 409 Conflict 처리 추가, bossId 하드코딩 제거
- 채널 이동 시 레이드 맵 해제, 플레이어 상태 보존
- 파티원 닉네임 손실 수정, HandlePartyLeaveOnExit 알림 타입 수정
- PacketCode enum 명시적 값 할당, MaplId→MapId/BossRaidAccesss→Access 오타 수정
- Channel.UserCount 음수 방지, HandleAuth 재연결 로직 수정

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 23:26:39 +09:00

886 lines
13 KiB
C#

#pragma warning disable CS8618
using ProtoBuf;
namespace MMOserver.Packet;
// ============================================================
// 에코용
// ============================================================
// ECHO
[ProtoContract]
public class EchoPacket
{
[ProtoMember(1)]
public string Str
{
get;
set;
}
}
// ============================================================
// 공통 타입
// ============================================================
[ProtoContract]
public class Position
{
[ProtoMember(1)]
public float X
{
get;
set;
}
[ProtoMember(2)]
public float Y
{
get;
set;
}
[ProtoMember(3)]
public float Z
{
get;
set;
}
}
[ProtoContract]
public class PlayerInfo
{
[ProtoMember(1)]
public int PlayerId
{
get;
set;
}
[ProtoMember(2)]
public string Nickname
{
get;
set;
}
[ProtoMember(3)]
public int Level
{
get;
set;
}
[ProtoMember(4)]
public int Hp
{
get;
set;
}
[ProtoMember(5)]
public int MaxHp
{
get;
set;
}
[ProtoMember(6)]
public int Mp
{
get;
set;
}
[ProtoMember(7)]
public int MaxMp
{
get;
set;
}
[ProtoMember(8)]
public Position Position
{
get;
set;
}
[ProtoMember(9)]
public float RotY
{
get;
set;
}
[ProtoMember(10)]
public int Experience
{
get;
set;
}
[ProtoMember(11)]
public int NextExp
{
get;
set;
}
[ProtoMember(12)]
public float AttackPower
{
get;
set;
}
[ProtoMember(13)]
public float AttackRange
{
get;
set;
}
[ProtoMember(14)]
public float SprintMultiplier
{
get;
set;
}
}
// ============================================================
// 인증
// ============================================================
// DUMMY_ACC_TOKEN
[ProtoContract]
public class DummyAccTokenPacket
{
[ProtoMember(1)]
public int Token
{
get;
set;
}
}
// ACC_TOKEN
[ProtoContract]
public class AccTokenPacket
{
[ProtoMember(1)]
public string Token
{
get;
set;
}
}
// LOAD_GAME 내 정보
[ProtoContract]
public class LoadGamePacket
{
[ProtoMember(1)]
public bool IsAccepted
{
get;
set;
}
[ProtoMember(2)]
public PlayerInfo Player
{
get;
set;
}
[ProtoMember(3)]
public int MapId
{
get;
set;
}
}
// ============================================================
// 로비
// ============================================================
[ProtoContract]
public class ChannelInfo
{
[ProtoMember(1)]
public int ChannelId
{
get;
set;
}
[ProtoMember(2)]
public int ChannelUserCount
{
get;
set;
}
[ProtoMember(3)]
public int ChannelUserMax
{
get;
set;
}
}
[ProtoContract]
public class LoadChannelPacket
{
[ProtoMember(1)]
public List<ChannelInfo> Channels
{
get;
set;
} = new List<ChannelInfo>();
}
// 채널 내 파티 정보 (INTO_CHANNEL 응답에 포함)
[ProtoContract]
public class PartyInfoData
{
[ProtoMember(1)]
public int PartyId
{
get;
set;
}
[ProtoMember(2)]
public int LeaderId
{
get;
set;
}
[ProtoMember(3)]
public List<int> MemberPlayerIds
{
get;
set;
} = new List<int>();
[ProtoMember(4)]
public string PartyName
{
get;
set;
}
}
// INTO_CHANNEL 클라->서버: 입장할 채널 ID / 서버->클라: 채널 내 나 이외 플레이어 목록
[ProtoContract]
public class IntoChannelPacket
{
[ProtoMember(1)]
public int ChannelId
{
get;
set;
} // 클라->서버: 입장할 채널 ID
[ProtoMember(2)]
public List<PlayerInfo> Players
{
get;
set;
} = new List<PlayerInfo>(); // 서버->클라: 채널 내 플레이어 목록
[ProtoMember(3)]
public List<PartyInfoData> Parties
{
get;
set;
} = new List<PartyInfoData>(); // 서버->클라: 채널 내 파티 목록
}
// 파티원 모두 채널이동
// 클라->서버: 입장할 채널 ID
[ProtoContract]
public class IntoChannelPartyPacket
{
[ProtoMember(1)]
public int ChannelId
{
get;
set;
} // 클라->서버: 입장할 채널 ID
[ProtoMember(2)]
public List<PlayerInfo> Players
{
get;
set;
} = new List<PlayerInfo>(); // 서버->클라: 채널 내 플레이어 목록
[ProtoMember(3)]
public List<PartyInfoData> Parties
{
get;
set;
} = new List<PartyInfoData>(); // 서버->클라: 채널 내 파티 목록
[ProtoMember(4)]
public int PartyId
{
get;
set;
}
}
// UPDATE_CHANNEL_USER 유저 접속/나감
[ProtoContract]
public class UpdateChannelUserPacket
{
[ProtoMember(1)]
public PlayerInfo Players
{
get;
set;
}
[ProtoMember(2)]
public bool IsAdd
{
get;
set;
}
}
// EXIT_CHANNEL 나가는 유저
[ProtoContract]
public class ExitChannelPacket
{
[ProtoMember(1)]
public int PlayerId
{
get;
set;
}
}
// ============================================================
// 플레이어
// ============================================================
public enum PlayerActionType
{
IDLE,
MOVE,
ATTACK,
SKILL,
DODGE,
DIE,
REVIVE
}
// TRANSFORM_PLAYER
[ProtoContract]
public class TransformPlayerPacket
{
[ProtoMember(1)]
public int PlayerId
{
get;
set;
}
[ProtoMember(2)]
public Position Position
{
get;
set;
}
[ProtoMember(3)]
public float RotY
{
get;
set;
}
}
// ACTION_PLAYER
[ProtoContract]
public class ActionPlayerPacket
{
[ProtoMember(1)]
public int PlayerId
{
get;
set;
}
[ProtoMember(2)]
public PlayerActionType Action
{
get;
set;
}
[ProtoMember(3)]
public int SkillId
{
get;
set;
} // ATTACK, SKILL일 때
[ProtoMember(4)]
public int TargetId
{
get;
set;
} // 공격 대상
}
// STATE_PLAYER
[ProtoContract]
public class StatePlayerPacket
{
[ProtoMember(1)]
public int PlayerId
{
get;
set;
}
[ProtoMember(2)]
public int Hp
{
get;
set;
}
[ProtoMember(3)]
public int MaxHp
{
get;
set;
}
[ProtoMember(4)]
public int Mp
{
get;
set;
}
[ProtoMember(5)]
public int MaxMp
{
get;
set;
}
}
// ============================================================
// NPC
// ============================================================
public enum NpcActionType
{
IDLE,
MOVE,
ATTACK,
SKILL,
DIE
}
// TRANSFORM_NPC
[ProtoContract]
public class TransformNpcPacket
{
[ProtoMember(1)]
public int NpcId
{
get;
set;
}
[ProtoMember(2)]
public Position Position
{
get;
set;
}
[ProtoMember(3)]
public float RotY
{
get;
set;
}
}
// ACTION_NPC
[ProtoContract]
public class ActionNpcPacket
{
[ProtoMember(1)]
public int NpcId
{
get;
set;
}
[ProtoMember(2)]
public NpcActionType Action
{
get;
set;
}
[ProtoMember(3)]
public int PatternId
{
get;
set;
} // 사용 패턴/스킬 번호
[ProtoMember(4)]
public int TargetId
{
get;
set;
}
}
// STATE_NPC
[ProtoContract]
public class StateNpcPacket
{
[ProtoMember(1)]
public int NpcId
{
get;
set;
}
[ProtoMember(2)]
public int Hp
{
get;
set;
}
[ProtoMember(3)]
public int MaxHp
{
get;
set;
}
[ProtoMember(4)]
public int Phase
{
get;
set;
}
}
// ============================================================
// 데미지
// ============================================================
// DAMAGE
[ProtoContract]
public class DamagePacket
{
[ProtoMember(1)]
public int AttackerId
{
get;
set;
}
[ProtoMember(2)]
public int TargetId
{
get;
set;
}
[ProtoMember(3)]
public int Amount
{
get;
set;
}
[ProtoMember(4)]
public bool IsCritical
{
get;
set;
}
}
// ============================================================
// 에러
// ============================================================
public enum ErrorCode : int
{
// 파티 (10021~)
PARTY_ALREADY_IN_PARTY = 10021,
PARTY_JOIN_FAILED = 10022,
PARTY_NOT_IN_PARTY = 10023,
PARTY_DELETE_FAILED = 10024,
PARTY_UPDATE_FAILED = 10025,
}
// ERROR (서버 -> 클라)
[ProtoContract]
public class ErrorPacket
{
[ProtoMember(1)]
public ErrorCode Code
{
get;
set;
}
}
// ============================================================
// 파티
// ============================================================
public enum PartyUpdateType
{
CREATE,
DELETE,
JOIN,
LEAVE,
UPDATE
}
// REQUEST_PARTY (클라 -> 서버) - CREATE: PartyName 사용 / JOIN·LEAVE·DELETE: PartyId 사용
[ProtoContract]
public class RequestPartyPacket
{
[ProtoMember(1)]
public PartyUpdateType Type
{
get;
set;
}
[ProtoMember(2)]
public int PartyId
{
get;
set;
} // JOIN, LEAVE, DELETE 시 사용
[ProtoMember(3)]
public string PartyName
{
get;
set;
} // 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;
}
}
// ============================================================
// 맵 이동
// ============================================================
// CHANGE_MAP (클라 -> 서버 & 서버 -> 클라)
[ProtoContract]
public class ChangeMapPacket
{
[ProtoMember(1)]
public int MapId
{
get;
set;
}
// 새 맵의 기존 플레이어 목록 (이동한 본인에게 전달)
[ProtoMember(2)]
public List<PlayerInfo> Players
{
get;
set;
} = new List<PlayerInfo>();
// 입장(true) / 퇴장(false) - 기존 맵 플레이어들에게 전달
[ProtoMember(3)]
public bool IsAdd
{
get;
set;
}
// 이동한 플레이어 정보 - 기존 맵 플레이어들에게 전달
[ProtoMember(4)]
public PlayerInfo Player
{
get;
set;
}
}
// INTO_BOSS_RAID
// 클라->서버: RaidId
// 서버->클라: RaidId + IsSuccess (파티장에게 결과 전달)
// 성공 시 파티원 전체에게 CHANGE_MAP 추가 전송
[ProtoContract]
public class IntoBossRaidPacket
{
// 입장할 보스 레이드 맵 Id
[ProtoMember(1)]
public int RaidId
{
get;
set;
}
// 입장 성공 여부 (서버 -> 클라)
[ProtoMember(2)]
public bool IsSuccess
{
get;
set;
}
[ProtoMember(3)]
public string Token
{
get;
set;
}
[ProtoMember(4)]
public string Session
{
get;
set;
}
}
// PARTY_CHANGE_MAP (클라 -> 서버 전용)
[ProtoContract]
public class PartyChangeMapPacket
{
[ProtoMember(1)]
public int MapId
{
get;
set;
}
[ProtoMember(2)]
public int PartyId
{
get;
set;
}
}
// ============================================================
// 파티
// ============================================================
// UPDATE_PARTY (서버 -> 클라) - 파티 생성/삭제: LeaderId 사용 / 파티원 추가/제거: PlayerId 사용
[ProtoContract]
public class UpdatePartyPacket
{
[ProtoMember(1)]
public int PartyId
{
get;
set;
}
[ProtoMember(2)]
public PartyUpdateType Type
{
get;
set;
}
[ProtoMember(3)]
public int LeaderId
{
get;
set;
}
[ProtoMember(4)]
public int PlayerId
{
get;
set;
}
[ProtoMember(5)]
public string PartyName
{
get;
set;
} // CREATE일 때 사용
}