Add OnPlayerRunCmdPost forward (#591)

* Add OnPlayerRunCmdPost forward

Allow plugins to catch the values that are actually used by the game
after some eventual changes by other plugins.

* Add |const| qualifier to arrays in OnPlayerRunCmdPost forward
This commit is contained in:
peace-maker 2017-05-09 08:16:05 -06:00 committed by Asher Baker
parent ed42d2feea
commit 1351df4260
3 changed files with 126 additions and 17 deletions

View File

@ -44,6 +44,7 @@
CHookManager g_Hooks; CHookManager g_Hooks;
static bool PRCH_enabled = false; static bool PRCH_enabled = false;
static bool PRCH_used = false; static bool PRCH_used = false;
static bool PRCHPost_used = false;
static bool FILE_used = false; static bool FILE_used = false;
SH_DECL_MANUALHOOK2_void(PlayerRunCmdHook, 0, 0, 0, CUserCmd *, IMoveHelper *); SH_DECL_MANUALHOOK2_void(PlayerRunCmdHook, 0, 0, 0, CUserCmd *, IMoveHelper *);
@ -60,6 +61,7 @@ SourceHook::CallClass<IBaseFileSystem> *basefilesystemPatch = NULL;
CHookManager::CHookManager() CHookManager::CHookManager()
{ {
m_usercmdsFwd = NULL; m_usercmdsFwd = NULL;
m_usercmdsPostFwd = NULL;
m_netFileSendFwd = NULL; m_netFileSendFwd = NULL;
m_netFileReceiveFwd = NULL; m_netFileReceiveFwd = NULL;
m_pActiveNetChannel = NULL; m_pActiveNetChannel = NULL;
@ -99,11 +101,25 @@ void CHookManager::Initialize()
Param_CellByRef, // tickcount Param_CellByRef, // tickcount
Param_CellByRef, // seed Param_CellByRef, // seed
Param_Array); // mouse[2] Param_Array); // mouse[2]
m_usercmdsPostFwd = forwards->CreateForward("OnPlayerRunCmdPost", ET_Ignore, 11, NULL,
Param_Cell, // client
Param_Cell, // buttons
Param_Cell, // impulse
Param_Array, // Float:vel[3]
Param_Array, // Float:angles[3]
Param_Cell, // weapon
Param_Cell, // subtype
Param_Cell, // cmdnum
Param_Cell, // tickcount
Param_Cell, // seed
Param_Array); // mouse[2]
} }
void CHookManager::Shutdown() void CHookManager::Shutdown()
{ {
forwards->ReleaseForward(m_usercmdsFwd); forwards->ReleaseForward(m_usercmdsFwd);
forwards->ReleaseForward(m_usercmdsPostFwd);
forwards->ReleaseForward(m_netFileSendFwd); forwards->ReleaseForward(m_netFileSendFwd);
forwards->ReleaseForward(m_netFileReceiveFwd); forwards->ReleaseForward(m_netFileReceiveFwd);
@ -127,14 +143,14 @@ void CHookManager::OnClientConnect(int client)
void CHookManager::OnClientPutInServer(int client) void CHookManager::OnClientPutInServer(int client)
{ {
PlayerRunCmdHook(client); if (PRCH_used)
PlayerRunCmdHook(client, false);
if (PRCHPost_used)
PlayerRunCmdHook(client, true);
} }
void CHookManager::PlayerRunCmdHook(int client) void CHookManager::PlayerRunCmdHook(int client, bool post)
{ {
if (!PRCH_used)
return;
edict_t *pEdict = PEntityOfEntIndex(client); edict_t *pEdict = PEntityOfEntIndex(client);
if (!pEdict) if (!pEdict)
{ {
@ -153,18 +169,24 @@ void CHookManager::PlayerRunCmdHook(int client)
return; return;
} }
ke::Vector<CVTableHook *> &runUserCmdHookVec = post ? m_runUserCmdPostHooks : m_runUserCmdHooks;
CVTableHook hook(pEntity); CVTableHook hook(pEntity);
for (size_t i = 0; i < m_runUserCmdHooks.length(); ++i) for (size_t i = 0; i < runUserCmdHookVec.length(); ++i)
{ {
if (hook == m_runUserCmdHooks[i]) if (hook == runUserCmdHookVec[i])
{ {
return; return;
} }
} }
int hookid = SH_ADD_MANUALVPHOOK(PlayerRunCmdHook, pEntity, SH_MEMBER(this, &CHookManager::PlayerRunCmd), false); int hookid;
if (post)
hookid = SH_ADD_MANUALVPHOOK(PlayerRunCmdHook, pEntity, SH_MEMBER(this, &CHookManager::PlayerRunCmdPost), true);
else
hookid = SH_ADD_MANUALVPHOOK(PlayerRunCmdHook, pEntity, SH_MEMBER(this, &CHookManager::PlayerRunCmd), false);
hook.SetHookID(hookid); hook.SetHookID(hookid);
m_runUserCmdHooks.append(new CVTableHook(hook)); runUserCmdHookVec.append(new CVTableHook(hook));
} }
void CHookManager::PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper) void CHookManager::PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper)
@ -230,6 +252,48 @@ void CHookManager::PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper)
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
void CHookManager::PlayerRunCmdPost(CUserCmd *ucmd, IMoveHelper *moveHelper)
{
if (m_usercmdsPostFwd->GetFunctionCount() == 0)
{
RETURN_META(MRES_IGNORED);
}
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
if (!pEntity)
{
RETURN_META(MRES_IGNORED);
}
edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
if (!pEdict)
{
RETURN_META(MRES_IGNORED);
}
int client = IndexOfEdict(pEdict);
cell_t vel[3] = { sp_ftoc(ucmd->forwardmove), sp_ftoc(ucmd->sidemove), sp_ftoc(ucmd->upmove) };
cell_t angles[3] = { sp_ftoc(ucmd->viewangles.x), sp_ftoc(ucmd->viewangles.y), sp_ftoc(ucmd->viewangles.z) };
cell_t mouse[2] = { ucmd->mousedx, ucmd->mousedy };
m_usercmdsPostFwd->PushCell(client);
m_usercmdsPostFwd->PushCell(ucmd->buttons);
m_usercmdsPostFwd->PushCell(ucmd->impulse);
m_usercmdsPostFwd->PushArray(vel, 3);
m_usercmdsPostFwd->PushArray(angles, 3);
m_usercmdsPostFwd->PushCell(ucmd->weaponselect);
m_usercmdsPostFwd->PushCell(ucmd->weaponsubtype);
m_usercmdsPostFwd->PushCell(ucmd->command_number);
m_usercmdsPostFwd->PushCell(ucmd->tick_count);
m_usercmdsPostFwd->PushCell(ucmd->random_seed);
m_usercmdsPostFwd->PushArray(mouse, 2);
m_usercmdsPostFwd->Execute();
RETURN_META(MRES_IGNORED);
}
void CHookManager::NetChannelHook(int client) void CHookManager::NetChannelHook(int client)
{ {
if (!FILE_used) if (!FILE_used)
@ -387,10 +451,23 @@ bool CHookManager::SendFile(const char *filename, unsigned int transferID)
void CHookManager::OnPluginLoaded(IPlugin *plugin) void CHookManager::OnPluginLoaded(IPlugin *plugin)
{ {
if (PRCH_enabled && !PRCH_used && m_usercmdsFwd->GetFunctionCount()) if (PRCH_enabled)
{
bool changed = false;
if (!PRCH_used && (m_usercmdsFwd->GetFunctionCount() > 0))
{ {
PRCH_used = true; PRCH_used = true;
changed = true;
}
if (!PRCHPost_used && (m_usercmdsPostFwd->GetFunctionCount() > 0))
{
PRCHPost_used = true;
changed = true;
}
// Only check the hooks on the players if a new hook is used by this plugin.
if (changed)
{
int MaxClients = playerhelpers->GetMaxClients(); int MaxClients = playerhelpers->GetMaxClients();
for (int i = 1; i <= MaxClients; i++) for (int i = 1; i <= MaxClients; i++)
{ {
@ -400,6 +477,7 @@ void CHookManager::OnPluginLoaded(IPlugin *plugin)
} }
} }
} }
}
if (!FILE_used && (m_netFileSendFwd->GetFunctionCount() || m_netFileReceiveFwd->GetFunctionCount())) if (!FILE_used && (m_netFileSendFwd->GetFunctionCount() || m_netFileReceiveFwd->GetFunctionCount()))
{ {
@ -429,6 +507,17 @@ void CHookManager::OnPluginUnloaded(IPlugin *plugin)
PRCH_used = false; PRCH_used = false;
} }
if (PRCHPost_used && !m_usercmdsPostFwd->GetFunctionCount())
{
for (size_t i = 0; i < m_runUserCmdPostHooks.length(); ++i)
{
delete m_runUserCmdPostHooks[i];
}
m_runUserCmdPostHooks.clear();
PRCHPost_used = false;
}
if (FILE_used && !m_netFileSendFwd->GetFunctionCount() && !m_netFileReceiveFwd->GetFunctionCount()) if (FILE_used && !m_netFileSendFwd->GetFunctionCount() && !m_netFileReceiveFwd->GetFunctionCount())
{ {
for (size_t i = 0; i < m_netChannelHooks.length(); ++i) for (size_t i = 0; i < m_netChannelHooks.length(); ++i)

View File

@ -49,6 +49,7 @@ public:
void OnClientConnect(int client); void OnClientConnect(int client);
void OnClientPutInServer(int client); void OnClientPutInServer(int client);
void PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper); void PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper);
void PlayerRunCmdPost(CUserCmd *ucmd, IMoveHelper *moveHelper);
void OnMapStart(); void OnMapStart();
public: /* NetChannel/Related Hooks */ public: /* NetChannel/Related Hooks */
bool FileExists(const char *filename, const char *pathID); bool FileExists(const char *filename, const char *pathID);
@ -66,14 +67,16 @@ public: //IFeatureProvider
virtual FeatureStatus GetFeatureStatus(FeatureType type, const char *name); virtual FeatureStatus GetFeatureStatus(FeatureType type, const char *name);
private: private:
void PlayerRunCmdHook(int client); void PlayerRunCmdHook(int client, bool post);
void NetChannelHook(int client); void NetChannelHook(int client);
private: private:
IForward *m_usercmdsFwd; IForward *m_usercmdsFwd;
IForward *m_usercmdsPostFwd;
IForward *m_netFileSendFwd; IForward *m_netFileSendFwd;
IForward *m_netFileReceiveFwd; IForward *m_netFileReceiveFwd;
ke::Vector<CVTableHook *> m_runUserCmdHooks; ke::Vector<CVTableHook *> m_runUserCmdHooks;
ke::Vector<CVTableHook *> m_runUserCmdPostHooks;
ke::Vector<CVTableHook *> m_netChannelHooks; ke::Vector<CVTableHook *> m_netChannelHooks;
INetChannel *m_pActiveNetChannel; INetChannel *m_pActiveNetChannel;
bool m_bFSTranHookWarned = false; bool m_bFSTranHookWarned = false;

View File

@ -58,6 +58,23 @@
*/ */
forward Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2]); forward Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2]);
/**
* @brief Called after a clients movement buttons were processed.
*
* @param client Index of the client.
* @param buttons The current commands (as bitflags - see entity_prop_stocks.inc).
* @param impulse The current impulse command.
* @param vel Players desired velocity.
* @param angles Players desired view angles.
* @param weapon Entity index of the new weapon if player switches weapon, 0 otherwise.
* @param subtype Weapon subtype when selected from a menu.
* @param cmdnum Command number. Increments from the first command sent.
* @param tickcount Tick count. A client's prediction based on the server's GetGameTickCount value.
* @param seed Random seed. Used to determine weapon recoil, spread, and other predicted elements.
* @param mouse Mouse direction (x, y).
*/
forward void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2]);
/** /**
* @brief Called when a client requests a file from the server. * @brief Called when a client requests a file from the server.
* *