Compare commits

...

20 Commits

Author SHA1 Message Date
Kyle Sanderson
f3a5c8341d am-deque.h 2019-09-10 11:23:08 +02:00
Kyle Sanderson
ee0fc2230f Update PlayerManager.h 2019-09-10 11:23:08 +02:00
Kyle Sanderson
b024ad05bf Update PlayerManager.cpp 2019-09-10 11:23:08 +02:00
Kyle Sanderson
ab218278f7 Update PlayerManager.h 2019-09-10 11:23:08 +02:00
Kyle Sanderson
026678d182 flip to queue - fix serial on resched. 2019-09-10 11:23:08 +02:00
Kyle Sanderson
291b83ed74 ep1 static const 2019-09-10 11:23:08 +02:00
Kyle Sanderson
5d70bb0122 remove local const references 2019-09-10 11:23:08 +02:00
Kyle Sanderson
eb61b40eaf lift consts to header. 2019-09-10 11:23:08 +02:00
Kyle Sanderson
bb87127d92 Update PlayerManager.cpp 2019-09-10 11:23:08 +02:00
Kyle Sanderson
105d41c88d style 2019-09-10 11:23:08 +02:00
Kyle Sanderson
9a3cad3b9d serials 2019-09-10 11:23:08 +02:00
Kyle Sanderson
c4c4cf0085 flip to serials. 2019-09-10 11:23:08 +02:00
Kyle Sanderson
6b3e661b2b ensure empty queue when netchan drops 2019-09-10 11:23:08 +02:00
Kyle Sanderson
eda65bb5bb remove m_PrintfStop 2019-09-10 11:23:08 +02:00
Kyle Sanderson
4cad93b505 remove m_PrintfStop 2019-09-10 11:23:08 +02:00
Kyle Sanderson
98f6ef8173 fix 2019-09-10 11:23:08 +02:00
Kyle Sanderson
9492337474 try reference for CPlayer. 2019-09-10 11:23:08 +02:00
BotoX
a51aa290d6 UNTESTED! Cleanup on disconnect, passthrough for >= 2048 msgs 2019-09-10 11:23:08 +02:00
BotoX
f1ca3e8c7f UNTESTED! Switch to ke::LinkedList<ke::AString> for PrintfBuffer.
Switch from OnGameFrame to FramAction.
Fix compiling on Episode1 by essentially disabling the feature.
2019-09-10 11:23:08 +02:00
BotoX
68e5c00f48 Avoid losing console messages.
Buffers up to 16k bytes of SVC_Print if buffer would overflow, then sends chunks every frame.
Sends up to 2048 bytes per frame and does not split messages.
2019-09-10 11:23:08 +02:00
2 changed files with 106 additions and 0 deletions

View File

@ -30,6 +30,7 @@
*/
#include "PlayerManager.h"
#include "sourcemod.h"
#include "IAdminSystem.h"
#include "ConCmdManager.h"
#include "MenuStyle_Valve.h"
@ -92,6 +93,12 @@ 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;
@ -172,6 +179,7 @@ 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);
@ -225,6 +233,7 @@ 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);
@ -846,6 +855,88 @@ 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];
@ -2145,6 +2236,13 @@ 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)

View File

@ -43,6 +43,7 @@
#include <sh_list.h>
#include <sh_vector.h>
#include <am-string.h>
#include <am-deque.h>
#include "ConVarManager.h"
#include <steam/steamclientpublic.h>
@ -123,6 +124,7 @@ private:
bool IsAuthStringValidated();
bool SetEngineString();
bool SetCSteamID();
void ClearNetchannelQueue(void);
private:
bool m_IsConnected = false;
bool m_IsInGame = false;
@ -152,6 +154,7 @@ private:
#if SOURCE_ENGINE == SE_CSGO
QueryCvarCookie_t m_LanguageCookie = InvalidQueryCvarCookie;
#endif
ke::Deque<ke::AString> m_PrintfBuffer;
};
class PlayerManager :
@ -190,6 +193,8 @@ public:
void OnClientSettingsChanged(edict_t *pEntity);
//void OnClientSettingsChanged_Pre(edict_t *pEntity);
void OnServerHibernationUpdate(bool bHibernating);
void OnClientPrintf(edict_t *pEdict, const char *szMsg);
void OnPrintfFrameAction(unsigned int serial);
public: //IPlayerManager
void AddClientListener(IClientListener *listener);
void RemoveClientListener(IClientListener *listener);
@ -267,6 +272,9 @@ private:
int m_SourceTVUserId;
int m_ReplayUserId;
bool m_bInCCKVHook;
private:
static const int NETMSG_TYPE_BITS = 5; // SVC_Print overhead for netmsg type
static const int SVC_Print_BufferSize = 2048 - 1; // -1 for terminating \0
};
#if SOURCE_ENGINE >= SE_ORANGEBOX