Raised This Month: $12 Target: $400
 3% 

[TUT] Tries


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
guipatinador
SourceMod Donner Party
Join Date: Oct 2009
Location: Poortugal
Old 11-27-2012 , 13:46   [TUT] Tries
Reply With Quote #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...
    
    
TrieSetCellg_tAuthIdBlackList"STEAM_2:3:123456")
    
TrieSetCellg_tAuthIdBlackList"STEAM_2:3:654321")
    
TrieSetCellg_tAuthIdBlackList"STEAM_2:3:123654")
    
TrieSetCellg_tAuthIdBlackList"STEAM_2:3:456123")
    
    
// 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( )
{
    
TrieDestroyg_tAuthIdBlackList // Destroys the trie when the map changes or the server shuts down
}

public 
client_authorizedid )
{
    new 
szAuthID35 ]; get_user_authididszAuthIDcharsmaxszAuthID ) )
    
    if( 
TrieKeyExistsg_tAuthIdBlackListszAuthID ) )
    {
        
// The Steam ID (key), exist in the trie
        
server_cmd"kick #%i ^"Your Steam ID is blacklisted^""get_user_useridid ) )
    }
    
    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( )
    
    
TrieSetCellg_tAuthIdOfPeople"STEAM_2:3:123456"ADMIN // admin is 1
    
TrieSetCellg_tAuthIdOfPeople"STEAM_2:3:654321"ADMIN )
    
TrieSetCellg_tAuthIdOfPeople"STEAM_2:3:123654"MOD // mod is 2
    
TrieSetCellg_tAuthIdOfPeople"STEAM_2:3:456123"VIP // vip is 3
}

public 
plugin_end( )
{
    
TrieDestroyg_tAuthIdOfPeople )
}

public 
client_authorizedid )
{
    new 
szAuthID35 ]; get_user_authididszAuthIDcharsmaxszAuthID ) )
    
    new 
iNum
    
    
// This will save our integer (ADMIN, MOD or VIP) in iNum, if the key is on the trie
    
if( TrieGetCellg_tAuthIdOfPeopleszAuthIDiNum ) )
    {
        switch( 
iNum )
        {
            case 
ADMIN:
                
log_to_fileLOGFILE"A Admin entered the server" )
            
            case 
MOD:
                
log_to_fileLOGFILE"A Mod entered the server" )
            
            case 
VIP:
                
log_to_fileLOGFILE"A Vip entered the server" )
        }
    }
    
    else 
// The key (Steam ID) is not in the trie
    
{
        
log_to_fileLOGFILE"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( )
{
    
TrieDestroyg_tNicks )
}

public 
BlockNickCmdidlevelcid )
{
    if( !
cmd_accessidlevelcid) )
        return 
PLUGIN_HANDLED
    
    
new szName32 ]    
    
read_argv1szNamecharsmaxszName ) )
    
    
// 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( TrieKeyExistsg_tNicksszName ) )
    {
        
client_printidprint_console"Username already added before" )    
    }
    
    else
    {
        
TrieSetCellg_tNicksszName)
        
client_printidprint_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 
UnBlockNickCmdidlevelcid )
{
    if( !
cmd_accessidlevelcid) )
        return 
PLUGIN_HANDLED
    
    
new szName32 ]    
    
read_argv1szNamecharsmaxszName ) )
    
    if( 
TrieDeleteKeyg_tNicksszName ) )
    {
        
client_printidprint_console"Username deleted with success" )
    }
    
    else
    {
        
client_printidprint_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 
RemoveNicksCmdidlevelcid )
{
    if( !
cmd_accessidlevelcid) )
        return 
PLUGIN_HANDLED
    
    TrieClear
g_tNicks // This one clears all the keys of the trie and the data
    
client_printidprint_console"All the blocked usernames were deleted" )
    
    return 
PLUGIN_HANDLED
}

