//++ BulliT #include "hud.h" #include "cl_util.h" #include "const.h" #include "com_model.h" #include "studio.h" #include "entity_state.h" #include "cl_entity.h" #include "dlight.h" #include "triangleapi.h" #include "studio_util.h" #include "r_studioint.h" #include "AgVariableChecker.h" #include "AgModelCheck.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// #ifdef AG_USE_CHEATPROTECTION extern engine_studio_api_t IEngineStudio; #define MAX_VIOLATIONS 5 struct VARIABLES { char szName[20]; double dMin; double dMax; double dDefault; bool bKeepSame; bool bAllowChangeAtInit; }; static VARIABLES s_Variables[]= { //Evironment "r_lightmap",-1,0,-1,false,true, "direct",0.9,0.9,0.9,false,true, "brightness",0,30,1,false,true, "lambert",1.5,1.5,1.5,true,true, "cl_solid_players",1,1,1,false,true, "cl_himodels",0,1,0,true,false, //Sounds "s_distance",10,60,60,false,true, "s_min_distance",1,20,8,false,true, "s_max_distance",20,1000,1000,false,true, "s_occlude",0,1,1,false,true, "s_occfactor",0.20,0.25,0.25,false,true, "s_refgain",0.4,0.45,0.41,false,true, //Cheats is somehow client also? "sv_cheats",0,0,0,true,true, }; static VARIABLES s_VariablesFast[]= { //Movement "m_pitch",-0.044,0.044,0.022,false,true, "cl_backspeed",300,500,400,false,true, "cl_sidespeed",300,500,400,false,true, "cl_forwardspeed",300,500,400,false,true, "cl_upspeed",300,500,320,false,true, "default_fov",30,130,90,false,true, //Net settings "cl_updaterate",15,100,30,false,true, "cl_cmdrate",15,100,30,false,true, "ex_extrapmax",1.2,1.2,1.2,false,true, #ifdef CLIENT_WEAPONS "ex_interp",0.05,0.1,0.1,false,true, #else "ex_interp",0.1,0.1,0.1,false,true, #endif // Fixed in next patch. "ex_minvelocity",0,0,0,false,true, "ex_maxspeed",750,750,750,false,true, "ex_maxaccel",2000,2000,2000,false,true, "ex_maxerrordistance",64,64,64,false,true, "cl_nopred",0,0,0,false,true, "ex_correct",0,0,0,false,true, "ex_diminishextrap",0,0,0,false,true, }; /* ex_correct ex_extrapmax ex_maxerror distance cl_nopred */ static VARIABLES s_VariablesHardware[]= { //Open GL settings. // "lightgamma",0,3,2.5,true,false, // "texgamma",1,3,2,true,false, "gl_max_size",128,512,512,false,false, "gl_zmax",2048,9999,4096,false,true, "gl_alphamin",0.25,0.25,0.25,false,true, "gl_nobind",0,0,0,false,true, "gl_picmip",0,2,0,false,true, "gl_playermip",0,5,0,false,true, //"gl_spriteblend",1,1,1,true,true, "gl_monolights",0,0,0,true,true, }; static VARIABLES s_VariablesPure2[]= { "s_distance",10,10,10,false,true, "s_rolloff",10,10,10,false,true, "s_min_distance",8,8,8,false,true, "s_max_distance",1000,1000,1000,false,true, }; static VARIABLES s_VariablesPure3[]= { "s_a3d",0,0,0,false,true, }; AgVariableChecker g_VariableChecker; static char szDisconnect[] = "disconnect\n"; AgVariableChecker::AgVariableChecker() { m_bHardware = false; m_bInit = false; m_dwNextCheck = m_dwNextCheckFast = m_dwNextA3D = GetTickCount(); m_iViolations = 0; m_bActive = false; } AgVariableChecker::~AgVariableChecker() { } void AgVariableChecker::Activate() { m_bActive = true; m_bInit = false; } bool InitVariables(VARIABLES* pvarArray,int iElements) { for (int i = 0; i < iElements; i++) { if (!gEngfuncs.pfnGetCvarPointer(pvarArray[i].szName )) continue; double dValue = gEngfuncs.pfnGetCvarFloat(pvarArray[i].szName); if (dValue < (pvarArray[i].dMin - 0.0001) ||dValue > (pvarArray[i].dMax + 0.0001)) { if (pvarArray[i].bAllowChangeAtInit) { //Correct it. gEngfuncs.Cvar_SetValue(pvarArray[i].szName, pvarArray[i].dDefault); //This dudes standard aint good enough - corrected it for him. char szMessage[256]; sprintf(szMessage,"Server enforces variables and \"%s\" was automatically reset to the HL default %f.\n",pvarArray[i].szName,pvarArray[i].dDefault); ConsolePrint(szMessage); AgLog(szMessage); } else { //This dudes standard aint good enough. char szMessage[256]; sprintf(szMessage,"Server enforces variables and \"%s\" needs to be between %f and %f. Your variable is set to %f.\n",pvarArray[i].szName,pvarArray[i].dMin,pvarArray[i].dMax,dValue); ConsolePrint(szMessage); AgLog(szMessage); return false; } } //Save this value as default. pvarArray[i].dDefault = gEngfuncs.pfnGetCvarFloat(pvarArray[i].szName); if (pvarArray[i].bKeepSame) pvarArray[i].dMin = pvarArray[i].dMax = pvarArray[i].dDefault; } return true; } void CheckVariables(VARIABLES* pvarArray,int iElements, short& iViolations) { for (int i = 0; i < iElements; i++) { if (!gEngfuncs.pfnGetCvarPointer(pvarArray[i].szName )) continue; double dValue = gEngfuncs.pfnGetCvarFloat(pvarArray[i].szName); if (dValue < (pvarArray[i].dMin - 0.0001) ||dValue > (pvarArray[i].dMax + 0.0001)) { char szMessage[256]; if (pvarArray[i].bKeepSame && pvarArray[i].bAllowChangeAtInit) sprintf(szMessage,"Server enforces variables and \"%s\" needs to be the same during the game\n",pvarArray[i].szName); else sprintf(szMessage,"Server enforces variables and \"%s\" needs to be between %f and %f.\n",pvarArray[i].szName,pvarArray[i].dMin,pvarArray[i].dMax); ConsolePrint(szMessage); if (pvarArray[i].bAllowChangeAtInit) { //Reset to previous value. gEngfuncs.Cvar_SetValue(pvarArray[i].szName, pvarArray[i].dDefault); iViolations++; } else { iViolations = MAX_VIOLATIONS + 1; } sprintf(szMessage,"say Warned for using variable %s with value %lf (%d violation(s)",pvarArray[i].szName,dValue,iViolations); ServerCmd(szMessage); } } } bool AgVariableChecker::Init() { if (m_bInit) return true; bool bSuccess = true; m_bHardware = IEngineStudio.IsHardware() ? true : false; if (!InitVariables(s_Variables,sizeof(s_Variables)/sizeof(s_Variables[0]))) bSuccess = false; if (!InitVariables(s_VariablesFast,sizeof(s_VariablesFast)/sizeof(s_VariablesFast[0]))) bSuccess = false; if (m_bHardware) { if (!InitVariables(s_VariablesHardware,sizeof(s_VariablesHardware)/sizeof(s_VariablesHardware[0]))) bSuccess = false; } if (bSuccess) { m_bInit = true; return true; } static char szMessage[] = "Variable init failed, exiting.\n"; ConsolePrint(szMessage); AgLog(szMessage); ServerCmd( "say Disconnected for using invalid variable.\n" ); ClientCmd( szDisconnect ); Reset(); return false; } void AgVariableChecker::Reset() { m_bHardware = false; m_bInit = false; m_bActive = false; m_iViolations = 0; } bool AgVariableChecker::Check() { if (!m_bActive) return true; if (!m_bInit) { return Init(); } DWORD dwNow = GetTickCount(); if (m_dwNextCheck < dwNow) { CheckVariables(s_Variables,sizeof(s_Variables)/sizeof(s_Variables[0]),m_iViolations); if (m_bHardware) CheckVariables(s_VariablesHardware,sizeof(s_VariablesHardware)/sizeof(s_VariablesHardware[0]),m_iViolations); if (g_iPure > 1) CheckVariables(s_VariablesPure2,sizeof(s_VariablesPure2)/sizeof(s_VariablesPure2[0]),m_iViolations); m_dwNextCheck = dwNow + 500; //500ms for the less important variables. } if (m_dwNextCheckFast < dwNow) { CheckVariables(s_VariablesFast,sizeof(s_VariablesFast)/sizeof(s_VariablesFast[0]),m_iViolations); m_dwNextCheckFast = dwNow + 150; //150ms for the important variables. } if (g_iPure > 2) { if (m_dwNextA3D < dwNow) { CheckVariables(s_VariablesPure3,sizeof(s_VariablesPure3)/sizeof(s_VariablesPure3[0]),m_iViolations); ClientCmd("s_disable_a3d\n"); m_dwNextA3D = dwNow + 5000; //5 seconds . } } if (m_iViolations > MAX_VIOLATIONS) { static char szMessageServer[] = "say Disconnected for repeated cvar violations\n"; static char szMessage[] = "Cheat check: Disconnected for repeated cvar violations\n"; ServerCmd(szMessageServer); AgLog(szMessage); ConsolePrint(szMessage); ClientCmd(szDisconnect); Reset(); return false; } return true; } #endif //AG_USE_CHEATPROTECTION //-- Martin Webrant