Add support for sending gameevent to specific client. (#505)
This commit is contained in:
parent
98e8f70424
commit
20c9815619
@ -31,6 +31,8 @@
|
||||
|
||||
#include "EventManager.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "PlayerManager.h"
|
||||
|
||||
#include "logic_bridge.h"
|
||||
#include <bridge/include/IScriptManager.h>
|
||||
|
||||
@ -360,6 +362,13 @@ void EventManager::FireEvent(EventInfo *pInfo, bool bDontBroadcast)
|
||||
m_FreeEvents.push(pInfo);
|
||||
}
|
||||
|
||||
void EventManager::FireEventToClient(EventInfo *pInfo, IClient *pClient)
|
||||
{
|
||||
// The IClient vtable is +4 from the IGameEventListener2 (CBaseClient) vtable due to multiple inheritance.
|
||||
IGameEventListener2 *pGameClient = (IGameEventListener2 *)((intptr_t)pClient - 4);
|
||||
pGameClient->FireGameEvent(pInfo->pEvent);
|
||||
}
|
||||
|
||||
void EventManager::CancelCreatedEvent(EventInfo *pInfo)
|
||||
{
|
||||
/* Free event from IGameEventManager2 */
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include <IForwardSys.h>
|
||||
#include <IPluginSys.h>
|
||||
|
||||
class IClient;
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
struct EventInfo
|
||||
@ -126,6 +128,7 @@ public:
|
||||
EventHookError UnhookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode=EventHookMode_Post);
|
||||
EventInfo *CreateEvent(IPluginContext *pContext, const char *name, bool force=false);
|
||||
void FireEvent(EventInfo *pInfo, bool bDontBroadcast=false);
|
||||
void FireEventToClient(EventInfo *pInfo, IClient *pClient);
|
||||
void CancelCreatedEvent(EventInfo *pInfo);
|
||||
private: // IGameEventManager2 hooks
|
||||
bool OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast);
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "HalfLife2.h"
|
||||
#include <inetchannel.h>
|
||||
#include <iclient.h>
|
||||
#include <iserver.h>
|
||||
#include <IGameConfigs.h>
|
||||
#include "ConsoleDetours.h"
|
||||
#include "logic_bridge.h"
|
||||
@ -2311,10 +2312,9 @@ void CPlayer::DumpAdmin(bool deleting)
|
||||
void CPlayer::Kick(const char *str)
|
||||
{
|
||||
MarkAsBeingKicked();
|
||||
INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(m_iIndex));
|
||||
if (pNetChan == NULL)
|
||||
IClient *pClient = GetIClient();
|
||||
if (pClient == nullptr)
|
||||
{
|
||||
/* What does this even mean? Hell if I know. */
|
||||
int userid = GetUserId();
|
||||
if (userid > 0)
|
||||
{
|
||||
@ -2325,7 +2325,6 @@ void CPlayer::Kick(const char *str)
|
||||
}
|
||||
else
|
||||
{
|
||||
IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
pClient->Disconnect(str);
|
||||
#else
|
||||
@ -2540,6 +2539,26 @@ int CPlayer::GetLifeState()
|
||||
}
|
||||
}
|
||||
|
||||
IClient *CPlayer::GetIClient() const
|
||||
{
|
||||
#if SOURCE_ENGINE == SE_TF2 \
|
||||
|| SOURCE_ENGINE == SE_CSS \
|
||||
|| SOURCE_ENGINE == SE_DODS \
|
||||
|| SOURCE_ENGINE == SE_HL2DM \
|
||||
|| SOURCE_ENGINE == SE_BMS \
|
||||
|| SOURCE_ENGINE == SE_INSURGENCY
|
||||
return engine->GetIServer()->GetClient(m_iIndex - 1);
|
||||
#else
|
||||
INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(m_iIndex));
|
||||
if (pNetChan)
|
||||
{
|
||||
return static_cast<IClient *>(pNetChan->GetMsgHandler());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int CPlayer::GetSerial()
|
||||
{
|
||||
return m_Serial.value;
|
||||
|
@ -48,6 +48,8 @@
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
class IClient;
|
||||
|
||||
#define PLAYER_LIFE_UNKNOWN 0
|
||||
#define PLAYER_LIFE_ALIVE 1
|
||||
#define PLAYER_LIFE_DEAD 2
|
||||
@ -104,6 +106,9 @@ public:
|
||||
void DoBasicAdminChecks();
|
||||
void MarkAsBeingKicked();
|
||||
int GetLifeState();
|
||||
|
||||
// This can be NULL for fakeclients due to limitations in our impl
|
||||
IClient *GetIClient() const;
|
||||
private:
|
||||
void Initialize(const char *name, const char *ip, edict_t *pEntity);
|
||||
void Connect();
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "sm_globals.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include "EventManager.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "logic_bridge.h"
|
||||
|
||||
static cell_t sm_HookEvent(IPluginContext *pContext, const cell_t *params)
|
||||
@ -146,6 +147,54 @@ static cell_t sm_FireEvent(IPluginContext *pContext, const cell_t *params)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t sm_FireEventToClient(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||
HandleError err;
|
||||
EventInfo *pInfo;
|
||||
HandleSecurity sec(pContext->GetIdentity(), g_pCoreIdent);
|
||||
|
||||
if ((err = handlesys->ReadHandle(hndl, g_EventManager.GetHandleType(), &sec, (void **)&pInfo))
|
||||
!= HandleError_None)
|
||||
{
|
||||
return pContext->ThrowNativeError("Invalid game event handle %x (error %d)", hndl, err);
|
||||
}
|
||||
|
||||
/* If identities do not match, don't fire event */
|
||||
if (pContext->GetIdentity() != pInfo->pOwner)
|
||||
{
|
||||
return pContext->ThrowNativeError("Game event \"%s\" could not be fired because it was not created by this plugin", pInfo->pEvent->GetName());
|
||||
}
|
||||
|
||||
if (pInfo->bDontBroadcast)
|
||||
{
|
||||
return pContext->ThrowNativeError("Game event \"%s\" is set to not be broadcasted to clients", pInfo->pEvent->GetName());
|
||||
}
|
||||
|
||||
int client = params[2];
|
||||
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
||||
|
||||
if (!pPlayer)
|
||||
{
|
||||
return pContext->ThrowNativeError("Client index %d is invalid", client);
|
||||
}
|
||||
|
||||
if (!pPlayer->IsConnected())
|
||||
{
|
||||
return pContext->ThrowNativeError("Client %d is not connected", client);
|
||||
}
|
||||
|
||||
IClient *pClient = pPlayer->GetIClient();
|
||||
if (!pClient)
|
||||
{
|
||||
return pContext->ThrowNativeError("Sending events to fakeclients is not supported on this game (client %d)", client);
|
||||
}
|
||||
|
||||
g_EventManager.FireEventToClient(pInfo, pClient);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cell_t sm_CancelCreatedEvent(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||
@ -421,6 +470,7 @@ REGISTER_NATIVES(gameEventNatives)
|
||||
|
||||
// Transitional syntax support.
|
||||
{"Event.Fire", sm_FireEvent},
|
||||
{"Event.FireToClient", sm_FireEventToClient},
|
||||
{"Event.Cancel", sm_CancelCreatedEvent},
|
||||
{"Event.GetName", sm_GetEventName},
|
||||
{"Event.GetBool", sm_GetEventBool},
|
||||
|
@ -79,6 +79,13 @@ methodmap Event < Handle
|
||||
//
|
||||
// @param dontBroadcast Optional boolean that determines if event should be broadcast to clients.
|
||||
public native void Fire(bool dontBroadcast=false);
|
||||
|
||||
// Fires a game event to only the specified client.
|
||||
//
|
||||
// Unlike Fire, this function DOES NOT close the event Handle.
|
||||
//
|
||||
// @param client Index of client to receive the event..
|
||||
public native void FireToClient(int client);
|
||||
|
||||
// Cancels a previously created game event that has not been fired. This
|
||||
// is necessary to avoid leaking memory when an event isn't fired.
|
||||
|
Loading…
Reference in New Issue
Block a user