added FakeClientCommandEx() to solve a nasty re-entrancy issue
--HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401344
This commit is contained in:
parent
ab2a4d5457
commit
290f90a3a3
@ -33,6 +33,7 @@
|
||||
#include "sourcemod.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include "UserMessages.h"
|
||||
#include "PlayerManager.h"
|
||||
|
||||
CHalfLife2 g_HL2;
|
||||
bool g_IsOriginalEngine = false;
|
||||
@ -333,3 +334,38 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CHalfLife2::AddToFakeCliCmdQueue(int client, int userid, const char *cmd)
|
||||
{
|
||||
DelayedFakeCliCmd *pFake;
|
||||
|
||||
if (m_FreeCmds.empty())
|
||||
{
|
||||
pFake = new DelayedFakeCliCmd;
|
||||
} else {
|
||||
pFake = m_FreeCmds.front();
|
||||
m_FreeCmds.pop();
|
||||
}
|
||||
|
||||
pFake->client = client;
|
||||
pFake->userid = userid;
|
||||
pFake->cmd.assign(cmd);
|
||||
|
||||
m_CmdQueue.push(pFake);
|
||||
}
|
||||
|
||||
void CHalfLife2::ProcessFakeCliCmdQueue()
|
||||
{
|
||||
while (!m_CmdQueue.empty())
|
||||
{
|
||||
DelayedFakeCliCmd *pFake = m_CmdQueue.first();
|
||||
|
||||
if (g_Players.GetClientOfUserId(pFake->userid) == pFake->client)
|
||||
{
|
||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(pFake->client);
|
||||
serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), pFake->cmd.c_str());
|
||||
}
|
||||
|
||||
m_CmdQueue.pop();
|
||||
}
|
||||
}
|
||||
|
@ -33,9 +33,11 @@
|
||||
#define _INCLUDE_SOURCEMOD_CHALFLIFE2_H_
|
||||
|
||||
#include <sh_list.h>
|
||||
#include <sh_string.h>
|
||||
#include <sh_tinyhash.h>
|
||||
#include "sm_trie.h"
|
||||
#include "sm_globals.h"
|
||||
#include "sm_queue.h"
|
||||
#include <IGameHelpers.h>
|
||||
#include <KeyValues.h>
|
||||
|
||||
@ -57,6 +59,13 @@ struct DataMapTrie
|
||||
Trie *trie;
|
||||
};
|
||||
|
||||
struct DelayedFakeCliCmd
|
||||
{
|
||||
String cmd;
|
||||
int client;
|
||||
int userid;
|
||||
};
|
||||
|
||||
class CHalfLife2 :
|
||||
public SMGlobalClass,
|
||||
public IGameHelpers
|
||||
@ -77,6 +86,9 @@ public: //IGameHelpers
|
||||
bool TextMsg(int client, int dest, const char *msg);
|
||||
bool HintTextMsg(int client, const char *msg);
|
||||
bool ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show);
|
||||
public:
|
||||
void AddToFakeCliCmdQueue(int client, int userid, const char *cmd);
|
||||
void ProcessFakeCliCmdQueue();
|
||||
private:
|
||||
DataTableInfo *_FindServerClass(const char *classname);
|
||||
private:
|
||||
@ -86,6 +98,8 @@ private:
|
||||
int m_MsgTextMsg;
|
||||
int m_HinTextMsg;
|
||||
int m_VGUIMenu;
|
||||
Queue<DelayedFakeCliCmd *> m_CmdQueue;
|
||||
CStack<DelayedFakeCliCmd *> m_FreeCmds;
|
||||
};
|
||||
|
||||
extern CHalfLife2 g_HL2;
|
||||
|
@ -838,7 +838,7 @@ static cell_t FakeClientCommandEx(IPluginContext *pContext, const cell_t *params
|
||||
return 0;
|
||||
}
|
||||
|
||||
serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), buffer);
|
||||
g_HL2.AddToFakeCliCmdQueue(params[1], engine->GetPlayerUserId(pPlayer->GetEdict()), buffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1020,5 +1020,6 @@ REGISTER_NATIVES(consoleNatives)
|
||||
{"GetCommandIterator", GetCommandIterator},
|
||||
{"ReadCommandIterator", ReadCommandIterator},
|
||||
{"CheckCommandAccess", CheckCommandAccess},
|
||||
{"FakeClientCommandEx", FakeClientCommandEx},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "MenuStyle_Valve.h"
|
||||
#include "MenuStyle_Radio.h"
|
||||
#include "Database.h"
|
||||
#include "HalfLife2.h"
|
||||
|
||||
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
|
||||
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false);
|
||||
@ -396,6 +397,7 @@ void SimulateTick()
|
||||
void SourceModBase::GameFrame(bool simulating)
|
||||
{
|
||||
g_DBMan.RunFrame();
|
||||
g_HL2.ProcessFakeCliCmdQueue();
|
||||
|
||||
/**
|
||||
* Note: This is all hardcoded rather than delegated to save
|
||||
|
@ -150,6 +150,12 @@ native ClientCommand(client, const String:fmt[], any:...);
|
||||
/**
|
||||
* Executes a client command on the server without being networked.
|
||||
*
|
||||
* FakeClientCommand() overwrites the command tokenization buffer. This can
|
||||
* cause undesired effects because future calls to GetCmdArg* will return
|
||||
* data from the FakeClientCommand(), not the parent command. If you are in
|
||||
* a hook where this matters (for example, a "say" hook), you should use
|
||||
* FakeClientCommandEx() instead.
|
||||
*
|
||||
* @param client Index of the client.
|
||||
* @param fmt Format of the client command.
|
||||
* @param ... Format parameters
|
||||
@ -158,6 +164,19 @@ native ClientCommand(client, const String:fmt[], any:...);
|
||||
*/
|
||||
native FakeClientCommand(client, const String:fmt[], any:...);
|
||||
|
||||
/**
|
||||
* Executes a client command on the server without being networked. The
|
||||
* execution of the client command is delayed by one frame to prevent any
|
||||
* re-entrancy issues that might surface with FakeClientCommand().
|
||||
*
|
||||
* @param client Index of the client.
|
||||
* @param fmt Format of the client command.
|
||||
* @param ... Format parameters
|
||||
* @noreturn
|
||||
* @error Invalid client index, or client not connected.
|
||||
*/
|
||||
native FakeClientCommandEx(client, const String:fmt[], any:...);
|
||||
|
||||
/**
|
||||
* Sends a message to the server console.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user