Add natives to get client ip and connect password
The hltv server doesn't provide a nice IPlayerInfo interface to get stuff. Have to grab it and hold on to it while we can!
This commit is contained in:
parent
10f7fa56a1
commit
c0eb6eb75f
@ -8,7 +8,8 @@ sourceFiles = [
|
|||||||
'extension.cpp',
|
'extension.cpp',
|
||||||
'natives.cpp',
|
'natives.cpp',
|
||||||
'forwards.cpp',
|
'forwards.cpp',
|
||||||
'hltvdirectorwrapper.cpp'
|
'hltvdirectorwrapper.cpp',
|
||||||
|
'hltvclientwrapper.cpp'
|
||||||
]
|
]
|
||||||
|
|
||||||
###############
|
###############
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include <IBinTools.h>
|
#include <IBinTools.h>
|
||||||
#include <ISDKTools.h>
|
#include <ISDKTools.h>
|
||||||
#include "hltvdirectorwrapper.h"
|
#include "hltvdirectorwrapper.h"
|
||||||
|
#include "hltvclientwrapper.h"
|
||||||
#include "ihltvdirector.h"
|
#include "ihltvdirector.h"
|
||||||
#include "ihltv.h"
|
#include "ihltv.h"
|
||||||
#include "iserver.h"
|
#include "iserver.h"
|
||||||
|
33
forwards.cpp
33
forwards.cpp
@ -97,14 +97,18 @@ void CForwardManager::HookServer(IServer *server)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
SH_ADD_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect), false);
|
SH_ADD_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect), false);
|
||||||
SH_ADD_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect_Post), true);
|
|
||||||
|
|
||||||
// Hook all already connected clients as well for late loading
|
// Hook all already connected clients as well for late loading
|
||||||
for (int i = 0; i < server->GetClientCount(); i++)
|
for (int i = 0; i < server->GetClientCount(); i++)
|
||||||
{
|
{
|
||||||
IClient *client = server->GetClient(i);
|
IClient *client = server->GetClient(i);
|
||||||
if (client->IsConnected())
|
if (client->IsConnected())
|
||||||
|
{
|
||||||
HookClient(client);
|
HookClient(client);
|
||||||
|
// Ip and password unknown :(
|
||||||
|
// Could add more gamedata to fetch it if people really lateload the extension and expect it to work :B
|
||||||
|
g_HLTVClientManager.GetClient(i + 1)->Initialize("", "", client);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +118,6 @@ void CForwardManager::UnhookServer(IServer *server)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
SH_REMOVE_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect), false);
|
SH_REMOVE_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect), false);
|
||||||
SH_REMOVE_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect_Post), true);
|
|
||||||
|
|
||||||
// Unhook all connected clients as well.
|
// Unhook all connected clients as well.
|
||||||
for (int i = 0; i < server->GetClientCount(); i++)
|
for (int i = 0; i < server->GetClientCount(); i++)
|
||||||
@ -296,9 +299,9 @@ IClient *CForwardManager::OnSpectatorConnect(netadr_t & address, int nProtocol,
|
|||||||
cell_t retVal = 1;
|
cell_t retVal = 1;
|
||||||
m_SpectatorPreConnectFwd->Execute(&retVal);
|
m_SpectatorPreConnectFwd->Execute(&retVal);
|
||||||
|
|
||||||
|
IServer *server = META_IFACEPTR(IServer);
|
||||||
if (retVal == 0)
|
if (retVal == 0)
|
||||||
{
|
{
|
||||||
IServer *server = META_IFACEPTR(IServer);
|
|
||||||
#if SOURCE_ENGINE == SE_CSGO
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
RejectConnection(server, address, rejectReason);
|
RejectConnection(server, address, rejectReason);
|
||||||
#else
|
#else
|
||||||
@ -307,30 +310,26 @@ IClient *CForwardManager::OnSpectatorConnect(netadr_t & address, int nProtocol,
|
|||||||
RETURN_META_VALUE(MRES_SUPERCEDE, nullptr);
|
RETURN_META_VALUE(MRES_SUPERCEDE, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pchPassword = passwordBuffer;
|
// Call the original function.
|
||||||
#if SOURCE_ENGINE == SE_CSGO
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
RETURN_META_VALUE_MNEWPARAMS(MRES_IGNORED, nullptr, CHLTVServer_ConnectClient, (address, nProtocol, iChallenge, nAuthProtocol, pchName, pchPassword, pCookie, cbCookie, pSplitPlayerConnectVector, bUnknown, platform, pUnknown, iUnknown));
|
IClient *client = SH_MCALL(server, CHLTVServer_ConnectClient)(address, nProtocol, iChallenge, nAuthProtocol, pchName, passwordBuffer, pCookie, cbCookie, pSplitPlayerConnectVector, bUnknown, platform, pUnknown, iUnknown);
|
||||||
#else
|
#else
|
||||||
RETURN_META_VALUE_MNEWPARAMS(MRES_IGNORED, nullptr, CHLTVServer_ConnectClient, (address, nProtocol, iChallenge, iClientChallenge, nAuthProtocol, pchName, pchPassword, pCookie, cbCookie));
|
IClient *client = SH_MCALL(server, CHLTVServer_ConnectClient)(address, nProtocol, iChallenge, iClientChallenge, nAuthProtocol, pchName, passwordBuffer, pCookie, cbCookie);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
#if SOURCE_ENGINE == SE_CSGO
|
|
||||||
IClient *CForwardManager::OnSpectatorConnect_Post(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<NetMsg_SplitPlayerConnect *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char * pUnknown, int iUnknown)
|
|
||||||
#else
|
|
||||||
IClient *CForwardManager::OnSpectatorConnect_Post(netadr_t & address, int nProtocol, int iChallenge, int iClientChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
IClient *client = META_RESULT_ORIG_RET(IClient *);
|
|
||||||
if (!client)
|
if (!client)
|
||||||
RETURN_META_VALUE(MRES_IGNORED, nullptr);
|
RETURN_META_VALUE(MRES_SUPERCEDE, nullptr);
|
||||||
|
|
||||||
HookClient(client);
|
HookClient(client);
|
||||||
|
|
||||||
m_SpectatorConnectedFwd->PushCell(client->GetPlayerSlot()+1);
|
HLTVClientWrapper *wrapper = g_HLTVClientManager.GetClient(client->GetPlayerSlot() + 1);
|
||||||
|
wrapper->Initialize(ipString, pchPassword, client);
|
||||||
|
|
||||||
|
m_SpectatorConnectedFwd->PushCell(client->GetPlayerSlot() + 1);
|
||||||
m_SpectatorConnectedFwd->Execute();
|
m_SpectatorConnectedFwd->Execute();
|
||||||
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, nullptr);
|
// Don't call the hooked function again, just return its value.
|
||||||
|
RETURN_META_VALUE(MRES_SUPERCEDE, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CForwardManager::OnSpectatorDisconnect(const char *reason)
|
void CForwardManager::OnSpectatorDisconnect(const char *reason)
|
||||||
|
@ -72,11 +72,9 @@ private:
|
|||||||
#if SOURCE_ENGINE == SE_CSGO
|
#if SOURCE_ENGINE == SE_CSGO
|
||||||
void OnStopRecording_Post(CGameInfo const *info);
|
void OnStopRecording_Post(CGameInfo const *info);
|
||||||
IClient *OnSpectatorConnect(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<NetMsg_SplitPlayerConnect *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown);
|
IClient *OnSpectatorConnect(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<NetMsg_SplitPlayerConnect *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown);
|
||||||
IClient *OnSpectatorConnect_Post(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<NetMsg_SplitPlayerConnect *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown);
|
|
||||||
#else
|
#else
|
||||||
void OnStopRecording_Post();
|
void OnStopRecording_Post();
|
||||||
IClient *OnSpectatorConnect(netadr_t &address, int nProtocol, int iChallenge, int iClientChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie);
|
IClient *OnSpectatorConnect(netadr_t &address, int nProtocol, int iChallenge, int iClientChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie);
|
||||||
IClient *OnSpectatorConnect_Post(netadr_t &address, int nProtocol, int iChallenge, int iClientChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie);
|
|
||||||
#endif
|
#endif
|
||||||
void OnSpectatorDisconnect(const char *reason);
|
void OnSpectatorDisconnect(const char *reason);
|
||||||
|
|
||||||
|
69
hltvclientwrapper.cpp
Normal file
69
hltvclientwrapper.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include "hltvclientwrapper.h"
|
||||||
|
|
||||||
|
HLTVClientWrapper::HLTVClientWrapper()
|
||||||
|
{
|
||||||
|
m_Client = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HLTVClientWrapper::Initialize(const char *ip, const char *password, IClient *client)
|
||||||
|
{
|
||||||
|
m_Ip = ip;
|
||||||
|
m_Password = password;
|
||||||
|
m_Client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *HLTVClientWrapper::Name()
|
||||||
|
{
|
||||||
|
return m_Client->GetClientName();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *HLTVClientWrapper::Ip()
|
||||||
|
{
|
||||||
|
return m_Ip.chars();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *HLTVClientWrapper::Password()
|
||||||
|
{
|
||||||
|
return m_Password.chars();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HLTVClientWrapper::IsConnected()
|
||||||
|
{
|
||||||
|
return m_Client && m_Client->IsConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
IClient *HLTVClientWrapper::BaseClient()
|
||||||
|
{
|
||||||
|
return m_Client;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HLTVClientWrapper::Kick(const char *reason)
|
||||||
|
{
|
||||||
|
// Go this route due to different IClient::Disconnect signatures in games..
|
||||||
|
m_Client->GetServer()->DisconnectClient(m_Client, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
HLTVClientWrapper *HLTVClientManager::GetClient(int index)
|
||||||
|
{
|
||||||
|
// Grow the vector with null pointers
|
||||||
|
// There might have been clients with lower indexes before we were loaded.
|
||||||
|
if (m_Clients.length() < (size_t)index)
|
||||||
|
{
|
||||||
|
int start = m_Clients.length();
|
||||||
|
m_Clients.resize(index);
|
||||||
|
for (int i = start; i < index; i++)
|
||||||
|
{
|
||||||
|
m_Clients[i] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_Clients[index - 1])
|
||||||
|
{
|
||||||
|
m_Clients[index - 1] = new HLTVClientWrapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_Clients[index - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: ClientManager instance for each hltvserver instance in csgo!
|
||||||
|
HLTVClientManager g_HLTVClientManager;
|
71
hltvclientwrapper.h
Normal file
71
hltvclientwrapper.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* =============================================================================
|
||||||
|
* SourceMod SourceTV Manager Extension
|
||||||
|
* Copyright (C) 2004-2016 AlliedModders LLC. All rights reserved.
|
||||||
|
* =============================================================================
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||||
|
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||||
|
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||||
|
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||||
|
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||||
|
* this exception to all derivative works. AlliedModders LLC defines further
|
||||||
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||||
|
* or <http://www.sourcemod.net/license.php>.
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_HLTVCLIENT_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_EXTENSION_HLTVCLIENT_H_
|
||||||
|
|
||||||
|
#include "extension.h"
|
||||||
|
#include "amtl/am-string.h"
|
||||||
|
#include "amtl/am-vector.h"
|
||||||
|
#include "amtl/am-utility.h"
|
||||||
|
|
||||||
|
class HLTVClientWrapper {
|
||||||
|
public:
|
||||||
|
HLTVClientWrapper();
|
||||||
|
void Initialize(const char *ip, const char *password, IClient *client);
|
||||||
|
|
||||||
|
public:
|
||||||
|
const char *Name();
|
||||||
|
const char *Ip();
|
||||||
|
const char *Password();
|
||||||
|
bool IsConnected();
|
||||||
|
IClient *BaseClient();
|
||||||
|
|
||||||
|
void Kick(const char *reason);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ke::AString m_Ip;
|
||||||
|
ke::AString m_Password;
|
||||||
|
IClient *m_Client;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HLTVClientManager {
|
||||||
|
|
||||||
|
public:
|
||||||
|
HLTVClientWrapper *GetClient(int index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ke::Vector<ke::AutoPtr<HLTVClientWrapper>> m_Clients;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern HLTVClientManager g_HLTVClientManager;
|
||||||
|
|
||||||
|
#endif // _INCLUDE_SOURCEMOD_EXTENSION_HLTVCLIENT_H_
|
64
natives.cpp
64
natives.cpp
@ -544,7 +544,7 @@ static cell_t Native_IsClientConnected(IPluginContext *pContext, const cell_t *p
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
IClient *pClient = hltvserver->GetBaseServer()->GetClient(client - 1);
|
HLTVClientWrapper *pClient = g_HLTVClientManager.GetClient(client);
|
||||||
return pClient->IsConnected();
|
return pClient->IsConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -561,14 +561,62 @@ static cell_t Native_GetSpectatorName(IPluginContext *pContext, const cell_t *pa
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
IClient *pClient = hltvserver->GetBaseServer()->GetClient(client - 1);
|
HLTVClientWrapper *pClient = g_HLTVClientManager.GetClient(client);
|
||||||
if (!pClient || !pClient->IsConnected())
|
if (!pClient->IsConnected())
|
||||||
{
|
{
|
||||||
pContext->ReportError("Client %d is not connected.", client);
|
pContext->ReportError("Client %d is not connected.", client);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), pClient->GetClientName(), NULL);
|
pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), pClient->Name(), NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// native SourceTV_GetSpectatorIP(client, String:ip[], maxlen);
|
||||||
|
static cell_t Native_GetSpectatorIP(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
if (hltvserver == nullptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cell_t client = params[1];
|
||||||
|
if (client < 1 || client > hltvserver->GetBaseServer()->GetClientCount())
|
||||||
|
{
|
||||||
|
pContext->ReportError("Invalid spectator client index %d.", client);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HLTVClientWrapper *pClient = g_HLTVClientManager.GetClient(client);
|
||||||
|
if (!pClient->IsConnected())
|
||||||
|
{
|
||||||
|
pContext->ReportError("Client %d is not connected.", client);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), pClient->Ip(), NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// native SourceTV_GetSpectatorPassword(client, String:password[], maxlen);
|
||||||
|
static cell_t Native_GetSpectatorPassword(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
if (hltvserver == nullptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cell_t client = params[1];
|
||||||
|
if (client < 1 || client > hltvserver->GetBaseServer()->GetClientCount())
|
||||||
|
{
|
||||||
|
pContext->ReportError("Invalid spectator client index %d.", client);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HLTVClientWrapper *pClient = g_HLTVClientManager.GetClient(client);
|
||||||
|
if (!pClient->IsConnected())
|
||||||
|
{
|
||||||
|
pContext->ReportError("Client %d is not connected.", client);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), pClient->Password(), NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,8 +633,8 @@ static cell_t Native_KickClient(IPluginContext *pContext, const cell_t *params)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
IClient *pClient = hltvserver->GetBaseServer()->GetClient(client - 1);
|
HLTVClientWrapper *pClient = g_HLTVClientManager.GetClient(client);
|
||||||
if (!pClient || !pClient->IsConnected())
|
if (!pClient->IsConnected())
|
||||||
{
|
{
|
||||||
pContext->ReportError("Client %d is not connected.", client);
|
pContext->ReportError("Client %d is not connected.", client);
|
||||||
return 0;
|
return 0;
|
||||||
@ -595,7 +643,7 @@ static cell_t Native_KickClient(IPluginContext *pContext, const cell_t *params)
|
|||||||
char *pReason;
|
char *pReason;
|
||||||
pContext->LocalToString(params[2], &pReason);
|
pContext->LocalToString(params[2], &pReason);
|
||||||
|
|
||||||
hltvserver->GetBaseServer()->DisconnectClient(pClient, pReason);
|
pClient->Kick(pReason);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,6 +674,8 @@ const sp_nativeinfo_t sourcetv_natives[] =
|
|||||||
{ "SourceTV_GetClientCount", Native_GetClientCount },
|
{ "SourceTV_GetClientCount", Native_GetClientCount },
|
||||||
{ "SourceTV_IsClientConnected", Native_IsClientConnected },
|
{ "SourceTV_IsClientConnected", Native_IsClientConnected },
|
||||||
{ "SourceTV_GetSpectatorName", Native_GetSpectatorName },
|
{ "SourceTV_GetSpectatorName", Native_GetSpectatorName },
|
||||||
|
{ "SourceTV_GetSpectatorIP", Native_GetSpectatorIP },
|
||||||
|
{ "SourceTV_GetSpectatorPassword", Native_GetSpectatorPassword },
|
||||||
{ "SourceTV_KickClient", Native_KickClient },
|
{ "SourceTV_KickClient", Native_KickClient },
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
@ -141,14 +141,15 @@ public Action:Cmd_GetDelay(client, args)
|
|||||||
public Action:Cmd_Spectators(client, args)
|
public Action:Cmd_Spectators(client, args)
|
||||||
{
|
{
|
||||||
ReplyToCommand(client, "SourceTV spectator count: %d/%d", SourceTV_GetSpectatorCount(), SourceTV_GetClientCount());
|
ReplyToCommand(client, "SourceTV spectator count: %d/%d", SourceTV_GetSpectatorCount(), SourceTV_GetClientCount());
|
||||||
new String:sName[64];
|
new String:sName[64], String:sIP[16];
|
||||||
for (new i=1;i<=SourceTV_GetClientCount();i++)
|
for (new i=1;i<=SourceTV_GetClientCount();i++)
|
||||||
{
|
{
|
||||||
if (!SourceTV_IsClientConnected(i))
|
if (!SourceTV_IsClientConnected(i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SourceTV_GetSpectatorName(i, sName, sizeof(sName));
|
SourceTV_GetSpectatorName(i, sName, sizeof(sName));
|
||||||
ReplyToCommand(client, "Client %d: %s", i, sName);
|
SourceTV_GetSpectatorIP(i, sIP, sizeof(sIP));
|
||||||
|
ReplyToCommand(client, "Client %d: %s - %s", i, sName, sIP);
|
||||||
}
|
}
|
||||||
return Plugin_Handled;
|
return Plugin_Handled;
|
||||||
}
|
}
|
||||||
|
@ -287,6 +287,30 @@ native bool:SourceTV_IsClientConnected(client);
|
|||||||
*/
|
*/
|
||||||
native SourceTV_GetSpectatorName(client, String:name[], maxlen);
|
native SourceTV_GetSpectatorName(client, String:name[], maxlen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the IP of a SourceTV spectator client.
|
||||||
|
*
|
||||||
|
* @param client The spectator client index.
|
||||||
|
* @param name Buffer for the client ip.
|
||||||
|
* @param maxlen Maximal length of the buffer.
|
||||||
|
* @noreturn
|
||||||
|
* @error Invalid client index or not connected.
|
||||||
|
*/
|
||||||
|
native SourceTV_GetSpectatorIP(client, String:ip[], maxlen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the password of a SourceTV spectator client.
|
||||||
|
* The password the client tried to connect with.
|
||||||
|
* Ignores changes from the SourceTV_OnSpectatorPreConnect forward.
|
||||||
|
*
|
||||||
|
* @param client The spectator client index.
|
||||||
|
* @param name Buffer for the client ip.
|
||||||
|
* @param maxlen Maximal length of the buffer.
|
||||||
|
* @noreturn
|
||||||
|
* @error Invalid client index or not connected.
|
||||||
|
*/
|
||||||
|
native SourceTV_GetSpectatorPassword(client, String:password[], maxlen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kick a SourceTV spectator client.
|
* Kick a SourceTV spectator client.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user