Added detection of Replay and SourceTV, and natives to query (bug 5124, r=fyren).
Added detection of Replay and SourceTV, and natives to query (
bug 5124, r=fyren).
1.1 --- a/core/PlayerManager.cpp Thu Oct 20 21:35:50 2011 -0400
1.2 +++ b/core/PlayerManager.cpp Thu Oct 20 21:39:57 2011 -0400
1.3 @@ -44,6 +44,7 @@
1.4 #include "HalfLife2.h"
1.5 #include <inetchannel.h>
1.6 #include <iclient.h>
1.7 +#include <tier0/icommandline.h>
1.8 #include <IGameConfigs.h>
1.9 #include "ExtensionSys.h"
1.10 #include <sourcemod_version.h>
1.11 @@ -113,6 +114,9 @@
1.12 m_FirstPass = false;
1.13 m_maxClients = 0;
1.14
1.15 + m_SourceTVUserId = -1;
1.16 + m_ReplayUserId = -1;
1.17 +
1.18 m_UserIdLookUp = new int[USHRT_MAX+1];
1.19 memset(m_UserIdLookUp, 0, sizeof(int) * (USHRT_MAX+1));
1.20 }
1.21 @@ -232,8 +236,20 @@
1.22
1.23 void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax)
1.24 {
1.25 + static ConVar *tv_enable = icvar->FindVar("tv_enable");
1.26 +#if SOURCE_ENGINE == SE_ORANGEBOXVALVE
1.27 + static ConVar *replay_enable = icvar->FindVar("replay_enable");
1.28 +#endif
1.29 +
1.30 // clientMax will not necessarily be correct here (such as on late SourceTV enable)
1.31 m_maxClients = gpGlobals->maxClients;
1.32 +
1.33 + m_bIsSourceTVActive = (tv_enable && tv_enable->GetBool() && CommandLine()->FindParm("-nohltv") == 0);
1.34 + m_bIsReplayActive = false;
1.35 +#if SOURCE_ENGINE == SE_ORANGEBOXVALVE
1.36 + m_bIsReplayActive = (replay_enable && replay_enable->GetBool());
1.37 +#endif
1.38 + m_PlayersSinceActive = 0;
1.39
1.40 if (!m_FirstPass)
1.41 {
1.42 @@ -411,6 +427,7 @@
1.43 {
1.44 int client = IndexOfEdict(pEntity);
1.45 CPlayer *pPlayer = &m_Players[client];
1.46 + ++m_PlayersSinceActive;
1.47
1.48 pPlayer->Initialize(pszName, pszAddress, pEntity);
1.49
1.50 @@ -518,6 +535,40 @@
1.51 const char *authid = engine->GetPlayerNetworkIDString(pEntity);
1.52 pPlayer->Authorize(authid);
1.53 pPlayer->m_bFakeClient = true;
1.54 +
1.55 + /*
1.56 + * While we're already filtered to just bots, we'll do other checks to
1.57 + * make sure that the requisite services are enabled and that the bots
1.58 + * have joined at the expected time.
1.59 + *
1.60 + * Checking playerinfo's IsHLTV and IsReplay would be better and less
1.61 + * error-prone but will always show false until later in the frame,
1.62 + * after PutInServer and Activate, and we want it now!
1.63 + */
1.64 +
1.65 + // This doesn't actually get incremented until OnClientConnect. Fake it to check.
1.66 + int newCount = m_PlayersSinceActive + 1;
1.67 + int userId = engine->GetPlayerUserId(pEntity);
1.68 +
1.69 +#if SOURCE_ENGINE == SE_ORANGEBOXVALVE
1.70 + if (m_bIsReplayActive && newCount == 1
1.71 + && (m_ReplayUserId == userId || strcmp(playername, "Replay") == 0))
1.72 + {
1.73 + pPlayer->m_bIsReplay = true;
1.74 + m_ReplayUserId = userId;
1.75 + }
1.76 +#endif
1.77 +
1.78 + if (m_bIsSourceTVActive
1.79 + && ((!m_bIsReplayActive && newCount == 1)
1.80 + || (m_bIsReplayActive && newCount == 2))
1.81 + && (m_SourceTVUserId == userId || strcmp(playername, "SourceTV") == 0)
1.82 + )
1.83 + {
1.84 + pPlayer->m_bIsSourceTV = true;
1.85 + m_SourceTVUserId = userId;
1.86 + }
1.87 +
1.88 if (!OnClientConnect(pEntity, playername, "127.0.0.1", error, sizeof(error)))
1.89 {
1.90 /* :TODO: kick the bot if it's rejected */
1.91 @@ -1452,6 +1503,8 @@
1.92 m_LastPassword.clear();
1.93 m_LangId = SOURCEMOD_LANGUAGE_ENGLISH;
1.94 m_bFakeClient = false;
1.95 + m_bIsSourceTV = false;
1.96 + m_bIsReplay = false;
1.97 m_Serial.value = -1;
1.98 }
1.99
1.100 @@ -1524,6 +1577,8 @@
1.101 m_UserId = -1;
1.102 m_bIsInKickQueue = false;
1.103 m_bFakeClient = false;
1.104 + m_bIsSourceTV = false;
1.105 + m_bIsReplay = false;
1.106 m_Serial.value = -1;
1.107 }
1.108
1.109 @@ -1592,6 +1647,16 @@
1.110 return m_bFakeClient;
1.111 }
1.112
1.113 +bool CPlayer::IsSourceTV() const
1.114 +{
1.115 + return m_bIsSourceTV;
1.116 +}
1.117 +
1.118 +bool CPlayer::IsReplay() const
1.119 +{
1.120 + return m_bIsReplay;
1.121 +}
1.122 +
1.123 void CPlayer::SetAdminId(AdminId id, bool temporary)
1.124 {
1.125 if (!m_IsConnected)
2.1 --- a/core/PlayerManager.h Thu Oct 20 21:35:50 2011 -0400
2.2 +++ b/core/PlayerManager.h Thu Oct 20 21:39:57 2011 -0400
2.3 @@ -76,6 +76,8 @@
2.4 bool IsConnected();
2.5 bool IsAuthorized();
2.6 bool IsFakeClient();
2.7 + bool IsSourceTV() const;
2.8 + bool IsReplay() const;
2.9 void SetAdminId(AdminId id, bool temporary);
2.10 AdminId GetAdminId();
2.11 void Kick(const char *str);
2.12 @@ -119,6 +121,8 @@
2.13 unsigned int m_LangId;
2.14 int m_UserId;
2.15 bool m_bFakeClient;
2.16 + bool m_bIsSourceTV;
2.17 + bool m_bIsReplay;
2.18 serial_t m_Serial;
2.19 };
2.20
2.21 @@ -208,12 +212,17 @@
2.22 int *m_UserIdLookUp;
2.23 int m_maxClients;
2.24 int m_PlayerCount;
2.25 + int m_PlayersSinceActive;
2.26 bool m_FirstPass;
2.27 unsigned int *m_AuthQueue;
2.28 String m_PassInfoVar;
2.29 bool m_QueryLang;
2.30 bool m_bIsListenServer;
2.31 int m_ListenClient;
2.32 + bool m_bIsSourceTVActive;
2.33 + bool m_bIsReplayActive;
2.34 + int m_SourceTVUserId;
2.35 + int m_ReplayUserId;
2.36 };
2.37
2.38 #if SOURCE_ENGINE >= SE_ORANGEBOX
3.1 --- a/core/smn_player.cpp Thu Oct 20 21:35:50 2011 -0400
3.2 +++ b/core/smn_player.cpp Thu Oct 20 21:39:57 2011 -0400
3.3 @@ -200,6 +200,40 @@
3.4 return (pPlayer->IsFakeClient()) ? 1 : 0;
3.5 }
3.6
3.7 +static cell_t sm_IsClientSourceTV(IPluginContext *pCtx, const cell_t *params)
3.8 +{
3.9 + int index = params[1];
3.10 + if ((index < 1) || (index > g_Players.GetMaxClients()))
3.11 + {
3.12 + return pCtx->ThrowNativeError("Client index %d is invalid", index);
3.13 + }
3.14 +
3.15 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
3.16 + if (!pPlayer->IsConnected())
3.17 + {
3.18 + return pCtx->ThrowNativeError("Client %d is not connected", index);
3.19 + }
3.20 +
3.21 + return (pPlayer->IsSourceTV()) ? 1 : 0;
3.22 +}
3.23 +
3.24 +static cell_t sm_IsClientReplay(IPluginContext *pCtx, const cell_t *params)
3.25 +{
3.26 + int index = params[1];
3.27 + if ((index < 1) || (index > g_Players.GetMaxClients()))
3.28 + {
3.29 + return pCtx->ThrowNativeError("Client index %d is invalid", index);
3.30 + }
3.31 +
3.32 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
3.33 + if (!pPlayer->IsConnected())
3.34 + {
3.35 + return pCtx->ThrowNativeError("Client %d is not connected", index);
3.36 + }
3.37 +
3.38 + return (pPlayer->IsReplay()) ? 1 : 0;
3.39 +}
3.40 +
3.41 static cell_t IsClientObserver(IPluginContext *pContext, const cell_t *params)
3.42 {
3.43 int client = params[1];
3.44 @@ -1605,6 +1639,8 @@
3.45 {"IsClientAuthorized", sm_IsClientAuthorized},
3.46 {"IsClientConnected", sm_IsClientConnected},
3.47 {"IsFakeClient", sm_IsClientFakeClient},
3.48 + {"IsClientSourceTV", sm_IsClientSourceTV},
3.49 + {"IsClientReplay", sm_IsClientReplay},
3.50 {"IsClientInGame", sm_IsClientInGame},
3.51 {"IsClientObserver", IsClientObserver},
3.52 {"RemoveUserFlags", RemoveUserFlags},
4.1 --- a/plugins/include/clients.inc Thu Oct 20 21:35:50 2011 -0400
4.2 +++ b/plugins/include/clients.inc Thu Oct 20 21:39:57 2011 -0400
4.3 @@ -315,6 +315,22 @@
4.4 native bool:IsFakeClient(client);
4.5
4.6 /**
4.7 + * Returns if a certain player is the SourceTV bot.
4.8 + *
4.9 + * @param client Player index.
4.10 + * @return True if player is the SourceTV bot, false otherwise.
4.11 + */
4.12 +native bool:IsClientSourceTV(client);
4.13 +
4.14 +/**
4.15 + * Returns if a certain player is the Replay bot.
4.16 + *
4.17 + * @param client Player index.
4.18 + * @return True if player is the Replay bot, false otherwise.
4.19 + */
4.20 +native bool:IsClientReplay(client);
4.21 +
4.22 +/**
4.23 * Returns if a certain player is an observer/spectator.
4.24 *
4.25 * @param client Player index.
5.1 --- a/public/IPlayerHelpers.h Thu Oct 20 21:35:50 2011 -0400
5.2 +++ b/public/IPlayerHelpers.h Thu Oct 20 21:39:57 2011 -0400
5.3 @@ -41,7 +41,7 @@
5.4 #include <IAdminSystem.h>
5.5
5.6 #define SMINTERFACE_PLAYERMANAGER_NAME "IPlayerManager"
5.7 -#define SMINTERFACE_PLAYERMANAGER_VERSION 14
5.8 +#define SMINTERFACE_PLAYERMANAGER_VERSION 15
5.9
5.10 struct edict_t;
5.11 class IPlayerInfo;
5.12 @@ -222,6 +222,20 @@
5.13 virtual void MarkAsBeingKicked() =0;
5.14
5.15 virtual void SetLanguageId(unsigned int id) =0;
5.16 +
5.17 + /**
5.18 + * @brief Returns whether the player is the SourceTV bot.
5.19 + *
5.20 + * @return True if the SourceTV bot, false otherwise.
5.21 + */
5.22 + virtual bool IsSourceTV() const =0;
5.23 +
5.24 + /**
5.25 + * @brief Returns whether the player is the Replay bot.
5.26 + *
5.27 + * @return True if the Replay bot, false otherwise.
5.28 + */
5.29 + virtual bool IsReplay() const =0;
5.30 };
5.31
5.32 /**