437 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
			
		
		
	
	
			437 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
#include "GameEvents.inc"
 | 
						|
#include "Forwards.inc"
 | 
						|
 | 
						|
#define MAX_SUBSCRIBERS MAX_CLIENTS
 | 
						|
 | 
						|
enum
 | 
						|
{
 | 
						|
	eSubscribeError_OutOfRange = -1,
 | 
						|
	eSubscribeError_Inactive = -2,
 | 
						|
	eSubscribeError_GameEvent = -3,
 | 
						|
	eSubscribeError_Forward = -4,
 | 
						|
}
 | 
						|
 | 
						|
static bool g_Subscriber_Active[MAX_SUBSCRIBERS] = { false, ... };
 | 
						|
static int g_Subscriber_Client[MAX_SUBSCRIBERS] = { -1, ... };
 | 
						|
 | 
						|
static ArrayList g_Subscriber_GameEvents[MAX_SUBSCRIBERS];
 | 
						|
static ArrayList g_Subscriber_Forwards[MAX_SUBSCRIBERS];
 | 
						|
 | 
						|
bool Subscribe_OnPluginStart()
 | 
						|
{
 | 
						|
	GameEvents_Init();
 | 
						|
}
 | 
						|
 | 
						|
int Subscriber_Create(int Client)
 | 
						|
{
 | 
						|
	int Index = Client;
 | 
						|
	if(Index < 0 || Index >= MAX_SUBSCRIBERS || g_Subscriber_Active[Index])
 | 
						|
	{
 | 
						|
		Index = GetFreeSubscriberIndex();
 | 
						|
		if(Index == eSubscribeError_OutOfRange)
 | 
						|
			return eSubscribeError_OutOfRange;
 | 
						|
	}
 | 
						|
 | 
						|
	g_Subscriber_Active[Index] = true;
 | 
						|
	g_Subscriber_Client[Index] = Client;
 | 
						|
 | 
						|
	g_Subscriber_GameEvents[Index] = new ArrayList(ByteCountToCells(32));
 | 
						|
	g_Subscriber_Forwards[Index] = new ArrayList(ByteCountToCells(32));
 | 
						|
 | 
						|
	return Index;
 | 
						|
}
 | 
						|
 | 
						|
