요구사항
- IGameState는 모든 virtual을 override한다. Enter에 이미지 로드를 추가한다.(기본이미지 dragon.png)
- enum으로 플레이어에 직업 추가 정의 필요(기본, 탱커, 힐러)
- Packet과 NetworkManager 정의 시 #pragma region COOP으로 묶어서 작성
클래스 정의
- COOPManager: 싱글턴, 플레이어들의 스테이터스 기록, 보스 몬스터 기록, 전투 로직 담당
- COOPReadyState, COOPSelectJobState, COOPBattleState, COOPRewardState extends IGameState
상태 정의
- COOPReadyState
- 직업 선택 시 COOPSelectJobState로 클라 상태 전환
PKT_C2S_COOP_Ready시PKT_C2S_COOP_Update_Status도 전송- 모든 플레이어가
PKT_C2S_COOP_Ready전송하면PKT_S2C_CHANGE_STATECOOPBattleState
- COOPSelectJobState
- 1, 2, 3 직업선택, 0 돌아가기
- COOPBattleState
- Ready 순서로 플레이어 턴 순서 결정
PKT_S2C_COOP_Update_Turn시 플레이어는 턴 시작(아니면 턴 대기) - 플레이어는
PKT_C2S_COOP_Use_AttackPKT_C2S_COOP_Use_BlockPKT_C2S_COOP_Use_HealPKT_C2S_COOP_Use_Item중 1가지 선택 가능(Block은 탱커, Heal은 힐러 클래스만 제공됨) - 서버에서는
PKT_C2S_COOP_Use_Attack시 몬스터 데미지 갱신,PKT_C2S_COOP_Use_Block을 받았다면 block 대상자에게 가는 공격을 block 시전자로 갱신 - 계산이 끝나면
PKT_C2S_COOP_Update_StatusPKT_S2C_COOP_Update_Monster로 각각 전장 갱신 - 만약 isDead인 플레이어면 관전 전환
- 만약 보스 사망 시
PKT_S2C_CHANGE_STATE로 COOPRewardState
- Ready 순서로 플레이어 턴 순서 결정
- COOPRewardState
- 각 플레이어들
PKT_C2S_COOP_Update_Status로 체력 업데이트,PKT_S2C_COOP_Take_Item으로 레이드 보상 PKT_S2C_CHANGE_STATE로 GameStartState
- 각 플레이어들
패킷 정의
name은 최대 32바이트 char
C2S
PKT_C2S_COOP_Readybool isReadyPKT_C2S_COOP_Update_Statusint atk, int hp, enum job, bool isDeadPKT_C2S_COOP_Use_ItemtargetName , int amountPKT_C2S_COOP_Use_AttacksourceName, targetName, int amountPKT_C2S_COOP_Use_BlocksourceName, targetNamePKT_C2S_COOP_Use_HealsourceName, targetName, int amount
S2C
PKT_S2C_CHANGE_STATEEGameState targetStatePKT_S2C_COOP_Update_Statusint atk, int hp, enum jobPKT_S2C_COOP_Update_TurntargetName, int turnPKT_S2C_COOP_Update_MonstertargetName, int hpPKT_S2C_COOP_Take_ItemtargetName, itemName
개인 참고용

사전 준비: 패킷 구조체 정의
가장 먼저 Packet.h에 통신할 데이터를 정의해야 합니다.
PacketTypeEnum에PKT_C2S_...와PKT_S2C_...추가- C2S와 S2C 각각에 사용할 패킷 구조체(
struct) 정의 (Header 상속 및 사이즈 지정)
1단계: C2S (Client to Server) 파이프라인 구현
클라이언트가 "나 이거 할게"라고 서버에 요청하고, 서버가 이를 처리하는 과정입니다.
Send...함수 작성 (요청 발송)- 위치:
NetworkManager - 역할: UI State에서 호출되는 진입점입니다. 패킷 구조체를 채웁니다.
- 주의: 방장 최적화 로직이 반드시 들어가야 합니다.C++
if (Client::isServer) { OnHost새기능(INVALID_SOCKET, pkt); // 방장은 통신 생략 } else { SendToServer(&pkt, pkt.header.size); // 게스트는 패킷 전송 }
- 위치:
ProcessPacket분기 추가 (서버 수신부)- 위치:
NetworkManager::ProcessPacket - 역할:
switch문에PKT_C2S_...케이스를 추가하고, 데이터 캐스팅 후OnHost...함수로 넘겨줍니다. 방장(Client::isServer)만 이 분기를 타도록 방어 코드가 필요합니다.
- 위치:
OnHost...함수 작성 (서버 로직 처리)- 위치:
NetworkManager - 역할: 패킷을 받은 서버가 실행하는 핵심 로직입니다.
- 구현 내용: * 데이터 유효성 검사 (턴이 맞는지, 쿨타임인지, 살아있는지 등)
- 내부 데이터 상태 갱신 (데미지 적용 등)
- 처리가 끝난 후 결과를 클라이언트들에게 알리기 위해 S2C 1단계의
Broadcast...함수를 호출합니다.
- 위치:
2단계: S2C (Server to Client) 파이프라인 구현
서버가 "이런 결과가 나왔으니 화면을 업데이트해라"라고 모든 클라이언트에게 전파하는 과정입니다.
Broadcast...함수 작성 (결과 전파)- 위치:
NetworkManager - 역할:
OnHost...처리 직후 호출됩니다. S2C 패킷 구조체를 조립합니다. - 구현 내용:
BroadcastToClients()를 호출하여 접속 중인 모든 게스트 소켓에 전송합니다.- 방장 로컬 화면도 업데이트해야 하므로
Notify...함수를 함께 호출합니다.
- 위치:
ProcessPacket분기 추가 (클라이언트 수신부)- 위치:
NetworkManager::ProcessPacket - 역할: 게스트가
PKT_S2C_...케이스를 수신했을 때의 처리입니다. 서버 로직이 아니므로Client::isServer일 때는 무시(break)하도록 합니다. 수신한 패킷을Notify...함수로 넘깁니다.
- 위치:
Notify...함수 작성 (로컬 옵저버 알림)- 위치:
NetworkManager - 역할: 네트워크 계층에서 수신된 데이터를 게임(UI) 계층으로 밀어 넣습니다.
- 구현 내용:
GameManager를 통해 현재 State 포인터를 가져온 뒤,dynamic_cast로 타겟 State(예:ArenaBattleState)인지 확인하고, 타겟 State의On...함수를 호출합니다.
- 위치:
On...함수 작성 (UI 및 상태 갱신)- 위치: 타겟 State 클래스 (예:
ArenaBattleState) - 역할: 전달받은 네트워크 결과를 멤버 변수에 저장하고,
Update()루프를 통해 화면에 렌더링되도록 합니다.
- 위치: 타겟 State 클래스 (예: