From 61fe805a29e3ce6408a5fc61b5131acd7b8e5fee Mon Sep 17 00:00:00 2001 From: s1lent Date: Thu, 21 Sep 2017 23:02:39 +0700 Subject: [PATCH] Add support rechecker API Minor refactoring --- getucrtinfo.bat | 4 + reapi/build.gradle | 2 +- .../extra/amxmodx/scripting/include/reapi.inc | 15 +- .../scripting/include/reapi_gamedll_const.inc | 8 +- .../scripting/include/reapi_rechecker.inc | 60 ++++++++ .../scripting/include/reapi_reunion.inc | 45 ++++++ .../amxmodx/scripting/include/reapi_vtc.inc | 68 +++++++++ reapi/include/rechecker_api.h | 132 ++++++++++++++++++ reapi/msvc/PreBuild.bat | 22 ++- reapi/msvc/reapi.vcxproj | 12 +- reapi/msvc/reapi.vcxproj.filters | 36 ++++- reapi/src/amxxmodule.cpp | 4 +- reapi/src/api_config.cpp | 9 +- reapi/src/api_config.h | 3 +- reapi/src/hook_callback.cpp | 55 ++++++++ reapi/src/hook_callback.h | 21 ++- reapi/src/hook_list.cpp | 38 +++-- reapi/src/hook_list.h | 20 ++- reapi/src/hook_manager.cpp | 2 +- reapi/src/hook_manager.h | 2 +- reapi/src/main.cpp | 6 +- reapi/src/mods/mod_rechecker_api.cpp | 47 +++++++ reapi/src/mods/mod_rechecker_api.h | 7 + reapi/src/mods/queryfile_handler.cpp | 73 ++++++++++ reapi/src/mods/queryfile_handler.h | 31 ++++ reapi/src/natives/natives_addons.h | 3 - reapi/src/natives/natives_common.cpp | 8 +- reapi/src/natives/natives_helper.h | 10 +- reapi/src/natives/natives_hookchains.cpp | 2 +- reapi/src/natives/natives_hookchains.h | 1 - reapi/src/natives/natives_rechecker.cpp | 82 +++++++++++ reapi/src/natives/natives_rechecker.h | 5 + reapi/src/natives/natives_reunion.cpp | 81 +++++++++++ reapi/src/natives/natives_reunion.h | 3 + .../{natives_addons.cpp => natives_vtc.cpp} | 92 ++---------- reapi/src/natives/natives_vtc.h | 3 + reapi/src/precompiled.h | 10 +- shared_icc.gradle | 18 ++- shared_msvc.gradle | 17 +++ 39 files changed, 899 insertions(+), 158 deletions(-) create mode 100644 getucrtinfo.bat create mode 100644 reapi/extra/amxmodx/scripting/include/reapi_rechecker.inc create mode 100644 reapi/extra/amxmodx/scripting/include/reapi_reunion.inc create mode 100644 reapi/extra/amxmodx/scripting/include/reapi_vtc.inc create mode 100644 reapi/include/rechecker_api.h create mode 100644 reapi/src/mods/mod_rechecker_api.cpp create mode 100644 reapi/src/mods/mod_rechecker_api.h create mode 100644 reapi/src/mods/queryfile_handler.cpp create mode 100644 reapi/src/mods/queryfile_handler.h delete mode 100644 reapi/src/natives/natives_addons.h create mode 100644 reapi/src/natives/natives_rechecker.cpp create mode 100644 reapi/src/natives/natives_rechecker.h create mode 100644 reapi/src/natives/natives_reunion.cpp create mode 100644 reapi/src/natives/natives_reunion.h rename reapi/src/natives/{natives_addons.cpp => natives_vtc.cpp} (52%) create mode 100644 reapi/src/natives/natives_vtc.h diff --git a/getucrtinfo.bat b/getucrtinfo.bat new file mode 100644 index 0000000..35911fa --- /dev/null +++ b/getucrtinfo.bat @@ -0,0 +1,4 @@ +@echo off +call "%VS140COMNTOOLS%vcvarsqueryregistry.bat" +echo %UniversalCRTSdkDir% +echo %UCRTVersion% diff --git a/reapi/build.gradle b/reapi/build.gradle index 1ff2caa..16183b6 100644 --- a/reapi/build.gradle +++ b/reapi/build.gradle @@ -60,7 +60,7 @@ void setupToolchain(NativeBinarySpec b) { '_snprintf': 'snprintf' ]) - cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-msse2', '-fomit-frame-pointer', '-inline-forceinline', '-fvisibility=default', '-fvisibility-inlines-hidden', '-fno-rtti', '-g0', '-s' + cfg.compilerOptions.args '-Qoption,cpp,--treat_func_as_string_literal_cpp', '-msse2', '-fomit-frame-pointer', '-inline-forceinline', '-fvisibility=default', '-fvisibility-inlines-hidden', '-fno-rtti', '-g0', '-s', '-fno-exceptions' } ToolchainConfigUtils.apply(project, cfg, b) diff --git a/reapi/extra/amxmodx/scripting/include/reapi.inc b/reapi/extra/amxmodx/scripting/include/reapi.inc index 44e925c..ebd6762 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi.inc @@ -19,7 +19,8 @@ enum hooks_tables_e ht_gamedll, ht_animating, ht_player, - ht_gamerules + ht_gamerules, + ht_rechecker }; enum members_tables_e @@ -42,7 +43,7 @@ enum members_tables_e }; // Is like FNullEnt -#define is_nullent(%0) (%0 != 0 && is_entity(%0) == false) +#define is_nullent(%0) (%0 == 0 || is_entity(%0) == false) #define MAX_REGION_RANGE 1024 @@ -51,10 +52,14 @@ enum members_tables_e #include +#include #include // NOTE: only for ReHLDS #include // NOTE: only for gamedll Counter-Strike (ReGameDLL_CS) -#include // NOTE: 3rd party addons -#include + +// addons +#include +#include +#include // hookchain return type enum @@ -90,7 +95,7 @@ enum HookChain * @return Returns a hook handle. Use EnableHookChain/DisableHookChain to toggle the forward on or off * */ -native HookChain:RegisterHookChain({EngineFunc, GamedllFunc, GamedllFunc_CBaseAnimating, GamedllFunc_CBasePlayer, GamedllFunc_CSGameRules}:function_id, const callback[], post = 0); +native HookChain:RegisterHookChain({EngineFunc, GamedllFunc, GamedllFunc_CBaseAnimating, GamedllFunc_CBasePlayer, GamedllFunc_CSGameRules, ReCheckerFunc}:function_id, const callback[], post = 0); /* * Stops a hook from triggering. diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index 5a7478f..4d9c024 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -1782,7 +1782,7 @@ enum CBasePlayer_Members m_bHighDamage, /* - * Description: - + * Description: Slow down the player based on the velocity modifier, applies when the player takes damage. * Member type: float * Get params: Float:get_member(index, member); * Set params: set_member(index, member, Float:value); @@ -3983,7 +3983,7 @@ enum CCSPlayer_Members enum CBasePlayerItem_Members { /* - * Description: - + * Description: ID of the owner on this item * Member type: class CBasePlayer * * Get params: get_member(index, member); * Set params: set_member(index, member, value); @@ -3991,7 +3991,7 @@ enum CBasePlayerItem_Members m_pPlayer = BEGIN_MEMBER_REGION(baseitem), /* - * Description: - + * Description: Iterator for linked list of the entities * Member type: class CBasePlayerItem * * Get params: get_member(index, member); * Set params: set_member(index, member, value); @@ -3999,7 +3999,7 @@ enum CBasePlayerItem_Members m_pNext, /* - * Description: - + * Description: ID of the item * Member type: int * Get params: get_member(index, member); * Set params: set_member(index, member, value); diff --git a/reapi/extra/amxmodx/scripting/include/reapi_rechecker.inc b/reapi/extra/amxmodx/scripting/include/reapi_rechecker.inc new file mode 100644 index 0000000..068ffde --- /dev/null +++ b/reapi/extra/amxmodx/scripting/include/reapi_rechecker.inc @@ -0,0 +1,60 @@ +#if defined _reapi_rechecker_included + #endinput +#endif +#define _reapi_rechecker_included + +enum ResourceType +{ + RES_TYPE_NONE = 0, + RES_TYPE_EXISTS, // to comparison with the specified hash value + RES_TYPE_MISSING, // check it missing file on client + RES_TYPE_IGNORE, // ignore the specified hash value + RES_TYPE_HASH_ANY, // any file with any the hash value +}; + +enum ReCheckerFunc +{ + /* + * Description: - + * Params: (const client, const filename[], const cmd[], const ResourceType:type, const responseHash, bool:isBreak) + */ + RC_FileConsistencyProcess = BEGIN_FUNC_REGION(rechecker), + + /* + * Description: - + * Params: (const client) + */ + RC_FileConsistencyFinal, + + /* + * Description: - + * Params: (const client, const filename[], const cmd[], const responseHash) + */ + RC_CmdExec, + + // [...] +}; + +/* +* Send request the file for the client to get hash +* +* @param file The file (Can contain a relative path to the file) +* @param function The forward to call +* @param type The request type, can be only RES_TYPE_EXISTS, RES_TYPE_MISSING or RES_TYPE_HASH_ANY +* @param hash Hash of file to request. +* +* @return Returns a hook handle. Use UnRegisterQueryFile to remove the forward +* +*/ +native QueryFileHook:RegisterQueryFile(const file[], const function[], const ResourceType:type, const hash = -1); + +/* +* Unregister the forward. +* Use the return value from RegisterQueryFile as the parameter here! +* +* @param hook The hook to remove +* +* @return Returns true if the hook is successfully removed, otherwise false +* +*/ +native bool:UnRegisterQueryFile(QueryFileHook:hook); diff --git a/reapi/extra/amxmodx/scripting/include/reapi_reunion.inc b/reapi/extra/amxmodx/scripting/include/reapi_reunion.inc new file mode 100644 index 0000000..7e202ca --- /dev/null +++ b/reapi/extra/amxmodx/scripting/include/reapi_reunion.inc @@ -0,0 +1,45 @@ +#if defined _reapi_reunion_included + #endinput +#endif +#define _reapi_reunion_included + +enum client_auth_type +{ + CA_TYPE_NONE = 0, + CA_TYPE_DPROTO, + CA_TYPE_STEAM, + CA_TYPE_STEAMEMU, + CA_TYPE_REVEMU, + CA_TYPE_OLDREVEMU, + CA_TYPE_HLTV, + CA_TYPE_SC2009, + CA_TYPE_AVSMP, + CA_TYPE_SXEI, + CA_TYPE_REVEMU2013, + CA_TYPE_SSE3, +}; + +/* +* Gets client protocol. +* +* @param index Client index +* @return Client protocol +*/ +native REU_GetProtocol(const index); + +/* +* Gets client auth type. +* +* @param index Client index +* @return Client auth type +*/ +native client_auth_type:REU_GetAuthtype(const index); + +/* +* Check if the client is running RevEmu with limited user rights. +* +* @param index Client index +* @return 1/0 +* +*/ +native bool:REU_IsRevemuWithoutAdminRights(const index); diff --git a/reapi/extra/amxmodx/scripting/include/reapi_vtc.inc b/reapi/extra/amxmodx/scripting/include/reapi_vtc.inc new file mode 100644 index 0000000..26a34ba --- /dev/null +++ b/reapi/extra/amxmodx/scripting/include/reapi_vtc.inc @@ -0,0 +1,68 @@ +#if defined _reapi_vtc_included + #endinput +#endif +#define _reapi_vtc_included + +/* +* Checks whether the player is talking at the moment. +* +* @param index Client index +* @return true if client is speaking, false otherwise +* +*/ +native bool:VTC_IsClientSpeaking(const index); + +/* +* Mutes the player. +* +* @param index Client index +* @noreturn +*/ +native VTC_MuteClient(const index); + +/* +* Unmutes the player. +* +* @param index Client index +* @noreturn +*/ +native VTC_UnmuteClient(const index); + +/* +* Checks whether the player is muted at the moment. +* +* @param index Client index +* @return true if client is muted, false otherwise +* +*/ +native bool:VTC_IsClientMuted(const index); + +/* +* Play the audio file via the voice stream. +* +* @param receiver Receiver index +* @param soundFilePath The path to the sound file +* +* @note Usage example: +* VTC_PlaySound(id, "sound/ambience/Opera.wav"); +* +* @noreturn +* +*/ +native VTC_PlaySound(const receiver, const soundFilePath[]); + +/* +* Called when the player started talking. +* +* @param index Client index +* @noreturn +*/ +forward VTC_OnClientStartSpeak(const index); + +/* +* Called when the player stopped talking. +* +* @param index Client index +* @noreturn +*/ +forward VTC_OnClientStopSpeak(const index); diff --git a/reapi/include/rechecker_api.h b/reapi/include/rechecker_api.h new file mode 100644 index 0000000..1ffaf4e --- /dev/null +++ b/reapi/include/rechecker_api.h @@ -0,0 +1,132 @@ +/* +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at +* your option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +* In addition, as a special exception, the author gives permission to +* link the code of this program with the Half-Life Game Engine ("HL +* Engine") and Modified Game Libraries ("MODs") developed by Valve, +* L.L.C ("Valve"). You must obey the GNU General Public License in all +* respects for all of the code used other than the HL Engine and MODs +* from Valve. If you modify this file, you may extend this exception +* to your version of the file, but you are not obligated to do so. If +* you do not wish to do so, delete this exception statement from your +* version. +* +*/ +#pragma once + +#include "hookchains.h" +#include "interface.h" + +#define RECHECKER_API_VERSION_MAJOR 2 +#define RECHECKER_API_VERSION_MINOR 1 + +enum ResourceType_e +{ + RES_TYPE_NONE = 0, + RES_TYPE_EXISTS, // to comparison with the specified hash value + RES_TYPE_MISSING, // check it missing file on client + RES_TYPE_IGNORE, // ignore the specified hash value + RES_TYPE_HASH_ANY, // any file with any the hash value +}; + +class IResourceBuffer; + +// FileConsistencyProcess hook +typedef IVoidHookChain IRecheckerHook_FileConsistencyProcess; +typedef IVoidHookChainRegistry IRecheckerHookRegistry_FileConsistencyProcess; + +// CmdExec hook +typedef IVoidHookChain IRecheckerHook_CmdExec; +typedef IVoidHookChainRegistry IRecheckerHookRegistry_CmdExec; + +// FileConsistencyFinal hook +typedef IVoidHookChain IRecheckerHook_FileConsistencyFinal; +typedef IVoidHookChainRegistry IRecheckerHookRegistry_FileConsistencyFinal; + +class IRecheckerHookchains { +protected: + virtual ~IRecheckerHookchains() {} + +public: + virtual IRecheckerHookRegistry_FileConsistencyProcess *FileConsistencyProcess() = 0; + virtual IRecheckerHookRegistry_CmdExec *CmdExec() = 0; + virtual IRecheckerHookRegistry_FileConsistencyFinal *FileConsistencyFinal() = 0; +}; + +class IResourceBuffer { +protected: + virtual ~IResourceBuffer() {} + +public: + virtual uint32 GetFileHash() const = 0; + virtual ResourceType_e GetFileFlag() const = 0; + + virtual const char *GetFileName() const = 0; + virtual const char *GetCmdExec() const = 0; + virtual int GetLine() const = 0; + + virtual bool IsBreak() const = 0; // is have do not check a next files + virtual bool IsDuplicate() const = 0; // it is already have in resourcelist + virtual bool IsAddEx() const = 0; // if it added via API +}; + +class IResponseBuffer { +protected: + virtual ~IResponseBuffer() {} + +public: + virtual int GetUserID() const = 0; + virtual IGameClient *GetGameClient() const = 0; + virtual const char *GetFileName() const = 0; + virtual uint32 GetClientHash() const = 0; + virtual uint32 GetPrevHash() const = 0; +}; + +class IResourceFile { +protected: + virtual ~IResourceFile() {} + +public: + virtual const char *FindFilenameOfHash(uint32 hash) = 0; + virtual int GetConsistencyNum() const = 0; + virtual uint32 GetPrevHash() const = 0; +}; + +#undef FindResource + +using query_func_t = void (*)(IGameClient *pClient, uint32 hash, int uniqueId); + +struct RecheckerFuncs_t { + IResourceBuffer *(*AddResource)(const char *filename, char *cmdExec, ResourceType_e flag, uint32 hash, bool bBreak); + IResourceBuffer *(*AddQueryFile)(const char *filename, ResourceType_e flag, uint32 hash, query_func_t callback, int uniqueId); + void (*RemoveQueryFile)(int uniqueId); + void (*ClearQueryFiles)(); + IResourceBuffer *(*FindResource)(const char *filename); + IResourceFile *(*GetResource)(); + IResponseBuffer *(*GetResponseFile)(IGameClient *pClient, const char *filename); + bool (*IsResourceExists)(IGameClient *pClient, const char *filename, uint32 &hash); +}; + +class IRecheckerApi { +protected: + virtual ~IRecheckerApi() { } + +public: + virtual int GetMajorVersion() = 0; + virtual int GetMinorVersion() = 0; + virtual const RecheckerFuncs_t *GetFuncs() = 0; + virtual IRecheckerHookchains *GetHookchains() = 0; +}; diff --git a/reapi/msvc/PreBuild.bat b/reapi/msvc/PreBuild.bat index 5dc46d1..ee8e20f 100644 --- a/reapi/msvc/PreBuild.bat +++ b/reapi/msvc/PreBuild.bat @@ -27,6 +27,14 @@ set "hour=%dt:~8,2%" set "min=%dt:~10,2%" set "sec=%dt:~12,2%" +:: +:: Remove leading zero from MM (e.g 09 > 9) +for /f "tokens=* delims=0" %%I in ("%MM%") do set MM=%%I +:: + +:: +:: Index into array to get month name +:: for /f "tokens=%MM%" %%I in ("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec") do set "month=%%I" :: @@ -143,10 +151,10 @@ IF NOT %errlvl% == "1" ( ) :: append extra string - If NOT "%commitURL%"=="%commitURL:bitbucket.org=%" ( - set commitURL=!commitURL!/commit/ - ) ELSE ( + If NOT "!commitURL!"=="!commitURL:bitbucket.org=!" ( set commitURL=!commitURL!/commits/ + ) ELSE ( + set commitURL=!commitURL!/commit/ ) ) ELSE ( @@ -158,10 +166,10 @@ IF NOT %errlvl% == "1" ( set commitURL=!commitURL::=/! :: append extra string - If NOT "%commitURL%"=="%commitURL:bitbucket.org=%" ( - set commitURL=https://!commitURL!/commit/ - ) ELSE ( + If NOT "!commitURL!"=="!commitURL:bitbucket.org=!" ( set commitURL=https://!commitURL!/commits/ + ) ELSE ( + set commitURL=https://!commitURL!/commit/ ) ) ) @@ -243,7 +251,7 @@ echo #define APP_VERSION_STRD "%version_major%.%version_minor%.%version_maintena echo #define APP_VERSION_FLAGS 0x0L>>"%srcdir%\appversion.h" echo.>>"%srcdir%\appversion.h" -echo #define APP_COMMIT_DATE "%YYYY%-%DD%-%MM%">>"%srcdir%\appversion.h" +echo #define APP_COMMIT_DATE "%month% %DD% %YYYY%">>"%srcdir%\appversion.h" echo #define APP_COMMIT_TIME "%hour%:%min%:%sec%">>"%srcdir%\appversion.h" echo.>>"%srcdir%\appversion.h" diff --git a/reapi/msvc/reapi.vcxproj b/reapi/msvc/reapi.vcxproj index 3eeb92d..8c7f3a4 100644 --- a/reapi/msvc/reapi.vcxproj +++ b/reapi/msvc/reapi.vcxproj @@ -204,16 +204,20 @@ + + - + + + @@ -247,15 +251,19 @@ + + - + + + Create Create diff --git a/reapi/msvc/reapi.vcxproj.filters b/reapi/msvc/reapi.vcxproj.filters index 7b01c75..6ddb4f8 100644 --- a/reapi/msvc/reapi.vcxproj.filters +++ b/reapi/msvc/reapi.vcxproj.filters @@ -651,9 +651,6 @@ src\mods - - src\natives - include @@ -669,6 +666,21 @@ src\natives + + src\mods + + + src\natives + + + src\natives + + + src\natives + + + src\mods + @@ -746,15 +758,27 @@ src\mods - - src\natives - version src\natives + + src\mods + + + src\natives + + + src\natives + + + src\natives + + + src\mods + diff --git a/reapi/src/amxxmodule.cpp b/reapi/src/amxxmodule.cpp index 1a869df..f21c24b 100644 --- a/reapi/src/amxxmodule.cpp +++ b/reapi/src/amxxmodule.cpp @@ -164,7 +164,9 @@ C_DLLEXPORT int AMXX_Attach(PFN_REQ_FNPTR reqFnptrFunc) RegisterNatives_HookChains(); RegisterNatives_Members(); RegisterNatives_Misc(); - RegisterNatives_Addons(); + RegisterNatives_VTC(); + RegisterNatives_Rechecker(); + RegisterNatives_Reunion(); RegisterNatives_Common(); return AMXX_OK; diff --git a/reapi/src/api_config.cpp b/reapi/src/api_config.cpp index 583257d..5d08991 100644 --- a/reapi/src/api_config.cpp +++ b/reapi/src/api_config.cpp @@ -9,10 +9,11 @@ CAPI_Config::CAPI_Config() : m_api_rehlds(false), m_api_regame(false), m_api_vtc void CAPI_Config::Init() { - m_api_rehlds = RehldsApi_Init(); - m_api_regame = RegamedllApi_Init(); - m_api_vtc = VTC_Api_Init(); - m_api_reunion = ReunionApi_Init(); + m_api_rehlds = RehldsApi_Init(); + m_api_regame = RegamedllApi_Init(); + m_api_vtc = VTC_Api_Init(); + m_api_reunion = ReunionApi_Init(); + m_api_rechecker = RecheckerApi_Init(); if (m_api_regame) { g_ReGameHookchains->InstallGameRules()->registerHook(&InstallGameRules); diff --git a/reapi/src/api_config.h b/reapi/src/api_config.h index 531bc9c..c650360 100644 --- a/reapi/src/api_config.h +++ b/reapi/src/api_config.h @@ -12,6 +12,7 @@ public: bool hasReGameDLL() const { return m_api_regame; } bool hasVTC() const { return m_api_vtc; } bool hasReunion() const { return m_api_reunion; } + bool hasRechecker() const { return m_api_rechecker; } void ServerDeactivate() const; @@ -25,7 +26,7 @@ private: bool m_api_reunion; // for information about authorization client //bool m_api_revoice; // for gag #2 - //bool m_api_rechecker; // for detection when checking and adding few files + bool m_api_rechecker; // for detection when checking and adding few files }; extern CAPI_Config api_cfg; diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index 17598be..c5162f3 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -828,3 +828,58 @@ void OnClientStopSpeak(size_t clientIndex) { g_amxxapi.ExecuteForward(g_iClientStopSpeak, clientIndex); } + +/* +* ReChecker functions +*/ +void FileConsistencyProcess_AMXX(FileConsistencyProcess_t *data, IGameClient *cl, const char *filename, const char *cmd, ResourceType_e type, uint32 responseHash, bool isBreak) +{ + int hashCopy = responseHash; + auto original = [data, hashCopy](int _cl, const char *_filename, const char *_cmd, ResourceType_e _type, uint32 _hash, bool _isBreak) + { + data->m_chain->callNext(g_RehldsSvs->GetClient(_cl - 1), data->m_data, _type, hashCopy); + }; + + if (g_RecheckerFuncs->GetResource()->GetPrevHash() == responseHash) { + responseHash = 0; + } + + callVoidForward(RC_FileConsistencyProcess, original, cl->GetId() + 1, filename, cmd, type, responseHash, isBreak); +} + +void FileConsistencyProcess(IRecheckerHook_FileConsistencyProcess *chain, IGameClient *cl, IResourceBuffer *res, ResourceType_e typeFind, uint32 responseHash) +{ + FileConsistencyProcess_t data(chain, res); + FileConsistencyProcess_AMXX(&data, cl, res->GetFileName(), res->GetCmdExec(), typeFind, responseHash, res->IsBreak()); +} + +void FileConsistencyFinal(IRecheckerHook_FileConsistencyFinal *chain, IGameClient *cl) +{ + auto original = [chain](int _cl) + { + chain->callNext(g_RehldsSvs->GetClient(_cl - 1)); + }; + + callVoidForward(RC_FileConsistencyFinal, original, cl->GetId() + 1); +} + +void CmdExec_AMXX(CmdExec_t *data, IGameClient *cl, const char *filename, char *cmd, uint32 responseHash) +{ + int hashCopy = responseHash; + auto original = [data, hashCopy](int _cl, const char *_filename, char *_cmd, uint32 _responseHash) + { + data->m_chain->callNext(g_RehldsSvs->GetClient(_cl - 1), data->m_data, _cmd, hashCopy); + }; + + if (g_RecheckerFuncs->GetResource()->GetPrevHash() == responseHash) { + responseHash = 0; + } + + callVoidForward(RC_CmdExec, original, cl->GetId() + 1, filename, cmd, responseHash); +} + +void CmdExec(IRecheckerHook_CmdExec *chain, IGameClient *cl, IResourceBuffer *res, char *cmdExec, uint32 responseHash) +{ + CmdExec_t data(chain, res); + CmdExec_AMXX(&data, cl, res->GetFileName(), cmdExec, responseHash); +} diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 4434c69..d7b4195 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -105,7 +105,7 @@ struct hookctx_t hookctx_t(size_t arg_count, t_args... args) { args_count = min(arg_count, MAX_HOOKCHAIN_ARGS); - + if (hasStringArgs(args...)) { tempstrings_used = 0; } @@ -285,6 +285,15 @@ R callForward(size_t func, original_t original, f_args... args) return ret; } +template +struct hookdata_t +{ + hookdata_t(T chain, A data) : m_chain(chain), m_data(data) {} + + T m_chain; + A m_data; +}; + // rehlds functions void SV_StartSound(IRehldsHook_SV_StartSound *chain, int recipients, edict_t *entity, int channel, const char *sample, int volume, float attenuation, int fFlags, int pitch); void SV_DropClient(IRehldsHook_SV_DropClient *chain, IGameClient *cl, bool crash, const char *fmt); @@ -379,3 +388,13 @@ extern int g_iClientStopSpeak; void OnClientStartSpeak(size_t clientIndex); void OnClientStopSpeak(size_t clientIndex); + +using CmdExec_t = hookdata_t; +void CmdExec_AMXX(CmdExec_t *chain, IGameClient *cl, const char *filename, char *cmd, uint32 responseHash); +void CmdExec(IRecheckerHook_CmdExec *chain, IGameClient *cl, IResourceBuffer *res, char *cmd, uint32 responseHash); + +using FileConsistencyProcess_t = hookdata_t; +void FileConsistencyProcess_AMXX(FileConsistencyProcess_t *data, IGameClient *cl, const char *filename, const char *cmd, ResourceType_e type, uint32 responseHash, bool isBreak); +void FileConsistencyProcess(IRecheckerHook_FileConsistencyProcess *chain, IGameClient *cl, IResourceBuffer *res, ResourceType_e typeFind, uint32 responseHash); + +void FileConsistencyFinal(IRecheckerHook_FileConsistencyFinal *chain, IGameClient *cl); diff --git a/reapi/src/hook_list.cpp b/reapi/src/hook_list.cpp index 40831c8..1559795 100644 --- a/reapi/src/hook_list.cpp +++ b/reapi/src/hook_list.cpp @@ -1,19 +1,22 @@ #include "precompiled.h" -inline size_t getFwdParamType(void(*)(int)) { return FP_CELL; } -inline size_t getFwdParamType(void(*)(short)) { return FP_CELL; } -inline size_t getFwdParamType(void(*)(bool)) { return FP_CELL; } -inline size_t getFwdParamType(void(*)(Vector&)) { return FP_ARRAY; } -inline size_t getFwdParamType(void(*)(PLAYER_ANIM)) { return FP_CELL; } -inline size_t getFwdParamType(void(*)(WeaponIdType)) { return FP_CELL; } -inline size_t getFwdParamType(void(*)(RewardType)) { return FP_CELL; } +inline size_t getFwdParamType(void(*)(int)) { return FP_CELL; } +inline size_t getFwdParamType(void(*)(short)) { return FP_CELL; } +inline size_t getFwdParamType(void(*)(bool)) { return FP_CELL; } +inline size_t getFwdParamType(void(*)(uint32)) { return FP_CELL; } +inline size_t getFwdParamType(void(*)(Vector&)) { return FP_ARRAY; } +inline size_t getFwdParamType(void(*)(PLAYER_ANIM)) { return FP_CELL; } +inline size_t getFwdParamType(void(*)(WeaponIdType)) { return FP_CELL; } +inline size_t getFwdParamType(void(*)(RewardType)) { return FP_CELL; } inline size_t getFwdParamType(void(*)(ScenarioEventEndRound)) { return FP_CELL; } -inline size_t getFwdParamType(void(*)(ItemID)) { return FP_CELL; } -inline size_t getFwdParamType(void(*)(ItemRestType)) { return FP_CELL; } -inline size_t getFwdParamType(void(*)(float)) { return FP_FLOAT; } -inline size_t getFwdParamType(void(*)(float&)) { return FP_FLOAT; } -inline size_t getFwdParamType(void(*)(const char *)) { return FP_STRING; } -inline size_t getFwdParamType(void(*)(char *)) { return FP_STRING; } +inline size_t getFwdParamType(void(*)(ItemID)) { return FP_CELL; } +inline size_t getFwdParamType(void(*)(ItemRestType)) { return FP_CELL; } +inline size_t getFwdParamType(void(*)(ResourceType_e)) { return FP_CELL; } +inline size_t getFwdParamType(void(*)(float)) { return FP_FLOAT; } +inline size_t getFwdParamType(void(*)(float&)) { return FP_FLOAT; } +inline size_t getFwdParamType(void(*)(const char *)) { return FP_STRING; } +inline size_t getFwdParamType(void(*)(char *)) { return FP_STRING; } +inline size_t getFwdParamType(void(*)(IResourceBuffer*)) { return FP_CELL; } template inline size_t getFwdParamType(void(*)(T *)) { return FP_CELL; } @@ -164,6 +167,13 @@ hook_t hooklist_gamerules[] = { DLL(CSGameRules_OnRoundFreezeEnd), }; +#define RCHECK(h,...) { {}, {}, #h, "ReChecker", [](){ return api_cfg.hasRechecker(); }, ((!(RC_##h & (MAX_REGION_RANGE - 1)) ? regfunc::current_cell = 1, true : false) || (RC_##h & (MAX_REGION_RANGE - 1)) == regfunc::current_cell++) ? regfunc(h##__VA_ARGS__) : regfunc(#h#__VA_ARGS__), [](){ g_RecheckerHookchains->##h##()->registerHook(&##h); }, [](){ g_RecheckerHookchains->##h##()->unregisterHook(&##h); }} +hook_t hooklist_rechecker[] = { + RCHECK(FileConsistencyProcess, _AMXX), + RCHECK(FileConsistencyFinal), + RCHECK(CmdExec, _AMXX) +}; + hook_t* hooklist_t::getHookSafe(size_t hook) { #define CASE(h) case ht_##h: if (likely(index < arraysize(hooklist_##h))) return &hooklist_##h[index]; else break; @@ -177,6 +187,7 @@ hook_t* hooklist_t::getHookSafe(size_t hook) CASE(animating) CASE(player) CASE(gamerules) + CASE(rechecker) } return nullptr; @@ -191,6 +202,7 @@ void hooklist_t::clear() FOREACH_CLEAR(animating); FOREACH_CLEAR(player); FOREACH_CLEAR(gamerules); + FOREACH_CLEAR(rechecker); } void hook_t::clear() diff --git a/reapi/src/hook_list.h b/reapi/src/hook_list.h index e49cbcd..4e897f5 100644 --- a/reapi/src/hook_list.h +++ b/reapi/src/hook_list.h @@ -12,13 +12,13 @@ typedef void (*regchain_t)(); struct hook_t { std::vector pre; // pre forwards - std::vector post; // post forwards + std::vector post; // post forwards - const char *func_name; // function name - const char *depend_name; // platform dependency + const char *func_name; // function name + const char *depend_name; // platform dependency reqfunc_t checkRequirements; - regfunc_t registerForward; // AMXX forward registration function + regfunc_t registerForward; // AMXX forward registration function regchain_t registerHookchain; // register re* API hook regchain_t unregisterHookchain; // unregister re* API hook @@ -30,6 +30,7 @@ extern hook_t hooklist_gamedll[]; extern hook_t hooklist_animating[]; extern hook_t hooklist_player[]; extern hook_t hooklist_gamerules[]; +extern hook_t hooklist_rechecker[]; enum { @@ -51,6 +52,7 @@ struct hooklist_t CASE(animating) CASE(player) CASE(gamerules) + CASE(rechecker) } return nullptr; @@ -66,6 +68,7 @@ struct hooklist_t ht_animating, ht_player, ht_gamerules, + ht_rechecker, ht_end }; @@ -186,3 +189,12 @@ enum GamedllFunc_CSGameRules // [...] }; + +enum ReCheckerFunc +{ + RC_FileConsistencyProcess = BEGIN_FUNC_REGION(rechecker), + RC_FileConsistencyFinal, + RC_CmdExec, + + // [...] +}; diff --git a/reapi/src/hook_manager.cpp b/reapi/src/hook_manager.cpp index 2886bfc..46a92e0 100644 --- a/reapi/src/hook_manager.cpp +++ b/reapi/src/hook_manager.cpp @@ -43,7 +43,7 @@ void CAmxxHook::SetState(fwdstate st) m_state = st; } -void CHookManager::clearHandlers() const +void CHookManager::Clear() const { m_hooklist.clear(); } diff --git a/reapi/src/hook_manager.h b/reapi/src/hook_manager.h index daae87e..df78642 100644 --- a/reapi/src/hook_manager.h +++ b/reapi/src/hook_manager.h @@ -35,7 +35,7 @@ private: class CHookManager { public: - void clearHandlers() const; + void Clear() const; cell addHandler(AMX* amx, int func, const char *funcname, int forward, bool post) const; hook_t* getHook(size_t func) const; CAmxxHook* getAmxxHook(cell hook) const; diff --git a/reapi/src/main.cpp b/reapi/src/main.cpp index 434d1b6..6c7d7d1 100644 --- a/reapi/src/main.cpp +++ b/reapi/src/main.cpp @@ -41,7 +41,8 @@ bool OnMetaAttach() void OnMetaDetach() { // clear all hooks? - g_hookManager.clearHandlers(); + g_hookManager.Clear(); + g_queryFileManager.Clear(); if (api_cfg.hasVTC()) { g_pVoiceTranscoderApi->OnClientStartSpeak() -= OnClientStartSpeak; @@ -66,7 +67,8 @@ void ServerDeactivate_Post() { g_pEdicts = nullptr; api_cfg.ServerDeactivate(); - g_hookManager.clearHandlers(); + g_hookManager.Clear(); + g_queryFileManager.Clear(); g_pFunctionTable->pfnSpawn = DispatchSpawn; g_pFunctionTable->pfnKeyValue = KeyValue; diff --git a/reapi/src/mods/mod_rechecker_api.cpp b/reapi/src/mods/mod_rechecker_api.cpp new file mode 100644 index 0000000..67ba0f3 --- /dev/null +++ b/reapi/src/mods/mod_rechecker_api.cpp @@ -0,0 +1,47 @@ +#include "precompiled.h" + +IRecheckerApi *g_RecheckerApi; +IRecheckerHookchains *g_RecheckerHookchains; +const RecheckerFuncs_t *g_RecheckerFuncs; + +bool RecheckerApi_Init() +{ + if (!g_RehldsApi) + return false; + + g_RecheckerApi = (IRecheckerApi *)g_RehldsApi->GetFuncs()->GetPluginApi("rechecker"); + + if (!g_RecheckerApi) + return false; + + if (g_RecheckerApi->GetMajorVersion() != RECHECKER_API_VERSION_MAJOR) + { + UTIL_ServerPrint("[%s]: Rechecker API major version mismatch; expected %d, real %d\n", Plugin_info.logtag, RECHECKER_API_VERSION_MAJOR, g_RecheckerApi->GetMajorVersion()); + + // need to notify that it is necessary to update the Rechecker. + if (g_RecheckerApi->GetMajorVersion() < RECHECKER_API_VERSION_MAJOR) + { + UTIL_ServerPrint("[%s]: Please update the Rechecker up to a major version API >= %d\n", Plugin_info.logtag, RECHECKER_API_VERSION_MAJOR); + } + + // need to notify that it is necessary to update the module. + else if (g_RecheckerApi->GetMajorVersion() > RECHECKER_API_VERSION_MAJOR) + { + UTIL_ServerPrint("[%s]: Please update the %s up to a major version API >= %d\n", Plugin_info.logtag, Plugin_info.logtag, g_RecheckerApi->GetMajorVersion()); + } + + return false; + } + + if (g_RecheckerApi->GetMinorVersion() < RECHECKER_API_VERSION_MINOR) + { + UTIL_ServerPrint("[%s]: Rechecker API minor version mismatch; expected at least %d, real %d\n", Plugin_info.logtag, RECHECKER_API_VERSION_MINOR, g_RecheckerApi->GetMinorVersion()); + UTIL_ServerPrint("[%s]: Please update the Rechecker up to a minor version API >= %d\n", Plugin_info.logtag, RECHECKER_API_VERSION_MINOR); + return false; + } + + g_RecheckerFuncs = g_RecheckerApi->GetFuncs(); + g_RecheckerHookchains = g_RecheckerApi->GetHookchains(); + + return true; +} diff --git a/reapi/src/mods/mod_rechecker_api.h b/reapi/src/mods/mod_rechecker_api.h new file mode 100644 index 0000000..a7ac59d --- /dev/null +++ b/reapi/src/mods/mod_rechecker_api.h @@ -0,0 +1,7 @@ +#pragma once + +extern IRecheckerApi *g_RecheckerApi; +extern IRecheckerHookchains *g_RecheckerHookchains; +extern const RecheckerFuncs_t *g_RecheckerFuncs; + +extern bool RecheckerApi_Init(); diff --git a/reapi/src/mods/queryfile_handler.cpp b/reapi/src/mods/queryfile_handler.cpp new file mode 100644 index 0000000..6130b97 --- /dev/null +++ b/reapi/src/mods/queryfile_handler.cpp @@ -0,0 +1,73 @@ +#include "precompiled.h" + +CQueryFileManager g_queryFileManager; + +void CQueryFileManager::Clear() +{ + for (auto query : m_hooklist) { + delete query; + } + + m_hooklist.clear(); +} + +int CQueryFileManager::Add(AMX *amx, const char *filename, const char *funcname, ResourceType_e flag, uint32 hash) +{ + auto handler = new CQueryFileHandler(amx, funcname); + m_hooklist.push_back(handler); + g_RecheckerFuncs->AddQueryFile(filename, flag, hash, &QueryFileHandler_Callback, handler->GetUniqueID()); + return handler->GetAmxxID(); +} + +bool CQueryFileManager::Remove(int index) +{ + auto iter = m_hooklist.begin(); + while (iter != m_hooklist.end()) + { + if ((*iter)->GetAmxxID() == index) { + delete (*iter); + iter = m_hooklist.erase(iter); + return true; + } + else + iter++; + } + + return false; +} + +void CQueryFileManager::FireCallback(IGameClient *pClient, uint32 hash, int uniqueId) +{ + for (auto query : m_hooklist) + { + if (query->GetUniqueID() != uniqueId) { + continue; + } + + if (g_RecheckerFuncs->GetResource()->GetPrevHash() == hash) { + hash = 0; + } + + g_amxxapi.ExecuteForward(query->GetAmxxID(), pClient->GetId() + 1, hash); + } +} + +CQueryFileManager::CQueryFileHandler::CQueryFileHandler(AMX *amx, const char *funcname) +{ + m_amxId = g_amxxapi.RegisterSPForwardByName(amx, funcname, FP_CELL, FP_CELL, FP_DONE); + m_uniqueId = MAKE_REQUESTID(PLID); +} + +CQueryFileManager::CQueryFileHandler::~CQueryFileHandler() +{ + if (m_amxId != -1) { + g_amxxapi.UnregisterSPForward(m_amxId); + } + + g_RecheckerFuncs->RemoveQueryFile(m_uniqueId); +} + +void QueryFileHandler_Callback(IGameClient *pClient, uint32 hash, int uniqueId) +{ + g_queryFileManager.FireCallback(pClient, hash, uniqueId); +} diff --git a/reapi/src/mods/queryfile_handler.h b/reapi/src/mods/queryfile_handler.h new file mode 100644 index 0000000..314d82f --- /dev/null +++ b/reapi/src/mods/queryfile_handler.h @@ -0,0 +1,31 @@ +#pragma once + +class CQueryFileManager +{ +public: + int Add(AMX *amx, const char *filename, const char *funcname, ResourceType_e flag, uint32 hash); + void Clear(); + bool Remove(int index); + void FireCallback(IGameClient *pClient, uint32 hash, int uniqueId); + +private: + class CQueryFileHandler + { + public: + CQueryFileHandler(AMX *amx, const char *funcname); + ~CQueryFileHandler(); + + const int GetAmxxID() const { return m_amxId; }; + const int GetUniqueID() const { return m_uniqueId; }; + + private: + int m_amxId; + int m_uniqueId; + }; + + std::vector m_hooklist; +}; + +extern CQueryFileManager g_queryFileManager; + +void QueryFileHandler_Callback(IGameClient *pClient, uint32 hash, int uniqueId); diff --git a/reapi/src/natives/natives_addons.h b/reapi/src/natives/natives_addons.h deleted file mode 100644 index a4093f7..0000000 --- a/reapi/src/natives/natives_addons.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -void RegisterNatives_Addons(); diff --git a/reapi/src/natives/natives_common.cpp b/reapi/src/natives/natives_common.cpp index 650d542..ee1bf92 100644 --- a/reapi/src/natives/natives_common.cpp +++ b/reapi/src/natives/natives_common.cpp @@ -153,11 +153,11 @@ cell AMX_NATIVE_CALL has_vtc(AMX *amx, cell *params) AMX_NATIVE_INFO Natives_Checks[] = { - { "is_entity", is_entity }, - { "is_rehlds", is_rehlds }, + { "is_entity", is_entity }, + { "is_rehlds", is_rehlds }, { "is_regamedll", is_regamedll }, - { "has_reunion", has_reunion }, - { "has_vtc", has_vtc } + { "has_reunion", has_reunion }, + { "has_vtc", has_vtc }, }; void RegisterNatives_Common() diff --git a/reapi/src/natives/natives_helper.h b/reapi/src/natives/natives_helper.h index 5bac3c1..207587e 100644 --- a/reapi/src/natives/natives_helper.h +++ b/reapi/src/natives/natives_helper.h @@ -1,9 +1,11 @@ #pragma once -#define CHECK_ISPLAYER(x) if (unlikely(params[x] <= 0 || params[x] > gpGlobals->maxClients)) { MF_LogError(amx, AMX_ERR_NATIVE, "%s: invalid player index %i [%s]", __FUNCTION__, params[x], #x); return FALSE; } -#define CHECK_ISENTITY(x) if (unlikely(params[x] > gpGlobals->maxEntities)) { MF_LogError(amx, AMX_ERR_NATIVE, "%s: invalid entity index %i [%s]", __FUNCTION__, params[x], #x); return FALSE; } -#define CHECK_GAMERULES() if (unlikely(!g_pGameRules)) { MF_LogError(amx, AMX_ERR_NATIVE, "%s: gamerules not initialized", __FUNCTION__); return FALSE; } -#define CHECK_CONNECTED(x, y) if (unlikely(x == nullptr || x->has_disconnected)) { MF_LogError(amx, AMX_ERR_NATIVE, "%s: player %i is not connected", __FUNCTION__, params[y]); return FALSE; } +#define PARAMS_COUNT (params[0] / sizeof(cell)) + +#define CHECK_ISPLAYER(x) if (unlikely(params[x] <= 0 || params[x] > gpGlobals->maxClients)) { MF_LogError(amx, AMX_ERR_NATIVE, "%s: invalid player index %i [%s]", __FUNCTION__, params[x], #x); return FALSE; } +#define CHECK_ISENTITY(x) if (unlikely(params[x] > gpGlobals->maxEntities)) { MF_LogError(amx, AMX_ERR_NATIVE, "%s: invalid entity index %i [%s]", __FUNCTION__, params[x], #x); return FALSE; } +#define CHECK_GAMERULES() if (unlikely(!g_pGameRules)) { MF_LogError(amx, AMX_ERR_NATIVE, "%s: gamerules not initialized", __FUNCTION__); return FALSE; } +#define CHECK_CONNECTED(x, y) if (unlikely(x == nullptr || x->has_disconnected)) { MF_LogError(amx, AMX_ERR_NATIVE, "%s: player %i is not connected", __FUNCTION__, params[y]); return FALSE; } class CAmxArg { diff --git a/reapi/src/natives/natives_hookchains.cpp b/reapi/src/natives/natives_hookchains.cpp index 16e51a0..e69f796 100644 --- a/reapi/src/natives/natives_hookchains.cpp +++ b/reapi/src/natives/natives_hookchains.cpp @@ -301,6 +301,6 @@ void RegisterNatives_HookChains() { if (!api_cfg.hasReHLDS() && !api_cfg.hasReGameDLL()) fillNatives(HookChain_Natives, [](AMX *amx, cell *params) -> cell { MF_LogError(amx, AMX_ERR_NATIVE, "You need ReHlds or ReGameDll for use hookchains"); return FALSE; }); - + g_amxxapi.AddNatives(HookChain_Natives); } diff --git a/reapi/src/natives/natives_hookchains.h b/reapi/src/natives/natives_hookchains.h index f7a47ce..572b1eb 100644 --- a/reapi/src/natives/natives_hookchains.h +++ b/reapi/src/natives/natives_hookchains.h @@ -1,6 +1,5 @@ #pragma once -#define PARAMS_COUNT (params[0] / sizeof(cell)) #define PARAMS_REQUIRE(x) if (params[0] != x * sizeof(cell)) { MF_LogError(amx, AMX_ERR_NATIVE, "Invalid parameters count in %s", __FUNCTION__); return nullptr; } #define NATIVE_MEMBER_REQUIRE(a,x) if (!api_cfg.has##x()) { MF_LogError(amx, AMX_ERR_NATIVE, "Member (%s) is not available, required %s", memberlist[a]->member_name, #x); return 0; } diff --git a/reapi/src/natives/natives_rechecker.cpp b/reapi/src/natives/natives_rechecker.cpp new file mode 100644 index 0000000..9f07fdc --- /dev/null +++ b/reapi/src/natives/natives_rechecker.cpp @@ -0,0 +1,82 @@ +#include "precompiled.h" + +/* +* Send request the file for the client to get hash +* +* @param file The file (Can contain a relative path to the file) +* @param function The forward to call +* @param flag_type The request type, can be only RES_TYPE_EXISTS, RES_TYPE_MISSING or RES_TYPE_HASH_ANY +* @param hash Hash of file to request. +* +* @return Returns a hook handle. Use UnRegisterQueryFile to unregister the forward +* +* native QueryFileHook:RegisterQueryFile(const file[], const function[], const ResourceType:flag_type, const hash = -1); +*/ +cell AMX_NATIVE_CALL RegisterQueryFile(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_file, arg_handler, arg_flag_type, arg_hash }; + + ResourceType_e flag = (ResourceType_e)params[arg_flag_type]; + switch (flag) + { + case RES_TYPE_NONE: + case RES_TYPE_IGNORE: + MF_LogError(amx, AMX_ERR_NATIVE, "%s: invalid flag type \"%i\".", __FUNCTION__, flag); + break; + case RES_TYPE_EXISTS: + if (params[arg_hash] == -1) { + flag = RES_TYPE_HASH_ANY; + } + break; + default: + break; + } + + const char *file = getAmxString(amx, params[arg_file]); + if (!file || file[0] == '\0') { + MF_LogError(amx, AMX_ERR_NATIVE, "%s: file can not be empty.", __FUNCTION__); + return FALSE; + } + + int funcid; + const char *funcname = getAmxString(amx, params[arg_handler]); + if (unlikely(g_amxxapi.amx_FindPublic(amx, funcname, &funcid) != AMX_ERR_NONE)) + { + MF_LogError(amx, AMX_ERR_NATIVE, "%s: public function \"%s\" not found.", __FUNCTION__, funcname); + return FALSE; + } + + return g_queryFileManager.Add(amx, file, funcname, flag, params[arg_hash]); +} + +/* +* Unregister the forward. +* Use the return value from RegisterQueryFile as the parameter here! +* +* @param hook The hook to remove +* +* @return Returns true if the hook is successfully removed, otherwise false +* +* native UnRegisterQueryFile(const QueryFileHook:index); +*/ +cell AMX_NATIVE_CALL UnRegisterQueryFile(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index }; + return g_queryFileManager.Remove(params[arg_index])? TRUE : FALSE; +} + +AMX_NATIVE_INFO Rechecker_Natives[] = +{ + { "RegisterQueryFile", RegisterQueryFile }, + { "UnRegisterQueryFile", UnRegisterQueryFile }, + + { nullptr, nullptr } +}; + +void RegisterNatives_Rechecker() +{ + if (!api_cfg.hasRechecker()) + fillNatives(Rechecker_Natives, [](AMX *amx, cell *params) -> cell { MF_LogError(amx, AMX_ERR_NATIVE, "%s: isn't available", "Rechecker"); return FALSE; }); + + g_amxxapi.AddNatives(Rechecker_Natives); +} diff --git a/reapi/src/natives/natives_rechecker.h b/reapi/src/natives/natives_rechecker.h new file mode 100644 index 0000000..7cbfb89 --- /dev/null +++ b/reapi/src/natives/natives_rechecker.h @@ -0,0 +1,5 @@ +#pragma once + +#include "queryfile_handler.h" + +void RegisterNatives_Rechecker(); diff --git a/reapi/src/natives/natives_reunion.cpp b/reapi/src/natives/natives_reunion.cpp new file mode 100644 index 0000000..4012e2a --- /dev/null +++ b/reapi/src/natives/natives_reunion.cpp @@ -0,0 +1,81 @@ +#include "precompiled.h" + +/* +* Get client protocol +* +* @param index Client index +* @return client protocol +* +* native REU_GetProtocol(const index); +*/ +cell AMX_NATIVE_CALL REU_GetProtocol(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index }; + + CHECK_ISPLAYER(arg_index); + + return g_ReunionApi->GetClientProtocol(params[arg_index] - 1); +} + +/* +* Get client auth type +* +* @param index Client index +* @return client auth type +* +* native REU_GetAuthtype(const index); +*/ +cell AMX_NATIVE_CALL REU_GetAuthtype(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index }; + + CHECK_ISPLAYER(arg_index); + + return g_ReunionApi->GetClientAuthtype(params[arg_index] - 1); +} + +/* +* Check if client running RevEmu with limited user rights +* +* @param index Client index +* @return 1/0 +* +* native REU_IsRevemuWithoutAdminRights(const index); +*/ +cell AMX_NATIVE_CALL REU_IsRevemuWithoutAdminRights(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index }; + + CHECK_ISPLAYER(arg_index); + + int clientId = params[arg_index] - 1; + if (g_ReunionApi->GetClientAuthtype(clientId) != DP_AUTH_REVEMU) + return FALSE; + + char buffer[256]; + size_t size = g_ReunionApi->GetClientAuthdata(clientId, buffer, sizeof buffer); + + for (size_t i = 0; i < size; i++) { + if (!isdigit(buffer[i])) + return FALSE; + } + + return TRUE; +} + +AMX_NATIVE_INFO Reunion_Natives[] = +{ + { "REU_GetProtocol", REU_GetProtocol }, + { "REU_GetAuthtype", REU_GetAuthtype }, + { "REU_IsRevemuWithoutAdminRights", REU_IsRevemuWithoutAdminRights }, + + { nullptr, nullptr } +}; + +void RegisterNatives_Reunion() +{ + if (!api_cfg.hasReunion()) + fillNatives(Reunion_Natives, [](AMX *amx, cell *params) -> cell { MF_LogError(amx, AMX_ERR_NATIVE, "%s: isn't available", "Reunion"); return FALSE; }); + + g_amxxapi.AddNatives(Reunion_Natives); +} diff --git a/reapi/src/natives/natives_reunion.h b/reapi/src/natives/natives_reunion.h new file mode 100644 index 0000000..2fb2b42 --- /dev/null +++ b/reapi/src/natives/natives_reunion.h @@ -0,0 +1,3 @@ +#pragma once + +void RegisterNatives_Reunion(); diff --git a/reapi/src/natives/natives_addons.cpp b/reapi/src/natives/natives_vtc.cpp similarity index 52% rename from reapi/src/natives/natives_addons.cpp rename to reapi/src/natives/natives_vtc.cpp index e277cd1..701ab5d 100644 --- a/reapi/src/natives/natives_addons.cpp +++ b/reapi/src/natives/natives_vtc.cpp @@ -93,97 +93,21 @@ cell AMX_NATIVE_CALL VTC_PlaySound(AMX *amx, cell *params) return TRUE; } -AMX_NATIVE_INFO Vtc_Natives[] = +AMX_NATIVE_INFO VTC_Natives[] = { { "VTC_IsClientSpeaking", VTC_IsClientSpeaking }, - { "VTC_MuteClient", VTC_MuteClient }, - { "VTC_UnmuteClient", VTC_UnmuteClient }, - { "VTC_IsClientMuted", VTC_IsClientMuted }, - { "VTC_PlaySound", VTC_PlaySound }, + { "VTC_MuteClient", VTC_MuteClient }, + { "VTC_UnmuteClient", VTC_UnmuteClient }, + { "VTC_IsClientMuted", VTC_IsClientMuted }, + { "VTC_PlaySound", VTC_PlaySound }, { nullptr, nullptr } }; -/* -* Get client protocol -* -* @param index Client index -* @return client protocol -* -* native REU_GetProtocol(const index); -*/ -cell AMX_NATIVE_CALL REU_GetProtocol(AMX *amx, cell *params) -{ - enum args_e { arg_count, arg_index }; - - CHECK_ISPLAYER(arg_index); - - return g_ReunionApi->GetClientProtocol(params[arg_index] - 1); -} - -/* -* Get client auth type -* -* @param index Client index -* @return client auth type -* -* native REU_GetAuthtype(const index); -*/ -cell AMX_NATIVE_CALL REU_GetAuthtype(AMX *amx, cell *params) -{ - enum args_e { arg_count, arg_index }; - - CHECK_ISPLAYER(arg_index); - - return g_ReunionApi->GetClientAuthtype(params[arg_index] - 1); -} - -/* -* Check if client running RevEmu with limited user rights -* -* @param index Client index -* @return 1/0 -* -* native REU_IsRevemuWithoutAdminRights(const index); -*/ -cell AMX_NATIVE_CALL REU_IsRevemuWithoutAdminRights(AMX *amx, cell *params) -{ - enum args_e { arg_count, arg_index }; - - CHECK_ISPLAYER(arg_index); - - int clientId = params[arg_index] - 1; - if (g_ReunionApi->GetClientAuthtype(clientId) != DP_AUTH_REVEMU) - return FALSE; - - char buffer[256]; - size_t size = g_ReunionApi->GetClientAuthdata(clientId, buffer, sizeof buffer); - - for (size_t i = 0; i < size; i++) { - if (!isdigit(buffer[i])) - return FALSE; - } - - return TRUE; -} - -AMX_NATIVE_INFO Reunion_Natives[] = -{ - { "REU_GetProtocol", REU_GetProtocol }, - { "REU_GetAuthtype", REU_GetAuthtype }, - { "REU_IsRevemuWithoutAdminRights", REU_IsRevemuWithoutAdminRights }, - - { nullptr, nullptr } -}; - -void RegisterNatives_Addons() +void RegisterNatives_VTC() { if (!api_cfg.hasVTC()) - fillNatives(Vtc_Natives, [](AMX *amx, cell *params) -> cell { MF_LogError(amx, AMX_ERR_NATIVE, "%s: isn't available", "VTC"); return FALSE; }); + fillNatives(VTC_Natives, [](AMX *amx, cell *params) -> cell { MF_LogError(amx, AMX_ERR_NATIVE, "%s: isn't available", "VTC"); return FALSE; }); - if (!api_cfg.hasReunion()) - fillNatives(Reunion_Natives, [](AMX *amx, cell *params) -> cell { MF_LogError(amx, AMX_ERR_NATIVE, "%s: isn't available", "Reunion"); return FALSE; }); - - g_amxxapi.AddNatives(Vtc_Natives); - g_amxxapi.AddNatives(Reunion_Natives); + g_amxxapi.AddNatives(VTC_Natives); } diff --git a/reapi/src/natives/natives_vtc.h b/reapi/src/natives/natives_vtc.h new file mode 100644 index 0000000..e3bb0df --- /dev/null +++ b/reapi/src/natives/natives_vtc.h @@ -0,0 +1,3 @@ +#pragma once + +void RegisterNatives_VTC(); diff --git a/reapi/src/precompiled.h b/reapi/src/precompiled.h index 15eaeda..6990dba 100644 --- a/reapi/src/precompiled.h +++ b/reapi/src/precompiled.h @@ -45,6 +45,10 @@ #include #include "mod_reunion_api.h" +// regamedll API +#include +#include "mod_rechecker_api.h" + // AmxModX API #include "amxxmodule.h" @@ -61,5 +65,9 @@ #include "natives_members.h" #include "natives_misc.h" #include "natives_common.h" -#include "natives_addons.h" #include "natives_helper.h" + +// addons +#include "natives_vtc.h" +#include "natives_reunion.h" +#include "natives_rechecker.h" diff --git a/shared_icc.gradle b/shared_icc.gradle index 9fb7e9d..f844c8a 100644 --- a/shared_icc.gradle +++ b/shared_icc.gradle @@ -18,14 +18,16 @@ rootProject.ext.createIccConfig = { boolean release, BinaryKind binKind -> extraDefines: [ 'linux': null, '__linux__': null, - 'NDEBUG': null - ] + 'NDEBUG': null, + '_GLIBCXX_USE_CXX11_ABI': 0, // don't use specific c++11 features from GCC 5.X for backward compatibility to earlier version ABI libstdc++.so.6 + ], ), linkerOptions: new GccToolchainConfig.LinkerOptions( - interProceduralOptimizations: true, + interProceduralOptimizations: true, // -ipo stripSymbolTable: true, - staticLibGcc: true, + staticLibStdCpp: false, + staticLibGcc: false, staticIntel: true, ), @@ -46,14 +48,16 @@ rootProject.ext.createIccConfig = { boolean release, BinaryKind binKind -> extraDefines: [ 'linux': null, '__linux__': null, - 'NDEBUG': null - ] + 'NDEBUG': null, + '_GLIBCXX_USE_CXX11_ABI': 0, // don't use specific c++11 features from GCC 5.X for backward compatibility to earlier version ABI libstdc++.so.6 + ], ), linkerOptions: new GccToolchainConfig.LinkerOptions( interProceduralOptimizations: false, stripSymbolTable: false, - staticLibGcc: true, + staticLibStdCpp: false, + staticLibGcc: false, staticIntel: true, ), diff --git a/shared_msvc.gradle b/shared_msvc.gradle index e563c52..c2a8b08 100644 --- a/shared_msvc.gradle +++ b/shared_msvc.gradle @@ -121,5 +121,22 @@ rootProject.ext.createMsvcConfig = { boolean release, BinaryKind binKind -> } } + // Detect and setup UCRT paths + def ucrtInfo = "getucrtinfo.bat".execute().text + def m = ucrtInfo =~ /^(.*)\r\n(.*)?$/ + if (!m.find()) { + return cfg + } + + def kitPath = m.group(1) + def ucrtVersion = m.group(2) + def ucrtCheckFile = new File("${kitPath}Include/${ucrtVersion}/ucrt/stdio.h"); + if (!ucrtCheckFile.exists()) { + return cfg + } + + cfg.compilerOptions.args "/FS", "/I${kitPath}Include/${ucrtVersion}/ucrt"; + cfg.linkerOptions.args("/LIBPATH:${kitPath}Lib/${ucrtVersion}/ucrt/x86"); + return cfg }