mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-26 06:45:37 +03:00
Cvars: Rearrange a bit some code
Changed class CCVar -> struct CvarInfo Added CvarManager class and moved some code there Code of registering a cvar is rewritten Cvars datas are stored in a hashtable for fast lookup For natives compatibility, an inline list is kept (though CList -> ke::InlineList) Replace some CVAR_GET/SEt_ by FindVar
This commit is contained in:
parent
f973f5beb7
commit
cdc7d550eb
@ -1923,11 +1923,15 @@ static cell AMX_NATIVE_CALL get_pcvar_string(AMX *amx, cell *params)
|
|||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_cvar_string(AMX *amx, cell *params) /* 3 param */
|
static cell AMX_NATIVE_CALL get_cvar_string(AMX *amx, cell *params) /* 3 param */
|
||||||
{
|
{
|
||||||
int ilen;
|
int length;
|
||||||
char* sptemp = get_amxstring(amx, params[1], 0, ilen);
|
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||||
|
|
||||||
const char *value = CVAR_GET_STRING(sptemp);
|
cvar_t* var = g_CvarManager.FindCvar(name);
|
||||||
return set_amxstring_utf8(amx, params[2], value, strlen(value), params[3] + 1); // + EOS
|
|
||||||
|
const char *value = var ? var->string : "";
|
||||||
|
length = var ? strlen(value) : 0;
|
||||||
|
|
||||||
|
return set_amxstring_utf8(amx, params[2], value, length, params[3] + 1); // + EOS
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_pcvar_float(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL get_pcvar_float(AMX *amx, cell *params)
|
||||||
@ -1939,18 +1943,17 @@ static cell AMX_NATIVE_CALL get_pcvar_float(AMX *amx, cell *params)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
REAL val = (REAL)ptr->value;
|
return amx_ftoc(ptr->value);
|
||||||
|
|
||||||
return amx_ftoc(val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_cvar_float(AMX *amx, cell *params) /* 1 param */
|
static cell AMX_NATIVE_CALL get_cvar_float(AMX *amx, cell *params) /* 1 param */
|
||||||
{
|
{
|
||||||
int ilen;
|
int length;
|
||||||
|
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||||
|
|
||||||
REAL pFloat = CVAR_GET_FLOAT(get_amxstring(amx, params[1], 0, ilen));
|
cvar_t* var = g_CvarManager.FindCvar(name);
|
||||||
|
|
||||||
return amx_ftoc(pFloat);
|
return var ? amx_ftoc(var->value) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL set_pcvar_float(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL set_pcvar_float(AMX *amx, cell *params)
|
||||||
@ -1962,15 +1965,24 @@ static cell AMX_NATIVE_CALL set_pcvar_float(AMX *amx, cell *params)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
UTIL_Format(CVarTempBuffer,sizeof(CVarTempBuffer)-1,"%f",amx_ctof(params[2]));
|
UTIL_Format(CVarTempBuffer, sizeof(CVarTempBuffer) - 1, "%f", amx_ctof(params[2]));
|
||||||
(*g_engfuncs.pfnCvar_DirectSet)(ptr, &CVarTempBuffer[0]);
|
CVAR_DIRECTSET(ptr, &CVarTempBuffer[0]);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL set_cvar_float(AMX *amx, cell *params) /* 2 param */
|
static cell AMX_NATIVE_CALL set_cvar_float(AMX *amx, cell *params) /* 2 param */
|
||||||
{
|
{
|
||||||
int ilen;
|
int length;
|
||||||
CVAR_SET_FLOAT(get_amxstring(amx, params[1], 0, ilen), amx_ctof(params[2]));
|
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||||
|
|
||||||
|
cvar_t* var = g_CvarManager.FindCvar(name);
|
||||||
|
|
||||||
|
if (var)
|
||||||
|
{
|
||||||
|
UTIL_Format(CVarTempBuffer, sizeof(CVarTempBuffer) - 1, "%f", amx_ctof(params[2]));
|
||||||
|
CVAR_DIRECTSET(var, &CVarTempBuffer[0]);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1989,8 +2001,13 @@ static cell AMX_NATIVE_CALL get_pcvar_num(AMX *amx, cell *params)
|
|||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_cvar_num(AMX *amx, cell *params) /* 1 param */
|
static cell AMX_NATIVE_CALL get_cvar_num(AMX *amx, cell *params) /* 1 param */
|
||||||
{
|
{
|
||||||
int ilen;
|
int length;
|
||||||
return (int)CVAR_GET_FLOAT(get_amxstring(amx, params[1], 0, ilen));
|
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||||
|
|
||||||
|
cvar_t* var = g_CvarManager.FindCvar(name);
|
||||||
|
|
||||||
|
return var ? (int)var->value : 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL set_pcvar_num(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL set_pcvar_num(AMX *amx, cell *params)
|
||||||
@ -2003,26 +2020,39 @@ static cell AMX_NATIVE_CALL set_pcvar_num(AMX *amx, cell *params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
UTIL_Format(CVarTempBuffer,sizeof(CVarTempBuffer)-1,"%d",params[2]);
|
UTIL_Format(CVarTempBuffer,sizeof(CVarTempBuffer)-1,"%d",params[2]);
|
||||||
(*g_engfuncs.pfnCvar_DirectSet)(ptr, &CVarTempBuffer[0]);
|
CVAR_DIRECTSET(ptr, &CVarTempBuffer[0]);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL set_cvar_num(AMX *amx, cell *params) /* 2 param */
|
static cell AMX_NATIVE_CALL set_cvar_num(AMX *amx, cell *params) /* 2 param */
|
||||||
{
|
{
|
||||||
int ilen;
|
int length;
|
||||||
CVAR_SET_FLOAT(get_amxstring(amx, params[1], 0, ilen), (float)params[2]);
|
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||||
|
int value = params[2];
|
||||||
|
|
||||||
|
cvar_t* var = g_CvarManager.FindCvar(name);
|
||||||
|
|
||||||
|
if (var)
|
||||||
|
{
|
||||||
|
UTIL_Format(CVarTempBuffer, sizeof(CVarTempBuffer) - 1, "%d", value);
|
||||||
|
CVAR_DIRECTSET(var, &CVarTempBuffer[0]);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL set_cvar_string(AMX *amx, cell *params) /* 2 param */
|
static cell AMX_NATIVE_CALL set_cvar_string(AMX *amx, cell *params) /* 2 param */
|
||||||
{
|
{
|
||||||
int ilen;
|
int length;
|
||||||
char* sptemp = get_amxstring(amx, params[1], 0, ilen);
|
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||||
char* szValue = get_amxstring(amx, params[2], 1, ilen);
|
|
||||||
|
|
||||||
CVAR_SET_STRING(sptemp, szValue);
|
cvar_t* var = g_CvarManager.FindCvar(name);
|
||||||
|
|
||||||
|
if (var)
|
||||||
|
{
|
||||||
|
CVAR_DIRECTSET(var, get_amxstring(amx, params[2], 1, length));
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -2038,7 +2068,7 @@ static cell AMX_NATIVE_CALL set_pcvar_string(AMX *amx, cell *params) /* 2 param
|
|||||||
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
(*g_engfuncs.pfnCvar_DirectSet)(ptr, get_amxstring(amx,params[2],0,len));
|
CVAR_DIRECTSET(ptr, get_amxstring(amx,params[2],0,len));
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -2598,40 +2628,28 @@ static cell AMX_NATIVE_CALL task_exists(AMX *amx, cell *params) /* 1 param */
|
|||||||
static cell AMX_NATIVE_CALL cvar_exists(AMX *amx, cell *params) /* 1 param */
|
static cell AMX_NATIVE_CALL cvar_exists(AMX *amx, cell *params) /* 1 param */
|
||||||
{
|
{
|
||||||
int ilen;
|
int ilen;
|
||||||
return (CVAR_GET_POINTER(get_amxstring(amx, params[1], 0, ilen)) ? 1 : 0);
|
return (g_CvarManager.FindCvar(get_amxstring(amx, params[1], 0, ilen)) ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL register_cvar(AMX *amx, cell *params) /* 3 param */
|
static cell AMX_NATIVE_CALL register_cvar(AMX *amx, cell *params) /* 3 param */
|
||||||
{
|
{
|
||||||
int i;
|
int length;
|
||||||
char* temp = get_amxstring(amx, params[1], 0, i);
|
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||||
|
const char* value = get_amxstring(amx, params[2], 1, length);
|
||||||
|
|
||||||
|
int flags = params[3];
|
||||||
|
float fvalue = amx_ctof(params[4]);
|
||||||
|
|
||||||
CPluginMngr::CPlugin *plugin = g_plugins.findPluginFast(amx);
|
CPluginMngr::CPlugin *plugin = g_plugins.findPluginFast(amx);
|
||||||
|
|
||||||
if (CheckBadConList(temp, 0))
|
if (CheckBadConList(name, 0))
|
||||||
{
|
{
|
||||||
plugin->AddToFailCounter(1);
|
plugin->AddToFailCounter(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_cvars.find(temp))
|
cvar_t* var = g_CvarManager.CreateCvar(name, value, fvalue, flags, plugin->getName(), plugin->getId());
|
||||||
{
|
|
||||||
CCVar* cvar = new CCVar(temp, plugin->getName(), params[3], amx_ctof(params[4]));
|
|
||||||
|
|
||||||
cvar->plugin_id = plugin->getId();
|
return reinterpret_cast<cell>(var);
|
||||||
|
|
||||||
g_cvars.put(cvar);
|
|
||||||
|
|
||||||
if (CVAR_GET_POINTER(temp) == 0)
|
|
||||||
{
|
|
||||||
static cvar_t cvar_reg_helper;
|
|
||||||
cvar_reg_helper = *(cvar->getCvar());
|
|
||||||
CVAR_REGISTER(&cvar_reg_helper);
|
|
||||||
}
|
|
||||||
|
|
||||||
CVAR_SET_STRING(temp, get_amxstring(amx, params[2], 1, i));
|
|
||||||
return reinterpret_cast<cell>(CVAR_GET_POINTER(temp));
|
|
||||||
}
|
|
||||||
|
|
||||||
return reinterpret_cast<cell>(CVAR_GET_POINTER(temp));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_user_ping(AMX *amx, cell *params) /* 3 param */
|
static cell AMX_NATIVE_CALL get_user_ping(AMX *amx, cell *params) /* 3 param */
|
||||||
@ -3022,30 +3040,17 @@ static cell AMX_NATIVE_CALL remove_quotes(AMX *amx, cell *params) /* 1 param */
|
|||||||
//native get_plugins_cvar(id, name[], namelen, &flags=0, &plugin_id=0, &pcvar_handle=0);
|
//native get_plugins_cvar(id, name[], namelen, &flags=0, &plugin_id=0, &pcvar_handle=0);
|
||||||
static cell AMX_NATIVE_CALL get_plugins_cvar(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL get_plugins_cvar(AMX *amx, cell *params)
|
||||||
{
|
{
|
||||||
int id = params[1];
|
CvarInfo* info = g_CvarManager.FindCvar(params[1]);
|
||||||
int iter_id = 0;
|
|
||||||
|
|
||||||
for (CList<CCVar>::iterator iter=g_cvars.begin(); iter; ++iter)
|
if (info)
|
||||||
{
|
{
|
||||||
if (id == iter_id)
|
set_amxstring(amx, params[2], info->name.chars(), params[3]);
|
||||||
{
|
*get_amxaddr(amx, params[4]) = info->var->flags;
|
||||||
CCVar *var = &(*iter);
|
*get_amxaddr(amx, params[5]) = info->pluginId;
|
||||||
set_amxstring(amx, params[2], var->getName(), params[3]);
|
*get_amxaddr(amx, params[6]) = reinterpret_cast<cell>(info->var);
|
||||||
cvar_t *ptr = CVAR_GET_POINTER(var->getName());
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
cell *addr = get_amxaddr(amx, params[4]);
|
|
||||||
*addr = ptr->flags;
|
|
||||||
addr = get_amxaddr(amx, params[5]);
|
|
||||||
*addr = var->plugin_id;
|
|
||||||
addr = get_amxaddr(amx, params[6]);
|
|
||||||
*addr = (cell)ptr;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
iter_id++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3053,7 +3058,7 @@ static cell AMX_NATIVE_CALL get_plugins_cvar(AMX *amx, cell *params)
|
|||||||
//native get_plugins_cvarsnum();
|
//native get_plugins_cvarsnum();
|
||||||
static cell AMX_NATIVE_CALL get_plugins_cvarsnum(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL get_plugins_cvarsnum(AMX *amx, cell *params)
|
||||||
{
|
{
|
||||||
return g_cvars.size();
|
return g_CvarManager.GetRegCvarsCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_user_aiming(AMX *amx, cell *params) /* 4 param */
|
static cell AMX_NATIVE_CALL get_user_aiming(AMX *amx, cell *params) /* 4 param */
|
||||||
@ -3107,7 +3112,7 @@ static cell AMX_NATIVE_CALL remove_cvar_flags(AMX *amx, cell *params)
|
|||||||
if (!strcmp(sCvar, "amx_version") || !strcmp(sCvar, "amxmodx_version") || !strcmp(sCvar, "fun_version") || !strcmp(sCvar, "sv_cheats"))
|
if (!strcmp(sCvar, "amx_version") || !strcmp(sCvar, "amxmodx_version") || !strcmp(sCvar, "fun_version") || !strcmp(sCvar, "sv_cheats"))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cvar_t* pCvar = CVAR_GET_POINTER(sCvar);
|
cvar_t* pCvar = g_CvarManager.FindCvar(sCvar);
|
||||||
|
|
||||||
if (pCvar)
|
if (pCvar)
|
||||||
{
|
{
|
||||||
@ -3135,7 +3140,7 @@ static cell AMX_NATIVE_CALL get_cvar_flags(AMX *amx, cell *params)
|
|||||||
int ilen;
|
int ilen;
|
||||||
char* sCvar = get_amxstring(amx, params[1], 0, ilen);
|
char* sCvar = get_amxstring(amx, params[1], 0, ilen);
|
||||||
|
|
||||||
cvar_t* pCvar = CVAR_GET_POINTER(sCvar);
|
cvar_t* pCvar = g_CvarManager.FindCvar(sCvar);
|
||||||
|
|
||||||
return pCvar ? pCvar->flags : 0;
|
return pCvar ? pCvar->flags : 0;
|
||||||
}
|
}
|
||||||
@ -3162,7 +3167,7 @@ static cell AMX_NATIVE_CALL set_cvar_flags(AMX *amx, cell *params)
|
|||||||
if (!strcmp(sCvar, "amx_version") || !strcmp(sCvar, "amxmodx_version") || !strcmp(sCvar, "fun_version") || !strcmp(sCvar, "sv_cheats"))
|
if (!strcmp(sCvar, "amx_version") || !strcmp(sCvar, "amxmodx_version") || !strcmp(sCvar, "fun_version") || !strcmp(sCvar, "sv_cheats"))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cvar_t* pCvar = CVAR_GET_POINTER(sCvar);
|
cvar_t* pCvar = g_CvarManager.FindCvar(sCvar);
|
||||||
|
|
||||||
if (pCvar)
|
if (pCvar)
|
||||||
{
|
{
|
||||||
@ -4448,9 +4453,9 @@ static cell AMX_NATIVE_CALL DestroyForward(AMX *amx, cell *params)
|
|||||||
static cell AMX_NATIVE_CALL get_cvar_pointer(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL get_cvar_pointer(AMX *amx, cell *params)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
char *temp = get_amxstring(amx, params[1], 0, len);
|
char *name = get_amxstring(amx, params[1], 0, len);
|
||||||
|
|
||||||
cvar_t *ptr = CVAR_GET_POINTER(temp);
|
cvar_t *ptr = g_CvarManager.FindCvar(name);
|
||||||
|
|
||||||
return reinterpret_cast<cell>(ptr);
|
return reinterpret_cast<cell>(ptr);
|
||||||
}
|
}
|
||||||
|
@ -162,7 +162,6 @@ extern CTaskMngr g_tasksMngr;
|
|||||||
extern CPlayer g_players[33];
|
extern CPlayer g_players[33];
|
||||||
extern CPlayer* mPlayer;
|
extern CPlayer* mPlayer;
|
||||||
extern CmdMngr g_commands;
|
extern CmdMngr g_commands;
|
||||||
extern CList<CCVar> g_cvars;
|
|
||||||
extern CList<ForceObject> g_forcemodels;
|
extern CList<ForceObject> g_forcemodels;
|
||||||
extern CList<ForceObject> g_forcesounds;
|
extern CList<ForceObject> g_forcesounds;
|
||||||
extern CList<ForceObject> g_forcegeneric;
|
extern CList<ForceObject> g_forcegeneric;
|
||||||
|
@ -11,25 +11,52 @@
|
|||||||
#include "amxmodx.h"
|
#include "amxmodx.h"
|
||||||
#include <CDetour/detours.h>
|
#include <CDetour/detours.h>
|
||||||
|
|
||||||
CDetour *Cvar_DirectSetDetour;
|
CvarManager g_CvarManager;
|
||||||
|
|
||||||
DETOUR_DECL_STATIC2(Cvar_DirectSet, void, struct cvar_s*, var, const char*, value)
|
DETOUR_DECL_STATIC2(Cvar_DirectSet, void, struct cvar_s*, var, const char*, value)
|
||||||
{
|
{
|
||||||
if (var && value)
|
static bool calledFromCallback = false;
|
||||||
|
|
||||||
|
if (!calledFromCallback && var && value)
|
||||||
{
|
{
|
||||||
if (strcmp(var->string, value) != 0)
|
if (strcmp(var->string, value) != 0)
|
||||||
{
|
{
|
||||||
|
calledFromCallback = true;
|
||||||
|
|
||||||
if (executeForwards(FF_CvarChanged, reinterpret_cast<cell>(var), var->string, value, var->name) > 0)
|
if (executeForwards(FF_CvarChanged, reinterpret_cast<cell>(var), var->string, value, var->name) > 0)
|
||||||
{
|
{
|
||||||
return;
|
//return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
calledFromCallback = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DETOUR_STATIC_CALL(Cvar_DirectSet)(var, value);
|
DETOUR_STATIC_CALL(Cvar_DirectSet)(var, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateCvarHook(void)
|
CvarManager::CvarManager() : m_AmxmodxCvars(0), m_HookDetour(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CvarManager::~CvarManager()
|
||||||
|
{
|
||||||
|
CvarsList::iterator iter = m_Cvars.begin();
|
||||||
|
|
||||||
|
while (iter != m_Cvars.end())
|
||||||
|
{
|
||||||
|
CvarInfo* info = (*iter);
|
||||||
|
|
||||||
|
iter = m_Cvars.erase(iter);
|
||||||
|
|
||||||
|
delete info;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Cache.clear();
|
||||||
|
m_HookDetour->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CvarManager::CreateCvarHook(void)
|
||||||
{
|
{
|
||||||
// void PF_Cvar_DirectSet(struct cvar_s *var, const char *value) // = pfnCvar_DirectSet
|
// void PF_Cvar_DirectSet(struct cvar_s *var, const char *value) // = pfnCvar_DirectSet
|
||||||
// {
|
// {
|
||||||
@ -69,11 +96,160 @@ void CreateCvarHook(void)
|
|||||||
|
|
||||||
if (functionAddress)
|
if (functionAddress)
|
||||||
{
|
{
|
||||||
CDetour *Cvar_DirectSetDetour = DETOUR_CREATE_STATIC_FIXED(Cvar_DirectSet, (void *)functionAddress);
|
m_HookDetour = DETOUR_CREATE_STATIC_FIXED(Cvar_DirectSet, (void *)functionAddress);
|
||||||
|
|
||||||
if (Cvar_DirectSetDetour)
|
if (m_HookDetour)
|
||||||
{
|
{
|
||||||
Cvar_DirectSetDetour->EnableDetour();
|
m_HookDetour->EnableDetour();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cvar_t* CvarManager::CreateCvar(const char* name, const char* value, float fvalue, int flags, const char* plugin, int plugnId)
|
||||||
|
{
|
||||||
|
cvar_t* var = nullptr;
|
||||||
|
CvarInfo* info = nullptr;
|
||||||
|
|
||||||
|
// Is cvar already cached ?
|
||||||
|
if (!m_Cache.retrieve(name, &info))
|
||||||
|
{
|
||||||
|
// Not cached - Is cvar already exist?
|
||||||
|
var = CVAR_GET_POINTER(name);
|
||||||
|
|
||||||
|
// Whether it exists, we need to prepare a new entry.
|
||||||
|
info = new CvarInfo();
|
||||||
|
|
||||||
|
// Shared datas.
|
||||||
|
info->name = name;
|
||||||
|
info->plugin = plugin;
|
||||||
|
info->pluginId = plugnId;
|
||||||
|
|
||||||
|
if (var)
|
||||||
|
{
|
||||||
|
// Cvar already exists. Just copy.
|
||||||
|
// "string" will be set after. "value" and "next" are automatically set.
|
||||||
|
info->var = var;
|
||||||
|
info->defaultval = var->string;
|
||||||
|
info->amxmodx = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Registers a new cvar.
|
||||||
|
static cvar_t cvar_reg_helper;
|
||||||
|
|
||||||
|
// "string" will be set after. "value" and "next" are automatically set.
|
||||||
|
cvar_reg_helper.name = info->name.chars();
|
||||||
|
cvar_reg_helper.string = "";
|
||||||
|
cvar_reg_helper.flags = flags;
|
||||||
|
|
||||||
|
// Adds cvar to global list.
|
||||||
|
CVAR_REGISTER(&cvar_reg_helper);
|
||||||
|
|
||||||
|
// Registering can fail if name is already a registered command.
|
||||||
|
var = CVAR_GET_POINTER(name);
|
||||||
|
|
||||||
|
// If so, we can't go further.
|
||||||
|
if (!var)
|
||||||
|
{
|
||||||
|
delete info;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If ok, we got a valid pointer, we can copy.
|
||||||
|
info->var = var;
|
||||||
|
info->defaultval = value;
|
||||||
|
info->amxmodx = true;
|
||||||
|
|
||||||
|
// Keeps track count of cvars registered by AMXX.
|
||||||
|
++m_AmxmodxCvars;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a new entry in the caches.
|
||||||
|
m_Cvars.append(info);
|
||||||
|
m_Cache.insert(name, info);
|
||||||
|
|
||||||
|
// Make sure that whether an existing or new cvar is set to the given value.
|
||||||
|
CVAR_DIRECTSET(var, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return info->var;
|
||||||
|
}
|
||||||
|
|
||||||
|
cvar_t* CvarManager::FindCvar(const char* name)
|
||||||
|
{
|
||||||
|
cvar_t* var = nullptr;
|
||||||
|
CvarInfo* info = nullptr;
|
||||||
|
|
||||||
|
// Do we have already cvar in cache?
|
||||||
|
if (m_Cache.retrieve(name, &info))
|
||||||
|
{
|
||||||
|
return info->var;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cvar doesn't exist.
|
||||||
|
if (!(var = CVAR_GET_POINTER(name)))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new entry.
|
||||||
|
info = new CvarInfo();
|
||||||
|
info->var = var;
|
||||||
|
info->name = name;
|
||||||
|
info->plugin = "";
|
||||||
|
info->pluginId = -1;
|
||||||
|
info->amxmodx = false;
|
||||||
|
|
||||||
|
// Add entry in the caches.
|
||||||
|
m_Cvars.append(info);
|
||||||
|
m_Cache.insert(name, info);
|
||||||
|
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
CvarInfo* CvarManager::FindCvar(size_t index)
|
||||||
|
{
|
||||||
|
// Used by get_plugins_cvar native.
|
||||||
|
// For compatibility, only cvars registered by AMXX are concerned.
|
||||||
|
|
||||||
|
size_t iter_id = 0;
|
||||||
|
|
||||||
|
for (CvarsList::iterator iter = m_Cvars.begin(); iter != m_Cvars.end(); iter++)
|
||||||
|
{
|
||||||
|
if (iter->amxmodx && iter_id++ == index)
|
||||||
|
{
|
||||||
|
return *(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t CvarManager::GetRegCvarsCount()
|
||||||
|
{
|
||||||
|
return m_AmxmodxCvars;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CvarManager::OnConsoleCommand()
|
||||||
|
{
|
||||||
|
print_srvconsole("Registered cvars:\n");
|
||||||
|
print_srvconsole(" %-24.23s %-24.23s %-16.15s\n", "name", "value", "plugin");
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
ke::AString pluginName;
|
||||||
|
|
||||||
|
if (CMD_ARGC() > 2) // Searching for cvars registered to a plugin
|
||||||
|
{
|
||||||
|
pluginName = CMD_ARGV(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CvarsList::iterator iter = m_Cvars.begin(); iter != m_Cvars.end(); iter++)
|
||||||
|
{
|
||||||
|
CvarInfo* ci = (*iter);
|
||||||
|
|
||||||
|
if (ci->amxmodx && (!pluginName.length() || strncmp(ci->name.chars(), pluginName.chars(), pluginName.length()) == 0))
|
||||||
|
{
|
||||||
|
print_srvconsole(" [%3d] %-24.23s %-24.23s %-16.15s\n", ++index, ci->name.chars(), ci->var->string, ci->plugin.chars());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,50 +11,53 @@
|
|||||||
#define CVARS_H
|
#define CVARS_H
|
||||||
|
|
||||||
#include "cvardef.h"
|
#include "cvardef.h"
|
||||||
#include <am-string.h>
|
#include <am-inlinelist.h>
|
||||||
|
#include <sm_namehashset.h>
|
||||||
|
|
||||||
class CDetour;
|
class CDetour;
|
||||||
|
|
||||||
class CCVar
|
struct CvarInfo : public ke::InlineListNode<CvarInfo>
|
||||||
{
|
{
|
||||||
cvar_t cvar;
|
cvar_t* var;
|
||||||
ke::AString name;
|
ke::AString name;
|
||||||
|
ke::AString defaultval;
|
||||||
ke::AString plugin;
|
ke::AString plugin;
|
||||||
|
int pluginId;
|
||||||
|
bool amxmodx;
|
||||||
|
|
||||||
public:
|
static inline bool matches(const char *name, const CvarInfo* info)
|
||||||
CCVar(const char* pname, const char* pplugin, int pflags, float pvalue) : name(pname), plugin(pplugin)
|
|
||||||
{
|
{
|
||||||
cvar.name = name.chars();
|
return strcmp(name, info->var->name) == 0;
|
||||||
cvar.flags = pflags;
|
|
||||||
cvar.string = "";
|
|
||||||
cvar.value = pvalue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline cvar_t* getCvar()
|
|
||||||
{
|
|
||||||
return &cvar;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char* getPluginName()
|
|
||||||
{
|
|
||||||
return plugin.chars();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char* getName()
|
|
||||||
{
|
|
||||||
return name.chars();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator == (const char* string)
|
|
||||||
{
|
|
||||||
return name.compare(string) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int plugin_id;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void CreateCvarHook(void);
|
typedef NameHashSet<CvarInfo*> CvarsCache;
|
||||||
|
typedef ke::InlineList<CvarInfo> CvarsList;
|
||||||
|
|
||||||
extern CDetour *Cvar_DirectSetDetour;
|
class CvarManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
CvarManager();
|
||||||
|
~CvarManager();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void CreateCvarHook();
|
||||||
|
cvar_t* CreateCvar(const char* name, const char* value, float fvalue, int flags, const char* plugin, int plugnId);
|
||||||
|
cvar_t* FindCvar(const char* name);
|
||||||
|
CvarInfo* FindCvar(size_t index);
|
||||||
|
size_t GetRegCvarsCount();
|
||||||
|
void OnConsoleCommand();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
CvarsCache m_Cache;
|
||||||
|
CvarsList m_Cvars;
|
||||||
|
size_t m_AmxmodxCvars;
|
||||||
|
CDetour* m_HookDetour;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern CvarManager g_CvarManager;
|
||||||
|
|
||||||
#endif // CVARS_H
|
#endif // CVARS_H
|
||||||
|
@ -64,7 +64,6 @@ extern CVector<CAdminData *> DynamicAdmins;
|
|||||||
CLog g_log;
|
CLog g_log;
|
||||||
CForwardMngr g_forwards;
|
CForwardMngr g_forwards;
|
||||||
CList<CPlayer*> g_auth;
|
CList<CPlayer*> g_auth;
|
||||||
CList<CCVar> g_cvars;
|
|
||||||
CList<ForceObject> g_forcemodels;
|
CList<ForceObject> g_forcemodels;
|
||||||
CList<ForceObject> g_forcesounds;
|
CList<ForceObject> g_forcesounds;
|
||||||
CList<ForceObject> g_forcegeneric;
|
CList<ForceObject> g_forcegeneric;
|
||||||
@ -122,7 +121,7 @@ cvar_t init_amxmodx_modules = {"amxmodx_modules", "", FCVAR_SPONLY};
|
|||||||
cvar_t init_amxmodx_debug = {"amx_debug", "1", FCVAR_SPONLY};
|
cvar_t init_amxmodx_debug = {"amx_debug", "1", FCVAR_SPONLY};
|
||||||
cvar_t init_amxmodx_mldebug = {"amx_mldebug", "", FCVAR_SPONLY};
|
cvar_t init_amxmodx_mldebug = {"amx_mldebug", "", FCVAR_SPONLY};
|
||||||
cvar_t init_amxmodx_language = {"amx_language", "en", FCVAR_SERVER};
|
cvar_t init_amxmodx_language = {"amx_language", "en", FCVAR_SERVER};
|
||||||
cvar_t init_amxmodx_cl_langs = {"amx_client_languages", "", FCVAR_SERVER};
|
cvar_t init_amxmodx_cl_langs = {"amx_client_languages", "1", FCVAR_SERVER};
|
||||||
cvar_t* amxmodx_version = NULL;
|
cvar_t* amxmodx_version = NULL;
|
||||||
cvar_t* amxmodx_modules = NULL;
|
cvar_t* amxmodx_modules = NULL;
|
||||||
cvar_t* amxmodx_language = NULL;
|
cvar_t* amxmodx_language = NULL;
|
||||||
@ -1492,7 +1491,7 @@ C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, m
|
|||||||
|
|
||||||
FlagMan.SetFile("cmdaccess.ini");
|
FlagMan.SetFile("cmdaccess.ini");
|
||||||
|
|
||||||
CreateCvarHook();
|
g_CvarManager.CreateCvarHook();
|
||||||
|
|
||||||
return (TRUE);
|
return (TRUE);
|
||||||
}
|
}
|
||||||
@ -1522,7 +1521,6 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
|
|||||||
g_vault.clear();
|
g_vault.clear();
|
||||||
g_xvars.clear();
|
g_xvars.clear();
|
||||||
g_plugins.clear();
|
g_plugins.clear();
|
||||||
g_cvars.clear();
|
|
||||||
g_langMngr.Clear();
|
g_langMngr.Clear();
|
||||||
|
|
||||||
ClearMessages();
|
ClearMessages();
|
||||||
|
@ -111,32 +111,7 @@ void amx_command()
|
|||||||
}
|
}
|
||||||
else if (!strcmp(cmd, "cvars"))
|
else if (!strcmp(cmd, "cvars"))
|
||||||
{
|
{
|
||||||
print_srvconsole("Registered cvars:\n");
|
g_CvarManager.OnConsoleCommand();
|
||||||
print_srvconsole(" %-24.23s %-24.23s %-16.15s\n", "name", "value", "plugin");
|
|
||||||
|
|
||||||
int ammount = 0;
|
|
||||||
|
|
||||||
if (CMD_ARGC() > 2) // Searching for cvars registered to a plugin
|
|
||||||
{
|
|
||||||
const char* targetname = CMD_ARGV(2);
|
|
||||||
size_t len = strlen(targetname);
|
|
||||||
for (CList<CCVar>::iterator a = g_cvars.begin(); a; ++a)
|
|
||||||
{
|
|
||||||
if (strncmp((*a).getPluginName(), targetname, len) == 0)
|
|
||||||
{
|
|
||||||
print_srvconsole(" [%3d] %-24.23s %-24.23s %-16.15s\n", ++ammount, (*a).getName(), CVAR_GET_STRING((*a).getName()), (*a).getPluginName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // No search
|
|
||||||
{
|
|
||||||
for (CList<CCVar>::iterator a = g_cvars.begin(); a; ++a)
|
|
||||||
{
|
|
||||||
print_srvconsole(" [%3d] %-24.23s %-24.23s %-16.15s\n", ++ammount, (*a).getName(), CVAR_GET_STRING((*a).getName()), (*a).getPluginName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print_srvconsole("%d cvars\n", ammount);
|
|
||||||
}
|
}
|
||||||
else if (!strcmp(cmd, "cmds"))
|
else if (!strcmp(cmd, "cmds"))
|
||||||
{
|
{
|
||||||
|
@ -29,8 +29,8 @@ public plugin_init()
|
|||||||
register_dictionary("common.txt")
|
register_dictionary("common.txt")
|
||||||
register_dictionary("languages.txt")
|
register_dictionary("languages.txt")
|
||||||
|
|
||||||
g_cvarClientLanguages = register_cvar("amx_client_languages", "1")
|
|
||||||
g_cvarDisplayClientMessage = register_cvar("amx_language_display_msg", "1")
|
g_cvarDisplayClientMessage = register_cvar("amx_language_display_msg", "1")
|
||||||
|
g_cvarClientLanguages = get_cvar_pointer("amx_client_languages")
|
||||||
g_cvarServerLanguage = get_cvar_pointer("amx_language");
|
g_cvarServerLanguage = get_cvar_pointer("amx_language");
|
||||||
|
|
||||||
register_clcmd("amx_langmenu", "cmdLangMenu", ADMIN_ALL)
|
register_clcmd("amx_langmenu", "cmdLangMenu", ADMIN_ALL)
|
||||||
|
201
public/sm_namehashset.h
Normal file
201
public/sm_namehashset.h
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 sw=4 tw=99 noet :
|
||||||
|
* =============================================================================
|
||||||
|
* SourceMod
|
||||||
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||||
|
* =============================================================================
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
* this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
* or <http://www.sourcemod.net/license.php>.
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _include_sourcemod_namehashset_h_
|
||||||
|
#define _include_sourcemod_namehashset_h_
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file sm_namehashset.h
|
||||||
|
*
|
||||||
|
* @brief Stores a set of uniquely named objects.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <am-allocator-policies.h>
|
||||||
|
#include <am-hashmap.h>
|
||||||
|
#include <am-string.h>
|
||||||
|
#include <sm_stringhashmap.h>
|
||||||
|
|
||||||
|
//namespace SourceMod
|
||||||
|
//{
|
||||||
|
|
||||||
|
// The HashPolicy type must have this method:
|
||||||
|
// static bool matches(const char *key, const T &value);
|
||||||
|
//
|
||||||
|
// Depending on what lookup types are used.
|
||||||
|
//
|
||||||
|
// If these members are available on T, then the HashPolicy type can be left
|
||||||
|
// default. It is okay to use |T *|, the functions will still be looked up
|
||||||
|
// on |T|.
|
||||||
|
template <typename T, typename KeyPolicy = T>
|
||||||
|
class NameHashSet : public ke::SystemAllocatorPolicy
|
||||||
|
{
|
||||||
|
typedef detail::CharsAndLength CharsAndLength;
|
||||||
|
|
||||||
|
// Default policy type: the two types are different. Use them directly.
|
||||||
|
template <typename KeyType, typename KeyPolicyType>
|
||||||
|
struct Policy
|
||||||
|
{
|
||||||
|
typedef KeyType Payload;
|
||||||
|
|
||||||
|
static uint32_t hash(const CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool matches(const CharsAndLength &key, const KeyType &value)
|
||||||
|
{
|
||||||
|
return KeyPolicyType::matches(key.chars(), value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Specialization: the types are equal, and T is a pointer. Strip the
|
||||||
|
// pointer off so we can access T:: for match functions.
|
||||||
|
template <typename KeyType>
|
||||||
|
struct Policy<KeyType *, KeyType *>
|
||||||
|
{
|
||||||
|
typedef KeyType *Payload;
|
||||||
|
|
||||||
|
static uint32_t hash(const detail::CharsAndLength &key)
|
||||||
|
{
|
||||||
|
return key.hash();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool matches(const CharsAndLength &key, const KeyType *value)
|
||||||
|
{
|
||||||
|
return KeyType::matches(key.chars(), value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef ke::HashTable<Policy<T, KeyPolicy>, ke::SystemAllocatorPolicy> Internal;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NameHashSet()
|
||||||
|
{
|
||||||
|
if (!table_.init())
|
||||||
|
this->reportOutOfMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef typename Internal::Result Result;
|
||||||
|
typedef typename Internal::Insert Insert;
|
||||||
|
typedef typename Internal::iterator iterator;
|
||||||
|
|
||||||
|
Result find(const char *aKey)
|
||||||
|
{
|
||||||
|
return table_.find(aKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
Insert findForAdd(const char *aKey)
|
||||||
|
{
|
||||||
|
return table_.findForAdd(aKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(Insert &i, const T &value)
|
||||||
|
{
|
||||||
|
return table_.add(i, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(Insert &i, T &&value)
|
||||||
|
{
|
||||||
|
return table_.add(i, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool retrieve(const char *aKey, T *value)
|
||||||
|
{
|
||||||
|
CharsAndLength key(aKey);
|
||||||
|
Result r = table_.find(aKey);
|
||||||
|
if (!r.found())
|
||||||
|
return false;
|
||||||
|
*value = *r;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool insert(const char *aKey, const T &value)
|
||||||
|
{
|
||||||
|
CharsAndLength key(aKey);
|
||||||
|
Insert i = table_.findForAdd(key);
|
||||||
|
if (i.found())
|
||||||
|
return false;
|
||||||
|
return table_.add(i, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool insert(const char *aKey, T &&value)
|
||||||
|
{
|
||||||
|
CharsAndLength key(aKey);
|
||||||
|
Insert i = table_.findForAdd(key);
|
||||||
|
if (i.found())
|
||||||
|
return false;
|
||||||
|
return table_.add(i, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(const char *aKey)
|
||||||
|
{
|
||||||
|
CharsAndLength key(aKey);
|
||||||
|
Result r = table_.find(aKey);
|
||||||
|
return r.found();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool remove(const char *aKey)
|
||||||
|
{
|
||||||
|
CharsAndLength key(aKey);
|
||||||
|
Result r = table_.find(key);
|
||||||
|
if (!r.found())
|
||||||
|
return false;
|
||||||
|
table_.remove(r);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(Result &r)
|
||||||
|
{
|
||||||
|
table_.remove(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
table_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t mem_usage() const
|
||||||
|
{
|
||||||
|
return table_.estimateMemoryUse();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator iter()
|
||||||
|
{
|
||||||
|
return iterator(&table_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Internal table_;
|
||||||
|
};
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
#endif // _include_sourcemod_namehashset_h_
|
Loading…
Reference in New Issue
Block a user