|
|
|
@@ -30,7 +30,6 @@
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "PlayerManager.h"
|
|
|
|
|
#include "sourcemod.h"
|
|
|
|
|
#include "IAdminSystem.h"
|
|
|
|
|
#include "ConCmdManager.h"
|
|
|
|
|
#include "MenuStyle_Valve.h"
|
|
|
|
@@ -93,12 +92,6 @@ SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &)
|
|
|
|
|
#else
|
|
|
|
|
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
|
|
|
|
|
#endif
|
|
|
|
|
SH_DECL_HOOK2_void(IVEngineServer, ClientPrintf, SH_NOATTRIB, 0, edict_t *, const char *);
|
|
|
|
|
|
|
|
|
|
static void PrintfBuffer_FrameAction(void *data)
|
|
|
|
|
{
|
|
|
|
|
g_Players.OnPrintfFrameAction(reinterpret_cast<unsigned int>(data));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ConCommand *maxplayersCmd = NULL;
|
|
|
|
|
|
|
|
|
@@ -179,7 +172,6 @@ void PlayerManager::OnSourceModAllInitialized()
|
|
|
|
|
#elif SOURCE_ENGINE > SE_EYE // 2013/orangebox, but not original orangebox.
|
|
|
|
|
SH_ADD_HOOK(IServerGameDLL, SetServerHibernation, gamedll, SH_MEMBER(this, &PlayerManager::OnServerHibernationUpdate), true);
|
|
|
|
|
#endif
|
|
|
|
|
SH_ADD_HOOK(IVEngineServer, ClientPrintf, engine, SH_MEMBER(this, &PlayerManager::OnClientPrintf), false);
|
|
|
|
|
|
|
|
|
|
sharesys->AddInterface(NULL, this);
|
|
|
|
|
|
|
|
|
@@ -233,7 +225,6 @@ void PlayerManager::OnSourceModShutdown()
|
|
|
|
|
#elif SOURCE_ENGINE > SE_EYE // 2013/orangebox, but not original orangebox.
|
|
|
|
|
SH_REMOVE_HOOK(IServerGameDLL, SetServerHibernation, gamedll, SH_MEMBER(this, &PlayerManager::OnServerHibernationUpdate), true);
|
|
|
|
|
#endif
|
|
|
|
|
SH_REMOVE_HOOK(IVEngineServer, ClientPrintf, engine, SH_MEMBER(this, &PlayerManager::OnClientPrintf), false);
|
|
|
|
|
|
|
|
|
|
/* Release forwards */
|
|
|
|
|
forwardsys->ReleaseForward(m_clconnect);
|
|
|
|
@@ -855,88 +846,6 @@ void PlayerManager::OnClientDisconnect_Post(edict_t *pEntity)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PlayerManager::OnClientPrintf(edict_t *pEdict, const char *szMsg)
|
|
|
|
|
{
|
|
|
|
|
int client = IndexOfEdict(pEdict);
|
|
|
|
|
|
|
|
|
|
CPlayer &player = m_Players[client];
|
|
|
|
|
if (!player.IsConnected())
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
|
|
|
|
|
|
INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(client));
|
|
|
|
|
if (pNetChan == NULL)
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
|
|
|
|
|
|
size_t nMsgLen = strlen(szMsg);
|
|
|
|
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
|
|
|
|
static const int nNumBitsWritten = 0;
|
|
|
|
|
#else
|
|
|
|
|
int nNumBitsWritten = pNetChan->GetNumBitsWritten(false); // SVC_Print uses unreliable netchan
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// if the msg is bigger than allowed then just let it fail
|
|
|
|
|
if (nMsgLen + 1 >= SVC_Print_BufferSize) // +1 for NETMSG_TYPE_BITS
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
|
|
|
|
|
|
// enqueue msgs if we'd overflow the SVC_Print buffer (+7 as ceil)
|
|
|
|
|
if (!player.m_PrintfBuffer.empty() || (nNumBitsWritten + NETMSG_TYPE_BITS + 7) / 8 + nMsgLen >= SVC_Print_BufferSize)
|
|
|
|
|
{
|
|
|
|
|
// Don't send any more messages for this player until the buffer is empty.
|
|
|
|
|
// Queue up a gameframe hook to empty the buffer (if we haven't already)
|
|
|
|
|
if (player.m_PrintfBuffer.empty())
|
|
|
|
|
g_SourceMod.AddFrameAction(PrintfBuffer_FrameAction, (void *)(uintptr_t)player.GetSerial());
|
|
|
|
|
|
|
|
|
|
player.m_PrintfBuffer.append(szMsg);
|
|
|
|
|
|
|
|
|
|
RETURN_META(MRES_SUPERCEDE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PlayerManager::OnPrintfFrameAction(unsigned int serial)
|
|
|
|
|
{
|
|
|
|
|
int client = GetClientFromSerial(serial);
|
|
|
|
|
CPlayer &player = m_Players[client];
|
|
|
|
|
if (!player.IsConnected())
|
|
|
|
|
{
|
|
|
|
|
player.ClearNetchannelQueue();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(client));
|
|
|
|
|
if (pNetChan == NULL)
|
|
|
|
|
{
|
|
|
|
|
player.ClearNetchannelQueue();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (!player.m_PrintfBuffer.empty())
|
|
|
|
|
{
|
|
|
|
|
#if SOURCE_ENGINE == SE_EPISODEONE
|
|
|
|
|
static const int nNumBitsWritten = 0;
|
|
|
|
|
#else
|
|
|
|
|
int nNumBitsWritten = pNetChan->GetNumBitsWritten(false); // SVC_Print uses unreliable netchan
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
ke::AString &string = player.m_PrintfBuffer.front();
|
|
|
|
|
|
|
|
|
|
// stop if we'd overflow the SVC_Print buffer (+7 as ceil)
|
|
|
|
|
if ((nNumBitsWritten + NETMSG_TYPE_BITS + 7) / 8 + string.length() >= SVC_Print_BufferSize)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
SH_CALL(engine, &IVEngineServer::ClientPrintf)(player.m_pEdict, string.chars());
|
|
|
|
|
|
|
|
|
|
player.m_PrintfBuffer.popFront();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!player.m_PrintfBuffer.empty())
|
|
|
|
|
{
|
|
|
|
|
// continue processing it on the next gameframe as buffer is not empty
|
|
|
|
|
g_SourceMod.AddFrameAction(PrintfBuffer_FrameAction, (void *)(uintptr_t)player.GetSerial());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ClientConsolePrint(edict_t *e, const char *fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
char buffer[512];
|
|
|
|
@@ -2236,13 +2145,6 @@ void CPlayer::Disconnect()
|
|
|
|
|
#if SOURCE_ENGINE == SE_CSGO
|
|
|
|
|
m_LanguageCookie = InvalidQueryCvarCookie;
|
|
|
|
|
#endif
|
|
|
|
|
ClearNetchannelQueue();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CPlayer::ClearNetchannelQueue(void)
|
|
|
|
|
{
|
|
|
|
|
while (!m_PrintfBuffer.empty())
|
|
|
|
|
m_PrintfBuffer.popFront();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CPlayer::SetName(const char *name)
|
|
|
|
|