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 "sourcemod.h"
|
||||||
#include "sourcemm_api.h"
|
#include "sourcemm_api.h"
|
||||||
#include "UserMessages.h"
|
#include "UserMessages.h"
|
||||||
|
#include "PlayerManager.h"
|
||||||
|
|
||||||
CHalfLife2 g_HL2;
|
CHalfLife2 g_HL2;
|
||||||
bool g_IsOriginalEngine = false;
|
bool g_IsOriginalEngine = false;
|
||||||
@ -333,3 +334,38 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
|
|||||||
|
|
||||||
return true;
|
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_
|
#define _INCLUDE_SOURCEMOD_CHALFLIFE2_H_
|
||||||
|
|
||||||
#include <sh_list.h>
|
#include <sh_list.h>
|
||||||
|
#include <sh_string.h>
|
||||||
#include <sh_tinyhash.h>
|
#include <sh_tinyhash.h>
|
||||||
#include "sm_trie.h"
|
#include "sm_trie.h"
|
||||||
#include "sm_globals.h"
|
#include "sm_globals.h"
|
||||||
|
#include "sm_queue.h"
|
||||||
#include <IGameHelpers.h>
|
#include <IGameHelpers.h>
|
||||||
#include <KeyValues.h>
|
#include <KeyValues.h>
|
||||||
|
|
||||||
@ -57,6 +59,13 @@ struct DataMapTrie
|
|||||||
Trie *trie;
|
Trie *trie;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DelayedFakeCliCmd
|
||||||
|
{
|
||||||
|
String cmd;
|
||||||
|
int client;
|
||||||
|
int userid;
|
||||||
|
};
|
||||||
|
|
||||||
class CHalfLife2 :
|
class CHalfLife2 :
|
||||||
public SMGlobalClass,
|
public SMGlobalClass,
|
||||||
public IGameHelpers
|
public IGameHelpers
|
||||||
@ -77,6 +86,9 @@ public: //IGameHelpers
|
|||||||
bool TextMsg(int client, int dest, const char *msg);
|
bool TextMsg(int client, int dest, const char *msg);
|
||||||
bool HintTextMsg(int client, const char *msg);
|
bool HintTextMsg(int client, const char *msg);
|
||||||
bool ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show);
|
bool ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show);
|
||||||
|
public:
|
||||||
|
void AddToFakeCliCmdQueue(int client, int userid, const char *cmd);
|
||||||
|
void ProcessFakeCliCmdQueue();
|
||||||
private:
|
private:
|
||||||
DataTableInfo *_FindServerClass(const char *classname);
|
DataTableInfo *_FindServerClass(const char *classname);
|
||||||
private:
|
private:
|
||||||
@ -86,6 +98,8 @@ private:
|
|||||||
int m_MsgTextMsg;
|
int m_MsgTextMsg;
|
||||||
int m_HinTextMsg;
|
int m_HinTextMsg;
|
||||||
int m_VGUIMenu;
|
int m_VGUIMenu;
|
||||||
|
Queue<DelayedFakeCliCmd *> m_CmdQueue;
|
||||||
|
CStack<DelayedFakeCliCmd *> m_FreeCmds;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CHalfLife2 g_HL2;
|
extern CHalfLife2 g_HL2;
|
||||||
|
@ -838,7 +838,7 @@ static cell_t FakeClientCommandEx(IPluginContext *pContext, const cell_t *params
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), buffer);
|
g_HL2.AddToFakeCliCmdQueue(params[1], engine->GetPlayerUserId(pPlayer->GetEdict()), buffer);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1020,5 +1020,6 @@ REGISTER_NATIVES(consoleNatives)
|
|||||||
{"GetCommandIterator", GetCommandIterator},
|
{"GetCommandIterator", GetCommandIterator},
|
||||||
{"ReadCommandIterator", ReadCommandIterator},
|
{"ReadCommandIterator", ReadCommandIterator},
|
||||||
{"CheckCommandAccess", CheckCommandAccess},
|
{"CheckCommandAccess", CheckCommandAccess},
|
||||||
|
{"FakeClientCommandEx", FakeClientCommandEx},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#include "MenuStyle_Valve.h"
|
#include "MenuStyle_Valve.h"
|
||||||
#include "MenuStyle_Radio.h"
|
#include "MenuStyle_Radio.h"
|
||||||
#include "Database.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_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);
|
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false);
|
||||||
@ -396,6 +397,7 @@ void SimulateTick()
|
|||||||
void SourceModBase::GameFrame(bool simulating)
|
void SourceModBase::GameFrame(bool simulating)
|
||||||
{
|
{
|
||||||
g_DBMan.RunFrame();
|
g_DBMan.RunFrame();
|
||||||
|
g_HL2.ProcessFakeCliCmdQueue();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: This is all hardcoded rather than delegated to save
|
* 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.
|
* 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 client Index of the client.
|
||||||
* @param fmt Format of the client command.
|
* @param fmt Format of the client command.
|
||||||
* @param ... Format parameters
|
* @param ... Format parameters
|
||||||
@ -158,6 +164,19 @@ native ClientCommand(client, const String:fmt[], any:...);
|
|||||||
*/
|
*/
|
||||||
native FakeClientCommand(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.
|
* Sends a message to the server console.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user