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