//======== (C) Copyright 2002 Charles G. Cleveland All rights reserved. ========= // // The copyright to the contents herein is the property of Charles G. Cleveland. // The contents may be used and/or copied only with the written permission of // Charles G. Cleveland, or in accordance with the terms and conditions stipulated in // the agreement/contract under which the contents have been supplied. // // Purpose: // // $Workfile: UPPUtil.h $ // $Date: 2002/11/12 22:39:25 $ // //------------------------------------------------------------------------------- // $Log: UPPUtil.h,v $ //=============================================================================== #ifdef USE_UPP #include "build.h" #include "dlls/extdll.h" #include "util/STLUtil.h" #include "mod/AvHServerUtil.h" #include "mod/AvHSharedUtil.h" #include "mod/AvHGamerules.h" #include "mod/UPPUtil.h" #include "AvHConstants.h" // TODO: // Move AuthGroup functionality into own logical section? // Move NetworkIDManager class and functionality into another file? // Add logic to clear temporary id cache intelligently to prevent dynamic ips from // causing collisions across multiple players; this should be a very rare occurance // even with the current code. // Fix UPPUtil_GetDefaultAuthorization to match Auth system's default behavior. // Add cheating death status to Auth mask? // Resolve HL version // Resolve Plugins // Resolve Gamestate - gamestate key-value pairs hold the name of a variable and // a concatentated listing of all of the values the variable has held at some point // during the round, e.g. ("sv_cheats","0:1") if sv_cheats had been turned on partway // through, then back off... a tracking method needs to be implemented for the // variables, a list of variables to track needs to be finalized, and the code to // transform a set of values into the final format needs to be written. // Implement unauthorized team join handler //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ typedef map AuthGroupMap; //CONSIDER: STLPort's hash map implementation instead bool UPPUtil_GetDefaultAuthorization(void) { bool theDefaultAuthorization = true; #ifdef AVH_PLAYTEST_BUILD theDefaultAuthorization = false; #endif return theDefaultAuthorization; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int UPPUtil_GetDefaultAuthMask(void) { return PLAYERAUTH_NONE; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string UPPUtil_GetDefaultScoreboardIcon(void) { return ""; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ map UPPUtil_CreateAuthGroupMap(void) { AuthGroupMap theMap; theMap.insert(AuthGroupMap::value_type("betaop",PLAYERAUTH_BETASERVEROP)); theMap.insert(AuthGroupMap::value_type("const",PLAYERAUTH_CONTRIBUTOR)); theMap.insert(AuthGroupMap::value_type("dev",PLAYERAUTH_DEVELOPER)); theMap.insert(AuthGroupMap::value_type("guide",PLAYERAUTH_GUIDE)); theMap.insert(AuthGroupMap::value_type("op",PLAYERAUTH_SERVEROP)); theMap.insert(AuthGroupMap::value_type("pt",PLAYERAUTH_PLAYTESTER)); theMap.insert(AuthGroupMap::value_type("vet",PLAYERAUTH_VETERAN)); return theMap; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int UPPUtil_GetAuthMask(const StringSet inAuthGroups) { int theAuthMask = PLAYERAUTH_NONE; //step 1 - convert auth groups into mask if(!inAuthGroups.empty()) { static AuthGroupMap theMap = UPPUtil_CreateAuthGroupMap(); AuthGroupMap::iterator theMapEntry; StringSet::const_iterator end = inAuthGroups.end(); for(StringSet::const_iterator i = inAuthGroups.begin(); i != end; ++i) { theMapEntry = theMap.find(*i); if(theMapEntry != theMap.end()) { theAuthMask |= theMapEntry->second; } } } return theAuthMask; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void UPPUtil_ProcessProfileInfo(auto_ptr inProfileInfo) { UPP::ProfileInfo* theProfileInfo = inProfileInfo.release(); UPPUtil_StoreProfileInfo(theProfileInfo); if(UPP::getGeneratePerformanceData()) //report if we're profiling { AvHSUPrintDevMessage(string("UPP ProfileInfo Received for ") + theProfileInfo->getNetworkID() + "\n",true); } AvHPlayer* thePlayer = NULL; FOR_ALL_ENTITIES(kAvHPlayerClassName, AvHPlayer*) if(!theEntity->GetNetworkID().compare(theProfileInfo->getNetworkID())) { thePlayer = theEntity; break; } END_FOR_ALL_ENTITIES(kAvHPlayerClassName) if(thePlayer) { UPPUtil_InitializePlayer(thePlayer); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void UPPUtil_ProcessPerformanceData(auto_ptr data) { string theMessage("UPP Signal Returned: "); theMessage += data->getSignalType() + " "; theMessage += MakeStringFromInt(data->getTimeInQueue()) + "/"; theMessage += MakeStringFromInt(data->getTimeInProcessing()-data->getTimeInProcessingOnServer()) + "/"; theMessage += MakeStringFromInt(data->getTimeInProcessingOnServer()) + " ms; "; theMessage += MakeStringFromInt(data->getRequestSize()) + "/"; theMessage += MakeStringFromInt(data->getResponseSize()) + " bytes; "; theMessage += MakeStringFromInt(data->getErrorCode()) + " "; theMessage += data->getErrorDescription() + " \n"; AvHSUPrintDevMessage(theMessage,true); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TeamSet UPPUtil_BuildTeamInfoList(void) { TeamSet theTeamInfoList; UPP::TeamInfo readyroom(TEAM_IND,"readyroom"); UPP::TeamInfo marines(TEAM_ONE,"marines"); UPP::TeamInfo aliens(TEAM_TWO,"aliens"); UPP::TeamInfo spectators(TEAM_SPECT,"spectators"); UPP::PlayerInfo player; FOR_ALL_ENTITIES(kAvHPlayerClassName, AvHPlayer*) player = UPPUtil_GetPlayerInfo(theEntity); switch(player.getTeamIndex()) { case TEAM_ONE: marines.addPlayer(player); break; case TEAM_TWO: aliens.addPlayer(player); break; case TEAM_IND: readyroom.addPlayer(player); break; case TEAM_SPECT: spectators.addPlayer(player); break; } END_FOR_ALL_ENTITIES(kAvHPlayerClassName) theTeamInfoList.insert(readyroom); theTeamInfoList.insert(marines); theTeamInfoList.insert(aliens); theTeamInfoList.insert(spectators); // Return them return theTeamInfoList; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ StringMap UPPUtil_BuildServerVariableList(bool GameEndVariables) { StringMap theVariableList; auto_ptr varsToUse = GameEndVariables ? UPP::listGameEndVariables() : UPP::listGameStartVariables(); string theKey; string theValue; const char* theRawValue; StringSet::const_iterator end = varsToUse->end(); for(StringSet::const_iterator i = varsToUse->begin(); i != end; ++i) { theKey.assign(*i); theRawValue = CVAR_GET_STRING(theKey.c_str()); if(theRawValue) { theValue = theRawValue; } else { theValue.clear(); } theVariableList.insert(StringMap::value_type(theKey,theValue)); } return theVariableList; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UPP::GameInfo UPPUtil_GetGameInfo(void) { string theGameType; switch(GetGameRules()->GetMapMode()) { case MAP_MODE_CO: theGameType.assign("CO"); break; case MAP_MODE_NS: theGameType.assign("NS"); break; } UPP::GameInfo game(theGameType); // Map name string theMapName = STRING(gpGlobals->mapname); game.setMapName(theMapName); // Add team infos TeamSet theTeamInfoList = UPPUtil_BuildTeamInfoList(); TeamSet::iterator end = theTeamInfoList.end(); for(TeamSet::iterator theTeamIter = theTeamInfoList.begin(); theTeamIter != end; ++theTeamIter) { game.addTeam(*theTeamIter); } StringMap theVariableValueList = UPPUtil_BuildServerVariableList(false); StringMap::iterator SMend = theVariableValueList.end(); for(StringMap::iterator theIter = theVariableValueList.begin(); theIter != SMend; ++theIter) { game.addVariable(theIter->first, theIter->second); } return game; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UPP::GameResultInfo UPPUtil_GetGameResultInfo(const int WinningTeam) { UPP::GameResultInfo result; result.setWinningTeam(WinningTeam); // Add team infos TeamSet theTeamInfoList = UPPUtil_BuildTeamInfoList(); TeamSet::iterator end = theTeamInfoList.end(); for(TeamSet::iterator theTeamIter = theTeamInfoList.begin(); theTeamIter != end; ++theTeamIter) { result.addTeam(*theTeamIter); } StringMap theVariableValueList = UPPUtil_BuildServerVariableList(true); StringMap::iterator SMend = theVariableValueList.end(); for(StringMap::iterator theIter = theVariableValueList.begin(); theIter != SMend; ++theIter) { result.addVariable(theIter->first, theIter->second); } return result; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UPP::PlayerInfo UPPUtil_GetConnectingPlayerInfo(edict_t* edict, const char* name, const char* address) { UPP::PlayerInfo player; player.setNetworkID(UPPUtil_GenerateNetworkID(edict,address)); player.setName(string(name)); player.setScore(0); player.setKills(0); player.setExperience(0.0f); player.setDeaths(0); player.setClass("none"); player.setTeamIndex(TEAM_IND); return player; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UPP::PlayerInfo UPPUtil_GetPlayerInfo(const AvHPlayer* inPlayer) { UPP::PlayerInfo player; string theName = STRING(inPlayer->pev->netname); player.setName(theName); player.setNetworkID(inPlayer->GetNetworkID()); player.setScore(inPlayer->GetScore()); player.setKills(inPlayer->pev->frags); player.setExperience(inPlayer->GetExperience()); player.setDeaths(inPlayer->m_iDeaths); switch(inPlayer->GetPlayMode()) { case PLAYMODE_READYROOM: player.setClass("none"); player.setTeamIndex(TEAM_IND); break; case PLAYMODE_OBSERVER: player.setClass("spectator"); player.setTeamIndex(TEAM_SPECT); break; default: const char* theUser3Name = AvHSHUGetClassNameFromUser3(inPlayer->GetUser3()); player.setClass(string(theUser3Name)); player.setTeamIndex(inPlayer->GetTeam()); break; } return player; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UPP::ClientInfo UPPUtil_GetClientInfo(void) { UPP::ClientInfo client; //Name const char* theCStrServerName = CVAR_GET_STRING("hostname"); client.setName(theCStrServerName ? string(theCStrServerName) : "Unspecified Server Name"); //IP Address & Port string theAddress("?.?.?.?"); int thePort = 0; const char* theCStrServerAddress = CVAR_GET_STRING("net_address"); if(theCStrServerAddress) { theAddress.assign(theCStrServerAddress); int theColonIndex = theAddress.find(':'); if(theColonIndex != string::npos) { thePort = MakeIntFromString(theAddress.substr(theColonIndex+1)); theAddress.resize(theColonIndex); } else { const char* theCStrPort = CVAR_GET_STRING("port"); if(theCStrPort) { thePort = MakeIntFromString(string(theCStrPort)); } } } client.setAddress(theAddress); client.setPort(thePort); // TODO: Plug-ins // Region const char* theCStrRegion = CVAR_GET_STRING("sv_region"); client.setRegion(theCStrRegion ? MakeIntFromString(string(theCStrRegion)) : 255); // TODO: Engine version string theEngineVersion = "1.1.1.0"; // WON: 1.1.1.0, STEAM: 1.1.2.0 client.setEngineVersion(theEngineVersion); // Game version string theGameVersion = AvHSUGetGameVersionString(); client.setGameVersion(theGameVersion); // Contact const char* theCStrContact = CVAR_GET_STRING("sv_contact"); client.setContact(theCStrContact ? string(theCStrContact) : ""); return client; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void UPPUtil_ConnectPlayer(edict_t* inEntity, const char* inName, const char* inAddress) { UPP::PlayerInfo thePlayerInfo = UPPUtil_GetConnectingPlayerInfo(inEntity,inName,inAddress); bool theResolved = UPPUtil_GetPlayerIsResolved(inEntity); UPP::reportPlayerEntered(thePlayerInfo,theResolved); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void UPPUtil_ResetPlayer(AvHPlayer* inPlayer) { inPlayer->SetAuthenticationMask(UPPUtil_GetDefaultAuthMask()); inPlayer->SetAuthorized(UPPUtil_GetDefaultAuthorization()); inPlayer->SetScoreboardIconName(UPPUtil_GetDefaultScoreboardIcon()); inPlayer->EffectivePlayerClassChanged(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void UPPUtil_HandleUnauthorizedJoinTeamAttempt(AvHPlayer* inPlayer, AvHTeam inTeamNumber) { } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void UPPUtil_InitializePlayer(CBasePlayer* inPlayer) { AvHPlayer* thePlayer = dynamic_cast(inPlayer); if(thePlayer) { thePlayer->SetNetworkAddress(UPPUtil_GetNetworkAddress(inPlayer->edict())); thePlayer->SetNetworkID(UPPUtil_GetNetworkID(inPlayer->edict())); UPPUtil_ResetPlayer(thePlayer); if(UPP::isConnected()) { UPP::ProfileInfo* theProfileInfo = UPPUtil_GetProfileInfo(thePlayer->GetNetworkID()); if(theProfileInfo) { thePlayer->SetAuthorized(theProfileInfo->getAuthorized()); thePlayer->SetAuthenticationMask(UPPUtil_GetAuthMask(theProfileInfo->getAuthGroups())); thePlayer->SetScoreboardIconName(theProfileInfo->getIconName()); thePlayer->EffectivePlayerClassChanged(); } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void UPPUtil_ProcessResponses(void) { //process ProfileInfos while(UPP::hasProfileInfo()) { UPPUtil_ProcessProfileInfo(UPP::getProfileInfo()); } //process PerformanceData while(UPP::hasPerformanceData()) { UPPUtil_ProcessPerformanceData(UPP::getPerformanceData()); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void UPPUtil_Disconnect(void) //actual function registered with atexit { UPP::disconnect(); FOR_ALL_ENTITIES(kAvHPlayerClassName, AvHPlayer*) UPPUtil_ResetPlayer(theEntity); END_FOR_ALL_ENTITIES(kAvHPlayerClassName) } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void UPPUtil_RegisterShutdown(void) { static bool registered = false; if(!registered) { atexit(UPPUtil_Disconnect); registered = true; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void UPPUtil_Connect(void) { UPP::setServerConnection("https://24.5.210.1/upp_server-dev/index.php","soap"); UPP::connect(UPPUtil_GetClientInfo()); UPP::requestAuthGroups(); UPP::requestVariables(); FOR_ALL_ENTITIES(kAvHPlayerClassName, AvHPlayer*) UPP::reportPlayerEntered(UPPUtil_GetPlayerInfo(theEntity),UPPUtil_GetPlayerIsResolved(theEntity->edict())); END_FOR_ALL_ENTITIES(kAvHPlayerClassName) UPPUtil_RegisterShutdown(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Network ID management functions for use with UPP // CONSIDER: this class isn't multithreading safe - do we need it to be? //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //CONSIDER: using hash_map instead typedef map NetworkIDMap; typedef map AddressMap; //key = edict, value = address typedef map ProfileInfoMap; typedef map TemporaryIDMap; //key = address, value = id class NetworkIDManager { public: const static string STEAM_ID_PENDING; const static string STEAM_ID_LAN; const static string WON_ID_LAN; const static string UNRESOLVED_PREFIX; static NetworkIDManager* GetInstance(void); ~NetworkIDManager(void); const string GenerateID(edict_t* inEntity, const char* inAddress); const string RetrieveID(const edict_t* inEntity) const; const string RetrieveAddress(const edict_t* inEntity) const; UPP::ProfileInfo* GetProfileInfo(const string& inNetworkID) const; void SetProfileInfo(const string& inNetworkID, UPP::ProfileInfo* info); bool GetIsResolved(const edict_t* inEntity); bool UpdateID(edict_t* inEntity); bool ClearForLevelReset(void); private: auto_ptr GenerateResolvedID(edict_t* inEntity); NetworkIDManager(void); NetworkIDMap mNetworkIDs; AddressMap mAddresses; ProfileInfoMap mProfiles; TemporaryIDMap mUnresolvedIDs; int mNextTempIDNumber; }; const string NetworkIDManager::STEAM_ID_PENDING("STEAM_ID_PENDING"); const string NetworkIDManager::STEAM_ID_LAN("STEAM_ID_LAN"); const string NetworkIDManager::WON_ID_LAN("-1"); const string NetworkIDManager::UNRESOLVED_PREFIX("UNKNOWN_"); NetworkIDManager::NetworkIDManager(void) : mNextTempIDNumber(1000) {} NetworkIDManager::~NetworkIDManager(void) {} //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkIDManager* NetworkIDManager::GetInstance(void) { static auto_ptr ptr(new NetworkIDManager()); return ptr.get(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool NetworkIDManager::ClearForLevelReset(void) { this->mNetworkIDs.clear(); this->mAddresses.clear(); this->mProfiles.clear(); return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ auto_ptr NetworkIDManager::GenerateResolvedID(edict_t* inEntity) { //(1) attempt to resolve it using STEAM auto_ptr theNetworkID(new string(g_engfuncs.pfnGetPlayerAuthId(inEntity))); if(!theNetworkID->compare(STEAM_ID_PENDING) || !theNetworkID->compare(STEAM_ID_LAN)) { //(2) attempt to resolve it using WON theNetworkID->assign(MakeStringFromInt(g_engfuncs.pfnGetPlayerWONId(inEntity))); if(!theNetworkID->compare(WON_ID_LAN)) { //(3) couldn't resolve it, return NULL theNetworkID.reset(); } } return theNetworkID; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const string NetworkIDManager::GenerateID(edict_t* inEntity, const char* inAddress) { string theAddress(inAddress); //(1) attempt to resolve it auto_ptr theNetworkID = this->GenerateResolvedID(inEntity); if(theNetworkID.get() == NULL) { //(2) attempt to retrieve temporary id matching the address - it's probably // a reconnection from the last map change and the same person... TemporaryIDMap::iterator theEntry = this->mUnresolvedIDs.find(inAddress); if(theEntry != this->mUnresolvedIDs.end()) { theNetworkID.reset(new string(theEntry->second)); } else { //(3) generate new temporary id and store in temporary id storage string theTempID(UNRESOLVED_PREFIX + MakeStringFromInt(this->mNextTempIDNumber)); ++this->mNextTempIDNumber; this->mUnresolvedIDs.insert(TemporaryIDMap::value_type(inAddress,theTempID)); theNetworkID.reset(new string(theTempID)); } } this->mNetworkIDs.insert(NetworkIDMap::value_type(inEntity,*theNetworkID.get())); this->mAddresses.insert(AddressMap::value_type(inEntity,theAddress)); return string(*theNetworkID.get()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const string NetworkIDManager::RetrieveID(const edict_t* inEntity) const { NetworkIDMap::const_iterator theEntry = this->mNetworkIDs.find(inEntity); return theEntry->second; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const string NetworkIDManager::RetrieveAddress(const edict_t* inEntity) const { AddressMap::const_iterator theEntry = this->mAddresses.find(inEntity); return theEntry->second; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool NetworkIDManager::GetIsResolved(const edict_t* inEntity) { return this->RetrieveID(inEntity).compare(0,UNRESOLVED_PREFIX.size(),UNRESOLVED_PREFIX); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool NetworkIDManager::UpdateID(edict_t* inEntity) { auto_ptr theNewID(NULL); if(!this->GetIsResolved(inEntity)) { theNewID = this->GenerateResolvedID(inEntity); if(theNewID.get()) { //remove this edict from the temporary list AddressMap::iterator theEntry = this->mAddresses.find(inEntity); this->mUnresolvedIDs.erase(theEntry->second); } } return theNewID.get(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UPP::ProfileInfo* NetworkIDManager::GetProfileInfo(const string& inNetworkID) const { UPP::ProfileInfo* theProfile = NULL; ProfileInfoMap::const_iterator i = this->mProfiles.find(inNetworkID); if(i != this->mProfiles.end()) { theProfile = i->second; } return theProfile; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void NetworkIDManager::SetProfileInfo(const string& inNetworkID, UPP::ProfileInfo* info) { this->mProfiles.insert(ProfileInfoMap::value_type(inNetworkID,info)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string UPPUtil_GenerateNetworkID(edict_t* inEntity, const char* inAddress) { return NetworkIDManager::GetInstance()->GenerateID(inEntity,inAddress); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string UPPUtil_GetNetworkID(const edict_t* inEntity) { return NetworkIDManager::GetInstance()->RetrieveID(inEntity); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string UPPUtil_GetNetworkAddress(const edict_t* inEntity) { return NetworkIDManager::GetInstance()->RetrieveAddress(inEntity); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool UPPUtil_GetPlayerIsResolved(edict_t* inEntity) { return NetworkIDManager::GetInstance()->GetIsResolved(inEntity); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool UPPUtil_GetPlayerIsResolved(const AvHPlayer* inPlayer) { return NetworkIDManager::GetInstance()->GetIsResolved(const_cast(inPlayer)->edict()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UPP::ProfileInfo* UPPUtil_GetProfileInfo(const string& inNetworkID) { return NetworkIDManager::GetInstance()->GetProfileInfo(inNetworkID); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bool UPPUtil_ResolvePlayer(AvHPlayer* inPlayer) { bool theUpdated = NetworkIDManager::GetInstance()->UpdateID(inPlayer->edict()); if(theUpdated) { string theNewID = NetworkIDManager::GetInstance()->RetrieveID(inPlayer->edict()); UPP::reportPlayerChangingIDs(UPPUtil_GetPlayerInfo(inPlayer),theNewID,true); inPlayer->SetNetworkID(theNewID); } return theUpdated; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void UPPUtil_StoreProfileInfo(UPP::ProfileInfo* info) { NetworkIDManager::GetInstance()->SetProfileInfo(info->getNetworkID(),info); } #endif