Merge pull request #185 from Arkshine/feature/hooking-cvars
Introduce new features for cvars
This commit is contained in:
commit
7d084ee0bf
|
@ -96,6 +96,10 @@ binary.sources = [
|
|||
'stackstructs.cpp',
|
||||
'CTextParsers.cpp',
|
||||
'textparse.cpp',
|
||||
'CvarManager.cpp',
|
||||
'cvars.cpp',
|
||||
'../public/memtools/CDetour/detours.cpp',
|
||||
'../public/memtools/CDetour/asm/asm.c',
|
||||
]
|
||||
|
||||
if builder.target_platform == 'windows':
|
||||
|
|
|
@ -13,32 +13,6 @@
|
|||
#include "CList.h"
|
||||
#include "sh_list.h"
|
||||
|
||||
// *****************************************************
|
||||
// class CCVar
|
||||
// *****************************************************
|
||||
|
||||
class CCVar
|
||||
{
|
||||
cvar_t cvar;
|
||||
String name;
|
||||
String plugin;
|
||||
|
||||
public:
|
||||
CCVar(const char* pname, const char* pplugin, int pflags, float pvalue) : name(pname), plugin(pplugin)
|
||||
{
|
||||
cvar.name = (char*)name.c_str();
|
||||
cvar.flags = pflags;
|
||||
cvar.string = "";
|
||||
cvar.value = pvalue;
|
||||
}
|
||||
|
||||
inline cvar_t* getCvar() { return &cvar; }
|
||||
inline const char* getPluginName() { return plugin.c_str(); }
|
||||
inline const char* getName() { return name.c_str(); }
|
||||
inline bool operator == (const char* string) { return (strcmp(name.c_str(), string) == 0); }
|
||||
int plugin_id;
|
||||
};
|
||||
|
||||
// *****************************************************
|
||||
// class CPlayer
|
||||
// *****************************************************
|
||||
|
|
623
amxmodx/CvarManager.cpp
Normal file
623
amxmodx/CvarManager.cpp
Normal file
|
@ -0,0 +1,623 @@
|
|||
// 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>
|
||||
#include <auto-string.h>
|
||||
|
||||
CvarManager g_CvarManager;
|
||||
|
||||
DETOUR_DECL_STATIC2(Cvar_DirectSet, void, struct cvar_s*, 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 do.
|
||||
{
|
||||
DETOUR_STATIC_CALL(Cvar_DirectSet)(var, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->bound.hasMin || info->bound.hasMax) // cvar_s doesn't have min/max mechanism, so we check things here.
|
||||
{
|
||||
float fvalue = atof(value);
|
||||
bool oob = false;
|
||||
|
||||
if (info->bound.hasMin && fvalue < info->bound.minVal)
|
||||
{
|
||||
oob = true;
|
||||
fvalue = info->bound.minVal;
|
||||
}
|
||||
else if (info->bound.hasMax && fvalue > info->bound.maxVal)
|
||||
{
|
||||
oob = true;
|
||||
fvalue = info->bound.maxVal;
|
||||
}
|
||||
|
||||
if (oob) // Found value out of bound, set new value and block original call.
|
||||
{
|
||||
CVAR_SET_FLOAT(var->name, fvalue);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ke::AString oldValue; // We save old value since it will be likely changed after original function called.
|
||||
|
||||
if (!info->hooks.empty())
|
||||
{
|
||||
oldValue = var->string;
|
||||
}
|
||||
|
||||
DETOUR_STATIC_CALL(Cvar_DirectSet)(var, value);
|
||||
|
||||
if (!info->binds.empty())
|
||||
{
|
||||
for (size_t i = 0; i < info->binds.length(); ++i)
|
||||
{
|
||||
CvarBind* bind = info->binds[i];
|
||||
|
||||
switch (bind->type)
|
||||
{
|
||||
case CvarBind::CvarType_Int:
|
||||
{
|
||||
*bind->varAddress = atoi(var->string);
|
||||
break;
|
||||
}
|
||||
case CvarBind::CvarType_Float:
|
||||
{
|
||||
float fvalue = atof(var->string);
|
||||
*bind->varAddress = amx_ftoc(fvalue);
|
||||
break;
|
||||
}
|
||||
case CvarBind::CvarType_String:
|
||||
{
|
||||
set_amxstring_simple(bind->varAddress, var->string, bind->varLength);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!info->hooks.empty())
|
||||
{
|
||||
for (size_t i = 0; i < info->hooks.length(); ++i)
|
||||
{
|
||||
CvarHook* hook = info->hooks[i];
|
||||
|
||||
if (hook->forward->state == AutoForward::FSTATE_OK) // Our callback can be enable/disabled by natives.
|
||||
{
|
||||
executeForwards(hook->forward->id, reinterpret_cast<cvar_t*>(var), oldValue.chars(), var->string);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// Disabled by default.
|
||||
m_HookDetour = DETOUR_CREATE_STATIC_FIXED(Cvar_DirectSet, (void *)functionAddress);
|
||||
}
|
||||
}
|
||||
|
||||
CvarInfo* CvarManager::CreateCvar(const char* name, const char* value, const char* plugin, int pluginId, int flags,
|
||||
const char* helpText, bool hasMin, float min, bool hasMax, float max)
|
||||
{
|
||||
cvar_t* var = nullptr;
|
||||
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(name, helpText, hasMin, min, hasMax, max, plugin, pluginId);
|
||||
|
||||
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);
|
||||
}
|
||||
else if (info->pluginId == -1)
|
||||
{
|
||||
// In situation where a plugin has been modified/recompiled
|
||||
// or new added plugins, and a change map occurs. We want to keep data up to date.
|
||||
info->bound.hasMin = false;
|
||||
info->bound.minVal = 0;
|
||||
info->bound.hasMax = false;
|
||||
info->bound.maxVal = 0;
|
||||
info->defaultval = value;
|
||||
info->description = helpText;
|
||||
info->pluginId = pluginId;
|
||||
}
|
||||
|
||||
// Detour is disabled on map change.
|
||||
// Don't enable it unless there are things to do.
|
||||
if (info->bound.hasMin || info->bound.hasMax)
|
||||
{
|
||||
m_HookDetour->EnableDetour();
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
CvarInfo* 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;
|
||||
}
|
||||
|
||||
// Cvar doesn't exist.
|
||||
if (!(var = CVAR_GET_POINTER(name)))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create a new entry.
|
||||
info = new CvarInfo(name);
|
||||
info->var = var;
|
||||
|
||||
// Add entry in the caches.
|
||||
m_Cvars.append(info);
|
||||
m_Cache.insert(name, info);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
AutoForward* 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(var->name);
|
||||
info->var = var;
|
||||
|
||||
// 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();
|
||||
|
||||
AutoForward* forward = new AutoForward(forwardId, *callback);
|
||||
info->hooks.append(new CvarHook(g_plugins.findPlugin(amx)->getId(), forward));
|
||||
|
||||
return forward;
|
||||
}
|
||||
|
||||
bool CvarManager::BindCvar(CvarInfo* info, CvarBind::CvarType type, AMX* amx, cell varofs, size_t varlen)
|
||||
{
|
||||
if (varofs > amx->hlw) // If variable address is not inside global area, we can't bind it.
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Cvars can only be bound to global variables");
|
||||
return false;
|
||||
}
|
||||
|
||||
int pluginId = g_plugins.findPluginFast(amx)->getId();
|
||||
cell* address = get_amxaddr(amx, varofs);
|
||||
|
||||
// To avoid unexpected behavior, probably better to error such situations.
|
||||
for (size_t i = 0; i < info->binds.length(); ++i)
|
||||
{
|
||||
CvarBind* bind = info->binds[i];
|
||||
|
||||
if (bind->pluginId == pluginId)
|
||||
{
|
||||
if (bind->varAddress == address)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "A global variable can not be bound to multiple Cvars");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CvarBind* bind = new CvarBind(pluginId, type, get_amxaddr(amx, varofs), varlen);
|
||||
|
||||
info->binds.append(bind);
|
||||
|
||||
// Update right away variable with current cvar value.
|
||||
switch (type)
|
||||
{
|
||||
case CvarBind::CvarType_Int:
|
||||
*bind->varAddress = atoi(info->var->string);
|
||||
break;
|
||||
case CvarBind::CvarType_Float:
|
||||
*bind->varAddress = amx_ftoc(info->var->value);
|
||||
break;
|
||||
case CvarBind::CvarType_String:
|
||||
set_amxstring_simple(bind->varAddress, info->var->string, bind->varLength);
|
||||
break;
|
||||
}
|
||||
|
||||
// Detour is disabled on map change.
|
||||
m_HookDetour->EnableDetour();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CvarManager::SetCvarMin(CvarInfo* info, bool set, float value, int pluginId)
|
||||
{
|
||||
info->bound.hasMin = set;
|
||||
info->bound.minPluginId = pluginId;
|
||||
|
||||
if (set)
|
||||
{
|
||||
if (info->bound.hasMax && value > info->bound.maxVal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
info->bound.minVal = value;
|
||||
|
||||
// Detour is disabled on map change.
|
||||
m_HookDetour->EnableDetour();
|
||||
|
||||
// Update if needed.
|
||||
CVAR_SET_FLOAT(info->var->name, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CvarManager::SetCvarMax(CvarInfo* info, bool set, float value, int pluginId)
|
||||
{
|
||||
info->bound.hasMax = set;
|
||||
info->bound.maxPluginId = pluginId;
|
||||
|
||||
if (set)
|
||||
{
|
||||
if (info->bound.hasMin && value < info->bound.minVal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
info->bound.maxVal = value;
|
||||
|
||||
// Detour is disabled on map change.
|
||||
m_HookDetour->EnableDetour();
|
||||
|
||||
// Update if needed.
|
||||
CVAR_SET_FLOAT(info->var->name, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t CvarManager::GetRegCvarsCount()
|
||||
{
|
||||
return m_AmxmodxCvars;
|
||||
}
|
||||
|
||||
AutoString convertFlagsToString(int flags)
|
||||
{
|
||||
AutoString flagsName;
|
||||
|
||||
if (flags > 0)
|
||||
{
|
||||
if (flags & FCVAR_ARCHIVE) flagsName = flagsName + "FCVAR_ARCHIVE ";
|
||||
if (flags & FCVAR_USERINFO) flagsName = flagsName + "FCVAR_USERINFO ";
|
||||
if (flags & FCVAR_SERVER) flagsName = flagsName + "FCVAR_SERVER ";
|
||||
if (flags & FCVAR_EXTDLL) flagsName = flagsName + "FCVAR_EXTDLL ";
|
||||
if (flags & FCVAR_CLIENTDLL) flagsName = flagsName + "FCVAR_CLIENTDLL ";
|
||||
if (flags & FCVAR_PROTECTED) flagsName = flagsName + "FCVAR_PROTECTED ";
|
||||
if (flags & FCVAR_SPONLY) flagsName = flagsName + "FCVAR_SPONLY ";
|
||||
if (flags & FCVAR_PRINTABLEONLY) flagsName = flagsName + "FCVAR_PRINTABLEONLY ";
|
||||
if (flags & FCVAR_UNLOGGED) flagsName = flagsName + "FCVAR_UNLOGGED ";
|
||||
if (flags & FCVAR_NOEXTRAWHITEPACE) flagsName = flagsName + "FCVAR_NOEXTRAWHITEPACE ";
|
||||
}
|
||||
|
||||
if (!flagsName.length())
|
||||
{
|
||||
flagsName = "-";
|
||||
}
|
||||
|
||||
return flagsName;
|
||||
}
|
||||
|
||||
void CvarManager::OnConsoleCommand()
|
||||
{
|
||||
size_t index = 0;
|
||||
size_t indexToSearch = 0;
|
||||
ke::AString partialName;
|
||||
|
||||
int argcount = CMD_ARGC();
|
||||
|
||||
// amxx cvars [partial plugin name] [index from listing]
|
||||
// E.g.:
|
||||
// amxx cvars test <- list all cvars from plugin name starting by "test"
|
||||
// amxx cvars 2 <- show informations about cvar in position 2 from "amxx cvars" list
|
||||
// amxx cvars test 2 <- show informations about cvar in position 2 from "amxx cvars test" list
|
||||
|
||||
if (argcount > 2)
|
||||
{
|
||||
const char* argument = CMD_ARGV(2);
|
||||
|
||||
indexToSearch = atoi(argument); // amxx cvars 2
|
||||
|
||||
if (!indexToSearch)
|
||||
{
|
||||
partialName = argument; // amxx cvars test
|
||||
|
||||
if (argcount > 3) // amxx cvars test 2
|
||||
{
|
||||
indexToSearch = atoi(CMD_ARGV(3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!indexToSearch)
|
||||
{
|
||||
print_srvconsole("\nManaged cvars:\n");
|
||||
print_srvconsole(" %-24.23s %-24.23s %-18.17s %-8.7s %-8.7s %-8.7s\n", "NAME", "VALUE", "PLUGIN", "BOUND", "HOOKED", "BOUNDED");
|
||||
print_srvconsole(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
|
||||
}
|
||||
|
||||
for (CvarsList::iterator iter = m_Cvars.begin(); iter != m_Cvars.end(); iter++)
|
||||
{
|
||||
CvarInfo* ci = (*iter);
|
||||
|
||||
// List any cvars having a status either created, hooked or bound by a plugin.
|
||||
bool in_list = ci->amxmodx || !ci->binds.empty() || !ci->hooks.empty() || ci->bound.hasMin || ci->bound.hasMax;
|
||||
|
||||
if (in_list && (!partialName.length() || strncmp(ci->plugin.chars(), partialName.chars(), partialName.length()) == 0))
|
||||
{
|
||||
if (!indexToSearch)
|
||||
{
|
||||
print_srvconsole(" [%3d] %-24.23s %-24.23s %-18.17s %-8.7s %-8.7s %-8.7s\n", ++index, ci->name.chars(), ci->var->string,
|
||||
ci->plugin.length() ? ci->plugin.chars() : "-",
|
||||
ci->binds.empty() ? "no" : "yes",
|
||||
ci->hooks.empty() ? "no" : "yes",
|
||||
ci->bound.hasMin || ci->bound.hasMax ? "yes" : "no");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (++index != indexToSearch)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
print_srvconsole("\nCvar details :\n\n");
|
||||
print_srvconsole(" Cvar name : %s\n", ci->var->name);
|
||||
print_srvconsole(" Value : %s\n", ci->var->string);
|
||||
print_srvconsole(" Def. value : %s\n", ci->defaultval.chars());
|
||||
print_srvconsole(" Description : %s\n", ci->description.chars());
|
||||
print_srvconsole(" Flags : %s\n\n", convertFlagsToString(ci->var->flags).ptr());
|
||||
|
||||
print_srvconsole(" %-12s %-26.25s %s\n", "STATUS", "PLUGIN", "INFOS");
|
||||
print_srvconsole(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
|
||||
|
||||
if (ci->amxmodx)
|
||||
{
|
||||
print_srvconsole(" Registered %-26.25s %s\n", ci->plugin.chars(), "-");
|
||||
}
|
||||
|
||||
if (ci->bound.hasMin)
|
||||
{
|
||||
print_srvconsole(" Min value %-26.25s %f\n", g_plugins.findPlugin(ci->bound.minPluginId)->getName(), ci->bound.minVal);
|
||||
}
|
||||
|
||||
if (ci->bound.hasMax)
|
||||
{
|
||||
print_srvconsole(" Max value %-26.25s %f\n", g_plugins.findPlugin(ci->bound.maxPluginId)->getName(), ci->bound.maxVal);
|
||||
}
|
||||
|
||||
if (!ci->binds.empty())
|
||||
{
|
||||
for (size_t i = 0; i < ci->binds.length(); ++i)
|
||||
{
|
||||
print_srvconsole(" Bound %-26.25s %s\n", g_plugins.findPlugin(ci->binds[i]->pluginId)->getName(), "-");
|
||||
}
|
||||
}
|
||||
|
||||
if (!ci->hooks.empty())
|
||||
{
|
||||
for (size_t i = 0; i < ci->hooks.length(); ++i)
|
||||
{
|
||||
CvarHook* hook = ci->hooks[i];
|
||||
|
||||
print_srvconsole(" Hooked %-26.25s %s (%s)\n", g_plugins.findPlugin(hook->pluginId)->getName(),
|
||||
hook->forward->callback.chars(),
|
||||
hook->forward->state == AutoForward::FSTATE_OK ? "active" : "inactive");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)->binds.length(); ++i)
|
||||
{
|
||||
delete (*cvar)->binds[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (*cvar)->hooks.length(); ++i)
|
||||
{
|
||||
delete (*cvar)->hooks[i];
|
||||
}
|
||||
|
||||
if ((*cvar)->amxmodx) // Mark registered cvars so we can refresh default datas at next map.
|
||||
{
|
||||
(*cvar)->pluginId = -1;
|
||||
}
|
||||
|
||||
(*cvar)->binds.clear();
|
||||
(*cvar)->hooks.clear();
|
||||
}
|
||||
|
||||
// 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)->binds.length(); ++i)
|
||||
{
|
||||
delete (*cvar)->binds[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (*cvar)->hooks.length(); ++i)
|
||||
{
|
||||
delete (*cvar)->hooks[i];
|
||||
}
|
||||
|
||||
delete (*cvar);
|
||||
}
|
||||
|
||||
m_Cache.clear();
|
||||
m_HookDetour->Destroy();
|
||||
}
|
183
amxmodx/CvarManager.h
Normal file
183
amxmodx/CvarManager.h
Normal file
|
@ -0,0 +1,183 @@
|
|||
// 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
|
||||
|
||||
#ifndef CVARS_H
|
||||
#define CVARS_H
|
||||
|
||||
#include "amxmodx.h"
|
||||
#include <am-vector.h>
|
||||
#include <am-inlinelist.h>
|
||||
#include <sm_namehashset.h>
|
||||
|
||||
class CDetour;
|
||||
|
||||
enum CvarBounds
|
||||
{
|
||||
CvarBound_Upper = 0,
|
||||
CvarBound_Lower
|
||||
};
|
||||
|
||||
struct AutoForward
|
||||
{
|
||||
enum fwdstate
|
||||
{
|
||||
FSTATE_INVALID = 0,
|
||||
FSTATE_OK,
|
||||
FSTATE_STOP,
|
||||
};
|
||||
|
||||
AutoForward(int id_, const char* handler) : id(id_), state(FSTATE_OK), callback(handler) {};
|
||||
AutoForward() : id(-1) , state(FSTATE_INVALID) {};
|
||||
|
||||
~AutoForward()
|
||||
{
|
||||
unregisterSPForward(id);
|
||||
}
|
||||
|
||||
int id;
|
||||
fwdstate state;
|
||||
ke::AString callback;
|
||||
};
|
||||
|
||||
struct CvarHook
|
||||
{
|
||||
CvarHook(int id, AutoForward* fwd) : pluginId(id), forward(fwd) {};
|
||||
CvarHook(int id) : pluginId(id), forward(new AutoForward()) {};
|
||||
|
||||
int pluginId;
|
||||
ke::AutoPtr<AutoForward> forward;
|
||||
};
|
||||
|
||||
struct CvarBind
|
||||
{
|
||||
enum CvarType
|
||||
{
|
||||
CvarType_Int,
|
||||
CvarType_Float,
|
||||
CvarType_String,
|
||||
};
|
||||
|
||||
CvarBind(int id_, CvarType type_, cell* varAddress_, size_t varLength_)
|
||||
:
|
||||
pluginId(id_),
|
||||
type(type_),
|
||||
varAddress(varAddress_),
|
||||
varLength(varLength_) {};
|
||||
|
||||
int pluginId;
|
||||
CvarType type;
|
||||
cell* varAddress;
|
||||
size_t varLength;
|
||||
};
|
||||
|
||||
struct CvarBound
|
||||
{
|
||||
CvarBound(bool hasMin_, float minVal_, bool hasMax_, float maxVal_, int minPluginId_, int maxPluginId_)
|
||||
:
|
||||
hasMin(hasMin_), minVal(minVal_),
|
||||
hasMax(hasMax_), maxVal(maxVal_),
|
||||
minPluginId(minPluginId_),
|
||||
maxPluginId(maxPluginId_) {};
|
||||
|
||||
CvarBound()
|
||||
:
|
||||
hasMin(false), minVal(0),
|
||||
hasMax(false), maxVal(0) {};
|
||||
|
||||
bool hasMin;
|
||||
float minVal;
|
||||
bool hasMax;
|
||||
float maxVal;
|
||||
int minPluginId;
|
||||
int maxPluginId;
|
||||
};
|
||||
|
||||
typedef ke::Vector<CvarHook*> CvarsHook;
|
||||
typedef ke::Vector<CvarBind*> CvarsBind;
|
||||
|
||||
struct CvarInfo : public ke::InlineListNode<CvarInfo>
|
||||
{
|
||||
CvarInfo(const char* name_, const char* helpText,
|
||||
bool hasMin_, float min_, bool hasMax_, float max_,
|
||||
const char* plugin_, int pluginId_)
|
||||
:
|
||||
name(name_), description(helpText),
|
||||
plugin(plugin_), pluginId(pluginId_),
|
||||
bound(hasMin_, min_, hasMax_, max_, pluginId_, pluginId_) {};
|
||||
|
||||
CvarInfo(const char* name_)
|
||||
:
|
||||
name(name_), defaultval(""), description(""),
|
||||
plugin(""), pluginId(-1), bound(), amxmodx(false) {};
|
||||
|
||||
cvar_t* var;
|
||||
ke::AString name;
|
||||
ke::AString defaultval;
|
||||
ke::AString description;
|
||||
|
||||
ke::AString plugin;
|
||||
int pluginId;
|
||||
|
||||
CvarBound bound;
|
||||
CvarsBind binds;
|
||||
CvarsHook hooks;
|
||||
|
||||
bool amxmodx;
|
||||
|
||||
static inline bool matches(const char *name, const CvarInfo* info)
|
||||
{
|
||||
return strcmp(name, info->var->name) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef NameHashSet<CvarInfo*> CvarsCache;
|
||||
typedef ke::InlineList<CvarInfo> CvarsList;
|
||||
|
||||
class CvarManager
|
||||
{
|
||||
public:
|
||||
|
||||
CvarManager();
|
||||
~CvarManager();
|
||||
|
||||
public:
|
||||
|
||||
void CreateCvarHook();
|
||||
|
||||
CvarInfo* CreateCvar(const char* name, const char* value, const char* plugin, int pluginId,
|
||||
int flags = 0, const char* helpText = "",
|
||||
bool hasMin = false, float min = 0,
|
||||
bool hasMax = false, float max = 0);
|
||||
|
||||
CvarInfo* FindCvar(const char* name);
|
||||
CvarInfo* FindCvar(size_t index);
|
||||
bool CacheLookup(const char* name, CvarInfo** info);
|
||||
|
||||
AutoForward* HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback);
|
||||
bool BindCvar(CvarInfo* info, CvarBind::CvarType type, AMX* amx, cell varofs, size_t varlen = 0);
|
||||
bool SetCvarMin(CvarInfo* info, bool set, float value, int pluginId);
|
||||
bool SetCvarMax(CvarInfo* info, bool set, float value, int pluginId);
|
||||
|
||||
size_t GetRegCvarsCount();
|
||||
|
||||
void OnConsoleCommand();
|
||||
void OnPluginUnloaded();
|
||||
void OnAmxxShutdown();
|
||||
|
||||
private:
|
||||
|
||||
CvarsCache m_Cache;
|
||||
CvarsList m_Cvars;
|
||||
size_t m_AmxmodxCvars;
|
||||
CDetour* m_HookDetour;
|
||||
};
|
||||
|
||||
extern CvarManager g_CvarManager;
|
||||
|
||||
#endif // CVARS_H
|
|
@ -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 \
|
||||
nongpl_matches.cpp CFlagManager.cpp datastructs.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 ###
|
||||
|
|
|
@ -22,25 +22,6 @@
|
|||
|
||||
extern CFlagManager FlagMan;
|
||||
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)
|
||||
{
|
||||
|
@ -1909,140 +1890,6 @@ static cell AMX_NATIVE_CALL client_cmd(AMX *amx, cell *params) /* 2 param */
|
|||
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 ilen;
|
||||
char* sptemp = get_amxstring(amx, params[1], 0, ilen);
|
||||
|
||||
const char *value = CVAR_GET_STRING(sptemp);
|
||||
return set_amxstring_utf8(amx, params[2], value, strlen(value), 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;
|
||||
}
|
||||
|
||||
REAL val = (REAL)ptr->value;
|
||||
|
||||
return amx_ftoc(val);
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL get_cvar_float(AMX *amx, cell *params) /* 1 param */
|
||||
{
|
||||
int ilen;
|
||||
|
||||
REAL pFloat = CVAR_GET_FLOAT(get_amxstring(amx, params[1], 0, ilen));
|
||||
|
||||
return amx_ftoc(pFloat);
|
||||
}
|
||||
|
||||
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]));
|
||||
(*g_engfuncs.pfnCvar_DirectSet)(ptr, &CVarTempBuffer[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL set_cvar_float(AMX *amx, cell *params) /* 2 param */
|
||||
{
|
||||
int ilen;
|
||||
CVAR_SET_FLOAT(get_amxstring(amx, params[1], 0, ilen), amx_ctof(params[2]));
|
||||
|
||||
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 ilen;
|
||||
return (int)CVAR_GET_FLOAT(get_amxstring(amx, params[1], 0, ilen));
|
||||
}
|
||||
|
||||
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]);
|
||||
(*g_engfuncs.pfnCvar_DirectSet)(ptr, &CVarTempBuffer[0]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL set_cvar_num(AMX *amx, cell *params) /* 2 param */
|
||||
{
|
||||
int ilen;
|
||||
CVAR_SET_FLOAT(get_amxstring(amx, params[1], 0, ilen), (float)params[2]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL set_cvar_string(AMX *amx, cell *params) /* 2 param */
|
||||
{
|
||||
int ilen;
|
||||
char* sptemp = get_amxstring(amx, params[1], 0, ilen);
|
||||
char* szValue = get_amxstring(amx, params[2], 1, ilen);
|
||||
|
||||
CVAR_SET_STRING(sptemp, szValue);
|
||||
|
||||
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;
|
||||
|
||||
(*g_engfuncs.pfnCvar_DirectSet)(ptr, get_amxstring(amx,params[2],0,len));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL log_message(AMX *amx, cell *params) /* 1 param */
|
||||
{
|
||||
int len;
|
||||
|
@ -2595,45 +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);
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL cvar_exists(AMX *amx, cell *params) /* 1 param */
|
||||
{
|
||||
int ilen;
|
||||
return (CVAR_GET_POINTER(get_amxstring(amx, params[1], 0, ilen)) ? 1 : 0);
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL register_cvar(AMX *amx, cell *params) /* 3 param */
|
||||
{
|
||||
int i;
|
||||
char* temp = get_amxstring(amx, params[1], 0, i);
|
||||
CPluginMngr::CPlugin *plugin = g_plugins.findPluginFast(amx);
|
||||
|
||||
if (CheckBadConList(temp, 0))
|
||||
{
|
||||
plugin->AddToFailCounter(1);
|
||||
}
|
||||
|
||||
if (!g_cvars.find(temp))
|
||||
{
|
||||
CCVar* cvar = new CCVar(temp, plugin->getName(), params[3], amx_ctof(params[4]));
|
||||
|
||||
cvar->plugin_id = plugin->getId();
|
||||
|
||||
g_cvars.put(cvar);
|
||||
|
||||
if (CVAR_GET_POINTER(temp) == 0)
|
||||
{
|
||||
static cvar_t cvar_reg_helper;
|
||||
cvar_reg_helper = *(cvar->getCvar());
|
||||
CVAR_REGISTER(&cvar_reg_helper);
|
||||
}
|
||||
|
||||
CVAR_SET_STRING(temp, get_amxstring(amx, params[2], 1, i));
|
||||
return reinterpret_cast<cell>(CVAR_GET_POINTER(temp));
|
||||
}
|
||||
|
||||
return reinterpret_cast<cell>(CVAR_GET_POINTER(temp));
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL get_user_ping(AMX *amx, cell *params) /* 3 param */
|
||||
{
|
||||
int index = params[1];
|
||||
|
@ -3019,43 +2827,6 @@ static cell AMX_NATIVE_CALL remove_quotes(AMX *amx, cell *params) /* 1 param */
|
|||
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)
|
||||
{
|
||||
int id = params[1];
|
||||
int iter_id = 0;
|
||||
|
||||
for (CList<CCVar>::iterator iter=g_cvars.begin(); iter; ++iter)
|
||||
{
|
||||
if (id == iter_id)
|
||||
{
|
||||
CCVar *var = &(*iter);
|
||||
set_amxstring(amx, params[2], var->getName(), params[3]);
|
||||
cvar_t *ptr = CVAR_GET_POINTER(var->getName());
|
||||
if (!ptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
cell *addr = get_amxaddr(amx, params[4]);
|
||||
*addr = ptr->flags;
|
||||
addr = get_amxaddr(amx, params[5]);
|
||||
*addr = var->plugin_id;
|
||||
addr = get_amxaddr(amx, params[6]);
|
||||
*addr = (cell)ptr;
|
||||
return 1;
|
||||
}
|
||||
iter_id++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//native get_plugins_cvarsnum();
|
||||
static cell AMX_NATIVE_CALL get_plugins_cvarsnum(AMX *amx, cell *params)
|
||||
{
|
||||
return g_cvars.size();
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL get_user_aiming(AMX *amx, cell *params) /* 4 param */
|
||||
{
|
||||
int index = params[1];
|
||||
|
@ -3099,80 +2870,6 @@ static cell AMX_NATIVE_CALL get_user_aiming(AMX *amx, cell *params) /* 4 param *
|
|||
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 = CVAR_GET_POINTER(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 = CVAR_GET_POINTER(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 = CVAR_GET_POINTER(sCvar);
|
||||
|
||||
if (pCvar)
|
||||
{
|
||||
pCvar->flags |= (int)(params[2]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL force_unmodified(AMX *amx, cell *params)
|
||||
{
|
||||
int a;
|
||||
|
@ -4121,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)
|
||||
{
|
||||
int err = params[1];
|
||||
|
@ -4445,16 +4046,6 @@ static cell AMX_NATIVE_CALL DestroyForward(AMX *amx, cell *params)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static cell AMX_NATIVE_CALL get_cvar_pointer(AMX *amx, cell *params)
|
||||
{
|
||||
int len;
|
||||
char *temp = get_amxstring(amx, params[1], 0, len);
|
||||
|
||||
cvar_t *ptr = CVAR_GET_POINTER(temp);
|
||||
|
||||
return reinterpret_cast<cell>(ptr);
|
||||
}
|
||||
|
||||
CVector<cell *> g_hudsync;
|
||||
|
||||
static cell AMX_NATIVE_CALL CreateHudSyncObj(AMX *amx, cell *params)
|
||||
|
@ -4860,7 +4451,6 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
|
|||
{"client_print_color", client_print_color},
|
||||
{"console_cmd", console_cmd},
|
||||
{"console_print", console_print},
|
||||
{"cvar_exists", cvar_exists},
|
||||
{"emit_sound", emit_sound},
|
||||
{"engclient_cmd", engclient_cmd},
|
||||
{"engclient_print", engclient_print},
|
||||
|
@ -4873,11 +4463,6 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
|
|||
{"get_concmd", get_concmd},
|
||||
{"get_concmdsnum", get_concmdsnum},
|
||||
{"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_func_id", get_func_id},
|
||||
{"get_gametime", get_gametime},
|
||||
|
@ -4889,16 +4474,10 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
|
|||
{"get_modname", get_modname},
|
||||
{"get_module", get_module},
|
||||
{"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_playersnum", get_playersnum},
|
||||
{"get_plugin", get_plugin},
|
||||
{"get_pluginsnum", get_pluginsnum},
|
||||
{"get_plugins_cvar", get_plugins_cvar},
|
||||
{"get_plugins_cvarsnum", get_plugins_cvarsnum},
|
||||
{"get_srvcmd", get_srvcmd},
|
||||
{"get_srvcmdsnum", get_srvcmdsnum},
|
||||
{"get_systime", get_systime},
|
||||
|
@ -4967,7 +4546,6 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
|
|||
{"precache_model", precache_model},
|
||||
{"precache_sound", precache_sound},
|
||||
{"precache_generic", precache_generic},
|
||||
{"query_client_cvar", query_client_cvar},
|
||||
{"random_float", random_float},
|
||||
{"random_num", random_num},
|
||||
{"read_argc", read_argc},
|
||||
|
@ -4982,7 +4560,6 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
|
|||
{"read_logdata", read_logdata},
|
||||
{"register_clcmd", register_clcmd},
|
||||
{"register_concmd", register_concmd},
|
||||
{"register_cvar", register_cvar},
|
||||
{"register_dictionary", register_dictionary},
|
||||
{"register_event", register_event},
|
||||
{"register_logevent", register_logevent},
|
||||
|
@ -4991,25 +4568,16 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
|
|||
{"register_plugin", register_plugin},
|
||||
{"register_srvcmd", register_srvcmd},
|
||||
{"require_module", require_module},
|
||||
{"remove_cvar_flags", remove_cvar_flags},
|
||||
{"remove_quotes", remove_quotes},
|
||||
{"remove_task", remove_task},
|
||||
{"remove_user_flags", remove_user_flags},
|
||||
{"server_cmd", server_cmd},
|
||||
{"server_exec", server_exec},
|
||||
{"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_dhudmessage", set_dhudmessage},
|
||||
{"set_hudmessage", set_hudmessage},
|
||||
{"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_user_flags", set_user_flags},
|
||||
{"set_user_info", set_user_info},
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "CLang.h"
|
||||
#include "fakemeta.h"
|
||||
#include "amxxlog.h"
|
||||
#include "CvarManager.h"
|
||||
|
||||
#define AMXXLOG_Log g_log.Log
|
||||
#define AMXXLOG_Error g_log.LogError
|
||||
|
@ -65,6 +66,7 @@ extern AMX_NATIVE_INFO g_SortNatives[];
|
|||
extern AMX_NATIVE_INFO g_DataStructNatives[];
|
||||
extern AMX_NATIVE_INFO g_StackNatives[];
|
||||
extern AMX_NATIVE_INFO g_TextParserNatives[];
|
||||
extern AMX_NATIVE_INFO g_CvarNatives[];
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define DLLOAD(path) (DLHANDLE)LoadLibrary(path)
|
||||
|
@ -161,7 +163,6 @@ extern CTaskMngr g_tasksMngr;
|
|||
extern CPlayer g_players[33];
|
||||
extern CPlayer* mPlayer;
|
||||
extern CmdMngr g_commands;
|
||||
extern CList<CCVar> g_cvars;
|
||||
extern CList<ForceObject> g_forcemodels;
|
||||
extern CList<ForceObject> g_forcesounds;
|
||||
extern CList<ForceObject> g_forcegeneric;
|
||||
|
@ -281,6 +282,7 @@ int amxstring_len(cell* cstr);
|
|||
int load_amxscript(AMX* amx, void** program, const char* path, char error[64], int debug);
|
||||
int set_amxnatives(AMX* amx, char error[64]);
|
||||
int set_amxstring(AMX *amx, cell amx_addr, const char *source, int max);
|
||||
int set_amxstring_simple(cell *dest, const char *source, int max);
|
||||
template <typename T> int set_amxstring_utf8(AMX *amx, cell amx_addr, const T *source, size_t sourcelen, size_t maxlen);
|
||||
int set_amxstring_utf8_char(AMX *amx, cell amx_addr, const char *source, size_t sourcelen, size_t maxlen);
|
||||
int set_amxstring_utf8_cell(AMX *amx, cell amx_addr, const cell *source, size_t sourcelen, size_t maxlen);
|
||||
|
@ -329,6 +331,7 @@ extern int FF_PluginEnd;
|
|||
extern int FF_InconsistentFile;
|
||||
extern int FF_ClientAuthorized;
|
||||
extern int FF_ChangeLevel;
|
||||
|
||||
extern bool g_coloredmenus;
|
||||
|
||||
typedef void (*AUTHORIZEFUNC)(int player, const char *authstring);
|
||||
|
|
720
amxmodx/cvars.cpp
Normal file
720
amxmodx/cvars.cpp
Normal file
|
@ -0,0 +1,720 @@
|
|||
// 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 "nongpl_matches.h"
|
||||
|
||||
char CVarTempBuffer[64];
|
||||
const char *invis_cvar_list[5] ={ "amxmodx_version", "amxmodx_modules", "amx_debug", "amx_mldebug", "amx_client_languages" };
|
||||
|
||||
// create_cvar(const name[], const default_value[], flags = 0, const description[] = "", bool:has_min = false, Float:min_val = 0.0, bool:has_max = false, Float:max_val = 0.0)
|
||||
static cell AMX_NATIVE_CALL create_cvar(AMX *amx, cell *params)
|
||||
{
|
||||
int length;
|
||||
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||
const char* value = get_amxstring(amx, params[2], 1, length);
|
||||
const char* helpText = get_amxstring(amx, params[4], 2, length);
|
||||
|
||||
int flags = params[3];
|
||||
|
||||
CPluginMngr::CPlugin *plugin = g_plugins.findPluginFast(amx);
|
||||
|
||||
if (CheckBadConList(name, 0))
|
||||
{
|
||||
plugin->AddToFailCounter(1);
|
||||
}
|
||||
|
||||
CvarInfo* info = g_CvarManager.CreateCvar(name, value, plugin->getName(), plugin->getId(), flags, helpText);
|
||||
|
||||
if (info)
|
||||
{
|
||||
bool hasMin = params[5] != 0;
|
||||
bool hasMax = params[7] != 0;
|
||||
float minVal = amx_ctof(params[6]);
|
||||
float maxVal = amx_ctof(params[8]);
|
||||
|
||||
if (!g_CvarManager.SetCvarMin(info, hasMin, minVal, plugin->getId()))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "The minimum value can not be above the maximum value");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!g_CvarManager.SetCvarMax(info, hasMax, maxVal, plugin->getId()))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "The maximum value can not be below the minimum value");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reinterpret_cast<cell>(info->var);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// register_cvar(const name[], const string[], flags=0, Float:fvalue=0.0)
|
||||
static cell AMX_NATIVE_CALL register_cvar(AMX *amx, cell *params)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
CvarInfo* info = g_CvarManager.CreateCvar(name, value, plugin->getName(), plugin->getId(), flags);
|
||||
|
||||
if (info)
|
||||
{
|
||||
return reinterpret_cast<cell>(info->var);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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;
|
||||
const char *name = get_amxstring(amx, params[1], 0, len);
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(name);
|
||||
|
||||
return reinterpret_cast<cell>(info ? info->var : 0);
|
||||
}
|
||||
|
||||
// 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;
|
||||
AutoForward* forward = g_CvarManager.HookCvarChange(var, amx, params[2], &callback);
|
||||
|
||||
if (!forward)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Function \"%s\" is not present", callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reinterpret_cast<cell>(forward);
|
||||
}
|
||||
|
||||
// enable_cvar_hook(cvarhook:handle);
|
||||
static cell AMX_NATIVE_CALL enable_cvar_hook(AMX *amx, cell *params)
|
||||
{
|
||||
AutoForward* forward = reinterpret_cast<AutoForward*>(params[1]);
|
||||
|
||||
if (!forward)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid cvar hook handle: %p", forward);
|
||||
return 0;
|
||||
}
|
||||
|
||||
forward->state = AutoForward::FSTATE_OK;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// disable_cvar_hook(cvarhook:handle);
|
||||
static cell AMX_NATIVE_CALL disable_cvar_hook(AMX *amx, cell *params)
|
||||
{
|
||||
AutoForward* forward = reinterpret_cast<AutoForward*>(params[1]);
|
||||
|
||||
if (!forward)
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid cvar hook handle: %p", forward);
|
||||
return 0;
|
||||
}
|
||||
|
||||
forward->state = AutoForward::FSTATE_STOP;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// get_cvar_flags(const cvar[])
|
||||
static cell AMX_NATIVE_CALL get_cvar_flags(AMX *amx, cell *params)
|
||||
{
|
||||
int ilen;
|
||||
char* sCvar = get_amxstring(amx, params[1], 0, ilen);
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(sCvar);
|
||||
|
||||
return info ? info->var->flags : 0;
|
||||
}
|
||||
|
||||
// get_cvar_float(const cvarname[])
|
||||
static cell AMX_NATIVE_CALL get_cvar_float(AMX *amx, cell *params)
|
||||
{
|
||||
int length;
|
||||
const char* name = get_amxstring(amx, params[1], 0, length);
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(name);
|
||||
|
||||
return info ? amx_ftoc(info->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);
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(name);
|
||||
|
||||
return info ? (int)info->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);
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(name);
|
||||
|
||||
const char *value = info ? info->var->string : "";
|
||||
length = info ? 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;
|
||||
const 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;
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(sCvar);
|
||||
|
||||
if (info)
|
||||
{
|
||||
info->var->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);
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(name);
|
||||
|
||||
if (info)
|
||||
{
|
||||
UTIL_Format(CVarTempBuffer, sizeof(CVarTempBuffer) - 1, "%f", amx_ctof(params[2]));
|
||||
CVAR_DIRECTSET(info->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];
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(name);
|
||||
|
||||
if (info)
|
||||
{
|
||||
UTIL_Format(CVarTempBuffer, sizeof(CVarTempBuffer) - 1, "%d", value);
|
||||
CVAR_DIRECTSET(info->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);
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(name);
|
||||
|
||||
if (info)
|
||||
{
|
||||
CVAR_DIRECTSET(info->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;
|
||||
}
|
||||
|
||||
// bool:get_pcvar_bool(pcvar)
|
||||
static cell AMX_NATIVE_CALL get_pcvar_bool(AMX *amx, cell *params)
|
||||
{
|
||||
return !!get_pcvar_num(amx, params);
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// get_pcvar_bounds(pcvar, CvarBounds:type, &Float:value)
|
||||
static cell AMX_NATIVE_CALL get_pcvar_bounds(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool hasBound = false;
|
||||
float bound;
|
||||
|
||||
switch (params[2])
|
||||
{
|
||||
case CvarBound_Lower:
|
||||
hasBound = info->bound.hasMin;
|
||||
bound = info->bound.minVal;
|
||||
break;
|
||||
case CvarBound_Upper:
|
||||
hasBound = info->bound.hasMax;
|
||||
bound = info->bound.maxVal;
|
||||
break;
|
||||
default:
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CvarBounds value: %d", params[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*get_amxaddr(amx, params[3]) = amx_ftoc(bound);
|
||||
|
||||
return hasBound;
|
||||
}
|
||||
|
||||
// bind_pcvar_float(pcvar, &Float:var)
|
||||
static cell AMX_NATIVE_CALL bind_pcvar_float(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return g_CvarManager.BindCvar(info, CvarBind::CvarType_Float, amx, params[2]);
|
||||
}
|
||||
|
||||
// bind_pcvar_num(pcvar, &any:var)
|
||||
static cell AMX_NATIVE_CALL bind_pcvar_num(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return g_CvarManager.BindCvar(info, CvarBind::CvarType_Int, amx, params[2]);
|
||||
}
|
||||
|
||||
// bind_pcvar_string(pcvar, any:var[], varlen)
|
||||
static cell AMX_NATIVE_CALL bind_pcvar_string(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return g_CvarManager.BindCvar(info, CvarBind::CvarType_String, amx, params[2], params[3]);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// set_pcvar_bounds(pcvar, CvarBounds:type, bool:set, Float:value = 0.0)
|
||||
static cell AMX_NATIVE_CALL set_pcvar_bounds(AMX *amx, cell *params)
|
||||
{
|
||||
cvar_t *ptr = reinterpret_cast<cvar_t *>(params[1]);
|
||||
CvarInfo* info = nullptr;
|
||||
|
||||
if (!ptr || !(info = g_CvarManager.FindCvar(ptr->name)))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CVAR pointer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool set = params[3] != 0;
|
||||
int pluginId = g_plugins.findPluginFast(amx)->getId();
|
||||
float value = amx_ctof(params[4]);
|
||||
|
||||
switch (params[2])
|
||||
{
|
||||
case CvarBound_Lower:
|
||||
{
|
||||
if (!g_CvarManager.SetCvarMin(info, set, value, pluginId))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "The minimum value can not be above the maximum value");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CvarBound_Upper:
|
||||
{
|
||||
if (!g_CvarManager.SetCvarMax(info, set, value, pluginId))
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "The maximum value can not be below the minimum value");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
LogError(amx, AMX_ERR_NATIVE, "Invalid CvarBounds value: %d", params[2]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
CvarInfo* info = g_CvarManager.FindCvar(sCvar);
|
||||
|
||||
if (info)
|
||||
{
|
||||
info->var->flags &= ~((int)(params[2]));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get_plugins_cvar(id, name[], namelen, &flags=0, &plugin_id=0, &pcvar_handle=0, description[]="", desc_len=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);
|
||||
|
||||
if (*params / sizeof(cell) >= 7)
|
||||
{
|
||||
set_amxstring(amx, params[7], info->description.chars(), params[8]);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
AMX_NATIVE_INFO g_CvarNatives[] =
|
||||
{
|
||||
{"create_cvar", create_cvar},
|
||||
{"register_cvar", register_cvar},
|
||||
{"cvar_exists", cvar_exists},
|
||||
{"get_cvar_pointer", get_cvar_pointer},
|
||||
|
||||
{"hook_cvar_change", hook_cvar_change},
|
||||
{"enable_cvar_hook", enable_cvar_hook},
|
||||
{"disable_cvar_hook", disable_cvar_hook},
|
||||
|
||||
{"get_cvar_flags", get_cvar_flags},
|
||||
{"get_cvar_float", get_cvar_float},
|
||||
{"get_cvar_num", get_cvar_num},
|
||||
{"get_cvar_string", get_cvar_string},
|
||||
|
||||
{"set_cvar_flags", set_cvar_flags},
|
||||
{"set_cvar_float", set_cvar_float},
|
||||
{"set_cvar_num", set_cvar_num},
|
||||
{"set_cvar_string", set_cvar_string},
|
||||
|
||||
{"get_pcvar_flags", get_pcvar_flags},
|
||||
{"get_pcvar_float", get_pcvar_float},
|
||||
{"get_pcvar_num", get_pcvar_num},
|
||||
{"get_pcvar_bool", get_pcvar_bool},
|
||||
{"get_pcvar_string", get_pcvar_string},
|
||||
{"get_pcvar_bounds", get_pcvar_bounds},
|
||||
|
||||
{"set_pcvar_flags", set_pcvar_flags},
|
||||
{"set_pcvar_float", set_pcvar_float},
|
||||
{"set_pcvar_num", set_pcvar_num},
|
||||
{"set_pcvar_bool", set_pcvar_num},
|
||||
{"set_pcvar_string", set_pcvar_string},
|
||||
{"set_pcvar_bounds", set_pcvar_bounds},
|
||||
|
||||
{"remove_cvar_flags", remove_cvar_flags},
|
||||
|
||||
{"bind_pcvar_float", bind_pcvar_float},
|
||||
{"bind_pcvar_num", bind_pcvar_num},
|
||||
{"bind_pcvar_string", bind_pcvar_string},
|
||||
|
||||
{"get_plugins_cvar", get_plugins_cvar},
|
||||
{"get_plugins_cvarsnum", get_plugins_cvarsnum},
|
||||
|
||||
{"query_client_cvar", query_client_cvar},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
|
@ -31,6 +31,7 @@
|
|||
#include "trie_natives.h"
|
||||
#include "CDataPack.h"
|
||||
#include "textparse.h"
|
||||
#include "CvarManager.h"
|
||||
|
||||
plugin_info_t Plugin_info =
|
||||
{
|
||||
|
@ -63,7 +64,6 @@ extern CVector<CAdminData *> DynamicAdmins;
|
|||
CLog g_log;
|
||||
CForwardMngr g_forwards;
|
||||
CList<CPlayer*> g_auth;
|
||||
CList<CCVar> g_cvars;
|
||||
CList<ForceObject> g_forcemodels;
|
||||
CList<ForceObject> g_forcesounds;
|
||||
CList<ForceObject> g_forcegeneric;
|
||||
|
@ -121,7 +121,7 @@ cvar_t init_amxmodx_modules = {"amxmodx_modules", "", FCVAR_SPONLY};
|
|||
cvar_t init_amxmodx_debug = {"amx_debug", "1", FCVAR_SPONLY};
|
||||
cvar_t init_amxmodx_mldebug = {"amx_mldebug", "", FCVAR_SPONLY};
|
||||
cvar_t init_amxmodx_language = {"amx_language", "en", FCVAR_SERVER};
|
||||
cvar_t init_amxmodx_cl_langs = {"amx_client_languages", "", FCVAR_SERVER};
|
||||
cvar_t init_amxmodx_cl_langs = {"amx_client_languages", "1", FCVAR_SERVER};
|
||||
cvar_t* amxmodx_version = NULL;
|
||||
cvar_t* amxmodx_modules = NULL;
|
||||
cvar_t* amxmodx_language = NULL;
|
||||
|
@ -697,6 +697,9 @@ void C_ServerDeactivate_Post()
|
|||
g_vault.clear();
|
||||
g_xvars.clear();
|
||||
g_plugins.clear();
|
||||
|
||||
g_CvarManager.OnPluginUnloaded();
|
||||
|
||||
ClearPluginLibraries();
|
||||
modules_callPluginsUnloaded();
|
||||
|
||||
|
@ -1489,6 +1492,8 @@ C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, m
|
|||
|
||||
FlagMan.SetFile("cmdaccess.ini");
|
||||
|
||||
g_CvarManager.CreateCvarHook();
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
@ -1517,7 +1522,6 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
|
|||
g_vault.clear();
|
||||
g_xvars.clear();
|
||||
g_plugins.clear();
|
||||
g_cvars.clear();
|
||||
g_langMngr.Clear();
|
||||
|
||||
ClearMessages();
|
||||
|
|
|
@ -553,6 +553,7 @@ int set_amxnatives(AMX* amx, char error[128])
|
|||
amx_Register(amx, g_DatapackNatives, -1);
|
||||
amx_Register(amx, g_StackNatives, -1);
|
||||
amx_Register(amx, g_TextParserNatives, -1);
|
||||
amx_Register(amx, g_CvarNatives, -1);
|
||||
|
||||
//we're not actually gonna check these here anymore
|
||||
amx->flags |= AMX_FLAG_PRENIT;
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\;..\..\public;..\..\public\sdk;..\..\public\amtl;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\;..\..\public;..\..\public\memtools;..\..\public\sdk;..\..\public\amtl;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;amxmodx_EXPORTS;PAWN_CELL_SIZE=32;ASM32;JIT;_CRT_SECURE_NO_DEPRECATE;HAVE_STDINT_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
|
@ -149,7 +149,7 @@
|
|||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>..\;..\..\public;..\..\public\sdk;..\..\public\amtl;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\;..\..\public;..\..\public\memtools;..\..\public\sdk;..\..\public\amtl;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;amxmodx_EXPORTS;JIT;ASM32;PAWN_CELL_SIZE=32;_CRT_SECURE_NO_DEPRECATE;HAVE_STDINT_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
|
||||
<StringPooling>true</StringPooling>
|
||||
|
@ -200,7 +200,7 @@
|
|||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\;..\..\public;..\..\public\sdk;..\..\public\amtl;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\;..\..\public;..\..\public\memtools;..\..\public\sdk;..\..\public\amtl;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;amxmodx_EXPORTS;PAWN_CELL_SIZE=32;ASM32;JIT;BINLOG_ENABLED;_CRT_SECURE_NO_DEPRECATE;HAVE_STDINT_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
|
@ -252,7 +252,7 @@
|
|||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>..\;..\..\public;..\..\public\sdk;..\..\public\amtl;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\;..\..\public;..\..\public\memtools;..\..\public\sdk;..\..\public\amtl;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\pm_shared;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;HAVE_STDINT_H;_USRDLL;amxmodx_EXPORTS;JIT;ASM32;PAWN_CELL_SIZE=32;BINLOG_ENABLED;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
|
||||
<StringPooling>true</StringPooling>
|
||||
|
@ -292,6 +292,8 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\public\memtools\CDetour\asm\asm.c" />
|
||||
<ClCompile Include="..\..\public\memtools\CDetour\detours.cpp" />
|
||||
<ClCompile Include="..\amx.cpp" />
|
||||
<ClCompile Include="..\amxcore.cpp" />
|
||||
<ClCompile Include="..\amxdbg.cpp" />
|
||||
|
@ -317,6 +319,8 @@
|
|||
<ClCompile Include="..\CPlugin.cpp" />
|
||||
<ClCompile Include="..\CTask.cpp" />
|
||||
<ClCompile Include="..\CTextParsers.cpp" />
|
||||
<ClCompile Include="..\CvarManager.cpp" />
|
||||
<ClCompile Include="..\cvars.cpp" />
|
||||
<ClCompile Include="..\CVault.cpp" />
|
||||
<ClCompile Include="..\datapacks.cpp" />
|
||||
<ClCompile Include="..\debugger.cpp" />
|
||||
|
@ -360,6 +364,9 @@
|
|||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\public\memtools\CDetour\asm\asm.h" />
|
||||
<ClInclude Include="..\..\public\memtools\CDetour\detourhelpers.h" />
|
||||
<ClInclude Include="..\..\public\memtools\CDetour\detours.h" />
|
||||
<ClInclude Include="..\amx.h" />
|
||||
<ClInclude Include="..\amxdbg.h" />
|
||||
<ClInclude Include="..\amxmodx.h" />
|
||||
|
@ -383,6 +390,7 @@
|
|||
<ClInclude Include="..\CString.h" />
|
||||
<ClInclude Include="..\CTask.h" />
|
||||
<ClInclude Include="..\CTextParsers.h" />
|
||||
<ClInclude Include="..\CvarManager.h" />
|
||||
<ClInclude Include="..\CVault.h" />
|
||||
<ClInclude Include="..\CVector.h" />
|
||||
<ClInclude Include="..\datastructs.h" />
|
||||
|
@ -414,6 +422,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\plugins\include\cellstack.inc" />
|
||||
<None Include="..\..\plugins\include\cvars.inc" />
|
||||
<None Include="..\..\plugins\include\datapack.inc" />
|
||||
<None Include="..\..\plugins\include\textparse_ini.inc" />
|
||||
<None Include="..\..\plugins\include\textparse_smc.inc" />
|
||||
|
|
|
@ -25,6 +25,15 @@
|
|||
<Filter Include="Pawn Includes">
|
||||
<UniqueIdentifier>{4022451d-eb5f-4f14-b8d8-2ce23fec6e59}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Memtools">
|
||||
<UniqueIdentifier>{a1f7babf-acb1-4a06-92e9-e8a411e1f02a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Memtools\CDetour">
|
||||
<UniqueIdentifier>{8b35d490-2b01-4997-ba02-5e2cfd9c9017}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Memtools\CDetour\asm">
|
||||
<UniqueIdentifier>{64a22cd4-3715-45de-8af2-e54017733be6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\amx.cpp">
|
||||
|
@ -183,6 +192,18 @@
|
|||
<ClCompile Include="..\..\public\sdk\amxxmodule.cpp">
|
||||
<Filter>SDK</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\public\memtools\CDetour\detours.cpp">
|
||||
<Filter>Memtools\CDetour</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\public\memtools\CDetour\asm\asm.c">
|
||||
<Filter>Memtools\CDetour\asm</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\CvarManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\cvars.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\amx.h">
|
||||
|
@ -329,6 +350,18 @@
|
|||
<ClInclude Include="..\..\public\sdk\moduleconfig.h">
|
||||
<Filter>SDK</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\public\memtools\CDetour\detourhelpers.h">
|
||||
<Filter>Memtools\CDetour</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\public\memtools\CDetour\detours.h">
|
||||
<Filter>Memtools\CDetour</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\public\memtools\CDetour\asm\asm.h">
|
||||
<Filter>Memtools\CDetour\asm</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\CvarManager.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\version.rc">
|
||||
|
@ -423,6 +456,9 @@
|
|||
<None Include="..\..\plugins\include\textparse_smc.inc">
|
||||
<Filter>Pawn Includes</Filter>
|
||||
</None>
|
||||
<None Include="..\..\plugins\include\cvars.inc">
|
||||
<Filter>Pawn Includes</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Object Include="..\Jit\helpers-x86.obj">
|
||||
|
|
|
@ -30,3 +30,19 @@ NONGPL_CVAR_T NONGPL_CVAR_LIST[] =
|
|||
{"amx_gg", 1},
|
||||
{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_CVAR_T NONGPL_CVAR_LIST[];
|
||||
extern bool CheckBadConList(const char *cvar, int type);
|
||||
|
||||
#endif //_INCLUDE_AMXMODX_NONGPL_MATCHES_H_
|
||||
|
|
|
@ -16,7 +16,6 @@ void amx_command()
|
|||
|
||||
if (!strcmp(cmd, "plugins") || !strcmp(cmd, "list"))
|
||||
{
|
||||
|
||||
print_srvconsole("Currently loaded plugins:\n");
|
||||
print_srvconsole(" %-23.22s %-11.10s %-17.16s %-16.15s %-9.8s\n", "name", "version", "author", "file", "status");
|
||||
|
||||
|
@ -45,7 +44,8 @@ void amx_command()
|
|||
{
|
||||
//error
|
||||
print_srvconsole("(%3d) Load fails: %s\n", num, (*a).getError());
|
||||
} else if ( (*a).getStatusCode() == ps_error) {
|
||||
}
|
||||
else if ((*a).getStatusCode() == ps_error) {
|
||||
//error
|
||||
print_srvconsole("(%3d) Error: %s\n", num, (*a).getError());
|
||||
}
|
||||
|
@ -105,38 +105,14 @@ void amx_command()
|
|||
else if (!plugin)
|
||||
{
|
||||
print_srvconsole("Couldn't find plugin matching \"%s\"\n", sPlugin);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
print_srvconsole("Plugin %s can't be unpaused right now.\n", sPlugin);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(cmd, "cvars"))
|
||||
{
|
||||
print_srvconsole("Registered cvars:\n");
|
||||
print_srvconsole(" %-24.23s %-24.23s %-16.15s\n", "name", "value", "plugin");
|
||||
|
||||
int ammount = 0;
|
||||
|
||||
if (CMD_ARGC() > 2) // Searching for cvars registered to a plugin
|
||||
{
|
||||
const char* targetname = CMD_ARGV(2);
|
||||
size_t len = strlen(targetname);
|
||||
for (CList<CCVar>::iterator a = g_cvars.begin(); a; ++a)
|
||||
{
|
||||
if (strncmp((*a).getPluginName(), targetname, len) == 0)
|
||||
{
|
||||
print_srvconsole(" [%3d] %-24.23s %-24.23s %-16.15s\n", ++ammount, (*a).getName(), CVAR_GET_STRING((*a).getName()), (*a).getPluginName());
|
||||
}
|
||||
}
|
||||
}
|
||||
else // No search
|
||||
{
|
||||
for (CList<CCVar>::iterator a = g_cvars.begin(); a; ++a)
|
||||
{
|
||||
print_srvconsole(" [%3d] %-24.23s %-24.23s %-16.15s\n", ++ammount, (*a).getName(), CVAR_GET_STRING((*a).getName()), (*a).getPluginName());
|
||||
}
|
||||
}
|
||||
|
||||
print_srvconsole("%d cvars\n", ammount);
|
||||
g_CvarManager.OnConsoleCommand();
|
||||
}
|
||||
else if (!strcmp(cmd, "cmds"))
|
||||
{
|
||||
|
@ -254,14 +230,16 @@ void amx_command()
|
|||
print_srvconsole("\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x3A\x78\x78\x24\x40\x4E\x4E\x4D\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5E\x3E\x3E\x3F\x3E\x3E\x3E\x3E\x3B\x3B\x3B\x3A\x3A\x3F\x3E\x3A\x2E\x2E\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2E\x45\x4D\x40\x45\x78\x5E\x33\x68\x33\x2B\n");
|
||||
print_srvconsole("\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x24\x48\x45\x48\x78\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2B\x4E\x40\x2B\x66\x33\x78\x20\x20\n");
|
||||
print_srvconsole("\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2B\x2C\x20\x3A\x20\x20\n");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
print_srvconsole("Usage: amxx < command > [ argument ]\n");
|
||||
print_srvconsole("Commands:\n");
|
||||
print_srvconsole(" version - display amxx version info\n");
|
||||
print_srvconsole(" gpl - print the license\n");
|
||||
print_srvconsole(" plugins - list plugins currently loaded\n");
|
||||
print_srvconsole(" modules - list modules currently loaded\n");
|
||||
print_srvconsole(" cvars [ plugin ] - list cvars registered by plugins\n");
|
||||
print_srvconsole(" cvars [ plugin ] [ index ] - list cvars handled by amxx or show information about a cvar if index is provided\n");
|
||||
print_srvconsole(" cmds [ plugin ] - list commands registered by plugins\n");
|
||||
print_srvconsole(" pause < plugin > - pause a running plugin\n");
|
||||
print_srvconsole(" unpause < plugin > - unpause a previously paused plugin\n");
|
||||
|
|
|
@ -65,6 +65,20 @@ cell* get_amxaddr(AMX *amx, cell amx_addr)
|
|||
return (cell *)(amx->base + (int)(((AMX_HEADER *)amx->base)->dat + amx_addr));
|
||||
}
|
||||
|
||||
int set_amxstring_simple(cell *dest, const char *source, int max)
|
||||
{
|
||||
cell* start = dest;
|
||||
|
||||
while (max-- && *source)
|
||||
{
|
||||
*dest++ = (unsigned char)*source++;
|
||||
}
|
||||
|
||||
*dest = 0;
|
||||
|
||||
return dest - start;
|
||||
}
|
||||
|
||||
int set_amxstring(AMX *amx, cell amx_addr, const char *source, int max)
|
||||
{
|
||||
register cell* dest = (cell *)(amx->base + (int)(((AMX_HEADER *)amx->base)->dat + amx_addr));
|
||||
|
|
|
@ -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_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
|
||||
*/
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <newmenus>
|
||||
#include <textparse_smc>
|
||||
#include <textparse_ini>
|
||||
#include <cvars>
|
||||
|
||||
/**
|
||||
* Called just after server activation.
|
||||
|
@ -1403,159 +1404,6 @@ native amxclient_cmd(index, const command[], const arg1[]="", const arg2[]="");
|
|||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -1963,31 +1811,6 @@ native get_concmd_plid(cid, flag_mask, id_type);
|
|||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -2057,23 +1880,6 @@ native server_exec();
|
|||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -2805,35 +2611,6 @@ native set_array(param, const 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.
|
||||
*
|
||||
|
@ -3219,110 +2996,6 @@ native ExecuteForward(forward_handle, &ret, any:...);
|
|||
*/
|
||||
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.
|
||||
*
|
||||
|
|
524
plugins/include/cvars.inc
Normal file
524
plugins/include/cvars.inc
Normal file
|
@ -0,0 +1,524 @@
|
|||
// 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
|
||||
|
||||
#if defined _cvars_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _cvars_included
|
||||
|
||||
/**
|
||||
* CVAR flags for create_cvar()
|
||||
*/
|
||||
#define FCVAR_NONE 0 /* No flags */
|
||||
#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 */
|
||||
|
||||
/**
|
||||
* Creates a new cvar for the engine.
|
||||
*
|
||||
* @note This has the same effect as register_cvar but provides more options.
|
||||
* @note For a list of possible cvar flags see FCVAR_* constants above.
|
||||
* @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 Optional bitsum of flags specifying cvar behavior
|
||||
* @param description Optional description of the cvar
|
||||
* @param has_min Optional boolean that specifies if the cvar has a minimum value
|
||||
* @param min_val Minimum floating point value
|
||||
* @param has_max Optional boolean that specifies if the cvar has a maximum value
|
||||
* @param max_val Maximum floating point value
|
||||
*
|
||||
* @return Unique cvar pointer
|
||||
*/
|
||||
native create_cvar(const name[], const string[], flags = FCVAR_NONE, const description[] = "", bool:has_min = false, Float:min_val = 0.0, bool:has_max = false, Float:max_val = 0.0);
|
||||
|
||||
/**
|
||||
* Registers a new cvar for the engine.
|
||||
*
|
||||
* @note Deprecated. Consider to use create_cvar for more options.
|
||||
* @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 Optional bitsum of flags specifying cvar behavior
|
||||
* @param fvalue Unused
|
||||
*
|
||||
* @return Unique cvar pointer
|
||||
*/
|
||||
native register_cvar(const name[], const string[], flags = FCVAR_NONE, 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 cvar's value is changed.
|
||||
*
|
||||
* @note Changing the cvar value from within this forward can lead to infinite
|
||||
* recursion and should be avoided.
|
||||
* @note Callback will be called in the following manner:
|
||||
*
|
||||
* public cvar_change_callback(pcvar, const old_value[], const new_value[])
|
||||
*
|
||||
* pcvar - Pointer to cvar that was changed
|
||||
* old_value - String containing the value of the cvar before it was changed
|
||||
* new_value - String containing the new value of the cvar
|
||||
*
|
||||
* The return value is ignored
|
||||
*
|
||||
* @param pcvar Pointer to cvar
|
||||
* @param callback Name of callback function
|
||||
*
|
||||
* @return Callback handle that can be used with [disable|enable]_cvar_hook
|
||||
* @error Invalid cvar pointer or invalid callback function
|
||||
*/
|
||||
native cvarhook:hook_cvar_change(pcvar, const callback[]);
|
||||
|
||||
/**
|
||||
* Stops a cvar hook forward from triggering.
|
||||
*
|
||||
* @note Use the handle returned by hook_cvar_change as the parameter here.
|
||||
*
|
||||
* @param handle Forward to stop
|
||||
* @error Invalid hook handle
|
||||
*/
|
||||
native disable_cvar_hook(cvarhook:handle);
|
||||
|
||||
/**
|
||||
* Starts a cvar hook forward back up.
|
||||
*
|
||||
* @note Use the handle returned by hook_cvar_change as the parameter here.
|
||||
*
|
||||
* @param handle Forward to back up
|
||||
* @error Invalid hook 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);
|
||||
|
||||
/**
|
||||
* Returns an boolean value from a cvar via direct pointer access.
|
||||
*
|
||||
* @param pcvar Pointer to cvar to retrieve value from
|
||||
*
|
||||
* @return Cvar value, converted to bool
|
||||
* @error If an invalid cvar pointer is specified, an error is thrown.
|
||||
*/
|
||||
native bool:get_pcvar_bool(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);
|
||||
|
||||
/**
|
||||
* Sets a boolean 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_bool(pcvar, bool: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[]);
|
||||
|
||||
/**
|
||||
* Cvar bound values used with get/set_pcvar_bounds()
|
||||
*/
|
||||
enum CvarBounds
|
||||
{
|
||||
CvarBound_Upper = 0,
|
||||
CvarBound_Lower
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the specified value bounds of a cvar.
|
||||
*
|
||||
* @param pcvar Pointer to cvar
|
||||
* @param type Type of bound to retrieve, CvarBound_Lower or CvarBound_Upper
|
||||
* @param value Variable to store the specified bound to
|
||||
*
|
||||
* @return True if the cvar has the specified bound set, false otherwise.
|
||||
* @error If an invalid cvar pointer or CvarBounds value, an error is thrown.
|
||||
*/
|
||||
native bool:get_pcvar_bounds(pcvar, CvarBounds:type, &Float:value);
|
||||
|
||||
/**
|
||||
* Sets the specified bounds of a cvar.
|
||||
*
|
||||
* @param pcvar Pointer to cvar
|
||||
* @param type Type of bound to set, CvarBound_Lower or CvarBound_Upper
|
||||
* @param set If set to true, cvar will use specified bound. If false, bound will be removed
|
||||
* @param value Floating point value to use as the specified bound
|
||||
*
|
||||
* @error If an invalid cvar pointer or CvarBounds value, an error is thrown.
|
||||
*/
|
||||
native set_pcvar_bounds(pcvar, CvarBounds:type, bool:set, Float:value = 0.0);
|
||||
|
||||
/**
|
||||
* Binds a cvar's integer value to a global variable. The variable will then
|
||||
* always contain the current cvar value as it is automatically kept up to date.
|
||||
*
|
||||
* @note The variable *has* to be a global or a static variable. Local variables
|
||||
* created within functions can not be used for technical reasons.
|
||||
* @note Variables can not be bound to multiple cvars.
|
||||
*
|
||||
* @param pcvar Pointer to cvar
|
||||
* @param var Global variable to keep updated
|
||||
*
|
||||
* @error Invalid cvar pointer, invalid provided variable or cvar/variable already binded.
|
||||
*/
|
||||
native bind_pcvar_num(pcvar, &any:var);
|
||||
|
||||
/**
|
||||
* Binds a cvar's float value to a global variable. The variable will then
|
||||
* always contain the current cvar value as it is automatically kept up to date.
|
||||
*
|
||||
* @note The variable *has* to be a global or a static variable. Local variables
|
||||
* created within functions can not be used for technical reasons.
|
||||
* @note Variables can not be bound to multiple cvars.
|
||||
*
|
||||
* @param pcvar Pointer to cvar
|
||||
* @param var Global variable to keep updated
|
||||
*
|
||||
* @error Invalid cvar pointer, invalid provided variable or cvar/variable already binded.
|
||||
*/
|
||||
native bind_pcvar_float(pcvar, &Float:var);
|
||||
|
||||
/**
|
||||
* Binds a cvar's string value to a global array. The array will then
|
||||
* always contain the current cvar value as it is automatically kept up to date.
|
||||
*
|
||||
* @note The array *has* to be a global or a static array. Local arrays
|
||||
* created within functions can not be used for technical reasons.
|
||||
* @note Arrays can not be bound to multiple cvars.
|
||||
*
|
||||
* @param pcvar Pointer to cvar
|
||||
* @param var Global array to keep updated
|
||||
* @param varlen Maximum length of string array
|
||||
*
|
||||
* @error Invalid cvar pointer, invalid provided variable or cvar/variable already binded.
|
||||
*/
|
||||
native bind_pcvar_string(pcvar, any:var[], varlen);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param description Variable to store cvar description to
|
||||
* @param desc_len Maximum length of string buffer
|
||||
*
|
||||
* @return 1 on success, 0 if index is invalid
|
||||
*/
|
||||
native get_plugins_cvar(num, name[], namelen, &flags=0, &plugin_id=0, &pcvar_handle=0, description[]="", desc_len=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[]="");
|
|
@ -29,8 +29,8 @@ public plugin_init()
|
|||
register_dictionary("common.txt")
|
||||
register_dictionary("languages.txt")
|
||||
|
||||
g_cvarClientLanguages = register_cvar("amx_client_languages", "1")
|
||||
g_cvarDisplayClientMessage = register_cvar("amx_language_display_msg", "1")
|
||||
g_cvarClientLanguages = get_cvar_pointer("amx_client_languages")
|
||||
g_cvarServerLanguage = get_cvar_pointer("amx_language");
|
||||
|
||||
register_clcmd("amx_langmenu", "cmdLangMenu", ADMIN_ALL)
|
||||
|
|
153
public/auto-string.h
Normal file
153
public/auto-string.h
Normal file
|
@ -0,0 +1,153 @@
|
|||
/* vim: set ts=2 sw=2 tw=99 et:
|
||||
*
|
||||
* Copyright (C) 2012 David Anderson
|
||||
*
|
||||
* This file is part of SourcePawn.
|
||||
*
|
||||
* SourcePawn is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* SourcePawn. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
#ifndef _include_auto_string_h_
|
||||
#define _include_auto_string_h_
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <am-string.h>
|
||||
|
||||
using namespace ke;
|
||||
|
||||
class AutoString
|
||||
{
|
||||
public:
|
||||
AutoString() : ptr_(NULL), length_(0)
|
||||
{
|
||||
}
|
||||
AutoString(AutoString &&other)
|
||||
: ptr_(other.ptr_),
|
||||
length_(other.length_)
|
||||
{
|
||||
other.ptr_ = nullptr;
|
||||
other.length_ = 0;
|
||||
}
|
||||
AutoString(const char *ptr)
|
||||
{
|
||||
assign(ptr);
|
||||
}
|
||||
AutoString(const AString &str)
|
||||
{
|
||||
assign(str.chars(), str.length());
|
||||
}
|
||||
AutoString(const char *ptr, size_t len)
|
||||
{
|
||||
assign(ptr, len);
|
||||
}
|
||||
AutoString(const AutoString &other)
|
||||
{
|
||||
assign(other.ptr(), other.length());
|
||||
}
|
||||
~AutoString()
|
||||
{
|
||||
free(ptr_);
|
||||
}
|
||||
|
||||
AutoString &operator =(const char *ptr) {
|
||||
free(ptr_);
|
||||
assign(ptr);
|
||||
return *this;
|
||||
}
|
||||
AutoString &operator =(const AutoString &other) {
|
||||
free(ptr_);
|
||||
assign(other.ptr(), other.length());
|
||||
return *this;
|
||||
}
|
||||
AutoString &operator =(AutoString &&other) {
|
||||
Swap(other.ptr_, ptr_);
|
||||
Swap(other.length_, length_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
AutoString operator +(const AutoString &other) const {
|
||||
size_t len = length() + other.length();
|
||||
char *buf = (char *)malloc(len + 1);
|
||||
memcpy(buf, ptr(), length());
|
||||
memcpy(buf + length(), other.ptr(), other.length());
|
||||
buf[len] = '\0';
|
||||
|
||||
AutoString r;
|
||||
r.ptr_ = buf;
|
||||
r.length_ = len;
|
||||
return r;
|
||||
}
|
||||
|
||||
AutoString operator +(const char *other) const {
|
||||
size_t other_length = strlen(other);
|
||||
size_t len = length() + other_length;
|
||||
char *buf = (char *)malloc(len + 1);
|
||||
memcpy(buf, ptr(), length());
|
||||
memcpy(buf + length(), other, other_length);
|
||||
buf[len] = '\0';
|
||||
|
||||
AutoString r;
|
||||
r.ptr_ = buf;
|
||||
r.length_ = len;
|
||||
return r;
|
||||
}
|
||||
|
||||
AutoString operator +(unsigned val) const {
|
||||
char buffer[24];
|
||||
_snprintf(buffer, sizeof(buffer), "%d", val);
|
||||
return *this + buffer;
|
||||
}
|
||||
|
||||
size_t length() const {
|
||||
return length_;
|
||||
}
|
||||
|
||||
bool operator !() const {
|
||||
return !length_;
|
||||
}
|
||||
|
||||
const char *ptr() const {
|
||||
return ptr_ ? ptr_ : "";
|
||||
}
|
||||
operator const char *() const {
|
||||
return ptr();
|
||||
}
|
||||
|
||||
private:
|
||||
void assign(const char *ptr) {
|
||||
if (!ptr) {
|
||||
ptr_ = NULL;
|
||||
length_ = 0;
|
||||
return;
|
||||
}
|
||||
assign(ptr, strlen(ptr));
|
||||
}
|
||||
void assign(const char *ptr, size_t length) {
|
||||
if (!ptr) {
|
||||
ptr_ = NULL;
|
||||
length_ = 0;
|
||||
return;
|
||||
}
|
||||
length_ = length;
|
||||
ptr_ = (char *)malloc(length_ + 1);
|
||||
memcpy(ptr_, ptr, length_);
|
||||
ptr_[length_] = '\0';
|
||||
}
|
||||
|
||||
private:
|
||||
char *ptr_;
|
||||
size_t length_;
|
||||
};
|
||||
|
||||
#endif // _include_spcomp_auto_string_h_
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 4096
|
||||
#endif
|
||||
|
|
|
@ -32,10 +32,12 @@
|
|||
#ifndef _INCLUDE_SOURCEMOD_DETOURS_H_
|
||||
#define _INCLUDE_SOURCEMOD_DETOURS_H_
|
||||
|
||||
#include "amxxmodule.h"
|
||||
//#include <jit/jit_helpers.h>
|
||||
//#include <jit/x86/x86_macros.h>
|
||||
#include "detourhelpers.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int32_t cell;
|
||||
|
||||
/**
|
||||
* CDetours class for SourceMod Extensions by pRED*
|
||||
|
|
201
public/sm_namehashset.h
Normal file
201
public/sm_namehashset.h
Normal file
|
@ -0,0 +1,201 @@
|
|||
/**
|
||||
* vim: set ts=4 sw=4 tw=99 noet :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _include_sourcemod_namehashset_h_
|
||||
#define _include_sourcemod_namehashset_h_
|
||||
|
||||
/**
|
||||
* @file sm_namehashset.h
|
||||
*
|
||||
* @brief Stores a set of uniquely named objects.
|
||||
*/
|
||||
|
||||
#include <am-allocator-policies.h>
|
||||
#include <am-hashmap.h>
|
||||
#include <am-string.h>
|
||||
#include <sm_stringhashmap.h>
|
||||
|
||||
//namespace SourceMod
|
||||
//{
|
||||
|
||||
// The HashPolicy type must have this method:
|
||||
// static bool matches(const char *key, const T &value);
|
||||
//
|
||||
// Depending on what lookup types are used.
|
||||
//
|
||||
// If these members are available on T, then the HashPolicy type can be left
|
||||
// default. It is okay to use |T *|, the functions will still be looked up
|
||||
// on |T|.
|
||||
template <typename T, typename KeyPolicy = T>
|
||||
class NameHashSet : public ke::SystemAllocatorPolicy
|
||||
{
|
||||
typedef detail::CharsAndLength CharsAndLength;
|
||||
|
||||
// Default policy type: the two types are different. Use them directly.
|
||||
template <typename KeyType, typename KeyPolicyType>
|
||||
struct Policy
|
||||
{
|
||||
typedef KeyType Payload;
|
||||
|
||||
static uint32_t hash(const CharsAndLength &key)
|
||||
{
|
||||
return key.hash();
|
||||
}
|
||||
|
||||
static bool matches(const CharsAndLength &key, const KeyType &value)
|
||||
{
|
||||
return KeyPolicyType::matches(key.chars(), value);
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization: the types are equal, and T is a pointer. Strip the
|
||||
// pointer off so we can access T:: for match functions.
|
||||
template <typename KeyType>
|
||||
struct Policy<KeyType *, KeyType *>
|
||||
{
|
||||
typedef KeyType *Payload;
|
||||
|
||||
static uint32_t hash(const detail::CharsAndLength &key)
|
||||
{
|
||||
return key.hash();
|
||||
}
|
||||
|
||||
static bool matches(const CharsAndLength &key, const KeyType *value)
|
||||
{
|
||||
return KeyType::matches(key.chars(), value);
|
||||
}
|
||||
};
|
||||
|
||||
typedef ke::HashTable<Policy<T, KeyPolicy>, ke::SystemAllocatorPolicy> Internal;
|
||||
|
||||
public:
|
||||
NameHashSet()
|
||||
{
|
||||
if (!table_.init())
|
||||
this->reportOutOfMemory();
|
||||
}
|
||||
|
||||
typedef typename Internal::Result Result;
|
||||
typedef typename Internal::Insert Insert;
|
||||
typedef typename Internal::iterator iterator;
|
||||
|
||||
Result find(const char *aKey)
|
||||
{
|
||||
return table_.find(aKey);
|
||||
}
|
||||
|
||||
Insert findForAdd(const char *aKey)
|
||||
{
|
||||
return table_.findForAdd(aKey);
|
||||
}
|
||||
|
||||
void add(Insert &i, const T &value)
|
||||
{
|
||||
return table_.add(i, value);
|
||||
}
|
||||
|
||||
void add(Insert &i, T &&value)
|
||||
{
|
||||
return table_.add(i, value);
|
||||
}
|
||||
|
||||
bool retrieve(const char *aKey, T *value)
|
||||
{
|
||||
CharsAndLength key(aKey);
|
||||
Result r = table_.find(aKey);
|
||||
if (!r.found())
|
||||
return false;
|
||||
*value = *r;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool insert(const char *aKey, const T &value)
|
||||
{
|
||||
CharsAndLength key(aKey);
|
||||
Insert i = table_.findForAdd(key);
|
||||
if (i.found())
|
||||
return false;
|
||||
return table_.add(i, value);
|
||||
}
|
||||
|
||||
bool insert(const char *aKey, T &&value)
|
||||
{
|
||||
CharsAndLength key(aKey);
|
||||
Insert i = table_.findForAdd(key);
|
||||
if (i.found())
|
||||
return false;
|
||||
return table_.add(i, value);
|
||||
}
|
||||
|
||||
bool contains(const char *aKey)
|
||||
{
|
||||
CharsAndLength key(aKey);
|
||||
Result r = table_.find(aKey);
|
||||
return r.found();
|
||||
}
|
||||
|
||||
bool remove(const char *aKey)
|
||||
{
|
||||
CharsAndLength key(aKey);
|
||||
Result r = table_.find(key);
|
||||
if (!r.found())
|
||||
return false;
|
||||
table_.remove(r);
|
||||
return true;
|
||||
}
|
||||
|
||||
void remove(Result &r)
|
||||
{
|
||||
table_.remove(r);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
table_.clear();
|
||||
}
|
||||
|
||||
size_t mem_usage() const
|
||||
{
|
||||
return table_.estimateMemoryUse();
|
||||
}
|
||||
|
||||
iterator iter()
|
||||
{
|
||||
return iterator(&table_);
|
||||
}
|
||||
|
||||
private:
|
||||
Internal table_;
|
||||
};
|
||||
|
||||
//}
|
||||
|
||||
#endif // _include_sourcemod_namehashset_h_
|
|
@ -245,6 +245,7 @@ scripting_files = [
|
|||
'include/csstats.inc',
|
||||
'include/cstrike.inc',
|
||||
'include/csx.inc',
|
||||
'include/cvars.inc',
|
||||
'include/datapack.inc',
|
||||
'include/dbi.inc',
|
||||
'include/dodconst.inc',
|
||||
|
|
Loading…
Reference in New Issue
Block a user