2
0
mirror of https://github.com/rehlds/metamod-r.git synced 2025-02-12 06:38:47 +03:00
metamod-r/metamod/src/mreg.cpp

493 lines
12 KiB
C++
Raw Normal View History

2016-07-26 07:22:47 +07:00
#include "precompiled.h"
2016-07-04 12:07:29 +06:00
// Init values. It would probably be more "proper" to use containers and
// constructors, rather than arrays and init-functions.
2016-07-26 07:22:47 +07:00
void MRegCmd::init(int idx)
2016-07-04 12:07:29 +06:00
{
index = idx;
name = NULL;
pfnCmd = NULL;
plugid = 0;
status = RG_INVALID;
}
// Try to call the function. Relies on OS-specific routine to attempt
// calling the function without generating a segfault from an unloaded
// plugin DLL.
// meta_errno values:
// - ME_BADREQ function disabled/invalid
// - ME_ARGUMENT function pointer is null
2016-07-26 23:31:47 +07:00
mBOOL MRegCmd::call()
2016-07-26 07:22:47 +07:00
{
2016-07-04 12:07:29 +06:00
mBOOL ret;
// can we expect to call this function?
2016-07-26 07:22:47 +07:00
if (status != RG_VALID)
2016-07-26 23:31:47 +07:00
RETURN_ERRNO(mFALSE, ME_BADREQ);
2016-07-26 07:22:47 +07:00
if (!pfnCmd)
2016-07-26 23:31:47 +07:00
RETURN_ERRNO(mFALSE, ME_ARGUMENT);
2016-07-04 12:07:29 +06:00
// try to call this function
ret = os_safe_call(pfnCmd);
2016-07-26 23:31:47 +07:00
if (!ret)
{
2016-07-04 12:07:29 +06:00
META_DEBUG(4, ("Plugin reg_cmd '%s' called after unloaded; removed from list", name));
status = RG_INVALID;
pfnCmd = NULL;
2016-07-04 12:07:29 +06:00
// NOTE: we can't free the malloc'd space for the name, as that
// would just re-introduce the segfault problem..
}
2016-07-26 23:31:47 +07:00
2016-07-04 12:07:29 +06:00
// meta_errno (if failed) is set already in os_safe_call()
2016-07-26 23:31:47 +07:00
return ret;
2016-07-04 12:07:29 +06:00
}
2016-07-26 23:31:47 +07:00
MRegCmdList::MRegCmdList()
2016-07-04 12:07:29 +06:00
: mlist(0), size(REG_CMD_GROWSIZE), endlist(0)
{
int i;
2016-07-26 23:31:47 +07:00
mlist = (MRegCmd *)Q_malloc(size * sizeof(MRegCmd));
2016-07-04 12:07:29 +06:00
// initialize array
for (i = 0; i < size; i++)
mlist[i].init(i + 1); // 1-based index
2016-07-26 23:31:47 +07:00
2016-07-26 07:22:47 +07:00
endlist = 0;
2016-07-04 12:07:29 +06:00
}
// Try to find a registered function with the given name.
// meta_errno values:
// - ME_NOTFOUND couldn't find a matching function
2016-07-26 23:31:47 +07:00
MRegCmd *MRegCmdList::find(const char *findname)
{
2016-07-26 23:31:47 +07:00
for (int i = 0; i < endlist; i++)
{
if (!Q_stricmp(mlist[i].name, findname))
return &mlist[i];
2016-07-04 12:07:29 +06:00
}
2016-07-26 23:31:47 +07:00
2016-07-04 12:07:29 +06:00
RETURN_ERRNO(NULL, ME_NOTFOUND);
}
// Add the given name to the list and return the instance. This only
// writes the "name" to the new cmd; other fields are writtin by caller
// (meta_AddServerCommand).
// meta_errno values:
// - ME_NOMEM couldn't realloc or malloc for various parts
2016-07-26 23:31:47 +07:00
MRegCmd *MRegCmdList::add(const char *addname)
{
2016-07-26 23:31:47 +07:00
if (endlist == size)
{
2016-07-04 12:07:29 +06:00
// grow array
2016-07-26 23:31:47 +07:00
int newsize = size + REG_CMD_GROWSIZE;
2016-07-04 12:07:29 +06:00
META_DEBUG(6, ("Growing reg cmd list from %d to %d", size, newsize));
2016-07-26 23:31:47 +07:00
MRegCmd *temp = (MRegCmd *) realloc(mlist, newsize * sizeof(MRegCmd));
if (!temp)
{
META_ERROR("Couldn't grow registered command list to %d for '%s': %s", newsize, addname, strerror(errno));
2016-07-04 12:07:29 +06:00
RETURN_ERRNO(NULL, ME_NOMEM);
}
2016-07-26 23:31:47 +07:00
mlist = temp;
size = newsize;
2016-07-26 23:31:47 +07:00
2016-07-04 12:07:29 +06:00
// initialize new (unused) entries
2016-07-26 23:31:47 +07:00
for (int i = endlist; i < size; i++)
mlist[i].init(i + 1); // 1-based
2016-07-04 12:07:29 +06:00
}
2016-07-26 23:31:47 +07:00
MRegCmd *icmd = &mlist[endlist];
2016-07-04 12:07:29 +06:00
// Malloc space separately for the command name, because:
2016-07-26 23:31:47 +07:00
// - Can't point to memory loc in plugin (another segv waiting to
2016-07-04 12:07:29 +06:00
// happen).
2016-07-26 23:31:47 +07:00
// - Can't point to memory in mlist which might get moved later by
2016-07-04 12:07:29 +06:00
// realloc (again, segv).
2016-07-26 23:31:47 +07:00
icmd->name = Q_strdup(addname);
if (!icmd->name)
{
META_ERROR("Couldn't Q_strdup for adding reg cmd name '%s': %s", addname, strerror(errno));
2016-07-04 12:07:29 +06:00
RETURN_ERRNO(NULL, ME_NOMEM);
}
2016-07-26 07:22:47 +07:00
2016-07-26 23:31:47 +07:00
endlist++;
return icmd;
2016-07-04 12:07:29 +06:00
}
// Disable any functions belonging to the given plugin (by index id).
void MRegCmdList::disable(int plugin_id)
{
2016-07-26 23:31:47 +07:00
for (int i = 0; i < size; i++)
{
2016-07-26 07:22:47 +07:00
if (mlist[i].plugid == plugin_id)
2016-07-04 12:07:29 +06:00
mlist[i].status = RG_INVALID;
}
}
// List all the registered commands.
2016-07-26 23:31:47 +07:00
void MRegCmdList::show()
2016-07-26 07:22:47 +07:00
{
2016-07-26 23:31:47 +07:00
int n = 0, a = 0;
MRegCmd *icmd;
MPlugin *iplug;
char bplug[18 + 1]; // +1 for term null
2016-07-04 12:07:29 +06:00
META_CONS("Registered plugin commands:");
2016-07-26 23:31:47 +07:00
META_CONS(" %*s %-*s %-s", WIDTH_MAX_REG, "", sizeof(bplug) - 1, "plugin", "command");
for (int i = 0; i < endlist; i++)
{
2016-07-04 12:07:29 +06:00
icmd = &mlist[i];
2016-07-26 23:31:47 +07:00
if (icmd->status == RG_VALID)
{
iplug = g_plugins->find(icmd->plugid);
2016-07-26 23:31:47 +07:00
if (iplug)
{
Q_strncpy(bplug, iplug->desc, sizeof bplug - 1);
bplug[sizeof bplug - 1] = '\0';
2016-07-26 07:22:47 +07:00
}
2016-07-26 23:31:47 +07:00
else
{
Q_strncpy(bplug, "(unknown)", sizeof bplug - 1);
bplug[sizeof bplug - 1] = '\0';
2016-07-26 07:22:47 +07:00
}
2016-07-04 12:07:29 +06:00
}
2016-07-26 23:31:47 +07:00
else
{
Q_strncpy(bplug, "(unloaded)", sizeof bplug - 1);
bplug[sizeof bplug - 1] = '\0';
2016-07-26 07:22:47 +07:00
}
2016-07-26 23:31:47 +07:00
META_CONS(" [%*d] %-*s %-s", WIDTH_MAX_REG, icmd->index, sizeof(bplug) - 1, bplug, icmd->name);
if (icmd->status == RG_VALID)
a++;
2016-07-04 12:07:29 +06:00
n++;
}
2016-07-26 23:31:47 +07:00
2016-07-04 12:07:29 +06:00
META_CONS("%d commands, %d available (%d allocated)", n, a, size);
}
// List all the registered commands for the given plugin id.
void MRegCmdList::show(int plugin_id)
{
2016-07-26 23:31:47 +07:00
int n = 0;
MRegCmd *icmd;
2016-07-26 07:22:47 +07:00
2016-07-04 12:07:29 +06:00
// If OS doesn't support DLFNAME, then we can't know what the plugin's
// registered cvars are.
DLFNAME(NULL);
2016-07-26 23:31:47 +07:00
if (meta_errno == ME_OSNOTSUP)
{
2016-07-04 12:07:29 +06:00
META_CONS("Registered commands: unknown (can't get info under this OS)");
return;
}
META_CONS("Registered commands:");
2016-07-26 23:31:47 +07:00
for (int i = 0; i < endlist; i++)
{
2016-07-04 12:07:29 +06:00
icmd = &mlist[i];
2016-07-26 23:31:47 +07:00
2016-07-26 07:22:47 +07:00
if (icmd->plugid != plugin_id)
2016-07-04 12:07:29 +06:00
continue;
2016-07-26 23:31:47 +07:00
2016-07-04 12:07:29 +06:00
META_CONS(" %s", icmd->name);
n++;
}
2016-07-26 23:31:47 +07:00
2016-07-04 12:07:29 +06:00
META_CONS("%d commands", n);
}
// Init values. It would probably be more "proper" to use containers and
// constructors, rather than arrays and init-functions.
2016-07-26 07:22:47 +07:00
void MRegCvar::init(int idx)
2016-07-04 12:07:29 +06:00
{
index = idx;
data = NULL;
plugid = 0;
status = RG_INVALID;
}
// Set the cvar, copying values from given cvar.
// meta_errno values:
// - ME_ARGUMENT given cvar doesn't match this cvar
2016-07-26 23:31:47 +07:00
mBOOL MRegCvar::set(cvar_t *src)
{
2016-07-26 23:31:47 +07:00
if (Q_stricmp(src->name, data->name))
{
META_ERROR("Tried to set cvar with mismatched name; src=%s dst=%s", src->name, data->name);
2016-07-04 12:07:29 +06:00
RETURN_ERRNO(mFALSE, ME_ARGUMENT);
}
2016-07-26 23:31:47 +07:00
2016-07-04 12:07:29 +06:00
// Would like to free() existing string, but can't tell where it was
// allocated...
2016-07-26 23:31:47 +07:00
data->string = Q_strdup(src->string);
2016-07-04 12:07:29 +06:00
data->flags = src->flags;
data->value = src->value;
data->next = src->next;
2016-07-26 23:31:47 +07:00
return mTRUE;
2016-07-04 12:07:29 +06:00
}
// Constructor
2016-07-26 23:31:47 +07:00
MRegCvarList::MRegCvarList()
2016-07-04 12:07:29 +06:00
: vlist(0), size(REG_CVAR_GROWSIZE), endlist(0)
{
2016-07-26 23:31:47 +07:00
vlist = (MRegCvar *)Q_malloc(size * sizeof(MRegCvar));
2016-07-04 12:07:29 +06:00
// initialize array
2016-07-26 23:31:47 +07:00
for (int i = 0; i < size; i++)
vlist[i].init(i + 1); // 1 - based
endlist = 0;
2016-07-04 12:07:29 +06:00
}
// 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
2016-07-26 23:31:47 +07:00
MRegCvar *MRegCvarList::add(const char *addname)
{
2016-07-26 23:31:47 +07:00
MRegCvar *icvar;
if (endlist == size)
{
2016-07-04 12:07:29 +06:00
// grow array
2016-07-26 23:31:47 +07:00
int newsize = size + REG_CVAR_GROWSIZE;
2016-07-04 12:07:29 +06:00
META_DEBUG(6, ("Growing reg cvar list from %d to %d", size, newsize));
2016-07-26 23:31:47 +07:00
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));
2016-07-04 12:07:29 +06:00
RETURN_ERRNO(NULL, ME_NOMEM);
}
vlist = temp;
size = newsize;
2016-07-04 12:07:29 +06:00
// initialize new (unused) entries
2016-07-26 23:31:47 +07:00
for (int i = endlist; i < size; i++)
vlist[i].init(i + 1); // 1-based
2016-07-04 12:07:29 +06:00
}
icvar = &vlist[endlist];
// Malloc space for the cvar and cvar name, for two reasons:
2016-07-26 23:31:47 +07:00
// - Can't point to memory loc in plugin (another segv waiting to
2016-07-04 12:07:29 +06:00
// happen).
2016-07-26 23:31:47 +07:00
// - Can't point to memory in vlist which might get moved later by
2016-07-04 12:07:29 +06:00
// realloc (again, segv).
2016-07-26 23:31:47 +07:00
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));
2016-07-04 12:07:29 +06:00
RETURN_ERRNO(NULL, ME_NOMEM);
}
2016-07-26 23:31:47 +07:00
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));
2016-07-04 12:07:29 +06:00
RETURN_ERRNO(NULL, ME_NOMEM);
}
endlist++;
2016-07-26 23:31:47 +07:00
return icvar;
2016-07-04 12:07:29 +06:00
}
// Try to find a registered cvar with the given name.
// meta_errno values:
// - ME_NOTFOUND couldn't find a matching cvar
2016-07-26 23:31:47 +07:00
MRegCvar *MRegCvarList::find(const char *findname)
{
2016-07-26 23:31:47 +07:00
for (int i = 0; i < endlist; i++)
{
if (!_stricmp(vlist[i].data->name, findname))
2016-07-26 23:31:47 +07:00
return &vlist[i];
2016-07-04 12:07:29 +06:00
}
2016-07-26 23:31:47 +07:00
2016-07-04 12:07:29 +06:00
RETURN_ERRNO(NULL, ME_NOTFOUND);
}
// Disable any cvars belonging to the given plugin (by index id).
void MRegCvarList::disable(int plugin_id)
{
2016-07-04 12:07:29 +06:00
int i;
2016-07-26 23:31:47 +07:00
MRegCvar *icvar;
for (i = 0; i < size; i++)
{
icvar = &vlist[i];
2016-07-26 23:31:47 +07:00
if (icvar->plugid == plugin_id)
{
2016-07-04 12:07:29 +06:00
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]");
}
}
}
// List all the registered cvars.
2016-07-26 23:31:47 +07:00
void MRegCvarList::show()
{
int i, n = 0, a = 0;
2016-07-26 23:31:47 +07:00
MRegCvar *icvar;
MPlugin *iplug;
char bplug[13 + 1], bname[20 + 1], bval[15 + 1]; // +1 for term null
2016-07-04 12:07:29 +06:00
META_CONS("Registered plugin cvars:");
2016-07-26 23:31:47 +07:00
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++)
{
2016-07-04 12:07:29 +06:00
icvar = &vlist[i];
2016-07-26 23:31:47 +07:00
if (icvar->status == RG_VALID)
{
iplug = g_plugins->find(icvar->plugid);
2016-07-26 23:31:47 +07:00
if (iplug)
{
Q_strncpy(bplug, iplug->desc, sizeof bplug - 1);
bplug[sizeof bplug - 1] = '\0';
2016-07-26 07:22:47 +07:00
}
2016-07-26 23:31:47 +07:00
else
{
Q_strncpy(bplug, "(unknown)", sizeof bplug - 1);
bplug[sizeof bplug - 1] = '\0';
2016-07-26 07:22:47 +07:00
}
2016-07-04 12:07:29 +06:00
}
2016-07-26 23:31:47 +07:00
else
{
Q_strncpy(bplug, "(unloaded)", sizeof bplug - 1);
bplug[sizeof bplug - 1] = '\0';
2016-07-26 07:22:47 +07:00
}
2016-07-26 23:31:47 +07:00
Q_strncpy(bname, icvar->data->name, sizeof bname - 1);
bname[sizeof bname - 1] = '\0';
2016-07-26 23:31:47 +07:00
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);
if (icvar->status == RG_VALID)
a++;
2016-07-04 12:07:29 +06:00
n++;
}
META_CONS("%d cvars, %d available (%d allocated)", n, a, size);
}
// List the registered cvars for the given plugin id.
void MRegCvarList::show(int plugin_id)
{
2016-07-26 23:31:47 +07:00
int n = 0;
MRegCvar *icvar;
char bname[30 + 1], bval[15 + 1]; // +1 for term null
// If OS doesn't support DLFNAME, then we can't know what the plugin's
// registered cvars are.
DLFNAME(NULL);
2016-07-26 23:31:47 +07:00
if (meta_errno == ME_OSNOTSUP)
{
META_CONS("Registered cvars: unknown (can't get info under this OS)");
return;
}
2016-07-26 23:31:47 +07:00
META_CONS("%-*s %*s %s", sizeof(bname) - 1, "Registered cvars:", sizeof(bval) - 1, "float value", "string value");
for (int i = 0; i < endlist; i++)
{
2016-07-04 12:07:29 +06:00
icvar = &vlist[i];
2016-07-26 07:22:47 +07:00
if (icvar->plugid != plugin_id)
2016-07-04 12:07:29 +06:00
continue;
2016-07-26 23:31:47 +07:00
Q_strncpy(bname, icvar->data->name, sizeof bname - 1);
bname[sizeof bname - 1] = '\0';
2016-07-26 23:31:47 +07:00
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);
2016-07-04 12:07:29 +06:00
n++;
}
2016-07-26 23:31:47 +07:00
2016-07-26 07:22:47 +07:00
META_CONS("%d cvars", n);
}
2016-07-04 12:07:29 +06:00
// Constructor
2016-07-26 23:31:47 +07:00
MRegMsgList::MRegMsgList()
2016-07-04 12:07:29 +06:00
: size(MAX_REG_MSGS), endlist(0)
{
// initialize array
2016-07-26 23:31:47 +07:00
Q_memset(mlist, 0, sizeof(mlist));
for (int i = 0; i < size; i++)
{
mlist[i].index = i + 1; // 1-based
2016-07-04 12:07:29 +06:00
}
2016-07-26 23:31:47 +07:00
endlist = 0;
2016-07-04 12:07:29 +06:00
}
// Add the given user msg the list and return the instance.
// meta_errno values:
// - ME_MAXREACHED reached max number of msgs allowed
2016-07-26 23:31:47 +07:00
MRegMsg *MRegMsgList::add(const char *addname, int addmsgid, int addsize)
{
2016-07-26 23:31:47 +07:00
if (endlist == size)
{
2016-07-04 12:07:29 +06:00
// all slots used
2016-07-26 23:31:47 +07:00
META_ERROR("Couldn't add registered msg '%s' to list; reached max msgs (%d)", addname, size);
2016-07-04 12:07:29 +06:00
RETURN_ERRNO(NULL, ME_MAXREACHED);
}
2016-07-26 23:31:47 +07:00
MRegMsg *imsg = &mlist[endlist];
2016-07-04 12:07:29 +06:00
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;
2016-07-04 12:07:29 +06:00
2016-07-26 23:31:47 +07:00
return imsg;
2016-07-04 12:07:29 +06:00
}
// Try to find a registered msg with the given name.
// meta_errno values:
// - ME_NOTFOUND couldn't find a matching cvar
2016-07-26 23:31:47 +07:00
MRegMsg *MRegMsgList::find(const char *findname)
2016-07-26 07:22:47 +07:00
{
2016-07-26 23:31:47 +07:00
for (int i = 0; i < endlist; i++)
{
if (!Q_strcmp(mlist[i].name, findname))
return &mlist[i];
2016-07-04 12:07:29 +06:00
}
2016-07-26 23:31:47 +07:00
2016-07-04 12:07:29 +06:00
RETURN_ERRNO(NULL, ME_NOTFOUND);
}
// Try to find a registered msg with the given msgid.
// meta_errno values:
// - ME_NOTFOUND couldn't find a matching cvar
2016-07-26 23:31:47 +07:00
MRegMsg *MRegMsgList::find(int findmsgid)
2016-07-26 07:22:47 +07:00
{
2016-07-26 23:31:47 +07:00
for (int i = 0; i < endlist; i++)
{
2016-07-26 07:22:47 +07:00
if (mlist[i].msgid == findmsgid)
2016-07-26 23:31:47 +07:00
return &mlist[i];
2016-07-04 12:07:29 +06:00
}
2016-07-26 23:31:47 +07:00
2016-07-04 12:07:29 +06:00
RETURN_ERRNO(NULL, ME_NOTFOUND);
}
// List the registered usermsgs for the gamedll.
2016-07-26 23:31:47 +07:00
void MRegMsgList::show()
2016-07-26 07:22:47 +07:00
{
int i, n = 0;
2016-07-26 23:31:47 +07:00
MRegMsg *imsg;
char bname[25 + 1]; // +1 for term null
2016-07-04 12:07:29 +06:00
2016-07-26 23:31:47 +07:00
META_CONS("%-*s %5s %5s", sizeof(bname) - 1, "Game registered user msgs:", "msgid", "size");
for (i = 0; i < endlist; i++)
{
2016-07-04 12:07:29 +06:00
imsg = &mlist[i];
2016-07-26 23:31:47 +07:00
Q_strncpy(bname, imsg->name, sizeof bname - 1);
bname[sizeof bname - 1] = '\0';
2016-07-26 23:31:47 +07:00
META_CONS(" %-*s %3d %3d", sizeof(bname) - 1, bname, imsg->msgid, imsg->size);
2016-07-04 12:07:29 +06:00
n++;
}
2016-07-26 23:31:47 +07:00
2016-07-26 07:22:47 +07:00
META_CONS("%d game user msgs", n);
2016-07-04 12:07:29 +06:00
}