Files
Sun1602/Server/AgentServer/Zone/RoomInterface.h
T
2022-10-26 12:25:11 +08:00

287 lines
10 KiB
C++

#pragma once
//==================================================================================================
/// RoomInterface 클래스
/**
@author Kim Min Wook < taiyo@webzen.com >
@since 2005. 9. 20
@remark
-
@note
-
@history
-
@usage
-
*/
//==================================================================================================
#include <Timer.h>
#include "ZoneInterface.h"
enum eROOMSTATE_TYPE
{
eROOMSTATE_NONE, //< 아무것도 아닌 상태
eROOMSTATE_READY, //< 준비상태
eROOMSTATE_GENERNAL, //< 일반적인상태
eROOMSTATE_DESTROY, //< 파괴된 방
};
class Party;
struct MSG_AG_ZONE_CAN_CREATE_ROOM_ACK;
typedef util::SolarHashTable<Party *>::iterator PARTY_ITERATOR;
//==================================================================================================
//
class RoomInterface : public ZoneInterface
{
friend class ZoneManager; //< CanJoin()
public:
enum {
MAX_DESTROY_TIMEOUT_TIME = 10 * 60 * 1000,
MAX_RELAY_TIMEOUT_TIME = 10 * 60 * 1000,
};
RoomInterface(void);
virtual ~RoomInterface(void);
inline User* GetMaster() { return m_pMasterUser; }
inline eZONEPUBLIC GetZonePublic() const { return (eZONEPUBLIC)m_byRoomPublic; }
inline TCHAR* GetRoomTitle() { return m_pszRoomTitle; }
inline TCHAR* GetRoomPWD() { return m_pszRoomPWD; }
inline eROOMSTATE_TYPE GetRoomState() const { return m_RoomState; }
inline void SetRoomState(eROOMSTATE_TYPE sts) { m_RoomState = sts; }
virtual BOOL IsRoomType() const { return TRUE; }
inline void SetLimitMaxUserNum(BYTE num) { m_MaxLimitUserNum = num; }
inline BYTE GetLimitMaxUserNum() const { return m_MaxLimitUserNum; }
virtual BOOL RecommendLevel(LEVELTYPE level) { __UNUSED(level); return FALSE; }
//virtual MAPCODE GetMapCode() { return m_MapCode; }
RC::eROOM_RESULT IsRecommendRoom(User* pUser);
void VestUserWithMaster(User* pExpectedMaster);
User* GetNextPriorityMaster(RoomInterface* pRoom, DWORD curMasterKey,
eROOM_SPECIAL_TYPE* OUT pRoomSpecialTypeByUser);
User* ChangeSpecialType(BOOLEAN isEnterEvent, User* pMaster);
// 평균 레벨, 승률
LEVELTYPE GetAvgLevel();
void GetCHuntingScore(BYTE& byAvgWinPercent, DWORD& dwTotCount);
protected:
void Create(User* pUser,
KEYTYPE key, MAPCODE MapCode,
eZONEPUBLIC ePublic, TCHAR* pszRoomTitle, TCHAR* pszRoomPWD,
BASE_ROOMINFO& IN baseRoomInfo,
ServerSession* pServerSession);
RC::eROOM_RESULT CanCreate(User* pUser,
MAPCODE MapCode, eZONETYPE eZoneType, eZONEPUBLIC ePublic,
BASE_ROOMINFO& IN baseRoomInfo, BOOL CheckOpenTime = TRUE);
//{__NA1279_1281_090209_TIMELINE_QUEST_BASED_MISSION__
// Setting by ZoneManager
void ChangePolicy(PolicymentForRoom::POLICY_T newPolicySet);
virtual RC::eROOM_RESULT MigratePortalUserFirstEnter(KEYTYPE key,
const RoomArgumentForRoomSetup& rRoomArgument,
User* pUser, ServerSession* pServerSession);
//}
public:
virtual RC::eROOM_RESULT _CanJoinAll(User* pUser, eZONEPUBLIC RoomPublic, TCHAR* pszRoomPWD);
#if defined(__NA_000000_20070528_TAIWAN_GUILD_PVP) && defined(__TW_0_20080521_GUILD_PVP_BUG_FIX)
// 대만 길드전 체크는 헌팅룸에만 속하지 않을수 있고, 룸의 타입체크는 룸정보 구조체를 가진 this클래스에서 체크
RC::eROOM_RESULT CanJoinGuildPVP(User* pUser);
BOOL IsSpecialType(eROOM_SPECIAL_TYPE SpecialType) { return m_RoomInfo.IsSpecialType(SpecialType); }
#endif//__NA_000000_20070528_TAIWAN_GUILD_PVP
BOOL ValidCharClass(eCHAR_TYPE type);
BOOL ValidLevel(LEVELTYPE LV);
BOOL ValidJoinMap(User* pUser);
virtual BOOL CanShowAtRoomList(User* pUser, eZONEPUBLIC RoomPublic, TCHAR* pszRoomPWD);
virtual RC::eROOM_RESULT Migrate(KEYTYPE key, RoomInterface* pPreviousRoom,
ServerSession* pServerSession);
void RelayUser(RoomInterface* pPreviousRoom);
virtual BOOL Process();
virtual void On_create();
virtual void On_destroy();
virtual void On_readyuser(User* pUser);
virtual void On_enteruser(User* pUser);
virtual void On_leaveuser(User* pUser);
//void SetMapCode(MAPCODE code);
inline void SetZonePublic(eZONEPUBLIC pub);
inline void SetRoomPWD(TCHAR* pw);
inline void SetRoomInfo(const BASE_ROOMINFO* pRoomInfo);
inline void SetMaster(User* pUser);
inline void SetRoomTitle(const TCHAR* title);
inline BASE_ROOMINFO* GetRoomInfo() { return &m_RoomInfo; }
// (WAVERIX) (NOTE) 하기 interface는 자료구조 변경 이후 수정하기로 한다.
inline virtual DWORD GetCurUserNum() { return ZoneInterface::GetUserNum() + m_RelayUserHash.GetDataNum(); }
inline util::SolarHashTable<User*>& GetRelayHash() { return m_RelayUserHash; }
inline User* FindRelayUser(DWORD PlayerKey) { return m_RelayUserHash.GetData(PlayerKey); }
inline void RemoveRelayUser(DWORD playerKey) { m_RelayUserHash.Remove(playerKey); }
inline void AddRelayUser(User* pUser, DWORD playerKey) { m_RelayUserHash.Add(pUser, playerKey); }
//__NA000000_090622_MOB_ABILITY_CONTROL_CHANGE__
inline BYTE GetNumberOfExpectedPlayers() const { return m_NumberOfExpectedPlayers; }
inline void SetNumberOfExpectedPlayers(BYTE number_of_players);
bool ExceptionProcessByLobbyMember(const MSG_AG_ZONE_CAN_CREATE_ROOM_ACK* check_msg, User* request_user);
PolicymentForRoom RoomPolicyment; // Property
private:
virtual BOOL CheckLimitUser(User* pUser);
//////////////////////////////////////////////////////////////////////////
// Fields
eROOMSTATE_TYPE m_RoomState;
util::Timer m_DestroyTimeout;
util::Timer m_MasterEnterTimeout;
util::SolarHashTable<User*> m_RelayUserHash;
// 방정보
User* m_pMasterUser;
BYTE m_NumberOfExpectedPlayers; //__NA000000_090622_MOB_ABILITY_CONTROL_CHANGE__
BYTE m_byRoomPublic; //< eZONEPUBLIC
TCHAR m_pszRoomTitle[MAX_ROOMTITLE_LENGTH + 1]; //< 안전한 문자열 처리를 위해 +1
TCHAR m_pszRoomPWD[MAX_ROOMPASSWORD_LENGTH + 1]; //< 안전한 문자열 처리를 위해 +1
BYTE m_MaxLimitUserNum;
BASE_ROOMINFO m_RoomInfo; //< 생성할 방 정보
};
//
//==================================================================================================
//
inline void
RoomInterface::SetNumberOfExpectedPlayers(BYTE number_of_players) {
//__NA000000_090622_MOB_ABILITY_CONTROL_CHANGE__
m_NumberOfExpectedPlayers = number_of_players;
}
inline void
RoomInterface::SetZonePublic(eZONEPUBLIC pub)
{
m_byRoomPublic = static_cast<uint8_t>(pub);
}
inline void
RoomInterface::SetRoomPWD(TCHAR* pw)
{
if(pw == 0)
return;
_tcsncpy(m_pszRoomPWD, pw, _countof(m_pszRoomPWD));
m_pszRoomPWD[_countof(m_pszRoomPWD) - 1] = '\0';
}
inline void
RoomInterface::SetRoomInfo(const BASE_ROOMINFO* pRoomInfo)
{
m_RoomInfo = *pRoomInfo;
}
inline void
RoomInterface::SetMaster(User* pUser)
{
m_pMasterUser = pUser;
}
inline void
RoomInterface::SetRoomTitle(const TCHAR* title)
{
_tcsncpy(m_pszRoomTitle, title, _countof(m_pszRoomTitle));
m_pszRoomTitle[_countof(m_pszRoomTitle) - 1] = '\0';
}
//==================================================================================================
//
template <class SRC_ROOM, class TARGET_ROOM, int Transaction>
class RoomMigrater
{
SRC_ROOM* m_SrcRoom;
TARGET_ROOM* m_pTargetRoom;
public:
RoomMigrater(SRC_ROOM* pSrc, TARGET_ROOM* pTarget) : m_SrcRoom(pSrc), m_pTargetRoom(pTarget) {}
~RoomMigrater() {}
void operator()(User* pUser)
{
pUser->BeginTransaction((eBEHAVE_TRANSACTION)Transaction);
m_SrcRoom->LeaveUser(pUser, eSEND_SYN, m_pTargetRoom->GetType(), m_pTargetRoom->GetLinkedServerIndex());
// 헌팅키를 저장해둠!!!!
pUser->SetTRRoomKey(m_pTargetRoom->GetKey());
DISPMSG("[U:%s]room(%u)_Leave_Syn\n", pUser->GetUserID(), m_pTargetRoom->GetKey());
}
};
//_NA_20110630_BATTLE_ZONE_RENEWAL
template <class TARGET_ROOM, int Transaction>
class RoomMigraterByParty
{
TARGET_ROOM* target_room_;
public:
RoomMigraterByParty(TARGET_ROOM* target_room) : target_room_(target_room){}
~RoomMigraterByParty(){}
void operator()(_PARTY_MEMBER_INFO* member_info)
{
User* user = UserManager::Instance()->GetUserByObjKey(member_info->m_dwMemberKey);
if (user == NULL)
{
SUNLOG(eCRITICAL_LOG, __FUNCTION__" : Not found user : %d", member_info->m_dwMemberKey);
return;
}
WORD party_key = user->GetPartyState().GetPartyKey();
DWORD master_key = AgentPartyManager::Instance()->GetMasterKey(party_key);
if (user->GetPlayerKey() == master_key)
{
return;
}
ZoneInterface* current_zone_interface = g_ZoneManager.FindZone(user->GetZoneKey());
if (current_zone_interface == NULL)
{
SUNLOG(eCRITICAL_LOG, __FUNCTION__ " : Not found zone : %d", user->GetUserGUID());
return;
}
user->BeginTransaction((eBEHAVE_TRANSACTION)Transaction);
current_zone_interface->LeaveUser(user, eSEND_SYN, target_room_->GetType(),
target_room_->GetLinkedServerIndex());
user->SetTRRoomKey(target_room_->GetKey());
}
};
//==================================================================================================
//
struct ChangeRoomName : public std::unary_function<User*, void>
{
MSG_CG_ZONE_EX_LOBBY_NAME_CHANGE_ACK m_SendData;
explicit ChangeRoomName(const char* pszRoomName)
{
BOOST_STATIC_ASSERT(_countof(m_SendData.m_pszRoomTitle) == MAX_ROOMTITLE_LENGTH);
strncpy(m_SendData.m_pszRoomTitle, pszRoomName, _countof(m_SendData.m_pszRoomTitle));
m_SendData.m_pszRoomTitle[_countof(m_SendData.m_pszRoomTitle) - 1] = '\0';
}
inline void operator()(User* pUser)
{
pUser->SendPacket(&m_SendData, sizeof(m_SendData));
}
};