Room을 생성하여 채팅을 할 수 있도록 구현
- Room 생성
- [PacketManager] CreateRommManager() 함수에서 RoomManager 객체 생성
- [RoomManager] Init() 함수에서 maxRoomCount 만큼의 Room 객체를 생성해두고 추후 사용
- Room 입장
- [PacketManager] ProcessPacket() 함수에서 확인한 패킷 데이터의 Id가 ROOM_ENTER_REQUEST일 경우
- [PacketManger] ProcessEnterRoom() 함수에서 응답으로 보내줄 패킷을 생성
- 유저가 존재하지 않는 경우 에러코드로 ENTER_ROOM_NOT_FIND_USER를 가진 응답을 전송
- 로그인하지 않은 유저의 요청일 경우 에러코드로 ENTER_ROOM_INVALID_USER_STATUS를 가진 응답을 전송
- 유저가 이미 방에 들어가 있는 경우 에러코드로 ENTER_ROOM_ALREADY를 가진 응답을 전송
- 그 외에는 Room의 EnterUser() 함수를 호출하여 응답 패킷의 Result 값으로 저장하여 전송
- [RoomManager] EnterUser() 함수에서 roomNumber에 따른 Room을 선택
- 올바르지 않은 roomNumber일 경우 에러코드로 ROOM_INVALID_INDEX를 반환
- 정상적인 roomNumber일 경우 Room의 EnterUser() 함수를 호출하여 반환값으로 사용
- [Room] EnterUser() 함수에서 해당 방의 유저 카운트를 확인
- 유저 카운트 수가 최대 유저 수 이상이라면 에러코드로 ENTER_ROOM_FULL_USER를 반환
- 최대 유저 수를 넘지 않는다면 유저 리스트에 유저를 추가하고, 유저의 EnterRoom() 함수를 호출하여 유저에게도 Room에 들어갔음을 알림
- Room 퇴장
- Room 입장 과정과 로직은 거의 동일
- 에러 케이스 처리만 조금씩 다른 부분이 존재
- Room 채팅
- [PacketManager] ProcessPacket() 함수에서 확인한 패킷 데이터의 Id가 ROOM_CHAT_REQUEST일 경우
- [PacketManger] ProcessRoomChatMessage() 함수에서 응답으로 보내줄 패킷을 생성, 각종 에러 케이스 처리 후 응답 패킷을 전송
- [Room] NotifyChat() 함수에서 ROOM_CHAT_REQUEST_PACKET을 생성
- [Room] SendToAllUser() 함수에서 Room에 존재하는 유저들에게 패킷을 전송
- Room.h
- Room에 속해있는 유저들을 list 형태로 관리
std::list<User*> mUserList;
void SendToAllUser(const UINT16 dataSize_, char* data_, const INT32 passUserIndex_, bool exceptMe)
{
for (auto pUser : mUserList)
{
if (pUser == nullptr)
{
continue;
}
if (exceptMe && pUser->GetNetConnIdx() == passUserIndex_)
{
continue;
}
SendPacketFunc((UINT32)pUser->GetNetConnIdx(), (UINT32)dataSize_, data_);
}
}
UINT16 EnterUser(User *user_)
{
if (mCurrentUserCount >= mMaxUserCount)
{
return (UINT16)ERROR_CODE::ENTER_ROOM_FULL_USER;
}
mUserList.push_back(user_);
++mCurrentUserCount;
user_->EnterRoom(mRoomNum);
return (UINT16)ERROR_CODE::NONE;
}
UINT16 LeaveUser(User *leaveUser_)
{
bool finduser = false;
mUserList.remove_if([&finduser, leaveUserId = leaveUser_->GetUserId()](User*& pUser) {
if (leaveUserId == pUser->GetUserId())
{
finduser = true;
}
return leaveUserId == pUser->GetUserId();
});
if (finduser == false)
{
return (UINT16)ERROR_CODE::ROOM_NOT_FIND_USER;
}
return (UINT16)ERROR_CODE::NONE;
}
void NotifyChat(INT32 clientIndex_, const char *userID_, const char *msg_)
{
ROOM_CHAT_NOTIFY_PACKET roomChatNotifyPacket;
roomChatNotifyPacket.PacketId = (UINT16)PACKET_ID::ROOM_CHAT_NOTIFY;
roomChatNotifyPacket.PacketLength = sizeof(roomChatNotifyPacket);
CopyMemory(roomChatNotifyPacket.Msg, msg_, sizeof(roomChatNotifyPacket.Msg));
CopyMemory(roomChatNotifyPacket.UserID, userID_, sizeof(roomChatNotifyPacket.UserID));
SendToAllUser(sizeof(roomChatNotifyPacket), (char*)&roomChatNotifyPacket, clientIndex_, false);
}
};
- RoomManager.h
- 생성되어있는 Room들을 vector 형태로 관리
std::vector<Room*> mRoomList;
void Init(const UINT32 beginRoomNumber_, const UINT32 maxRoomCount_, const UINT32 maxRoomUserCount_)
{
mBeginRoomNumber = beginRoomNumber_;
mMaxRoomCount = maxRoomCount_;
mEndRoomNumber = beginRoomNumber_ + maxRoomCount_;
mRoomList = std::vector<Room*>(maxRoomCount_);
for (UINT32 i = 0; i < maxRoomCount_; i++)
{
mRoomList[i] = new Room();
mRoomList[i]->SendPacketFunc = SendPacketFunc;
mRoomList[i]->Init((i + beginRoomNumber_), maxRoomUserCount_);
}
}
UINT16 EnterUser(UINT32 roomNumber_, User* user_)
{
auto pRoom = GetRoomByNumber(roomNumber_);
if (pRoom == nullptr)
{
std::cout << "Invalid RoomNumber\n";
return (UINT16)ERROR_CODE::ROOM_INVALID_INDEX;
}
return pRoom->EnterUser(user_);
}
UINT16 LeaveUser(INT32 roomNumber_, User *user_)
{
auto pRoom = GetRoomByNumber(roomNumber_);
if (pRoom == nullptr)
{
return (UINT16)ERROR_CODE::ROOM_INVALID_INDEX;
}
user_->SetDomainState(User::DOMAIN_STATE::LOGIN);
return (pRoom->LeaveUser(user_));
}
'개인공부 > IOCP 서버 제작 실습' 카테고리의 다른 글
IOCP 서버 제작 실습 10 (1) | 2023.03.27 |
---|---|
IOCP 서버 제작 실습 9 (0) | 2023.03.27 |
IOCP 서버 제작 실습 7 (0) | 2023.03.25 |
IOCP 서버 제작 실습 6 (0) | 2023.03.23 |
IOCP 서버 제작 실습 5 (0) | 2023.03.23 |
댓글