diff --git a/reapi/build.gradle b/reapi/build.gradle index b7b8239..0ddda3d 100644 --- a/reapi/build.gradle +++ b/reapi/build.gradle @@ -37,7 +37,7 @@ void postEvaluate(NativeBinarySpec b) { void setupToolchain(NativeBinarySpec b) { ToolchainConfig cfg = rootProject.createToolchainConfig(b) - cfg.projectInclude(project, '', '/src', '/src/mods', '/src/natives', '/include', '/include/metamod', '/include/cssdk/common', '/include/cssdk/dlls', '/include/cssdk/engine', '/include/cssdk/game_shared', '/include/cssdk/pm_shared', '/include/cssdk/public') + cfg.projectInclude(project, '', '/src', '/common', '/src/mods', '/src/natives', '/include', '/include/metamod', '/include/cssdk/common', '/include/cssdk/dlls', '/include/cssdk/engine', '/include/cssdk/game_shared', '/include/cssdk/pm_shared', '/include/cssdk/public') cfg.singleDefines('HAVE_STRONG_TYPEDEF'); if (cfg instanceof MsvcToolchainConfig) { @@ -108,7 +108,7 @@ model { } reapi_src(CppSourceSet) { source { - srcDirs "src", "include/cssdk/public" + srcDirs "src", "common", "include/cssdk/public" include "**/*.cpp" exclude "precompiled.cpp" diff --git a/reapi/common/info.cpp b/reapi/common/info.cpp new file mode 100644 index 0000000..5e0f096 --- /dev/null +++ b/reapi/common/info.cpp @@ -0,0 +1,364 @@ +#include "precompiled.h" + +// NOTE: This file contains a lot of fixes that are not covered by REHLDS_FIXES define. +// TODO: Most of the Info_ functions can be speedup via removing unneded copy of key and values. + +// Searches the string for the given +// key and returns the associated value, or an empty string. +const char *Info_ValueForKey(const char *s, const char *key) +{ + // use few (two?) buffers so compares work without stomping on each other + static char value[INFO_MAX_BUFFER_VALUES][MAX_KV_LEN]; + static int valueindex; + char pkey[MAX_KV_LEN]; + char *c; + int nCount; + + while (*s) + { + if (*s == '\\') + { + s++; // skip the slash + } + + // Copy a key + nCount = 0; + c = pkey; + while (*s != '\\') + { + if (!*s) + { + // key should end with a \, not a NULL, but suppose its value as absent + return ""; + } + + if (nCount >= MAX_KV_LEN) + { + s++; + continue; // skip oversized key chars till the slash or EOL + } + *c++ = *s++; + nCount++; + } + *c = 0; + s++; // skip the slash + + // Copy a value + nCount = 0; + c = value[valueindex]; + while (*s != '\\') + { + if (!*s) + { + break; // allow value to be ended with NULL + } + + if (nCount >= MAX_KV_LEN) + { + s++; + continue; // skip oversized value chars till the slash or EOL + } + + *c++ = *s++; + nCount++; + } + *c = 0; + + if (!Q_strcmp(key, pkey)) + { + c = value[valueindex]; + valueindex = (valueindex + 1) % INFO_MAX_BUFFER_VALUES; + return c; + } + } + + return ""; +} + +void Info_RemoveKey(char *s, const char *key) +{ + char pkey[MAX_KV_LEN]; + char value[MAX_KV_LEN]; + char *start; + char *c; + int cmpsize; + int nCount; + + if (Q_strstr(key, "\\")) + { + UTIL_ServerPrint("Can't use a key with a \\\n"); + return; + } + + cmpsize = Q_strlen(key); + if (cmpsize > MAX_KV_LEN - 1) + cmpsize = MAX_KV_LEN - 1; + + while (*s) + { + start = s; + + if (*s == '\\') + { + s++; // skip the slash + } + + // Copy a key + nCount = 0; + c = pkey; + while (*s != '\\') + { + if (!*s) + { + break; // key should end with a \, not a NULL, but allow to remove it + } + if (nCount >= MAX_KV_LEN) + { + s++; + continue; // skip oversized key chars till the slash or EOL + } + *c++ = *s++; + nCount++; + } + *c = 0; + if (*s) + s++; // skip the slash + + // Copy a value + nCount = 0; + c = value; + while (*s != '\\') + { + if (!*s) + { + break; // allow value to be ended with NULL + } + + if (nCount >= MAX_KV_LEN) + { + s++; + continue; // skip oversized value chars till the slash or EOL + } + + *c++ = *s++; + nCount++; + } + *c = 0; + + // Compare keys + if (!Q_strncmp(key, pkey, cmpsize)) + { + Q_strcpy_s(start, s); // remove this part + s = start; // continue searching + } + } +} + +qboolean Info_IsKeyImportant(const char *key) +{ + if (key[0] == '*') + return true; + if (!strcmp(key, "name")) + return true; + if (!strcmp(key, "model")) + return true; + if (!strcmp(key, "rate")) + return true; + if (!strcmp(key, "topcolor")) + return true; + if (!strcmp(key, "bottomcolor")) + return true; + if (!strcmp(key, "cl_updaterate")) + return true; + if (!strcmp(key, "cl_lw")) + return true; + if (!strcmp(key, "cl_lc")) + return true; + + return false; +} + +char *Info_FindLargestKey(char *s, int maxsize) +{ + static char largest_key[MAX_KV_LEN]; + char key[MAX_KV_LEN]; + char value[MAX_KV_LEN]; + char *c; + int nCount; + int largest_size = 0; + + largest_key[0] = 0; + + while (*s) + { + if (*s == '\\') + { + s++; // skip the slash + } + + // Copy a key + nCount = 0; + c = key; + while (*s != '\\') + { + // key should end with a \, not a NULL, return this key, so it will be deleted as wrong + if (!*s) + { + *c = 0; + strcpy(largest_key, key); + return largest_key; + } + + // oversized key, return this key, so it will be deleted as wrong + if (nCount >= MAX_KV_LEN) + { + *c = 0; + strcpy(largest_key, key); + return largest_key; + } + *c++ = *s++; + nCount++; + } + *c = 0; + s++; // skip the slash + + // Get length + int size = c - key; + + // Copy a value + nCount = 0; + c = value; + while (*s != '\\') + { + if (!*s) + { + break; // allow value to be ended with NULL + } + if (nCount >= MAX_KV_LEN) // oversized value, return this key, so it will be deleted as wrong + { + *c = 0; + strcpy(largest_key, key); + return largest_key; + } + *c++ = *s++; + nCount++; + } + *c = 0; + + // Add length + size += c - value; + + if (size > largest_size && !Info_IsKeyImportant(key)) + { + largest_size = size; + strcpy(largest_key, key); + } + } + + return largest_key; +} + +void Info_SetValueForStarKey(char *s, const char *key, const char *value, int maxsize) +{ + char newArray[MAX_INFO_STRING]; + char *v; + int c; + + if (!key || !value) + { + UTIL_ServerPrint("Keys and values can't be null\n"); + return; + } + + if (key[0] == 0) + { + UTIL_ServerPrint("Keys can't be an empty string\n"); + return; + } + + if (Q_strstr(key, "\\") || Q_strstr(value, "\\")) + { + UTIL_ServerPrint("Can't use keys or values with a \\\n"); + return; + } + + if (Q_strstr(key, "..") || Q_strstr(value, "..")) + { + // TODO: Why silently return? + //UTIL_ServerPrint("Can't use keys or values with a ..\n"); + return; + } + + if (Q_strstr(key, "\"") || Q_strstr(value, "\"")) + { + UTIL_ServerPrint("Can't use keys or values with a \"\n"); + return; + } + + int keyLen = Q_strlen(key); + int valueLan = Q_strlen(value); + + if (keyLen >= MAX_KV_LEN || valueLan >= MAX_KV_LEN) + { + UTIL_ServerPrint("Keys and values must be < %i characters\n", MAX_KV_LEN); + return; + } + + /*if (!Q_UnicodeValidate(key) || !Q_UnicodeValidate(value)) + { + UTIL_ServerPrint("Keys and values must be valid utf8 text\n"); + return; + }*/ + + // Remove current key/value and return if we doesn't specified to set a value + Info_RemoveKey(s, key); + if (value[0] == 0) + { + return; + } + + // Create key/value pair + Q_snprintf(newArray, MAX_INFO_STRING - 1, "\\%s\\%s", key, value); + newArray[MAX_INFO_STRING - 1] = 0; + + int neededLength = Q_strlen(newArray); + if ((int)Q_strlen(s) + neededLength >= maxsize) + { + // no more room in the buffer to add key/value + if (!Info_IsKeyImportant(key)) + { + // no room to add setting + UTIL_ServerPrint("Info string length exceeded\n"); + return; + } + + // keep removing the largest key/values until we have a room + char *largekey; + do + { + largekey = Info_FindLargestKey(s, maxsize); + if (largekey[0] == 0) + { + // no room to add setting + UTIL_ServerPrint("Info string length exceeded\n"); + return; + } + Info_RemoveKey(s, largekey); + } while ((int)Q_strlen(s) + neededLength >= maxsize); + } + + // auto lowercase team + bool lowerCaseValue = _stricmp(key, "team") == 0; + s += Q_strlen(s); + v = newArray; + while (*v) + { + c = (unsigned char)*v++; + if (lowerCaseValue) + { + c = tolower(c); + } + *s++ = c; + } + *s = 0; +} diff --git a/reapi/common/info.h b/reapi/common/info.h new file mode 100644 index 0000000..f12fb75 --- /dev/null +++ b/reapi/common/info.h @@ -0,0 +1,10 @@ +#pragma once + +// Key + value + 2 x slash + NULL +const int MAX_INFO_STRING = 256; +const int MAX_KV_LEN = 127; +const int INFO_MAX_BUFFER_VALUES = 4; + +const char *Info_ValueForKey(const char *s, const char *key); +void Info_RemoveKey(char *s, const char *key); +void Info_SetValueForStarKey(char *s, const char *key, const char *value, int maxsize); diff --git a/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc index 1974acf..691a6f3 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_engine_const.inc @@ -18,32 +18,32 @@ enum MapNameType enum EngineFunc { /* - * Description: - - * Params: (const recipients, const entity, const channel, const sample[], const volume, Float:attenuation, const fFlags, const pitch) + * Description: - + * Params: (const recipients, const entity, const channel, const sample[], const volume, Float:attenuation, const fFlags, const pitch) */ RH_SV_StartSound = BEGIN_FUNC_REGION(engine), /* - * Description: - - * Params: (const client, bool:crash, const fmt[]) + * Description: - + * Params: (const client, bool:crash, const fmt[]) */ RH_SV_DropClient, /* - * Description: - - * Params: (const runPhysics) + * Description: - + * Params: (const runPhysics) */ RH_SV_ActivateServer, /* - * Description: - - * Params: (pcvar, const value[]) + * Description: - + * Params: (pcvar, const value[]) */ RH_Cvar_DirectSet, /* - * Description: Receiver is player index or 0 when update will be sended to all. - * Params: (client, receiver, pinfo) + * Description: Receiver is player index or 0 when update will be sended to all. + * Params: (const client, buffer, const receiver) */ RH_SV_WriteFullClientUpdate, }; diff --git a/reapi/include/com_client.h b/reapi/include/com_client.h index a5a8013..4a305b1 100644 --- a/reapi/include/com_client.h +++ b/reapi/include/com_client.h @@ -34,10 +34,6 @@ #include "com_progdefs.h" #include "com_delta_packet.h" -// Key + value + 2 x slash + NULL -const int MAX_INFO_STRING = 256; -const int MAX_KV_LEN = 127; - typedef struct client_frame_s { double senttime; diff --git a/reapi/include/typedef_strong.h b/reapi/include/typedef_strong.h deleted file mode 100644 index 28f51a1..0000000 --- a/reapi/include/typedef_strong.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -* -* 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 - -class string_t -{ -public: - using unsigned int; -}; diff --git a/reapi/msvc/reapi.vcxproj b/reapi/msvc/reapi.vcxproj index 5d07f4b..6990ff4 100644 --- a/reapi/msvc/reapi.vcxproj +++ b/reapi/msvc/reapi.vcxproj @@ -11,6 +11,7 @@ + @@ -227,6 +228,7 @@ + true true @@ -336,7 +338,7 @@ true MultiThreadedDebug precompiled.h - $(ProjectDir)\..\src;$(ProjectDir)\..\src\mods;$(ProjectDir)\..\src\natives;$(ProjectDir)\..\version;$(ProjectDir)\..\include;$(ProjectDir)\..\include\metamod;$(ProjectDir)\..\include\cssdk\common;$(ProjectDir)\..\include\cssdk\dlls;$(ProjectDir)\..\include\cssdk\engine;$(ProjectDir)\..\include\cssdk\game_shared;$(ProjectDir)\..\include\cssdk\pm_shared;$(ProjectDir)\..\include\cssdk\public;%(AdditionalIncludeDirectories) + $(ProjectDir)\..\src;$(ProjectDir)\..\src\mods;$(ProjectDir)\..\src\natives;$(ProjectDir)\..\common;$(ProjectDir)\..\version;$(ProjectDir)\..\include;$(ProjectDir)\..\include\metamod;$(ProjectDir)\..\include\cssdk\common;$(ProjectDir)\..\include\cssdk\dlls;$(ProjectDir)\..\include\cssdk\engine;$(ProjectDir)\..\include\cssdk\game_shared;$(ProjectDir)\..\include\cssdk\pm_shared;$(ProjectDir)\..\include\cssdk\public;%(AdditionalIncludeDirectories) ProgramDatabase true false @@ -385,7 +387,7 @@ WIN32;HAVE_STRONG_TYPEDEF;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - $(ProjectDir)\..\src;$(ProjectDir)\..\src\mods;$(ProjectDir)\..\src\natives;$(ProjectDir)\..\version;$(ProjectDir)\..\include;$(ProjectDir)\..\include\metamod;$(ProjectDir)\..\include\cssdk\common;$(ProjectDir)\..\include\cssdk\dlls;$(ProjectDir)\..\include\cssdk\engine;$(ProjectDir)\..\include\cssdk\game_shared;$(ProjectDir)\..\include\cssdk\pm_shared;$(ProjectDir)\..\include\cssdk\public;%(AdditionalIncludeDirectories) + $(ProjectDir)\..\src;$(ProjectDir)\..\src\mods;$(ProjectDir)\..\src\natives;$(ProjectDir)\..\common;$(ProjectDir)\..\version;$(ProjectDir)\..\include;$(ProjectDir)\..\include\metamod;$(ProjectDir)\..\include\cssdk\common;$(ProjectDir)\..\include\cssdk\dlls;$(ProjectDir)\..\include\cssdk\engine;$(ProjectDir)\..\include\cssdk\game_shared;$(ProjectDir)\..\include\cssdk\pm_shared;$(ProjectDir)\..\include\cssdk\public;%(AdditionalIncludeDirectories) MultiThreaded precompiled.h AnySuitable diff --git a/reapi/msvc/reapi.vcxproj.filters b/reapi/msvc/reapi.vcxproj.filters index ea57442..6023445 100644 --- a/reapi/msvc/reapi.vcxproj.filters +++ b/reapi/msvc/reapi.vcxproj.filters @@ -58,6 +58,9 @@ {60b1b924-8415-4c1d-9fef-57e717e12f42} + + {8232a3e7-911f-4ee1-8223-03ac077d7bee} + @@ -690,6 +693,9 @@ include + + common + @@ -788,6 +794,9 @@ src\mods + + common + diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index 1152b75..d1cfef2 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -46,24 +46,21 @@ void Cvar_DirectSet(IRehldsHook_Cvar_DirectSet *chain, cvar_t *var, const char * callVoidForward(RH_Cvar_DirectSet, original, var, value); } -void SV_WriteFullClientUpdate(IRehldsHook_SV_WriteFullClientUpdate *chain, IGameClient *client, char *info, size_t maxlen, sizebuf_t *sb, IGameClient *receiver) +void SV_WriteFullClientUpdate_AMXX(SV_WriteFullClientUpdate_t *data, IGameClient *client, size_t buffer, IGameClient *receiver) { - int receiver_id = 0; - if (receiver) - receiver_id = receiver->GetId() + 1; - - auto original = [chain, sb](int _client, int _receiver, int _pinfo) + auto original = [data](int _client, size_t _buffer, int _receiver) { - sizebuf_t* dest = sb; - IGameClient* receiver = nullptr; - if (_receiver) { - receiver = g_RehldsSvs->GetClient(_receiver - 1); - dest = receiver->GetNetChan()->GetMessageBuf(); - } - chain->callNext(g_RehldsSvs->GetClient(_client - 1), (char *)_pinfo, MAX_INFO_STRING, dest, receiver); + data->m_chain->callNext(g_RehldsSvs->GetClient(_client - 1), (char *)_buffer, data->m_args.maxlen, data->m_args.message, g_RehldsSvs->GetClient(_receiver - 1)); }; - callVoidForward(RH_SV_WriteFullClientUpdate, original, client->GetId() + 1, receiver_id, int(info)); + callVoidForward(RH_SV_WriteFullClientUpdate, original, client->GetId() + 1, buffer, receiver ? receiver->GetId() + 1 : AMX_NULLENT); +} + +void SV_WriteFullClientUpdate(IRehldsHook_SV_WriteFullClientUpdate *chain, IGameClient *client, char *buffer, size_t maxlen, sizebuf_t *sb, IGameClient *receiver) +{ + SV_WriteFullClientUpdate_args_t args(sb, maxlen); + SV_WriteFullClientUpdate_t data(chain, args); + SV_WriteFullClientUpdate_AMXX(&data, client, (size_t)buffer, receiver); } /* @@ -857,7 +854,7 @@ void FileConsistencyProcess_AMXX(FileConsistencyProcess_t *data, IGameClient *cl 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); + data->m_chain->callNext(g_RehldsSvs->GetClient(_cl - 1), data->m_args, _type, hashCopy); }; if (g_RecheckerFuncs->GetResource()->GetPrevHash() == responseHash) { @@ -888,7 +885,7 @@ void CmdExec_AMXX(CmdExec_t *data, IGameClient *cl, const char *filename, char * 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); + data->m_chain->callNext(g_RehldsSvs->GetClient(_cl - 1), data->m_args, _cmd, hashCopy); }; if (g_RecheckerFuncs->GetResource()->GetPrevHash() == responseHash) { diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 8dee606..61bbbe7 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -29,8 +29,8 @@ struct retval_t { char* _string; float _float; - int _integer; - CBaseEntity* _classptr; + int _integer; + CBaseEntity* _classptr; edict_t* _edict; entvars_t* _pev; }; @@ -39,11 +39,11 @@ struct retval_t inline AType getApiType(int) { return ATYPE_INTEGER; } inline AType getApiType(unsigned) { return ATYPE_INTEGER; } inline AType getApiType(float) { return ATYPE_FLOAT; } -inline AType getApiType(const char *) { return ATYPE_STRING; } +inline AType getApiType(const char *) { return ATYPE_STRING; } inline AType getApiType(char[]) { return ATYPE_STRING; } -inline AType getApiType(CBaseEntity *) { return ATYPE_CLASSPTR; } +inline AType getApiType(CBaseEntity *) { return ATYPE_CLASSPTR; } inline AType getApiType(edict_t *) { return ATYPE_EDICT; } -inline AType getApiType(entvars_t *) { return ATYPE_EVARS; } +inline AType getApiType(entvars_t *) { return ATYPE_EVARS; } template inline AType getApiType(T *) { return ATYPE_INTEGER; } @@ -288,10 +288,10 @@ R callForward(size_t func, original_t original, f_args... args) template struct hookdata_t { - hookdata_t(T chain, A data) : m_chain(chain), m_data(data) {} + hookdata_t(T chain, A args) : m_chain(chain), m_args(args) {} T m_chain; - A m_data; + A m_args; }; // rehlds functions @@ -299,7 +299,18 @@ void SV_StartSound(IRehldsHook_SV_StartSound *chain, int recipients, edict_t *en void SV_DropClient(IRehldsHook_SV_DropClient *chain, IGameClient *cl, bool crash, const char *fmt); void SV_ActivateServer(IRehldsHook_SV_ActivateServer *chain, int runPhysics); void Cvar_DirectSet(IRehldsHook_Cvar_DirectSet *chain, cvar_t *var, const char *value); -void SV_WriteFullClientUpdate(IRehldsHook_SV_WriteFullClientUpdate *chain, IGameClient *client, char *info, size_t maxlen, sizebuf_t *sb, IGameClient *receiver); + +struct SV_WriteFullClientUpdate_args_t +{ + SV_WriteFullClientUpdate_args_t(sizebuf_t *msg, int size) : message(msg), maxlen(size) {} + + sizebuf_t *message; + int maxlen; +}; + +using SV_WriteFullClientUpdate_t = hookdata_t; +void SV_WriteFullClientUpdate_AMXX(SV_WriteFullClientUpdate_t *data, IGameClient *client, size_t buffer, IGameClient *receiver); +void SV_WriteFullClientUpdate(IRehldsHook_SV_WriteFullClientUpdate *chain, IGameClient *client, char *buffer, size_t maxlen, sizebuf_t *sb, IGameClient *receiver); // regamedll functions int GetForceCamera(IReGameHook_GetForceCamera *chain, CBasePlayer *pObserver); diff --git a/reapi/src/hook_list.cpp b/reapi/src/hook_list.cpp index be0eb9c..655e31d 100644 --- a/reapi/src/hook_list.cpp +++ b/reapi/src/hook_list.cpp @@ -1,13 +1,13 @@ #include "precompiled.h" -inline size_t getFwdParamType(void(*)(int)) { return FP_CELL; } -inline size_t getFwdParamType(void(*)(size_t)) { 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(*)(size_t)) { 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(*)(ScenarioEventEndRound)) { return FP_CELL; } inline size_t getFwdParamType(void(*)(ItemID)) { return FP_CELL; } inline size_t getFwdParamType(void(*)(ItemRestType)) { return FP_CELL; } @@ -19,7 +19,7 @@ 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; } +inline size_t getFwdParamType(void(*)(T *)) { return FP_CELL; } template void setupParamTypes(size_t param_types[], void (*)()) @@ -69,13 +69,13 @@ struct regfunc int regfunc::current_cell = 1; -#define ENG(h) { {}, {}, #h, "ReHLDS", [](){ return api_cfg.hasReHLDS(); }, ((!(RH_##h & (MAX_REGION_RANGE - 1)) ? regfunc::current_cell = 1, true : false) || (RH_##h & (MAX_REGION_RANGE - 1)) == regfunc::current_cell++) ? regfunc(h) : regfunc(#h), [](){ g_RehldsHookchains->##h##()->registerHook(&##h); }, [](){ g_RehldsHookchains->##h##()->unregisterHook(&##h); }} +#define ENG(h,...) { {}, {}, #h, "ReHLDS", [](){ return api_cfg.hasReHLDS(); }, ((!(RH_##h & (MAX_REGION_RANGE - 1)) ? regfunc::current_cell = 1, true : false) || (RH_##h & (MAX_REGION_RANGE - 1)) == regfunc::current_cell++) ? regfunc(h##__VA_ARGS__) : regfunc(#h#__VA_ARGS__), [](){ g_RehldsHookchains->##h##()->registerHook(&##h); }, [](){ g_RehldsHookchains->##h##()->unregisterHook(&##h); }} hook_t hooklist_engine[] = { ENG(SV_StartSound), ENG(SV_DropClient), ENG(SV_ActivateServer), ENG(Cvar_DirectSet), - ENG(SV_WriteFullClientUpdate) + ENG(SV_WriteFullClientUpdate, _AMXX) }; #define DLL(h) { {}, {}, #h, "ReGameDLL", [](){ return api_cfg.hasReGameDLL(); }, ((!(RG_##h & (MAX_REGION_RANGE - 1)) ? regfunc::current_cell = 1, true : false) || (RG_##h & (MAX_REGION_RANGE - 1)) == regfunc::current_cell++) ? regfunc(h) : regfunc(#h), [](){ g_ReGameHookchains->##h##()->registerHook(&##h); }, [](){ g_ReGameHookchains->##h##()->unregisterHook(&##h); }} diff --git a/reapi/src/natives/natives_common.cpp b/reapi/src/natives/natives_common.cpp index be4d9ef..8bb77cc 100644 --- a/reapi/src/natives/natives_common.cpp +++ b/reapi/src/natives/natives_common.cpp @@ -129,9 +129,15 @@ cell AMX_NATIVE_CALL amx_get_key_value(AMX *amx, cell *params) { enum args_e { arg_count, arg_buffer, arg_key, arg_value, arg_maxlen }; - char buffer[MAX_INFO_STRING], key[MAX_KV_LEN]; - Q_strlcpy(buffer, getAmxString(amx, params[arg_buffer])); - Q_strlcpy(key, getAmxString(amx, params[arg_key])); + char *buffer = reinterpret_cast(params[arg_buffer]); + if (!buffer) + { + MF_LogError(amx, AMX_ERR_NATIVE, "%s: Invalid buffer", __FUNCTION__); + return FALSE; + } + + char key[MAX_KV_LEN]; + Q_strlcpy(key, getAmxString(amx, params[arg_key])); return g_amxxapi.SetAmxString(amx, params[arg_value], g_engfuncs.pfnInfoKeyValue(buffer, key), params[arg_maxlen]); } @@ -145,18 +151,33 @@ cell AMX_NATIVE_CALL amx_get_key_value(AMX *amx, cell *params) * * @noreturn * -* native set_key_value(const pbuffer, const key[], const value[]); +* native set_key_value(const &pbuffer, const key[], const value[]); */ cell AMX_NATIVE_CALL amx_set_key_value(AMX *amx, cell *params) { enum args_e { arg_count, arg_buffer, arg_key, arg_value }; - char buffer[MAX_INFO_STRING], key[MAX_KV_LEN], value[MAX_KV_LEN]; - Q_strlcpy(buffer, getAmxString(amx, params[arg_buffer])); + char *buffer = reinterpret_cast(params[arg_buffer]); + if (!buffer) + { + MF_LogError(amx, AMX_ERR_NATIVE, "%s: Invalid buffer", __FUNCTION__); + return FALSE; + } + + char key[MAX_KV_LEN], value[MAX_KV_LEN]; Q_strlcpy(key, getAmxString(amx, params[arg_key])); Q_strlcpy(value, getAmxString(amx, params[arg_value])); - g_engfuncs.pfnSetKeyValue(buffer, key, value); + if (!key[0]) + { + buffer[0] = '\0'; + return TRUE; + } + + Info_SetValueForStarKey(buffer, key, value, MAX_INFO_STRING); + + // TODO: this function doesn't let me sets another buffer + //g_engfuncs.pfnSetKeyValue(buffer, key, value); return TRUE; } diff --git a/reapi/src/precompiled.h b/reapi/src/precompiled.h index 0a7ca81..c780735 100644 --- a/reapi/src/precompiled.h +++ b/reapi/src/precompiled.h @@ -52,6 +52,7 @@ // AmxModX API #include "amxxmodule.h" +#include "info.h" #include "com_client.h" // reapi main