Add SourceTV_BroadcastChatMessage native
Add option to send messages to locally connected spectators only or to replay proxies as well.
This commit is contained in:
		
							parent
							
								
									c0eb6eb75f
								
							
						
					
					
						commit
						d03b22abf6
					
				
							
								
								
									
										90
									
								
								natives.cpp
									
									
									
									
									
								
							
							
						
						
									
										90
									
								
								natives.cpp
									
									
									
									
									
								
							@ -158,7 +158,48 @@ static cell_t Native_GetDelay(IPluginContext *pContext, const cell_t *params)
 | 
				
			|||||||
	return sp_ftoc(hltvdirector->GetDelay());
 | 
						return sp_ftoc(hltvdirector->GetDelay());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// native bool:SourceTV_BroadcastScreenMessage(const String:format[], any:...);
 | 
					static bool BroadcastEventLocal(IHLTVServer *server, IGameEvent *event, bool bReliable)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static ICallWrapper *pBroadcastEventLocal = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!pBroadcastEventLocal)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							void *addr = nullptr;
 | 
				
			||||||
 | 
							if (!g_pGameConf->GetMemSig("CHLTVServer::BroadcastEventLocal", &addr) || !addr)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								smutils->LogError(myself, "Failed to get CHLTVServer::BroadcastEventLocal signature.");
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							PassInfo pass[2];
 | 
				
			||||||
 | 
							pass[0].flags = PASSFLAG_BYVAL;
 | 
				
			||||||
 | 
							pass[0].type = PassType_Basic;
 | 
				
			||||||
 | 
							pass[0].size = sizeof(IGameEvent *);
 | 
				
			||||||
 | 
							pass[1].flags = PASSFLAG_BYVAL;
 | 
				
			||||||
 | 
							pass[1].type = PassType_Basic;
 | 
				
			||||||
 | 
							pass[1].size = sizeof(bool);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pBroadcastEventLocal = bintools->CreateCall(addr, CallConv_ThisCall, NULL, pass, 2);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pBroadcastEventLocal)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							unsigned char vstk[sizeof(void *) + sizeof(IGameEvent *) + sizeof(bool)];
 | 
				
			||||||
 | 
							unsigned char *vptr = vstk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*(void **)vptr = (void *)server;
 | 
				
			||||||
 | 
							vptr += sizeof(void *);
 | 
				
			||||||
 | 
							*(IGameEvent **)vptr = event;
 | 
				
			||||||
 | 
							vptr += sizeof(char *);
 | 
				
			||||||
 | 
							*(bool *)vptr = bReliable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pBroadcastEventLocal->Execute(vstk, NULL);
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// native bool:SourceTV_BroadcastScreenMessage(bool:bLocalOnly, const String:format[], any:...);
 | 
				
			||||||
static cell_t Native_BroadcastScreenMessage(IPluginContext *pContext, const cell_t *params)
 | 
					static cell_t Native_BroadcastScreenMessage(IPluginContext *pContext, const cell_t *params)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (hltvserver == nullptr)
 | 
						if (hltvserver == nullptr)
 | 
				
			||||||