int Subscriber_Destroy(int Index)
 | 
						|
{
 | 
						|
	if(Index < 0 || Index >= MAX_SUBSCRIBERS)
 | 
						|
		return eSubscribeError_OutOfRange;
 | 
						|
 | 
						|
	if(!g_Subscriber_Active[Index])
 | 
						|
		return eSubscribeError_Inactive;
 | 
						|
 | 
						|
	for(int i = 0; i < g_Subscriber_GameEvents[Index].Length; i++)
 | 
						|
	{
 | 
						|
		static char sEventName[32];
 | 
						|
		g_Subscriber_GameEvents[Index].GetString(i, sEventName, sizeof(sEventName));
 | 
						|
		GameEvents_Unhook(sEventName);
 | 
						|
	}
 | 
						|
 | 
						|
	delete g_Subscriber_GameEvents[Index];
 | 
						|
	delete g_Subscriber_Forwards[Index];
 | 
						|
 | 
						|
	g_Subscriber_Active[Index] = false;
 | 
						|
	g_Subscriber_Client[Index] = -1;
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int Subscriber_HandleRequest(int Index, JSONObject Request, JSONObject Response)
 | 
						|
{
 | 
						|
	static char sMethod[32];
 | 
						|
	Request.GetString("method", sMethod, sizeof(sMethod));
 | 
						|
 | 
						|
	static char sModule[32];
 | 
						|
	if(Request.GetString("module", sModule, sizeof(sModule)) < 0)
 | 
						|
	{
 | 
						|
		JSONObject jError = new JSONObject();
 | 
						|
		jError.SetString("error", "Request has no 'module' string-value.");
 | 
						|
		Response.Set("error", jError);
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	Response.SetString("module", sModule);
 | 
						|
 | 
						|
	if(StrEqual(sModule, "gameevents"))
 | 
						|
	{
 | 
						|
		JSONArray EventArray = view_as<JSONArray>(Request.Get("events"));
 | 
						|
		if(EventArray == null || !EventArray.IsArray)
 | 
						|
		{
 | 
						|
			delete EventArray;
 | 
						|
			JSONObject jError = new JSONObject();
 | 
						|
			jError.SetString("error", "Request has no 'events' array-value.");
 | 
						|
			Response.Set("error", jError);
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
 | 
						|
		int Method = 0;
 | 
						|
		if(StrEqual(sMethod, "subscribe"))
 | 
						|
			Method = 1;
 | 
						|
		else if(StrEqual(sMethod, "unsubscribe"))
 | 
						|
			Method = 2;
 | 
						|
		else if(StrEqual(sMethod, "replay"))
 | 
						|
			Method = 3;
 | 
						|
 | 
						|
		JSONArray EventArrayResponse = new JSONArray();
 | 
						|
 | 
						|
		for(int i = 0; i < EventArray.Length; i++)
 | 
						|
		{
 | 
						|
			static char sEventName[32];
 | 
						|
			if(EventArray.GetString(i, sEventName, sizeof(sEventName)) < 0)
 | 
						|
			{
 | 
						|
				JSONObject jError = new JSONObject();
 | 
						|
				jError.SetString("error", "not a string-value");
 | 
						|
				EventArrayResponse.Append(jError);
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
 | 
						|
			int Res;
 | 
						|
			if(Method == 1)
 | 
						|
				Res = Subscribe_GameEvents_Subscribe(Index, sEventName);
 | 
						|
			else if(Method == 2)
 | 
						|
				Res = Subscribe_GameEvents_Unsubscribe(Index, sEventName);
 | 
						|
			else if(Method == 3)
 | 
						|
				Res = Subscribe_GameEvents_Replay(Index, sEventName);
 | 
						|
 | 
						|
			EventArrayResponse.AppendInt(Res);
 | 
						|
		}
 | 
						|
		delete EventArray;
 | 
						|
 | 
						|
		Response.Set("events", EventArrayResponse);
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
	else if(StrEqual(sModule, "forwards"))
 | 
						|
	{
 | 
						|
		JSONArray EventArray = view_as<JSONArray>(Request.Get("events"));
 | 
						|
		if(EventArray == null || !EventArray.IsArray)
 | 
						|
		{
 | 
						|
			delete EventArray;
 | 
						|
			JSONObject jError = new JSONObject();
 | 
						|
			jError.SetString("error", "Request has no 'events' array-value.");
 | 
						|
			Response.Set("error", jError);
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
 | 
						|
		int Method = 0;
 | 
						|
		if(StrEqual(sMethod, "subscribe"))
 | 
						|
			Method = 1;
 | 
						|
		else if(StrEqual(sMethod, "unsubscribe"))
 | 
						|
			Method = 2;
 | 
						|
		else if(StrEqual(sMethod, "replay"))
 | 
						|
			Method = 3;
 | 
						|
 | 
						|
		JSONArray EventArrayResponse = new JSONArray();
 | 
						|
 | 
						|
		for(int i = 0; i < EventArray.Length; i++)
 | 
						|
		{
 | 
						|
			static char sEventName[32];
 | 
						|
			if(EventArray.GetString(i, sEventName, sizeof(sEventName)) < 0)
 | 
						|
			{
 | 
						|
				JSONObject jError = new JSONObject();
 | 
						|
				jError.SetString("error", "not a string-value");
 | 
						|
				EventArrayResponse.Append(jError);
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
 | 
						|
			int Res;
 | 
						|
			if(Method == 1)
 | 
						|
				Res = Subscribe_Forwards_Subscribe(Index, sEventName);
 | 
						|
			else if(Method == 2)
 | 
						|
				Res = Subscribe_Forwards_Unsubscribe(Index, sEventName);
 | 
						|
			else if(Method == 3)
 | 
						|
				Res = Subscribe_Forwards_Replay(Index, sEventName);
 | 
						|
 | 
						|
			EventArrayResponse.AppendInt(Res);
 | 
						|
		}
 | 
						|
		delete EventArray;
 | 
						|
 | 
						|
		Response.Set("events", EventArrayResponse);
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	JSONObject jError = new JSONObject();
 | 
						|
	jError.SetString("error", "No handler found for requested module.");
 | 
						|
	Response.Set("error", jError);
 | 
						|
	return -1;
 | 
						|
}
 | 
						|
 | 
						|
static int GetFreeSubscriberIndex()
 | 
						|
{
 | 
						|
	for(int i = 0; i < MAX_SUBSCRIBERS; i++)
 | 
						|
	{
 | 
						|
		if(!g_Subscriber_Active[i])
 | 
						|
			return i;
 | 
						|
	}
 | 
						|
	return eSubscribeError_OutOfRange;
 | 
						|
}
 | 
						|
 | 
						|
/* GameEvents */
 | 
						|
static int Subscribe_GameEvents_Subscribe(int Index, const char[] sEventName)
 | 
						|
{
 | 
						|
	if(Index < 0 || Index >= MAX_SUBSCRIBERS)
 | 
						|
		return eSubscribeError_OutOfRange;
 | 
						|
 | 
						|
	if(!g_Subscriber_Active[Index])
 | 
						|
		return eSubscribeError_Inactive;
 | 
						|
 | 
						|
	int Find = g_Subscriber_GameEvents[Index].FindString(sEventName);
 | 
						|
	if(Find != -1)
 | 
						|
		return Find;
 | 
						|
 | 
						|
	if(GameEvents_Hook(sEventName) < 0)
 | 
						|
		return eSubscribeError_GameEvent;
 | 
						|
 | 
						|
	return g_Subscriber_GameEvents[Index].PushString(sEventName);
 | 
						|
}
 | 
						|
 | 
						|
static int Subscribe_GameEvents_Unsubscribe(int Index, const char[] sEventName)
 | 
						|
{
 | 
						|
	if(Index < 0 || Index >= MAX_SUBSCRIBERS)
 | 
						|
		return eSubscribeError_OutOfRange;
 | 
						|
 | 
						|
	if(!g_Subscriber_Active[Index])
 | 
						|
		return eSubscribeError_Inactive;
 | 
						|
 | 
						|
	int Find = g_Subscriber_GameEvents[Index].FindString(sEventName);
 | 
						|
	if(Find == -1)
 | 
						|
		return 0;
 | 
						|
 | 
						|
	if(GameEvents_Unhook(sEventName) < 0)
 | 
						|
		return eSubscribeError_GameEvent;
 | 
						|
 | 
						|
	g_Subscriber_GameEvents[Index].Erase(Find);
 | 
						|
	return Find;
 | 
						|
}
 | 
						|
 | 
						|
static int Subscribe_GameEvents_Replay(int Index, const char[] sEventName)
 | 
						|
{
 | 
						|
	if(Index < 0 || Index >= MAX_SUBSCRIBERS)
 | 
						|
		return eSubscribeError_OutOfRange;
 | 
						|
 | 
						|
	if(!g_Subscriber_Active[Index])
 | 
						|
		return eSubscribeError_Inactive;
 | 
						|
 | 
						|
	if(StrEqual(sEventName, "player_connect"))
 | 
						|
	{
 | 
						|
		for(int client = 1; client <= MaxClients; client++)
 | 
						|
		{
 | 
						|
			if(!IsClientConnected(client))
 | 
						|
				continue;
 | 
						|
 | 
						|
			char sName[MAX_NAME_LENGTH];
 | 
						|
			GetClientName(client, sName, sizeof(sName));
 | 
						|
 | 
						|
			char sSteamID[32];
 | 
						|
			GetClientAuthId(client, AuthId_Engine, sSteamID, sizeof(sSteamID), false);
 | 
						|
 | 
						|
			char sAddress[32];
 | 
						|
			GetClientIP(client, sAddress, sizeof(sAddress), false);
 | 
						|
 | 
						|
			JSONObject jEventData = new JSONObject();
 | 
						|
			jEventData.SetString("name", sName);
 | 
						|
			jEventData.SetInt("index", client - 1);
 | 
						|
			jEventData.SetInt("userid", GetClientUserId(client));
 | 
						|
			jEventData.SetString("networkid", sSteamID);
 | 
						|
			jEventData.SetString("address", sAddress);
 | 
						|
			jEventData.SetBool("bot", IsFakeClient(client));
 | 
						|
 | 
						|
			Subscribe_GameEvents_FakePublish(g_Subscriber_Client[Index], sEventName, jEventData);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	else if(StrEqual(sEventName, "player_activate"))
 | 
						|
	{
 | 
						|
		for(int client = 1; client <= MaxClients; client++)
 | 
						|
		{
 | 
						|
			if(!IsClientInGame(client))
 | 
						|
				continue;
 | 
						|
 | 
						|
			JSONObject jEventData = new JSONObject();
 | 
						|
			jEventData.SetInt("userid", GetClientUserId(client));
 | 
						|
 | 
						|
			Subscribe_GameEvents_FakePublish(g_Subscriber_Client[Index], sEventName, jEventData);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	else
 | 
						|
		return eSubscribeError_GameEvent;
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int Subscribe_GameEvents_FakePublish(int Index, const char[] sEventName, JSONObject jEventData)
 | 
						|
{
 | 
						|
	if(Index < 0 || Index >= MAX_SUBSCRIBERS)
 | 
						|
		return eSubscribeError_OutOfRange;
 | 
						|
 | 
						|
	if(!g_Subscriber_Active[Index])
 | 
						|
		return eSubscribeError_Inactive;
 | 
						|
 | 
						|
	JSONObject jEvent = new JSONObject();
 | 
						|
	jEvent.SetString("name", sEventName);
 | 
						|
	jEvent.Set("data", jEventData);
 | 
						|
 | 
						|
	JSONObject jPublish = new JSONObject();
 | 
						|
	jPublish.SetString("method", "publish");
 | 
						|
	jPublish.SetString("module", "gameevents");
 | 
						|
	jPublish.Set("event", jEvent);
 | 
						|
 | 
						|
	PublishEvent(g_Subscriber_Client[Index], jPublish);
 | 
						|
	delete jPublish;
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
void Subscribe_GameEvents_Publish(const char[] sEventName, JSONObject jEvent)
 | 
						|
{
 | 
						|
	JSONObject jPublish = new JSONObject();
 | 
						|
	jPublish.SetString("method", "publish");
 | 
						|
	jPublish.SetString("module", "gameevents");
 | 
						|
	jPublish.Set("event", jEvent);
 | 
						|
 | 
						|
	for(int Index = 0; Index < MAX_SUBSCRIBERS; Index++)
 | 
						|
	{
 | 
						|
		if(!g_Subscriber_Active[Index])
 | 
						|
			continue;
 | 
						|
 | 
						|
		if(g_Subscriber_GameEvents[Index].FindString(sEventName) == -1)
 | 
						|
			continue;
 | 
						|
 | 
						|
		PublishEvent(g_Subscriber_Client[Index], jPublish);
 | 
						|
	}
 | 
						|
 | 
						|
	delete jPublish;
 | 
						|
}
 | 
						|
/* GameEvents */
 | 
						|
 | 
						|
/* Forwards */
 | 
						|
static int Subscribe_Forwards_Subscribe(int Index, const char[] sEventName)
 | 
						|
{
 | 
						|
	if(Index < 0 || Index >= MAX_SUBSCRIBERS)
 | 
						|
		return eSubscribeError_OutOfRange;
 | 
						|
 | 
						|
	if(!g_Subscriber_Active[Index])
 | 
						|
		return eSubscribeError_Inactive;
 | 
						|
 | 
						|
	int Find = g_Subscriber_Forwards[Index].FindString(sEventName);
 | 
						|
	if(Find != -1)
 | 
						|
		return Find;
 | 
						|
 | 
						|
	// TODO: forward exists?
 | 
						|
 | 
						|
	return g_Subscriber_Forwards[Index].PushString(sEventName);
 | 
						|
}
 | 
						|
 | 
						|
static int Subscribe_Forwards_Unsubscribe(int Index, const char[] sEventName)
 | 
						|
{
 | 
						|
	if(Index < 0 || Index >= MAX_SUBSCRIBERS)
 | 
						|
		return eSubscribeError_OutOfRange;
 | 
						|
 | 
						|
	if(!g_Subscriber_Active[Index])
 | 
						|
		return eSubscribeError_Inactive;
 | 
						|
 | 
						|
	int Find = g_Subscriber_Forwards[Index].FindString(sEventName);
 | 
						|
	if(Find == -1)
 | 
						|
		return 0;
 | 
						|
 | 
						|
	g_Subscriber_Forwards[Index].Erase(Find);
 | 
						|
	return Find;
 | 
						|
}
 | 
						|
 | 
						|
static int Subscribe_Forwards_Replay(int Index, const char[] sEventName)
 | 
						|
{
 | 
						|
	if(Index < 0 || Index >= MAX_SUBSCRIBERS)
 | 
						|
		return eSubscribeError_OutOfRange;
 | 
						|
 | 
						|
	if(!g_Subscriber_Active[Index])
 | 
						|
		return eSubscribeError_Inactive;
 | 
						|
 | 
						|
	if(StrEqual(sEventName, "OnClientPostAdminCheck"))
 | 
						|
	{
 | 
						|
		for(int client = 1; client <= MaxClients; client++)
 | 
						|
		{
 | 
						|
			if(!IsClientInGame(client) || !IsClientAuthorized(client))
 | 
						|
				continue;
 | 
						|
 | 
						|
			JSONObject jEventData = new JSONObject();
 | 
						|
			jEventData.SetInt("client", client);
 | 
						|
 | 
						|
			Subscribe_Forwards_FakePublish(g_Subscriber_Client[Index], sEventName, jEventData);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	else
 | 
						|
		return eSubscribeError_Forward;
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int Subscribe_Forwards_FakePublish(int Index, const char[] sEventName, JSONObject jEventData)
 | 
						|
{
 | 
						|
	if(Index < 0 || Index >= MAX_SUBSCRIBERS)
 | 
						|
		return eSubscribeError_OutOfRange;
 | 
						|
 | 
						|
	if(!g_Subscriber_Active[Index])
 | 
						|
		return eSubscribeError_Inactive;
 | 
						|
 | 
						|
	JSONObject jEvent = new JSONObject();
 | 
						|
	jEvent.SetString("name", sEventName);
 | 
						|
	jEvent.Set("data", jEventData);
 | 
						|
 | 
						|
	JSONObject jPublish = new JSONObject();
 | 
						|
	jPublish.SetString("method", "publish");
 | 
						|
	jPublish.SetString("module", "forwards");
 | 
						|
	jPublish.Set("event", jEvent);
 | 
						|
 | 
						|
	PublishEvent(g_Subscriber_Client[Index], jPublish);
 | 
						|
	delete jPublish;
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
void Subscribe_Forwards_Publish(const char[] sEventName, JSONObject jEvent)
 | 
						|
{
 | 
						|
	JSONObject jPublish = new JSONObject();
 | 
						|
	jPublish.SetString("method", "publish");
 | 
						|
	jPublish.SetString("module", "forwards");
 | 
						|
	jPublish.Set("event", jEvent);
 | 
						|
 | 
						|
	for(int Index = 0; Index < MAX_SUBSCRIBERS; Index++)
 | 
						|
	{
 | 
						|
		if(!g_Subscriber_Active[Index])
 | 
						|
			continue;
 | 
						|
 | 
						|
		if(g_Subscriber_Forwards[Index].FindString(sEventName) == -1)
 | 
						|
			continue;
 | 
						|
 | 
						|
		PublishEvent(g_Subscriber_Client[Index], jPublish);
 | 
						|
	}
 | 
						|
 | 
						|
	delete jPublish;
 | 
						|
}
 | 
						|
/* Forwards */
 |