Core now detects and handles a changed maxplayers value (bug 2537 and bug 2758)
This commit is contained in:
parent
4517031861
commit
f4dba84ae5
@ -68,6 +68,15 @@ SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *)
|
||||
SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *);
|
||||
SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int);
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
|
||||
#else
|
||||
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
|
||||
#endif
|
||||
|
||||
ConCommand *maxplayersCmd = NULL;
|
||||
|
||||
class KickPlayerTimer : public ITimedEvent
|
||||
{
|
||||
public:
|
||||
@ -137,6 +146,32 @@ void PlayerManager::OnSourceModAllInitialized()
|
||||
|
||||
m_bIsListenServer = !engine->IsDedicatedServer();
|
||||
m_ListenClient = 0;
|
||||
|
||||
g_ConVarManager.AddConVarChangeListener("tv_enable", this);
|
||||
|
||||
ConCommandBase *pBase = icvar->GetCommands();
|
||||
ConCommand *pCmd = NULL;
|
||||
while (pBase)
|
||||
{
|
||||
if (strcmp(pBase->GetName(), "maxplayers") == 0)
|
||||
{
|
||||
/* Don't want to return convar with same name */
|
||||
if (!pBase->IsCommand())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pCmd = (ConCommand *)pBase;
|
||||
break;
|
||||
}
|
||||
pBase = const_cast<ConCommandBase *>(pBase->GetNext());
|
||||
}
|
||||
|
||||
if (pCmd != NULL)
|
||||
{
|
||||
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pCmd, CmdMaxplayersCallback, true);
|
||||
maxplayersCmd = pCmd;
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerManager::OnSourceModShutdown()
|
||||
@ -165,6 +200,13 @@ void PlayerManager::OnSourceModShutdown()
|
||||
g_Forwards.ReleaseForward(PostAdminFilter);
|
||||
|
||||
delete [] m_Players;
|
||||
|
||||
g_ConVarManager.RemoveConVarChangeListener("tv_enable", this);
|
||||
|
||||
if (maxplayersCmd != NULL)
|
||||
{
|
||||
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, maxplayersCmd, CmdMaxplayersCallback, true);
|
||||
}
|
||||
}
|
||||
|
||||
ConfigResult PlayerManager::OnSourceModConfigChanged(const char *key,
|
||||
@ -202,11 +244,11 @@ void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int cl
|
||||
/* Initialize all players */
|
||||
m_maxClients = clientMax;
|
||||
m_PlayerCount = 0;
|
||||
m_Players = new CPlayer[m_maxClients + 1];
|
||||
m_AuthQueue = new unsigned int[m_maxClients + 1];
|
||||
m_Players = new CPlayer[ABSOLUTE_PLAYER_LIMIT + 1];
|
||||
m_AuthQueue = new unsigned int[ABSOLUTE_PLAYER_LIMIT + 1];
|
||||
m_FirstPass = true;
|
||||
|
||||
memset(m_AuthQueue, 0, sizeof(unsigned int) * (m_maxClients + 1));
|
||||
memset(m_AuthQueue, 0, sizeof(unsigned int) * (ABSOLUTE_PLAYER_LIMIT + 1));
|
||||
|
||||
g_NumPlayersToAuth = &m_AuthQueue[0];
|
||||
}
|
||||
@ -1203,6 +1245,68 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerManager::OnConVarChanged( ConVar *pConVar, const char *oldValue, float flOldValue )
|
||||
{
|
||||
if (pConVar->GetBool() && !atoi(oldValue))
|
||||
{
|
||||
MaxPlayersChanged(gpGlobals->maxClients + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
MaxPlayersChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerManager::OnSourceModMaxPlayersChanged( int newvalue )
|
||||
{
|
||||
m_maxClients = newvalue;
|
||||
}
|
||||
|
||||
void PlayerManager::MaxPlayersChanged( int newvalue /*= -1*/ )
|
||||
{
|
||||
if (newvalue == -1)
|
||||
{
|
||||
newvalue = gpGlobals->maxClients;
|
||||
}
|
||||
|
||||
if (newvalue == MaxClients())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Notify the rest of core */
|
||||
SMGlobalClass *pBase = SMGlobalClass::head;
|
||||
while (pBase)
|
||||
{
|
||||
pBase->OnSourceModMaxPlayersChanged(newvalue);
|
||||
pBase = pBase->m_pGlobalClassNext;
|
||||
}
|
||||
|
||||
/* Notify Extensions */
|
||||
List<IClientListener *>::iterator iter;
|
||||
IClientListener *pListener = NULL;
|
||||
for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
|
||||
{
|
||||
pListener = (*iter);
|
||||
if (pListener->GetClientListenerVersion() >= 8)
|
||||
{
|
||||
pListener->OnMaxPlayersChanged(newvalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
void CmdMaxplayersCallback(const CCommand &command)
|
||||
{
|
||||
#else
|
||||
void CmdMaxplayersCallback()
|
||||
{
|
||||
#endif
|
||||
|
||||
g_Players.MaxPlayersChanged();
|
||||
}
|
||||
|
||||
|
||||
/*******************
|
||||
*** PLAYER CODE ***
|
||||
*******************/
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <sh_string.h>
|
||||
#include <sh_list.h>
|
||||
#include <sh_vector.h>
|
||||
#include "ConVarManager.h"
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
@ -110,7 +111,8 @@ private:
|
||||
|
||||
class PlayerManager :
|
||||
public SMGlobalClass,
|
||||
public IPlayerManager
|
||||
public IPlayerManager,
|
||||
public IConVarChangeListener
|
||||
{
|
||||
friend class CPlayer;
|
||||
public:
|
||||
@ -121,6 +123,7 @@ public: //SMGlobalClass
|
||||
void OnSourceModShutdown();
|
||||
void OnSourceModLevelEnd();
|
||||
ConfigResult OnSourceModConfigChanged(const char *key, const char *value, ConfigSource source, char *error, size_t maxlength);
|
||||
void OnSourceModMaxPlayersChanged(int newvalue);
|
||||
public:
|
||||
CPlayer *GetPlayerByIndex(int client) const;
|
||||
void RunAuthChecks();
|
||||
@ -153,6 +156,8 @@ public: //IPlayerManager
|
||||
void RegisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
|
||||
void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
|
||||
void ProcessCommandTarget(cmd_target_info_t *info);
|
||||
public: // IConVarChangeListener
|
||||
void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
|
||||
public:
|
||||
inline int MaxClients()
|
||||
{
|
||||
@ -172,6 +177,7 @@ public:
|
||||
void RecheckAnyAdmins();
|
||||
unsigned int GetReplyTo();
|
||||
unsigned int SetReplyTo(unsigned int reply);
|
||||
void MaxPlayersChanged(int newvalue = -1);
|
||||
private:
|
||||
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
|
||||
void InvalidatePlayer(CPlayer *pPlayer);
|
||||
@ -198,6 +204,12 @@ private:
|
||||
int m_ListenClient;
|
||||
};
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
void CmdMaxplayersCallback(const CCommand &command);
|
||||
#else
|
||||
void CmdMaxplayersCallback();
|
||||
#endif
|
||||
|
||||
extern PlayerManager g_Players;
|
||||
extern bool g_OnMapStarted;
|
||||
extern const unsigned int *g_NumPlayersToAuth;
|
||||
|
@ -74,6 +74,7 @@ class SMGlobalClass
|
||||
friend class SourceModBase;
|
||||
friend class CoreConfig;
|
||||
friend class CExtensionManager;
|
||||
friend class PlayerManager;
|
||||
public:
|
||||
SMGlobalClass();
|
||||
public:
|
||||
@ -167,6 +168,15 @@ public:
|
||||
virtual void OnSourceModIdentityDropped(IdentityToken_t *pToken)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when the server maxplayers changes
|
||||
*
|
||||
* @param newvalue New maxplayers value.
|
||||
*/
|
||||
virtual void OnSourceModMaxPlayersChanged(int newvalue)
|
||||
{
|
||||
}
|
||||
private:
|
||||
SMGlobalClass *m_pGlobalClassNext;
|
||||
static SMGlobalClass *head;
|
||||
|
@ -93,7 +93,7 @@ unsigned int TopMenu::CalcMemUsage()
|
||||
|
||||
size += m_Config.strings.GetMemTable()->MemUsage();
|
||||
size += (m_Config.cats.size() * sizeof(int));
|
||||
size += (sizeof(topmenu_player_t) * m_max_clients);
|
||||
size += (sizeof(topmenu_player_t) * (ABSOLUTE_PLAYER_LIMIT + 1));
|
||||
size += (m_SortedCats.size() * sizeof(unsigned int));
|
||||
size += (m_UnsortedCats.size() * sizeof(unsigned int));
|
||||
size += (m_Categories.size() * (sizeof(topmenu_category_t *) + sizeof(topmenu_category_t)));
|
||||
@ -904,8 +904,8 @@ void TopMenu::SortCategoriesIfNeeded()
|
||||
void TopMenu::CreatePlayers(int max_clients)
|
||||
{
|
||||
m_max_clients = max_clients;
|
||||
m_clients = (topmenu_player_t *)malloc(sizeof(topmenu_player_t) * (max_clients + 1));
|
||||
memset(m_clients, 0, sizeof(topmenu_player_t) * (max_clients + 1));
|
||||
m_clients = (topmenu_player_t *)malloc(sizeof(topmenu_player_t) * (ABSOLUTE_PLAYER_LIMIT + 1));
|
||||
memset(m_clients, 0, sizeof(topmenu_player_t) * (ABSOLUTE_PLAYER_LIMIT + 1));
|
||||
}
|
||||
|
||||
void TopMenu::TearDownClient(topmenu_player_t *player)
|
||||
@ -1100,6 +1100,11 @@ unsigned int TopMenu::FindCategory(const char *name)
|
||||
return obj->object_id;
|
||||
}
|
||||
|
||||
void TopMenu::OnMaxPlayersChanged( int newvalue )
|
||||
{
|
||||
m_max_clients = newvalue;
|
||||
}
|
||||
|
||||
int _SortObjectNamesDescending(const void *ptr1, const void *ptr2)
|
||||
{
|
||||
obj_by_name_t *obj1 = (obj_by_name_t *)ptr1;
|
||||
|
@ -42,6 +42,8 @@
|
||||
using namespace SourceHook;
|
||||
using namespace SourceMod;
|
||||
|
||||
#define ABSOLUTE_PLAYER_LIMIT 255 // not 256, so we can send the limit as a byte
|
||||
|
||||
struct config_category_t
|
||||
{
|
||||
int name;
|
||||
@ -162,6 +164,7 @@ private:
|
||||
void OnClientDisconnected(int client);
|
||||
void OnServerActivated(int max_clients);
|
||||
bool OnIdentityRemoval(IdentityToken_t *owner);
|
||||
void OnMaxPlayersChanged(int newvalue);
|
||||
private:
|
||||
config_root_t m_Config; /* Configuration from file */
|
||||
topmenu_player_t *m_clients; /* Client array */
|
||||
|
@ -117,3 +117,13 @@ void TopMenuManager::DestroyTopMenu(ITopMenu *topmenu)
|
||||
|
||||
delete pMenu;
|
||||
}
|
||||
|
||||
void TopMenuManager::OnMaxPlayersChanged( int newvalue )
|
||||
{
|
||||
List<TopMenu *>::iterator iter;
|
||||
|
||||
for (iter = m_TopMenus.begin(); iter != m_TopMenus.end(); iter++)
|
||||
{
|
||||
(*iter)->OnMaxPlayersChanged(newvalue);
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ public:
|
||||
void OnClientDisconnected(int client);
|
||||
void OnServerActivated(int max_clients);
|
||||
void OnPluginUnloaded(IPlugin *plugin);
|
||||
void OnMaxPlayersChanged(int newvalue);
|
||||
private:
|
||||
List<TopMenu *> m_TopMenus;
|
||||
};
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include <IAdminSystem.h>
|
||||
|
||||
#define SMINTERFACE_PLAYERMANAGER_NAME "IPlayerManager"
|
||||
#define SMINTERFACE_PLAYERMANAGER_VERSION 7
|
||||
#define SMINTERFACE_PLAYERMANAGER_VERSION 8
|
||||
|
||||
struct edict_t;
|
||||
class IPlayerInfo;
|
||||
@ -301,6 +301,15 @@ namespace SourceMod
|
||||
virtual void OnClientPostAdminCheck(int client)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notifies the extension that the maxplayers value has changed
|
||||
*
|
||||
* @param newvalue New maxplayers value.
|
||||
*/
|
||||
virtual void OnMaxPlayersChanged(int newvalue)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#define COMMAND_FILTER_ALIVE (1<<0) /**< Only allow alive players */
|
||||
|
Loading…
Reference in New Issue
Block a user