Core now detects and handles a changed maxplayers value (bug 2537 and bug 2758)

This commit is contained in:
Matt Woodrow 2008-09-26 19:08:49 +12:00
parent 4517031861
commit f4dba84ae5
8 changed files with 162 additions and 8 deletions

View File

@ -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 ***
*******************/

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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);
}
}

View File

@ -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;
};

View File

@ -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 */