mirror of
https://github.com/rehlds/metamod-r.git
synced 2025-01-27 22:17:54 +03:00
Finished rewriting of mreg code
Debug macro replaced to inline function
This commit is contained in:
parent
be24b08896
commit
ccea6516cb
@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#define MM_PRE_HOOK
|
||||
#define MM_POST_HOOK
|
||||
|
||||
enum
|
||||
{
|
||||
P_PRE, // plugin function called before gamedll
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -11,11 +11,11 @@
|
||||
extern cvar_t meta_debug;
|
||||
|
||||
template<typename ...t_args>
|
||||
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, ...);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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<cvar_t>();
|
||||
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>()) 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)
|
||||
{
|
||||
// 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
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
||||
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>()) 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);
|
||||
}
|
||||
|
@ -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<MRegCmd *> 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<MRegCvar *> 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<MRegMsg *> m_list;
|
||||
};
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -12,3 +12,5 @@
|
||||
// defined.
|
||||
#include "enginecallbacks.h"
|
||||
#include <util.h>
|
||||
|
||||
void UTIL_HudMessage(edict_t *pEntity, const hudtextparms_t &textparms, const char *pMessage);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -1,11 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
class execmem_allocator
|
||||
template <typename T, size_t N>
|
||||
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<typename T>
|
||||
T* allocate()
|
||||
{
|
||||
return (T *)allocate(sizeof(T));
|
||||
}
|
||||
|
||||
private:
|
||||
void allocate_page();
|
||||
@ -17,8 +40,11 @@ private:
|
||||
|
||||
size_t m_used = 0;
|
||||
std::vector<void *> m_pages;
|
||||
memory_protection m_protection;
|
||||
};
|
||||
|
||||
extern static_allocator g_static_allocator;
|
||||
|
||||
bool is_yes(const char* str);
|
||||
bool is_no(const char* str);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user