Good to hear, Mordekay. The new version has been posted. Thanks again, Shadows Adi.
If the certificate is not found when the plugin loads, it will fail with the below:
Code:
L 02/01/2021 - 21:59:42: [AMXX] Plugin says: curl SSL certificate not found.
Place here: cstrike/addons/amxmodx/data/curl_cert/cacert.pem
Visit: https://curl.se/docs/caextract.html
Hi Bugsy ;) Thanks for release. I've tried plugin and got server dump.
LINUX PuTTy console:
L 02/03/2021 - 150:12: [AMXX] Run time error 5: memory access
L 02/03/2021 - 150:12: [AMXX] [0] vacbans.sma::ResponseReceived (line 749)
Floating point exception (core dumped)
Hi Bugsy ;) Thanks for release. I've tried plugin and got server dump.
LINUX PuTTy console:
L 02/03/2021 - 150:12: [AMXX] Run time error 5: memory access
L 02/03/2021 - 150:12: [AMXX] [0] vacbans.sma::ResponseReceived (line 749)
Floating point exception (core dumped)
Using beta plugin
Thanks for the report, please try the below and provide the logs when the error occurs.
size=# num_memb=# buffer len=#
Also, after doing that, try replacing
PHP Code:
return ( iSize * iNumMemb );
with
PHP Code:
return ( iNumMemb );
Spoiler
PHP Code:
/*
VAC Ban Status by bugsy
Description: This plugin will check if a steam account has ever been VAC banned. Checking an account can be done in 2 ways; manually via console and auto. Auto checking will automatically check a player either when they first connect to the server or when they join a team. To specify when a player is checked, set the cvar vbs_vaccheck to the appropriate value (default: 0 [on connect]). If a VAC ban is found on a players steam account then the selected punishment will be issued on player. There are 5 punishments to choose from (see below enum) which can be defined by cvar vbs_punishment (default: 0 [log only]). Punishments can be issued either when a VAC ban status is found or when the player reaches a specified kill\death ratio. To make a punishment be issued when the player reaches a specified kill-death ratio, select the appropriate punishment below. Each punishment named KDRATIO will be issued once the player reaches the kill\death ratio. To specify the kill-death ratio, set it in the cvar vbs_kdratio (default 3 [3:1]). You can also specify a minimum kills value for when the plugin will start to check a players kill\death ratio; to set this value set cvar vbs_kdminkills to the appropriate value (default: 15 [kills]). When auto-checking is enabled, the server will check the VAC ban status on the steam server and save the ban status value to the database. If the player is not banned, the database entry is added with a timestamp that will expire in the number of days defined in cvar vbs_expiredays (default: 15 [days]). This will prevent a plugin from having to constantly re-check a player everytime they connect. When the entry expires, they will get re-checked on the steam server on their next connection. If a VAC ban is found on a steam account, the database is permanent and will never expire. If a player connects that has a positive VAC ban status saved to the database, the selected punishment will be issued. There is a whitelisting system that allows you to whitelist particular players steam accounts. This will make the plugin not recognize them as being VAC banned and they will be immune to the plugin until they are removed from the whitelist.
Usage: [command] [parameter] [description] amx_vacban <name\steamid> Check a players VAC ban status amx_vacclearall Clear all entries from database amx_vacclearnotbanned Clear all non-VAC banned entries from database amx_vacremoveentry <name\steamid> Remove an entry from database amx_vacaddwhitelist <name\steamid> Add a player to whitelist. Player will be considered not banned. amx_vacremovewhitelist <name\steamid> Remove a player from whitelist. amx_vacquery <name\steamid> Query the database for a players VAC ban status
Database Storage: [key] [val] [storage duration] [description] STEAMID 1 <timestamped> Player not VAC banned STEAMID 2 <permanent> Player VAC banned STEAMID 3 <permanent> Player whitelisted with no VAC ban STEAMID 4 <permanent> Player whitelisted with VAC ban
ChangeLog v0.41 - 02/01/2021 - Added write buffer size curl option so curl does not use the default buffer size. - Added a return value in the write function. This allows the data to come in multiple packets. Without this, the plugin was only receiving one packets worth of data. - Added error buffer curl option and error trapping (set_fail_state()) if the curl request fails. - Added SSL certificate curl option. Thanks to Shadows Adi for the find. v0.4 - 01/23/2021 - Changed from sockets to cURL v0.3 - Improved speed of checking by increasing incoming data buffer size to 4096. Defined by BUFFER_SIZE - I noticed at times particular steam id checks would not work. I found that depending on the size of the users steam community page, the incoming data was sometimes cut off in the middle of a string/phrase we are looking for. For example, if we are looking for "<vacBanned>1" for ban status. One packet would have "<vacB" and the following packet would start with "anned>1" causing the plugin to not notice the ban string. Now, when data is received it is added to the previously received data so the detection strings can be checked within the entire buffer. - Fixed bug where if you try to manually check a SteamID and accidentally have a space on the end it would print out checking SteamID []. - Replaced set_user_hitzones with fm_set_user_hitzones. Removed fun module, fakemeta is now required. - Revised\improved DeathMsg code for applying punishment based on kill\death ratio. - Changed punishment and notify admin flag selection to cvar. - Added cvar to specify the seconds used to consider a connection to steam server as timedout. The cvar that specifies the time out is vbs_sockettimeout [default 5.0] - Added KICK_BAN_ID_KDRATIO and KICK_BAN_IP_KDRATIO, these were both accidentally not coded. - Added punishment function so all punishments are issued in one place instead of having them coded multiple times. - Added cvar to specify the time period to ban a player when a ban punishment is used. vbs_bantime [default: 0] - Added clear all command to clear the database of all entries (everything, including both VAC banned\unbanned status and whitelist entries). Note: You cannot clear all whitelisted or all VAC banned without clearing the entire db. - Added clear non VAC banned command to clear database of entires that are not VAC banned (VAC banned and whitelist entries will remain in database). Command: amx_vacclearall - Added whitelist system so you can whitelist a steamid\player. When whitelisted, the player will be treated as if they have no VAC ban and will not get checked. The whitelist entry is permanent and will not be cleared unless done so manually with the amx_vacremovewhitelist or amx_vacclearall command. Commands: amx_vacaddwhitelist , amx_vacremovewhitelist - Added query command so you can manually check a players entry in the db. Command: amx_vacquery - Added display of time that a manual VAC ban status check took with steam server. - Added cvar to set when a player is auto-checked vbs_vaccheck [default: 0] 0=on connect, 1=team join [T\CT only] - Switched back to regular sockets module as sockets_hz didn't solve the lag issue. - Added error checking when opening vault. Since almost every function of the plugin uses vault communication, if the vault does not open properly then the plugin cannot function as it was designed to. If an error is found when opening the nvault file, the plugin will fail and report an error in log. - Corrected AMXBan usage. - Added usage of config file (vacbanstatus.cfg)
v0.2b - Changed get_gametime() to get_systime() for nvault pruning. - Change socket module to sockets_hz to prevent the game from freezing slightly when a new player connects to server. - Made few optimizations suggested by hawk552 */
//Global vars new g_VACBanned[ MAX_PLAYERS + 1 ]; //1 if VAC banned new g_Punished[ MAX_PLAYERS + 1 ]; //1 when player punished new g_ShootsBlanks[ MAX_PLAYERS + 1 ]; //1 if player shoots blanks new g_JoinedTeam[ MAX_PLAYERS + 1 ]; //1 when joins a team (T or CT) new g_IsBot[ MAX_PLAYERS + 1 ]; //1 if player is bot new g_NotifyFlag[ MAX_PLAYERS + 1 ]; //1 if user has notify admin flag new g_FMTraceLine; //FM traceline forward handle. new g_NumShootsBlanks; //# of players who shoot blanks. new g_Vault; //nVault handle new g_MaxPlayers; //Max players server holds new g_szSteamName[ MAX_PLAYERS + 1 ][65]; //Steam community name new g_szFriendID[ MAX_PLAYERS + 1 ][65]; //Steam community ID# new g_szAuthID[ MAX_PLAYERS + 1 ][35]; //Steam ID new g_szName[ MAX_PLAYERS + 1 ][33]; //Name new g_BodyHits[ MAX_PLAYERS + 1 ][33]; //For fm_set_user_hitzones
enum _:RequestData { RequestorID, PlayerID, RequestType, SteamID64[ 32 ] } new g_CurlRequests[ CURL:33 ][ RequestData ]; //Request ID (handle of curl request) const CURL_BUFFERSIZE = 4096; new g_szCurlErrorBuffer[ CURL_ERROR_SIZE ]; new g_szCurlSSLCert[ 64 ];
//Cvar pointers new g_pAutoCheck; //CVAR Enable\disable autocheck new g_pVACCheck; //CVAR Specifies when to check player (0=connect or 1=team join) new g_pExpireDays; //CVAR Days at which a saved VAC ban is removed new g_pKDRatio; //CVAR Kill\Death ratio used for kdratio punishments new g_pKDMin; //CVAR Min kills required before checking kdratios new g_pPunishment; //CVAR Type of punishment to issue new g_pBanTime; //CVAR Number of minutes a player is banned for ban punishments new g_pNotifyFlag; //CVAR Notify flag required for notifications
public plugin_init() { register_plugin( "VAC Ban Status" , Version , "bugsy" ); register_cvar( "VAC Ban Status" , Version , FCVAR_SERVER , 0.0 );
register_concmd( "amx_vacban" , "CommandHandler" , ADMIN_BAN , "<Player\SteamID> - Check if player\steamid is VAC banned." ); register_concmd( "amx_vacquery" , "CommandHandler" , ADMIN_BAN , "<Player\SteamID>- Query a player\steamid database entry." ); register_concmd( "amx_vacaddwhitelist" , "CommandHandler" , ADMIN_BAN , "<Player\SteamID>- Add player\steamid to whitelist." ); register_concmd( "amx_vacremovewhitelist" , "CommandHandler" , ADMIN_BAN , "<Player\SteamID>- Remove player\steamid from whitelist." ); register_concmd( "amx_vacremoveentry" , "CommandHandler" , ADMIN_BAN , "<Player\SteamID>- Remove VAC ban status from database." ); register_concmd( "amx_vacclearall" , "CommandHandler" , ADMIN_BAN , "- Clear all database entries" ); register_concmd( "amx_vacclearnotbanned" , "CommandHandler" , ADMIN_BAN , "- Clear database entries for players that are not VAC banned." );
public client_connect( id ) { fm_hitzones_reset( id ); }
public client_putinserver( id ) { if ( ( g_IsBot[ id ] = is_user_bot( id ) ) ) return PLUGIN_CONTINUE;
//Get users name and steamid and store it in global variable so it will //not need to be retrieved again if needed later. get_user_name( id , g_szName[ id ] , charsmax( g_szName[] ) ); get_user_authid( id , g_szAuthID[ id ], charsmax( g_szAuthID[] ) );
//For testing with a known banned steamid //if ( id == get_user_index("bugsy") ) // g_szAuthID[id] = "STEAM_0:0:100";
//If auto-checking and check-on-connect are enabled, check player for VAC ban if ( get_pcvar_num( g_pAutoCheck ) && !get_pcvar_num( g_pVACCheck ) ) AutoCheckPlayer(id);
//An admin has connected, check if has the required admin flag needed for notification. //If so, notify him of any players that are connected that have a VAC ban on record. if ( is_user_admin( id ) ) { new szFlag[2]; get_pcvar_string( g_pNotifyFlag , szFlag , 1 );
//If player has admin flag specified in cvar vbs_notifyflag if ( ( g_NotifyFlag[ id ] = ( get_user_flags( id ) & read_flags( szFlag ) ) ) ) set_task( 8.0 , "NotifyAdmin" , id ); }
return PLUGIN_CONTINUE; }
public fwPlayerJoinedTeam() { new id = read_data( 1 );
#if AMXX_VERSION_NUM < 190 public client_disconnect( id ) #else public client_disconnected( id ) #endif { if( g_IsBot[ id ] ) return PLUGIN_CONTINUE;
if ( g_ShootsBlanks[ id ] ) SetShootBlanks( id , 0 );
//Clear all vars for player index g_szSteamName[ id ][ 0 ] = EOS; g_szFriendID[ id ][ 0 ] = EOS; g_szAuthID[ id ][ 0 ] = EOS; g_szName[ id ][ 0 ] = EOS; g_VACBanned[ id ] = 0; g_JoinedTeam[ id ] = 0; g_NotifyFlag[ id ] = 0; g_Punished[ id ] = 0;
return PLUGIN_CONTINUE; }
public AutoCheckPlayer(id) { new iBanVal = nvault_get( g_Vault , g_szAuthID[ id ] );
//No entry exists in database for player, send VAC check request to steam server if ( iBanVal == NO_DB_ENTRY ) { SendRequest( 0 , id , AUTO_CHECK ); } //Entry found in database and player is VAC banned, punish and notify admins else if ( iBanVal == BANNED ) { static szHUD[ 256 ]; new iPlayers[ 32 ]; new iPlayersNum; new iPlayer;
g_VACBanned[ id ] = 1;
get_players( iPlayers , iPlayersNum , "c" );
formatex( szHUD , charsmax( szHUD ) , "[VAC Ban Status]^n^n%s has a VAC ban on record. [Database]^nSteamID: %s" , g_szName[ id ] , g_szAuthID[ id ] ); set_hudmessage( 255 , 255 , 255 , 0.10 , 0.35 , 0 , 2.0 , 4.0 , 0.5 , 0.5 , 3 );
//Notify all connected admins that this player has connected and is banned for ( new i = 0 ; ( i < iPlayersNum ) ; i++ ) { iPlayer = iPlayers[ i ]; if ( g_NotifyFlag[ iPlayer ] ) { show_hudmessage( iPlayer , szHUD ); client_cmd( iPlayer , "spk buttons/blip1.wav" ); } }
//If punishment is not a kd-ratio punishment, issue punishment now. new iPunishment = get_pcvar_num( g_pPunishment );
if ( iPunishment <= SHOOTBLANKS ) { //VAC check done on client connect so we need a little pause to allow player to //fully initialize into game or else some punishments will not work. if ( !get_pcvar_num( g_pVACCheck ) ) { new params[ 2 ]; params[ 0 ] = id; params[ 1 ] = iPunishment; set_task( 0.5 , "DelayPunishment" , _ , params , sizeof( params ) ); } else { PunishPlayer( id , iPunishment ); } } } }
if ( equal( szCmd , "amx_vacclearnotbanned" ) ) { nvault_prune( g_Vault , 0 , get_systime() ); console_print( id , "*[VAC BAN Status] All non VAC banned entries have been cleared." );
if ( delete_file( szVaultFile ) ) { if ( ( g_Vault = nvault_open( VAULT ) ) != INVALID_HANDLE ) { console_print( id , "*[VAC Ban Status] Database successfully cleared." ); return PLUGIN_HANDLED; } }
set_fail_state( "Error clearing nvault" );
return PLUGIN_HANDLED; }
new iPlayer; new szVal[2]; new iBanVal; new iTimestamp; new szArgs[46]; new iRequestType;
read_args( szArgs , charsmax( szArgs ) );
//The below commands all require a parameter (name\steamid) so we determine which is //being specified by the user. if( !equali( szArgs , "STEAM_0:" , 8 ) ) { iPlayer = cmd_target( id , szArgs , ( CMDTARGET_ALLOW_SELF | CMDTARGET_NO_BOTS ) );
if ( equal( szCmd , "amx_vacban" ) ) { //if( g_Socket[id] ) //{ // console_print( id , "*[VAC Ban Status] Previous check still in progress, try again when it completes." ); // return PLUGIN_HANDLED; //}
if ( iPlayer ) { console_print( id , "*[VAC Ban Status] Checking %s [%s]." , g_szName[iPlayer] , g_szAuthID[iPlayer] ); iRequestType = MANUAL_NAME; } else { console_print( id , "*[VAC Ban Status] Checking SteamID [%s]." , g_szAuthID[iPlayer] ); iRequestType = MANUAL_STEAMID; }
SendRequest( id , iPlayer , iRequestType );
return PLUGIN_HANDLED; } else if ( equal( szCmd , "amx_vacquery" ) ) { switch ( iBanVal ) { case NO_DB_ENTRY: console_print( id , "*[VAC Ban Status] Query: No entry exists in database for %s." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] ); case NOT_BANNED: { new Float:fExpireDays = ( ( get_pcvar_float( g_pExpireDays ) * 86400.0 ) - ( float(get_systime()) - float(iTimestamp) ) ) / 86400.0; console_print( id , "*[VAC Ban Status] Query: %s is not VAC banned. Entry expires in %d days." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] , floatround(fExpireDays) ); } case BANNED: console_print( id , "*[VAC Ban Status] Query: %s has a VAC ban on record." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] ); case NOT_BANNED_WHITELIST: console_print( id , "*[VAC Ban Status] Query: %s is whitelisted with no VAC ban on record." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] ); case BANNED_WHITELIST: console_print( id , "*[VAC Ban Status] Query: %s is whitelisted with a VAC ban on record." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] ); }
return PLUGIN_HANDLED; } else if ( equal( szCmd , "amx_vacaddwhitelist" ) ) { if ( iBanVal <= BANNED ) { if ( !iBanVal ) iBanVal = NOT_BANNED;
console_print( id , "*[VAC Ban Status] %s has been whitelisted." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] ); } else { console_print( id , "*[VAC Ban Status] %s is already on the whitelist." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] ); }
return PLUGIN_HANDLED; }
//The below commands involve removing existing entries so we verify that an entry exists first. if ( !iBanVal ) { console_print( id , "*[VAC Ban Status] No database entry exists for %s." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] ); return PLUGIN_HANDLED; }
if ( equal( szCmd , "amx_vacremoveentry" ) ) { //Player has VAC status in db and is not whitelisted if ( iBanVal <= BANNED ) { nvault_remove( g_Vault , g_szAuthID[iPlayer] ); console_print( id , "*[VAC Ban Status] VAC ban database entry for %s was removed." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] ); } else { console_print( id , "*[VAC Ban Status] %s is whitelisted, must use amx_vacremovewhitelist command." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] ); } } else if ( equal( szCmd , "amx_vacremovewhitelist" ) ) { //Player is on whitelist, set appropriate ban status by subtracting 2 from whitelist status if ( iBanVal >= NOT_BANNED_WHITELIST ) { szVal[0] = '0' + ( iBanVal - 2 );
console_print( id , "*[VAC Ban Status] %s was removed from the whitelist; player is%s VAC banned." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] , ( iBanVal == NOT_BANNED_WHITELIST ) ? " not" : "" ); } else { console_print( id , "*[VAC Ban Status] %s has an entry in the db but is not whitelisted. Use amx_vacremoveentry command" , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] ); } }
return PLUGIN_HANDLED; }
public NotifyAdmin( id ) { static szNames[513]; new iPlayers[32]; new iPlayersNum; new iPlayer; new iPos; new iFound;
iPos = formatex( szNames , 512 , "[VAC Ban Status]^nThe following players have^na VAC ban on record:^n^n" );
get_players( iPlayers , iPlayersNum , "c" );
//Cycle through all players and create a list of VAC banned players for ( new i = 0 ; i < iPlayersNum ; i++ ) { iPlayer = iPlayers[ i ];
} case MANUAL_NAME: console_print( id , "*[VAC Ban Status] %s is not VAC banned." , g_szName[ idCheck ] ); case MANUAL_STEAMID: console_print( id , "*[VAC Ban Status] SteamID [%s] is not VAC banned." , g_szAuthID[ idCheck ] ); } }
public PunishPlayer( id , iPunishment ) { new szMsg[ 30 ];
g_Punished[id] = 1;
switch ( iPunishment ) { case LOG_ONLY: { return PLUGIN_HANDLED; } case KICK_ONLY: { KickPlayer( id , "[VAC Ban Status]", "A VAC ban record was found on your steam account." , "You have been kicked" ) ; formatex( szMsg , charsmax( szMsg ) , "was kicked" ); } case KICK_BAN_ID: { server_cmd("amx_ban ^"#%d^" ^"%d^" ^"VAC Banned^"" , get_user_userid( id ) , get_pcvar_num( g_pBanTime ) ); formatex( szMsg , charsmax( szMsg ) , "was kicked and banned" ); } case KICK_BAN_IP: { server_cmd( "amx_banip ^"#%d^" ^"%d^" ^"VAC Banned^"" , get_user_userid( id ) , get_pcvar_num( g_pBanTime ) ); formatex( szMsg , charsmax( szMsg ) , "was kicked and banned" ); } case KICK_AMXBAN: { server_cmd( "amx_ban %d %s VAC Banned", get_pcvar_num( g_pBanTime ) , g_szAuthID[ id ] ); formatex( szMsg , charsmax( szMsg ) , "was kicked and banned" ); } case SHOOTBLANKS: { SetShootBlanks( id , 1 ); formatex( szMsg , charsmax( szMsg ) , "will now shoot blanks" ); } }
new iPlayers[ 32 ]; new iPlayersNum; new iPlayer;
get_players( iPlayers, iPlayersNum , "c" );
for ( new i = 0 ; i < iPlayersNum ; i++ ) { iPlayer = iPlayers[ i ];
if ( g_NotifyFlag[ iPlayer ] ) client_print( iPlayer , print_chat , "[VAC Ban Status] %s %s for being VAC banned%s" , g_szName[ id ] , szMsg , ( get_pcvar_num( g_pPunishment ) >= 6 ) ? " with a high kill:death ratio." : "." ); }
return PLUGIN_HANDLED; }
public SetShootBlanks( id , iVal ) { //iVal = 1 - Set shoot blanks on player and enable traceline forward if not yet enabled. //iVal = 0 - Remove shoot blanks for player id and disable forward if no other players shoot blanks.
public fm_set_user_hitzones(index, target, body) { if ( !index && !target ) { for ( new i = 1 ; i <= g_MaxPlayers ; i++ ) for (new j = 1 ; j <= g_MaxPlayers ; j++ ) g_BodyHits[i][j] = body; } else if ( !index && target ) { for ( new i = 1 ; i <= g_MaxPlayers ; i++ ) g_BodyHits[i][target] = body; } else if ( index && !target ) { for ( new i = 1 ; i <= g_MaxPlayers ; i++ ) g_BodyHits[index][i] = body; } else if ( index && target ) { g_BodyHits[index][target] = body; } }
public fm_hitzones_reset(index) { for ( new i = 1 ; i <= g_MaxPlayers ; i++ ) { g_BodyHits[index][i] = (1<<HIT_GENERIC) | (1<<HIT_HEAD) | (1<<HIT_CHEST) | (1<<HIT_STOMACH) | (1<<HIT_LEFTARM) | (1<<HIT_RIGHTARM)| (1<<HIT_LEFTLEG) | (1<<HIT_RIGHTLEG); }
}
// Credit to Teyut for multi-line kick message KickPlayer( target , szReason[] , szLine2[] , szLine3[] ) { static msg_content[1024];
// AuthID + Base Number + Server Number NumString_Add(szSteamID,szFriendsBaseNum,szSteamID,charsmax(szSteamID)); NumString_Add(szSteamID,szServer,szSteamID,charsmax(szSteamID));
Thanks for the report, please try the below and provide the logs when the error occurs.
size=# num_memb=# buffer len=#
Also, after doing that, try replacing
PHP Code:
return ( iSize * iNumMemb );
with
PHP Code:
return ( iNumMemb );
Spoiler
PHP Code:
/*
VAC Ban Status
by bugsy
Description:
This plugin will check if a steam account has ever been VAC banned. Checking an account can be done in 2
ways; manually via console and auto. Auto checking will automatically check a player either when they
first connect to the server or when they join a team. To specify when a player is checked, set the cvar
vbs_vaccheck to the appropriate value (default: 0 [on connect]). If a VAC ban is found on a players
steam account then the selected punishment will be issued on player. There are 5 punishments to choose
from (see below enum) which can be defined by cvar vbs_punishment (default: 0 [log only]). Punishments can
be issued either when a VAC ban status is found or when the player reaches a specified kill\death ratio.
To make a punishment be issued when the player reaches a specified kill-death ratio, select the appropriate
punishment below. Each punishment named KDRATIO will be issued once the player reaches the kill\death
ratio. To specify the kill-death ratio, set it in the cvar vbs_kdratio (default 3 [3:1]). You can also
specify a minimum kills value for when the plugin will start to check a players kill\death ratio; to set
this value set cvar vbs_kdminkills to the appropriate value (default: 15 [kills]). When auto-checking is
enabled, the server will check the VAC ban status on the steam server and save the ban status value to the
database. If the player is not banned, the database entry is added with a timestamp that will expire in the
number of days defined in cvar vbs_expiredays (default: 15 [days]). This will prevent a plugin from having
to constantly re-check a player everytime they connect. When the entry expires, they will get re-checked on
the steam server on their next connection. If a VAC ban is found on a steam account, the database is permanent
and will never expire. If a player connects that has a positive VAC ban status saved to the database, the
selected punishment will be issued. There is a whitelisting system that allows you to whitelist particular
players steam accounts. This will make the plugin not recognize them as being VAC banned and they will be
immune to the plugin until they are removed from the whitelist.
Usage:
[command] [parameter] [description]
amx_vacban <name\steamid> Check a players VAC ban status
amx_vacclearall Clear all entries from database
amx_vacclearnotbanned Clear all non-VAC banned entries from database
amx_vacremoveentry <name\steamid> Remove an entry from database
amx_vacaddwhitelist <name\steamid> Add a player to whitelist. Player will be considered not banned.
amx_vacremovewhitelist <name\steamid> Remove a player from whitelist.
amx_vacquery <name\steamid> Query the database for a players VAC ban status
Database Storage:
[key] [val] [storage duration] [description]
STEAMID 1 <timestamped> Player not VAC banned
STEAMID 2 <permanent> Player VAC banned
STEAMID 3 <permanent> Player whitelisted with no VAC ban
STEAMID 4 <permanent> Player whitelisted with VAC ban
ChangeLog
v0.41 - 02/01/2021
- Added write buffer size curl option so curl does not use the default buffer size.
- Added a return value in the write function. This allows the data to come in multiple packets. Without this,
the plugin was only receiving one packets worth of data.
- Added error buffer curl option and error trapping (set_fail_state()) if the curl request fails.
- Added SSL certificate curl option. Thanks to Shadows Adi for the find.
v0.4 - 01/23/2021
- Changed from sockets to cURL
v0.3
- Improved speed of checking by increasing incoming data buffer size to 4096. Defined by BUFFER_SIZE
- I noticed at times particular steam id checks would not work. I found that depending on the size of
the users steam community page, the incoming data was sometimes cut off in the middle of a string/phrase
we are looking for. For example, if we are looking for "<vacBanned>1" for ban status. One packet would
have "<vacB" and the following packet would start with "anned>1" causing the plugin to not notice the
ban string. Now, when data is received it is added to the previously received data so the detection strings
can be checked within the entire buffer.
- Fixed bug where if you try to manually check a SteamID and accidentally have a space on the end it would
print out checking SteamID [].
- Replaced set_user_hitzones with fm_set_user_hitzones. Removed fun module, fakemeta is now required.
- Revised\improved DeathMsg code for applying punishment based on kill\death ratio.
- Changed punishment and notify admin flag selection to cvar.
- Added cvar to specify the seconds used to consider a connection to steam server as timedout. The cvar that
specifies the time out is vbs_sockettimeout [default 5.0]
- Added KICK_BAN_ID_KDRATIO and KICK_BAN_IP_KDRATIO, these were both accidentally not coded.
- Added punishment function so all punishments are issued in one place instead of having them coded multiple
times.
- Added cvar to specify the time period to ban a player when a ban punishment is used. vbs_bantime [default: 0]
- Added clear all command to clear the database of all entries (everything, including both VAC banned\unbanned status
and whitelist entries). Note: You cannot clear all whitelisted or all VAC banned without clearing the entire db.
- Added clear non VAC banned command to clear database of entires that are not VAC banned (VAC banned and whitelist
entries will remain in database). Command: amx_vacclearall
- Added whitelist system so you can whitelist a steamid\player. When whitelisted, the player will be treated as if
they have no VAC ban and will not get checked. The whitelist entry is permanent and will not be cleared unless
done so manually with the amx_vacremovewhitelist or amx_vacclearall command.
Commands: amx_vacaddwhitelist , amx_vacremovewhitelist
- Added query command so you can manually check a players entry in the db. Command: amx_vacquery
- Added display of time that a manual VAC ban status check took with steam server.
- Added cvar to set when a player is auto-checked vbs_vaccheck [default: 0] 0=on connect, 1=team join [T\CT only]
- Switched back to regular sockets module as sockets_hz didn't solve the lag issue.
- Added error checking when opening vault. Since almost every function of the plugin uses vault communication, if
the vault does not open properly then the plugin cannot function as it was designed to. If an error is found when
opening the nvault file, the plugin will fail and report an error in log.
- Corrected AMXBan usage.
- Added usage of config file (vacbanstatus.cfg)
v0.2b
- Changed get_gametime() to get_systime() for nvault pruning.
- Change socket module to sockets_hz to prevent the game from freezing slightly when a new player connects to
server.
- Made few optimizations suggested by hawk552
*/
//Global vars
new g_VACBanned[ MAX_PLAYERS + 1 ]; //1 if VAC banned
new g_Punished[ MAX_PLAYERS + 1 ]; //1 when player punished
new g_ShootsBlanks[ MAX_PLAYERS + 1 ]; //1 if player shoots blanks
new g_JoinedTeam[ MAX_PLAYERS + 1 ]; //1 when joins a team (T or CT)
new g_IsBot[ MAX_PLAYERS + 1 ]; //1 if player is bot
new g_NotifyFlag[ MAX_PLAYERS + 1 ]; //1 if user has notify admin flag
new g_FMTraceLine; //FM traceline forward handle.
new g_NumShootsBlanks; //# of players who shoot blanks.
new g_Vault; //nVault handle
new g_MaxPlayers; //Max players server holds
new g_szSteamName[ MAX_PLAYERS + 1 ][65]; //Steam community name
new g_szFriendID[ MAX_PLAYERS + 1 ][65]; //Steam community ID#
new g_szAuthID[ MAX_PLAYERS + 1 ][35]; //Steam ID
new g_szName[ MAX_PLAYERS + 1 ][33]; //Name
new g_BodyHits[ MAX_PLAYERS + 1 ][33]; //For fm_set_user_hitzones
enum _:RequestData
{
RequestorID,
PlayerID,
RequestType,
SteamID64[ 32 ]
}
new g_CurlRequests[ CURL:33 ][ RequestData ]; //Request ID (handle of curl request)
const CURL_BUFFERSIZE = 4096;
new g_szCurlErrorBuffer[ CURL_ERROR_SIZE ];
new g_szCurlSSLCert[ 64 ];
//Cvar pointers
new g_pAutoCheck; //CVAR Enable\disable autocheck
new g_pVACCheck; //CVAR Specifies when to check player (0=connect or 1=team join)
new g_pExpireDays; //CVAR Days at which a saved VAC ban is removed
new g_pKDRatio; //CVAR Kill\Death ratio used for kdratio punishments
new g_pKDMin; //CVAR Min kills required before checking kdratios
new g_pPunishment; //CVAR Type of punishment to issue
new g_pBanTime; //CVAR Number of minutes a player is banned for ban punishments
new g_pNotifyFlag; //CVAR Notify flag required for notifications
public plugin_init()
{
register_plugin( "VAC Ban Status" , Version , "bugsy" );
register_cvar( "VAC Ban Status" , Version , FCVAR_SERVER , 0.0 );
register_concmd( "amx_vacban" , "CommandHandler" , ADMIN_BAN , "<Player\SteamID> - Check if player\steamid is VAC banned." );
register_concmd( "amx_vacquery" , "CommandHandler" , ADMIN_BAN , "<Player\SteamID>- Query a player\steamid database entry." );
register_concmd( "amx_vacaddwhitelist" , "CommandHandler" , ADMIN_BAN , "<Player\SteamID>- Add player\steamid to whitelist." );
register_concmd( "amx_vacremovewhitelist" , "CommandHandler" , ADMIN_BAN , "<Player\SteamID>- Remove player\steamid from whitelist." );
register_concmd( "amx_vacremoveentry" , "CommandHandler" , ADMIN_BAN , "<Player\SteamID>- Remove VAC ban status from database." );
register_concmd( "amx_vacclearall" , "CommandHandler" , ADMIN_BAN , "- Clear all database entries" );
register_concmd( "amx_vacclearnotbanned" , "CommandHandler" , ADMIN_BAN , "- Clear database entries for players that are not VAC banned." );
public client_connect( id )
{
fm_hitzones_reset( id );
}
public client_putinserver( id )
{
if ( ( g_IsBot[ id ] = is_user_bot( id ) ) )
return PLUGIN_CONTINUE;
//Get users name and steamid and store it in global variable so it will
//not need to be retrieved again if needed later.
get_user_name( id , g_szName[ id ] , charsmax( g_szName[] ) );
get_user_authid( id , g_szAuthID[ id ], charsmax( g_szAuthID[] ) );
//For testing with a known banned steamid
//if ( id == get_user_index("bugsy") )
// g_szAuthID[id] = "STEAM_0:0:100";
//If auto-checking and check-on-connect are enabled, check player for VAC ban
if ( get_pcvar_num( g_pAutoCheck ) && !get_pcvar_num( g_pVACCheck ) )
AutoCheckPlayer(id);
//An admin has connected, check if has the required admin flag needed for notification.
//If so, notify him of any players that are connected that have a VAC ban on record.
if ( is_user_admin( id ) )
{
new szFlag[2];
get_pcvar_string( g_pNotifyFlag , szFlag , 1 );
//If player has admin flag specified in cvar vbs_notifyflag
if ( ( g_NotifyFlag[ id ] = ( get_user_flags( id ) & read_flags( szFlag ) ) ) )
set_task( 8.0 , "NotifyAdmin" , id );
}
return PLUGIN_CONTINUE;
}
public fwPlayerJoinedTeam()
{
new id = read_data( 1 );
#if AMXX_VERSION_NUM < 190
public client_disconnect( id )
#else
public client_disconnected( id )
#endif
{
if( g_IsBot[ id ] )
return PLUGIN_CONTINUE;
if ( g_ShootsBlanks[ id ] )
SetShootBlanks( id , 0 );
//Clear all vars for player index
g_szSteamName[ id ][ 0 ] = EOS;
g_szFriendID[ id ][ 0 ] = EOS;
g_szAuthID[ id ][ 0 ] = EOS;
g_szName[ id ][ 0 ] = EOS;
g_VACBanned[ id ] = 0;
g_JoinedTeam[ id ] = 0;
g_NotifyFlag[ id ] = 0;
g_Punished[ id ] = 0;
return PLUGIN_CONTINUE;
}
public AutoCheckPlayer(id)
{
new iBanVal = nvault_get( g_Vault , g_szAuthID[ id ] );
//No entry exists in database for player, send VAC check request to steam server
if ( iBanVal == NO_DB_ENTRY )
{
SendRequest( 0 , id , AUTO_CHECK );
}
//Entry found in database and player is VAC banned, punish and notify admins
else if ( iBanVal == BANNED )
{
static szHUD[ 256 ];
new iPlayers[ 32 ];
new iPlayersNum;
new iPlayer;
g_VACBanned[ id ] = 1;
get_players( iPlayers , iPlayersNum , "c" );
formatex( szHUD , charsmax( szHUD ) , "[VAC Ban Status]^n^n%s has a VAC ban on record. [Database]^nSteamID: %s" , g_szName[ id ] , g_szAuthID[ id ] );
set_hudmessage( 255 , 255 , 255 , 0.10 , 0.35 , 0 , 2.0 , 4.0 , 0.5 , 0.5 , 3 );
//Notify all connected admins that this player has connected and is banned
for ( new i = 0 ; ( i < iPlayersNum ) ; i++ )
{
iPlayer = iPlayers[ i ];
if ( g_NotifyFlag[ iPlayer ] )
{
show_hudmessage( iPlayer , szHUD );
client_cmd( iPlayer , "spk buttons/blip1.wav" );
}
}
//If punishment is not a kd-ratio punishment, issue punishment now.
new iPunishment = get_pcvar_num( g_pPunishment );
if ( iPunishment <= SHOOTBLANKS )
{
//VAC check done on client connect so we need a little pause to allow player to
//fully initialize into game or else some punishments will not work.
if ( !get_pcvar_num( g_pVACCheck ) )
{
new params[ 2 ];
params[ 0 ] = id;
params[ 1 ] = iPunishment;
set_task( 0.5 , "DelayPunishment" , _ , params , sizeof( params ) );
}
else
{
PunishPlayer( id , iPunishment );
}
}
}
}
if ( equal( szCmd , "amx_vacclearnotbanned" ) )
{
nvault_prune( g_Vault , 0 , get_systime() );
console_print( id , "*[VAC BAN Status] All non VAC banned entries have been cleared." );
if ( delete_file( szVaultFile ) )
{
if ( ( g_Vault = nvault_open( VAULT ) ) != INVALID_HANDLE )
{
console_print( id , "*[VAC Ban Status] Database successfully cleared." );
return PLUGIN_HANDLED;
}
}
set_fail_state( "Error clearing nvault" );
return PLUGIN_HANDLED;
}
new iPlayer;
new szVal[2];
new iBanVal;
new iTimestamp;
new szArgs[46];
new iRequestType;
read_args( szArgs , charsmax( szArgs ) );
//The below commands all require a parameter (name\steamid) so we determine which is
//being specified by the user.
if( !equali( szArgs , "STEAM_0:" , 8 ) )
{
iPlayer = cmd_target( id , szArgs , ( CMDTARGET_ALLOW_SELF | CMDTARGET_NO_BOTS ) );
if ( equal( szCmd , "amx_vacban" ) )
{
//if( g_Socket[id] )
//{
// console_print( id , "*[VAC Ban Status] Previous check still in progress, try again when it completes." );
// return PLUGIN_HANDLED;
//}
if ( iPlayer )
{
console_print( id , "*[VAC Ban Status] Checking %s [%s]." , g_szName[iPlayer] , g_szAuthID[iPlayer] );
iRequestType = MANUAL_NAME;
}
else
{
console_print( id , "*[VAC Ban Status] Checking SteamID [%s]." , g_szAuthID[iPlayer] );
iRequestType = MANUAL_STEAMID;
}
SendRequest( id , iPlayer , iRequestType );
return PLUGIN_HANDLED;
}
else if ( equal( szCmd , "amx_vacquery" ) )
{
switch ( iBanVal )
{
case NO_DB_ENTRY: console_print( id , "*[VAC Ban Status] Query: No entry exists in database for %s." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] );
case NOT_BANNED:
{
new Float:fExpireDays = ( ( get_pcvar_float( g_pExpireDays ) * 86400.0 ) - ( float(get_systime()) - float(iTimestamp) ) ) / 86400.0;
console_print( id , "*[VAC Ban Status] Query: %s is not VAC banned. Entry expires in %d days." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] , floatround(fExpireDays) );
}
case BANNED: console_print( id , "*[VAC Ban Status] Query: %s has a VAC ban on record." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] );
case NOT_BANNED_WHITELIST: console_print( id , "*[VAC Ban Status] Query: %s is whitelisted with no VAC ban on record." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] );
case BANNED_WHITELIST: console_print( id , "*[VAC Ban Status] Query: %s is whitelisted with a VAC ban on record." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] );
}
return PLUGIN_HANDLED;
}
else if ( equal( szCmd , "amx_vacaddwhitelist" ) )
{
if ( iBanVal <= BANNED )
{
if ( !iBanVal )
iBanVal = NOT_BANNED;
console_print( id , "*[VAC Ban Status] %s has been whitelisted." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] );
}
else
{
console_print( id , "*[VAC Ban Status] %s is already on the whitelist." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] );
}
return PLUGIN_HANDLED;
}
//The below commands involve removing existing entries so we verify that an entry exists first.
if ( !iBanVal )
{
console_print( id , "*[VAC Ban Status] No database entry exists for %s." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] );
return PLUGIN_HANDLED;
}
if ( equal( szCmd , "amx_vacremoveentry" ) )
{
//Player has VAC status in db and is not whitelisted
if ( iBanVal <= BANNED )
{
nvault_remove( g_Vault , g_szAuthID[iPlayer] );
console_print( id , "*[VAC Ban Status] VAC ban database entry for %s was removed." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] );
}
else
{
console_print( id , "*[VAC Ban Status] %s is whitelisted, must use amx_vacremovewhitelist command." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] );
}
}
else if ( equal( szCmd , "amx_vacremovewhitelist" ) )
{
//Player is on whitelist, set appropriate ban status by subtracting 2 from whitelist status
if ( iBanVal >= NOT_BANNED_WHITELIST )
{
szVal[0] = '0' + ( iBanVal - 2 );
console_print( id , "*[VAC Ban Status] %s was removed from the whitelist; player is%s VAC banned." , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] , ( iBanVal == NOT_BANNED_WHITELIST ) ? " not" : "" );
}
else
{
console_print( id , "*[VAC Ban Status] %s has an entry in the db but is not whitelisted. Use amx_vacremoveentry command" , !iPlayer ? g_szAuthID[iPlayer] : g_szName[iPlayer] );
}
}
return PLUGIN_HANDLED;
}
public NotifyAdmin( id )
{
static szNames[513];
new iPlayers[32];
new iPlayersNum;
new iPlayer;
new iPos;
new iFound;
iPos = formatex( szNames , 512 , "[VAC Ban Status]^nThe following players have^na VAC ban on record:^n^n" );
get_players( iPlayers , iPlayersNum , "c" );
//Cycle through all players and create a list of VAC banned players
for ( new i = 0 ; i < iPlayersNum ; i++ )
{
iPlayer = iPlayers[ i ];
}
case MANUAL_NAME: console_print( id , "*[VAC Ban Status] %s is not VAC banned." , g_szName[ idCheck ] );
case MANUAL_STEAMID: console_print( id , "*[VAC Ban Status] SteamID [%s] is not VAC banned." , g_szAuthID[ idCheck ] );
}
}
public PunishPlayer( id , iPunishment )
{
new szMsg[ 30 ];
g_Punished[id] = 1;
switch ( iPunishment )
{
case LOG_ONLY:
{
return PLUGIN_HANDLED;
}
case KICK_ONLY:
{
KickPlayer( id , "[VAC Ban Status]", "A VAC ban record was found on your steam account." , "You have been kicked" ) ;
formatex( szMsg , charsmax( szMsg ) , "was kicked" );
}
case KICK_BAN_ID:
{
server_cmd("amx_ban ^"#%d^" ^"%d^" ^"VAC Banned^"" , get_user_userid( id ) , get_pcvar_num( g_pBanTime ) );
formatex( szMsg , charsmax( szMsg ) , "was kicked and banned" );
}
case KICK_BAN_IP:
{
server_cmd( "amx_banip ^"#%d^" ^"%d^" ^"VAC Banned^"" , get_user_userid( id ) , get_pcvar_num( g_pBanTime ) );
formatex( szMsg , charsmax( szMsg ) , "was kicked and banned" );
}
case KICK_AMXBAN:
{
server_cmd( "amx_ban %d %s VAC Banned", get_pcvar_num( g_pBanTime ) , g_szAuthID[ id ] );
formatex( szMsg , charsmax( szMsg ) , "was kicked and banned" );
}
case SHOOTBLANKS:
{
SetShootBlanks( id , 1 );
formatex( szMsg , charsmax( szMsg ) , "will now shoot blanks" );
}
}
new iPlayers[ 32 ];
new iPlayersNum;
new iPlayer;
get_players( iPlayers, iPlayersNum , "c" );
for ( new i = 0 ; i < iPlayersNum ; i++ )
{
iPlayer = iPlayers[ i ];
if ( g_NotifyFlag[ iPlayer ] )
client_print( iPlayer , print_chat , "[VAC Ban Status] %s %s for being VAC banned%s" , g_szName[ id ] , szMsg , ( get_pcvar_num( g_pPunishment ) >= 6 ) ? " with a high kill:death ratio." : "." );
}
return PLUGIN_HANDLED;
}
public SetShootBlanks( id , iVal )
{
//iVal = 1 - Set shoot blanks on player and enable traceline forward if not yet enabled.
//iVal = 0 - Remove shoot blanks for player id and disable forward if no other players shoot blanks.
public fm_set_user_hitzones(index, target, body)
{
if ( !index && !target )
{
for ( new i = 1 ; i <= g_MaxPlayers ; i++ )
for (new j = 1 ; j <= g_MaxPlayers ; j++ )
g_BodyHits[i][j] = body;
}
else if ( !index && target )
{
for ( new i = 1 ; i <= g_MaxPlayers ; i++ )
g_BodyHits[i][target] = body;
}
else if ( index && !target )
{
for ( new i = 1 ; i <= g_MaxPlayers ; i++ )
g_BodyHits[index][i] = body;
}
else if ( index && target )
{
g_BodyHits[index][target] = body;
}
}
public fm_hitzones_reset(index)
{
for ( new i = 1 ; i <= g_MaxPlayers ; i++ )
{
g_BodyHits[index][i] = (1<<HIT_GENERIC) | (1<<HIT_HEAD) | (1<<HIT_CHEST) |
(1<<HIT_STOMACH) | (1<<HIT_LEFTARM) | (1<<HIT_RIGHTARM)|
(1<<HIT_LEFTLEG) | (1<<HIT_RIGHTLEG);
}
}
// Credit to Teyut for multi-line kick message
KickPlayer( target , szReason[] , szLine2[] , szLine3[] )
{
static msg_content[1024];
// AuthID + Base Number + Server Number
NumString_Add(szSteamID,szFriendsBaseNum,szSteamID,charsmax(szSteamID));
NumString_Add(szSteamID,szServer,szSteamID,charsmax(szSteamID));
Still server crashing but didnt remember error type. Still something with overloaded size or smth.. ;) I turn off plugin for a while. How about others? Everything ok?
I'm not entirely sure, but I guess the notification does not work.
When someone connects there is no check shown. The only way to see a check is by doing it manually. And this check is only visible in the console.
IIrc the check was shown in the server-chat. Or am I completely off here?