@ -168,7 +209,7 @@ static cell_t Native_BroadcastScreenMessage(IPluginContext *pContext, const cell
 | 
				
			|||||||
	size_t len;
 | 
						size_t len;
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		DetectExceptions eh(pContext);
 | 
							DetectExceptions eh(pContext);
 | 
				
			||||||
		len = smutils->FormatString(buffer, sizeof(buffer), pContext, params, 1);
 | 
							len = smutils->FormatString(buffer, sizeof(buffer), pContext, params, 2);
 | 
				
			||||||
		if (eh.HasException())
 | 
							if (eh.HasException())
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -178,10 +219,17 @@ static cell_t Native_BroadcastScreenMessage(IPluginContext *pContext, const cell
 | 
				
			|||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	msg->SetString("text", buffer);
 | 
						msg->SetString("text", buffer);
 | 
				
			||||||
	hltvserver->BroadcastEvent(msg);
 | 
					
 | 
				
			||||||
 | 
						int ret = 1;
 | 
				
			||||||
 | 
						bool bLocalOnly = params[1] != 0;
 | 
				
			||||||
 | 
						if (bLocalOnly)
 | 
				
			||||||
 | 
							hltvserver->BroadcastEvent(msg);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ret = BroadcastEventLocal(hltvserver, msg, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gameevents->FreeEvent(msg);
 | 
						gameevents->FreeEvent(msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 1;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// native bool:SourceTV_BroadcastConsoleMessage(const String:format[], any:...);
 | 
					// native bool:SourceTV_BroadcastConsoleMessage(const String:format[], any:...);
 | 
				
			||||||
@ -250,6 +298,39 @@ static cell_t Native_BroadcastConsoleMessage(IPluginContext *pContext, const cel
 | 
				
			|||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// native bool:SourceTV_BroadcastChatMessage(bool:bLocalOnly, const String:format[], any:...);
 | 
				
			||||||
 | 
					static cell_t Native_BroadcastChatMessage(IPluginContext *pContext, const cell_t *params)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (hltvserver == nullptr)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char buffer[1024];
 | 
				
			||||||
 | 
						size_t len;
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							DetectExceptions eh(pContext);
 | 
				
			||||||
 | 
							len = smutils->FormatString(buffer, sizeof(buffer), pContext, params, 2);
 | 
				
			||||||
 | 
							if (eh.HasException())
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						IGameEvent *msg = gameevents->CreateEvent("hltv_chat", true);
 | 
				
			||||||
 | 
						if (!msg)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg->SetString("text", buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int ret = 1;
 | 
				
			||||||
 | 
						bool bLocalOnly = params[1] != 0;
 | 
				
			||||||
 | 
						if (bLocalOnly)
 | 
				
			||||||
 | 
							hltvserver->BroadcastEvent(msg);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ret = BroadcastEventLocal(hltvserver, msg, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gameevents->FreeEvent(msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// native SourceTV_GetViewEntity();
 | 
					// native SourceTV_GetViewEntity();
 | 
				
			||||||
static cell_t Native_GetViewEntity(IPluginContext *pContext, const cell_t *params)
 | 
					static cell_t Native_GetViewEntity(IPluginContext *pContext, const cell_t *params)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -659,6 +740,7 @@ const sp_nativeinfo_t sourcetv_natives[] =
 | 
				
			|||||||
	{ "SourceTV_GetDelay", Native_GetDelay },
 | 
						{ "SourceTV_GetDelay", Native_GetDelay },
 | 
				
			||||||
	{ "SourceTV_BroadcastScreenMessage", Native_BroadcastScreenMessage },
 | 
						{ "SourceTV_BroadcastScreenMessage", Native_BroadcastScreenMessage },
 | 
				
			||||||
	{ "SourceTV_BroadcastConsoleMessage", Native_BroadcastConsoleMessage },
 | 
						{ "SourceTV_BroadcastConsoleMessage", Native_BroadcastConsoleMessage },
 | 
				
			||||||
 | 
						{ "SourceTV_BroadcastChatMessage", Native_BroadcastChatMessage },
 | 
				
			||||||
	{ "SourceTV_GetViewEntity", Native_GetViewEntity },
 | 
						{ "SourceTV_GetViewEntity", Native_GetViewEntity },
 | 
				
			||||||
	{ "SourceTV_GetViewOrigin", Native_GetViewOrigin },
 | 
						{ "SourceTV_GetViewOrigin", Native_GetViewOrigin },
 | 
				
			||||||
	{ "SourceTV_ForceFixedCameraShot", Native_ForceFixedCameraShot },
 | 
						{ "SourceTV_ForceFixedCameraShot", Native_ForceFixedCameraShot },
 | 
				
			||||||
 | 
				
			|||||||
@ -15,6 +15,8 @@ public OnPluginStart()
 | 
				
			|||||||
	RegConsoleCmd("sm_getdelay", Cmd_GetDelay);
 | 
						RegConsoleCmd("sm_getdelay", Cmd_GetDelay);
 | 
				
			||||||
	RegConsoleCmd("sm_spectators", Cmd_Spectators);
 | 
						RegConsoleCmd("sm_spectators", Cmd_Spectators);
 | 
				
			||||||
	RegConsoleCmd("sm_spechintmsg", Cmd_SendHintMessage);
 | 
						RegConsoleCmd("sm_spechintmsg", Cmd_SendHintMessage);
 | 
				
			||||||
 | 
						RegConsoleCmd("sm_specchat", Cmd_SendChatMessage);
 | 
				
			||||||
 | 
						RegConsoleCmd("sm_specchatlocal", Cmd_SendChatMessageLocal);
 | 
				
			||||||
	RegConsoleCmd("sm_specmsg", Cmd_SendMessage);
 | 
						RegConsoleCmd("sm_specmsg", Cmd_SendMessage);
 | 
				
			||||||
	RegConsoleCmd("sm_viewentity", Cmd_GetViewEntity);
 | 
						RegConsoleCmd("sm_viewentity", Cmd_GetViewEntity);
 | 
				
			||||||
	RegConsoleCmd("sm_vieworigin", Cmd_GetViewOrigin);
 | 
						RegConsoleCmd("sm_vieworigin", Cmd_GetViewOrigin);
 | 
				
			||||||
@ -166,7 +168,7 @@ public Action:Cmd_SendHintMessage(client, args)
 | 
				
			|||||||
	GetCmdArgString(sMsg, sizeof(sMsg));
 | 
						GetCmdArgString(sMsg, sizeof(sMsg));
 | 
				
			||||||
	StripQuotes(sMsg);
 | 
						StripQuotes(sMsg);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	new bool:bSent = SourceTV_BroadcastScreenMessage("%s", sMsg);
 | 
						new bool:bSent = SourceTV_BroadcastScreenMessage(false, "%s", sMsg);
 | 
				
			||||||
	ReplyToCommand(client, "SourceTV sending hint message (success %d): %s", bSent, sMsg);
 | 
						ReplyToCommand(client, "SourceTV sending hint message (success %d): %s", bSent, sMsg);
 | 
				
			||||||
	return Plugin_Handled;
 | 
						return Plugin_Handled;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -188,6 +190,40 @@ public Action:Cmd_SendMessage(client, args)
 | 
				
			|||||||
	return Plugin_Handled;
 | 
						return Plugin_Handled;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public Action:Cmd_SendChatMessage(client, args)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (args < 1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ReplyToCommand(client, "Usage: sm_specchat <message>");
 | 
				
			||||||
 | 
							return Plugin_Handled;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						new String:sMsg[128];
 | 
				
			||||||
 | 
						GetCmdArgString(sMsg, sizeof(sMsg));
 | 
				
			||||||
 | 
						StripQuotes(sMsg);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						new bool:bSent = SourceTV_BroadcastChatMessage(false, "%s", sMsg);
 | 
				
			||||||
 | 
						ReplyToCommand(client, "SourceTV sending chat message to all spectators (including relays) (success %d): %s", bSent, sMsg);
 | 
				
			||||||
 | 
						return Plugin_Handled;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public Action:Cmd_SendChatMessageLocal(client, args)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (args < 1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ReplyToCommand(client, "Usage: sm_specchatlocal <message>");
 | 
				
			||||||
 | 
							return Plugin_Handled;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						new String:sMsg[128];
 | 
				
			||||||
 | 
						GetCmdArgString(sMsg, sizeof(sMsg));
 | 
				
			||||||
 | 
						StripQuotes(sMsg);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						new bool:bSent = SourceTV_BroadcastChatMessage(true, "%s", sMsg);
 | 
				
			||||||
 | 
						ReplyToCommand(client, "SourceTV sending chat message to local spectators (success %d): %s", bSent, sMsg);
 | 
				
			||||||
 | 
						return Plugin_Handled;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public Action:Cmd_GetViewEntity(client, args)
 | 
					public Action:Cmd_GetViewEntity(client, args)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ReplyToCommand(client, "SourceTV view entity: %d", SourceTV_GetViewEntity());
 | 
						ReplyToCommand(client, "SourceTV view entity: %d", SourceTV_GetViewEntity());
 | 
				
			||||||
 | 
				
			|||||||
@ -70,6 +70,14 @@
 | 
				
			|||||||
				// ping(CCommand const&) "Client ping times:\n"
 | 
									// ping(CCommand const&) "Client ping times:\n"
 | 
				
			||||||
				"windows" "\x55\x8B\xEC\x83\xE4\xC0\x83\xEC\x34\x83\x3D\x2A\x2A\x2A\x2A\x01\x53\x56\x57\x75\x2A"
 | 
									"windows" "\x55\x8B\xEC\x83\xE4\xC0\x83\xEC\x34\x83\x3D\x2A\x2A\x2A\x2A\x01\x53\x56\x57\x75\x2A"
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								"CHLTVServer::BroadcastEventLocal"
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									"library"	"engine"
 | 
				
			||||||
 | 
									"linux"	"@_ZN11CHLTVServer19BroadcastEventLocalEP10IGameEventb"
 | 
				
			||||||
 | 
									// "SourceTV broadcast local event: %s\n"
 | 
				
			||||||
 | 
									"windows"	"\x55\x8B\xEC\x83\xEC\x4C\x53\x8B\xD9\xC7\x45\xB4\x2A\x2A\x2A\x2A\x56\x8D"
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	"cstrike"
 | 
						"cstrike"
 | 
				
			||||||
@ -154,6 +162,14 @@
 | 
				
			|||||||
				// ping(CCommand const&) "Client ping times:\n"
 | 
									// ping(CCommand const&) "Client ping times:\n"
 | 
				
			||||||
				"windows" "\x55\x8B\xEC\x51\x83\x3D\x2A\x2A\x2A\x2A\x01\x75\x2A"
 | 
									"windows" "\x55\x8B\xEC\x51\x83\x3D\x2A\x2A\x2A\x2A\x01\x75\x2A"
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								"CHLTVServer::BroadcastEventLocal"
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									"library"	"engine"
 | 
				
			||||||
 | 
									"linux"	"@_ZN11CHLTVServer19BroadcastEventLocalEP10IGameEventb"
 | 
				
			||||||
 | 
									// "SourceTV broadcast local event: %s\n"
 | 
				
			||||||
 | 
									"windows"	"\x55\x8B\xEC\x81\xEC\x44\x04\x00\x00\x53"
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -92,11 +92,12 @@ native Float:SourceTV_GetDelay();
 | 
				
			|||||||
 * Print a center message to all SourceTV spectators for ~2 seconds.
 | 
					 * Print a center message to all SourceTV spectators for ~2 seconds.
 | 
				
			||||||
 * Like the tv_msg command.
 | 
					 * Like the tv_msg command.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @param bLocalOnly	Send only to directly connected spectators or proxies as well?
 | 
				
			||||||
 * @param format	The format string.
 | 
					 * @param format	The format string.
 | 
				
			||||||
 * @param ...	Variable number of format string arguments.
 | 
					 * @param ...	Variable number of format string arguments.
 | 
				
			||||||
 * @return	True if message was sent, false otherwise.
 | 
					 * @return	True if message was sent, false otherwise.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
native bool:SourceTV_BroadcastScreenMessage(const String:format[], any:...);
 | 
					native bool:SourceTV_BroadcastScreenMessage(bool:bLocalOnly, const String:format[], any:...);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Prints text to the console of all connected SourceTV spectators.
 | 
					 * Prints text to the console of all connected SourceTV spectators.
 | 
				
			||||||
@ -107,7 +108,15 @@ native bool:SourceTV_BroadcastScreenMessage(const String:format[], any:...);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
native bool:SourceTV_BroadcastConsoleMessage(const String:format[], any:...);
 | 
					native bool:SourceTV_BroadcastConsoleMessage(const String:format[], any:...);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Print a chat message to all SourceTV spectators.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param bLocalOnly	Send only to directly connected spectators or proxies as well?
 | 
				
			||||||
 | 
					 * @param format	The format string.
 | 
				
			||||||
 | 
					 * @param ...	Variable number of format string arguments.
 | 
				
			||||||
 | 
					 * @return	True if message was sent, false otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					native bool:SourceTV_BroadcastChatMessage(bool:bLocalOnly, const String:format[], any:...);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/********************************************************************************
 | 
					/********************************************************************************
 | 
				
			||||||
@ -393,6 +402,7 @@ public __ext_stvmngr_SetNTVOptional()
 | 
				
			|||||||
	MarkNativeAsOptional("SourceTV_GetDelay");
 | 
						MarkNativeAsOptional("SourceTV_GetDelay");
 | 
				
			||||||
	MarkNativeAsOptional("SourceTV_BroadcastScreenMessage");
 | 
						MarkNativeAsOptional("SourceTV_BroadcastScreenMessage");
 | 
				
			||||||
	MarkNativeAsOptional("SourceTV_BroadcastConsoleMessage");
 | 
						MarkNativeAsOptional("SourceTV_BroadcastConsoleMessage");
 | 
				
			||||||
 | 
						MarkNativeAsOptional("SourceTV_BroadcastChatMessage");
 | 
				
			||||||
	MarkNativeAsOptional("SourceTV_GetViewEntity");
 | 
						MarkNativeAsOptional("SourceTV_GetViewEntity");
 | 
				
			||||||
	MarkNativeAsOptional("SourceTV_GetViewOrigin");
 | 
						MarkNativeAsOptional("SourceTV_GetViewOrigin");
 | 
				
			||||||
	MarkNativeAsOptional("SourceTV_ForceFixedCameraShot");
 | 
						MarkNativeAsOptional("SourceTV_ForceFixedCameraShot");
 | 
				
			||||||
@ -408,6 +418,8 @@ public __ext_stvmngr_SetNTVOptional()
 | 
				
			|||||||
	MarkNativeAsOptional("SourceTV_GetClientCount");
 | 
						MarkNativeAsOptional("SourceTV_GetClientCount");
 | 
				
			||||||
	MarkNativeAsOptional("SourceTV_IsClientConnected");
 | 
						MarkNativeAsOptional("SourceTV_IsClientConnected");
 | 
				
			||||||
	MarkNativeAsOptional("SourceTV_GetSpectatorName");
 | 
						MarkNativeAsOptional("SourceTV_GetSpectatorName");
 | 
				
			||||||
 | 
						MarkNativeAsOptional("SourceTV_GetSpectatorIP");
 | 
				
			||||||
 | 
						MarkNativeAsOptional("SourceTV_GetSpectatorPassword");
 | 
				
			||||||
	MarkNativeAsOptional("SourceTV_KickClient");
 | 
						MarkNativeAsOptional("SourceTV_KickClient");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user