public 
client_authorizedid )
{
    new 
szName32 ]; get_user_nameidszNamecharsmaxszName ) )
    
    if( 
TrieKeyExistsg_tNicksszName ) )
    {
        
server_cmd"kick #%i ^"Your nickname is blocked^""get_user_useridid ) )
    }
    
    
/*
    // 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( 0sizeof VIPDATEi++ )
    {
        
TrieSetStringg_tVipDateVIPDATE][ ], VIPDATE][ ] )
        
// First param = name of the trie
        // Second param = Steam ID (key)
        // Third param = date when the vip ends (string)
    
}
}

public 
plugin_end( )
{
    
TrieDestroyg_tVipDate )
}

public 
VipDateid )
{
    new 
szAuthID35 ]; get_user_authididszAuthIDcharsmaxszAuthID ) )
    
    
// First we’ll check if the Steam ID of the player is in the trie
    
new szVipDate12 ]
    if( 
TrieGetStringg_tVipDateszAuthIDszVipDatecharsmaxszVipDate ) ) )
    {
        
// The user is vip because the Steam ID is one of the keys of the trie
        
client_printidprint_chat"Your VIP will end in: %s"szVipDate )
    }
    
    else
    {
        
// User is not vip
        
client_printidprint_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_szAuthID33 ][ 35 // This will save the Steam ID of any player

enum _:Stats {
    
SteamID35 ],
    
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( )
{
    
TrieDestroyg_StatsOfPlayers )
}

public 
ReadStatsFromFile( )
{
    new 
szFilePath128 ]
    
get_configsdirszFilePathcharsmaxszFilePath ) )
    
addszFilePathcharsmaxszFilePath ), "/stats_of_players.ini" // File where the stats are saved
    
    
new fopenszFilePath"rt" )
    
    if( !
)
    {
        new 
szMessage256 ]
        
formatexszMessagecharsmaxszMessage ), "Unable to open %s"szFilePath )
        
set_fail_stateszMessage )
    }
    
    new 
szDataFromFile128 ]
    new 
DataStats ]
    new 
szKills]
    new 
szDeaths]
    new 
szKnife]
    new 
szHE]
    
    while( !
feof) ) // Opens the file
    
{
        
fgetsfszDataFromFilecharsmaxszDataFromFile ) )
        
        if( !
szDataFromFile] || szDataFromFile] == ';' || szDataFromFile] == '/' && szDataFromFile] == '/' )
            continue
        
        
trimszDataFromFile )
        
parseszDataFromFile,
        
DataSteamID ], charsmaxDataSteamID ] ), // This is our key
        
szKillscharsmaxszKills ),
        
szDeathscharsmaxszDeaths ),
        
szKnifecharsmaxszKnife ),
        
szHEcharsmaxszHE ) )
        
        
// All those things are strings. Let's convert to integers
        
DataKills ] = str_to_numszKills )
        
DataDeaths ] = str_to_numszDeaths )
        
DataKillsKnife ] = str_to_numszKnife )
        
DataKillsHE ] = str_to_numszHE )
        
        
// This will save the Steam ID and the stats in the trie
        
TrieSetArrayg_StatsOfPlayersDataSteamID ], Datasizeof 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// Closes the file
}

public 
client_authorizedid )
{
    
get_user_authididg_szAuthIDid ], charsmaxg_szAuthID[ ] ) )
}

public 
PrintStatsid )
{
    new 
DataStats ]
    
    if( 
TrieGetArrayg_StatsOfPlayersg_szAuthIDid ], Datasizeof 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_printidprint_chat"Steam ID: %s | Kills: %i | Deaths: %i | Knife: %i | HE: %i"DataSteamID ], DataKills ], DataDeaths ], DataKillsKnife ], DataKillsHE ] )
    }
    
    
//  If the Steam ID doesn't exist in the file, it is better to print another message
    
else
    {
        
client_printidprint_chat"Your Steam ID do not have stats saved" )
    }

That's all

Last edited by guipatinador; 03-09-2013 at 15:39.
guipatinador is offline
ConnorMcLeod
Veteran Member
Join Date: Jul 2006
Location: France (95)
Old 11-27-2012 , 14:20   Re: [TUT] Tries
Reply With Quote #2

Tries don't need to be destroyed at plugin_end, it is automatic.
__________________
- tired and retired -

- my plugins -
ConnorMcLeod is offline
bibu
Veteran Member
Join Date: Sep 2010
Old 11-27-2012 , 15:54   Re: [TUT] Tries
Reply With Quote #3

Wow, this is really useful for me. Thanks.
__________________
Selling tons of my own private works.
Accepting paid work for clans and communities.
Don't hesitate to contact me.
bibu is offline
pokemonmaster
princess milk
Join Date: Nov 2010
Location: Somewhere in this world
Old 11-28-2012 , 13:10   Re: [TUT] Tries
Reply With Quote #4

Thank you for this.
Waiting for cell arrays tutorial
__________________
اَشْهَدُ اَنْ لَّآ اِلٰهَ اِلَّا اللہُ وَحْدَه لَا شَرِيْكَ لَه وَ اَشْهَدُ اَنَّ مُحَمَّدًا عَبْدُه وَرَسُوْلُه
No longer active in AMXX. Sorry.
pokemonmaster is offline
aaarnas
Veteran Member
Join Date: Jun 2008
Location: Lithuania
Old 11-28-2012 , 21:06   Re: [TUT] Tries
Reply With Quote #5

Quote:
- I will not talk about TrieSetArray and TrieGetArray
Why? You should.
How to play with structures, arrays, because it could be useful for someone. I remember, that it was difficult to understand these dynamic structures (cellarray also) and there aren't any documentation for this.
__________________
My plugins:
[ZP] ZM_VIP (v2.0.0 is comming. v1.9.1 BETA is out!)

aaarnas is offline
guipatinador
SourceMod Donner Party
Join Date: Oct 2009
Location: Poortugal
Old 11-29-2012 , 06:03   Re: [TUT] Tries
Reply With Quote #6

I don't know if TrieSetArray and TrieGetArray bug is really fixed on amx v1.8.2.
Can someone confirm that?

Last edited by guipatinador; 11-29-2012 at 06:03.
guipatinador is offline
Arkshine
AMX Mod X Plugin Approver
Join Date: Oct 2005
Old 11-29-2012 , 06:38   Re: [TUT] Tries
Reply With Quote #7

Yes it's fixed.

http://hg.alliedmods.net/amxmodx-central/
__________________
Arkshine is offline
aaarnas
Veteran Member
Join Date: Jun 2008
Location: Lithuania
Old 11-29-2012 , 12:54   Re: [TUT] Tries
Reply With Quote #8

It's working good. Using without any problems.
__________________
My plugins:
[ZP] ZM_VIP (v2.0.0 is comming. v1.9.1 BETA is out!)

aaarnas is offline
guipatinador
SourceMod Donner Party
Join Date: Oct 2009
Location: Poortugal
Old 11-29-2012 , 14:09   Re: [TUT] Tries
Reply With Quote #9

I have updated the tutorial with TrieGetArray and TrieSetArray

btw this is very very cool http://forums.alliedmods.net/showthread.php?t=74753

Last edited by guipatinador; 11-29-2012 at 14:27.
guipatinador is offline
Mucx
Member
Join Date: Mar 2011
Location: Estonia
Old 12-07-2012 , 02:27   Re: [TUT] Tries
Reply With Quote #10

Good tutorial, was searching a way to save data.

Can i set multiple key's to TrieSetString, if yes, then how?
For example i have Name and Steam in my table.
Idea is when Name or Steam is valid then plugin takes action, gives the rest data that is taken from mysql.
Mucx is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 01:13.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode