From d75b14d4afc4f9e402ddde5f4e5dce885838f67f Mon Sep 17 00:00:00 2001 From: Arkshine Date: Tue, 27 Jan 2015 01:49:57 +0100 Subject: [PATCH] Cvars: Extend "amxx cvars" command output --- amxmodx/CvarManager.cpp | 149 +++++++++++++++++++++++++++++++++----- amxmodx/CvarManager.h | 56 ++++++++++----- amxmodx/cvars.cpp | 29 ++++---- amxmodx/srvcmd.cpp | 16 ++--- public/auto-string.h | 153 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 349 insertions(+), 54 deletions(-) create mode 100644 public/auto-string.h diff --git a/amxmodx/CvarManager.cpp b/amxmodx/CvarManager.cpp index b5668007..b24d79f8 100644 --- a/amxmodx/CvarManager.cpp +++ b/amxmodx/CvarManager.cpp @@ -10,6 +10,7 @@ #include "CvarManager.h" #include "amxmodx.h" #include +#include CvarManager g_CvarManager; @@ -27,20 +28,20 @@ bool Cvar_DirectSet_Custom(cvar_t* var, const char* value) return true; } - if (info->hasMin || info->hasMax) // cvar_s doesn't have min/max mechanism, so we check things here. + 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->hasMin && fvalue < info->minVal) + if (info->bound.hasMin && fvalue < info->bound.minVal) { oob = true; - fvalue = info->minVal; + fvalue = info->bound.minVal; } - else if (info->hasMax && fvalue > info->maxVal) + else if (info->bound.hasMax && fvalue > info->bound.maxVal) { oob = true; - fvalue = info->maxVal; + fvalue = info->bound.maxVal; } if (oob) // Found value out of bound, set new value and block original call. @@ -58,7 +59,7 @@ bool Cvar_DirectSet_Custom(cvar_t* var, const char* value) { CvarHook* hook = info->hooks[i]; - if (hook->forward->state == Forward::FSTATE_OK) // Our callback can be enable/disabled by natives. + if (hook->forward->state == AutoForward::FSTATE_OK) // Our callback can be enable/disabled by natives. { int result = executeForwards(hook->forward->id, reinterpret_cast(var), var->string, value); @@ -295,7 +296,7 @@ bool CvarManager::CacheLookup(const char* name, CvarInfo** info) return m_Cache.retrieve(name, info); } -Forward* CvarManager::HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback) +AutoForward* CvarManager::HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback) { CvarInfo* info = nullptr; @@ -329,7 +330,7 @@ Forward* CvarManager::HookCvarChange(cvar_t* var, AMX* amx, cell param, const ch // Detour is disabled on map change. m_HookDetour->EnableDetour(); - Forward* forward = new Forward(forwardId, *callback); + AutoForward* forward = new AutoForward(forwardId, *callback); info->hooks.append(new CvarHook(g_plugins.findPlugin(amx)->getId(), forward)); return forward; @@ -340,26 +341,141 @@ 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() { - print_srvconsole("Registered cvars:\n"); - print_srvconsole(" %-24.23s %-24.23s %-16.15s\n", "name", "value", "plugin"); - size_t index = 0; - ke::AString pluginName; + size_t indexToSearch = 0; + ke::AString partialName; - if (CMD_ARGC() > 2) // Searching for cvars registered to a plugin + int argcount = CMD_ARGC(); + + // amxx cvars + // 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) { - pluginName = CMD_ARGV(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", "BINDED", "HOOKED", "BOUNDED"); + print_srvconsole(" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n"); + } for (CvarsList::iterator iter = m_Cvars.begin(); iter != m_Cvars.end(); iter++) { CvarInfo* ci = (*iter); - if (ci->amxmodx && (!pluginName.length() || strncmp(ci->name.chars(), pluginName.chars(), pluginName.length()) == 0)) + // List any cvars having a status either created, hooked, binded or bounded 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)) { - print_srvconsole(" [%3d] %-24.23s %-24.23s %-16.15s\n", ++index, ci->name.chars(), ci->var->string, ci->plugin.chars()); + 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 Bounded %-26.25s %f\n", g_plugins.findPlugin(ci->bound.minPluginId)->getName(), ci->bound.minVal); + } + + if (ci->bound.hasMax) + { + print_srvconsole(" Max Bounded %-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(" Binded %-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; + } } } } @@ -391,6 +507,7 @@ void CvarManager::OnPluginUnloaded() 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) diff --git a/amxmodx/CvarManager.h b/amxmodx/CvarManager.h index f6c250a5..5da648c7 100644 --- a/amxmodx/CvarManager.h +++ b/amxmodx/CvarManager.h @@ -23,7 +23,7 @@ enum CvarBounds CvarBound_Lower }; -struct Forward +struct AutoForward { enum fwdstate { @@ -32,10 +32,10 @@ struct Forward FSTATE_STOP, }; - Forward(int id_, const char* handler) : id(id_), state(FSTATE_OK), callback(handler) {}; - Forward() : id(-1) , state(FSTATE_INVALID) {}; + AutoForward(int id_, const char* handler) : id(id_), state(FSTATE_OK), callback(handler) {}; + AutoForward() : id(-1) , state(FSTATE_INVALID) {}; - ~Forward() + ~AutoForward() { unregisterSPForward(id); } @@ -47,11 +47,11 @@ struct Forward struct CvarHook { - CvarHook(int id, Forward* fwd) : pluginId(id), forward(fwd) {}; - CvarHook(int id) : pluginId(id), forward(new Forward()) {}; + CvarHook(int id, AutoForward* fwd) : pluginId(id), forward(fwd) {}; + CvarHook(int id) : pluginId(id), forward(new AutoForward()) {}; int pluginId; - ke::AutoPtr forward; + ke::AutoPtr forward; }; struct CvarBind @@ -65,7 +65,10 @@ struct CvarBind CvarBind(int id_, CvarType type_, cell* varAddress_, size_t varLength_) : - pluginId(id_), type(type_), varAddress(varAddress_), varLength(varLength_) {}; + pluginId(id_), + type(type_), + varAddress(varAddress_), + varLength(varLength_) {}; int pluginId; CvarType type; @@ -73,8 +76,30 @@ struct CvarBind size_t varLength; }; +struct CvarBound +{ + CvarBound(bool hasMin_, float minVal_, bool hasMax_, float maxVal_, int minPluginId_, int maxPluginId_) + : + hasMin(hasMin_), hasMax(hasMax_), + minVal(minVal_), maxVal(maxVal_), + minPluginId(minPluginId_), + maxPluginId(maxPluginId_) {}; + + CvarBound() + : + hasMin(false), hasMax(false), + minVal(0), maxVal(0) {}; + + bool hasMin; + bool hasMax; + float minVal; + float maxVal; + int minPluginId; + int maxPluginId; +}; + typedef ke::Vector CvarsHook; -typedef ke::Vector CvarsBind; +typedef ke::Vector CvarsBind; struct CvarInfo : public ke::InlineListNode { @@ -83,29 +108,26 @@ struct CvarInfo : public ke::InlineListNode const char* plugin_, int pluginId_) : name(name_), description(helpText), - hasMin(hasMin_), minVal(min_), hasMax(hasMax_), maxVal(max_), + bound(hasMin_, min_, hasMax_, max_, pluginId_, pluginId_), plugin(plugin_), pluginId(pluginId_) {}; CvarInfo(const char* name_) : name(name_), defaultval(""), description(""), - hasMin(false), minVal(0), hasMax(false), maxVal(0), - plugin(""), pluginId(-1), amxmodx(false) {}; + bound(), plugin(""), pluginId(-1), amxmodx(false) {}; cvar_t* var; ke::AString name; ke::AString defaultval; ke::AString description; - bool hasMin; - bool hasMax; - float minVal; - float maxVal; ke::AString plugin; int pluginId; + CvarBound bound; CvarsBind binds; CvarsHook hooks; + bool amxmodx; static inline bool matches(const char *name, const CvarInfo* info) @@ -137,7 +159,7 @@ class CvarManager CvarInfo* FindCvar(size_t index); bool CacheLookup(const char* name, CvarInfo** info); - Forward* HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback); + AutoForward* HookCvarChange(cvar_t* var, AMX* amx, cell param, const char** callback); size_t GetRegCvarsCount(); diff --git a/amxmodx/cvars.cpp b/amxmodx/cvars.cpp index bf387a50..18930737 100644 --- a/amxmodx/cvars.cpp +++ b/amxmodx/cvars.cpp @@ -92,7 +92,7 @@ static cell AMX_NATIVE_CALL hook_cvar_change(AMX *amx, cell *params) } const char* callback; - Forward* forward = g_CvarManager.HookCvarChange(var, amx, params[2], &callback); + AutoForward* forward = g_CvarManager.HookCvarChange(var, amx, params[2], &callback); if (!forward) { @@ -106,7 +106,7 @@ static cell AMX_NATIVE_CALL hook_cvar_change(AMX *amx, cell *params) // enable_cvar_hook(cvarhook:handle); static cell AMX_NATIVE_CALL enable_cvar_hook(AMX *amx, cell *params) { - Forward* forward = reinterpret_cast(params[1]); + AutoForward* forward = reinterpret_cast(params[1]); if (!forward) { @@ -114,7 +114,7 @@ static cell AMX_NATIVE_CALL enable_cvar_hook(AMX *amx, cell *params) return 0; } - forward->state = Forward::FSTATE_OK; + forward->state = AutoForward::FSTATE_OK; return 1; } @@ -122,7 +122,7 @@ static cell AMX_NATIVE_CALL enable_cvar_hook(AMX *amx, cell *params) // disable_cvar_hook(cvarhook:handle); static cell AMX_NATIVE_CALL disable_cvar_hook(AMX *amx, cell *params) { - Forward* forward = reinterpret_cast(params[1]); + AutoForward* forward = reinterpret_cast(params[1]); if (!forward) { @@ -130,7 +130,7 @@ static cell AMX_NATIVE_CALL disable_cvar_hook(AMX *amx, cell *params) return 0; } - forward->state = Forward::FSTATE_STOP; + forward->state = AutoForward::FSTATE_STOP; return 1; } @@ -329,12 +329,12 @@ static cell AMX_NATIVE_CALL get_pcvar_bounds(AMX *amx, cell *params) switch (params[2]) { case CvarBound_Lower: - hasBound = info->hasMin; - bound = info->minVal; + hasBound = info->bound.hasMin; + bound = info->bound.minVal; break; case CvarBound_Upper: - hasBound = info->hasMax; - bound = info->maxVal; + hasBound = info->bound.hasMax; + bound = info->bound.maxVal; break; default: LogError(amx, AMX_ERR_NATIVE, "Invalid CvarBounds value: %d", params[2]); @@ -520,16 +520,19 @@ static cell AMX_NATIVE_CALL set_pcvar_bounds(AMX *amx, cell *params) } bool set = params[3] > 0 ? true : false; + int pluginId = g_plugins.findPluginFast(amx)->getId(); switch (params[2]) { case CvarBound_Lower: - info->hasMin = set; - info->minVal = set ? amx_ctof(params[4]) : 0; + info->bound.hasMin = set; + info->bound.minVal = set ? amx_ctof(params[4]) : 0; + info->bound.minPluginId = pluginId; break; case CvarBound_Upper: - info->hasMax = set; - info->maxVal = set ? amx_ctof(params[4]) : 0; + info->bound.hasMax = set; + info->bound.maxVal = set ? amx_ctof(params[4]) : 0; + info->bound.maxPluginId = pluginId; break; default: LogError(amx, AMX_ERR_NATIVE, "Invalid CvarBounds value: %d", params[2]); diff --git a/amxmodx/srvcmd.cpp b/amxmodx/srvcmd.cpp index 847b7f28..be619d44 100755 --- a/amxmodx/srvcmd.cpp +++ b/amxmodx/srvcmd.cpp @@ -232,14 +232,14 @@ void amx_command() } 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(" 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"); + 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 ] [ index ] - list cvars handled by amxx or show informations 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"); } } diff --git a/public/auto-string.h b/public/auto-string.h new file mode 100644 index 00000000..75e4f8f0 --- /dev/null +++ b/public/auto-string.h @@ -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 +#include +#include +#include + +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_