2
0
mirror of https://github.com/rehlds/metamod-r.git synced 2025-01-16 00:28:07 +03:00
metamod-r/metamod/src/mutil.cpp

445 lines
11 KiB
C++
Raw Normal View History

// vi: set ts=4 sw=4 :
// vim: set tw=75 :
// mutil.cpp - utility functions to provide to plugins
/*
* Copyright (c) 2001-2003 Will Day <willday@hpgx.net>
*
* This file is part of Metamod.
*
* Metamod is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* Metamod is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Metamod; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game g_engine ("HL
* g_engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL g_engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
2016-07-26 07:22:47 +07:00
#include "precompiled.h"
2016-07-04 12:07:29 +06:00
hudtextparms_t default_csay_tparms = {
-1, 0.25, // x, y
2, // effect
0, 255, 0, 0, // r, g, b, a1
0, 0, 0, 0, // r2, g2, b2, a2
0, 0, 10, 10, // fadein, fadeout, hold, fxtime
1 // channel
2016-07-04 12:07:29 +06:00
};
// Log to console; newline added.
void mutil_LogConsole(plid_t /* plid */, const char* fmt, ...)
{
2016-07-04 12:07:29 +06:00
va_list ap;
char buf[MAX_LOGMSG_LEN];
unsigned int len;
2016-07-04 12:07:29 +06:00
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
2016-07-04 12:07:29 +06:00
va_end(ap);
// end msg with newline
len = strlen(buf);
if (len < sizeof(buf) - 2) // -1 null, -1 for newline
strcat(buf, "\n");
2016-07-04 12:07:29 +06:00
else
buf[len - 1] = '\n';
2016-07-04 12:07:29 +06:00
SERVER_PRINT(buf);
}
// Log regular message to logs; newline added.
void mutil_LogMessage(plid_t plid, const char* fmt, ...)
{
2016-07-04 12:07:29 +06:00
va_list ap;
char buf[MAX_LOGMSG_LEN];
plugin_info_t* plinfo;
plinfo = (plugin_info_t *)plid;
2016-07-04 12:07:29 +06:00
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
2016-07-04 12:07:29 +06:00
va_end(ap);
ALERT(at_logged, "[%s] %s\n", plinfo->logtag, buf);
}
// Log an error message to logs; newline added.
void mutil_LogError(plid_t plid, const char* fmt, ...)
{
2016-07-04 12:07:29 +06:00
va_list ap;
char buf[MAX_LOGMSG_LEN];
plugin_info_t* plinfo;
plinfo = (plugin_info_t *)plid;
2016-07-04 12:07:29 +06:00
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
2016-07-04 12:07:29 +06:00
va_end(ap);
ALERT(at_logged, "[%s] ERROR: %s\n", plinfo->logtag, buf);
}
// Log a message only if cvar "developer" set; newline added.
void mutil_LogDeveloper(plid_t plid, const char* fmt, ...)
{
2016-07-04 12:07:29 +06:00
va_list ap;
char buf[MAX_LOGMSG_LEN];
plugin_info_t* plinfo;
if ((int) CVAR_GET_FLOAT("developer") == 0)
2016-07-04 12:07:29 +06:00
return;
plinfo = (plugin_info_t *)plid;
2016-07-04 12:07:29 +06:00
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
2016-07-04 12:07:29 +06:00
va_end(ap);
ALERT(at_logged, "[%s] dev: %s\n", plinfo->logtag, buf);
}
// Print message on center of all player's screens. Uses default text
// parameters (color green, 10 second fade-in).
void mutil_CenterSay(plid_t plid, const char* fmt, ...)
{
2016-07-04 12:07:29 +06:00
va_list ap;
va_start(ap, fmt);
mutil_CenterSayVarargs(plid, default_csay_tparms, fmt, ap);
va_end(ap);
}
// Print a center-message, with given text parameters.
void mutil_CenterSayParms(plid_t plid, hudtextparms_t tparms, const char* fmt, ...)
{
2016-07-04 12:07:29 +06:00
va_list ap;
va_start(ap, fmt);
mutil_CenterSayVarargs(plid, tparms, fmt, ap);
va_end(ap);
}
// Print a center-message, with text parameters and varargs. Provides
// functionality to the above center_say interfaces.
void mutil_CenterSayVarargs(plid_t plid, hudtextparms_t tparms,
const char* fmt, va_list ap)
{
char buf[MAX_LOGMSG_LEN];
int n;
edict_t* pEntity;
vsnprintf(buf, sizeof(buf), fmt, ap);
mutil_LogMessage(plid, "(centersay) %s", buf);
for (n = 1; n <= gpGlobals->maxClients; n++) {
pEntity = INDEXENT(n);
if (FNullEnt(pEntity) || pEntity->free)
continue;
//META_UTIL_HudMessage(pEntity, tparms, buf); // TODO
}
}
2016-07-04 12:07:29 +06:00
// Allow plugins to call the entity functions in the GameDLL. In
// particular, calling "player()" as needed by most Bots. Suggested by
// Jussi Kivilinna.
qboolean mutil_CallGameEntity(plid_t plid, const char* entStr, entvars_t* pev)
{
plugin_info_t* plinfo;
2016-07-04 12:07:29 +06:00
ENTITY_FN pfnEntity;
plinfo = (plugin_info_t *)plid;
2016-07-04 12:07:29 +06:00
META_DEBUG(8, ("Looking up game entity '%s' for plugin '%s'", entStr,
plinfo->name));
2016-07-04 12:07:29 +06:00
pfnEntity = (ENTITY_FN) DLSYM(GameDLL.handle, entStr);
2016-07-26 07:22:47 +07:00
if (!pfnEntity) {
META_ERROR("Couldn't find game entity '%s' in game DLL '%s' for plugin '%s'", entStr, GameDLL.name, plinfo->name);
return (false);
2016-07-04 12:07:29 +06:00
}
META_DEBUG(7, ("Calling game entity '%s' for plugin '%s'", entStr,
plinfo->name));
2016-07-04 12:07:29 +06:00
(*pfnEntity)(pev);
return (true);
2016-07-04 12:07:29 +06:00
}
// Find a usermsg, registered by the gamedll, with the corresponding
// msgname, and return remaining info about it (msgid, size).
int mutil_GetUserMsgID(plid_t plid, const char* msgname, int* size)
{
plugin_info_t* plinfo;
MRegMsg* umsg;
2016-07-04 12:07:29 +06:00
plinfo = (plugin_info_t *)plid;
2016-07-04 12:07:29 +06:00
META_DEBUG(8, ("Looking up usermsg name '%s' for plugin '%s'", msgname,
plinfo->name));
umsg = g_regMsgs->find(msgname);
2016-07-26 07:22:47 +07:00
if (umsg) {
if (size)
*size = umsg->size;
return (umsg->msgid);
2016-07-04 12:07:29 +06:00
}
else
return (0);
2016-07-04 12:07:29 +06:00
}
// Find a usermsg, registered by the gamedll, with the corresponding
// msgid, and return remaining info about it (msgname, size).
const char* mutil_GetUserMsgName(plid_t plid, int msgid, int* size)
{
plugin_info_t* plinfo;
MRegMsg* umsg;
2016-07-04 12:07:29 +06:00
plinfo = (plugin_info_t *)plid;
2016-07-04 12:07:29 +06:00
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;
2016-07-04 12:07:29 +06:00
// from dlls/util.h.
2016-07-26 07:22:47 +07:00
if (msgid < 64) {
switch (msgid) {
2016-07-26 07:22:47 +07:00
case SVC_TEMPENTITY:
if (size) *size = -1;
return ("tempentity?");
2016-07-26 07:22:47 +07:00
case SVC_INTERMISSION:
if (size) *size = -1;
return ("intermission?");
2016-07-26 07:22:47 +07:00
case SVC_CDTRACK:
if (size) *size = -1;
return ("cdtrack?");
2016-07-26 07:22:47 +07:00
case SVC_WEAPONANIM:
if (size) *size = -1;
return ("weaponanim?");
2016-07-26 07:22:47 +07:00
case SVC_ROOMTYPE:
if (size) *size = -1;
return ("roomtype?");
2016-07-26 07:22:47 +07:00
case SVC_DIRECTOR:
if (size) *size = -1;
return ("director?");
2016-07-04 12:07:29 +06:00
}
}
umsg = g_regMsgs->find(msgid);
if (umsg) {
2016-07-26 07:22:47 +07:00
if (size)
*size = umsg->size;
2016-07-04 12:07:29 +06:00
// 'name' is assumed to be a constant string, allocated in the
// gamedll.
return (umsg->name);
2016-07-04 12:07:29 +06:00
}
else
return (NULL);
2016-07-04 12:07:29 +06:00
}
// Return the full path of the plugin's loaded dll/so file.
const char* mutil_GetPluginPath(plid_t plid)
{
static char buf[PATH_MAX ];
MPlugin* plug;
plug = g_plugins->find(plid);
if (!plug) {
META_ERROR("GetPluginPath: couldn't find plugin '%s'",
plid->name);
return (NULL);
2016-07-04 12:07:29 +06:00
}
strncpy(buf, plug->pathname, sizeof buf - 1);
buf[sizeof buf - 1] = '\0';
2016-07-26 07:22:47 +07:00
return buf;
2016-07-04 12:07:29 +06:00
}
// Return various string-based info about the game/MOD/gamedll.
const char* mutil_GetGameInfo(plid_t plid, ginfo_t type)
2016-07-26 07:22:47 +07:00
{
2016-07-04 12:07:29 +06:00
static char buf[MAX_STRBUF_LEN];
const char* cp;
switch (type) {
2016-07-26 07:22:47 +07:00
case GINFO_NAME:
cp = GameDLL.name;
break;
case GINFO_DESC:
cp = GameDLL.desc;
break;
case GINFO_GAMEDIR:
cp = GameDLL.gamedir;
break;
case GINFO_DLL_FULLPATH:
cp = GameDLL.pathname;
break;
case GINFO_DLL_FILENAME:
cp = GameDLL.file;
break;
case GINFO_REALDLL_FULLPATH:
cp = GameDLL.real_pathname;
break;
default:
META_ERROR("GetGameInfo: invalid request '%d' from plugin '%s'",
type, plid->name);
return (NULL);
2016-07-04 12:07:29 +06:00
}
strncpy(buf, cp, sizeof buf - 1);
buf[sizeof buf - 1] = '\0';
2016-07-26 07:22:47 +07:00
return buf;
2016-07-04 12:07:29 +06:00
}
int mutil_LoadMetaPlugin(plid_t plid, const char* fname, PLUG_LOADTIME now, void** plugin_handle)
2016-07-04 12:07:29 +06:00
{
MPlugin* pl_loaded;
2016-07-26 07:22:47 +07:00
if (NULL == fname) {
return ME_ARGUMENT;
2016-07-04 12:07:29 +06:00
}
meta_errno = ME_NOERROR;
if (! (pl_loaded = g_plugins->plugin_addload(plid, fname, now))) {
2016-07-26 07:22:47 +07:00
if (plugin_handle)
2016-07-04 12:07:29 +06:00
*plugin_handle = NULL;
2016-07-26 07:22:47 +07:00
return meta_errno;
}
else {
2016-07-26 07:22:47 +07:00
if (plugin_handle)
*plugin_handle = (void *)pl_loaded->handle;
2016-07-26 07:22:47 +07:00
return 0;
2016-07-04 12:07:29 +06:00
}
}
int mutil_UnloadMetaPlugin(plid_t plid, const char* fname, PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
2016-07-04 12:07:29 +06:00
{
MPlugin* findp = NULL;
2016-07-04 12:07:29 +06:00
int pindex;
char* endptr;
2016-07-26 07:22:47 +07:00
if (NULL == fname) {
return ME_ARGUMENT;
2016-07-04 12:07:29 +06:00
}
pindex = strtol(fname, &endptr, 10);
2016-07-26 07:22:47 +07:00
if (*fname != '\0' && *endptr == '\0')
findp = g_plugins->find(pindex);
2016-07-04 12:07:29 +06:00
else
findp = g_plugins->find_match(fname);
2016-07-04 12:07:29 +06:00
2016-07-26 07:22:47 +07:00
if (!findp)
return meta_errno;
2016-07-04 12:07:29 +06:00
meta_errno = ME_NOERROR;
2016-07-26 07:22:47 +07:00
if (findp->plugin_unload(plid, now, reason))
return 0;
return meta_errno;
2016-07-04 12:07:29 +06:00
}
int mutil_UnloadMetaPluginByHandle(plid_t plid, void* plugin_handle, PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
2016-07-04 12:07:29 +06:00
{
MPlugin* findp;
2016-07-04 12:07:29 +06:00
2016-07-26 07:22:47 +07:00
if (NULL == plugin_handle) {
return ME_ARGUMENT;
2016-07-04 12:07:29 +06:00
}
if (!(findp = g_plugins->find((DLHANDLE)plugin_handle)))
2016-07-26 07:22:47 +07:00
return ME_NOTFOUND;
2016-07-04 12:07:29 +06:00
meta_errno = ME_NOERROR;
2016-07-26 07:22:47 +07:00
if (findp->plugin_unload(plid, now, reason))
return 0;
2016-07-04 12:07:29 +06:00
2016-07-26 07:22:47 +07:00
return meta_errno;
2016-07-04 12:07:29 +06:00
}
const char* mutil_IsQueryingClientCvar(plid_t /*plid*/, const edict_t* pEdict)
{
return g_Players.is_querying_cvar(pEdict);
2016-07-04 12:07:29 +06:00
}
int mutil_MakeRequestId(plid_t /*plid*/)
{
//the offset is to distinguish from gamedll requests, if any
return (abs(0xbeef << 16) + (++requestid_counter));
2016-07-04 12:07:29 +06:00
}
void mutil_GetHookTables(plid_t /*plid*/, enginefuncs_t** peng, DLL_FUNCTIONS** pdll, NEW_DLL_FUNCTIONS** pnewdll)
{
2016-07-04 12:07:29 +06:00
if (peng)
*peng = &meta_engfuncs;
if (pdll)
*pdll = pHookedDllFunctions;
2016-07-04 12:07:29 +06:00
if (pnewdll)
*pnewdll = pHookedNewDllFunctions;
}
#ifdef UNFINISHED
int mutil_HookGameEvent(plid_t plid, game_event_t event,
event_func_t pfnHandle)
{
return(Hooks->add(plid, event, pfnHandle));
}
int mutil_HookLogTrigger(plid_t plid, const char *trigger,
logmatch_func_t pfnHandle)
{
return(Hooks->add(plid, H_TRIGGER, trigger, pfnHandle));
}
int mutil_HookLogString(plid_t plid, const char *string,
logmatch_func_t pfnHandle)
{
return(Hooks->add(plid, H_STRING, string, pfnHandle));
}
int mutil_HookLogRegex(plid_t plid, const char *pattern,
logmatch_func_t pfnHandle)
{
return(Hooks->add(plid, H_STRING, pattern, pfnHandle));
}
qboolean mutil_RemoveHookID(plid_t plid, int hookid) {
mBOOL ret;
ret=Hooks->remove(plid, hookid);
if(ret==mTRUE) return(true);
else return(false);
}
int mutil_RemoveHookAll(plid_t plid) {
return(Hooks->remove_all(plid));
2016-07-04 12:07:29 +06:00
}
#endif /* UNFINISHED */
2016-07-04 12:07:29 +06:00
// Meta Utility Function table.
mutil_funcs_t MetaUtilFunctions = {
mutil_LogConsole, // pfnLogConsole
mutil_LogMessage, // pfnLogMessage
mutil_LogError, // pfnLogError
mutil_LogDeveloper, // pfnLogDeveloper
mutil_CenterSay, // pfnCenterSay
mutil_CenterSayParms, // pfnCenterSayParms
mutil_CenterSayVarargs, // pfnCenterSayVarargs
mutil_CallGameEntity, // pfnCallGameEntity
mutil_GetUserMsgID, // pfnGetUserMsgID
mutil_GetUserMsgName, // pfnGetUserMsgName
mutil_GetPluginPath, // pfnGetPluginPath
mutil_GetGameInfo, // pfnGetGameInfo
mutil_LoadMetaPlugin, // pfnLoadPlugin
mutil_UnloadMetaPlugin, // pfnUnloadPlugin
mutil_UnloadMetaPluginByHandle, //pfnUnloadPluginByHandle
mutil_IsQueryingClientCvar, //pfnIsQueryingClientCvar
mutil_MakeRequestId, // pfnMakeRequestId
mutil_GetHookTables, // pfnGetHookTables
#ifdef UNFINISHED
mutil_HookGameEvent, // pfnGameEvent
mutil_HookLogTrigger, // pfnLogTrigger
mutil_HookLogString, // pfnLogString
mutil_HookLogRegex, // pfnLogRegex
mutil_RemoveHookID, // pfnRemoveHookID
mutil_RemoveHookAll, // pfnRemoveHookAll
#endif /* UNFINISHED */
2016-07-04 12:07:29 +06:00
};