Cvars: Adjust more things
- Moved some functions in CvarManager - Fixed detour enabled all the time - Fixed bounds not properly handled - Refreshed data of regisetered cvars at map change
This commit is contained in:
parent
187b187ef2
commit
f8baef15ca
@ -154,7 +154,7 @@ void CvarManager::CreateCvarHook(void)
|
||||
}
|
||||
}
|
||||
|
||||
cvar_t* CvarManager::CreateCvar(const char* name, const char* value, const char* plugin, int pluginId, int flags,
|
||||
CvarInfo* CvarManager::CreateCvar(const char* name, const char* value, const char* plugin, int pluginId, int flags,
|
||||
const char* helpText, bool hasMin, float min, bool hasMax, float max)
|
||||
{
|
||||
cvar_t* var = nullptr;
|
||||
@ -215,11 +215,27 @@ cvar_t* CvarManager::CreateCvar(const char* name, const char* value, const char*
|
||||
// Make sure that whether an existing or new cvar is set to the given value.
|
||||
CVAR_DIRECTSET(var, value);
|
||||
}
|
||||
else if (info->pluginId == -1)
|
||||
{
|
||||
// In situation where a plugin has been modified/recompiled
|
||||
// or new added plugins, and a change map occurs. We want to keep data up to date.
|
||||
info->bound.hasMin = hasMin;
|
||||
info->bound.minVal = min;
|
||||
info->bound.hasMax = hasMax;
|
||||
info->bound.maxVal = max;
|
||||
info->defaultval = value;
|
||||
info->description = helpText;
|
||||
info->pluginId = pluginId;
|
||||
}
|
||||
|
||||
// Detour is disabled on map change.
|
||||
m_HookDetour->EnableDetour();
|
||||
// Don't enable it unless there are things to do.
|
||||
if (info->bound.hasMin || info->bound.hasMax)
|
||||
{
|
||||
m_HookDetour->EnableDetour();
|
||||
}
|
||||
|
||||
return info->var;
|
||||
return info;
|
||||
}
|
||||
|
||||
CvarInfo* CvarManager::FindCvar(const char* name)
|
||||
@ -227,9 +243,6 @@ CvarInfo* CvarManager::FindCvar(const char* name)
|
||||
cvar_t* var = nullptr;
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
// Detour is disabled on map change.
|
||||
m_HookDetour->EnableDetour();
|
||||
|
||||
// Do we have already cvar in cache?
|
||||
if (CacheLookup(name, &info))
|
||||
{
|
||||
@ -316,6 +329,104 @@ AutoForward* CvarManager::HookCvarChange(cvar_t* var, AMX* amx, cell param, cons
|
||||
return forward;
|
||||
}
|
||||
|
||||
bool CvarManager::BindCvar(CvarInfo* info, CvarBind::CvarType type, AMX* amx, cell varofs, size_t varlen)
|
||||
{
|
||||
if (varofs > amx->hlw) // If variable address is not inside global area, we can't bind it.
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "A global variable must be provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
int pluginId = g_plugins.findPluginFast(amx)->getId();
|
||||
cell* address = get_amxaddr(amx, varofs);
|
||||
|
||||
// To avoid unexpected behavior, probably better to error such situations.
|
||||
for (size_t i = 0; i < info->binds.length(); ++i)
|
||||
{
|
||||
CvarBind* bind = info->binds[i];
|
||||
|
||||
if (bind->pluginId == pluginId)
|
||||
{
|
||||
if (bind->varAddress == address)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "A same variable can't be binded with several cvars");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CvarBind* bind = new CvarBind(pluginId, type, get_amxaddr(amx, varofs), varlen);
|
||||
|
||||
info->binds.append(bind);
|
||||
|
||||
// Update right away variable with current cvar value.
|
||||
switch (type)
|
||||
{
|
||||
case CvarBind::CvarType_Int:
|
||||
*bind->varAddress = atoi(info->var->string);
|
||||
break;
|
||||
case CvarBind::CvarType_Float:
|
||||
*bind->varAddress = amx_ftoc(info->var->value);
|
||||
break;
|
||||
case CvarBind::CvarType_String:
|
||||
set_amxstring_simple(bind->varAddress, info->var->string, bind->varLength);
|
||||
break;
|
||||
}
|
||||
|
||||
// Detour is disabled on map change.
|
||||
m_HookDetour->EnableDetour();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CvarManager::SetCvarMin(CvarInfo* info, bool set, float value, int pluginId)
|
||||
{
|
||||
info->bound.hasMin = set;
|
||||
info->bound.minPluginId = pluginId;
|
||||
|
||||
if (set)
|
||||
{
|
||||
if (info->bound.hasMax && value > info->bound.maxVal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
info->bound.minVal = value;
|
||||
|
||||
// Detour is disabled on map change.
|
||||
m_HookDetour->EnableDetour();
|
||||
|
||||
// Update if needed.
|
||||
CVAR_SET_FLOAT(info->var->name, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CvarManager::SetCvarMax(CvarInfo* info, bool set, float value, int pluginId)
|
||||
{
|
||||
info->bound.hasMax = set;
|
||||
info->bound.maxPluginId = pluginId;
|
||||
|
||||
if (set)
|
||||
{
|
||||
if (info->bound.hasMin && value < info->bound.minVal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
info->bound.maxVal = value;
|
||||
|
||||
// Detour is disabled on map change.
|
||||
m_HookDetour->EnableDetour();
|
||||
|
||||
// Update if needed.
|
||||
CVAR_SET_FLOAT(info->var->name, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t CvarManager::GetRegCvarsCount()
|
||||
{
|
||||
return m_AmxmodxCvars;
|
||||
@ -475,6 +586,11 @@ void CvarManager::OnPluginUnloaded()
|
||||
delete (*cvar)->hooks[i];
|
||||
}
|
||||
|
||||
if ((*cvar)->amxmodx) // Mark registered cvars so we can refresh default datas at next map.
|
||||
{
|
||||
(*cvar)->pluginId = -1;
|
||||
}
|
||||
|
||||
(*cvar)->binds.clear();
|
||||
(*cvar)->hooks.clear();
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ class CvarManager
|
||||
|
||||
void CreateCvarHook();
|
||||
|
||||
cvar_t* CreateCvar(const char* name, const char* value, const char* plugin, int pluginId,
|
||||
CvarInfo* CreateCvar(const char* name, const char* value, const char* plugin, int pluginId,
|
||||
int flags = 0, const char* helpText = "",
|
||||
bool hasMin = false, float min = 0,
|
||||
bool hasMax = false, float max = 0);
|
||||
@ -160,6 +160,9 @@ class CvarManager
|
||||
bool CacheLookup(const char* name, CvarInfo** info);
|
||||
|
||||
AutoForward* HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback);
|
||||
bool BindCvar(CvarInfo* info, CvarBind::CvarType type, AMX* amx, cell varofs, size_t varlen = 0);
|
||||
bool SetCvarMin(CvarInfo* info, bool set, float value, int pluginId);
|
||||
bool SetCvarMax(CvarInfo* info, bool set, float value, int pluginId);
|
||||
|
||||
size_t GetRegCvarsCount();
|
||||
|
||||
|
@ -22,34 +22,8 @@ static cell AMX_NATIVE_CALL create_cvar(AMX *amx, cell *params)
|
||||
const char* value = get_amxstring(amx, params[2], 1, length);
|
||||
const char* helpText = get_amxstring(amx, params[4], 2, length);
|
||||
|
||||
int flags = params[3];
|
||||
bool hasMin = params[5] != 0;
|
||||
bool hasMax = params[7] != 0;
|
||||
float minVal = 0;
|
||||
float maxVal = 0;
|
||||
|
||||
if (hasMin)
|
||||
{
|
||||
minVal = amx_ctof(params[6]);
|
||||
|
||||
if (hasMax && minVal > maxVal)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "A lower bound can't be above an upper bound");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
int flags = params[3];
|
||||
|
||||
if (hasMax)
|
||||
{
|
||||
maxVal = amx_ctof(params[8]);
|
||||
|
||||
if (hasMin && maxVal < minVal)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "An upper bound can't be below a lower bound");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
CPluginMngr::CPlugin *plugin = g_plugins.findPluginFast(amx);
|
||||
|
||||
if (CheckBadConList(name, 0))
|
||||
@ -57,9 +31,31 @@ static cell AMX_NATIVE_CALL create_cvar(AMX *amx, cell *params)
|
||||
plugin->AddToFailCounter(1);
|
||||
}
|
||||
|
||||
cvar_t* var = g_CvarManager.CreateCvar(name, value, plugin->getName(), plugin->getId(), flags, helpText, hasMin, minVal, hasMax, maxVal);
|
||||
CvarInfo* info = g_CvarManager.CreateCvar(name, value, plugin->getName(), plugin->getId(), flags, helpText);
|
||||
|
||||
return reinterpret_cast<cell>(var);
|
||||
if (info)
|
||||
{
|
||||
bool hasMin = params[5] != 0;
|
||||
bool hasMax = params[7] != 0;
|
||||
float minVal = amx_ctof(params[6]);
|
||||
float maxVal = amx_ctof(params[8]);
|
||||
|
||||
if (!g_CvarManager.SetCvarMin(info, hasMin, minVal, plugin->getId()))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "A lower bound can't be above an upper bound");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!g_CvarManager.SetCvarMax(info, hasMax, maxVal, plugin->getId()))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "An upper bound can't be below a lower bound");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reinterpret_cast<cell>(info->var);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// register_cvar(const name[], const string[], flags=0, Float:fvalue=0.0)
|
||||
@ -79,9 +75,14 @@ static cell AMX_NATIVE_CALL register_cvar(AMX *amx, cell *params)
|
||||
plugin->AddToFailCounter(1);
|
||||
}
|
||||
|
||||
cvar_t* var = g_CvarManager.CreateCvar(name, value, plugin->getName(), plugin->getId(), flags);
|
||||
CvarInfo* info = g_CvarManager.CreateCvar(name, value, plugin->getName(), plugin->getId(), flags);
|
||||
|
||||
return reinterpret_cast<cell>(var);
|
||||
if (info)
|
||||
{
|
||||
return reinterpret_cast<cell>(info->var);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// cvar_exists(const cvar[])
|
||||
@ -368,53 +369,6 @@ static cell AMX_NATIVE_CALL get_pcvar_bounds(AMX *amx, cell *params)
|
||||
return hasBound;
|
||||
}
|
||||
|
||||
bool bind_pcvar(CvarInfo* info, CvarBind::CvarType type, AMX* amx, cell varofs, size_t varlen = 0)
|
||||
{
|
||||
if (varofs > amx->hlw) // If variable address is not inside global area, we can't bind it.
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "A global variable must be provided");
|
||||
return false;
|
||||
}
|
||||
|
||||
int pluginId = g_plugins.findPluginFast(amx)->getId();
|
||||
cell* address = get_amxaddr(amx, varofs);
|
||||
|
||||
// To avoid unexpected behavior, probably better to error such situations.
|
||||
for (size_t i = 0; i < info->binds.length(); ++i)
|
||||
{
|
||||
CvarBind* bind = info->binds[i];
|
||||
|
||||
if (bind->pluginId == pluginId)
|
||||
{
|
||||
if (bind->varAddress == address)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "A same variable can't be binded with several cvars");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CvarBind* bind = new CvarBind(pluginId, type, get_amxaddr(amx, varofs), varlen);
|
||||
|
||||
info->binds.append(bind);
|
||||
|
||||
// Update right away variable with current cvar value.
|
||||
switch (type)
|
||||
{
|
||||
case CvarBind::CvarType_Int:
|
||||
*bind->varAddress = atoi(info->var->string);
|
||||
break;
|
||||
case CvarBind::CvarType_Float:
|
||||
*bind->varAddress = amx_ftoc(info->var->value);
|
||||
break;
|
||||
case CvarBind::CvarType_String:
|
||||
set_amxstring_simple(bind->varAddress, info->var->string, bind->varLength);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// bind_pcvar_float(pcvar, &Float:var)
|
||||
static cell AMX_NATIVE_CALL bind_pcvar_float(AMX *amx, cell *params)
|
||||
{
|
||||
@ -427,7 +381,7 @@ static cell AMX_NATIVE_CALL bind_pcvar_float(AMX *amx, cell *params)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return bind_pcvar(info, CvarBind::CvarType_Float, amx, params[2]);
|
||||
return g_CvarManager.BindCvar(info, CvarBind::CvarType_Float, amx, params[2]);
|
||||
}
|
||||
|
||||
// bind_pcvar_num(pcvar, &any:var)
|
||||
@ -442,7 +396,7 @@ static cell AMX_NATIVE_CALL bind_pcvar_num(AMX *amx, cell *params)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return bind_pcvar(info, CvarBind::CvarType_Int, amx, params[2]);
|
||||
return g_CvarManager.BindCvar(info, CvarBind::CvarType_Int, amx, params[2]);
|
||||
}
|
||||
|
||||
// bind_pcvar_string(pcvar, any:var[], varlen)
|
||||
@ -457,7 +411,7 @@ static cell AMX_NATIVE_CALL bind_pcvar_string(AMX *amx, cell *params)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return bind_pcvar(info, CvarBind::CvarType_String, amx, params[2], params[3]);
|
||||
return g_CvarManager.BindCvar(info, CvarBind::CvarType_String, amx, params[2], params[3]);
|
||||
}
|
||||
|
||||
// set_pcvar_flags(pcvar, flags)
|
||||
@ -538,53 +492,26 @@ static cell AMX_NATIVE_CALL set_pcvar_bounds(AMX *amx, cell *params)
|
||||
|
||||
bool set = params[3] != 0;
|
||||
int pluginId = g_plugins.findPluginFast(amx)->getId();
|
||||
float value = 0;
|
||||
bool should_update = false;
|
||||
float value = amx_ctof(params[4]);
|
||||
|
||||
switch (params[2])
|
||||
{
|
||||
case CvarBound_Lower:
|
||||
{
|
||||
info->bound.hasMin = set;
|
||||
|
||||
if (set)
|
||||
if (!g_CvarManager.SetCvarMin(info, set, value, pluginId))
|
||||
{
|
||||
value = amx_ctof(params[4]);
|
||||
|
||||
if (info->bound.hasMax && value > info->bound.maxVal)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "A lower bound can't be above an upper bound");
|
||||
return 0;
|
||||
}
|
||||
|
||||
should_update = true;
|
||||
|
||||
info->bound.minVal = value;
|
||||
info->bound.minPluginId = pluginId;
|
||||
LogError(amx, AMX_ERR_NATIVE, "A lower bound can't be above an upper bound");
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case CvarBound_Upper:
|
||||
{
|
||||
info->bound.hasMax = set;
|
||||
|
||||
if (set)
|
||||
if (!g_CvarManager.SetCvarMax(info, set, value, pluginId))
|
||||
{
|
||||
value = amx_ctof(params[4]);
|
||||
|
||||
if (info->bound.hasMin && value < info->bound.minVal)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "An upper bound can't be below a lower bound");
|
||||
return 0;
|
||||
}
|
||||
|
||||
should_update = true;
|
||||
|
||||
info->bound.maxVal = value;
|
||||
info->bound.maxPluginId = pluginId;
|
||||
LogError(amx, AMX_ERR_NATIVE, "An upper bound can't be below a lower bound");
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -594,11 +521,6 @@ static cell AMX_NATIVE_CALL set_pcvar_bounds(AMX *amx, cell *params)
|
||||
}
|
||||
}
|
||||
|
||||
if (should_update)
|
||||
{
|
||||
CVAR_SET_FLOAT(ptr->name, value);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user