diff --git a/main/cl_dlls/client.dll b/main/cl_dlls/client.dll index d703ff97..486b9659 100644 Binary files a/main/cl_dlls/client.dll and b/main/cl_dlls/client.dll differ diff --git a/main/dlls/ns.dll b/main/dlls/ns.dll index eb627fde..0b4a8527 100644 Binary files a/main/dlls/ns.dll and b/main/dlls/ns.dll differ diff --git a/main/source/Natural_Selection.ncb b/main/source/Natural_Selection.ncb index 9c2adbb3..764fe88b 100644 Binary files a/main/source/Natural_Selection.ncb and b/main/source/Natural_Selection.ncb differ diff --git a/main/source/Natural_Selection.suo b/main/source/Natural_Selection.suo index 649d9ed1..3dd4cc21 100644 Binary files a/main/source/Natural_Selection.suo and b/main/source/Natural_Selection.suo differ diff --git a/main/source/cl_dll/chudmisc.h b/main/source/cl_dll/chudmisc.h index 14a780b1..5948e1ed 100644 --- a/main/source/cl_dll/chudmisc.h +++ b/main/source/cl_dll/chudmisc.h @@ -220,6 +220,8 @@ protected: }; class ScoreboardIcon; +// puzl: 0001073 +#define CUSTOM_ICON_LENGTH 32 struct extra_player_info_t { @@ -230,8 +232,10 @@ struct extra_player_info_t short frags; short deaths; short playerclass; + short auth; short teamnumber; char teamname[MAX_TEAM_NAME]; + char customicon[CUSTOM_ICON_LENGTH + 3]; //last 3 characters is the color. ScoreboardIcon* icon; }; diff --git a/main/source/cl_dll/cl_dll.vcproj b/main/source/cl_dll/cl_dll.vcproj index a366d526..5dd32302 100644 --- a/main/source/cl_dll/cl_dll.vcproj +++ b/main/source/cl_dll/cl_dll.vcproj @@ -27,7 +27,7 @@ Optimization="0" OptimizeForProcessor="0" AdditionalIncludeDirectories=""$(SolutionDir)";U:\inlcude\stlport;U:\include\vgui;U:\include\nexus;U:\include\libpng;U:\include\fmod;U:\include\lua;U:\include\particle;U:\include\zlib" - PreprocessorDefinitions="_DEBUG;_MBCS;DEBUG;WIN32;_WINDOWS;AVH_CLIENT;$(NoInherit)" + PreprocessorDefinitions="_DEBUG;_MBCS;DEBUG;WIN32;_WINDOWS;AVH_CLIENT;$(NoInherit);USE_OLDAUTH" MinimalRebuild="TRUE" BasicRuntimeChecks="3" SmallerTypeCheck="TRUE" @@ -113,7 +113,7 @@ EnableIntrinsicFunctions="TRUE" OptimizeForProcessor="0" AdditionalIncludeDirectories=""$(SolutionDir)";U:\inlcude\stlport;U:\include\vgui;U:\include\nexus;U:\include\libpng;U:\include\fmod;U:\include\lua;U:\include\particle;U:\include\zlib" - PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;AVH_CLIENT;AVH_PLAYTEST_BUILD;$(NOINHERIT)" + PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;AVH_CLIENT;AVH_PLAYTEST_BUILD;$(NOINHERIT);USE_OLDAUTH" StringPooling="TRUE" RuntimeLibrary="0" RuntimeTypeInfo="TRUE" @@ -131,7 +131,7 @@ Name="VCCustomBuildTool"/> playerclass; short theTeamNumber = theExtraPlayerInfo->teamnumber; + string theCustomIcon = (string)theExtraPlayerInfo->customicon; +// puzl: 0001073 + short thePlayerAuthentication = theExtraPlayerInfo->auth; bool thePlayerIsDead = false; switch( thePlayerClass ) { @@ -1043,11 +1067,121 @@ void ScorePanel::FillGrid() break; case COLUMN_RANK_ICON: +// puzl: 0001073 +#ifdef USE_OLDAUTH + // Check if we have authority. Right now these override the tracker icons. Listed in increasing order of "importance". + if(thePlayerAuthentication & PLAYERAUTH_CHEATINGDEATH) + { + // Red + pLabel->setImage(m_pCheatingDeathIcon); + pLabel->setFgColorAsImageColor(false); + m_pCheatingDeathIcon->setColor(BuildColor(255, 69, 9, gHUD.GetGammaSlope())); + } + if(thePlayerAuthentication & PLAYERAUTH_VETERAN) + { + // Yellow + pLabel->setImage(m_pVeteranIcon); + pLabel->setFgColorAsImageColor(false); + m_pVeteranIcon->setColor(BuildColor(248, 252, 0, gHUD.GetGammaSlope())); + } + if(thePlayerAuthentication & PLAYERAUTH_BETASERVEROP) + { + // Whitish + pLabel->setImage(m_pServerOpIcon); + pLabel->setFgColorAsImageColor(false); + m_pServerOpIcon->setColor(BuildColor(220, 220, 220, gHUD.GetGammaSlope())); + } + if(thePlayerAuthentication & PLAYERAUTH_CONTRIBUTOR) + { + // Light blue + pLabel->setImage(m_pContribIcon); + pLabel->setFgColorAsImageColor(false); + m_pContribIcon->setColor(BuildColor(117, 214, 241, gHUD.GetGammaSlope())); + } + if(thePlayerAuthentication & PLAYERAUTH_GUIDE) + { + // Magenta + pLabel->setImage(m_pGuideIcon); + pLabel->setFgColorAsImageColor(false); + m_pGuideIcon->setColor(BuildColor(208, 16, 190, gHUD.GetGammaSlope())); + } + if(thePlayerAuthentication & PLAYERAUTH_PLAYTESTER) + { + // Orange + pLabel->setImage(m_pPTIcon); + pLabel->setFgColorAsImageColor(false); + m_pPTIcon->setColor(BuildColor(255, 167, 54, gHUD.GetGammaSlope())); + } + if(thePlayerAuthentication & PLAYERAUTH_DEVELOPER) + { + // TSA blue + pLabel->setImage(m_pDevIcon); + pLabel->setFgColorAsImageColor(false); + m_pDevIcon->setColor(BuildColor(100, 215, 255, gHUD.GetGammaSlope())); + } + + if(thePlayerAuthentication & PLAYERAUTH_SERVEROP) + { + // Bright green + pLabel->setImage(m_pServerOpIcon); + pLabel->setFgColorAsImageColor(false); + m_pServerOpIcon->setColor(BuildColor(0, 255, 0, gHUD.GetGammaSlope())); + } + + // Allow custom icons to override other general icons + if(thePlayerAuthentication & PLAYERAUTH_CUSTOM) + { + if(theCustomIcon != "") + { + string theIconName = theCustomIcon.substr(0, strlen(theCustomIcon.c_str()) - 3); + string theFullCustomIconString = string("gfx/vgui/640_") + theIconName + string(".tga"); + + vgui::BitmapTGA *pIcon = GetIconPointer(theCustomIcon); + + //Icon hasnt been loaded, load it now and add it to list of icons. + if(pIcon == NULL) + { + pIcon = vgui_LoadTGANoInvertAlpha(theFullCustomIconString.c_str()); + + if(pIcon) + m_CustomIconList.push_back( make_pair(pIcon, theCustomIcon) ); + } + + if(pIcon) + { + pLabel->setImage(pIcon); + pLabel->setFgColorAsImageColor(false); + + // Parse color (last 3 bytes are the RGB values 1-9) + string theColor = theCustomIcon.substr( strlen(theCustomIcon.c_str())-3, 3); + int theRed = (MakeIntFromString(theColor.substr(0, 1))/9.0f)*255; + int theGreen = (MakeIntFromString(theColor.substr(1, 1))/9.0f)*255; + int theBlue = (MakeIntFromString(theColor.substr(2, 1))/9.0f)*255; + + pIcon->setColor(BuildColor(theRed, theGreen, theBlue, gHUD.GetGammaSlope())); + } + } + } + + if(g_pTrackerUser) + { + int playerSlot = theSortedRow; + int trackerID = gEngfuncs.GetTrackerIDForPlayer(playerSlot); + + if (g_pTrackerUser->IsFriend(trackerID) && trackerID != g_pTrackerUser->GetTrackerID()) + { + pLabel->setImage(m_pTrackerIcon); + pLabel->setFgColorAsImageColor(false); + m_pTrackerIcon->setColor(Color(255, 255, 255, 0)); + } + } +#else if( theExtraPlayerInfo->icon ) { vgui::Bitmap* image = theExtraPlayerInfo->icon->getImage( this->GetIconFrame() ); if( image ) { pLabel->setImage( image ); } } +#endif break; case COLUMN_SCORE: if(!theIsForEnemy) diff --git a/main/source/cl_dll/vgui_TeamFortressViewport.cpp b/main/source/cl_dll/vgui_TeamFortressViewport.cpp index 733fd44f..c4665c50 100644 --- a/main/source/cl_dll/vgui_TeamFortressViewport.cpp +++ b/main/source/cl_dll/vgui_TeamFortressViewport.cpp @@ -2558,6 +2558,8 @@ int TeamFortressViewport::MsgFunc_ScoreInfo( const char *pszName, int iSize, voi g_PlayerExtraInfo[info.player_index].frags = info.frags; g_PlayerExtraInfo[info.player_index].deaths = info.deaths; g_PlayerExtraInfo[info.player_index].playerclass = info.player_class; + // puzl: 0001073 + g_PlayerExtraInfo[info.player_index].auth = info.auth; g_PlayerExtraInfo[info.player_index].teamnumber = max( info.team, 0 ); // Icon is now handled through the ProfileInfo update diff --git a/main/source/dlls/hl.vcproj b/main/source/dlls/hl.vcproj index b07d47aa..7d73e70c 100644 --- a/main/source/dlls/hl.vcproj +++ b/main/source/dlls/hl.vcproj @@ -26,8 +26,8 @@ GlobalOptimizations="TRUE" InlineFunctionExpansion="2" EnableIntrinsicFunctions="TRUE" - AdditionalIncludeDirectories=""$(SolutionDir)";U:\include\stlport;U:\include\nexus;U:\include\lua;U:\include\particle" - PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;QUIVER;VOXEL;QUAKE2;VALVE_DLL;AVH_SERVER;AVH_PLAYTEST_BUILD;$(NOINHERIT)" + AdditionalIncludeDirectories=""$(SolutionDir)";U:\include\stlport;U:\include\nexus;U:\include\lua;U:\include\particle;U:\include\curl" + PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;QUIVER;VOXEL;QUAKE2;VALVE_DLL;AVH_SERVER;AVH_PLAYTEST_BUILD;$(NOINHERIT);AVH_SECURE_PRERELEASE_BUILD;USE_OLDAUTH" StringPooling="TRUE" MinimalRebuild="TRUE" RuntimeLibrary="0" @@ -46,7 +46,7 @@ Name="VCCustomBuildTool"/> + + InitializeAuthentication(); + UTIL_SayText("Initialized authentication.", theAvHPlayer); + } + theSuccess = true; + } + # endif else if(FStrEq(pcmd, kcSetBalanceVar)) { if( theAvHPlayer && theAvHPlayer->GetIsAuthorized(AUTH_ACTION_ADJUST_BALANCE,0) ) @@ -1409,7 +1421,12 @@ BOOL AvHGamerules::ClientCommand( CBasePlayer *pPlayer, const char *pcmd ) { AvHNexus::handleUnauthorizedJoinTeamAttempt(theAvHPlayer->edict(),TEAM_SPECT); } +// puzl: 0001073 +#ifdef USE_OLDAUTH + else if(allow_spectators.value && GetGameRules()->PerformHardAuthorization(theAvHPlayer)) +#else else if(allow_spectators.value) +#endif { if(theAvHPlayer->GetPlayMode() == PLAYMODE_READYROOM) { @@ -1544,6 +1561,28 @@ BOOL AvHGamerules::ClientCommand( CBasePlayer *pPlayer, const char *pcmd ) theSuccess = true; } } +// puzl: 0001073 +#ifdef USE_OLDAUTH + #ifndef AVH_SECURE_PRERELEASE_BUILD + else if(FStrEq(pcmd, kcAuth)) + { + // Toggle auth mask + bool theNewState = !theAvHPlayer->GetAllowAuth(); + theAvHPlayer->SetAllowAuth(theNewState); + + if(theNewState) + { + UTIL_SayText("Authentication ON\n", theAvHPlayer); + } + else + { + UTIL_SayText("Authentication OFF\n", theAvHPlayer); + } + + theSuccess = true; + } + #endif +#endif else if(FStrEq(pcmd, kcNumEnts)) { bool theEnableNumEnts = GetGameRules()->GetCheatsEnabled(); diff --git a/main/source/mod/AvHConstants.h b/main/source/mod/AvHConstants.h index e6ee3916..e3ad442e 100644 --- a/main/source/mod/AvHConstants.h +++ b/main/source/mod/AvHConstants.h @@ -276,6 +276,25 @@ typedef enum PLAYERCLASS_REINFORCINGCOMPLETE } AvHPlayerClass; +// puzl: 0001073 +#ifdef USE_OLDAUTH +// This is a mask because players can have more then one of these +typedef enum +{ + PLAYERAUTH_NONE = 0, + PLAYERAUTH_DEVELOPER = 1, + PLAYERAUTH_GUIDE = 2, + PLAYERAUTH_SERVEROP = 4, + PLAYERAUTH_PLAYTESTER = 8, + PLAYERAUTH_CONTRIBUTOR = 16, + PLAYERAUTH_CHEATINGDEATH = 32, + PLAYERAUTH_VETERAN = 64, + PLAYERAUTH_BETASERVEROP = 128, + PLAYERAUTH_PENDING = 256, + PLAYERAUTH_CUSTOM = 512, + PLAYERAUTH_UPP_MODE = 16384 +} AvHPlayerAuthentication; +#else // Mask replaced with explicit string set for GetIsMember function const static string PLAYERAUTH_DEVELOPER("dev"); const static string PLAYERAUTH_PLAYTESTER("pt"); @@ -284,6 +303,7 @@ const static string PLAYERAUTH_CONTRIBUTOR("const"); const static string PLAYERAUTH_SERVEROP("op"); const static string PLAYERAUTH_VETERAN("vet"); const static string PLAYERAUTH_BETASERVEROP("betaop"); +#endif typedef enum { diff --git a/main/source/mod/AvHGamerules.cpp b/main/source/mod/AvHGamerules.cpp index 9fa9f343..302fab39 100644 --- a/main/source/mod/AvHGamerules.cpp +++ b/main/source/mod/AvHGamerules.cpp @@ -201,6 +201,16 @@ #include "mod/AvHNetworkMessages.h" #include "mod/AvHNexusServer.h" +// puzl: 0001073 +#ifdef USE_OLDAUTH +AuthMaskListType gAuthMaskList; +extern const char* kSteamIDPending; +extern const char* kSteamIDLocal; +extern const char* kSteamIDBot; +extern const char* kSteamIDInvalidID; +extern const char* kSteamIDDefault; +#endif + AvHSoundListManager gSoundListManager; extern AvHVoiceHelper gVoiceHelper; CVoiceGameMgr g_VoiceGameMgr; @@ -347,6 +357,38 @@ int AvHGamerules::WeaponShouldRespawn(CBasePlayerItem *pWeapon) return GR_WEAPON_RESPAWN_NO; } +// puzl: 0001073 +#ifdef USE_OLDAUTH //players are authorized by UPP now. +const AuthIDListType& AvHGamerules::GetServerOpList() const +{ + return this->mServerOpList; +} + +bool AvHGamerules::PerformHardAuthorization(AvHPlayer* inPlayer) const +{ + bool theAuthorized = true; + + #ifdef AVH_SECURE_PRERELEASE_BUILD + if(!this->GetIsClientAuthorizedToPlay(inPlayer->edict(), false, true)) + { + char* theMessage = UTIL_VarArgs( + "%s<%s> is not authorized to play on beta NS servers.\n", + STRING(inPlayer->pev->netname), + AvHSUGetPlayerAuthIDString(inPlayer->edict()).c_str() + ); + ALERT(at_logged, theMessage); + + // Boot player off server + inPlayer->Kick(); + + theAuthorized = false; + } + #endif + + return theAuthorized; +} +#endif + // Sets the player up to join the team, though they may not respawn in immediately depending // on the ruleset and the state of the game. Assumes 1 or a 2 for team number bool AvHGamerules::AttemptToJoinTeam(AvHPlayer* inPlayer, AvHTeamNumber inTeamToJoin, bool inDisplayErrorMessage) @@ -360,6 +402,10 @@ bool AvHGamerules::AttemptToJoinTeam(AvHPlayer* inPlayer, AvHTeamNumber inTeamTo AvHNexus::handleUnauthorizedJoinTeamAttempt(inPlayer->edict(),inTeamToJoin); } else +// puzl: 0001073 +#ifdef USE_OLDAUTH + if(this->PerformHardAuthorization(inPlayer)) +#endif { int teamA = this->mTeamA.GetTeamNumber(); int teamB = this->mTeamB.GetTeamNumber(); @@ -618,6 +664,116 @@ void AvHGamerules::CalculateMapGamma() this->mCalculatedMapGamma = true; } +// puzl: 0001073 +#ifdef USE_OLDAUTH +BOOL AvHGamerules::GetIsClientAuthorizedToPlay(edict_t* inEntity, bool inDisplayMessage, bool inForcePending) const +{ + BOOL theIsAuthorized = false; + + #ifndef AVH_SECURE_PRERELEASE_BUILD + theIsAuthorized = true; + #endif + + #ifdef AVH_SECURE_PRERELEASE_BUILD + string theAuthID = AvHSUGetPlayerAuthIDString(inEntity); + const char* thePlayerName = STRING(inEntity->v.netname); + if(!strcmp(thePlayerName, "")) + { + thePlayerName = "unknown"; + } + + // Allow only select players to play + int theSecurityMask = PLAYERAUTH_DEVELOPER | PLAYERAUTH_PLAYTESTER | PLAYERAUTH_CONTRIBUTOR; + + // If any of these bits are set, allow them to play + int theAuthMask = 0; + + // Get the auth mask the cheap way if possible + AvHPlayer* thePlayer = dynamic_cast(CBaseEntity::Instance(inEntity)); + if(thePlayer) + { + theAuthMask = thePlayer->GetAuthenticationMask(); + } + else + { + theAuthMask = GetGameRules()->GetAuthenticationMask(theAuthID); + } + + if(theAuthMask & theSecurityMask) + { + if(inDisplayMessage) + { + char theAuthenticateString[512]; + sprintf(theAuthenticateString, "Player (%s -> %s) authenticated as privileged player.\r\n", thePlayerName, theAuthID.c_str()); + ALERT(at_logged, theAuthenticateString); + } + + theIsAuthorized = true; + } + // Pending + else if(theAuthID == kSteamIDPending) + { + if(!inForcePending) + { + // The player is authorized + theIsAuthorized = true; + } + } + // Local players or bots are always allowed + else if((theAuthID == kSteamIDLocal) || (theAuthID == kSteamIDBot)) + { + theIsAuthorized = true; + } + + // Display message on failure + if(!theIsAuthorized && inDisplayMessage) + { + char theAuthenticateString[512]; + sprintf(theAuthenticateString, "Player (%s -> %s) failed authentication.\r\n", thePlayerName, theAuthID.c_str()); + ALERT(at_logged, theAuthenticateString); + } + + #endif + + return theIsAuthorized; +} +#endif + +// puzl: 0001073 +#ifdef USE_OLDAUTH +BOOL AvHGamerules::ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] ) +{ + bool theAllowedToConnect = true; + BOOL theSuccess = false; + + #ifdef AVH_SECURE_PRERELEASE_BUILD + this->UpdateUplink(); + #endif + + #ifdef AVH_SECURE_PRERELEASE_BUILD + theAllowedToConnect = false; + theAllowedToConnect = this->GetIsClientAuthorizedToPlay(pEntity, true, false); + #endif + + if(theAllowedToConnect) + { + g_VoiceGameMgr.ClientConnected(pEntity); + + // Play connect sound + EMIT_SOUND(pEntity, CHAN_AUTO, kConnectSound, 0.8, ATTN_NORM); + + theSuccess = CHalfLifeTeamplay::ClientConnected(pEntity, pszName, pszAddress, szRejectReason); + } + else + { + sprintf(szRejectReason, "Only authorized players can join beta NS servers.\n"); + } + + return theSuccess; +} + +#else + BOOL AvHGamerules::ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] ) { BOOL theSuccess = false; @@ -630,6 +786,7 @@ BOOL AvHGamerules::ClientConnected( edict_t *pEntity, const char *pszName, const theSuccess = CHalfLifeTeamplay::ClientConnected(pEntity, pszName, pszAddress, szRejectReason); return theSuccess; } +#endif void AvHGamerules::ClientDisconnected( edict_t *pClient ) @@ -2553,6 +2710,11 @@ void AvHGamerules::InternalResetGameRules() this->mLastWorldEntityUpdate = -1; this->mLastCloakableUpdate = -1; this->mLastVictoryUpdate = -1; +// puzl: 0001073 +#ifdef USE_OLDAUTH //under UPP, we don't want to reestablish a connection with each new game + this->mUpdatedUplink = false; +#endif + } void AvHGamerules::CopyDataToSpawnEntity(const AvHSpawn& inSpawnEntity) const @@ -2640,6 +2802,56 @@ bool AvHGamerules::CanPlayerBeacon(CBaseEntity *inPlayer) } return result; } + +// puzl: 0001073 +#ifdef USE_OLDAUTH +unsigned int gTimeLastUpdatedUplink = 0; +void AvHGamerules::UpdateUplink() +{ + #ifdef AVH_SECURE_PRERELEASE_BUILD + avh_uplink.value = 1; + #endif + + // If authentication is enabled + if(!this->mUpdatedUplink && (avh_uplink.value > 0)) + { + // Only allow it once every day -> 500 servers == num queries per hour = 500*75k = 1,500k per hour -> just over a 1 gig a month + unsigned int theCurrentSystemTime = AvHSUTimeGetTime(); + int theUpdateUplinkInterval = (60*60*1000)*24; + + #ifdef AVH_SECURE_PRERELEASE_BUILD + theUpdateUplinkInterval = (60*60*1000)/30; // every 30 minutes or so while testing + #endif + + #ifdef DEBUG + theUpdateUplinkInterval = 0; + #endif + + if((gTimeLastUpdatedUplink == 0) || (theCurrentSystemTime > (gTimeLastUpdatedUplink + theUpdateUplinkInterval))) + { + // Initialize it + ALERT(at_logged, "Contacting www.natural-selection.org...\n"); + this->InitializeAuthentication(); + //this->DisplayVersioning(); + } + else + { + //ALERT(at_logged, "You must wait longer before uplinking again.\n"); + } + } + + // If it just turned off, clear auth masks + if(this->mUpdatedUplink && !avh_uplink.value) + { + gAuthMaskList.clear(); + ALERT(at_logged, "Authentication disabled.\n"); + } + + this->mUpdatedUplink = avh_uplink.value; +} +#endif + + edict_t* AvHGamerules::SelectSpawnPoint(CBaseEntity* inPlayer, const string& inSpawnEntityName) const { bool theDone = false; @@ -2975,6 +3187,10 @@ void AvHGamerules::Think(void) PROFILE_START(); AvHNexus::processResponses(); this->RecalculateHandicap(); +// puzl: 0001073 +#ifdef USE_OLDAUTH + this->UpdateUplink(); +#endif this->UpdatePlaytesting(); this->UpdateHLTVProxy(); PROFILE_END(kUpdateMisc); diff --git a/main/source/mod/AvHGamerules.h b/main/source/mod/AvHGamerules.h index 8ab0ad82..996df319 100644 --- a/main/source/mod/AvHGamerules.h +++ b/main/source/mod/AvHGamerules.h @@ -121,6 +121,11 @@ public: typedef vector< pair > MapVoteListType; typedef map< int, int > PlayerMapVoteListType; typedef map< int, float > PlayerVoteTimeType; +// puzl: 0001073 +#ifdef USE_OLDAUTH +typedef vector< pair > AuthIDListType; +typedef map AuthMaskListType; +#endif class AvHGamerules : public CHalfLifeTeamplay //public CHalfLifeMultiplay/*, public AvHCOCRuleset*/ { @@ -128,7 +133,16 @@ public: AvHGamerules(); virtual ~AvHGamerules(); - // this is the game name that gets seen in the server browser +// puzl: 0001073 +#ifdef USE_OLDAUTH + virtual BOOL GetIsClientAuthorizedToPlay(edict_t* inEntity, bool inDisplayMessage, bool inForcePending = false) const; + virtual bool PerformHardAuthorization(AvHPlayer* inPlayer) const; + virtual int GetAuthenticationMask(const string& inAuthID) const; + const AuthIDListType& GetServerOpList() const; + void UpdateUplink(); +#endif + + // this is the game name that gets seen in the server browser virtual int AmmoShouldRespawn( CBasePlayerAmmo *pAmmo ); virtual void BuildableBuilt(AvHBuildable* inBuildable); virtual void BuildableKilled(AvHBuildable* inBuildable); @@ -280,6 +294,15 @@ protected: //void PutPlayerIntoSpectateMode(AvHPlayer* inPlayer) const; virtual void SendMOTDToClient( edict_t *client ); + +// puzl: 0001073 +#ifdef USE_OLDAUTH + + void AddAuthStatus(AvHPlayerAuthentication inAuthMask, const string& inWONID, const string& inSteamID); + void DisplayVersioning(); + void InitializeAuthentication(); +#endif + private: void AwardExperience(AvHPlayer* inPlayer, int inTargetLevel, bool inAwardFriendliesInRange = true); void CalculateMapExtents(); @@ -333,6 +356,11 @@ private: AvHTeam mTeamB; float mVictoryTime; AvHMapMode mMapMode; +// puzl: 0001073 +#ifdef USE_OLDAUTH + bool mUpdatedUplink; + AuthIDListType mServerOpList; +#endif float mLastParticleUpdate; float mLastNetworkUpdate; diff --git a/main/source/mod/AvHNetworkMessages.cpp b/main/source/mod/AvHNetworkMessages.cpp index ef14bc66..9ea98900 100644 --- a/main/source/mod/AvHNetworkMessages.cpp +++ b/main/source/mod/AvHNetworkMessages.cpp @@ -3,7 +3,9 @@ #include "util/MathUtil.h" //for WrapFloat #include "util/STLUtil.h" //for MakeBytesFromHexPairs #include "cl_dll/parsemsg.h" - +#ifndef AVH_SERVER +#include "cl_dll/chudmisc.h" +#endif //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MESSAGE CODES - NEED TO BE INITIALIZED BEFORE CLIENT CONNECTION, OR THEY'D // BE LOCAL STATICS INSIDE OF THE FUNCTIONS USING LAZY INSTANTIATION @@ -45,7 +47,8 @@ void Net_InitializeMessages(void) g_msgMOTD = REG_USER_MSG( "MOTD", -1 ); g_msgResetHUD = REG_USER_MSG( "ResetHUD", 0 ); g_msgSayText = REG_USER_MSG( "SayText", -1 ); - g_msgScoreInfo = REG_USER_MSG( "ScoreInfo", 10 ); + // puzl: 0001073 + g_msgScoreInfo = REG_USER_MSG( "ScoreInfo", -1 ); g_msgServerName = REG_USER_MSG( "ServerName", -1 ); g_msgSetFOV = REG_USER_MSG( "SetFOV", 1 ); g_msgShake = REG_USER_MSG( "ScreenShake", 6 ); @@ -473,6 +476,7 @@ void Net_InitializeMessages(void) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// puzl: 0001073 #ifndef AVH_SERVER void NetMsg_ScoreInfo( void* const buffer, const int size, ScoreInfo& info ) { @@ -482,7 +486,23 @@ void Net_InitializeMessages(void) info.frags = READ_SHORT(); info.deaths = READ_SHORT(); info.player_class = READ_BYTE(); + info.auth = READ_SHORT(); info.team = READ_SHORT(); + char* theString = READ_STRING(); +#ifdef USE_OLDAUTH + if(info.auth & PLAYERAUTH_CUSTOM) + { + //clear the string (I dont think this array is reset anywhere else (since everything is set when the score info message is sent anyways) + //so just memset it here to prevent any possible problems. + memset(&g_PlayerExtraInfo[info.player_index].customicon, 0, sizeof(g_PlayerExtraInfo[info.player_index].customicon)); + + // Read custom icon + + + if(theString && strlen(theString) >= 4 && strlen(theString) <= CUSTOM_ICON_LENGTH+2)//make sure the string is within the right size. + strncpy(g_PlayerExtraInfo[info.player_index].customicon, theString, sizeof(g_PlayerExtraInfo[info.player_index].customicon)-1); + } +#endif END_READ(); } #else @@ -494,7 +514,9 @@ void Net_InitializeMessages(void) WRITE_SHORT( info.frags ); WRITE_SHORT( info.deaths ); WRITE_BYTE( info.player_class ); + WRITE_SHORT( info.auth ); WRITE_SHORT( info.team ); + WRITE_STRING("0"); MESSAGE_END(); } #endif diff --git a/main/source/mod/AvHPlayer.cpp b/main/source/mod/AvHPlayer.cpp index 24a4ca40..6ed8a6dc 100644 --- a/main/source/mod/AvHPlayer.cpp +++ b/main/source/mod/AvHPlayer.cpp @@ -274,7 +274,9 @@ extern AvHParticleTemplateListServer gParticleTemplateList; extern AvHSoundListManager gSoundListManager; extern cvar_t allow_spectators; extern cvar_t avh_marinereinforcementcost; - +#ifdef USE_OLDAUTH +extern cvar_t avh_uplink; +#endif #ifdef DEBUG extern cvar_t avh_spawninvulnerabletime; #endif @@ -1962,6 +1964,59 @@ AvHServerPlayerData* AvHPlayer::GetServerPlayerData() return theServerPlayerData; } +#ifdef USE_OLDAUTH +int AvHPlayer::GetAuthenticationMask() +{ + int theMask = 0; + + // Get WON id + if(this->GetAllowAuth()) + { + // Use cached value if valid + theMask = this->mCachedAuthenticationMask; + + // Look it up if uninitialized or Steam isn't ready yet + if((theMask == -1) || (theMask == PLAYERAUTH_PENDING)) + { + string theAuthID = AvHSUGetPlayerAuthIDString(this->edict()); + theMask = GetGameRules()->GetAuthenticationMask(theAuthID); + + // Save cached value + this->mCachedAuthenticationMask = theMask; + } + } + + bool theAllowAuthCheatMask = GetGameRules()->GetCheatsEnabled(); + + #ifdef AVH_LAN_PLAYTEST_BUILD + theAllowAuthCheatMask = true; + #endif + + if(theAllowAuthCheatMask) + { + theMask |= this->mAuthCheatMask; + } + return theMask; +} + +bool AvHPlayer::GetAllowAuth() const +{ + return (this->mAllowAuth && (avh_uplink.value > 0)); +} + + +void AvHPlayer::SetAllowAuth(bool inAllowAuth) +{ + this->mAllowAuth = inAllowAuth; +} + +void AvHPlayer::SetAuthCheatMask(int inAuthCheatMask) +{ + this->mAuthCheatMask = inAuthCheatMask; +} + +#endif + bool AvHPlayer::GetCurrentWeaponCannotHolster() const { bool theCannotHolster = false; @@ -3274,7 +3329,11 @@ void AvHPlayer::Init() this->mResources = 0; this->mScore = 0; this->mSavedCombatFrags = 0; - this->mLastModelIndex = -1; + this->mLastModelIndex = -1; +#ifdef USE_OLDAUTH + this->mCachedAuthenticationMask = -1; + +#endif this->mFirstUpdate = true; this->mNewMap = true; @@ -3456,6 +3515,10 @@ void AvHPlayer::Init() this->mPreThinkTicks = 0; this->mDesiredNetName = ""; +#ifdef USE_OLDAUTH + this->mAuthCheatMask = 0; + this->mAllowAuth = true; +#endif this->mTimeOfLastClassAndTeamUpdate = -1; this->mEffectivePlayerClassChanged = false; @@ -9158,6 +9221,7 @@ void AvHPlayer::UpdateEffectiveClassAndTeam() info.frags = this->pev->frags; info.deaths = this->m_iDeaths; info.player_class = this->GetEffectivePlayerClass(); + info.auth = this->GetAuthenticationMask(); info.team = GetGameRules()->GetTeamIndex(this->TeamID()); NetMsg_ScoreInfo( info ); this->mEffectivePlayerClassChanged = false; @@ -9505,7 +9569,7 @@ void AvHPlayer::UpdateTechNodes() if(theTeam) { // Propagate and use local tech nodes in combat mode, else use team nodes in NS mode - AvHTechTree theTechNodes = theIsCombatMode ? this->mCombatNodes : theTeam->GetTechNodes(); + AvHTechTree& theTechNodes = theIsCombatMode ? this->mCombatNodes : theTeam->GetTechNodes(); // Now customize nodes for aliens in NS if(theIsNSMode && this->GetIsAlien()) @@ -9838,10 +9902,17 @@ bool AvHPlayer::GetIsAuthorized(AvHAuthAction inAction, int inParameter) const } } +#ifdef USE_OLDAUTH +bool AvHPlayer::GetIsMember(const AvHPlayerAuthentication inAuthGroup) +{ + return (this->GetAuthenticationMask() & inAuthGroup); +} +#else bool AvHPlayer::GetIsMember(const string& inAuthGroup) const { return false; } +#endif //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/main/source/mod/AvHPlayer.h b/main/source/mod/AvHPlayer.h index c70ebb12..949ca913 100644 --- a/main/source/mod/AvHPlayer.h +++ b/main/source/mod/AvHPlayer.h @@ -348,7 +348,15 @@ public: //Nexus interface - replaces all old auth information bool GetIsAuthorized(AvHAuthAction inAction, int inParameter) const; +#ifdef USE_OLDAUTH + int GetAuthenticationMask(); + bool GetIsMember(const AvHPlayerAuthentication inAuthGroup); + bool GetAllowAuth() const; + void SetAllowAuth(bool inAllowAuth); + void SetAuthCheatMask(int inAuthCheatMask); +#else bool GetIsMember(const string& inAuthGroup) const; +#endif //END Nexus interface float GetTimeLastPlaying() const; @@ -847,6 +855,12 @@ private: mutable BalanceIntCollection mBalanceMapInts; mutable BalanceStringCollection mBalanceMapStrings; float mNextBalanceVarUpdate; +#ifdef USE_OLDAUTH + bool mAllowAuth; + int mAuthCheatMask; + int mCachedAuthenticationMask; +#endif + }; typedef vector PlayerListType; diff --git a/main/source/mod/AvHServerUtil.cpp b/main/source/mod/AvHServerUtil.cpp index 63b9a45a..37a4dc04 100644 --- a/main/source/mod/AvHServerUtil.cpp +++ b/main/source/mod/AvHServerUtil.cpp @@ -241,6 +241,48 @@ const char* AvHSUGetTeamName(int inTeamNumber) return theTeamName; } +#ifdef USE_OLDAUTH +// Steam IDs +const char* kSteamIDPending = "STEAM_ID_PENDING"; +const char* kSteamIDLocal = "STEAM_ID_LOOPBACK"; +const char* kSteamIDBot = "BOT"; +const char* kSteamIDInvalidID = "-1"; +const char* kSteamIDDefault = "STEAM_0:0:0"; +const char* kSteamIDPrefix = "STEAM_"; +bool AvHSUGetIsValidAuthID(const string& inAuthID) +{ + bool theIsValid = true; + + // "0" is WONid that hasn't been entered + if((inAuthID == "") || (inAuthID == " ") || (inAuthID == "0") || (inAuthID == kSteamIDDefault) || (inAuthID == kSteamIDInvalidID) || (inAuthID == kSteamIDBot) || (inAuthID == kSteamIDLocal)) + { + theIsValid = false; + } + + return theIsValid; +} +// Function that is backwards-compatible with WON ids +string AvHSUGetPlayerAuthIDString(edict_t* inPlayer) +{ + string thePlayerAuthID; + + // Try to get SteamID + const char* theSteamID = g_engfuncs.pfnGetPlayerAuthId(inPlayer); + if(strcmp(theSteamID, kSteamIDInvalidID)) + { + thePlayerAuthID = theSteamID; + } + // If that fails, get WonID and put it into a string + else + { + int theWonID = g_engfuncs.pfnGetPlayerWONId(inPlayer); + thePlayerAuthID = MakeStringFromInt(theWonID); + } + + return thePlayerAuthID; +} +#endif + void AvHSUKillPlayersTouchingPlayer(AvHPlayer* inPlayer, entvars_t* inInflictor) { // If new player is stuck inside another player, kill old player diff --git a/main/source/mod/AvHServerUtil.h b/main/source/mod/AvHServerUtil.h index 96950818..72d3df20 100644 --- a/main/source/mod/AvHServerUtil.h +++ b/main/source/mod/AvHServerUtil.h @@ -131,6 +131,11 @@ Vector AvHSUGetRandomBuildingAngles(); char* AvHSUGetGameVersionString(); bool AvHSUGetIsRelevantForTopDownPlayer(const vec3_t& inTopDownPosition, const vec3_t& inEntityPosition, float inScalar = 1.0f); const char* AvHSUGetTeamName(int inTeamNumber); +#ifdef USE_OLDAUTH +bool AvHSUGetIsValidAuthID(const string& inAuthID); +string AvHSUGetPlayerAuthIDString(edict_t* inPlayer); +#endif + void AvHSUKillPlayersTouchingPlayer(AvHPlayer* inPlayer, entvars_t* inInflictor); void AvHSUKillBuildablesTouchingPlayer(AvHPlayer* inPlayer, entvars_t* inInflictor); void AvHSUBuildingJustCreated(AvHMessageID inBuildID, CBaseEntity* theBuilding, AvHPlayer* inPlayer); diff --git a/main/source/mod/AvHSharedTypes.h b/main/source/mod/AvHSharedTypes.h index fd7a3986..f31447a8 100644 --- a/main/source/mod/AvHSharedTypes.h +++ b/main/source/mod/AvHSharedTypes.h @@ -60,6 +60,7 @@ typedef struct ScoreInfo_s int frags; int deaths; int player_class; + int auth; int team; } ScoreInfo; diff --git a/main/source/mod/AvHTeam.cpp b/main/source/mod/AvHTeam.cpp index 9edff8db..bda3724a 100644 --- a/main/source/mod/AvHTeam.cpp +++ b/main/source/mod/AvHTeam.cpp @@ -2482,6 +2482,7 @@ void AvHTeam::UpdateResources() } // puzl: 1041 // o Added back in steamid based authids +#ifndef USE_OLDAUTH #ifdef AVH_PLAYTEST_BUILD // Function that is backwards-compatible with WON ids string AvHSUGetPlayerAuthIDString(edict_t* inPlayer) @@ -2505,6 +2506,7 @@ string AvHSUGetPlayerAuthIDString(edict_t* inPlayer) return thePlayerAuthID; } #endif +#endif AvHServerPlayerData* AvHTeam::GetServerPlayerData(edict_t* inEdict) { #ifdef AVH_PLAYTEST_BUILD