diff --git a/dist/resources.ini b/dist/resources.ini index 4f387a5..de7b398 100644 --- a/dist/resources.ini +++ b/dist/resources.ini @@ -8,6 +8,7 @@ # # [file_name] - the path of the file # [file_hash] - hash the file of responce client +# [file_md5hash] - md5 hash (from big-endian to little endian) the file of responce client # # -> Format # path to file hash (exec cmd) diff --git a/engine/custom.h b/engine/custom.h index 1e07a97..5a5156e 100644 --- a/engine/custom.h +++ b/engine/custom.h @@ -18,6 +18,7 @@ #include "const.h" #define MAX_QPATH 64 // Must match value in quakedefs.h +#define MAX_RESOURCE_LIST 1280 ///////////////// // Customization diff --git a/src/cmdexec.cpp b/src/cmdexec.cpp index 9c4f58d..3b516e9 100644 --- a/src/cmdexec.cpp +++ b/src/cmdexec.cpp @@ -37,6 +37,8 @@ void StringReplace(char *src, const char *strold, const char *strnew) } } +extern uint32 swap_endian(uint32 value); + char *GetExecCmdPrepare(IGameClient *pClient, CResourceBuffer *pResource, uint32 responseHash) { int len; @@ -55,6 +57,7 @@ char *GetExecCmdPrepare(IGameClient *pClient, CResourceBuffer *pResource, uint32 // replace key values StringReplace(string, "[file_name]", pResource->GetFileName()); StringReplace(string, "[file_hash]", UTIL_VarArgs("%x", responseHash)); + StringReplace(string, "[file_md5hash]", UTIL_VarArgs("%x", swap_endian(responseHash))); // replace of templates for identification StringReplace(string, "[userid]", UTIL_VarArgs("#%u", g_engfuncs.pfnGetPlayerUserId(pClient->GetEdict()))); @@ -62,9 +65,9 @@ char *GetExecCmdPrepare(IGameClient *pClient, CResourceBuffer *pResource, uint32 StringReplace(string, "[ip]", UTIL_VarArgs("%i.%i.%i.%i", net->ip[0], net->ip[1], net->ip[2], net->ip[3])); StringReplace(string, "[name]", pClient->GetName()); - if (string != NULL && string[0] != '\0') + if (string[0] != '\0') { - Resource.Log(" -> ExecuteCMD: (%s), for (%s)", string, pClient->GetName()); + Resource.Log(" -> ExecuteCMD: (%s), for (%s)", string, pClient->GetName()); } len = strlen(string); @@ -111,12 +114,13 @@ void CExecMngr::CommandExecute(IGameClient *pClient) // execute cmdexec SERVER_COMMAND(cmdExec); } + + bBreak = pRes->IsBreak(); } // erase cmdexec delete pExec; iter = m_execList.erase(iter); - bBreak = (pRes->GetFileFlag() == FLAG_TYPE_BREAK); } } diff --git a/src/main.cpp b/src/main.cpp index 9eaa277..03da6ee 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,18 +13,37 @@ bool OnMetaAttach() // initialize resource config Resource.Init(); - // set force cvar on own value and replacement of original - // NOTE: in gamedll used this cvar not through a pointer thus we create own cvar for gamedll with default values - // so for engine set it the cvar values is 1. - pcv_consistency_old = g_engfuncs.pfnCVarGetPointer("mp_consistency"); + // if have already registered take it + cvar_t *pcv_consistency_prev = g_engfuncs.pfnCVarGetPointer("mp_consistency_"); - cv_mp_consistency.value = pcv_consistency_old->value; - cv_mp_consistency.string = pcv_consistency_old->string; - cv_mp_consistency.flags = pcv_consistency_old->flags; - cv_mp_consistency.name = pcv_consistency_old->name; - pcv_consistency_old->name = "mp_consistency_"; + if (pcv_consistency_prev != NULL) + { + pcv_consistency_old = g_engfuncs.pfnCVarGetPointer("mp_consistency"); + + const char *tempName = pcv_consistency_old->name; + pcv_consistency_old->name = pcv_consistency_prev->name; + + pcv_consistency_prev->value = pcv_consistency_old->value; + pcv_consistency_prev->string = pcv_consistency_old->string; + pcv_consistency_prev->flags = pcv_consistency_old->flags; + pcv_consistency_prev->name = tempName; + } + else + { + // set force cvar on own value and replacement of original + // NOTE: in gamedll used this cvar not through a pointer thus we create own cvar for gamedll with default values + // so for engine set it the cvar values is 1. + pcv_consistency_old = g_engfuncs.pfnCVarGetPointer("mp_consistency"); + + cv_mp_consistency.value = pcv_consistency_old->value; + cv_mp_consistency.string = pcv_consistency_old->string; + cv_mp_consistency.flags = pcv_consistency_old->flags; + cv_mp_consistency.name = pcv_consistency_old->name; + + pcv_consistency_old->name = STRING(ALLOC_STRING("mp_consistency_")); + g_engfuncs.pfnCVarRegister(&cv_mp_consistency); + } - g_engfuncs.pfnCVarRegister(&cv_mp_consistency); g_engfuncs.pfnCvar_DirectSet(pcv_consistency_old, "1"); // to remove the old cvar of cvars list @@ -57,12 +76,13 @@ void OnMetaDetach() cvar_t *pcv_mp_consistency = g_engfuncs.pfnCVarGetPointer("mp_consistency"); // to restore the pointer address of a string + const char *tempName = pcv_consistency_old->name; pcv_consistency_old->name = cv_mp_consistency.name; g_engfuncs.pfnCvar_DirectSet(pcv_consistency_old, pcv_mp_consistency->string); + pcv_mp_consistency->name = tempName; // restore old cvar mp_consistency cvar_t *cvar_vars = g_RehldsApi->GetFuncs()->GetCvarVars(); - for (cvar_t *var = cvar_vars, *prev = NULL; var != NULL; prev = var, var = var->next) { if (var == pcv_mp_consistency) diff --git a/src/meta_api.cpp b/src/meta_api.cpp index 7c390f5..1ab1260 100644 --- a/src/meta_api.cpp +++ b/src/meta_api.cpp @@ -4,7 +4,7 @@ plugin_info_t Plugin_info = { META_INTERFACE_VERSION, "Rechecker", - "1.1", + "1.2", __DATE__, "s1lent", "http://www.dedicated-server.ru/", @@ -30,7 +30,7 @@ C_DLLEXPORT int Meta_Query(char *, plugin_info_t **pPlugInfo, mutil_funcs_t *pMe *pPlugInfo = &(Plugin_info); gpMetaUtilFuncs = pMetaUtilFuncs; - return 1; + return TRUE; } C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs) @@ -40,7 +40,7 @@ C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, m if (!OnMetaAttach()) { - return 0; + return FALSE; } gMetaFunctionTable.pfnGetEntityAPI2 = GetEntityAPI2; @@ -48,11 +48,11 @@ C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, m memcpy(pFunctionTable, &gMetaFunctionTable, sizeof(META_FUNCTIONS)); - return 1; + return TRUE; } C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { OnMetaDetach(); - return 1; + return TRUE; } diff --git a/src/resource.cpp b/src/resource.cpp index 670e35e..a59b83f 100644 --- a/src/resource.cpp +++ b/src/resource.cpp @@ -159,6 +159,16 @@ void CResourceFile::Init() pcv_rch_log = g_engfuncs.pfnCVarGetPointer(cv_rch_log.name); } +uint32 __declspec(naked) swap_endian(uint32 value) +{ + __asm + { + mov eax, dword ptr[esp + 4] + bswap eax + ret + } +} + inline uint8 hexbyte(uint8 *hex) { return ((hex[0] > '9' ? toupper(hex[0]) - 'A' + 10 : hex[0] - '0') << 4) @@ -240,6 +250,7 @@ void CResourceFile::LoadResources() char filename[MAX_PATH_LENGTH]; char cmdBufExec[MAX_PATH_LENGTH]; int cline = 0; + bool bBreak; fp = fopen(m_PathDir, "r"); @@ -261,6 +272,7 @@ void CResourceFile::LoadResources() const char *pToken = GetNextToken(&pos); argc = 0; + bBreak = false; flag = FLAG_TYPE_NONE; memset(hash, 0, sizeof(hash)); @@ -309,7 +321,7 @@ void CResourceFile::LoadResources() } else if (_stricmp(cmdBufExec, "BREAK") == 0) { - flag = FLAG_TYPE_BREAK; + bBreak = true; cmdBufExec[0] = '\0'; } else @@ -327,7 +339,7 @@ void CResourceFile::LoadResources() } else if (_stricmp(pToken, "BREAK") == 0) { - flag = FLAG_TYPE_BREAK; + bBreak = true; } break; } @@ -368,13 +380,13 @@ void CResourceFile::LoadResources() UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; parsing hash failed on line %d\n", cline); continue; } - else if (strlen(cmdBufExec) <= 0 && (flag != FLAG_TYPE_IGNORE && flag != FLAG_TYPE_BREAK)) + else if (strlen(cmdBufExec) <= 0 && (flag != FLAG_TYPE_IGNORE && !bBreak)) { UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; parsing command line is empty on line %d\n", cline); continue; } - AddElement(filename, cmdBufExec, flag, *(uint32 *)&hash[0], cline); + AddElement(filename, cmdBufExec, flag, *(uint32 *)&hash[0], cline, bBreak); } else if (pToken != NULL || argc > ARG_TYPE_FILE_NAME) { @@ -450,9 +462,9 @@ const char *CResourceFile::GetNextToken(char **pbuf) return res; } -void CResourceFile::AddElement(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line) +void CResourceFile::AddElement(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line, bool bBreak) { - auto nRes = new CResourceBuffer(filename, cmdExec, flag, hash, line); + auto nRes = new CResourceBuffer(filename, cmdExec, flag, hash, line, bBreak); // to mark files which are not required to add to the resource again for (auto iter = m_resourceList.cbegin(), end = m_resourceList.cend(); iter != end; ++iter) @@ -513,9 +525,6 @@ bool CResourceFile::FileConsistencyResponse(IGameClient *pSenderClient, resource switch (typeFind) { - case FLAG_TYPE_BREAK: - /* empty */ - break; case FLAG_TYPE_IGNORE: tempResourceList.push_back(pRes); break; @@ -568,13 +577,14 @@ bool CResourceFile::FileConsistencyResponse(IGameClient *pSenderClient, resource if (hashFoundFile == NULL) hashFoundFile = "null"; - Log(" -> file: (%s), exphash: (%x), got: (%x), typeFind: (%d), prevhash: (%x), (%s), prevfiles: (%s), findathash: (%s)", pRes->GetFileName(), pRes->GetFileHash(), hash, typeFind, m_PrevHash, pSenderClient->GetName(), prevHashFoundFile, hashFoundFile); + Log(" -> file: (%s), exphash: (%x), got: (%x), typeFind: (%d), prevhash: (%x), (%s), prevfiles: (%s), findathash: (%s), md5hex: (%x)", pRes->GetFileName(), pRes->GetFileHash(), hash, typeFind, m_PrevHash, pSenderClient->GetName(), prevHashFoundFile, hashFoundFile, swap_endian(hash)); } bHandled = true; } m_PrevHash = hash; + AddFileResponse(pSenderClient, resource->szFileName, hash); return !bHandled; } @@ -599,7 +609,7 @@ void ClearStringsCache() StringsCache.clear(); } -CResourceBuffer::CResourceBuffer(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line) +CResourceBuffer::CResourceBuffer(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line, bool bBreak) { m_FileName = DuplicateString(filename); m_CmdExec = (cmdExec[0] != '\0') ? DuplicateString(cmdExec) : NULL; @@ -609,6 +619,7 @@ CResourceBuffer::CResourceBuffer(char *filename, char *cmdExec, flag_type_resour m_Flag = flag; m_FileHash = hash; m_Line = line; + m_Break = bBreak; } CResourceFile::ResponseBuffer::ResponseBuffer(IGameClient *pSenderClient, char *filename, uint32 hash) diff --git a/src/resource.h b/src/resource.h index 57d5c74..dcac538 100644 --- a/src/resource.h +++ b/src/resource.h @@ -1,9 +1,7 @@ #pragma once #define FILE_INI_RESOURCES "resources.ini" - #define MAX_CMD_LENGTH 128 -#define MAX_RESOURCE_LIST 1280 enum flag_type_resources { @@ -11,7 +9,6 @@ enum flag_type_resources FLAG_TYPE_EXISTS, // to comparison with the specified hash value FLAG_TYPE_MISSING, // check it missing file on client FLAG_TYPE_IGNORE, // ignore the specified hash value - FLAG_TYPE_BREAK, // do not check a next files FLAG_TYPE_HASH_ANY, // any file with any the hash value }; @@ -29,7 +26,7 @@ enum arg_type_e class CResourceBuffer { public: - CResourceBuffer(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line); + CResourceBuffer(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line, bool bBreak); uint32 GetFileHash() const { return m_FileHash; }; flag_type_resources GetFileFlag() const { return m_Flag; }; @@ -38,6 +35,7 @@ public: const char *GetCmdExec() const { return m_CmdExec; }; int GetLine() const { return m_Line; }; + bool IsBreak() const { return m_Break; }; bool IsDuplicate() const { return m_Duplicate; }; void SetDuplicate() { m_Duplicate = true; }; @@ -49,7 +47,9 @@ private: const char *m_FileName; const char *m_CmdExec; - bool m_Duplicate; + + bool m_Duplicate; // for to check for duplicate + bool m_Break; // do not check a next files }; class CResourceFile @@ -82,7 +82,7 @@ private: private: // for temporary files of responses - void AddElement(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line); + void AddElement(char *filename, char *cmdExec, flag_type_resources flag, uint32 hash, int line, bool bBreak); void AddFileResponse(IGameClient *pSenderClient, char *filename, uint32 hash); const char *FindFilenameOfHash(uint32 hash); void LogPrepare();