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 */
|
||||
{
|
||||
int ilen;
|
||||
char* sptemp = get_amxstring(amx, params[1], 0, ilen);
|
||||
int length;
|
||||
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||
|
||||
const char *value = CVAR_GET_STRING(sptemp);
|
||||
return set_amxstring_utf8(amx, params[2], value, strlen(value), params[3] + 1); // + EOS
|
||||
cvar_t* var = g_CvarManager.FindCvar(name);
|
||||
|
||||
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)
|
||||
@ -1939,18 +1943,17 @@ static cell AMX_NATIVE_CALL get_pcvar_float(AMX *amx, cell *params)
|
||||
return 0;
|
||||
}
|
||||
|
||||
REAL val = (REAL)ptr->value;
|
||||
|
||||
return amx_ftoc(val);
|
||||
return amx_ftoc(ptr->value);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
return amx_ftoc(pFloat);
|
||||
cvar_t* var = g_CvarManager.FindCvar(name);
|
||||
|
||||
return var ? amx_ftoc(var->value) : 0;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL set_pcvar_float(AMX *amx, cell *params)
|
||||
@ -1962,16 +1965,25 @@ static cell AMX_NATIVE_CALL set_pcvar_float(AMX *amx, cell *params)
|
||||
return 0;
|
||||
}
|
||||
|
||||
UTIL_Format(CVarTempBuffer,sizeof(CVarTempBuffer)-1,"%f",amx_ctof(params[2]));
|
||||
(*g_engfuncs.pfnCvar_DirectSet)(ptr, &CVarTempBuffer[0]);
|
||||
UTIL_Format(CVarTempBuffer, sizeof(CVarTempBuffer) - 1, "%f", amx_ctof(params[2]));
|
||||
CVAR_DIRECTSET(ptr, &CVarTempBuffer[0]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL set_cvar_float(AMX *amx, cell *params) /* 2 param */
|
||||
{
|
||||
int ilen;
|
||||
CVAR_SET_FLOAT(get_amxstring(amx, params[1], 0, ilen), amx_ctof(params[2]));
|
||||
|
||||
int length;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
{
|
||||
int ilen;
|
||||
return (int)CVAR_GET_FLOAT(get_amxstring(amx, params[1], 0, ilen));
|
||||
int length;
|
||||
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)
|
||||
@ -2003,27 +2020,40 @@ static cell AMX_NATIVE_CALL set_pcvar_num(AMX *amx, cell *params)
|
||||
}
|
||||
|
||||
UTIL_Format(CVarTempBuffer,sizeof(CVarTempBuffer)-1,"%d",params[2]);
|
||||
(*g_engfuncs.pfnCvar_DirectSet)(ptr, &CVarTempBuffer[0]);
|
||||
CVAR_DIRECTSET(ptr, &CVarTempBuffer[0]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL set_cvar_num(AMX *amx, cell *params) /* 2 param */
|
||||
{
|
||||
int ilen;
|
||||
CVAR_SET_FLOAT(get_amxstring(amx, params[1], 0, ilen), (float)params[2]);
|
||||
|
||||
int length;
|
||||
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;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL set_cvar_string(AMX *amx, cell *params) /* 2 param */
|
||||
{
|
||||
int ilen;
|
||||
char* sptemp = get_amxstring(amx, params[1], 0, ilen);
|
||||
char* szValue = get_amxstring(amx, params[2], 1, ilen);
|
||||
|
||||
CVAR_SET_STRING(sptemp, szValue);
|
||||
int length;
|
||||
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||
|
||||
cvar_t* var = g_CvarManager.FindCvar(name);
|
||||
|
||||
if (var)
|
||||
{
|
||||
CVAR_DIRECTSET(var, get_amxstring(amx, params[2], 1, length));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2038,7 +2068,7 @@ static cell AMX_NATIVE_CALL set_pcvar_string(AMX *amx, cell *params) /* 2 param
|
||||
|
||||
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;
|
||||
}
|
||||
@ -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 */
|
||||
{
|
||||
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 */
|
||||
{
|
||||
int i;
|
||||
char* temp = get_amxstring(amx, params[1], 0, i);
|
||||
int length;
|
||||
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);
|
||||
|
||||
if (CheckBadConList(temp, 0))
|
||||
if (CheckBadConList(name, 0))
|
||||
{
|
||||
plugin->AddToFailCounter(1);
|
||||
}
|
||||
|
||||
if (!g_cvars.find(temp))
|
||||
{
|
||||
CCVar* cvar = new CCVar(temp, plugin->getName(), params[3], amx_ctof(params[4]));
|
||||
cvar_t* var = g_CvarManager.CreateCvar(name, value, fvalue, flags, plugin->getName(), plugin->getId());
|
||||
|
||||
cvar->plugin_id = plugin->getId();
|
||||
|
||||
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));
|
||||
return reinterpret_cast<cell>(var);
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL get_user_ping(AMX *amx, cell *params) /* 3 param */
|
||||
@ -3022,29 +3040,16 @@ 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);
|
||||
static cell AMX_NATIVE_CALL get_plugins_cvar(AMX *amx, cell *params)
|
||||
{
|
||||
int id = params[1];
|
||||
int iter_id = 0;
|
||||
CvarInfo* info = g_CvarManager.FindCvar(params[1]);
|
||||
|
||||
for (CList<CCVar>::iterator iter=g_cvars.begin(); iter; ++iter)
|
||||
if (info)
|
||||
{
|
||||
if (id == iter_id)
|
||||
{
|
||||
CCVar *var = &(*iter);
|
||||
set_amxstring(amx, params[2], var->getName(), params[3]);
|
||||
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;
|
||||
}
|
||||
iter_id++;
|
||||
set_amxstring(amx, params[2], info->name.chars(), params[3]);
|
||||
*get_amxaddr(amx, params[4]) = info->var->flags;
|
||||
*get_amxaddr(amx, params[5]) = info->pluginId;
|
||||
*get_amxaddr(amx, params[6]) = reinterpret_cast<cell>(info->var);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -3053,7 +3058,7 @@ static cell AMX_NATIVE_CALL get_plugins_cvar(AMX *amx, cell *params)
|
||||
//native get_plugins_cvarsnum();
|
||||
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 */
|
||||
@ -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"))
|
||||
return 0;
|
||||
|
||||
cvar_t* pCvar = CVAR_GET_POINTER(sCvar);
|
||||
cvar_t* pCvar = g_CvarManager.FindCvar(sCvar);
|
||||
|
||||
if (pCvar)
|
||||
{
|
||||
@ -3135,7 +3140,7 @@ static cell AMX_NATIVE_CALL get_cvar_flags(AMX *amx, cell *params)
|
||||
int 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;
|
||||
}
|
||||
@ -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"))
|
||||
return 0;
|
||||
|
||||
cvar_t* pCvar = CVAR_GET_POINTER(sCvar);
|
||||
cvar_t* pCvar = g_CvarManager.FindCvar(sCvar);
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@ -162,7 +162,6 @@ extern CTaskMngr g_tasksMngr;
|
||||
extern CPlayer g_players[33];
|
||||
extern CPlayer* mPlayer;
|
||||
extern CmdMngr g_commands;
|
||||
extern CList<CCVar> g_cvars;
|
||||
extern CList<ForceObject> g_forcemodels;
|
||||
extern CList<ForceObject> g_forcesounds;
|
||||
extern CList<ForceObject> g_forcegeneric;
|
||||
|
@ -11,25 +11,52 @@
|
||||
#include "amxmodx.h"
|
||||
#include <CDetour/detours.h>
|
||||
|
||||
CDetour *Cvar_DirectSetDetour;
|
||||
CvarManager g_CvarManager;
|
||||
|
||||
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)
|
||||
{
|
||||
calledFromCallback = true;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
// {
|
||||
@ -69,11 +96,160 @@ void CreateCvarHook(void)
|
||||
|
||||
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
|
||||
|
||||
#include "cvardef.h"
|
||||
#include <am-string.h>
|
||||
#include <am-inlinelist.h>
|
||||
#include <sm_namehashset.h>
|
||||
|
||||
class CDetour;
|
||||
|
||||
class CCVar
|
||||
struct CvarInfo : public ke::InlineListNode<CvarInfo>
|
||||
{
|
||||
cvar_t cvar;
|
||||
ke::AString name;
|
||||
ke::AString plugin;
|
||||
cvar_t* var;
|
||||
ke::AString name;
|
||||
ke::AString defaultval;
|
||||
ke::AString plugin;
|
||||
int pluginId;
|
||||
bool amxmodx;
|
||||
|
||||
public:
|
||||
CCVar(const char* pname, const char* pplugin, int pflags, float pvalue) : name(pname), plugin(pplugin)
|
||||
static inline bool matches(const char *name, const CvarInfo* info)
|
||||
{
|
||||
cvar.name = name.chars();
|
||||
cvar.flags = pflags;
|
||||
cvar.string = "";
|
||||
cvar.value = pvalue;
|
||||
return strcmp(name, info->var->name) == 0;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -64,7 +64,6 @@ extern CVector<CAdminData *> DynamicAdmins;
|
||||
CLog g_log;
|
||||
CForwardMngr g_forwards;
|
||||
CList<CPlayer*> g_auth;
|
||||
CList<CCVar> g_cvars;
|
||||
CList<ForceObject> g_forcemodels;
|
||||
CList<ForceObject> g_forcesounds;
|
||||
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_mldebug = {"amx_mldebug", "", FCVAR_SPONLY};
|
||||
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_modules = 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");
|
||||
|
||||
CreateCvarHook();
|
||||
g_CvarManager.CreateCvarHook();
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
@ -1522,7 +1521,6 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
|
||||
g_vault.clear();
|
||||
g_xvars.clear();
|
||||
g_plugins.clear();
|
||||
g_cvars.clear();
|
||||
g_langMngr.Clear();
|
||||
|
||||
ClearMessages();
|
||||
|
@ -111,32 +111,7 @@ void amx_command()
|
||||
}
|
||||
else if (!strcmp(cmd, "cvars"))
|
||||
{
|
||||
print_srvconsole("Registered cvars:\n");
|
||||
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);
|
||||
g_CvarManager.OnConsoleCommand();
|
||||
}
|
||||
else if (!strcmp(cmd, "cmds"))
|
||||
{
|
||||
|
@ -28,9 +28,9 @@ public plugin_init()
|
||||
register_dictionary("multilingual.txt")
|
||||
register_dictionary("common.txt")
|
||||
register_dictionary("languages.txt")
|
||||
|
||||
g_cvarClientLanguages = register_cvar("amx_client_languages", "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");
|
||||
|
||||
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