diff --git a/extension.cpp b/extension.cpp index 25dfc8b..538c4fb 100644 --- a/extension.cpp +++ b/extension.cpp @@ -56,16 +56,20 @@ SMEXT_LINK(&g_Interface); CDetour *g_pDetour_SendTo = NULL; +ConVar g_A2SMaxPlayers("a2s_maxplayers", "-1", FCVAR_NONE, "Maximum Players in the A2S Packet."); +ConVar g_A2SIncludeSourceTV("a2s_includesourcetv", "0", FCVAR_NONE, "Include SourceTV in the Player Count and List."); + char *NewBuf; char *OldBuf; -struct PlayerInfo -{ +struct PlayerInfo { char Name[32]; long Score; float Time; }; +int g_FakePlayers = 0; + /** * @brief */ @@ -118,16 +122,23 @@ DETOUR_DECL_STATIC6(Detour_SendTo, int, int, s, char *, buf, int, len, int, flag for (int index = 0; index <= SM_MAXPLAYERS; index++) { IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(index); - - if (pPlayer != NULL && pPlayer->IsConnected() && !pPlayer->IsSourceTV()) - { + if (pPlayer != NULL && pPlayer->IsConnected() && (!pPlayer->IsSourceTV() || g_A2SIncludeSourceTV.GetInt())) iPlayers++; - } } + iPlayers += g_FakePlayers; + // Correct playercount memset(NewBuf, iPlayers, 1); + // Set MaxPlayers + int iMaxPlayers = g_A2SMaxPlayers.GetInt(); + if (iMaxPlayers > 0) + { + NewBuf++; + memset(NewBuf, iMaxPlayers, 1); + } + // Reset Pointer NewBuf = OldBuf; @@ -152,7 +163,7 @@ DETOUR_DECL_STATIC6(Detour_SendTo, int, int, s, char *, buf, int, len, int, flag { IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(index); - if (pPlayer != NULL && pPlayer->IsConnected() && pPlayer->IsInGame() && !pPlayer->IsSourceTV()) + if (pPlayer != NULL && pPlayer->IsConnected() && pPlayer->IsInGame() && (!pPlayer->IsSourceTV() || g_A2SIncludeSourceTV.GetInt())) { memcpy(PlayerList[iPlayers].Name, pPlayer->GetName(), 32); @@ -190,6 +201,29 @@ DETOUR_DECL_STATIC6(Detour_SendTo, int, int, s, char *, buf, int, len, int, flag return DETOUR_STATIC_CALL(Detour_SendTo)(s, buf, len, flags, to, tolen); } +/** + * @brief + */ +cell_t FakePlayers(IPluginContext *pContext, const cell_t *params) +{ + g_FakePlayers = params[1]; + return 1; +} + +/** + * @brief + */ +const sp_nativeinfo_t MyNatives[] = +{ + {"FakePlayers", FakePlayers}, + {NULL, NULL}, +}; + +void A2SFixes::SDK_OnAllLoaded() +{ + sharesys->AddNatives(myself, MyNatives); +} + /** * @brief This is called after the initial loading sequence has been processed. * @@ -227,6 +261,12 @@ void A2SFixes::SDK_OnUnload() } } +bool A2SFixes::RegisterConCommandBase(ConCommandBase *pVar) +{ + /* Always call META_REGCVAR instead of going through the engine. */ + return META_REGCVAR(pVar); +} + /** * @brief Called when Metamod is attached, before the extension version is called. * @@ -238,6 +278,8 @@ void A2SFixes::SDK_OnUnload() bool A2SFixes::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late) { GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER); + GET_V_IFACE_CURRENT(GetEngineFactory, g_pCVar, ICvar, CVAR_INTERFACE_VERSION); + ConVar_Register(0, this); return true; } \ No newline at end of file diff --git a/extension.h b/extension.h index 6d01fd1..4d9b5eb 100644 --- a/extension.h +++ b/extension.h @@ -44,7 +44,9 @@ * @brief A2SFixes implementation of the SDK Extension. * Note: Uncomment one of the pre-defined virtual functions in order to use it. */ -class A2SFixes : public SDKExtension +class A2SFixes : + public SDKExtension, + public IConCommandBaseAccessor { public: /** @@ -66,7 +68,7 @@ public: * @brief This is called once all known extensions have been loaded. * Note: It is is a good idea to add natives here, if any are provided. */ - //virtual void SDK_OnAllLoaded(); + virtual void SDK_OnAllLoaded(); /** * @brief Called when the pause state is changed. @@ -114,6 +116,9 @@ public: */ //virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength); #endif + +public: // IConCommandBaseAccessor + virtual bool RegisterConCommandBase(ConCommandBase *pVar); }; #endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_