Cvars: Moving cvars stuffs in its own files
cvars.cpp renamed to CvarManager.cpp all cvars natives moved to a new cvars.cpp file Pawn include is updated as wall.
This commit is contained in:
parent
768fa2c3bc
commit
15ad1d2247
|
@ -96,6 +96,7 @@ binary.sources = [
|
||||||
'stackstructs.cpp',
|
'stackstructs.cpp',
|
||||||
'CTextParsers.cpp',
|
'CTextParsers.cpp',
|
||||||
'textparse.cpp',
|
'textparse.cpp',
|
||||||
|
'CvarManager.cpp',
|
||||||
'cvars.cpp',
|
'cvars.cpp',
|
||||||
'../public/memtools/CDetour/detours.cpp',
|
'../public/memtools/CDetour/detours.cpp',
|
||||||
'../public/memtools/CDetour/asm/asm.c',
|
'../public/memtools/CDetour/asm/asm.c',
|
||||||
|
|
348
amxmodx/CvarManager.cpp
Normal file
348
amxmodx/CvarManager.cpp
Normal file
|
@ -0,0 +1,348 @@
|
||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
//
|
||||||
|
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||||
|
// Copyright (C) The AMX Mod X Development Team.
|
||||||
|
//
|
||||||
|
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||||
|
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||||
|
// https://alliedmods.net/amxmodx-license
|
||||||
|
|
||||||
|
#include "CvarManager.h"
|
||||||
|
#include "amxmodx.h"
|
||||||
|
#include <CDetour/detours.h>
|
||||||
|
|
||||||
|
CvarManager g_CvarManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true to call original function, otherwise false to block it.
|
||||||
|
*/
|
||||||
|
bool Cvar_DirectSet_Custom(cvar_t* var, const char* value)
|
||||||
|
{
|
||||||
|
CvarInfo* info = nullptr;
|
||||||
|
|
||||||
|
if (!var || !value // Sanity checks against bogus pointers.
|
||||||
|
|| strcmp(var->string, value) == 0 // Make sure old and new values are different to not trigger callbacks.
|
||||||
|
|| !g_CvarManager.CacheLookup(var->name, &info) // No data in cache, nothing to call.
|
||||||
|
|| info->hooks.empty()) // No hooked cvars, nothing to call.
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lastResult = 0;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < info->hooks.length(); ++i)
|
||||||
|
{
|
||||||
|
CvarPlugin* p = info->hooks[i];
|
||||||
|
|
||||||
|
if (p->forward->state == Forward::FSTATE_OK) // Our callback can be enable/disabled by natives.
|
||||||
|
{
|
||||||
|
result = executeForwards(p->forward->id, reinterpret_cast<cvar_t*>(var), var->string, value);
|
||||||
|
|
||||||
|
if (result >= lastResult)
|
||||||
|
{
|
||||||
|
lastResult = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!!lastResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
DETOUR_DECL_STATIC2(Cvar_DirectSet, void, struct cvar_s*, var, const char*, value)
|
||||||
|
{
|
||||||
|
if (Cvar_DirectSet_Custom(var, value))
|
||||||
|
{
|
||||||
|
DETOUR_STATIC_CALL(Cvar_DirectSet)(var, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CvarManager::CvarManager() : m_AmxmodxCvars(0), m_HookDetour(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CvarManager::~CvarManager()
|
||||||
|
{
|
||||||
|
OnAmxxShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CvarManager::CreateCvarHook(void)
|
||||||
|
{
|
||||||
|
// void PF_Cvar_DirectSet(struct cvar_s *var, const char *value) // = pfnCvar_DirectSet
|
||||||
|
// {
|
||||||
|
// Cvar_DirectSet(var, value); // <- We want to hook this.
|
||||||
|
// }
|
||||||
|
|
||||||
|
byte *baseAddress = (byte *)g_engfuncs.pfnCvar_DirectSet;
|
||||||
|
uintptr_t *functionAddress = nullptr;
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
// 55 push ebp
|
||||||
|
// 8B EC mov ebp, esp
|
||||||
|
// 8B 45 0C mov eax, [ebp+arg_4]
|
||||||
|
// 8B 4D 08 mov ecx, [ebp+arg_0]
|
||||||
|
// 50 push eax
|
||||||
|
// 51 push ecx
|
||||||
|
// E8 XX XX XX XX call Cvar_DirectSet
|
||||||
|
const byte opcodeJump = 0xE8;
|
||||||
|
#else
|
||||||
|
// E9 XX XX XX XX jmp Cvar_DirectSet
|
||||||
|
const byte opcodeJump = 0xE9;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const byte opcodeJumpSize = 5;
|
||||||
|
const byte opcodeJumpByteSize = 1;
|
||||||
|
|
||||||
|
const int maxBytesLimit = 20;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < maxBytesLimit; ++i, ++baseAddress)
|
||||||
|
{
|
||||||
|
if (*baseAddress == opcodeJump)
|
||||||
|
{
|
||||||
|
functionAddress = (uintptr_t *)(&baseAddress[opcodeJumpSize] + *(uintptr_t *)&baseAddress[opcodeJumpByteSize]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (functionAddress)
|
||||||
|
{
|
||||||
|
m_HookDetour = DETOUR_CREATE_STATIC_FIXED(Cvar_DirectSet, (void *)functionAddress);
|
||||||
|
|
||||||
|
if (m_HookDetour)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!CacheLookup(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 (CacheLookup(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CvarManager::CacheLookup(const char* name, CvarInfo** info)
|
||||||
|
{
|
||||||
|
return m_Cache.retrieve(name, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
Forward* CvarManager::HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback)
|
||||||
|
{
|
||||||
|
CvarInfo* info = nullptr;
|
||||||
|
|
||||||
|
// A cvar is guaranteed to be in cache if pointer is got from
|
||||||
|
// get_cvar_pointer and register_cvar natives. Though it might be
|
||||||
|
// provided by another way. If by any chance we run in such
|
||||||
|
// situation, we create a new entry right now.
|
||||||
|
|
||||||
|
if (!CacheLookup(var->name, &info))
|
||||||
|
{
|
||||||
|
// Create a new entry.
|
||||||
|
info = new CvarInfo();
|
||||||
|
info->var = var;
|
||||||
|
info->name = var->name;
|
||||||
|
info->plugin = "";
|
||||||
|
info->pluginId = -1;
|
||||||
|
info->amxmodx = false;
|
||||||
|
|
||||||
|
// Add entry in the caches.
|
||||||
|
m_Cvars.append(info);
|
||||||
|
m_Cache.insert(info->name.chars(), info);
|
||||||
|
}
|
||||||
|
|
||||||
|
int length;
|
||||||
|
*callback = get_amxstring(amx, param, 0, length);
|
||||||
|
|
||||||
|
int forwardId = registerSPForwardByName(amx, *callback, FP_CELL, FP_STRING, FP_STRING, FP_DONE);
|
||||||
|
|
||||||
|
// Invalid callback, it could be: not a public function, wrongly named, or simply missing.
|
||||||
|
if (forwardId == -1)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detour is disabled on map change.
|
||||||
|
m_HookDetour->EnableDetour();
|
||||||
|
|
||||||
|
Forward* forward = new Forward(forwardId, *callback);
|
||||||
|
info->hooks.append(new CvarPlugin(g_plugins.findPlugin(amx)->getId(), forward));
|
||||||
|
|
||||||
|
return forward;
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CvarManager::OnPluginUnloaded()
|
||||||
|
{
|
||||||
|
// Clear only plugin hooks list.
|
||||||
|
for (CvarsList::iterator cvar = m_Cvars.begin(); cvar != m_Cvars.end(); cvar++)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < (*cvar)->hooks.length(); ++i)
|
||||||
|
{
|
||||||
|
delete (*cvar)->hooks[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
(*cvar)->hooks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is no point to enable detour if at next map change
|
||||||
|
// no plugins hook cvars.
|
||||||
|
m_HookDetour->DisableDetour();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CvarManager::OnAmxxShutdown()
|
||||||
|
{
|
||||||
|
// Free everything.
|
||||||
|
for (CvarsList::iterator cvar = m_Cvars.begin(); cvar != m_Cvars.end(); cvar = m_Cvars.erase(cvar))
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < (*cvar)->hooks.length(); ++i)
|
||||||
|
{
|
||||||
|
delete (*cvar)->hooks[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
delete (*cvar);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Cache.clear();
|
||||||
|
m_HookDetour->Destroy();
|
||||||
|
}
|
|
@ -22,7 +22,8 @@ OBJECTS = meta_api.cpp CFile.cpp CVault.cpp vault.cpp float.cpp file.cpp modules
|
||||||
optimizer.cpp format.cpp messages.cpp libraries.cpp vector.cpp sorting.cpp \
|
optimizer.cpp format.cpp messages.cpp libraries.cpp vector.cpp sorting.cpp \
|
||||||
nongpl_matches.cpp CFlagManager.cpp datastructs.cpp \
|
nongpl_matches.cpp CFlagManager.cpp datastructs.cpp \
|
||||||
trie_natives.cpp CDataPack.cpp datapacks.cpp stackstructs.cpp \
|
trie_natives.cpp CDataPack.cpp datapacks.cpp stackstructs.cpp \
|
||||||
CTextParsers.cpp textparse.cpp \
|
CTextParsers.cpp textparse.cpp CvarManager.cpp cvars.cpp \
|
||||||
|
../public/memtools/CDetour/detours.cpp ../public/memtools/CDetour/asm/asm.c
|
||||||
|
|
||||||
##############################################
|
##############################################
|
||||||
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
||||||
|
|
|
@ -22,25 +22,6 @@
|
||||||
|
|
||||||
extern CFlagManager FlagMan;
|
extern CFlagManager FlagMan;
|
||||||
CVector<CAdminData *> DynamicAdmins;
|
CVector<CAdminData *> DynamicAdmins;
|
||||||
char CVarTempBuffer[64];
|
|
||||||
|
|
||||||
const char *invis_cvar_list[5] = {"amxmodx_version", "amxmodx_modules", "amx_debug", "amx_mldebug", "amx_client_languages"};
|
|
||||||
|
|
||||||
bool CheckBadConList(const char *cvar, int type)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
while (NONGPL_CVAR_LIST[i].cvar != NULL)
|
|
||||||
{
|
|
||||||
if (NONGPL_CVAR_LIST[i].type == type
|
|
||||||
&& strcmp(NONGPL_CVAR_LIST[i].cvar, cvar) == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_xvar_id(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL get_xvar_id(AMX *amx, cell *params)
|
||||||
{
|
{
|
||||||
|
@ -112,36 +93,6 @@ static cell AMX_NATIVE_CALL emit_sound(AMX *amx, cell *params) /* 7 param */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL enable_cvar_hook(AMX *amx, cell *params) /* 7 param */
|
|
||||||
{
|
|
||||||
Forward* forward = reinterpret_cast<Forward*>(params[1]);
|
|
||||||
|
|
||||||
if (!forward)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid cvar hook handle: %p", forward);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
forward->state = Forward::FSTATE_OK;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL disable_cvar_hook(AMX *amx, cell *params) /* 7 param */
|
|
||||||
{
|
|
||||||
Forward* forward = reinterpret_cast<Forward*>(params[1]);
|
|
||||||
|
|
||||||
if (!forward)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid cvar hook handle: %p", forward);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
forward->state = Forward::FSTATE_STOP;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL server_print(AMX *amx, cell *params) /* 1 param */
|
static cell AMX_NATIVE_CALL server_print(AMX *amx, cell *params) /* 1 param */
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
@ -1939,170 +1890,6 @@ static cell AMX_NATIVE_CALL client_cmd(AMX *amx, cell *params) /* 2 param */
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_pcvar_string(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return set_amxstring_utf8(amx, params[2], ptr->string ? ptr->string : "", ptr->string ? strlen(ptr->string) : 0, params[3] + 1); // EOS
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_cvar_string(AMX *amx, cell *params) /* 3 param */
|
|
||||||
{
|
|
||||||
int length;
|
|
||||||
const char* name = get_amxstring(amx, params[1], 0, length);
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return amx_ftoc(ptr->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_cvar_float(AMX *amx, cell *params) /* 1 param */
|
|
||||||
{
|
|
||||||
int length;
|
|
||||||
const char* name = get_amxstring(amx, params[1], 0, length);
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
|
||||||
return 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 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_pcvar_num(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (int)ptr->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_cvar_num(AMX *amx, cell *params) /* 1 param */
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
UTIL_Format(CVarTempBuffer,sizeof(CVarTempBuffer)-1,"%d",params[2]);
|
|
||||||
CVAR_DIRECTSET(ptr, &CVarTempBuffer[0]);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL set_cvar_num(AMX *amx, cell *params) /* 2 param */
|
|
||||||
{
|
|
||||||
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 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL set_pcvar_string(AMX *amx, cell *params) /* 2 param */
|
|
||||||
{
|
|
||||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int len;
|
|
||||||
|
|
||||||
CVAR_DIRECTSET(ptr, get_amxstring(amx,params[2],0,len));
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL log_message(AMX *amx, cell *params) /* 1 param */
|
static cell AMX_NATIVE_CALL log_message(AMX *amx, cell *params) /* 1 param */
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
@ -2655,33 +2442,6 @@ static cell AMX_NATIVE_CALL task_exists(AMX *amx, cell *params) /* 1 param */
|
||||||
return g_tasksMngr.taskExists(params[1], params[2] ? 0 : amx);
|
return g_tasksMngr.taskExists(params[1], params[2] ? 0 : amx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL cvar_exists(AMX *amx, cell *params) /* 1 param */
|
|
||||||
{
|
|
||||||
int ilen;
|
|
||||||
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 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(name, 0))
|
|
||||||
{
|
|
||||||
plugin->AddToFailCounter(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
cvar_t* var = g_CvarManager.CreateCvar(name, value, fvalue, flags, plugin->getName(), plugin->getId());
|
|
||||||
|
|
||||||
return reinterpret_cast<cell>(var);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 */
|
||||||
{
|
{
|
||||||
int index = params[1];
|
int index = params[1];
|
||||||
|
@ -3067,30 +2827,6 @@ static cell AMX_NATIVE_CALL remove_quotes(AMX *amx, cell *params) /* 1 param */
|
||||||
return 0;
|
return 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)
|
|
||||||
{
|
|
||||||
CvarInfo* info = g_CvarManager.FindCvar(params[1]);
|
|
||||||
|
|
||||||
if (info)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//native get_plugins_cvarsnum();
|
|
||||||
static cell AMX_NATIVE_CALL get_plugins_cvarsnum(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
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 */
|
||||||
{
|
{
|
||||||
int index = params[1];
|
int index = params[1];
|
||||||
|
@ -3134,80 +2870,6 @@ static cell AMX_NATIVE_CALL get_user_aiming(AMX *amx, cell *params) /* 4 param *
|
||||||
return amx_ftoc(pfloat);
|
return amx_ftoc(pfloat);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL remove_cvar_flags(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
int ilen;
|
|
||||||
char* sCvar = get_amxstring(amx, params[1], 0, ilen);
|
|
||||||
|
|
||||||
if (!strcmp(sCvar, "amx_version") || !strcmp(sCvar, "amxmodx_version") || !strcmp(sCvar, "fun_version") || !strcmp(sCvar, "sv_cheats"))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
cvar_t* pCvar = g_CvarManager.FindCvar(sCvar);
|
|
||||||
|
|
||||||
if (pCvar)
|
|
||||||
{
|
|
||||||
pCvar->flags &= ~((int)(params[2]));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_pcvar_flags(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptr->flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = g_CvarManager.FindCvar(sCvar);
|
|
||||||
|
|
||||||
return pCvar ? pCvar->flags : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL set_pcvar_flags(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
|
||||||
if (!ptr)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr->flags = static_cast<int>(params[2]);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL set_cvar_flags(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
int ilen;
|
|
||||||
char* sCvar = get_amxstring(amx, params[1], 0, ilen);
|
|
||||||
|
|
||||||
if (!strcmp(sCvar, "amx_version") || !strcmp(sCvar, "amxmodx_version") || !strcmp(sCvar, "fun_version") || !strcmp(sCvar, "sv_cheats"))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
cvar_t* pCvar = g_CvarManager.FindCvar(sCvar);
|
|
||||||
|
|
||||||
if (pCvar)
|
|
||||||
{
|
|
||||||
pCvar->flags |= (int)(params[2]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL force_unmodified(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL force_unmodified(AMX *amx, cell *params)
|
||||||
{
|
{
|
||||||
int a;
|
int a;
|
||||||
|
@ -4156,102 +3818,6 @@ static cell AMX_NATIVE_CALL int3(AMX *amx, cell *params)
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
|
||||||
#if defined AMD64
|
|
||||||
static bool g_warned_ccqv = false;
|
|
||||||
#endif
|
|
||||||
// native query_client_cvar(id, const cvar[], const resultfunc[])
|
|
||||||
static cell AMX_NATIVE_CALL query_client_cvar(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
int numParams = params[0] / sizeof(cell);
|
|
||||||
|
|
||||||
if (numParams != 3 && numParams != 5)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid number of parameters passed!");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined AMD64
|
|
||||||
if (!g_warned_ccqv)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "[AMXX] Client CVAR Querying is not available on AMD64 (one time warn)");
|
|
||||||
g_warned_ccqv = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!g_NewDLL_Available)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Client CVAR querying is not enabled - check MM version!");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int id = params[1];
|
|
||||||
|
|
||||||
if (id < 1 || id > gpGlobals->maxClients)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid player id %d", id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CPlayer *pPlayer = GET_PLAYER_POINTER_I(id);
|
|
||||||
|
|
||||||
if (!pPlayer->initialized || pPlayer->IsBot())
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Player %d is either not connected or a bot", id);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dummy;
|
|
||||||
const char *cvarname = get_amxstring(amx, params[2], 0, dummy);
|
|
||||||
const char *resultfuncname = get_amxstring(amx, params[3], 1, dummy);
|
|
||||||
|
|
||||||
// public clientcvarquery_result(id, const cvar[], const result[], [const param[]])
|
|
||||||
int iFunc;
|
|
||||||
|
|
||||||
if (numParams == 5 && params[4] != 0)
|
|
||||||
iFunc = registerSPForwardByName(amx, resultfuncname, FP_CELL, FP_STRING, FP_STRING, FP_ARRAY, FP_DONE);
|
|
||||||
else
|
|
||||||
iFunc = registerSPForwardByName(amx, resultfuncname, FP_CELL, FP_STRING, FP_STRING, FP_DONE);
|
|
||||||
|
|
||||||
if (iFunc == -1)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Function \"%s\" is not present", resultfuncname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientCvarQuery_Info *queryObject = new ClientCvarQuery_Info;
|
|
||||||
queryObject->resultFwd = iFunc;
|
|
||||||
queryObject->requestId = MAKE_REQUESTID(PLID);
|
|
||||||
|
|
||||||
if (numParams == 5 && params[4] != 0)
|
|
||||||
{
|
|
||||||
queryObject->paramLen = params[4] + 1;
|
|
||||||
queryObject->params = new cell[queryObject->paramLen];
|
|
||||||
|
|
||||||
if (!queryObject->params)
|
|
||||||
{
|
|
||||||
delete queryObject;
|
|
||||||
unregisterSPForward(iFunc);
|
|
||||||
LogError(amx, AMX_ERR_MEMORY, "Hmm. Out of memory?");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(reinterpret_cast<void*>(queryObject->params), reinterpret_cast<const void *>(get_amxaddr(amx, params[5])), queryObject->paramLen * sizeof(cell));
|
|
||||||
|
|
||||||
queryObject->params[queryObject->paramLen - 1] = 0;
|
|
||||||
} else {
|
|
||||||
queryObject->params = NULL;
|
|
||||||
queryObject->paramLen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pPlayer->queries.push_back(queryObject);
|
|
||||||
|
|
||||||
QUERY_CLIENT_CVAR_VALUE2(pPlayer->pEdict, cvarname, queryObject->requestId);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL amx_abort(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL amx_abort(AMX *amx, cell *params)
|
||||||
{
|
{
|
||||||
int err = params[1];
|
int err = params[1];
|
||||||
|
@ -4480,16 +4046,6 @@ static cell AMX_NATIVE_CALL DestroyForward(AMX *amx, cell *params)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL get_cvar_pointer(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
char *name = get_amxstring(amx, params[1], 0, len);
|
|
||||||
|
|
||||||
cvar_t *ptr = g_CvarManager.FindCvar(name);
|
|
||||||
|
|
||||||
return reinterpret_cast<cell>(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
CVector<cell *> g_hudsync;
|
CVector<cell *> g_hudsync;
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL CreateHudSyncObj(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL CreateHudSyncObj(AMX *amx, cell *params)
|
||||||
|
@ -4861,29 +4417,6 @@ static cell AMX_NATIVE_CALL has_map_ent_class(AMX *amx, cell *params)
|
||||||
return len && !FNullEnt(FIND_ENTITY_BY_STRING(NULL, "classname", name));
|
return len && !FNullEnt(FIND_ENTITY_BY_STRING(NULL, "classname", name));
|
||||||
};
|
};
|
||||||
|
|
||||||
// hook_cvar_change(cvarHandle, const callback[])
|
|
||||||
static cell AMX_NATIVE_CALL hook_cvar_change(AMX *amx, cell *params)
|
|
||||||
{
|
|
||||||
cvar_t* var = reinterpret_cast<cvar_t*>(params[1]);
|
|
||||||
|
|
||||||
if (!var)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid cvar handle: %p", var);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* callback;
|
|
||||||
Forward* forward = g_CvarManager.HookCvarChange(var, amx, params[2], &callback);
|
|
||||||
|
|
||||||
if (!forward)
|
|
||||||
{
|
|
||||||
LogError(amx, AMX_ERR_NATIVE, "Invalid callback function: %s", callback);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return reinterpret_cast<cell>(forward);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cell AMX_NATIVE_CALL is_rukia_a_hag(AMX *amx, cell *params)
|
static cell AMX_NATIVE_CALL is_rukia_a_hag(AMX *amx, cell *params)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -4918,10 +4451,7 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
|
||||||
{"client_print_color", client_print_color},
|
{"client_print_color", client_print_color},
|
||||||
{"console_cmd", console_cmd},
|
{"console_cmd", console_cmd},
|
||||||
{"console_print", console_print},
|
{"console_print", console_print},
|
||||||
{"cvar_exists", cvar_exists},
|
|
||||||
{"emit_sound", emit_sound},
|
{"emit_sound", emit_sound},
|
||||||
{"enable_cvar_hook", enable_cvar_hook},
|
|
||||||
{"disable_cvar_hook", disable_cvar_hook},
|
|
||||||
{"engclient_cmd", engclient_cmd},
|
{"engclient_cmd", engclient_cmd},
|
||||||
{"engclient_print", engclient_print},
|
{"engclient_print", engclient_print},
|
||||||
{"find_player", find_player},
|
{"find_player", find_player},
|
||||||
|
@ -4933,11 +4463,6 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
|
||||||
{"get_concmd", get_concmd},
|
{"get_concmd", get_concmd},
|
||||||
{"get_concmdsnum", get_concmdsnum},
|
{"get_concmdsnum", get_concmdsnum},
|
||||||
{"get_concmd_plid", get_concmd_plid},
|
{"get_concmd_plid", get_concmd_plid},
|
||||||
{"get_cvar_flags", get_cvar_flags},
|
|
||||||
{"get_cvar_float", get_cvar_float},
|
|
||||||
{"get_cvar_num", get_cvar_num},
|
|
||||||
{"get_cvar_pointer", get_cvar_pointer},
|
|
||||||
{"get_cvar_string", get_cvar_string},
|
|
||||||
{"get_flags", get_flags},
|
{"get_flags", get_flags},
|
||||||
{"get_func_id", get_func_id},
|
{"get_func_id", get_func_id},
|
||||||
{"get_gametime", get_gametime},
|
{"get_gametime", get_gametime},
|
||||||
|
@ -4949,16 +4474,10 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
|
||||||
{"get_modname", get_modname},
|
{"get_modname", get_modname},
|
||||||
{"get_module", get_module},
|
{"get_module", get_module},
|
||||||
{"get_modulesnum", get_modulesnum},
|
{"get_modulesnum", get_modulesnum},
|
||||||
{"get_pcvar_flags", get_pcvar_flags},
|
|
||||||
{"get_pcvar_float", get_pcvar_float},
|
|
||||||
{"get_pcvar_num", get_pcvar_num},
|
|
||||||
{"get_pcvar_string", get_pcvar_string},
|
|
||||||
{"get_players", get_players},
|
{"get_players", get_players},
|
||||||
{"get_playersnum", get_playersnum},
|
{"get_playersnum", get_playersnum},
|
||||||
{"get_plugin", get_plugin},
|
{"get_plugin", get_plugin},
|
||||||
{"get_pluginsnum", get_pluginsnum},
|
{"get_pluginsnum", get_pluginsnum},
|
||||||
{"get_plugins_cvar", get_plugins_cvar},
|
|
||||||
{"get_plugins_cvarsnum", get_plugins_cvarsnum},
|
|
||||||
{"get_srvcmd", get_srvcmd},
|
{"get_srvcmd", get_srvcmd},
|
||||||
{"get_srvcmdsnum", get_srvcmdsnum},
|
{"get_srvcmdsnum", get_srvcmdsnum},
|
||||||
{"get_systime", get_systime},
|
{"get_systime", get_systime},
|
||||||
|
@ -4995,7 +4514,6 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
|
||||||
{"get_xvar_id", get_xvar_id},
|
{"get_xvar_id", get_xvar_id},
|
||||||
{"get_xvar_num", get_xvar_num},
|
{"get_xvar_num", get_xvar_num},
|
||||||
{"has_map_ent_class", has_map_ent_class},
|
{"has_map_ent_class", has_map_ent_class},
|
||||||
{"hook_cvar_change", hook_cvar_change},
|
|
||||||
{"int3", int3},
|
{"int3", int3},
|
||||||
{"is_amd64_server", is_amd64_server},
|
{"is_amd64_server", is_amd64_server},
|
||||||
{"is_dedicated_server", is_dedicated_server},
|
{"is_dedicated_server", is_dedicated_server},
|
||||||
|
@ -5028,7 +4546,6 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
|
||||||
{"precache_model", precache_model},
|
{"precache_model", precache_model},
|
||||||
{"precache_sound", precache_sound},
|
{"precache_sound", precache_sound},
|
||||||
{"precache_generic", precache_generic},
|
{"precache_generic", precache_generic},
|
||||||
{"query_client_cvar", query_client_cvar},
|
|
||||||
{"random_float", random_float},
|
{"random_float", random_float},
|
||||||
{"random_num", random_num},
|
{"random_num", random_num},
|
||||||
{"read_argc", read_argc},
|
{"read_argc", read_argc},
|
||||||
|
@ -5043,7 +4560,6 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
|
||||||
{"read_logdata", read_logdata},
|
{"read_logdata", read_logdata},
|
||||||
{"register_clcmd", register_clcmd},
|
{"register_clcmd", register_clcmd},
|
||||||
{"register_concmd", register_concmd},
|
{"register_concmd", register_concmd},
|
||||||
{"register_cvar", register_cvar},
|
|
||||||
{"register_dictionary", register_dictionary},
|
{"register_dictionary", register_dictionary},
|
||||||
{"register_event", register_event},
|
{"register_event", register_event},
|
||||||
{"register_logevent", register_logevent},
|
{"register_logevent", register_logevent},
|
||||||
|
@ -5052,25 +4568,16 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
|
||||||
{"register_plugin", register_plugin},
|
{"register_plugin", register_plugin},
|
||||||
{"register_srvcmd", register_srvcmd},
|
{"register_srvcmd", register_srvcmd},
|
||||||
{"require_module", require_module},
|
{"require_module", require_module},
|
||||||
{"remove_cvar_flags", remove_cvar_flags},
|
|
||||||
{"remove_quotes", remove_quotes},
|
{"remove_quotes", remove_quotes},
|
||||||
{"remove_task", remove_task},
|
{"remove_task", remove_task},
|
||||||
{"remove_user_flags", remove_user_flags},
|
{"remove_user_flags", remove_user_flags},
|
||||||
{"server_cmd", server_cmd},
|
{"server_cmd", server_cmd},
|
||||||
{"server_exec", server_exec},
|
{"server_exec", server_exec},
|
||||||
{"server_print", server_print},
|
{"server_print", server_print},
|
||||||
{"set_cvar_flags", set_cvar_flags},
|
|
||||||
{"set_cvar_float", set_cvar_float},
|
|
||||||
{"set_cvar_num", set_cvar_num},
|
|
||||||
{"set_cvar_string", set_cvar_string},
|
|
||||||
{"set_fail_state", set_fail_state},
|
{"set_fail_state", set_fail_state},
|
||||||
{"set_dhudmessage", set_dhudmessage},
|
{"set_dhudmessage", set_dhudmessage},
|
||||||
{"set_hudmessage", set_hudmessage},
|
{"set_hudmessage", set_hudmessage},
|
||||||
{"set_localinfo", set_localinfo},
|
{"set_localinfo", set_localinfo},
|
||||||
{"set_pcvar_flags", set_pcvar_flags},
|
|
||||||
{"set_pcvar_float", set_pcvar_float},
|
|
||||||
{"set_pcvar_string", set_pcvar_string},
|
|
||||||
{"set_pcvar_num", set_pcvar_num},
|
|
||||||
{"set_task", set_task},
|
{"set_task", set_task},
|
||||||
{"set_user_flags", set_user_flags},
|
{"set_user_flags", set_user_flags},
|
||||||
{"set_user_info", set_user_info},
|
{"set_user_info", set_user_info},
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
#include "CLang.h"
|
#include "CLang.h"
|
||||||
#include "fakemeta.h"
|
#include "fakemeta.h"
|
||||||
#include "amxxlog.h"
|
#include "amxxlog.h"
|
||||||
#include "cvars.h"
|
#include "CvarManager.h"
|
||||||
|
|
||||||
#define AMXXLOG_Log g_log.Log
|
#define AMXXLOG_Log g_log.Log
|
||||||
#define AMXXLOG_Error g_log.LogError
|
#define AMXXLOG_Error g_log.LogError
|
||||||
|
@ -66,6 +66,7 @@ extern AMX_NATIVE_INFO g_SortNatives[];
|
||||||
extern AMX_NATIVE_INFO g_DataStructNatives[];
|
extern AMX_NATIVE_INFO g_DataStructNatives[];
|
||||||
extern AMX_NATIVE_INFO g_StackNatives[];
|
extern AMX_NATIVE_INFO g_StackNatives[];
|
||||||
extern AMX_NATIVE_INFO g_TextParserNatives[];
|
extern AMX_NATIVE_INFO g_TextParserNatives[];
|
||||||
|
extern AMX_NATIVE_INFO g_CvarNatives[];
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#define DLLOAD(path) (DLHANDLE)LoadLibrary(path)
|
#define DLLOAD(path) (DLHANDLE)LoadLibrary(path)
|
||||||
|
|
|
@ -7,342 +7,520 @@
|
||||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||||
// https://alliedmods.net/amxmodx-license
|
// https://alliedmods.net/amxmodx-license
|
||||||
|
|
||||||
#include "cvars.h"
|
#include "CvarManager.h"
|
||||||
#include "amxmodx.h"
|
#include "amxmodx.h"
|
||||||
#include <CDetour/detours.h>
|
#include "nongpl_matches.h"
|
||||||
|
|
||||||
CvarManager g_CvarManager;
|
char CVarTempBuffer[64];
|
||||||
|
const char *invis_cvar_list[5] = { "amxmodx_version", "amxmodx_modules", "amx_debug", "amx_mldebug", "amx_client_languages" };
|
||||||
|
|
||||||
/**
|
// register_cvar(const name[], const string[], flags=0, Float:fvalue=0.0)
|
||||||
* Returns true to call original function, otherwise false to block it.
|
static cell AMX_NATIVE_CALL register_cvar(AMX *amx, cell *params)
|
||||||
*/
|
|
||||||
bool Cvar_DirectSet_Custom(cvar_t* var, const char* value)
|
|
||||||
{
|
{
|
||||||
CvarInfo* info = nullptr;
|
int length;
|
||||||
|
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||||
|
const char* value = get_amxstring(amx, params[2], 1, length);
|
||||||
|
|
||||||
if (!var || !value // Sanity checks against bogus pointers.
|
int flags = params[3];
|
||||||
|| strcmp(var->string, value) == 0 // Make sure old and new values are different to not trigger callbacks.
|
float fvalue = amx_ctof(params[4]);
|
||||||
|| !g_CvarManager.CacheLookup(var->name, &info) // No data in cache, nothing to call.
|
|
||||||
|| info->hooks.empty()) // No hooked cvars, nothing to call.
|
CPluginMngr::CPlugin *plugin = g_plugins.findPluginFast(amx);
|
||||||
|
|
||||||
|
if (CheckBadConList(name, 0))
|
||||||
{
|
{
|
||||||
return true;
|
plugin->AddToFailCounter(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int lastResult = 0;
|
cvar_t* var = g_CvarManager.CreateCvar(name, value, fvalue, flags, plugin->getName(), plugin->getId());
|
||||||
int result;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < info->hooks.length(); ++i)
|
return reinterpret_cast<cell>(var);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cvar_exists(const cvar[])
|
||||||
|
static cell AMX_NATIVE_CALL cvar_exists(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
int ilen;
|
||||||
|
return (g_CvarManager.FindCvar(get_amxstring(amx, params[1], 0, ilen)) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_cvar_pointer(const cvar[])
|
||||||
|
static cell AMX_NATIVE_CALL get_cvar_pointer(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char *name = get_amxstring(amx, params[1], 0, len);
|
||||||
|
|
||||||
|
cvar_t *ptr = g_CvarManager.FindCvar(name);
|
||||||
|
|
||||||
|
return reinterpret_cast<cell>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// hook_cvar_change(cvarHandle, const callback[])
|
||||||
|
static cell AMX_NATIVE_CALL hook_cvar_change(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
cvar_t* var = reinterpret_cast<cvar_t*>(params[1]);
|
||||||
|
|
||||||
|
if (!var)
|
||||||
{
|
{
|
||||||
CvarPlugin* p = info->hooks[i];
|
LogError(amx, AMX_ERR_NATIVE, "Invalid cvar handle: %p", var);
|
||||||
|
return 0;
|
||||||
if (p->forward->state == Forward::FSTATE_OK) // Our callback can be enable/disabled by natives.
|
|
||||||
{
|
|
||||||
result = executeForwards(p->forward->id, reinterpret_cast<cvar_t*>(var), var->string, value);
|
|
||||||
|
|
||||||
if (result >= lastResult)
|
|
||||||
{
|
|
||||||
lastResult = result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return !!!lastResult;
|
const char* callback;
|
||||||
}
|
Forward* forward = g_CvarManager.HookCvarChange(var, amx, params[2], &callback);
|
||||||
|
|
||||||
DETOUR_DECL_STATIC2(Cvar_DirectSet, void, struct cvar_s*, var, const char*, value)
|
if (!forward)
|
||||||
{
|
|
||||||
if (Cvar_DirectSet_Custom(var, value))
|
|
||||||
{
|
{
|
||||||
DETOUR_STATIC_CALL(Cvar_DirectSet)(var, value);
|
LogError(amx, AMX_ERR_NATIVE, "Function \"%s\" is not present", callback);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<cell>(forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
CvarManager::CvarManager() : m_AmxmodxCvars(0), m_HookDetour(nullptr)
|
// enable_cvar_hook(cvarhook:handle);
|
||||||
|
static cell AMX_NATIVE_CALL enable_cvar_hook(AMX *amx, cell *params)
|
||||||
{
|
{
|
||||||
|
Forward* forward = reinterpret_cast<Forward*>(params[1]);
|
||||||
|
|
||||||
|
if (!forward)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid cvar hook handle: %p", forward);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
forward->state = Forward::FSTATE_OK;
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CvarManager::~CvarManager()
|
// disable_cvar_hook(cvarhook:handle);
|
||||||
|
static cell AMX_NATIVE_CALL disable_cvar_hook(AMX *amx, cell *params)
|
||||||
{
|
{
|
||||||
OnAmxxShutdown();
|
Forward* forward = reinterpret_cast<Forward*>(params[1]);
|
||||||
|
|
||||||
|
if (!forward)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid cvar hook handle: %p", forward);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
forward->state = Forward::FSTATE_STOP;
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CvarManager::CreateCvarHook(void)
|
// get_cvar_flags(const cvar[])
|
||||||
|
static cell AMX_NATIVE_CALL get_cvar_flags(AMX *amx, cell *params)
|
||||||
{
|
{
|
||||||
// void PF_Cvar_DirectSet(struct cvar_s *var, const char *value) // = pfnCvar_DirectSet
|
int ilen;
|
||||||
// {
|
char* sCvar = get_amxstring(amx, params[1], 0, ilen);
|
||||||
// Cvar_DirectSet(var, value); // <- We want to hook this.
|
|
||||||
// }
|
|
||||||
|
|
||||||
byte *baseAddress = (byte *)g_engfuncs.pfnCvar_DirectSet;
|
cvar_t* pCvar = g_CvarManager.FindCvar(sCvar);
|
||||||
uintptr_t *functionAddress = nullptr;
|
|
||||||
|
|
||||||
#if defined(WIN32)
|
return pCvar ? pCvar->flags : 0;
|
||||||
// 55 push ebp
|
}
|
||||||
// 8B EC mov ebp, esp
|
|
||||||
// 8B 45 0C mov eax, [ebp+arg_4]
|
// get_cvar_float(const cvarname[])
|
||||||
// 8B 4D 08 mov ecx, [ebp+arg_0]
|
static cell AMX_NATIVE_CALL get_cvar_float(AMX *amx, cell *params)
|
||||||
// 50 push eax
|
{
|
||||||
// 51 push ecx
|
int length;
|
||||||
// E8 XX XX XX XX call Cvar_DirectSet
|
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||||
const byte opcodeJump = 0xE8;
|
|
||||||
#else
|
cvar_t* var = g_CvarManager.FindCvar(name);
|
||||||
// E9 XX XX XX XX jmp Cvar_DirectSet
|
|
||||||
const byte opcodeJump = 0xE9;
|
return var ? amx_ftoc(var->value) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_cvar_num(const cvarname[])
|
||||||
|
static cell AMX_NATIVE_CALL get_cvar_num(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_cvar_string(const cvarname[], output[], iLen)
|
||||||
|
static cell AMX_NATIVE_CALL get_cvar_string(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
int length;
|
||||||
|
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_cvar_flags(const cvar[], flags)
|
||||||
|
static cell AMX_NATIVE_CALL set_cvar_flags(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
int ilen;
|
||||||
|
char* sCvar = get_amxstring(amx, params[1], 0, ilen);
|
||||||
|
|
||||||
|
if (!strcmp(sCvar, "amx_version") || !strcmp(sCvar, "amxmodx_version") || !strcmp(sCvar, "fun_version") || !strcmp(sCvar, "sv_cheats"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cvar_t* pCvar = g_CvarManager.FindCvar(sCvar);
|
||||||
|
|
||||||
|
if (pCvar)
|
||||||
|
{
|
||||||
|
pCvar->flags |= (int)(params[2]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_cvar_float(const cvar[], Float:value)
|
||||||
|
static cell AMX_NATIVE_CALL set_cvar_float(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_cvar_num(const cvarname[], value)
|
||||||
|
static cell AMX_NATIVE_CALL set_cvar_num(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_cvar_string(const cvar[], const value[])
|
||||||
|
static cell AMX_NATIVE_CALL set_cvar_string(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_pcvar_flags(pcvar)
|
||||||
|
static cell AMX_NATIVE_CALL get_pcvar_flags(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float:get_pcvar_float(pcvar)
|
||||||
|
static cell AMX_NATIVE_CALL get_pcvar_float(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return amx_ftoc(ptr->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_pcvar_num(pcvar)
|
||||||
|
static cell AMX_NATIVE_CALL get_pcvar_num(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)ptr->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_pcvar_string(pcvar, string[], maxlen)
|
||||||
|
static cell AMX_NATIVE_CALL get_pcvar_string(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return set_amxstring_utf8(amx, params[2], ptr->string ? ptr->string : "", ptr->string ? strlen(ptr->string) : 0, params[3] + 1); // EOS
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_pcvar_flags(pcvar, flags)
|
||||||
|
static cell AMX_NATIVE_CALL set_pcvar_flags(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr->flags = static_cast<int>(params[2]);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_pcvar_float(pcvar, Float:num)
|
||||||
|
static cell AMX_NATIVE_CALL set_pcvar_float(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UTIL_Format(CVarTempBuffer, sizeof(CVarTempBuffer) - 1, "%f", amx_ctof(params[2]));
|
||||||
|
CVAR_DIRECTSET(ptr, &CVarTempBuffer[0]);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_pcvar_num(pcvar, num)
|
||||||
|
static cell AMX_NATIVE_CALL set_pcvar_num(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UTIL_Format(CVarTempBuffer, sizeof(CVarTempBuffer) - 1, "%d", params[2]);
|
||||||
|
CVAR_DIRECTSET(ptr, &CVarTempBuffer[0]);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_pcvar_string(pcvar, const string[])
|
||||||
|
static cell AMX_NATIVE_CALL set_pcvar_string(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len;
|
||||||
|
|
||||||
|
CVAR_DIRECTSET(ptr, get_amxstring(amx, params[2], 0, len));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove_cvar_flags(const cvar[], flags=-1)
|
||||||
|
static cell AMX_NATIVE_CALL remove_cvar_flags(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
int ilen;
|
||||||
|
char* sCvar = get_amxstring(amx, params[1], 0, ilen);
|
||||||
|
|
||||||
|
if (!strcmp(sCvar, "amx_version") || !strcmp(sCvar, "amxmodx_version") || !strcmp(sCvar, "fun_version") || !strcmp(sCvar, "sv_cheats"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cvar_t* pCvar = g_CvarManager.FindCvar(sCvar);
|
||||||
|
|
||||||
|
if (pCvar)
|
||||||
|
{
|
||||||
|
pCvar->flags &= ~((int)(params[2]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
CvarInfo* info = g_CvarManager.FindCvar(params[1]);
|
||||||
|
|
||||||
|
if (info)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_plugins_cvarsnum()
|
||||||
|
static cell AMX_NATIVE_CALL get_plugins_cvarsnum(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
return g_CvarManager.GetRegCvarsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined AMD64
|
||||||
|
static bool g_warned_ccqv = false;
|
||||||
|
#endif
|
||||||
|
// query_client_cvar(id, const cvar[], const resultfunc[])
|
||||||
|
static cell AMX_NATIVE_CALL query_client_cvar(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
int numParams = params[0] / sizeof(cell);
|
||||||
|
|
||||||
|
if (numParams != 3 && numParams != 5)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid number of parameters passed!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined AMD64
|
||||||
|
if (!g_warned_ccqv)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "[AMXX] Client CVAR Querying is not available on AMD64 (one time warn)");
|
||||||
|
g_warned_ccqv = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const byte opcodeJumpSize = 5;
|
if (!g_NewDLL_Available)
|
||||||
const byte opcodeJumpByteSize = 1;
|
|
||||||
|
|
||||||
const int maxBytesLimit = 20;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < maxBytesLimit; ++i, ++baseAddress)
|
|
||||||
{
|
{
|
||||||
if (*baseAddress == opcodeJump)
|
LogError(amx, AMX_ERR_NATIVE, "Client CVAR querying is not enabled - check MM version!");
|
||||||
{
|
return 0;
|
||||||
functionAddress = (uintptr_t *)(&baseAddress[opcodeJumpSize] + *(uintptr_t *)&baseAddress[opcodeJumpByteSize]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (functionAddress)
|
int id = params[1];
|
||||||
{
|
|
||||||
m_HookDetour = DETOUR_CREATE_STATIC_FIXED(Cvar_DirectSet, (void *)functionAddress);
|
|
||||||
|
|
||||||
if (m_HookDetour)
|
if (id < 1 || id > gpGlobals->maxClients)
|
||||||
{
|
{
|
||||||
m_HookDetour->EnableDetour();
|
LogError(amx, AMX_ERR_NATIVE, "Invalid player id %d", id);
|
||||||
}
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
cvar_t* CvarManager::CreateCvar(const char* name, const char* value, float fvalue, int flags, const char* plugin, int plugnId)
|
CPlayer *pPlayer = GET_PLAYER_POINTER_I(id);
|
||||||
{
|
|
||||||
cvar_t* var = nullptr;
|
|
||||||
CvarInfo* info = nullptr;
|
|
||||||
|
|
||||||
if (!CacheLookup(name, &info))
|
if (!pPlayer->initialized || pPlayer->IsBot())
|
||||||
{
|
{
|
||||||
// Not cached - Is cvar already exist?
|
LogError(amx, AMX_ERR_NATIVE, "Player %d is either not connected or a bot", id);
|
||||||
var = CVAR_GET_POINTER(name);
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Whether it exists, we need to prepare a new entry.
|
int dummy;
|
||||||
info = new CvarInfo();
|
const char *cvarname = get_amxstring(amx, params[2], 0, dummy);
|
||||||
|
const char *resultfuncname = get_amxstring(amx, params[3], 1, dummy);
|
||||||
|
|
||||||
// Shared datas.
|
// public clientcvarquery_result(id, const cvar[], const result[], [const param[]])
|
||||||
info->name = name;
|
int iFunc;
|
||||||
info->plugin = plugin;
|
|
||||||
info->pluginId = plugnId;
|
|
||||||
|
|
||||||
if (var)
|
if (numParams == 5 && params[4] != 0)
|
||||||
|
iFunc = registerSPForwardByName(amx, resultfuncname, FP_CELL, FP_STRING, FP_STRING, FP_ARRAY, FP_DONE);
|
||||||
|
else
|
||||||
|
iFunc = registerSPForwardByName(amx, resultfuncname, FP_CELL, FP_STRING, FP_STRING, FP_DONE);
|
||||||
|
|
||||||
|
if (iFunc == -1)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Function \"%s\" is not present", resultfuncname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientCvarQuery_Info *queryObject = new ClientCvarQuery_Info;
|
||||||
|
queryObject->resultFwd = iFunc;
|
||||||
|
queryObject->requestId = MAKE_REQUESTID(PLID);
|
||||||
|
|
||||||
|
if (numParams == 5 && params[4] != 0)
|
||||||
|
{
|
||||||
|
queryObject->paramLen = params[4] + 1;
|
||||||
|
queryObject->params = new cell[queryObject->paramLen];
|
||||||
|
|
||||||
|
if (!queryObject->params)
|
||||||
{
|
{
|
||||||
// Cvar already exists. Just copy.
|
delete queryObject;
|
||||||
// "string" will be set after. "value" and "next" are automatically set.
|
unregisterSPForward(iFunc);
|
||||||
info->var = var;
|
LogError(amx, AMX_ERR_MEMORY, "Hmm. Out of memory?");
|
||||||
info->defaultval = var->string;
|
return 0;
|
||||||
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.
|
memcpy(reinterpret_cast<void*>(queryObject->params), reinterpret_cast<const void *>(get_amxaddr(amx, params[5])), queryObject->paramLen * sizeof(cell));
|
||||||
m_Cvars.append(info);
|
|
||||||
m_Cache.insert(name, info);
|
|
||||||
|
|
||||||
// Make sure that whether an existing or new cvar is set to the given value.
|
queryObject->params[queryObject->paramLen - 1] = 0;
|
||||||
CVAR_DIRECTSET(var, value);
|
}
|
||||||
|
else {
|
||||||
|
queryObject->params = NULL;
|
||||||
|
queryObject->paramLen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return info->var;
|
pPlayer->queries.push_back(queryObject);
|
||||||
|
|
||||||
|
QUERY_CLIENT_CVAR_VALUE2(pPlayer->pEdict, cvarname, queryObject->requestId);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cvar_t* CvarManager::FindCvar(const char* name)
|
|
||||||
|
AMX_NATIVE_INFO g_CvarNatives[] =
|
||||||
{
|
{
|
||||||
cvar_t* var = nullptr;
|
{"register_cvar", register_cvar},
|
||||||
CvarInfo* info = nullptr;
|
{"cvar_exists", cvar_exists},
|
||||||
|
{"get_cvar_pointer", get_cvar_pointer},
|
||||||
|
|
||||||
// Do we have already cvar in cache?
|
{"hook_cvar_change", hook_cvar_change},
|
||||||
if (CacheLookup(name, &info))
|
{"enable_cvar_hook", enable_cvar_hook},
|
||||||
{
|
{"disable_cvar_hook", disable_cvar_hook},
|
||||||
return info->var;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cvar doesn't exist.
|
{"get_cvar_flags", get_cvar_flags},
|
||||||
if (!(var = CVAR_GET_POINTER(name)))
|
{"get_cvar_float", get_cvar_float},
|
||||||
{
|
{"get_cvar_num", get_cvar_num},
|
||||||
return nullptr;
|
{"get_cvar_string", get_cvar_string},
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new entry.
|
{"set_cvar_flags", set_cvar_flags},
|
||||||
info = new CvarInfo();
|
{"set_cvar_float", set_cvar_float},
|
||||||
info->var = var;
|
{"set_cvar_num", set_cvar_num},
|
||||||
info->name = name;
|
{"set_cvar_string", set_cvar_string},
|
||||||
info->plugin = "";
|
|
||||||
info->pluginId = -1;
|
|
||||||
info->amxmodx = false;
|
|
||||||
|
|
||||||
// Add entry in the caches.
|
{"get_pcvar_flags", get_pcvar_flags},
|
||||||
m_Cvars.append(info);
|
{"get_pcvar_float", get_pcvar_float},
|
||||||
m_Cache.insert(name, info);
|
{"get_pcvar_num", get_pcvar_num},
|
||||||
|
{"get_pcvar_string", get_pcvar_string},
|
||||||
|
|
||||||
return var;
|
{"set_pcvar_flags", set_pcvar_flags},
|
||||||
}
|
{"set_pcvar_float", set_pcvar_float},
|
||||||
|
{"set_pcvar_string", set_pcvar_string},
|
||||||
|
{"set_pcvar_num", set_pcvar_num},
|
||||||
|
|
||||||
CvarInfo* CvarManager::FindCvar(size_t index)
|
{"remove_cvar_flags", remove_cvar_flags},
|
||||||
{
|
|
||||||
// Used by get_plugins_cvar native.
|
|
||||||
// For compatibility, only cvars registered by AMXX are concerned.
|
|
||||||
|
|
||||||
size_t iter_id = 0;
|
{"get_plugins_cvar", get_plugins_cvar},
|
||||||
|
{"get_plugins_cvarsnum", get_plugins_cvarsnum},
|
||||||
for (CvarsList::iterator iter = m_Cvars.begin(); iter != m_Cvars.end(); iter++)
|
|
||||||
{
|
|
||||||
if (iter->amxmodx && iter_id++ == index)
|
|
||||||
{
|
|
||||||
return *(iter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CvarManager::CacheLookup(const char* name, CvarInfo** info)
|
|
||||||
{
|
|
||||||
return m_Cache.retrieve(name, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
Forward* CvarManager::HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback)
|
|
||||||
{
|
|
||||||
CvarInfo* info = nullptr;
|
|
||||||
|
|
||||||
// A cvar is guaranteed to be in cache if pointer is got from
|
|
||||||
// get_cvar_pointer and register_cvar natives. Though it might be
|
|
||||||
// provided by another way. If by any chance we run in such
|
|
||||||
// situation, we create a new entry right now.
|
|
||||||
|
|
||||||
if (!CacheLookup(var->name, &info))
|
|
||||||
{
|
|
||||||
// Create a new entry.
|
|
||||||
info = new CvarInfo();
|
|
||||||
info->var = var;
|
|
||||||
info->name = var->name;
|
|
||||||
info->plugin = "";
|
|
||||||
info->pluginId = -1;
|
|
||||||
info->amxmodx = false;
|
|
||||||
|
|
||||||
// Add entry in the caches.
|
|
||||||
m_Cvars.append(info);
|
|
||||||
m_Cache.insert(info->name.chars(), info);
|
|
||||||
}
|
|
||||||
|
|
||||||
int length;
|
|
||||||
*callback = get_amxstring(amx, param, 0, length);
|
|
||||||
|
|
||||||
int forwardId = registerSPForwardByName(amx, *callback, FP_CELL, FP_STRING, FP_STRING, FP_DONE);
|
|
||||||
|
|
||||||
// Invalid callback, it could be: not a public function, wrongly named, or simply missing.
|
|
||||||
if (forwardId == -1)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detour is disabled on map change.
|
|
||||||
m_HookDetour->EnableDetour();
|
|
||||||
|
|
||||||
Forward* forward = new Forward(forwardId, *callback);
|
{"query_client_cvar", query_client_cvar},
|
||||||
info->hooks.append(new CvarPlugin(g_plugins.findPlugin(amx)->getId(), forward));
|
|
||||||
|
|
||||||
return forward;
|
{NULL, NULL}
|
||||||
}
|
};
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CvarManager::OnPluginUnloaded()
|
|
||||||
{
|
|
||||||
// Clear only plugin hooks list.
|
|
||||||
for (CvarsList::iterator cvar = m_Cvars.begin(); cvar != m_Cvars.end(); cvar++)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < (*cvar)->hooks.length(); ++i)
|
|
||||||
{
|
|
||||||
delete (*cvar)->hooks[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
(*cvar)->hooks.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// There is no point to enable detour if at next map change
|
|
||||||
// no plugins hook cvars.
|
|
||||||
m_HookDetour->DisableDetour();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CvarManager::OnAmxxShutdown()
|
|
||||||
{
|
|
||||||
// Free everything.
|
|
||||||
for (CvarsList::iterator cvar = m_Cvars.begin(); cvar != m_Cvars.end(); cvar = m_Cvars.erase(cvar))
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < (*cvar)->hooks.length(); ++i)
|
|
||||||
{
|
|
||||||
delete (*cvar)->hooks[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
delete (*cvar);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Cache.clear();
|
|
||||||
m_HookDetour->Destroy();
|
|
||||||
}
|
|
|
@ -31,7 +31,7 @@
|
||||||
#include "trie_natives.h"
|
#include "trie_natives.h"
|
||||||
#include "CDataPack.h"
|
#include "CDataPack.h"
|
||||||
#include "textparse.h"
|
#include "textparse.h"
|
||||||
#include "cvars.h"
|
#include "CvarManager.h"
|
||||||
|
|
||||||
plugin_info_t Plugin_info =
|
plugin_info_t Plugin_info =
|
||||||
{
|
{
|
||||||
|
|
|
@ -553,6 +553,7 @@ int set_amxnatives(AMX* amx, char error[128])
|
||||||
amx_Register(amx, g_DatapackNatives, -1);
|
amx_Register(amx, g_DatapackNatives, -1);
|
||||||
amx_Register(amx, g_StackNatives, -1);
|
amx_Register(amx, g_StackNatives, -1);
|
||||||
amx_Register(amx, g_TextParserNatives, -1);
|
amx_Register(amx, g_TextParserNatives, -1);
|
||||||
|
amx_Register(amx, g_CvarNatives, -1);
|
||||||
|
|
||||||
//we're not actually gonna check these here anymore
|
//we're not actually gonna check these here anymore
|
||||||
amx->flags |= AMX_FLAG_PRENIT;
|
amx->flags |= AMX_FLAG_PRENIT;
|
||||||
|
|
|
@ -319,6 +319,7 @@
|
||||||
<ClCompile Include="..\CPlugin.cpp" />
|
<ClCompile Include="..\CPlugin.cpp" />
|
||||||
<ClCompile Include="..\CTask.cpp" />
|
<ClCompile Include="..\CTask.cpp" />
|
||||||
<ClCompile Include="..\CTextParsers.cpp" />
|
<ClCompile Include="..\CTextParsers.cpp" />
|
||||||
|
<ClCompile Include="..\CvarManager.cpp" />
|
||||||
<ClCompile Include="..\cvars.cpp" />
|
<ClCompile Include="..\cvars.cpp" />
|
||||||
<ClCompile Include="..\CVault.cpp" />
|
<ClCompile Include="..\CVault.cpp" />
|
||||||
<ClCompile Include="..\datapacks.cpp" />
|
<ClCompile Include="..\datapacks.cpp" />
|
||||||
|
@ -389,7 +390,7 @@
|
||||||
<ClInclude Include="..\CString.h" />
|
<ClInclude Include="..\CString.h" />
|
||||||
<ClInclude Include="..\CTask.h" />
|
<ClInclude Include="..\CTask.h" />
|
||||||
<ClInclude Include="..\CTextParsers.h" />
|
<ClInclude Include="..\CTextParsers.h" />
|
||||||
<ClInclude Include="..\cvars.h" />
|
<ClInclude Include="..\CvarManager.h" />
|
||||||
<ClInclude Include="..\CVault.h" />
|
<ClInclude Include="..\CVault.h" />
|
||||||
<ClInclude Include="..\CVector.h" />
|
<ClInclude Include="..\CVector.h" />
|
||||||
<ClInclude Include="..\datastructs.h" />
|
<ClInclude Include="..\datastructs.h" />
|
||||||
|
|
|
@ -192,15 +192,18 @@
|
||||||
<ClCompile Include="..\..\public\sdk\amxxmodule.cpp">
|
<ClCompile Include="..\..\public\sdk\amxxmodule.cpp">
|
||||||
<Filter>SDK</Filter>
|
<Filter>SDK</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\cvars.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\public\memtools\CDetour\detours.cpp">
|
<ClCompile Include="..\..\public\memtools\CDetour\detours.cpp">
|
||||||
<Filter>Memtools\CDetour</Filter>
|
<Filter>Memtools\CDetour</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\public\memtools\CDetour\asm\asm.c">
|
<ClCompile Include="..\..\public\memtools\CDetour\asm\asm.c">
|
||||||
<Filter>Memtools\CDetour\asm</Filter>
|
<Filter>Memtools\CDetour\asm</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\CvarManager.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\cvars.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\amx.h">
|
<ClInclude Include="..\amx.h">
|
||||||
|
@ -347,9 +350,6 @@
|
||||||
<ClInclude Include="..\..\public\sdk\moduleconfig.h">
|
<ClInclude Include="..\..\public\sdk\moduleconfig.h">
|
||||||
<Filter>SDK</Filter>
|
<Filter>SDK</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\cvars.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\public\memtools\CDetour\detourhelpers.h">
|
<ClInclude Include="..\..\public\memtools\CDetour\detourhelpers.h">
|
||||||
<Filter>Memtools\CDetour</Filter>
|
<Filter>Memtools\CDetour</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -359,6 +359,9 @@
|
||||||
<ClInclude Include="..\..\public\memtools\CDetour\asm\asm.h">
|
<ClInclude Include="..\..\public\memtools\CDetour\asm\asm.h">
|
||||||
<Filter>Memtools\CDetour\asm</Filter>
|
<Filter>Memtools\CDetour\asm</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\CvarManager.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="..\version.rc">
|
<ResourceCompile Include="..\version.rc">
|
||||||
|
|
|
@ -30,3 +30,19 @@ NONGPL_CVAR_T NONGPL_CVAR_LIST[] =
|
||||||
{"amx_gg", 1},
|
{"amx_gg", 1},
|
||||||
{NULL, 0},
|
{NULL, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool CheckBadConList(const char *cvar, int type)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (NONGPL_CVAR_LIST[i].cvar != NULL)
|
||||||
|
{
|
||||||
|
if (NONGPL_CVAR_LIST[i].type == type
|
||||||
|
&& strcmp(NONGPL_CVAR_LIST[i].cvar, cvar) == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -25,5 +25,6 @@ struct NONGPL_CVAR_T
|
||||||
|
|
||||||
extern NONGPL_PLUGIN_T NONGPL_PLUGIN_LIST[];
|
extern NONGPL_PLUGIN_T NONGPL_PLUGIN_LIST[];
|
||||||
extern NONGPL_CVAR_T NONGPL_CVAR_LIST[];
|
extern NONGPL_CVAR_T NONGPL_CVAR_LIST[];
|
||||||
|
extern bool CheckBadConList(const char *cvar, int type);
|
||||||
|
|
||||||
#endif //_INCLUDE_AMXMODX_NONGPL_MATCHES_H_
|
#endif //_INCLUDE_AMXMODX_NONGPL_MATCHES_H_
|
||||||
|
|
|
@ -105,20 +105,6 @@ public stock const MaxClients; /* Maximum number of players the server supports
|
||||||
#define PLUGIN_HANDLED 1 /* stop other plugins */
|
#define PLUGIN_HANDLED 1 /* stop other plugins */
|
||||||
#define PLUGIN_HANDLED_MAIN 2 /* to use in client_command(), continue all plugins but stop the command */
|
#define PLUGIN_HANDLED_MAIN 2 /* to use in client_command(), continue all plugins but stop the command */
|
||||||
|
|
||||||
/**
|
|
||||||
* CVAR flags for register_cvar()
|
|
||||||
*/
|
|
||||||
#define FCVAR_ARCHIVE 1 /* Set to cause it to be saved to vars.rc */
|
|
||||||
#define FCVAR_USERINFO 2 /* Changes the client's info string */
|
|
||||||
#define FCVAR_SERVER 4 /* Notifies players when changed */
|
|
||||||
#define FCVAR_EXTDLL 8 /* Defined by external DLL */
|
|
||||||
#define FCVAR_CLIENTDLL 16 /* Defined by the client dll */
|
|
||||||
#define FCVAR_PROTECTED 32 /* It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value */
|
|
||||||
#define FCVAR_SPONLY 64 /* This cvar cannot be changed by clients connected to a multiplayer server. */
|
|
||||||
#define FCVAR_PRINTABLEONLY 128 /* This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ). */
|
|
||||||
#define FCVAR_UNLOGGED 256 /* If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log */
|
|
||||||
#define FCVAR_NOEXTRAWHITEPACE 512 /* Strip trailing/leading white space from this cvar */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IDs of weapons in CS
|
* IDs of weapons in CS
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1404,159 +1404,6 @@ native amxclient_cmd(index, const command[], const arg1[]="", const arg2[]="");
|
||||||
*/
|
*/
|
||||||
native server_cmd(const command[], any:...);
|
native server_cmd(const command[], any:...);
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a cvar to a given string value. The cvar is accessed by name.
|
|
||||||
*
|
|
||||||
* @note Accessing a cvar by name requires this function to walk through the
|
|
||||||
* engine's cvar list every time, which can result in a considerable waste
|
|
||||||
* of processing time, especially if many cvars have been registered. For
|
|
||||||
* a vastly superior alternative look at the set_pcvar_string function.
|
|
||||||
*
|
|
||||||
* @param cvar Cvar name to set value of
|
|
||||||
* @param value Value to set cvar to
|
|
||||||
*
|
|
||||||
* @noreturn
|
|
||||||
*/
|
|
||||||
native set_cvar_string(const cvar[], const value[]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns if a cvar is registered on the server.
|
|
||||||
*
|
|
||||||
* @param cvar Cvar name to check
|
|
||||||
*
|
|
||||||
* @return 1 if the cvar exists, 0 otherwise
|
|
||||||
*/
|
|
||||||
native cvar_exists(const cvar[]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes specified flags from a cvar. The cvar is accessed by name.
|
|
||||||
*
|
|
||||||
* @note Not permitted for the "amx_version", "amxmodx_version", "fun_version"
|
|
||||||
* and "sv_cheats" cvars.
|
|
||||||
* @note For a list of possible flags see the FCVAR_* constants in amxconst.inc
|
|
||||||
* @note This function removes the flags using a bitwise-and operation.
|
|
||||||
* @note Accessing a Cvar by name requires this function to walk through the
|
|
||||||
* engine's cvar list every time, which can result in a considerable waste
|
|
||||||
* of processing time, especially if many cvars have been registered. For
|
|
||||||
* a vastly superior alternative look at the set_pcvar_flags function.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param cvar Cvar name to remove flags from
|
|
||||||
* @param flags Bitflag sum of flags to remove
|
|
||||||
*
|
|
||||||
* @return 1 on success, 0 if cvar does not exist or is not permitted
|
|
||||||
*/
|
|
||||||
native remove_cvar_flags(const cvar[], flags=-1);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets specified flags to a cvar. The cvar is accessed by name.
|
|
||||||
*
|
|
||||||
* @note Not permitted for the "amx_version", "amxmodx_version", "fun_version"
|
|
||||||
* and "sv_cheats" cvars.
|
|
||||||
* @note For a list of possible flags see the FCVAR_* constants in amxconst.inc
|
|
||||||
* @note This function just adds the flags using a bitwise-or operation. After
|
|
||||||
* it has run the flags may not exactly equal the specified bitflag sum.
|
|
||||||
* @note Accessing a Cvar by name requires this function to walk through the
|
|
||||||
* engine's cvar list every time, which can result in a considerable waste
|
|
||||||
* of processing time, especially if many cvars have been registered. For
|
|
||||||
* a vastly superior alternative look at the set_pcvar_flags function.
|
|
||||||
*
|
|
||||||
* @param cvar Cvar name to remove flags from
|
|
||||||
* @param flags Bitflag sum of flags to set
|
|
||||||
*
|
|
||||||
* @return 1 on success, 0 if cvar does not exist or is not permitted
|
|
||||||
*/
|
|
||||||
native set_cvar_flags(const cvar[], flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns flags of a cvar. The cvar is accessed by name.
|
|
||||||
*
|
|
||||||
* @note For a list of possible flags see the FCVAR_* constants in amxconst.inc
|
|
||||||
* @note Accessing a Cvar by name requires this function to walk through the
|
|
||||||
* engine's cvar list every time, which can result in a considerable waste
|
|
||||||
* of processing time, especially if many cvars have been registered. For
|
|
||||||
* a vastly superior alternative look at the get_pcvar_flags function.
|
|
||||||
*
|
|
||||||
* @param cvar Cvar name to retrieve flags from
|
|
||||||
*
|
|
||||||
* @return 1 on success, 0 if cvar does not exist or is not permitted
|
|
||||||
*/
|
|
||||||
native get_cvar_flags(const cvar[]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a cvar to a given float value. The cvar is accessed by name.
|
|
||||||
*
|
|
||||||
* @note Accessing a Cvar by name requires this function to walk through the
|
|
||||||
* engine's cvar list every time, which can result in a considerable waste
|
|
||||||
* of processing time, especially if many cvars have been registered. For
|
|
||||||
* a vastly superior alternative look at the set_pcvar_float function.
|
|
||||||
*
|
|
||||||
* @param cvar Cvar name to set value of
|
|
||||||
* @param value Value to set cvar to
|
|
||||||
*
|
|
||||||
* @noreturn
|
|
||||||
*/
|
|
||||||
native set_cvar_float(const cvar[], Float:value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a floating value from a cvar. The cvar is accessed by name.
|
|
||||||
*
|
|
||||||
* @note Accessing a Cvar by name requires this function to walk through the
|
|
||||||
* engine's cvar list every time, which can result in a considerable waste
|
|
||||||
* of processing time, especially if many cvars have been registered. For
|
|
||||||
* a vastly superior alternative look at the get_pcvar_float function.
|
|
||||||
*
|
|
||||||
* @param cvarname Cvar name to retrieve value from
|
|
||||||
*
|
|
||||||
* @return Cvar value, converted to float
|
|
||||||
*/
|
|
||||||
native Float:get_cvar_float(const cvarname[]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an integer value from a cvar. The cvar is accessed by name.
|
|
||||||
*
|
|
||||||
* @note Accessing a Cvar by name requires this function to walk through the
|
|
||||||
* engine's cvar list every time, which can result in a considerable waste
|
|
||||||
* of processing time, especially if many cvars have been registered. For
|
|
||||||
* a vastly superior alternative look at the get_pcvar_num function.
|
|
||||||
*
|
|
||||||
* @param cvarname Cvar name to retrieve value from
|
|
||||||
*
|
|
||||||
* @return Cvar value, converted to int
|
|
||||||
*/
|
|
||||||
native get_cvar_num(const cvarname[]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a cvar to a given integer value. The cvar is accessed by name.
|
|
||||||
*
|
|
||||||
* @note Accessing a Cvar by name requires this function to walk through the
|
|
||||||
* engine's cvar list every time, which can result in a considerable waste
|
|
||||||
* of processing time, especially if many cvars have been registered. For
|
|
||||||
* a vastly superior alternative look at the set_pcvar_num function.
|
|
||||||
*
|
|
||||||
* @param cvar Cvar name to set value of
|
|
||||||
* @param value Value to set cvar to
|
|
||||||
*
|
|
||||||
* @noreturn
|
|
||||||
*/
|
|
||||||
native set_cvar_num(const cvarname[], value);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a string value from a cvar. The cvar is accessed by name.
|
|
||||||
*
|
|
||||||
* @note Accessing a Cvar by name requires this function to walk through the
|
|
||||||
* engine's cvar list every time, which can result in a considerable waste
|
|
||||||
* of processing time, especially if many cvars have been registered. For
|
|
||||||
* a vastly superior alternative look at the get_pcvar_string function.
|
|
||||||
*
|
|
||||||
* @param cvar Cvar name to retrieve value from
|
|
||||||
* @param output Buffer to copy cvar value to
|
|
||||||
* @param iLen Maximum size of the buffer
|
|
||||||
*
|
|
||||||
* @return Number of cells written to buffer.
|
|
||||||
*/
|
|
||||||
native get_cvar_string(const cvarname[], output[], iLen);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the name of the currently played map.
|
* Retrieves the name of the currently played map.
|
||||||
*
|
*
|
||||||
|
@ -1964,31 +1811,6 @@ native get_concmd_plid(cid, flag_mask, id_type);
|
||||||
*/
|
*/
|
||||||
native get_concmdsnum(flag, id=-1);
|
native get_concmdsnum(flag, id=-1);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of plugin-registered cvars.
|
|
||||||
*
|
|
||||||
* @return Number of registered cvars
|
|
||||||
*/
|
|
||||||
native get_plugins_cvarsnum();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves information about a plugin-registered cvar.
|
|
||||||
*
|
|
||||||
* @note The returned cvar pointer should be used with the get_pcvar_* and
|
|
||||||
* set_pcvar_* set of functions.
|
|
||||||
*
|
|
||||||
* @param num Cvar index, this does not equal the cvar pointer, it is
|
|
||||||
* the internal index, incremented for each registered cvar
|
|
||||||
* @param name Buffer to copy cvar name to
|
|
||||||
* @param namelen Maximum buffer size
|
|
||||||
* @param flags Variable to store cvar flags to
|
|
||||||
* @param plugin_id Variable to store id of the registering plugin to
|
|
||||||
* @param pcvar_handle Variable to store cvar pointer to
|
|
||||||
*
|
|
||||||
* @return 1 on success, 0 if index is invalid
|
|
||||||
*/
|
|
||||||
native get_plugins_cvar(num, name[], namelen, &flags=0, &plugin_id=0, &pcvar_handle=0);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns unique menu id of a menu.
|
* Returns unique menu id of a menu.
|
||||||
*
|
*
|
||||||
|
@ -2058,23 +1880,6 @@ native server_exec();
|
||||||
*/
|
*/
|
||||||
native emit_sound(index, channel, const sample[], Float:vol, Float:att, flags, pitch);
|
native emit_sound(index, channel, const sample[], Float:vol, Float:att, flags, pitch);
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers a new cvar for the engine.
|
|
||||||
*
|
|
||||||
* @note For a list of possible cvar flags see FCVAR_* constants in amxconst.inc
|
|
||||||
* @note If an already existing cvar is registered it will not be duplicated.
|
|
||||||
* @note The returned cvar pointer should be used with the get_pcvar_* and
|
|
||||||
* set_pcvar_* set of functions.
|
|
||||||
*
|
|
||||||
* @param name Cvar name
|
|
||||||
* @param string Default cvar value
|
|
||||||
* @param flags Cvar flags
|
|
||||||
* @param fvalue Unused
|
|
||||||
*
|
|
||||||
* @return Unique cvar pointer
|
|
||||||
*/
|
|
||||||
native register_cvar(const name[], const string[], flags=0, Float:fvalue=0.0);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a random floating point value generated by the engine.
|
* Returns a random floating point value generated by the engine.
|
||||||
*
|
*
|
||||||
|
@ -2806,35 +2611,6 @@ native set_array(param, const source[], size);
|
||||||
*/
|
*/
|
||||||
native set_array_f(param, const Float:source[], size);
|
native set_array_f(param, const Float:source[], size);
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches a client cvar query, allowing the plugin to query for its value on
|
|
||||||
* the client.
|
|
||||||
*
|
|
||||||
* @note The callback will be called in the following manner:
|
|
||||||
*
|
|
||||||
* public cvar_query_callback(id, const cvar[], const value[], const param[])
|
|
||||||
*
|
|
||||||
* id - Client index
|
|
||||||
* cvar - Cvar queried
|
|
||||||
* value - Cvar value on the client
|
|
||||||
* param - Extra data [optional]
|
|
||||||
*
|
|
||||||
* @param id Client index
|
|
||||||
* @param cvar Cvar to query
|
|
||||||
* @param resultFunc Callback function
|
|
||||||
* @param paramlen Size of extra data
|
|
||||||
* @param params Extra data to pass through to callback
|
|
||||||
*
|
|
||||||
* @noreturn
|
|
||||||
* @error If the client index is not within the range of 1 to
|
|
||||||
* MaxClients or the client is not connected, an error
|
|
||||||
* will be thrown.
|
|
||||||
* If the callback function is invalid, cvar querying is
|
|
||||||
* unavailable or the querying process runs out of memory,
|
|
||||||
* an error will be thrown.
|
|
||||||
*/
|
|
||||||
native query_client_cvar(id, const cvar[], const resultFunc[], paramlen=0, const params[]="");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows to trap error messages that occur in a plugin.
|
* Allows to trap error messages that occur in a plugin.
|
||||||
*
|
*
|
||||||
|
@ -3220,110 +2996,6 @@ native ExecuteForward(forward_handle, &ret, any:...);
|
||||||
*/
|
*/
|
||||||
native DestroyForward(forward_handle);
|
native DestroyForward(forward_handle);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the cvar pointer of the specified cvar.
|
|
||||||
*
|
|
||||||
* @note A pointer is also returned by register_cvar(). Plugins can (and should)
|
|
||||||
* retrieve and use pointers for already existing mod cvars.
|
|
||||||
*
|
|
||||||
* @param cvar Cvar name to find
|
|
||||||
*
|
|
||||||
* @return Cvar pointer on success, 0 if cvar was not found
|
|
||||||
*/
|
|
||||||
native get_cvar_pointer(const cvar[]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns flags of a cvar via direct pointer access.
|
|
||||||
*
|
|
||||||
* @note For a list of possible flags see the FCVAR_* constants in amxconst.inc
|
|
||||||
*
|
|
||||||
* @param pcvar Pointer to cvar to retrieve flags from
|
|
||||||
*
|
|
||||||
* @return 1 on success, 0 if cvar pointer is invalid
|
|
||||||
* @error If an invalid cvar pointer is specified, an error is thrown.
|
|
||||||
*/
|
|
||||||
native get_pcvar_flags(pcvar);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets specified flags to a cvar via direct pointer access.
|
|
||||||
*
|
|
||||||
* @note For a list of possible flags see the FCVAR_* constants in amxconst.inc
|
|
||||||
* @note This function directly sets the provided bitflag, unlike set_cvar_flags
|
|
||||||
* which adds them using a bitwise OR.
|
|
||||||
*
|
|
||||||
* @param pcvar Pointer to cvar to set flags of
|
|
||||||
* @param flags Bitflag sum of flags to set
|
|
||||||
*
|
|
||||||
* @return 1 on success, 0 if cvar does not exist or is not permitted
|
|
||||||
* @error If an invalid cvar pointer is specified, an error is thrown.
|
|
||||||
*/
|
|
||||||
native set_pcvar_flags(pcvar, flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an integer value from a cvar via direct pointer access.
|
|
||||||
*
|
|
||||||
* @param pcvar Pointer to cvar to retrieve value from
|
|
||||||
*
|
|
||||||
* @return Cvar value, converted to int
|
|
||||||
* @error If an invalid cvar pointer is specified, an error is thrown.
|
|
||||||
*/
|
|
||||||
native get_pcvar_num(pcvar);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets an integer value to a cvar via direct pointer access.
|
|
||||||
*
|
|
||||||
* @param pcvar Pointer to cvar to set value of
|
|
||||||
* @param num Value to set cvar to
|
|
||||||
*
|
|
||||||
* @noreturn
|
|
||||||
* @error If an invalid cvar pointer is specified, an error is thrown.
|
|
||||||
*/
|
|
||||||
native set_pcvar_num(pcvar, num);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a float value from a cvar via direct pointer access.
|
|
||||||
*
|
|
||||||
* @param pcvar Pointer to cvar to retrieve value from
|
|
||||||
*
|
|
||||||
* @return Cvar value, converted to float
|
|
||||||
* @error If an invalid cvar pointer is specified, an error is thrown.
|
|
||||||
*/
|
|
||||||
native Float:get_pcvar_float(pcvar);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a float value to a cvar via direct pointer access.
|
|
||||||
*
|
|
||||||
* @param pcvar Pointer to cvar to set value of
|
|
||||||
* @param num Value to set cvar to
|
|
||||||
*
|
|
||||||
* @noreturn
|
|
||||||
* @error If an invalid cvar pointer is specified, an error is thrown.
|
|
||||||
*/
|
|
||||||
native set_pcvar_float(pcvar, Float:num);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a string value from a cvar via direct pointer access.
|
|
||||||
*
|
|
||||||
* @param pcvar Pointer to cvar to retrieve value from
|
|
||||||
* @param string Buffer to copy cvar value to
|
|
||||||
* @param maxlen Maximum size of the buffer
|
|
||||||
*
|
|
||||||
* @return Number of cells written to buffer.
|
|
||||||
* @error If an invalid cvar pointer is specified, an error is thrown.
|
|
||||||
*/
|
|
||||||
native get_pcvar_string(pcvar, string[], maxlen);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a string value to a cvar via direct pointer access.
|
|
||||||
*
|
|
||||||
* @param pcvar Pointer to cvar to retrieve value from
|
|
||||||
* @param string Value to set cvar to
|
|
||||||
*
|
|
||||||
* @noreturn
|
|
||||||
* @error If an invalid cvar pointer is specified, an error is thrown.
|
|
||||||
*/
|
|
||||||
native set_pcvar_string(pcvar, const string[]);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets all elements of array to a specified value.
|
* Sets all elements of array to a specified value.
|
||||||
*
|
*
|
||||||
|
|
|
@ -12,6 +12,58 @@
|
||||||
#endif
|
#endif
|
||||||
#define _cvars_included
|
#define _cvars_included
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CVAR flags for register_cvar()
|
||||||
|
*/
|
||||||
|
#define FCVAR_ARCHIVE 1 /* Set to cause it to be saved to vars.rc */
|
||||||
|
#define FCVAR_USERINFO 2 /* Changes the client's info string */
|
||||||
|
#define FCVAR_SERVER 4 /* Notifies players when changed */
|
||||||
|
#define FCVAR_EXTDLL 8 /* Defined by external DLL */
|
||||||
|
#define FCVAR_CLIENTDLL 16 /* Defined by the client dll */
|
||||||
|
#define FCVAR_PROTECTED 32 /* It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value */
|
||||||
|
#define FCVAR_SPONLY 64 /* This cvar cannot be changed by clients connected to a multiplayer server. */
|
||||||
|
#define FCVAR_PRINTABLEONLY 128 /* This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ). */
|
||||||
|
#define FCVAR_UNLOGGED 256 /* If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log */
|
||||||
|
#define FCVAR_NOEXTRAWHITEPACE 512 /* Strip trailing/leading white space from this cvar */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a new cvar for the engine.
|
||||||
|
*
|
||||||
|
* @note For a list of possible cvar flags see FCVAR_* constants in amxconst.inc
|
||||||
|
* @note If an already existing cvar is registered it will not be duplicated.
|
||||||
|
* @note The returned cvar pointer should be used with the get_pcvar_* and
|
||||||
|
* set_pcvar_* set of functions.
|
||||||
|
*
|
||||||
|
* @param name Cvar name
|
||||||
|
* @param string Default cvar value
|
||||||
|
* @param flags Cvar flags
|
||||||
|
* @param fvalue Unused
|
||||||
|
*
|
||||||
|
* @return Unique cvar pointer
|
||||||
|
*/
|
||||||
|
native register_cvar(const name[], const string[], flags=0, Float:fvalue=0.0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if a cvar is registered on the server.
|
||||||
|
*
|
||||||
|
* @param cvar Cvar name to check
|
||||||
|
*
|
||||||
|
* @return 1 if the cvar exists, 0 otherwise
|
||||||
|
*/
|
||||||
|
native cvar_exists(const cvar[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cvar pointer of the specified cvar.
|
||||||
|
*
|
||||||
|
* @note A pointer is also returned by register_cvar(). Plugins can (and should)
|
||||||
|
* retrieve and use pointers for already existing mod cvars.
|
||||||
|
*
|
||||||
|
* @param cvar Cvar name to find
|
||||||
|
*
|
||||||
|
* @return Cvar pointer on success, 0 if cvar was not found
|
||||||
|
*/
|
||||||
|
native get_cvar_pointer(const cvar[]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a hook for when a console variable's value is changed.
|
* Creates a hook for when a console variable's value is changed.
|
||||||
*
|
*
|
||||||
|
@ -49,4 +101,292 @@ native disable_cvar_hook(cvarhook:handle);
|
||||||
*/
|
*/
|
||||||
native enable_cvar_hook(cvarhook:handle);
|
native enable_cvar_hook(cvarhook:handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns flags of a cvar. The cvar is accessed by name.
|
||||||
|
*
|
||||||
|
* @note For a list of possible flags see the FCVAR_* constants in amxconst.inc
|
||||||
|
* @note Accessing a Cvar by name requires this function to walk through the
|
||||||
|
* engine's cvar list every time, which can result in a considerable waste
|
||||||
|
* of processing time, especially if many cvars have been registered. For
|
||||||
|
* a vastly superior alternative look at the get_pcvar_flags function.
|
||||||
|
*
|
||||||
|
* @param cvar Cvar name to retrieve flags from
|
||||||
|
*
|
||||||
|
* @return 1 on success, 0 if cvar does not exist or is not permitted
|
||||||
|
*/
|
||||||
|
native get_cvar_flags(const cvar[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets specified flags to a cvar. The cvar is accessed by name.
|
||||||
|
*
|
||||||
|
* @note Not permitted for the "amx_version", "amxmodx_version", "fun_version"
|
||||||
|
* and "sv_cheats" cvars.
|
||||||
|
* @note For a list of possible flags see the FCVAR_* constants in amxconst.inc
|
||||||
|
* @note This function just adds the flags using a bitwise-or operation. After
|
||||||
|
* it has run the flags may not exactly equal the specified bitflag sum.
|
||||||
|
* @note Accessing a Cvar by name requires this function to walk through the
|
||||||
|
* engine's cvar list every time, which can result in a considerable waste
|
||||||
|
* of processing time, especially if many cvars have been registered. For
|
||||||
|
* a vastly superior alternative look at the set_pcvar_flags function.
|
||||||
|
*
|
||||||
|
* @param cvar Cvar name to remove flags from
|
||||||
|
* @param flags Bitflag sum of flags to set
|
||||||
|
*
|
||||||
|
* @return 1 on success, 0 if cvar does not exist or is not permitted
|
||||||
|
*/
|
||||||
|
native set_cvar_flags(const cvar[], flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes specified flags from a cvar. The cvar is accessed by name.
|
||||||
|
*
|
||||||
|
* @note Not permitted for the "amx_version", "amxmodx_version", "fun_version"
|
||||||
|
* and "sv_cheats" cvars.
|
||||||
|
* @note For a list of possible flags see the FCVAR_* constants in amxconst.inc
|
||||||
|
* @note This function removes the flags using a bitwise-and operation.
|
||||||
|
* @note Accessing a Cvar by name requires this function to walk through the
|
||||||
|
* engine's cvar list every time, which can result in a considerable waste
|
||||||
|
* of processing time, especially if many cvars have been registered. For
|
||||||
|
* a vastly superior alternative look at the set_pcvar_flags function.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param cvar Cvar name to remove flags from
|
||||||
|
* @param flags Bitflag sum of flags to remove
|
||||||
|
*
|
||||||
|
* @return 1 on success, 0 if cvar does not exist or is not permitted
|
||||||
|
*/
|
||||||
|
native remove_cvar_flags(const cvar[], flags=-1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a string value from a cvar. The cvar is accessed by name.
|
||||||
|
*
|
||||||
|
* @note Accessing a Cvar by name requires this function to walk through the
|
||||||
|
* engine's cvar list every time, which can result in a considerable waste
|
||||||
|
* of processing time, especially if many cvars have been registered. For
|
||||||
|
* a vastly superior alternative look at the get_pcvar_string function.
|
||||||
|
*
|
||||||
|
* @param cvar Cvar name to retrieve value from
|
||||||
|
* @param output Buffer to copy cvar value to
|
||||||
|
* @param iLen Maximum size of the buffer
|
||||||
|
*
|
||||||
|
* @return Number of cells written to buffer.
|
||||||
|
*/
|
||||||
|
native get_cvar_string(const cvarname[], output[], iLen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a cvar to a given string value. The cvar is accessed by name.
|
||||||
|
*
|
||||||
|
* @note Accessing a cvar by name requires this function to walk through the
|
||||||
|
* engine's cvar list every time, which can result in a considerable waste
|
||||||
|
* of processing time, especially if many cvars have been registered. For
|
||||||
|
* a vastly superior alternative look at the set_pcvar_string function.
|
||||||
|
*
|
||||||
|
* @param cvar Cvar name to set value of
|
||||||
|
* @param value Value to set cvar to
|
||||||
|
*
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
native set_cvar_string(const cvar[], const value[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a floating value from a cvar. The cvar is accessed by name.
|
||||||
|
*
|
||||||
|
* @note Accessing a Cvar by name requires this function to walk through the
|
||||||
|
* engine's cvar list every time, which can result in a considerable waste
|
||||||
|
* of processing time, especially if many cvars have been registered. For
|
||||||
|
* a vastly superior alternative look at the get_pcvar_float function.
|
||||||
|
*
|
||||||
|
* @param cvarname Cvar name to retrieve value from
|
||||||
|
*
|
||||||
|
* @return Cvar value, converted to float
|
||||||
|
*/
|
||||||
|
native Float:get_cvar_float(const cvarname[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a cvar to a given float value. The cvar is accessed by name.
|
||||||
|
*
|
||||||
|
* @note Accessing a Cvar by name requires this function to walk through the
|
||||||
|
* engine's cvar list every time, which can result in a considerable waste
|
||||||
|
* of processing time, especially if many cvars have been registered. For
|
||||||
|
* a vastly superior alternative look at the set_pcvar_float function.
|
||||||
|
*
|
||||||
|
* @param cvar Cvar name to set value of
|
||||||
|
* @param value Value to set cvar to
|
||||||
|
*
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
native set_cvar_float(const cvar[], Float:value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an integer value from a cvar. The cvar is accessed by name.
|
||||||
|
*
|
||||||
|
* @note Accessing a Cvar by name requires this function to walk through the
|
||||||
|
* engine's cvar list every time, which can result in a considerable waste
|
||||||
|
* of processing time, especially if many cvars have been registered. For
|
||||||
|
* a vastly superior alternative look at the get_pcvar_num function.
|
||||||
|
*
|
||||||
|
* @param cvarname Cvar name to retrieve value from
|
||||||
|
*
|
||||||
|
* @return Cvar value, converted to int
|
||||||
|
*/
|
||||||
|
native get_cvar_num(const cvarname[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a cvar to a given integer value. The cvar is accessed by name.
|
||||||
|
*
|
||||||
|
* @note Accessing a Cvar by name requires this function to walk through the
|
||||||
|
* engine's cvar list every time, which can result in a considerable waste
|
||||||
|
* of processing time, especially if many cvars have been registered. For
|
||||||
|
* a vastly superior alternative look at the set_pcvar_num function.
|
||||||
|
*
|
||||||
|
* @param cvar Cvar name to set value of
|
||||||
|
* @param value Value to set cvar to
|
||||||
|
*
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
native set_cvar_num(const cvarname[], value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns flags of a cvar via direct pointer access.
|
||||||
|
*
|
||||||
|
* @note For a list of possible flags see the FCVAR_* constants in amxconst.inc
|
||||||
|
*
|
||||||
|
* @param pcvar Pointer to cvar to retrieve flags from
|
||||||
|
*
|
||||||
|
* @return 1 on success, 0 if cvar pointer is invalid
|
||||||
|
* @error If an invalid cvar pointer is specified, an error is thrown.
|
||||||
|
*/
|
||||||
|
native get_pcvar_flags(pcvar);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets specified flags to a cvar via direct pointer access.
|
||||||
|
*
|
||||||
|
* @note For a list of possible flags see the FCVAR_* constants in amxconst.inc
|
||||||
|
* @note This function directly sets the provided bitflag, unlike set_cvar_flags
|
||||||
|
* which adds them using a bitwise OR.
|
||||||
|
*
|
||||||
|
* @param pcvar Pointer to cvar to set flags of
|
||||||
|
* @param flags Bitflag sum of flags to set
|
||||||
|
*
|
||||||
|
* @return 1 on success, 0 if cvar does not exist or is not permitted
|
||||||
|
* @error If an invalid cvar pointer is specified, an error is thrown.
|
||||||
|
*/
|
||||||
|
native set_pcvar_flags(pcvar, flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an integer value from a cvar via direct pointer access.
|
||||||
|
*
|
||||||
|
* @param pcvar Pointer to cvar to retrieve value from
|
||||||
|
*
|
||||||
|
* @return Cvar value, converted to int
|
||||||
|
* @error If an invalid cvar pointer is specified, an error is thrown.
|
||||||
|
*/
|
||||||
|
native get_pcvar_num(pcvar);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an integer value to a cvar via direct pointer access.
|
||||||
|
*
|
||||||
|
* @param pcvar Pointer to cvar to set value of
|
||||||
|
* @param num Value to set cvar to
|
||||||
|
*
|
||||||
|
* @noreturn
|
||||||
|
* @error If an invalid cvar pointer is specified, an error is thrown.
|
||||||
|
*/
|
||||||
|
native set_pcvar_num(pcvar, num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a float value from a cvar via direct pointer access.
|
||||||
|
*
|
||||||
|
* @param pcvar Pointer to cvar to retrieve value from
|
||||||
|
*
|
||||||
|
* @return Cvar value, converted to float
|
||||||
|
* @error If an invalid cvar pointer is specified, an error is thrown.
|
||||||
|
*/
|
||||||
|
native Float:get_pcvar_float(pcvar);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a float value to a cvar via direct pointer access.
|
||||||
|
*
|
||||||
|
* @param pcvar Pointer to cvar to set value of
|
||||||
|
* @param num Value to set cvar to
|
||||||
|
*
|
||||||
|
* @noreturn
|
||||||
|
* @error If an invalid cvar pointer is specified, an error is thrown.
|
||||||
|
*/
|
||||||
|
native set_pcvar_float(pcvar, Float:num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string value from a cvar via direct pointer access.
|
||||||
|
*
|
||||||
|
* @param pcvar Pointer to cvar to retrieve value from
|
||||||
|
* @param string Buffer to copy cvar value to
|
||||||
|
* @param maxlen Maximum size of the buffer
|
||||||
|
*
|
||||||
|
* @return Number of cells written to buffer.
|
||||||
|
* @error If an invalid cvar pointer is specified, an error is thrown.
|
||||||
|
*/
|
||||||
|
native get_pcvar_string(pcvar, string[], maxlen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a string value to a cvar via direct pointer access.
|
||||||
|
*
|
||||||
|
* @param pcvar Pointer to cvar to retrieve value from
|
||||||
|
* @param string Value to set cvar to
|
||||||
|
*
|
||||||
|
* @noreturn
|
||||||
|
* @error If an invalid cvar pointer is specified, an error is thrown.
|
||||||
|
*/
|
||||||
|
native set_pcvar_string(pcvar, const string[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of plugin-registered cvars.
|
||||||
|
*
|
||||||
|
* @return Number of registered cvars
|
||||||
|
*/
|
||||||
|
native get_plugins_cvarsnum();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves information about a plugin-registered cvar.
|
||||||
|
*
|
||||||
|
* @note The returned cvar pointer should be used with the get_pcvar_* and
|
||||||
|
* set_pcvar_* set of functions.
|
||||||
|
*
|
||||||
|
* @param num Cvar index, this does not equal the cvar pointer, it is
|
||||||
|
* the internal index, incremented for each registered cvar
|
||||||
|
* @param name Buffer to copy cvar name to
|
||||||
|
* @param namelen Maximum buffer size
|
||||||
|
* @param flags Variable to store cvar flags to
|
||||||
|
* @param plugin_id Variable to store id of the registering plugin to
|
||||||
|
* @param pcvar_handle Variable to store cvar pointer to
|
||||||
|
*
|
||||||
|
* @return 1 on success, 0 if index is invalid
|
||||||
|
*/
|
||||||
|
native get_plugins_cvar(num, name[], namelen, &flags=0, &plugin_id=0, &pcvar_handle=0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches a client cvar query, allowing the plugin to query for its value on
|
||||||
|
* the client.
|
||||||
|
*
|
||||||
|
* @note The callback will be called in the following manner:
|
||||||
|
*
|
||||||
|
* public cvar_query_callback(id, const cvar[], const value[], const param[])
|
||||||
|
*
|
||||||
|
* id - Client index
|
||||||
|
* cvar - Cvar queried
|
||||||
|
* value - Cvar value on the client
|
||||||
|
* param - Extra data [optional]
|
||||||
|
*
|
||||||
|
* @param id Client index
|
||||||
|
* @param cvar Cvar to query
|
||||||
|
* @param resultFunc Callback function
|
||||||
|
* @param paramlen Size of extra data
|
||||||
|
* @param params Extra data to pass through to callback
|
||||||
|
*
|
||||||
|
* @noreturn
|
||||||
|
* @error If the client index is not within the range of 1 to
|
||||||
|
* MaxClients or the client is not connected, an error
|
||||||
|
* will be thrown.
|
||||||
|
* If the callback function is invalid, cvar querying is
|
||||||
|
* unavailable or the querying process runs out of memory,
|
||||||
|
* an error will be thrown.
|
||||||
|
*/
|
||||||
|
native query_client_cvar(id, const cvar[], const resultFunc[], paramlen=0, const params[]="");
|
Loading…
Reference in New Issue
Block a user