CallAdmin: ready to go

added feature where message to discord is blocked if active admins are in-game
This commit is contained in:
Dogan
2019-10-17 00:01:09 +02:00
parent 77968e36c1
commit ff4daeab8c
14 changed files with 82 additions and 27 deletions
@@ -0,0 +1,715 @@
#if defined _autoexecconfig_included
#endinput
#endif
#define _autoexecconfig_included
#include <sourcemod>
// Append
#define AUTOEXEC_APPEND_BAD_FILENAME 0
#define AUTOEXEC_APPEND_FILE_NOT_FOUND 1
#define AUTOEXEC_APPEND_BAD_HANDLE 2
#define AUTOEXEC_APPEND_SUCCESS 3
// Find
#define AUTOEXEC_FIND_BAD_FILENAME 10
#define AUTOEXEC_FIND_FILE_NOT_FOUND 11
#define AUTOEXEC_FIND_BAD_HANDLE 12
#define AUTOEXEC_FIND_NOT_FOUND 13
#define AUTOEXEC_FIND_SUCCESS 14
// Clean
#define AUTOEXEC_CLEAN_FILE_NOT_FOUND 20
#define AUTOEXEC_CLEAN_BAD_HANDLE 21
#define AUTOEXEC_CLEAN_SUCCESS 22
// General
#define AUTOEXEC_NO_CONFIG 30
// Formatter
#define AUTOEXEC_FORMAT_BAD_FILENAME 40
#define AUTOEXEC_FORMAT_SUCCESS 41
// Global variables
static char g_sConfigFile[PLATFORM_MAX_PATH];
static char g_sRawFileName[PLATFORM_MAX_PATH];
static char g_sFolderPath[PLATFORM_MAX_PATH];
static bool g_bCreateFile = false;
static Handle g_hPluginHandle = null;
// Workaround for now
static int g_iLastFindResult;
static int g_iLastAppendResult;
/**
* Returns the last result from the parser.
*
* @return Returns one of the AUTOEXEC_FIND values or -1 if not set.
*/
stock int AutoExecConfig_GetFindResult()
{
return g_iLastFindResult;
}
/**
* Returns the last result from the appender.
*
* @return Returns one of the AUTOEXEC_APPEND values or -1 if not set.
*/
stock int AutoExecConfig_GetAppendResult()
{
return g_iLastAppendResult;
}
/**
* Set if the config file should be created if it doesn't exist yet.
*
* @param create True if config file should be created, false otherwise.
* @noreturn
*/
stock void AutoExecConfig_SetCreateFile(bool create)
{
g_bCreateFile = create;
}
/**
* Returns if the config file should be created if it doesn't exist.
*
* @return Returns true, if the config file should be created or false if it should not.
*/
stock bool AutoExecConfig_GetCreateFile()
{
return g_bCreateFile;
}
/**
* Set the plugin for which the config file should be created.
* Set to null to use the calling plugin.
* Used to print the correct filename in the top comment when creating the file.
*
* @param plugin The plugin to create convars for or null to use the calling plugin.
* @noreturn
*/
stock void AutoExecConfig_SetPlugin(Handle plugin)
{
g_hPluginHandle = plugin;
}
/**
* Returns the plugin for which the config file is created.
*
* @return The plugin handle
*/
stock Handle AutoExecConfig_GetPlugin()
{
return g_hPluginHandle;
}
/**
* Set the global autoconfigfile used by functions of this file.
*
* @param file Name of the config file, path and .cfg extension is being added if not given.
* @param folder Folder under cfg/ to use. By default this is "sourcemod."
* @return True if formatter returned success, false otherwise.
*/
stock bool AutoExecConfig_SetFile(char[] file, char[] folder="sourcemod")
{
Format(g_sConfigFile, sizeof(g_sConfigFile), "%s", file);
// Global buffers for cfg execution
strcopy(g_sRawFileName, sizeof(g_sRawFileName), file);
strcopy(g_sFolderPath, sizeof(g_sFolderPath), folder);
// Format the filename
return AutoExecConfig_FormatFileName(g_sConfigFile, sizeof(g_sConfigFile), folder) == AUTOEXEC_FORMAT_SUCCESS;
}
/**
* Get the formatted autoconfigfile used by functions of this file.
*
* @param buffer String to format.
* @param size Maximum size of buffer
* @return True if filename was set, false otherwise.
*/
stock bool AutoExecConfig_GetFile(char[] buffer,int size)
{
if(strlen(g_sConfigFile) > 0)
{
strcopy(buffer, size, g_sConfigFile);
return true;
}
// Security for decl users
buffer[0] = '\0';
return false;
}
/**
* Creates a convar and appends it to the autoconfigfile if not found.
* FCVAR_DONTRECORD will be skipped.
*
* @param name Name of new convar.
* @param defaultValue String containing the default value of new convar.
* @param description Optional description of the convar.
* @param flags Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details.
* @param hasMin Optional boolean that determines if the convar has a minimum value.
* @param min Minimum floating point value that the convar can have if hasMin is true.
* @param hasMax Optional boolean that determines if the convar has a maximum value.
* @param max Maximum floating point value that the convar can have if hasMax is true.
* @return A handle to the newly created convar. If the convar already exists, a handle to it will still be returned.
* @error Convar name is blank or is the same as an existing console command.
*/
stock ConVar AutoExecConfig_CreateConVar(const char[] name, const char[] defaultValue, const char[] description="", int flags=0, bool hasMin=false, float min=0.0, bool hasMax=false, float max=0.0)
{
// If configfile was set and convar has no dontrecord flag
if(!(flags & FCVAR_DONTRECORD) && strlen(g_sConfigFile) > 0)
{
// Reset the results
g_iLastFindResult = -1;
g_iLastAppendResult = -1;
// Add it if not found
char buffer[64];
g_iLastFindResult = AutoExecConfig_FindValue(name, buffer, sizeof(buffer), true);
// We only add this convar if it doesn't exist, or the file doesn't exist and it should be auto-generated
if(g_iLastFindResult == AUTOEXEC_FIND_NOT_FOUND || (g_iLastFindResult == AUTOEXEC_FIND_FILE_NOT_FOUND && g_bCreateFile))
{
g_iLastAppendResult = AutoExecConfig_AppendValue(name, defaultValue, description, flags, hasMin, min, hasMax, max);
}
}
// Create the convar
return CreateConVar(name, defaultValue, description, flags, hasMin, min, hasMax, max);
}
/**
* Executes the autoconfigfile, and adds it to the OnConfigsExecuted forward.
* If we didn't created it already we let SourceMod create it.
*
* @noreturn
*/
stock void AutoExecConfig_ExecuteFile()
{
// Only let sourcemod create the file, if we didn't do that already.
AutoExecConfig(!g_bCreateFile, g_sRawFileName, g_sFolderPath);
}
/**
* Formats a autoconfigfile, prefixes path and adds .cfg extension if missed.
*
* @param buffer String to format.
* @param size Maximum size of buffer.
* @return Returns one of the AUTOEXEC_FORMAT values..
*/
stock static int AutoExecConfig_FormatFileName(char[] buffer, int size, char[] folder="sourcemod")
{
// No config set
if(strlen(g_sConfigFile) < 1)
{
return AUTOEXEC_NO_CONFIG;
}
// Can't be an cfgfile
if(StrContains(g_sConfigFile, ".cfg") == -1 && strlen(g_sConfigFile) < 4)
{
return AUTOEXEC_FORMAT_BAD_FILENAME;
}
// Pathprefix
char pathprefixbuffer[PLATFORM_MAX_PATH];
if(strlen(folder) > 0)
{
Format(pathprefixbuffer, sizeof(pathprefixbuffer), "cfg/%s/", folder);
}
else
{
Format(pathprefixbuffer, sizeof(pathprefixbuffer), "cfg/");
}
char filebuffer[PLATFORM_MAX_PATH];
filebuffer[0] = '\0';
// Add path if file doesn't begin with it
if(StrContains(buffer, pathprefixbuffer) != 0)
{
StrCat(filebuffer, sizeof(filebuffer), pathprefixbuffer);
}
StrCat(filebuffer, sizeof(filebuffer), g_sConfigFile);
// Add .cfg extension if file doesn't end with it
if(StrContains(filebuffer[strlen(filebuffer) - 4], ".cfg") != 0)
{
StrCat(filebuffer, sizeof(filebuffer), ".cfg");
}
strcopy(buffer, size, filebuffer);
return AUTOEXEC_FORMAT_SUCCESS;
}
/**
* Appends a convar to the global autoconfigfile
*
* @param name Name of new convar.
* @param defaultValue String containing the default value of new convar.
* @param description Optional description of the convar.
* @param flags Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details.
* @param hasMin Optional boolean that determines if the convar has a minimum value.
* @param min Minimum floating point value that the convar can have if hasMin is true.
* @param hasMax Optional boolean that determines if the convar has a maximum value.
* @param max Maximum floating point value that the convar can have if hasMax is true.
* @return Returns one of the AUTOEXEC_APPEND values
*/
stock int AutoExecConfig_AppendValue(const char[] name, const char[] defaultValue, const char[] description, int flags, bool hasMin, float min, bool hasMax, float max)
{
// No config set
if(strlen(g_sConfigFile) < 1)
{
return AUTOEXEC_NO_CONFIG;
}
char filebuffer[PLATFORM_MAX_PATH];
strcopy(filebuffer, sizeof(filebuffer), g_sConfigFile);
//PrintToServer("pathbuffer: %s", filebuffer);
bool bFileExists = FileExists(filebuffer);
if(g_bCreateFile || bFileExists)
{
// If the file already exists we open it in append mode, otherwise we use a write mode which creates the file
File fFile = OpenFile(filebuffer, (bFileExists ? "a" : "w"));
char writebuffer[2048];
if(fFile == null)
{
return AUTOEXEC_APPEND_BAD_HANDLE;
}
// We just created the file, so add some header about version and stuff
if(g_bCreateFile && !bFileExists)
{
fFile.WriteLine( "// This file was auto-generated by AutoExecConfig read and append beta");
GetPluginFilename(g_hPluginHandle, writebuffer, sizeof(writebuffer));
Format(writebuffer, sizeof(writebuffer), "// ConVars for plugin \"%s\"", writebuffer);
fFile.WriteLine(writebuffer);
}
// Spacer
fFile.WriteLine("\n");
// This is used for multiline comments
int newlines = GetCharCountInStr('\n', description);
if(newlines == 0)
{
// We have no newlines, we can write the description to the file as is
Format(writebuffer, sizeof(writebuffer), "// %s", description);
fFile.WriteLine(writebuffer);
}
else
{
char[][] newlineBuf = new char[newlines +1][2048];
ExplodeString(description, "\n", newlineBuf, newlines +1, 2048, false);
// Each newline gets a commented newline
for(int i; i <= newlines; i++)
{
if(strlen(newlineBuf[i]) > 0)
{
fFile.WriteLine("// %s", newlineBuf[i]);
}
}
}
// Descspacer
fFile.WriteLine("// -");
// Default
Format(writebuffer, sizeof(writebuffer), "// Default: \"%s\"", defaultValue);
fFile.WriteLine(writebuffer);
// Minimum
if(hasMin)
{
Format(writebuffer, sizeof(writebuffer), "// Minimum: \"%f\"", min);
fFile.WriteLine(writebuffer);
}
// Maximum
if(hasMax)
{
Format(writebuffer, sizeof(writebuffer), "// Maximum: \"%f\"", max);
fFile.WriteLine(writebuffer);
}
// Write end and defaultvalue
Format(writebuffer, sizeof(writebuffer), "%s \"%s\"", name, defaultValue);
fFile.WriteLine(writebuffer);
fFile.Close();
// Clean up the file
//AutoExecConfig_CleanFile(filebuffer, false);
return AUTOEXEC_APPEND_SUCCESS;
}
return AUTOEXEC_APPEND_FILE_NOT_FOUND;
}
/**
* Returns a convars value from the global autoconfigfile
*
* @param cvar Cvar to search for.
* @param value Buffer to store result into.
* @param size Maximum size of buffer.
* @param caseSensitive Whether or not the search should be case sensitive.
* @return Returns one of the AUTOEXEC_FIND values
*/
stock int AutoExecConfig_FindValue(const char[] cvar, char[] value, int size, bool caseSensitive=false)
{
// Security for decl users
value[0] = '\0';
// No config set
if(strlen(g_sConfigFile) < 1)
{
return AUTOEXEC_NO_CONFIG;
}
char filebuffer[PLATFORM_MAX_PATH];
strcopy(filebuffer, sizeof(filebuffer), g_sConfigFile);
//PrintToServer("pathbuffer: %s", filebuffer);
bool bFileExists = FileExists(filebuffer);
// We want to create the config file and it doesn't exist yet.
if(g_bCreateFile && !bFileExists)
{
return AUTOEXEC_FIND_FILE_NOT_FOUND;
}
if(bFileExists)
{
File fFile = OpenFile(filebuffer, "r");
int valuestart;
int valueend;
int cvarend;
// Just an reminder to self, leave the values that high
char sConvar[64];
char sValue[64];
char readbuffer[2048];
char copybuffer[2048];
if(fFile == null)
{
return AUTOEXEC_FIND_BAD_HANDLE;
}
while(!fFile.EndOfFile() && fFile.ReadLine(readbuffer, sizeof(readbuffer)))
{
// Is a comment or not valid
if(IsCharSpace(readbuffer[0]) || readbuffer[0] == '/' || !IsCharAlpha(readbuffer[0]))
{
continue;
}
// Has not enough spaces, must have at least 1
if(GetCharCountInStr(' ', readbuffer) < 1)
{
continue;
}
// Ignore cvars which aren't quoted
if(GetCharCountInStr('"', readbuffer) != 2)
{
continue;
}
// Get the start of the value
if( (valuestart = StrContains(readbuffer, "\"")) == -1 )
{
continue;
}
// Get the end of the value
if( (valueend = StrContains(readbuffer[valuestart+1], "\"")) == -1 )
{
continue;
}
// Get the start of the cvar,
if( (cvarend = StrContains(readbuffer, " ")) == -1 || cvarend >= valuestart)
{
continue;
}
// Skip if cvarendindex is before valuestartindex
if(cvarend >= valuestart)
{
continue;
}
// Convar
// Tempcopy for security
strcopy(copybuffer, sizeof(copybuffer), readbuffer);
copybuffer[cvarend] = '\0';
strcopy(sConvar, sizeof(sConvar), copybuffer);
// Value
// Tempcopy for security
strcopy(copybuffer, sizeof(copybuffer), readbuffer[valuestart+1]);
copybuffer[valueend] = '\0';
strcopy(sValue, sizeof(sValue), copybuffer);
//PrintToServer("Cvar %s has a value of %s", sConvar, sValue);
if(StrEqual(sConvar, cvar, caseSensitive))
{
Format(value, size, "%s", sConvar);
fFile.Close();
return AUTOEXEC_FIND_SUCCESS;
}
}
fFile.Close();
return AUTOEXEC_FIND_NOT_FOUND;
}
return AUTOEXEC_FIND_FILE_NOT_FOUND;
}
/**
* Cleans the global autoconfigfile from too much spaces
*
* @return One of the AUTOEXEC_CLEAN values.
*/
stock int AutoExecConfig_CleanFile()
{
// No config set
if(strlen(g_sConfigFile) < 1)
{
return AUTOEXEC_NO_CONFIG;
}
char sfile[PLATFORM_MAX_PATH];
strcopy(sfile, sizeof(sfile), g_sConfigFile);
// Security
if(!FileExists(sfile))
{
return AUTOEXEC_CLEAN_FILE_NOT_FOUND;
}
char sfile2[PLATFORM_MAX_PATH];
Format(sfile2, sizeof(sfile2), "%s_tempcopy", sfile);
char readbuffer[2048];
int count;
bool firstreached;
// Open files
File fFile1 = OpenFile(sfile, "r");
File fFile2 = OpenFile(sfile2, "w");
// Check filehandles
if(fFile1 == null || fFile2 == null)
{
if(fFile1 != null)
{
//PrintToServer("Handle1 invalid");
fFile1.Close();
}
if(fFile2 != null)
{
//PrintToServer("Handle2 invalid");
fFile2.Close();
}
return AUTOEXEC_CLEAN_BAD_HANDLE;
}
while(!fFile1.EndOfFile() && fFile1.ReadLine(readbuffer, sizeof(readbuffer)))
{
// Is space
if(IsCharSpace(readbuffer[0]))
{
count++;
}
// No space, count from start
else
{
count = 0;
}
// Don't write more than 1 space if seperation after informations have been reached
if(count < 2 || !firstreached)
{
ReplaceString(readbuffer, sizeof(readbuffer), "\n", "");
fFile2.WriteLine(readbuffer);
}
// First bigger seperation after informations has been reached
if(count == 2)
{
firstreached = true;
}
}
fFile1.Close();
fFile2.Close();
// This might be a risk, for now it works
DeleteFile(sfile);
RenameFile(sfile, sfile2);
return AUTOEXEC_CLEAN_SUCCESS;
}
/**
* Returns how many times the given char occures in the given string.
*
* @param str String to search for in.
* @return Occurences of the given char found in string.
*/
stock static int GetCharCountInStr(int character, const char[] str)
{
int len = strlen(str);
int count;
for(int i; i < len; i++)
{
if(str[i] == character)
{
count++;
}
}
return count;
}
+289
View File
@@ -0,0 +1,289 @@
/** Include guard */
#if defined _calladmin_included
#endinput
#endif
#define _calladmin_included
/** Global calladmin version, do not change */
#define CALLADMIN_VERSION "0.1.5"
/** Pass this as a clientindex to the ReportPlayer native if you don't have a client, eg report from server automatically */
#define REPORTER_CONSOLE 0
/** Maximum size a reason string can be in length */
#define REASON_MAX_LENGTH 128
/**
* Called when the main CallAdmin client selection menu is about to be drawn for a client.
*
* @param client Client index of the caller.
* @return Plugin_Continue to allow, Plugin_Handled otherwise.
*/
forward Action CallAdmin_OnDrawMenu(int client);
/**
* Called when the own reason selection is enabled and the select item for it is about to be drawn for a client.
*
* @param client Client index of the caller.
* @return Plugin_Continue to allow, Plugin_Handled otherwise.
*/
forward Action CallAdmin_OnDrawOwnReason(int client);
/**
* Called when a target is about to be drawn to the target selection menu for a client.
* Note: Called *n-1 times for the client selection menu where n is the amount of valid targets including the caller.
*
* @param client Client index of the caller.
* @param target Client index of the target about to be drawed.
* @return Plugin_Continue to allow the target to be drawn, Plugin_Handled otherwise.
*/
forward Action CallAdmin_OnDrawTarget(int client, int target);
/**
* Called when the trackercount was changed.
*
* @param oldVal Trackercount before update.
* @param newVal Trackercount after update.
* @noreturn
*/
forward void CallAdmin_OnTrackerCountChanged(int oldVal, int newVal);
/**
* Called before a client (or module) has reported another client.
*
* @param client Client index of the caller.
* @param target Client index of the target.
* @param reason Reason selected by the client for the report.
* @return Plugin_Continue to allow, Plugin_Handled otherwise.
*/
forward Action CallAdmin_OnReportPre(int client, int target, const char[] reason);
/**
* Called after a client (or module) has reported another client.
* Be sure to check that client != REPORTER_CONSOLE if you expect a valid client index.
*
* @param client Client index of the caller.
* @param target Client index of the target.
* @param reason Reason selected by the client for the report.
* @noreturn
*/
forward void CallAdmin_OnReportPost(int client, int target, const char[] reason);
/**
* Initiates an report call.
* If you report automatically (via a module for example) set the clientindex to REPORTER_CONSOLE.
*
* @param client Client index of the caller.
* @param target Client index of the target.
* @param reason Reason for the report.
* @return True if target could be reported, false otherwise.
*/
native bool CallAdmin_ReportClient(int client, int target, const char[] reason);
/**
* Called when an admin is about to be added to the in-game admin count.
*
* @param client Client index of the admin.
* @return Plugin_Continue to allow, Plugin_Handled otherwise.
*/
forward Action CallAdmin_OnAddToAdminCount(int client);
/**
* Returns the cached count of current trackers.
*
* @return Count of current trackers.
*/
native int CallAdmin_GetTrackersCount();
/**
* Requests a forced refresh of the trackers count.
* Note that most modules work asynchronous and only return their own cached count.
*
* @noreturn
*/
native void CallAdmin_RequestTrackersCountRefresh();
/**
* Called when the trackercount of a module is requested.
* This is either called periodically via the base calladmin, or when RequestTrackersCountRefresh is invoked.
*
* @param trackers By ref value of your trackers.
* @noreturn
*/
forward void CallAdmin_OnRequestTrackersCountRefresh(int &trackers);
enum ServerData
{
ServerData_HostName, /**< This is the hostname of the server, gathered from the `hostname` convar */
ServerData_HostIP, /**< This is the hostip of the server, gathered and converted from the `hostip` convar */
ServerData_HostPort /**< This is the hostport of the server, gathered from the `hostport` convar */
};
/**
* Called when the serverdata data is changed.
*
* @param convar Handle to the convar which was changed.
* @param type Type of data which was changed.
* @param oldVal Value of data before change.
* @param newVal Value of data after change.
* @noreturn
*/
forward void CallAdmin_OnServerDataChanged(ConVar convar, ServerData type, const char[] oldVal, const char[] newVal);
/**
* Returns the server's hostname.
*
* @param buffer String to copy hostname to.
* @param max_size Maximum size of buffer.
* @noreturn
*/
native void CallAdmin_GetHostName(char[] buffer, int max_size);
/**
* Returns the server's IP String.
*
* @param buffer String to copy hostip to.
* @param max_size Maximum size of buffer.
* @noreturn
*/
native void CallAdmin_GetHostIP(char[] buffer, int max_size);
/**
* Returns the server's HostPort.
*
* @return Hostport.
*/
native int CallAdmin_GetHostPort();
/**
* Logs a message to the calladmin logfile.
* The message has this format "[Pluginname] Message", where the plugin name is detected automatically.
*
* @param format Formatting rules.
* @param ... Variable number of format parameters.
* @noreturn
*/
native void CallAdmin_LogMessage(const char[] format, any ...);
/**
* Called when a message was logged to the calladmin logfile.
*
* @param plugin Handle to the plugin which logged a message.
* @param message Message which was logged.
* @noreturn
*/
forward void CallAdmin_OnLogMessage(Handle plugin, const char[] message);
/**
* Returns the server's current report id.
* This is a temporary value and is increased with each report.
*
* @return Current report id of the server.
*/
native int CallAdmin_GetReportID();
/**
* Called when a report was handled.
*
* @param client Admin who handled the report.
* @param id ID of the handled report.
* @noreturn
*/
forward void CallAdmin_OnReportHandled(int client, int id);
/* Do not edit below this line */
public SharedPlugin __pl_calladmin =
{
name = "calladmin",
file = "calladmin.smx",
#if defined REQUIRE_PLUGIN
required = 1,
#else
required = 0,
#endif
};
#if !defined REQUIRE_PLUGIN
public __pl_calladmin_SetNTVOptional()
{
MarkNativeAsOptional("CallAdmin_GetTrackersCount");
MarkNativeAsOptional("CallAdmin_RequestTrackersCountRefresh");
MarkNativeAsOptional("CallAdmin_GetHostName");
MarkNativeAsOptional("CallAdmin_GetHostIP");
MarkNativeAsOptional("CallAdmin_GetHostPort");
MarkNativeAsOptional("CallAdmin_ReportClient");
MarkNativeAsOptional("CallAdmin_LogMessage");
MarkNativeAsOptional("CallAdmin_GetReportID");
}
#endif
@@ -0,0 +1,18 @@
/** Include guard */
#if defined _calladmin_stocks_included
#endinput
#endif
#define _calladmin_stocks_included
stock bool IsClientValid(int id)
{
if (id > 0 && id <= MaxClients && IsClientInGame(id))
{
return true;
}
return false;
}
@@ -0,0 +1,83 @@
/** Include guard */
#if defined _calladmin_usermanager_included
#endinput
#endif
#define _calladmin_usermanager_included
/**
* Returns whether a client is immune or not.
* If a client is immune, he can't be reported.
*
* @param client The Client.
* @return True if client is immune, false otherwise.
*/
native bool CallAdmin_IsClientImmune(int client);
/**
* Returns whether a client is on the blacklist or not.
* If a client is on the blacklist, he can't report players.
*
* @param client The Client.
* @return True if client is on blacklist, false otherwise.
*/
native bool CallAdmin_IsClientOnBlacklist(int client);
/**
* Sets whether a client is immune or not.
* If a client is immune, he can't be reported.
*
* @param client The Client.
* @param immune True to immune client, false otherwise.
* @noreturn
*/
native void CallAdmin_SetClientImmune(int client, bool immune);
/**
* Sets whether a client is in the backlist or not.
* If a client is on the blacklist, he can't report players.
*
* @param client The Client.
* @param add True to add client to blacklist, false to remove.
* @noreturn
*/
native void CallAdmin_SetClientOnBlacklist(int client, bool add);
/* Do not edit below this line */
public SharedPlugin __pl_calladmin_usermanager =
{
name = "calladmin_usermanager",
file = "calladmin_usermanager.smx",
#if defined REQUIRE_PLUGIN
required = 1,
#else
required = 0,
#endif
};
#if !defined REQUIRE_PLUGIN
public __pl_calladmin_SetNTVOptional()
{
MarkNativeAsOptional("CallAdmin_SetClientOnBlacklist");
MarkNativeAsOptional("CallAdmin_SetClientImmune");
MarkNativeAsOptional("CallAdmin_IsClientOnBlacklist");
MarkNativeAsOptional("CallAdmin_IsClientImmune");
}
#endif