SourceMod Donner Party
Join Date: Oct 2009
Location: Poortugal
|
11-27-2012
, 13:46
[TUT] Tries
|
#1
|
Before we start, this tutorial is for everyone that don’t know how to use tries. I will assume that you know the basics of pawn / amxx language.
Basically, tries let you store data associated to a key (string). The data usually is an integer or a string.
Some considerations on this tutorial:
- I will not make comparisons between tries and arrays ( https://forums.alliedmods.net/showthread.php?t=88396)
- I will not talk about TrieSetArray and TrieGetArray - already made
- All the examples will be generally simple. I just want to show you how to use tries
So, for the first example I will demonstrate how to detect if a player has a Steam ID in the black list.
PHP Code:
#include < amxmodx >
new Trie:g_tAuthIdBlackList // g means global; t means trie
public plugin_init( ) { register_plugin( "trie example", "1.0.1", "guipatinador" ) g_tAuthIdBlackList = TrieCreate( ) // Create the trie... TrieSetCell( g_tAuthIdBlackList, "STEAM_2:3:123456", 1 ) TrieSetCell( g_tAuthIdBlackList, "STEAM_2:3:654321", 1 ) TrieSetCell( g_tAuthIdBlackList, "STEAM_2:3:123654", 1 ) TrieSetCell( g_tAuthIdBlackList, "STEAM_2:3:456123", 1 ) // First param = name of the trie // Second param = string with the Steam ID blacklisted (this is the key and it should be unique) // Third param = it is our integer, we will not use this }
public plugin_end( ) { TrieDestroy( g_tAuthIdBlackList ) // Destroys the trie when the map changes or the server shuts down }
public client_authorized( id ) { new szAuthID[ 35 ]; get_user_authid( id, szAuthID, charsmax( szAuthID ) ) if( TrieKeyExists( g_tAuthIdBlackList, szAuthID ) ) { // The Steam ID (key), exist in the trie server_cmd( "kick #%i ^"Your Steam ID is blacklisted^"", get_user_userid( id ) ) } else { // The Steam ID is not in the trie // We won’t do anything because the Steam ID is not blacklisted } }
For the second example, we will associate a Steam ID with an integer, and check if the player is an ADMIN, MOD or VIP.
PHP Code:
#include < amxmodx >
new Trie:g_tAuthIdOfPeople
#define LOGFILE "steamidsofpeople.log"
// Just to be more easy... #define ADMIN 1 #define MOD 2 #define VIP 3
public plugin_init( ) { register_plugin( "trie example", "1.0.2", "guipatinador" ) g_tAuthIdOfPeople = TrieCreate( ) TrieSetCell( g_tAuthIdOfPeople, "STEAM_2:3:123456", ADMIN ) // admin is 1 TrieSetCell( g_tAuthIdOfPeople, "STEAM_2:3:654321", ADMIN ) TrieSetCell( g_tAuthIdOfPeople, "STEAM_2:3:123654", MOD ) // mod is 2 TrieSetCell( g_tAuthIdOfPeople, "STEAM_2:3:456123", VIP ) // vip is 3 }
public plugin_end( ) { TrieDestroy( g_tAuthIdOfPeople ) }
public client_authorized( id ) { new szAuthID[ 35 ]; get_user_authid( id, szAuthID, charsmax( szAuthID ) ) new iNum // This will save our integer (ADMIN, MOD or VIP) in iNum, if the key is on the trie if( TrieGetCell( g_tAuthIdOfPeople, szAuthID, iNum ) ) { switch( iNum ) { case ADMIN: log_to_file( LOGFILE, "A Admin entered the server" ) case MOD: log_to_file( LOGFILE, "A Mod entered the server" ) case VIP: log_to_file( LOGFILE, "A Vip entered the server" ) } } else // The key (Steam ID) is not in the trie { log_to_file( LOGFILE, "A normal player entered the server" ) } }
If you understand this, you know how to work with TrieCreate, TrieDestroy, TrieGetCell, TrieSetCell and TrieKeyExists.
Now let’s work with a few more natives.
For the third example, we will use admin commands to block some nicknames.
PHP Code:
#include < amxmodx > #include < amxmisc >
new Trie:g_tNicks
#define ADMIN_FLAG ADMIN_RCON
public plugin_init( ) { register_plugin( "trie example", "1.0.3", "guipatinador" ) register_concmd( "amx_blocknick", "BlockNickCmd", ADMIN_FLAG, "<name to block>" ) register_concmd( "amx_unblocknick", "UnBlockNickCmd", ADMIN_FLAG, "<name to unblock>" ) register_concmd( "amx_removenicks", "RemoveNicksCmd", ADMIN_FLAG ) g_tNicks = TrieCreate( ) }
public plugin_end( ) { TrieDestroy( g_tNicks ) }
public BlockNickCmd( id, level, cid ) { if( !cmd_access( id, level, cid, 2 ) ) return PLUGIN_HANDLED new szName[ 32 ] read_argv( 1, szName, charsmax( szName ) ) // First we’ll check if the username is in the trie // If it is, we won't do anything // If it isn’t, we’ll add the nick // I will show two methods // METHOD ONE if( TrieKeyExists( g_tNicks, szName ) ) { client_print( id, print_console, "Username already added before" ) } else { TrieSetCell( g_tNicks, szName, 1 ) client_print( id, print_console, "Username added with success" ) } /* // METHOD TWO new iNum new bool:bNameAlreadyAdded = TrieGetCell( g_tNicks, szName, iNum ) if( bNameAlreadyAdded ) { client_print( id, print_console, "Username already added before" ) } else { TrieSetCell( g_tNicks, szName, 1 ) client_print( id, print_console, "Username added with success" ) } */ return PLUGIN_HANDLED }
public UnBlockNickCmd( id, level, cid ) { if( !cmd_access( id, level, cid, 2 ) ) return PLUGIN_HANDLED new szName[ 32 ] read_argv( 1, szName, charsmax( szName ) ) if( TrieDeleteKey( g_tNicks, szName ) ) { client_print( id, print_console, "Username deleted with success" ) } else { client_print( id, print_console, "Username already deleted before" ) }
/* // If you want to delete, without print a message just do this TrieDeleteKey( g_tNicks, szName ) */ return PLUGIN_HANDLED }
public RemoveNicksCmd( id, level, cid ) { if( !cmd_access( id, level, cid, 1 ) ) return PLUGIN_HANDLED TrieClear( g_tNicks ) // This one clears all the keys of the trie and the data client_print( id, print_console, "All the blocked usernames were deleted" ) return PLUGIN_HANDLED }
public client_authorized( id ) { new szName[ 32 ]; get_user_name( id, szName, charsmax( szName ) ) if( TrieKeyExists( g_tNicks, szName ) ) { server_cmd( "kick #%i ^"Your nickname is blocked^"", get_user_userid( id ) ) } /* // Note that this will also work new iNum if( TrieGetCell( g_tNicks, szName, iNum ) ) { server_cmd( "kick #%i ^"Your nickname is blocked^"", get_user_userid( id ) ) } */ }
For the TrieGetString and TrieSetString we will associate some VIP dates to Steam IDs.
PHP Code:
#include < amxmodx > #include < amxmisc >
new Trie:g_tVipDate
new const VIPDATE[ ][ ][ ] = { { "STEAM_2:3:123456", "01-04-2013" }, { "STEAM_2:3:654321", "25-02-2013" }, { "STEAM_2:3:123654", "13-03-2013" }, { "STEAM_2:3:456123", "09-01-2013" } }
public plugin_init( ) { register_plugin( "trie example", "1.0.4", "guipatinador" ) register_clcmd( "say /vipdate", "VipDate" ) g_tVipDate = TrieCreate( ) new i for( i = 0; i < sizeof VIPDATE; i++ ) { TrieSetString( g_tVipDate, VIPDATE[ i ][ 0 ], VIPDATE[ i ][ 1 ] ) // First param = name of the trie // Second param = Steam ID (key) // Third param = date when the vip ends (string) } }
public plugin_end( ) { TrieDestroy( g_tVipDate ) }
public VipDate( id ) { new szAuthID[ 35 ]; get_user_authid( id, szAuthID, charsmax( szAuthID ) ) // First we’ll check if the Steam ID of the player is in the trie new szVipDate[ 12 ] if( TrieGetString( g_tVipDate, szAuthID, szVipDate, charsmax( szVipDate ) ) ) { // The user is vip because the Steam ID is one of the keys of the trie client_print( id, print_chat, "Your VIP will end in: %s", szVipDate ) } else { // User is not vip client_print( id, print_chat, "You are not VIP" ) } }
And for the last... let's work with TrieSetArray and TrieGetArray.
This plugin read the stats of a file and save it by Steam ID.
PHP Code:
#include < amxmodx > #include < amxmisc >
new Trie:g_StatsOfPlayers
new g_szAuthID[ 33 ][ 35 ] // This will save the Steam ID of any player
enum _:Stats { SteamID[ 35 ], Kills, Deaths, KillsKnife, KillsHE } // Those are the stats we want to save. Note that the Steam ID is a string, the rest are integers
public plugin_init( ) { register_plugin( "trie example", "1.0.5", "guipatinador" ) register_clcmd( "say /mystats", "PrintStats" ) // We will use this command to see the stats g_StatsOfPlayers = TrieCreate( ) ReadStatsFromFile( ) // Reads stats from the file when the server starts or the map changes }
public plugin_end( ) { TrieDestroy( g_StatsOfPlayers ) }
public ReadStatsFromFile( ) { new szFilePath[ 128 ] get_configsdir( szFilePath, charsmax( szFilePath ) ) add( szFilePath, charsmax( szFilePath ), "/stats_of_players.ini" ) // File where the stats are saved new f = fopen( szFilePath, "rt" ) if( !f ) { new szMessage[ 256 ] formatex( szMessage, charsmax( szMessage ), "Unable to open %s", szFilePath ) set_fail_state( szMessage ) } new szDataFromFile[ 128 ] new Data[ Stats ] new szKills[ 5 ] new szDeaths[ 5 ] new szKnife[ 5 ] new szHE[ 5 ] while( !feof( f ) ) // Opens the file { fgets( f, szDataFromFile, charsmax( szDataFromFile ) ) if( !szDataFromFile[ 0 ] || szDataFromFile[ 0 ] == ';' || szDataFromFile[ 0 ] == '/' && szDataFromFile[ 1 ] == '/' ) continue trim( szDataFromFile ) parse( szDataFromFile, Data[ SteamID ], charsmax( Data[ SteamID ] ), // This is our key szKills, charsmax( szKills ), szDeaths, charsmax( szDeaths ), szKnife, charsmax( szKnife ), szHE, charsmax( szHE ) ) // All those things are strings. Let's convert to integers Data[ Kills ] = str_to_num( szKills ) Data[ Deaths ] = str_to_num( szDeaths ) Data[ KillsKnife ] = str_to_num( szKnife ) Data[ KillsHE ] = str_to_num( szHE ) // This will save the Steam ID and the stats in the trie TrieSetArray( g_StatsOfPlayers, Data[ SteamID ], Data, sizeof Data ) // First param = name of the trie // Second param = key (string) (in this case it's the Steam ID) // Third param = array that contains the stats // Fourth param = size of the array (note that 'sizeof Data - 1' will not work) } fclose( f ) // Closes the file }
public client_authorized( id ) { get_user_authid( id, g_szAuthID[ id ], charsmax( g_szAuthID[ ] ) ) }
public PrintStats( id ) { new Data[ Stats ] if( TrieGetArray( g_StatsOfPlayers, g_szAuthID[ id ], Data, sizeof Data ) ) { // The params are similar to TrieSetString // First = name of the array // Second = key. g_szAuthID[ id ] contains the Steam ID of the player that types /mystats // Third = array to retrieve the data // Fourth = size client_print( id, print_chat, "Steam ID: %s | Kills: %i | Deaths: %i | Knife: %i | HE: %i", Data[ SteamID ], Data[ Kills ], Data[ Deaths ], Data[ KillsKnife ], Data[ KillsHE ] ) } // If the Steam ID doesn't exist in the file, it is better to print another message else { client_print( id, print_chat, "Your Steam ID do not have stats saved" ) } }
That's all
Last edited by guipatinador; 03-09-2013 at 15:39.
|
|