/* AMX CVAR GUARD
   by Wilson [29th ID]
   
   DESCRIPTION
   Executes commands listed in an ini file on every incoming client upon
   their connection to the server, and optionally can prevent the client
   from changing the command to anything else.
   
   WARNING
   If the "lock" option is enabled, so that clients cannot set the commands
   to anything else, the client will have to exit their game before they 
   can set it to anything else. No permanent effects, but sometimes people
   get confused.
   
   NOTE
   Blocking commands only works for client CVARs, which are "settings".
   See cvarguard.ini for examples of these cvars.
   
   USAGE
    Place cvarguard.ini in amxmodx/configs directory.
    Follow instructions in that file for adding commands.
    Use the below CVARs to enable this plugin in your server.
   
    amx_cvarguard <1/0>
	Enables or Disables the plugin
	
    amx_cvarguard_lock <1/0>
	Enables or Disables the "lock" feature, preventing clients from
	changing commands to anything else
*/

#include <amxmodx>
#include <amxmisc>

#pragma semicolon 1

#define PLUGIN "CVAR Guard"
#define VERSION "1.0"
#define AUTHOR "29th ID"

#define MAX_CVARS 32
#define MAX_CVAR_LEN 32
#define MAX_FILEPATH_LEN 128
#define MAX_FILE_LINE_LEN 128

new g_cvarEnabled;
new g_cvarLock;

// Path to list of commands, from amxmodx/configs directory
new const g_szFileName[] = "cvarguard.ini";

// Command that blocked cvars are hooked to
new const g_szBlockedCmd[] = "command_blocked_restart_game";

// Message displayed when blocked cvar is executed by client
new const g_szBlockMessage[] = "That command is blocked on this server";

enum { cvar, value };
new const g_commands[MAX_CVARS][2][MAX_CVAR_LEN];


public plugin_init() {
	register_plugin( PLUGIN, VERSION, AUTHOR );
	register_clcmd( g_szBlockedCmd, "clcmd_blockedcmd" );
}

public plugin_precache() {
	g_cvarEnabled = register_cvar( "amx_cvarguard", "1" );
	g_cvarLock = register_cvar( "amx_cvarguard_lock", "1" );
	if( cvar_enabled() )
	{
		new szFilePath[128];
		get_configsdir( szFilePath, 127 );
		format( szFilePath, 127, "%s/%s", szFilePath, g_szFileName );
		
		if ( file_exists( szFilePath ) )
			read_config( szFilePath );
	}
}

// Reads ini file
public read_config( const szFilePath[] ) {
	new szLine[MAX_FILE_LINE_LEN];
	new line_count, line_len, index;
	
	new szCvar[MAX_CVAR_LEN];
	new szValue[MAX_CVAR_LEN];
	
	while( read_file( szFilePath, line_count++, szLine, MAX_FILE_LINE_LEN, line_len ) ) {
		if( line_len && ( !equal( szLine, "//", 2 ) ) )
		{
			parse( szLine, szCvar, MAX_CVAR_LEN-1, szValue, MAX_CVAR_LEN-1 );
			
			g_commands[index][cvar] = szCvar;
			g_commands[index][value] = szValue;
			
			index++;
		}
	}
}

public client_connect( id ) {
	if( cvar_enabled() ) loop_commands( id );
}

public loop_commands( id ) {
	for( new i; i < MAX_CVARS; i++ )
	{
		if( g_commands[i][cvar][0] )
			execute_command( id, i );
	}
}

public execute_command( id, index ) {
	new szClCmd[128];
	format( szClCmd, 127, "%s %s", g_commands[index][cvar], g_commands[index][value] );
	
	// If "lock" is enabled, add the locking section of the command
	if( cvar_lock() )
		format( szClCmd, 127, "%s; alias %s %s", szClCmd, g_commands[index][cvar], g_szBlockedCmd );
	
	client_cmd( id, szClCmd );
}

// Hook the blocked command to display the error message
// when the client tries to alter the command
public clcmd_blockedcmd( id ) {
	client_print( id, print_console, g_szBlockMessage );
	return PLUGIN_HANDLED;
}
	
///////////////////

stock cvar_enabled() return get_pcvar_num( g_cvarEnabled );
stock cvar_lock() return get_pcvar_num( g_cvarLock );

