Skip to content

Commit

Permalink
allow plugin hooks to abort funcs and override return values
Browse files Browse the repository at this point in the history
also add some player hooks and fix some warnings
  • Loading branch information
wootguy committed Oct 27, 2024
1 parent a2ac216 commit 4c62125
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 24 deletions.
7 changes: 7 additions & 0 deletions dlls/CBasePlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "skill.h"
#include "CBreakable.h"
#include "CFuncVehicle.h"
#include "PluginManager.h"

// #define DUCKFIX

Expand Down Expand Up @@ -1686,6 +1687,8 @@ void CBasePlayer::LeaveObserver()
//
void CBasePlayer::PlayerUse ( void )
{
CALL_HOOKS_VOID(&HLCOOP_PLUGIN_HOOKS::pfnPlayerUse, this);

if ( IsObserver() )
return;

Expand Down Expand Up @@ -2222,6 +2225,8 @@ void CBasePlayer::UpdateStatusBar()

void CBasePlayer::PreThink(void)
{
CALL_HOOKS_VOID(&HLCOOP_PLUGIN_HOOKS::pfnPlayerPreThink, this);

int buttonsChanged = (m_afButtonLast ^ pev->button); // These buttons have changed this frame

// Debounced button codes for pressed/released
Expand Down Expand Up @@ -2992,6 +2997,8 @@ void CBasePlayer :: UpdatePlayerSound ( void )

void CBasePlayer::PostThink()
{
CALL_HOOKS_VOID(&HLCOOP_PLUGIN_HOOKS::pfnPlayerPostThink, this);

if ( g_fGameOver )
goto pt_end; // intermission or finale

Expand Down
2 changes: 1 addition & 1 deletion dlls/CWorld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ void CWorld::Precache(void)
CVAR_SET_FLOAT("mp_defaultteam", 0);
}

g_pluginManager.CallHooks(&HLCOOP_PLUGIN_HOOKS::pfnMapInit);
CALL_HOOKS_VOID(&HLCOOP_PLUGIN_HOOKS::pfnMapInit);
}


Expand Down
27 changes: 22 additions & 5 deletions dlls/PluginHooks.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
#include "mod_api.h"

enum HOOK_RETURN_CODE {
HOOK_CONTINUE,
HOOK_HANDLED
struct HOOK_RETURN_DATA {
uint32_t code; // what to do after processing this hook
void* data; // overridden return value for the mod
};

#define HOOKBIT_HANDLED 1 // If set, forbid later plugins from processing the hook
#define HOOKBIT_OVERRIDE 2 // If set, do not call the game function and return the given value

#define HOOK_CONTINUE {0, 0}
#define HOOK_CONTINUE_OVERRIDE(data) {HOOKBIT_OVERRIDE, (void*)data}
#define HOOK_HANDLED {HOOKBIT_HANDLED, 0}
#define HOOK_HANDLED_OVERRIDE(data) {(HOOKBIT_HANDLED | HOOKBIT_OVERRIDE), (void*)data}

struct HLCOOP_PLUGIN_HOOKS {
// called when the server starts, before any entities are spawns
HOOK_RETURN_CODE (*pfnMapInit)();
HOOK_RETURN_DATA (*pfnMapInit)();

// called after map entities are spawned
HOOK_RETURN_CODE (*pfnMapActivate)();
HOOK_RETURN_DATA (*pfnMapActivate)();

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

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

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

// boilerplate for PluginInit functions
Expand Down
25 changes: 12 additions & 13 deletions dlls/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ void PluginManager::UnloadPlugin(const Plugin& plugin) {
apiFunc();
}
else {
ALERT(at_console, "PluginExit not found in plugin '%s'\n", plugin.fpath);
ALERT(at_console, "PluginExit not found in plugin '%s'\n", plugin.fpath.c_str());
}

FreeLibrary((HMODULE)plugin.h_module);
Expand All @@ -98,9 +98,8 @@ void PluginManager::UnloadPlugin(const Plugin& plugin) {
void PluginManager::RemovePlugin(const Plugin& plugin) {
UnloadPlugin(plugin);

for (int i = 0; i < plugins.size(); i++) {
const Plugin& plugin = plugins[i];
if (&plugin == &plugin) {
for (int i = 0; i < (int)plugins.size(); i++) {
if (&plugins[i] == &plugin) {
plugins.erase(plugins.begin() + i);
return;
}
Expand Down Expand Up @@ -183,8 +182,8 @@ void PluginManager::UpdateServerPlugins(bool forceUpdate) {
}

bool found = false;
for (std::string& path : pluginPaths) {
if (std::string(plugin.fpath) == path) {
for (std::string& p : pluginPaths) {
if (std::string(plugin.fpath) == p) {
found = true;
break;
}
Expand All @@ -203,16 +202,16 @@ void PluginManager::UpdateServerPlugins(bool forceUpdate) {
int numFailed = 0;

// add new plugins
for (std::string& path : pluginPaths) {
for (std::string& p : pluginPaths) {
bool found = false;
for (const Plugin& plugin : plugins) {
if (std::string(plugin.fpath) == path) {
if (std::string(plugin.fpath) == p) {
continue;
}
}

if (!found) {
if (AddPlugin(path.c_str(), false)) {
if (AddPlugin(p.c_str(), false)) {
numLoaded++;
}
else {
Expand All @@ -222,11 +221,11 @@ void PluginManager::UpdateServerPlugins(bool forceUpdate) {
}

// assign ids and sort
for (int i = 0; i < pluginPaths.size(); i++) {
std::string& path = pluginPaths[i];
for (int i = 0; i < (int)pluginPaths.size(); i++) {
std::string& p = pluginPaths[i];

for (Plugin& plugin : plugins) {
if (std::string(plugin.fpath) == path) {
if (std::string(plugin.fpath) == p) {
plugin.sortId = i+1;
}
}
Expand Down Expand Up @@ -268,7 +267,7 @@ void PluginManager::ListPlugins(edict_t* plr) {
lines.push_back(UTIL_VarArgs("\n %-20s %-8s %-44s\n", "Name", "Type", isAdmin ? "File path" : ""));
lines.push_back("--------------------------------------------------------------------------------\n");

for (int i = 0; i < plugins.size(); i++) {
for (int i = 0; i < (int)plugins.size(); i++) {
const Plugin& plugin = plugins[i];

std::string name = plugin.fpath;
Expand Down
28 changes: 25 additions & 3 deletions dlls/PluginManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ struct Plugin {

typedef void(*ENTITYINIT)(struct entvars_s*);

#define CALL_HOOKS_VOID(...) \
if (g_pluginManager.CallHooks(__VA_ARGS__).code & HOOKBIT_OVERRIDE) { return; }

#define CALL_HOOKS(type, ...) { \
HOOK_RETURN_DATA ret = g_pluginManager.CallHooks(__VA_ARGS__); \
if (ret.code & HOOKBIT_OVERRIDE) { \
return (type)ret.data; \
} \
}

class PluginManager {
public:
std::vector<Plugin> plugins;
Expand All @@ -38,18 +48,30 @@ class PluginManager {
void ListPlugins(edict_t* plr);

template<typename Func, typename... Args>
void CallHooks(Func hookFunction, Args&&... args) {
HOOK_RETURN_DATA CallHooks(Func hookFunction, Args&&... args) {
HOOK_RETURN_DATA totalRet = {0, 0};

for (const Plugin& plugin : plugins) {
if (!(plugin.hooks.*hookFunction)) {
continue;
}

HOOK_RETURN_CODE ret = (*(plugin.hooks.*hookFunction))(std::forward<Args>(args)...);
HOOK_RETURN_DATA ret = (*(plugin.hooks.*hookFunction))(std::forward<Args>(args)...);

if (ret.code & HOOKBIT_OVERRIDE) {
if (totalRet.code & HOOKBIT_OVERRIDE) {
ALERT(at_console, "Multiple plugins want to override a function return value\n");
}
totalRet.code |= HOOKBIT_OVERRIDE;
totalRet.data = ret.data;
}

if (ret == HOOK_HANDLED) {
if (ret.code & HOOKBIT_HANDLED) {
break;
}
}

return totalRet;
}

ENTITYINIT GetCustomEntityInitFunc(const char* pname);
Expand Down
2 changes: 1 addition & 1 deletion dlls/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
}
}

g_pluginManager.CallHooks(&HLCOOP_PLUGIN_HOOKS::pfnMapActivate);
CALL_HOOKS_VOID(&HLCOOP_PLUGIN_HOOKS::pfnMapActivate);
}

/*
Expand Down
2 changes: 1 addition & 1 deletion dlls/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3347,7 +3347,7 @@ void PRECACHE_MODEL_EXTRAS(const char* path, studiohdr_t* mdl) {
mstudioevent_t* evt = (mstudioevent_t*)((byte*)mdl + seq->eventindex) + k;

std::string opt(evt->options, 64);
int lastDot = opt.find(".");
lastDot = opt.find(".");

if (lastDot == -1 || lastDot == (int)opt.size()-1)
continue; // no file extension
Expand Down

0 comments on commit 4c62125

Please sign in to comment.