Skip to content

Commit

Permalink
update plugin api and add helpers
Browse files Browse the repository at this point in the history
copied Scheduler, CommandArgs, admin logic from mmlib. Added a few more hooks. Plugins send the game a name so they can be identified when calling game functions (needed for clearing timers when a plugin is unloaded).

Added a "removeplugin" command and "adminlistfile" cvar. "pluginlist" cvar renamed to "pluginlistfile".
  • Loading branch information
wootguy committed Oct 28, 2024
1 parent 4c62125 commit df1a867
Show file tree
Hide file tree
Showing 15 changed files with 563 additions and 72 deletions.
4 changes: 4 additions & 0 deletions dlls/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -415,23 +415,27 @@ set(UTIL_HDR
Bsp.h
bsptypes.h
bsplimits.h
CommandArgs.h
plane.h
util.h
mstream.h
lagcomp.h
vector.h
Scheduler.h
TextMenu.h
../game_shared/shared_util.h
)
set(UTIL_SRC
animation.cpp
Bsp.cpp
bsptypes.cpp
CommandArgs.cpp
plane.cpp
sound.cpp
util.cpp
mstream.cpp
lagcomp.cpp
Scheduler.cpp
TextMenu.cpp
../pm_shared/pm_debug.cpp
../pm_shared/pm_math.cpp
Expand Down
74 changes: 74 additions & 0 deletions dlls/CommandArgs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include "CommandArgs.h"
#include "util.h"

CommandArgs::CommandArgs() {

}

void CommandArgs::loadArgs() {
std::string firstArgLower = toLowerCase(CMD_ARGV(0));
isConsoleCmd = firstArgLower != "say" && firstArgLower != "say_team";

std::string argStr = CMD_ARGC() > 1 ? CMD_ARGS() : "";

if (isConsoleCmd) {
argStr = CMD_ARGV(0) + std::string(" ") + argStr;
}

if (!isConsoleCmd && argStr.length() > 2 && argStr[0] == '\"' && argStr[argStr.length() - 1] == '\"') {
argStr = argStr.substr(1, argStr.length() - 2); // strip surrounding quotes
}

while (!argStr.empty()) {
// strip spaces
argStr = trimSpaces(argStr);


if (argStr[0] == '\"') { // quoted argument (include the spaces between quotes)
argStr = argStr.substr(1);
int endQuote = argStr.find("\"");

if (endQuote == -1) {
args.push_back(argStr);
break;
}

args.push_back(argStr.substr(0, endQuote));
argStr = argStr.substr(endQuote + 1);
}
else {
// normal argument, separate by space
int nextSpace = argStr.find(" ");

if (nextSpace == -1) {
args.push_back(argStr);
break;
}

args.push_back(argStr.substr(0, nextSpace));
argStr = argStr.substr(nextSpace + 1);
}
}
}

std::string CommandArgs::ArgV(int idx) {
if (idx >= 0 && idx < (int)args.size()) {
return args[idx];
}

return "";
}

int CommandArgs::ArgC() {
return args.size();
}

std::string CommandArgs::getFullCommand() {
std::string str = ArgV(0);

for (int i = 1; i < (int)args.size(); i++) {
str += " " + args[i];
}

return str;
}
26 changes: 26 additions & 0 deletions dlls/CommandArgs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once
#include <extdll.h>
#include <string>
#include <vector>
#include <stdint.h>

struct CommandArgs {
bool isConsoleCmd;

// gets current globally defined args
EXPORT CommandArgs();

EXPORT void loadArgs();

// returns empty string if idx is out of bounds
EXPORT std::string ArgV(int idx);

// return number of args
EXPORT int ArgC();

// return entire command string
EXPORT std::string getFullCommand();

private:
std::vector<std::string> args;
};
29 changes: 23 additions & 6 deletions dlls/PluginHooks.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#pragma once
#include "mod_api.h"

struct HOOK_RETURN_DATA {
Expand All @@ -21,24 +22,40 @@ struct HLCOOP_PLUGIN_HOOKS {
HOOK_RETURN_DATA (*pfnMapActivate)();

// called before the player PreThink function
HOOK_RETURN_DATA (*pfnPlayerPreThink)(CBasePlayer*);
HOOK_RETURN_DATA (*pfnPlayerPreThink)(CBasePlayer* pPlayer);

// called before the player PostThink function
HOOK_RETURN_DATA (*pfnPlayerPostThink)(CBasePlayer*);
HOOK_RETURN_DATA (*pfnPlayerPostThink)(CBasePlayer* pPlayer);

// called before the player Use function is called
HOOK_RETURN_DATA (*pfnPlayerUse)(CBasePlayer*);
HOOK_RETURN_DATA (*pfnPlayerUse)(CBasePlayer* pPlayer);

// called before a client command is processed
HOOK_RETURN_DATA (*pfnClientCommand)(CBasePlayer* pPlayer);

// called when a client connects to the server. Return 0 to reject the connection with the given reason.
HOOK_RETURN_DATA (*pfnClientConnect)(edict_t* pEntity, const char* pszName, const char* pszAddress, char szRejectReason[128]);

// called when a player is fully connected to the server and is about to spawn
HOOK_RETURN_DATA (*pfnClientPutInServer)(CBasePlayer* pPlayer);
};

EXPORT cvar_t* RegisterPluginCVar(void* plugin, char* name, char* strDefaultValue, int intDefaultValue, int flags);

EXPORT void RegisterPlugin(void* plugin, HLCOOP_PLUGIN_HOOKS* hooks, const char* name);

// boilerplate for PluginInit functions
// must be inline so that plugins don't reference the game definition of HLCOOP_API_VERSION
inline int InitPluginApi(HLCOOP_PLUGIN_HOOKS* destApi, HLCOOP_PLUGIN_HOOKS* srcApi, int interfaceVersion) {
inline int InitPluginApi(void* plugin, HLCOOP_PLUGIN_HOOKS* srcApi, int interfaceVersion) {
if (interfaceVersion != HLCOOP_API_VERSION) {
ALERT(at_error, "Plugin API version mismatch. Game wanted: %d, Plugin has: %d\n", interfaceVersion, HLCOOP_API_VERSION);
return 0;
}

memcpy(destApi, srcApi, sizeof(HLCOOP_PLUGIN_HOOKS));

#ifdef PLUGIN_NAME
RegisterPlugin(plugin, srcApi, PLUGIN_NAME);
#else
ALERT(at_error, "Plugin was not compiled correctly. PLUGIN_NAME is undefined.\n");
#endif
return 1;
}
Loading

0 comments on commit df1a867

Please sign in to comment.