From ccea6516cb52ab0565a9169ae7e904743bde29e8 Mon Sep 17 00:00:00 2001 From: asmodai Date: Mon, 9 Jan 2017 01:30:23 +0300 Subject: [PATCH] Finished rewriting of mreg code Debug macro replaced to inline function --- metamod/src/api_info.h | 3 + metamod/src/callback_jit.cpp | 15 +- metamod/src/callback_jit.h | 6 +- metamod/src/conf_meta.cpp | 2 +- metamod/src/dllapi.cpp | 12 +- metamod/src/engine_api.cpp | 12 +- metamod/src/log_meta.h | 4 +- metamod/src/mlist.cpp | 10 +- metamod/src/mplugin.cpp | 5 +- metamod/src/mreg.cpp | 349 +++++++++++++---------------------- metamod/src/mreg.h | 92 ++++----- metamod/src/mutil.cpp | 218 +++++++++++++--------- metamod/src/osdep.cpp | 47 ----- metamod/src/osdep.h | 5 - metamod/src/reg_support.cpp | 52 ++---- metamod/src/sdk_util.cpp | 75 +++++++- metamod/src/sdk_util.h | 2 + metamod/src/studioapi.cpp | 12 +- metamod/src/utils.cpp | 21 ++- metamod/src/utils.h | 30 ++- 20 files changed, 472 insertions(+), 500 deletions(-) diff --git a/metamod/src/api_info.h b/metamod/src/api_info.h index 308eae7..3bb4355 100644 --- a/metamod/src/api_info.h +++ b/metamod/src/api_info.h @@ -1,5 +1,8 @@ #pragma once +#define MM_PRE_HOOK +#define MM_POST_HOOK + enum { P_PRE, // plugin function called before gamedll diff --git a/metamod/src/callback_jit.cpp b/metamod/src/callback_jit.cpp index fe3767a..d07602f 100644 --- a/metamod/src/callback_jit.cpp +++ b/metamod/src/callback_jit.cpp @@ -315,6 +315,10 @@ void CSimpleJmp::naked_main() }*/ } +CJit::CJit() : m_callback_allocator(static_allocator::mp_rwx), m_tramp_allocator(static_allocator::mp_rwx) +{ +} + size_t CJit::compile_callback(jitdata_t* jitdata) { if (!is_hook_needed(jitdata)) { @@ -326,7 +330,7 @@ size_t CJit::compile_callback(jitdata_t* jitdata) auto code = callback.GetCode(); auto codeSize = callback.GetCodeSize(); - auto ptr = m_allocator.allocate(codeSize); + auto ptr = m_callback_allocator.allocate(codeSize); return (size_t)memcpy(ptr, code, codeSize); } @@ -338,14 +342,19 @@ size_t CJit::compile_tramp(size_t ptr_to_func/*, size_t hook, size_t hook_time*/ auto code = jmp.GetCode(); auto codeSize = jmp.GetCodeSize(); - auto ptr = m_static_allocator.allocate(codeSize); + auto ptr = m_tramp_allocator.allocate(codeSize); return (size_t)memcpy(ptr, code, codeSize); } void CJit::clear_callbacks() { - m_allocator.deallocate_all(); + m_callback_allocator.deallocate_all(); +} + +void CJit::clear_tramps() +{ + m_tramp_allocator.deallocate_all(); } bool CJit::is_hook_needed(jitdata_t* jitdata) diff --git a/metamod/src/callback_jit.h b/metamod/src/callback_jit.h index 6151b1e..c8b5d0e 100644 --- a/metamod/src/callback_jit.h +++ b/metamod/src/callback_jit.h @@ -80,16 +80,18 @@ bool is_varargs(ret_t (*)(t_args..., ...)) class CJit { public: + CJit(); size_t compile_callback(jitdata_t* jitdata); size_t compile_tramp(size_t ptr_to_func/*, size_t hook, size_t hook_time*/); void clear_callbacks(); + void clear_tramps(); private: static bool is_hook_needed(jitdata_t* jitdata); private: - execmem_allocator m_allocator; - execmem_allocator m_static_allocator; + static_allocator m_callback_allocator; + static_allocator m_tramp_allocator; }; extern CJit g_jit; diff --git a/metamod/src/conf_meta.cpp b/metamod/src/conf_meta.cpp index 64ce70e..2b94ae1 100644 --- a/metamod/src/conf_meta.cpp +++ b/metamod/src/conf_meta.cpp @@ -54,7 +54,7 @@ bool MConfig::set(option_t* setp, const char* setstr) return false; } *optval = Q_atoi(setstr); - META_DEBUG(3, ("set config int: %s = %d", setp->name, *optval)); + META_DEBUG(3, "set config int: %s = %d", setp->name, *optval); break; case CF_BOOL: if (is_yes(setstr)) diff --git a/metamod/src/dllapi.cpp b/metamod/src/dllapi.cpp index 1605f53..bf78f73 100644 --- a/metamod/src/dllapi.cpp +++ b/metamod/src/dllapi.cpp @@ -12,17 +12,17 @@ NEW_DLL_FUNCTIONS sNewFunctionTable; NEW_DLL_FUNCTIONS sNewFunctionTable_jit; NEW_DLL_FUNCTIONS *pHookedNewDllFunctions = &sNewFunctionTable; -void mm_ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] ) +void MM_PRE_HOOK EXT_FUNC mm_ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128] ) { g_players.clear_player_cvar_query(pEntity); } -void mm_ClientDisconnect(edict_t *pEntity) +void MM_PRE_HOOK EXT_FUNC mm_ClientDisconnect(edict_t *pEntity) { g_players.clear_player_cvar_query(pEntity); } -void mm_ClientCommand(edict_t *pEntity) +void MM_PRE_HOOK mm_ClientCommand(edict_t *pEntity) { if (!strcmp(CMD_ARGV(0), "meta")) { client_meta(pEntity); @@ -147,7 +147,7 @@ compile_data_t g_newdllfunc_cdata[] = // GetAPI or not.. C_DLLEXPORT int GetEntityAPI(DLL_FUNCTIONS *pFunctionTable, int interfaceVersion) { - META_DEBUG(3, ("called: GetEntityAPI; version=%d", interfaceVersion)); + META_DEBUG(3, "called: GetEntityAPI; version=%d", interfaceVersion); if (!pFunctionTable) { META_ERROR("GetEntityAPI called with null pFunctionTable"); @@ -165,7 +165,7 @@ C_DLLEXPORT int GetEntityAPI(DLL_FUNCTIONS *pFunctionTable, int interfaceVersion C_DLLEXPORT int GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion) { - META_DEBUG(3, ("called: GetEntityAPI2; version=%d", *interfaceVersion)); + META_DEBUG(3, "called: GetEntityAPI2; version=%d", *interfaceVersion); if (!pFunctionTable) { @@ -186,7 +186,7 @@ C_DLLEXPORT int GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersi C_DLLEXPORT int GetNewDLLFunctions(NEW_DLL_FUNCTIONS *pNewFunctionTable, int *interfaceVersion) { - META_DEBUG(6, ("called: GetNewDLLFunctions; version=%d", *interfaceVersion)); + META_DEBUG(6, "called: GetNewDLLFunctions; version=%d", *interfaceVersion); #if 0 // ~dvander - but then you can't use cvar querying on many mods... // Don't provide these functions to engine if gamedll doesn't provide // them. Otherwise, we're in the position of having to provide answers diff --git a/metamod/src/engine_api.cpp b/metamod/src/engine_api.cpp index e927a78..70a8b92 100644 --- a/metamod/src/engine_api.cpp +++ b/metamod/src/engine_api.cpp @@ -3,28 +3,28 @@ #define CDATA_ENG_H(x, p, h) CDATA_ENTRY(enginefuncs_t, x, p, size_t(h)) #define CDATA_ENG(x) CDATA_ENTRY(enginefuncs_t, x, P_PRE, 0u) -meta_enginefuncs_t meta_engfuncs; // static addresses for gamedll +meta_enginefuncs_t meta_engfuncs; // static trampolines to dynamic callbacks (for gamedll) meta_enginefuncs_t meta_engfuncs_jit; // dynamic jit callbacks -void mm_QueryClientCvarValue(const edict_t* pEdict, const char* cvarName) +void MM_PRE_HOOK mm_QueryClientCvarValue(const edict_t* pEdict, const char* cvarName) { g_players.set_player_cvar_query(pEdict, cvarName); } // int -> void -void mm_RegUserMsg(const char* pszName, int iSize) +void MM_POST_HOOK mm_RegUserMsg(const char* pszName, int iSize) { // Add the msgid, name, and size to our saved list, if we haven't already. auto imsgid = *(int *)(g_metaGlobals.status == MRES_OVERRIDE ? g_metaGlobals.override_ret : g_metaGlobals.orig_ret); auto nmsg = g_regMsgs->find(imsgid); if (nmsg) { - if (!strcmp(pszName, nmsg->name)) + if (!Q_strcmp(pszName, nmsg->getname())) // This name/msgid pair was already registered. - META_DEBUG(3, ("user message registered again: name=%s, msgid=%d", pszName, imsgid)); + META_DEBUG(3, "user message registered again: name=%s, msgid=%d", pszName, imsgid); else // This msgid was previously used by a different message name. - META_ERROR("user message id reused: msgid=%d, oldname=%s, newname=%s", imsgid, nmsg->name, pszName); + META_ERROR("user message id reused: msgid=%d, oldname=%s, newname=%s", imsgid, nmsg->getname(), pszName); } else g_regMsgs->add(pszName, imsgid, iSize); diff --git a/metamod/src/log_meta.h b/metamod/src/log_meta.h index 724fb25..207303d 100644 --- a/metamod/src/log_meta.h +++ b/metamod/src/log_meta.h @@ -11,11 +11,11 @@ extern cvar_t meta_debug; template -void META_DEBUG(int level, t_args... args) +void META_DEBUG(int level, const char* fmt, t_args... args) { if (meta_debug.value < level) return; - ALERT(at_logged, "[META] (debug:%i) %s\n", level, args...); + ALERT(at_logged, "[META] (debug:%i) %s\n", level, args...); // TODO } void META_CONS(const char *fmt, ...); diff --git a/metamod/src/mlist.cpp b/metamod/src/mlist.cpp index 5425ebe..a17ea0e 100644 --- a/metamod/src/mlist.cpp +++ b/metamod/src/mlist.cpp @@ -391,11 +391,11 @@ bool MPluginList::ini_startup() { if (pmatch->pfspecific >= plist[n].pfspecific) { - META_DEBUG(1, ("ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d)", ln, inifile, pmatch->pfspecific, plist[n].pfspecific)); + META_DEBUG(1, "ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d)", ln, inifile, pmatch->pfspecific, plist[n].pfspecific); continue; } - META_DEBUG(1, ("ini: Plugin in line %d overrides existing plugin with lower platform specific level %d, ours %d", ln, pmatch->pfspecific, plist[n].pfspecific)); + META_DEBUG(1, "ini: Plugin in line %d overrides existing plugin with lower platform specific level %d, ours %d", ln, pmatch->pfspecific, plist[n].pfspecific); int _index = pmatch->index; Q_memset(pmatch, 0, sizeof(MPlugin)); pmatch->index = _index; @@ -462,19 +462,19 @@ bool MPluginList::ini_refresh() { if (pl_found->pfspecific >= pl_temp.pfspecific) { - META_DEBUG(1, ("ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d)", ln, inifile, pl_found->pfspecific, pl_temp.pfspecific)); + META_DEBUG(1, "ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d)", ln, inifile, pl_found->pfspecific, pl_temp.pfspecific); continue; } if (PA_LOAD == pl_found->action) { - META_DEBUG(1, ("ini: Plugin in line %d overrides loading of plugin with lower platform specific level %d, ours %d", ln, pl_found->pfspecific, pl_temp.pfspecific)); + META_DEBUG(1, "ini: Plugin in line %d overrides loading of plugin with lower platform specific level %d, ours %d", ln, pl_found->pfspecific, pl_temp.pfspecific); int _index = pl_found->index; Q_memset(pl_found, 0, sizeof(MPlugin)); pl_found->index = _index; } else { - META_DEBUG(1, ("ini: Plugin in line %d should override existing plugin with lower platform specific level %d, ours %d. Unable to comply.", ln, pl_found->pfspecific, pl_temp.pfspecific)); + META_DEBUG(1, "ini: Plugin in line %d should override existing plugin with lower platform specific level %d, ours %d. Unable to comply.", ln, pl_found->pfspecific, pl_temp.pfspecific); continue; } } diff --git a/metamod/src/mplugin.cpp b/metamod/src/mplugin.cpp index e337410..3a6cb61 100644 --- a/metamod/src/mplugin.cpp +++ b/metamod/src/mplugin.cpp @@ -946,7 +946,8 @@ bool MPlugin::attach(PLUG_LOADTIME now) if (!engine_table) engine_table = (meta_enginefuncs_t *)calloc(1, sizeof(meta_enginefuncs_t)); if (meta_table.pfnGetEngineFunctions(engine_table, &iface_vers)) { do { - if (meta_debug.value < 3) break; else (*g_engfuncs.pfnAlertMessage)(at_logged, "[META] (debug:%d) %s\n", 3, UTIL_VarArgs("dll: Plugin '%s': Found %s", desc, "GetEngineFunctions")); + if (meta_debug.value < 3) break; + else (*g_engfuncs.pfnAlertMessage)(at_logged, "[META] (debug:%d) %s\n", 3, UTIL_VarArgs("dll: Plugin '%s': Found %s", desc, "GetEngineFunctions")); } while (0); } @@ -1412,7 +1413,7 @@ bool MPlugin::newer_file() return false; file_time = st.st_ctime > st.st_mtime ? st.st_ctime : st.st_mtime; - META_DEBUG(5, ("newer_file? file=%s; load=%d, file=%d; ctime=%d, mtime=%d", file, time_loaded, file_time, st.st_ctime, st.st_mtime)); + META_DEBUG(5, "newer_file? file=%s; load=%d, file=%d; ctime=%d, mtime=%d", file, time_loaded, file_time, st.st_ctime, st.st_mtime); if (file_time > time_loaded) return true; else diff --git a/metamod/src/mreg.cpp b/metamod/src/mreg.cpp index 4dcc2b2..54ff5f8 100644 --- a/metamod/src/mreg.cpp +++ b/metamod/src/mreg.cpp @@ -1,26 +1,31 @@ #include "precompiled.h" -MRegCmd::MRegCmd(char* cmd_name, REG_CMD_FN cmd_handler, MPlugin* cmd_plugin) : pfnCmd(cmd_handler), status(RG_VALID), plugid(cmd_plugin->index) +MRegCmd::MRegCmd(char* cmd_name, REG_CMD_FN cmd_handler, MPlugin* cmd_plugin) : m_pfunction(cmd_handler), m_status(RG_VALID), m_plugid(cmd_plugin->index) { - name = _strdup(name); + m_name = _strdup(m_name); } bool MRegCmd::call() const { - pfnCmd(); - return status != RG_INVALID; + m_pfunction(); + return m_status != RG_INVALID; } void MRegCmd::disable() { - pfnCmd = [](){}; - plugid = 0; - status = RG_INVALID; + m_pfunction = [](){}; + m_plugid = 0; + m_status = RG_INVALID; } char* MRegCmd::getname() const { - return name; + return m_name; +} + +REG_CMD_FN MRegCmd::gethandler() const +{ + return m_pfunction; } MRegCmdList::MRegCmdList() : m_list() @@ -29,10 +34,10 @@ MRegCmdList::MRegCmdList() : m_list() MRegCmd *MRegCmdList::find(const char *name) const { - for (auto icmd : m_list) + for (auto reg : m_list) { - if (!Q_stricmp(icmd->name, name)) - return icmd; + if (!Q_stricmp(reg->m_name, name)) + return reg; } return nullptr; @@ -40,23 +45,23 @@ MRegCmd *MRegCmdList::find(const char *name) const MRegCmd *MRegCmdList::add(char *addname, REG_CMD_FN cmd_handler, MPlugin* cmd_plugin) { - auto icmd = new MRegCmd(addname, cmd_handler, cmd_plugin); - m_list.push_back(icmd); - return icmd; + auto reg = new MRegCmd(addname, cmd_handler, cmd_plugin); + m_list.push_back(reg); + return reg; } void MRegCmdList::remove(char* cmd_name) { for (auto it = m_list.begin(), end = m_list.end(); it != end; ++it) { - auto icmd = *it; + auto reg = *it; - if (!Q_stricmp(icmd->name, cmd_name)) { + if (!Q_stricmp(reg->m_name, cmd_name)) { if (g_RehldsFuncs) { g_RehldsFuncs->Cmd_RemoveCmd(cmd_name); m_list.erase(it); } else { - icmd->disable(); + reg->disable(); } } } @@ -66,15 +71,15 @@ void MRegCmdList::remove(char* cmd_name) void MRegCmdList::remove(int owner_plugin_id) { for (auto it = m_list.begin(), end = m_list.end(); it != end; ++it) { - auto icmd = *it; + auto reg = *it; - if (icmd->plugid == owner_plugin_id) { + if (reg->m_plugid == owner_plugin_id) { if (g_RehldsFuncs) { - g_RehldsFuncs->Cmd_RemoveCmd(icmd->name); + g_RehldsFuncs->Cmd_RemoveCmd(reg->m_name); m_list.erase(it); } else { - icmd->disable(); + reg->disable(); } } } @@ -83,17 +88,17 @@ void MRegCmdList::remove(int owner_plugin_id) // List all the registered commands. void MRegCmdList::show() const { - int n = 0, a = 0; + int total_count = 0, valid_count = 0; char bplug[18 + 1]; // +1 for term null META_CONS("Registered plugin commands:"); META_CONS(" %*s %-*s %-s", WIDTH_MAX_REG, "", sizeof bplug - 1, "plugin", "command"); - for (auto icmd : m_list) + for (auto reg : m_list) { - if (icmd->status == RG_VALID) + if (reg->m_status == RG_VALID) { - auto iplug = g_plugins->find(icmd->plugid); + auto iplug = g_plugins->find(reg->m_plugid); Q_strncpy(bplug, iplug ? iplug->desc : "(unknown)", sizeof bplug - 1); bplug[sizeof bplug - 1] = '\0'; @@ -104,136 +109,67 @@ void MRegCmdList::show() const bplug[sizeof bplug - 1] = '\0'; } - META_CONS(" [%*d] %-*s %-s", WIDTH_MAX_REG, ++n, sizeof bplug - 1, bplug, icmd->name); + META_CONS(" [%*d] %-*s %-s", WIDTH_MAX_REG, ++total_count, sizeof bplug - 1, bplug, reg->m_name); - if (icmd->status == RG_VALID) - a++; + if (reg->m_status == RG_VALID) + valid_count++; } - META_CONS("%d commands, %d available", n, a); + META_CONS("%d commands, %d available", total_count, valid_count); } // List all the registered commands for the given plugin id. void MRegCmdList::show(int plugin_id) const { - int n = 0; + int total_count = 0; META_CONS("Registered commands:"); - for (auto icmd : m_list) + + for (auto reg : m_list) { - if (icmd->plugid != plugin_id) + if (reg->m_plugid != plugin_id) continue; - META_CONS(" %s", icmd->name); - n++; + META_CONS(" %s", reg->m_name); + total_count++; } - META_CONS("%d commands", n); + META_CONS("%d commands", total_count); } -// Init values. It would probably be more "proper" to use containers and -// constructors, rather than arrays and init-functions. -void MRegCvar::init(int idx) +MRegCvar::MRegCvar(cvar_t* cv_ptr, MPlugin* cv_plugin) : m_cvar(cv_ptr), m_plugid(cv_plugin->index), m_status(RG_VALID) { - index = idx; - data = NULL; - plugid = 0; - status = RG_INVALID; + m_cvar = g_static_allocator.allocate(); + m_cvar->name = _strdup(cv_ptr->name); + m_cvar->string = _strdup(cv_ptr->string); + m_cvar->flags = cv_ptr->flags; + m_cvar->value = cv_ptr->value; + m_cvar->next = cv_ptr->next; } -// Set the cvar, copying values from given cvar. -// meta_errno values: -// - ME_ARGUMENT given cvar doesn't match this cvar -bool MRegCvar::set(cvar_t *src) const +cvar_t* MRegCvar::getcvar() const { - if (Q_stricmp(src->name, data->name)) - { - META_ERROR("Tried to set cvar with mismatched name; src=%s dst=%s", src->name, data->name); - return false; - } - - // Would like to free() existing string, but can't tell where it was - // allocated... - data->string = Q_strdup(src->string); - data->flags = src->flags; - data->value = src->value; - data->next = src->next; - return true; + return m_cvar; } // Constructor -MRegCvarList::MRegCvarList() - : vlist(0), size(REG_CVAR_GROWSIZE), endlist(0) +MRegCvarList::MRegCvarList() : m_list() { - vlist = (MRegCvar *)Q_malloc(size * sizeof(MRegCvar)); - - // initialize array - for (int i = 0; i < size; i++) - vlist[i].init(i + 1); // 1 - based - - endlist = 0; } -// Add the given cvar name to the list and return the instance. This only -// writes the "name" to the new cvar; other fields are written with -// cvar::set(). -// meta_errno values: -// - ME_NOMEM couldn't alloc or realloc for various parts -MRegCvar *MRegCvarList::add(const char *addname) +MRegCvar *MRegCvarList::add(cvar_t* src, MPlugin* plugin) { - MRegCvar *icvar; - if (endlist == size) - { - // grow array - int newsize = size + REG_CVAR_GROWSIZE; - - META_DEBUG(6, ("Growing reg cvar list from %d to %d", size, newsize)); - MRegCvar *temp = (MRegCvar *) realloc(vlist, newsize * sizeof(MRegCvar)); - if (!temp) - { - META_ERROR("Couldn't grow registered cvar list to %d for '%s'; %s", newsize, addname, strerror(errno)); - return NULL; - } - vlist = temp; - size = newsize; - // initialize new (unused) entries - for (int i = endlist; i < size; i++) - vlist[i].init(i + 1); // 1-based - } - - icvar = &vlist[endlist]; - - // Malloc space for the cvar and cvar name, for two reasons: - // - Can't point to memory loc in plugin (another segv waiting to - // happen). - // - Can't point to memory in vlist which might get moved later by - // realloc (again, segv). - icvar->data = (cvar_t *)Q_malloc(sizeof(cvar_t)); - if (!icvar->data) - { - META_ERROR("Couldn't malloc cvar for adding reg cvar name '%s': %s", addname, strerror(errno)); - return NULL; - } - - icvar->data->name = Q_strdup(addname); - if (!icvar->data->name) - { - META_ERROR("Couldn't Q_strdup for adding reg cvar name '%s': %s", addname, strerror(errno)); - return NULL; - } - endlist++; - return icvar; + MRegCvar *reg_cvar = new(g_static_allocator.allocate()) MRegCvar(src, plugin); + m_list.push_back(reg_cvar); + return reg_cvar; } -// Try to find a registered cvar with the given name. -// meta_errno values: -// - ME_NOTFOUND couldn't find a matching cvar MRegCvar *MRegCvarList::find(const char *findname) { - for (int i = 0; i < endlist; i++) + for (auto reg : m_list) { - if (!_stricmp(vlist[i].data->name, findname)) - return &vlist[i]; + if (!Q_stricmp(reg->m_cvar->name, findname)) + return reg; } return NULL; @@ -242,18 +178,12 @@ MRegCvar *MRegCvarList::find(const char *findname) // Disable any cvars belonging to the given plugin (by index id). void MRegCvarList::disable(int plugin_id) const { - int i; - MRegCvar *icvar; - for (i = 0; i < size; i++) + for (auto reg : m_list) { - icvar = &vlist[i]; - if (icvar->plugid == plugin_id) + if (reg->m_plugid == plugin_id) { - icvar->status = RG_INVALID; - icvar->plugid = 0; - // Decided not to do this, in order to keep pre-existing values - // after a plugin reload. - // CVAR_SET_STRING(icvar->data->name, "[metamod: cvar invalid; plugin unloaded]"); + reg->m_status = RG_INVALID; + reg->m_plugid = 0; } } } @@ -261,29 +191,19 @@ void MRegCvarList::disable(int plugin_id) const // List all the registered cvars. void MRegCvarList::show() const { - int i, n = 0, a = 0; - MRegCvar *icvar; - MPlugin *iplug; + int total_count = 0, valid_count = 0; char bplug[13 + 1], bname[20 + 1], bval[15 + 1]; // +1 for term null META_CONS("Registered plugin cvars:"); - META_CONS(" %*s %-*s %-*s %*s %s", WIDTH_MAX_REG, "", sizeof(bplug) - 1, "plugin", sizeof(bname) - 1, "cvar", sizeof(bval) - 1, "float value", "string value"); - for (i = 0; i < endlist; i++) + META_CONS(" %*s %-*s %-*s %*s %s", WIDTH_MAX_REG, "", sizeof bplug - 1, "plugin", sizeof bname - 1, "cvar", sizeof bval - 1, "float value", "string value"); + + for (auto reg : m_list) { - icvar = &vlist[i]; - if (icvar->status == RG_VALID) + if (reg->m_status == RG_VALID) { - iplug = g_plugins->find(icvar->plugid); - if (iplug) - { - Q_strncpy(bplug, iplug->desc, sizeof bplug - 1); - bplug[sizeof bplug - 1] = '\0'; - } - else - { - Q_strncpy(bplug, "(unknown)", sizeof bplug - 1); - bplug[sizeof bplug - 1] = '\0'; - } + auto plug = g_plugins->find(reg->m_plugid); + Q_strncpy(bplug, plug ? plug->desc : "(unknown)", sizeof bplug - 1); + bplug[sizeof bplug - 1] = '\0'; } else { @@ -291,127 +211,110 @@ void MRegCvarList::show() const bplug[sizeof bplug - 1] = '\0'; } - Q_strncpy(bname, icvar->data->name, sizeof bname - 1); + Q_strncpy(bname, reg->m_cvar->name, sizeof bname - 1); bname[sizeof bname - 1] = '\0'; - Q_snprintf(bval, sizeof(bval), "%f", icvar->data->value); - META_CONS(" [%*d] %-*s %-*s %*s %s", WIDTH_MAX_REG, icvar->index, sizeof(bplug) - 1, bplug, sizeof(bname) - 1, bname, sizeof(bval) - 1, bval, icvar->data->string); + Q_snprintf(bval, sizeof bval, "%f", reg->m_cvar->value); + META_CONS(" [%*d] %-*s %-*s %*s %s", WIDTH_MAX_REG, ++total_count, sizeof bplug - 1, bplug, sizeof bname - 1, bname, sizeof bval - 1, bval, reg->m_cvar->string); - if (icvar->status == RG_VALID) - a++; - - n++; + if (reg->m_status == RG_VALID) + valid_count++; } - META_CONS("%d cvars, %d available (%d allocated)", n, a, size); + + META_CONS("%d cvars, %d available", total_count, valid_count); } // List the registered cvars for the given plugin id. void MRegCvarList::show(int plugin_id) const { - int n = 0; - MRegCvar *icvar; + int total_count = 0; char bname[30 + 1], bval[15 + 1]; // +1 for term null - META_CONS("%-*s %*s %s", sizeof(bname) - 1, "Registered cvars:", sizeof(bval) - 1, "float value", "string value"); - for (int i = 0; i < endlist; i++) + META_CONS("%-*s %*s %s", sizeof(bname) - 1, "Registered cvars:", sizeof bval - 1, "float value", "string value"); + + for (auto reg : m_list) { - icvar = &vlist[i]; - if (icvar->plugid != plugin_id) + if (reg->m_plugid != plugin_id) continue; - Q_strncpy(bname, icvar->data->name, sizeof bname - 1); + Q_strncpy(bname, reg->m_cvar->name, sizeof bname - 1); bname[sizeof bname - 1] = '\0'; - Q_snprintf(bval, sizeof(bval), "%f", icvar->data->value); - META_CONS(" %-*s %*s %s", sizeof(bname) - 1, bname, sizeof(bval) - 1, bval, icvar->data->string); - n++; + Q_snprintf(bval, sizeof(bval), "%f", reg->m_cvar->value); + META_CONS(" %-*s %*s %s", sizeof(bname) - 1, bname, sizeof(bval) - 1, bval, reg->m_cvar->string); + total_count++; } - META_CONS("%d cvars", n); + META_CONS("%d cvars", total_count); } -// Constructor -MRegMsgList::MRegMsgList() - : size(MAX_REG_MSGS), endlist(0) +MRegMsg::MRegMsg(const char* name, int msgid, int size) : m_name(name), m_msgid(msgid), m_size(size) +{ + +} + +const char* MRegMsg::getname() const +{ + return m_name; +} + +int MRegMsg::getid() const +{ + return m_msgid; +} + +int MRegMsg::getsize() const +{ + return m_size; +} + +MRegMsgList::MRegMsgList() : m_list() { - // initialize array - Q_memset(mlist, 0, sizeof(mlist)); - for (int i = 0; i < size; i++) - { - mlist[i].index = i + 1; // 1-based - } - - endlist = 0; } -// Add the given user msg the list and return the instance. -// meta_errno values: -// - ME_MAXREACHED reached max number of msgs allowed MRegMsg *MRegMsgList::add(const char *addname, int addmsgid, int addsize) { - if (endlist == size) - { - // all slots used - META_ERROR("Couldn't add registered msg '%s' to list; reached max msgs (%d)", addname, size); - return NULL; - } - - MRegMsg *imsg = &mlist[endlist]; - endlist++; - // Copy msg data into empty slot. // Note: 'addname' assumed to be a constant string allocated in the // gamedll. - imsg->name = addname; - imsg->msgid = addmsgid; - imsg->size = addsize; - - return imsg; + auto msg = new(g_static_allocator.allocate()) MRegMsg(addname, addmsgid, addsize); + m_list.push_back(msg); + return msg; } -// Try to find a registered msg with the given name. -// meta_errno values: -// - ME_NOTFOUND couldn't find a matching cvar MRegMsg *MRegMsgList::find(const char *findname) { - for (int i = 0; i < endlist; i++) + for (auto msg : m_list) { - if (!Q_strcmp(mlist[i].name, findname)) - return &mlist[i]; + if (!Q_strcmp(msg->m_name, findname)) + return msg; } - return NULL; + return nullptr; } -// Try to find a registered msg with the given msgid. -// meta_errno values: -// - ME_NOTFOUND couldn't find a matching cvar MRegMsg *MRegMsgList::find(int findmsgid) { - for (int i = 0; i < endlist; i++) - { - if (mlist[i].msgid == findmsgid) - return &mlist[i]; + for (auto msg : m_list) { + if (msg->m_msgid == findmsgid) + return msg; } - return NULL; + return nullptr; } // List the registered usermsgs for the gamedll. void MRegMsgList::show() { - int i, n = 0; - MRegMsg *imsg; + int total_count = 0; char bname[25 + 1]; // +1 for term null META_CONS("%-*s %5s %5s", sizeof(bname) - 1, "Game registered user msgs:", "msgid", "size"); - for (i = 0; i < endlist; i++) - { - imsg = &mlist[i]; - - Q_strncpy(bname, imsg->name, sizeof bname - 1); + + for (auto msg : m_list) { + Q_strncpy(bname, msg->m_name, sizeof bname - 1); bname[sizeof bname - 1] = '\0'; - META_CONS(" %-*s %3d %3d", sizeof(bname) - 1, bname, imsg->msgid, imsg->size); - n++; + META_CONS(" %-*s %3d %3d", sizeof(bname) - 1, bname, msg->m_msgid, msg->m_size); + total_count++; } - META_CONS("%d game user msgs", n); + META_CONS("%d game user msgs", total_count); } diff --git a/metamod/src/mreg.h b/metamod/src/mreg.h index 4d8e20e..ff6bf7e 100644 --- a/metamod/src/mreg.h +++ b/metamod/src/mreg.h @@ -1,10 +1,4 @@ #pragma once -#include "types_meta.h" // bool - -// Number of entries to add to reglists when they need to grow. Typically -// more cvars than commands, so we grow them at different increments. -#define REG_CMD_GROWSIZE 32 -#define REG_CVAR_GROWSIZE 64 // Width required to printf a Reg*List index number, for show() functions. // This used to correspond to the number of digits in MAX_REG, which was a @@ -27,101 +21,97 @@ typedef void (*REG_CMD_FN)(); class MPlugin; // An individual registered function/command. -class MRegCmd { +class MRegCmd +{ public: MRegCmd(char* cmd_name, REG_CMD_FN cmd_handler, MPlugin* cmd_plugin); bool call() const; // try to call the function void disable(); char* getname() const; + REG_CMD_FN gethandler() const; private: - char *name; // space is malloc'd - REG_CMD_FN pfnCmd; // pointer to the function - int plugid; // index id of corresponding plugin - REG_STATUS status; // whether corresponding plugin is loaded + char* m_name; // space is malloc'd + REG_CMD_FN m_pfunction; // pointer to the function + int m_plugid; // index id of corresponding plugin + REG_STATUS m_status; // whether corresponding plugin is loaded friend class MRegCmdList; }; // A list of registered commands. -class MRegCmdList { +class MRegCmdList +{ public: MRegCmdList(); - - MRegCmd *find(const char *name) const; // find by MRegCmd->name + MRegCmd *find(const char *name) const; MRegCmd *add(char *name, REG_CMD_FN cmd_handler, MPlugin* cmd_plugin); void remove(char* cmd_name); - void remove(int owner_plugin_id); // change status to Invalid - void show() const; // list all funcs to console - void show(int plugin_id) const; // list given plugin's funcs to console + void remove(int owner_plugin_id); + void show() const; + void show(int plugin_id) const; private: std::vector m_list; }; // An individual registered cvar. -class MRegCvar { +class MRegCvar +{ public: - friend class MRegCvarList; - - cvar_t *data; // actual cvar structure, malloc'd - int plugid; // index id of corresponding plugin - REG_STATUS status; // whether corresponding plugin is loaded - - void init(int idx); // init values, as not using constructors - bool set(cvar_t *src) const; + MRegCvar(cvar_t* cv_ptr, MPlugin* cv_plugin); + cvar_t* getcvar() const; private: - int index; // 1-based + cvar_t* m_cvar; + int m_plugid; + REG_STATUS m_status; + + friend class MRegCvarList; }; // A list of registered cvars. -class MRegCvarList { - +class MRegCvarList +{ public: MRegCvarList(); - - MRegCvar *add(const char *addname); + MRegCvar *add(cvar_t* src, MPlugin* plugin); MRegCvar *find(const char *findname); // find by MRegCvar->data.name void disable(int plugin_id) const; // change status to Invalid void show() const; // list all cvars to console void show(int plugin_id) const; // list given plugin's cvars to console private: - MRegCvar *vlist; // malloc'd array of registered cvars - int size; // size of list, ie MAX_REG_CVARS - int endlist; // index of last used entry - // Private; to satisfy -Weffc++ "has pointer data members but does - // not override" copy/assignment constructor. - void operator=(const MRegCvarList &src); - MRegCvarList(const MRegCvarList &src); + std::vector m_list; }; // An individual registered user msg, from gamedll. -class MRegMsg { +class MRegMsg +{ public: - friend class MRegMsgList; - - const char *name; // name, assumed constant string in gamedll - int msgid; // msgid, assigned by engine - int size; // size, if given by gamedll + MRegMsg(const char* name, int msgid, int size); + const char* getname() const; + int getid() const; + int getsize() const; private: - int index; // 1-based + const char* m_name; + int m_msgid; + int m_size; + + friend class MRegMsgList; }; // A list of registered user msgs. -class MRegMsgList { +class MRegMsgList +{ public: MRegMsgList(); - MRegMsg *add(const char *addname, int addmsgid, int addsize); MRegMsg *find(const char *findname); MRegMsg *find(int findmsgid); - void show(); // list all msgs to console + void show(); private: - MRegMsg mlist[MAX_REG_MSGS]; // array of registered msgs - int size; // size of list, ie MAX_REG_MSGS - int endlist; // index of last used entry + std::vector m_list; }; diff --git a/metamod/src/mutil.cpp b/metamod/src/mutil.cpp index 42e3a68..140c298 100644 --- a/metamod/src/mutil.cpp +++ b/metamod/src/mutil.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" -hudtextparms_t default_csay_tparms = { +static hudtextparms_t g_default_csay_tparms = { -1, 0.25, // x, y 2, // effect 0, 255, 0, 0, // r, g, b, a1 @@ -9,23 +9,81 @@ hudtextparms_t default_csay_tparms = { 1 // channel }; +static const char* g_engine_msg_names[] = +{ + "svc_bad", + "svc_nop", + "svc_disconnect", + "svc_event", + "svc_version", + "svc_setview", + "svc_sound", + "svc_time", + "svc_print", + "svc_stufftext", + "svc_setangle", + "svc_serverinfo", + "svc_lightstyle", + "svc_updateuserinfo", + "svc_deltadescription", + "svc_clientdata", + "svc_stopsound", + "svc_pings", + "svc_particle", + "svc_damage", + "svc_spawnstatic", + "svc_event_reliable", + "svc_spawnbaseline", + "svc_temp_entity", + "svc_setpause", + "svc_signonnum", + "svc_centerprint", + "svc_killedmonster", + "svc_foundsecret", + "svc_spawnstaticsound", + "svc_intermission", + "svc_finale", + "svc_cdtrack", + "svc_restore", + "svc_cutscene", + "svc_weaponanim", + "svc_decalname", + "svc_roomtype", + "svc_addangle", + "svc_newusermsg", + "svc_packetentities", + "svc_deltapacketentities", + "svc_choke", + "svc_resourcelist", + "svc_newmovevars", + "svc_resourcerequest", + "svc_customization", + "svc_crosshairangle", + "svc_soundfade", + "svc_filetxferfailed", + "svc_hltv", + "svc_director", + "svc_voiceinit", + "svc_voicedata", + "svc_sendextrainfo", + "svc_timescale", + "svc_resourcelocation", + "svc_sendcvarvalue", + "svc_sendcvarvalue2" +}; + // Log to console; newline added. void EXT_FUNC mutil_LogConsole(plid_t plid, const char *fmt, ...) { - va_list ap; char buf[MAX_LOGMSG_LEN]; - unsigned int len; + va_list ap; va_start(ap, fmt); - Q_vsnprintf(buf, sizeof(buf), fmt, ap); + size_t len = Q_vsnprintf(buf, sizeof buf - 1, fmt, ap); va_end(ap); - // end msg with newline - len = Q_strlen(buf); - if (len < sizeof(buf) - 2) // -1 null, -1 for newline - Q_strcat(buf, "\n"); - else - buf[len - 1] = '\n'; + buf[len] = '\n'; + buf[len + 1] = '\0'; SERVER_PRINT(buf); } @@ -33,44 +91,43 @@ void EXT_FUNC mutil_LogConsole(plid_t plid, const char *fmt, ...) // Log regular message to logs; newline added. void EXT_FUNC mutil_LogMessage(plid_t plid, const char *fmt, ...) { - va_list ap; char buf[MAX_LOGMSG_LEN]; - plugin_info_t *plinfo = (plugin_info_t *)plid; + va_list ap; va_start(ap, fmt); - Q_vsnprintf(buf, sizeof(buf), fmt, ap); + Q_vsnprintf(buf, sizeof buf, fmt, ap); va_end(ap); - ALERT(at_logged, "[%s] %s\n", plinfo->logtag, buf); + + ALERT(at_logged, "[%s] %s\n", plid->logtag, buf); } // Log an error message to logs; newline added. void EXT_FUNC mutil_LogError(plid_t plid, const char *fmt, ...) { - va_list ap; char buf[MAX_LOGMSG_LEN]; - plugin_info_t *plinfo = (plugin_info_t *)plid; + va_list ap; va_start(ap, fmt); - Q_vsnprintf(buf, sizeof(buf), fmt, ap); + Q_vsnprintf(buf, sizeof buf, fmt, ap); va_end(ap); - ALERT(at_logged, "[%s] ERROR: %s\n", plinfo->logtag, buf); + + ALERT(at_logged, "[%s] ERROR: %s\n", plid->logtag, buf); } // Log a message only if cvar "developer" set; newline added. void EXT_FUNC mutil_LogDeveloper(plid_t plid, const char* fmt, ...) { - va_list ap; char buf[MAX_LOGMSG_LEN]; - plugin_info_t* plinfo; - if ((int) CVAR_GET_FLOAT("developer") == 0) + if ((int)CVAR_GET_FLOAT("developer") == 0) return; - plinfo = (plugin_info_t *)plid; + va_list ap; va_start(ap, fmt); - Q_vsnprintf(buf, sizeof(buf), fmt, ap); + Q_vsnprintf(buf, sizeof buf, fmt, ap); va_end(ap); - ALERT(at_logged, "[%s] dev: %s\n", plinfo->logtag, buf); + + ALERT(at_logged, "[%s] dev: %s\n", plid->logtag, buf); } // Print message on center of all player's screens. Uses default text @@ -79,7 +136,7 @@ void EXT_FUNC mutil_CenterSay(plid_t plid, const char* fmt, ...) { va_list ap; va_start(ap, fmt); - mutil_CenterSayVarargs(plid, default_csay_tparms, fmt, ap); + mutil_CenterSayVarargs(plid, g_default_csay_tparms, fmt, ap); va_end(ap); } @@ -97,18 +154,18 @@ void EXT_FUNC mutil_CenterSayParms(plid_t plid, hudtextparms_t tparms, const cha void EXT_FUNC mutil_CenterSayVarargs(plid_t plid, hudtextparms_t tparms, const char* fmt, va_list ap) { char buf[MAX_LOGMSG_LEN]; - int n; - edict_t *pEntity; - - Q_vsnprintf(buf, sizeof(buf), fmt, ap); + Q_vsnprintf(buf, sizeof buf, fmt, ap); mutil_LogMessage(plid, "(centersay) %s", buf); - for (n = 1; n <= gpGlobals->maxClients; n++) + + for (int n = 1; n <= gpGlobals->maxClients; n++) { - pEntity = INDEXENT(n); + auto pEntity = INDEXENT(n); + if (FNullEnt(pEntity) || pEntity->free) continue; - //META_UTIL_HudMessage(pEntity, tparms, buf); // TODO + + UTIL_HudMessage(pEntity, tparms, buf); } } @@ -117,16 +174,16 @@ void EXT_FUNC mutil_CenterSayVarargs(plid_t plid, hudtextparms_t tparms, const c // Jussi Kivilinna. qboolean EXT_FUNC mutil_CallGameEntity(plid_t plid, const char *entStr, entvars_t *pev) { - plugin_info_t *plinfo = (plugin_info_t *)plid; - META_DEBUG(8, ("Looking up game entity '%s' for plugin '%s'", entStr, plinfo->name)); + META_DEBUG(8, ("Looking up game entity '%s' for plugin '%s'", entStr, plid->name)); ENTITY_FN pfnEntity = (ENTITY_FN)GameDLL.sys_module.getsym(entStr); + if (!pfnEntity) { - META_ERROR("Couldn't find game entity '%s' in game DLL '%s' for plugin '%s'", entStr, GameDLL.name, plinfo->name); + META_ERROR("Couldn't find game entity '%s' in game DLL '%s' for plugin '%s'", entStr, GameDLL.name, plid->name); return false; } - META_DEBUG(7, ("Calling game entity '%s' for plugin '%s'", entStr, plinfo->name)); + META_DEBUG(7, ("Calling game entity '%s' for plugin '%s'", entStr, plid->name)); (*pfnEntity)(pev); return true; } @@ -135,18 +192,24 @@ qboolean EXT_FUNC mutil_CallGameEntity(plid_t plid, const char *entStr, entvars_ // msgname, and return remaining info about it (msgid, size). int EXT_FUNC mutil_GetUserMsgID(plid_t plid, const char* msgname, int* size) { - plugin_info_t *plinfo = (plugin_info_t *)plid; - META_DEBUG(8, ("Looking up usermsg name '%s' for plugin '%s'", msgname, plinfo->name)); + META_DEBUG(8, "Looking up usermsg name '%s' for plugin '%s'", msgname, plid->name); MRegMsg *umsg = g_regMsgs->find(msgname); + if (umsg) { - if (size) - *size = umsg->size; - return umsg->msgid; + if (size) *size = umsg->getsize(); + return umsg->getid(); } - else - return 0; + + for (int n = 1; n < arraysize(g_engine_msg_names); n++) { + if (!strcmp(msgname, g_engine_msg_names[n])) { + if (size) *size = -1; + return n; + } + } + + return 0; } // Find a usermsg, registered by the gamedll, with the corresponding @@ -154,59 +217,39 @@ int EXT_FUNC mutil_GetUserMsgID(plid_t plid, const char* msgname, int* size) const char* EXT_FUNC mutil_GetUserMsgName(plid_t plid, int msgid, int *size) { plugin_info_t *plinfo = (plugin_info_t *)plid; - META_DEBUG(8, ("Looking up usermsg id '%d' for plugin '%s'", msgid, plinfo->name)); + META_DEBUG(8, "Looking up usermsg id '%d' for plugin '%s'", msgid, plinfo->name); // Guess names for any built-in g_engine messages mentioned in the SDK; // from dlls/util.h. - if (msgid < 64) + if (msgid < arraysize(g_engine_msg_names)) { - switch (msgid) - { - case SVC_TEMPENTITY: - if (size) *size = -1; - return "tempentity?"; - case SVC_INTERMISSION: - if (size) *size = -1; - return "intermission?"; - case SVC_CDTRACK: - if (size) *size = -1; - return "cdtrack?"; - case SVC_WEAPONANIM: - if (size) *size = -1; - return "weaponanim?"; - case SVC_ROOMTYPE: - if (size) *size = -1; - return "roomtype?"; - case SVC_DIRECTOR: - if (size) *size = -1; - return "director?"; - } + if (size) *size = -1; + return g_engine_msg_names[msgid]; } MRegMsg *umsg = g_regMsgs->find(msgid); + if (umsg) { - if (size) - *size = umsg->size; + if (size) *size = umsg->getsize(); // 'name' is assumed to be a constant string, allocated in the // gamedll. - return umsg->name; + return umsg->getname(); } - else - return NULL; + + return nullptr; } // Return the full path of the plugin's loaded dll/so file. const char* EXT_FUNC mutil_GetPluginPath(plid_t plid) { - static char buf[PATH_MAX ]; - MPlugin *plug; + static char buf[PATH_MAX]; - plug = g_plugins->find(plid); + auto plug = g_plugins->find(plid); if (!plug) { META_ERROR("GetPluginPath: couldn't find plugin '%s'", plid->name); - return NULL; + return nullptr; } Q_strncpy(buf, plug->pathname, sizeof buf - 1); @@ -219,6 +262,7 @@ const char* EXT_FUNC mutil_GetGameInfo(plid_t plid, ginfo_t type) { static char buf[MAX_STRBUF_LEN]; const char *cp; + switch (type) { case GINFO_NAME: @@ -241,7 +285,7 @@ const char* EXT_FUNC mutil_GetGameInfo(plid_t plid, ginfo_t type) break; default: META_ERROR("GetGameInfo: invalid request '%d' from plugin '%s'", type, plid->name); - return NULL; + return nullptr; } Q_strncpy(buf, cp, sizeof buf - 1); @@ -251,39 +295,41 @@ const char* EXT_FUNC mutil_GetGameInfo(plid_t plid, ginfo_t type) int EXT_FUNC mutil_LoadMetaPlugin(plid_t plid, const char* fname, PLUG_LOADTIME now, void **plugin_handle) { - MPlugin *pl_loaded; if (!fname) { return 1; } - if (!(pl_loaded = g_plugins->plugin_addload(plid, fname, now))) + auto pl_loaded = g_plugins->plugin_addload(plid, fname, now); + + if (!pl_loaded) { if (plugin_handle) *plugin_handle = nullptr; - return 1; + return 1; // TODO: WTF } else { if (plugin_handle) *plugin_handle = (void *)pl_loaded->sys_module.gethandle(); + return 0; } } int EXT_FUNC mutil_UnloadMetaPlugin(plid_t plid, const char *fname, PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { - MPlugin *findp = nullptr; - int pindex; - char *endptr; + MPlugin *findp; if (!fname) { return 1; } - pindex = strtol(fname, &endptr, 10); + char *endptr; + int pindex = strtol(fname, &endptr, 10); + if (*fname != '\0' && *endptr == '\0') findp = g_plugins->find(pindex); else @@ -300,14 +346,14 @@ int EXT_FUNC mutil_UnloadMetaPlugin(plid_t plid, const char *fname, PLUG_LOADTIM int EXT_FUNC mutil_UnloadMetaPluginByHandle(plid_t plid, void *plugin_handle, PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { - MPlugin *findp; - if (!plugin_handle) { return 1; } - if (!(findp = g_plugins->find((module_handle_t)plugin_handle))) + auto findp = g_plugins->find((module_handle_t)plugin_handle); + + if (!findp) return 1; if (findp->plugin_unload(plid, now, reason)) diff --git a/metamod/src/osdep.cpp b/metamod/src/osdep.cpp index 4c9fa9c..3392779 100644 --- a/metamod/src/osdep.cpp +++ b/metamod/src/osdep.cpp @@ -146,50 +146,3 @@ const char* str_os_error() #endif } #endif - -// Determine whether the given memory location is valid (ie whether we -// should expect to be able to reference strings or functions at this -// location without segfaulting). -#if defined(linux) || defined(__APPLE__) -// Simulate this with dladdr. I'm not convinced this will be as generally -// applicable as the native windows routine below, but it should do what -// we need it for in this particular situation. -// meta_errno values: -// - ME_NOTFOUND couldn't find a matching sharedlib for this ptr -bool IS_VALID_PTR(void *memptr) -{ - Dl_info dli; - Q_memset(&dli, 0, sizeof(dli)); - if (dladdr(memptr, &dli)) - return true; - else - RETURN_ERRNO(false, ME_NOTFOUND); -} -#elif defined(_WIN32) -// Use the native windows routine IsBadCodePtr. -// meta_errno values: -// - ME_BADMEMPTR not a valid memory pointer -bool IS_VALID_PTR(void *memptr) -{ - if (IsBadCodePtr((FARPROC) memptr)) - return false; - else - return true; -} -#endif // _WIN32 - -// This used to be OS-dependent, as it used a SEGV signal handler under -// linux, but that was removed because (a) it masked legitimate segfaults -// in plugin commands and produced confusing output ("plugin has been -// unloaded", when really it segfaultd), and (b) wasn't necessary since -// IS_VALID_PTR() should cover the situation. -bool os_safe_call(REG_CMD_FN pfn) -{ - // try and see if this is a valid memory location - if (!IS_VALID_PTR((void *)pfn)) - // meta_errno should be already set in is_valid_ptr() - return false; - - pfn(); - return true; -} diff --git a/metamod/src/osdep.h b/metamod/src/osdep.h index a162e82..219c382 100644 --- a/metamod/src/osdep.h +++ b/metamod/src/osdep.h @@ -40,11 +40,6 @@ private: uintptr_t m_size; }; -bool IS_VALID_PTR(void *memptr); - -// Attempt to call the given function pointer, without segfaulting. -bool os_safe_call(REG_CMD_FN pfn); - // Windows doesn't have an strtok_r() routine, so we write our own. #ifdef _WIN32 #define strtok_r(s, delim, ptrptr) mm_strtok_r(s, delim, ptrptr) diff --git a/metamod/src/reg_support.cpp b/metamod/src/reg_support.cpp index 1895030..ced3aec 100644 --- a/metamod/src/reg_support.cpp +++ b/metamod/src/reg_support.cpp @@ -32,24 +32,17 @@ void EXT_FUNC meta_AddServerCommand(char *cmd_name, void (*function)()) META_DEBUG(4, ("called: meta_AddServerCommand; cmd_name=%s, function=%d, plugin=%s", cmd_name, function, plug ? plug->file : "unknown")); - // try to find which plugin is registering this command if (!plug) { META_ERROR("Failed to find memloc for regcmd '%s'", cmd_name); } // See if this command was previously registered, ie a "reloaded" plugin. - auto icmd = g_regCmds->find(cmd_name); - if (!icmd) + auto cmd = g_regCmds->find(cmd_name); + if (!cmd) { // If not found, add. - icmd = g_regCmds->add(cmd_name, function, plug); - if (!icmd) - { - return; - } - - // Only register if not previously registered.. - REG_SVR_COMMAND(icmd->getname(), meta_command_handler); + cmd = g_regCmds->add(cmd_name, function, plug); + REG_SVR_COMMAND(cmd->getname(), g_RehldsFuncs ? cmd->gethandler() : meta_command_handler); } } @@ -68,43 +61,24 @@ void EXT_FUNC meta_AddServerCommand(char *cmd_name, void (*function)()) // it will fail to work properly. void EXT_FUNC meta_CVarRegister(cvar_t *pCvar) { - MPlugin *iplug = g_plugins->find_memloc(pCvar); + MPlugin *plug = g_plugins->find_memloc(pCvar); - META_DEBUG(4, ("called: meta_CVarRegister; name=%s", pCvar->name)); + META_DEBUG(4, "called: meta_CVarRegister; name=%s", pCvar->name); // try to find which plugin is registering this cvar - if (!iplug) + if (!plug) { - META_DEBUG(1, ("Failed to find memloc for regcvar '%s'", pCvar->name)); + META_DEBUG(1, "Failed to find memloc for regcvar '%s'", pCvar->name); } // See if this cvar was previously registered, ie a "reloaded" plugin. - auto icvar = g_regCvars->find(pCvar->name); - if (!icvar) + auto reg = g_regCvars->find(pCvar->name); + + if (!reg) { - // If not found, add. - icvar = g_regCvars->add(pCvar->name); - if (!icvar) - { - // error details logged in add() - return; - } - - // Reset to given value - icvar->set(pCvar); - CVAR_REGISTER(icvar->data); + reg = g_regCvars->add(pCvar, plug); + CVAR_REGISTER(reg->getcvar()); } - - // Note: if not a new cvar, then we don't set the values, and just keep - // the pre-existing value. - icvar->status = RG_VALID; - - // Store which plugin this is for, if we know. Use '0' for unknown - // plugin, as plugin index starts at 1. - if (iplug) - icvar->plugid = iplug->index; - else - icvar->plugid = 0; } // Replacement for engine routine RegUserMsg; called by plugins. Rather diff --git a/metamod/src/sdk_util.cpp b/metamod/src/sdk_util.cpp index 349247d..c5591a9 100644 --- a/metamod/src/sdk_util.cpp +++ b/metamod/src/sdk_util.cpp @@ -12,17 +12,72 @@ char *UTIL_VarArgs(char *format, ...) return string; } -// UTIL_LogPrintf - Prints a logged message to console. -// Preceded by LOG: ( timestamp ) < message > -void UTIL_LogPrintf(char *fmt, ...) +short FixedSigned16(float value, float scale) { - va_list argptr; - char string[1024]; + int output; - va_start(argptr, fmt); - Q_vsnprintf(string, sizeof(string), fmt, argptr); - va_end(argptr); + output = (int)(value * scale); - // Print to server console - ALERT(at_logged, "%s", string); + if (output > 32767) + output = 32767; + + if (output < -32768) + output = -32768; + + return (short)output; +} + +unsigned short FixedUnsigned16(float value, float scale) +{ + int output; + + output = (int)(value * scale); + if (output < 0) + output = 0; + if (output > 0xFFFF) + output = 0xFFFF; + + return (unsigned short)output; +} + +void UTIL_HudMessage(edict_t *pEntity, const hudtextparms_t &textparms, const char *pMessage) +{ + if (FNullEnt(pEntity) || pEntity->free) + return; + + MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, NULL, pEntity); + WRITE_BYTE(TE_TEXTMESSAGE); + WRITE_BYTE(textparms.channel & 0xFF); + + WRITE_SHORT(FixedSigned16(textparms.x, 1 << 13)); + WRITE_SHORT(FixedSigned16(textparms.y, 1 << 13)); + WRITE_BYTE(textparms.effect); + + WRITE_BYTE(textparms.r1); + WRITE_BYTE(textparms.g1); + WRITE_BYTE(textparms.b1); + WRITE_BYTE(textparms.a1); + + WRITE_BYTE(textparms.r2); + WRITE_BYTE(textparms.g2); + WRITE_BYTE(textparms.b2); + WRITE_BYTE(textparms.a2); + + WRITE_SHORT(FixedUnsigned16(textparms.fadeinTime, 1 << 8)); + WRITE_SHORT(FixedUnsigned16(textparms.fadeoutTime, 1 << 8)); + WRITE_SHORT(FixedUnsigned16(textparms.holdTime, 1 << 8)); + + if (textparms.effect == 2) + WRITE_SHORT(FixedUnsigned16(textparms.fxTime, 1 << 8)); + + if (strlen(pMessage) < 512) { + WRITE_STRING(pMessage); + } + else { + char tmp[512]; + strncpy(tmp, pMessage, sizeof tmp - 1); + tmp[sizeof tmp - 1] = 0; + WRITE_STRING(tmp); + } + MESSAGE_END(); } diff --git a/metamod/src/sdk_util.h b/metamod/src/sdk_util.h index 18239ab..0584c41 100644 --- a/metamod/src/sdk_util.h +++ b/metamod/src/sdk_util.h @@ -12,3 +12,5 @@ // defined. #include "enginecallbacks.h" #include + +void UTIL_HudMessage(edict_t *pEntity, const hudtextparms_t &textparms, const char *pMessage); diff --git a/metamod/src/studioapi.cpp b/metamod/src/studioapi.cpp index d088255..22f4ea9 100644 --- a/metamod/src/studioapi.cpp +++ b/metamod/src/studioapi.cpp @@ -35,24 +35,24 @@ C_DLLEXPORT int Server_GetBlendingInterface(int version, // "Couldn't get server .dll studio model blending interface. Version // mismatch?", but this will only show in "developer" (-dev) mode. - META_DEBUG(6, ("called: Server_GetBlendingInterface; version=%d", version)); + META_DEBUG(6, "called: Server_GetBlendingInterface; version=%d", version); if (missing) { - META_DEBUG(6, ("Skipping Server_GetBlendingInterface; was previously found missing")); + META_DEBUG(6, "Skipping Server_GetBlendingInterface; was previously found missing"); return 0; } if (!getblend) { - META_DEBUG(6, ("Looking up Server_GetBlendingInterface")); + META_DEBUG(6, "Looking up Server_GetBlendingInterface"); getblend = (GETBLENDAPI_FN)GameDLL.sys_module.getsym("Server_GetBlendingInterface"); } if (!getblend) { - META_DEBUG(6, ("Couldn't find Server_GetBlendingInterface in game DLL '%s': %s", GameDLL.name, "function not found")); + META_DEBUG(6, "Couldn't find Server_GetBlendingInterface in game DLL '%s': %s", GameDLL.name, "function not found"); missing = 1; return 0; } - META_DEBUG(6, ("Calling Server_GetBlendingInterface")); - return (getblend)(version, ppinterface, pstudio, rotationmatrix, bonetransform); + META_DEBUG(6, "Calling Server_GetBlendingInterface"); + return getblend(version, ppinterface, pstudio, rotationmatrix, bonetransform); } diff --git a/metamod/src/utils.cpp b/metamod/src/utils.cpp index 2ce8c7e..58b2dbe 100644 --- a/metamod/src/utils.cpp +++ b/metamod/src/utils.cpp @@ -1,5 +1,7 @@ #include "precompiled.h" +static_allocator g_static_allocator(static_allocator::mp_readwrite); + bool is_yes(const char* str) { return !Q_strcmp(str, "true") || !Q_strcmp(str, "yes") || !Q_strcmp(str, "1"); @@ -20,7 +22,12 @@ const char* LOCALINFO(char* key) return ENTITY_KEYVALUE(NULL, key); } -char* execmem_allocator::allocate(const size_t n) +static_allocator::static_allocator(memory_protection protection) : m_protection(protection) +{ + +} + +char* static_allocator::allocate(const size_t n) { if (!m_pages.size() || m_used + n > Pagesize) allocate_page(); @@ -30,7 +37,13 @@ char* execmem_allocator::allocate(const size_t n) return ptr; } -void execmem_allocator::deallocate_all() +char* static_allocator::strdup(const char* string) +{ + size_t len = strlen(string) + 1; + return (char *)memcpy(allocate(len), string, len); +} + +void static_allocator::deallocate_all() { for (auto page : m_pages) #ifdef WIN32 @@ -42,12 +55,12 @@ void execmem_allocator::deallocate_all() m_pages.clear(); } -size_t execmem_allocator::memoryUsed() const +size_t static_allocator::memory_used() const { return (m_pages.size() - 1) * Pagesize + m_used; } -void execmem_allocator::allocate_page() +void static_allocator::allocate_page() { #ifdef WIN32 auto page = VirtualAlloc(NULL, Pagesize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); diff --git a/metamod/src/utils.h b/metamod/src/utils.h index dfb1351..2199099 100644 --- a/metamod/src/utils.h +++ b/metamod/src/utils.h @@ -1,11 +1,34 @@ #pragma once -class execmem_allocator +template +char(&ArraySizeHelper(T(&array)[N]))[N]; +#define arraysize(array) (sizeof(ArraySizeHelper(array))) + +class static_allocator { public: + enum memory_protection : uint8 + { +#ifdef _WIN32 + mp_readwrite = PAGE_READWRITE, + mp_rwx = PAGE_EXECUTE_READWRITE +#else + mp_readwrite = PROT_READ | PROT_WRITE, + mp_rwx = PROT_READ | PROT_WRITE | PROT_EXEC +#endif + }; + + static_allocator(memory_protection protection); char* allocate(const size_t n); + char* strdup(const char* string); void deallocate_all(); - size_t memoryUsed() const; + size_t memory_used() const; + + template + T* allocate() + { + return (T *)allocate(sizeof(T)); + } private: void allocate_page(); @@ -17,8 +40,11 @@ private: size_t m_used = 0; std::vector m_pages; + memory_protection m_protection; }; +extern static_allocator g_static_allocator; + bool is_yes(const char* str); bool is_no(const char* str);