Raised This Month: $7 Target: $400
 1% 

nVault Tutorial


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
Old 05-02-2009 , 01:04   nVault Tutorial
Reply With Quote #1

nVault Tutorial

Intro
nVault is an AMX-X tool designed for an easy method of saving and retrieving data from an external file. I have seen many people ask how to save data in a plugin so it can be retrieved after a map change or server restart. nVault will allow you to do this and it is very simple to use. nVault stores data using a key:data system; each chunk of data that you save has a unique key that corresponds to it. Both key and data are always strings when saving but data can be retrieved as integer, float, or string (see nvault_get). Data is saved to a nvault file in binary format, not plain text; this means that you cannot edit the file in [your favorite text editor here] but there is an nVault Editor that can be used. Also note that you cannot iterate through entries in a nvault file with the native nvault functions. You can iterate through entries using the nVault Utility include file. The ability the store arrays in nVault can also be accomplished with the nVault Utility.

nVault info from AMX-X documentation:
http://www.amxmodx.org/funcwiki.php?go=module&id=20
Code:
nVault is a binary vault implementation. It allows you to open named vaults (which are stored in 
data\vault) and read/write to them at any time. 

The vault is implemented with a simple hash lookup, and the binary file format is primitive. However, it 
should be much faster than AMX Mod X's built-in vault for most things. Each entry is also timestamped, 
so you can prune for old entries. 

Furthermore, the vault attempts to be journaled. That is, it keeps a log of everything it does, so if the 
server crashes, it can "replay" the journal and recover damage. The journal is erased on synchronization 
to the vault binary, which occurs on vault close/mapchange.
These are the available nvault functions:
Code:
nvault_open - Opens a vault by name (such as "myvault").
nvault_close - Closes a vault.
nvault_lookup - Looks up a vault value for full information.
nvault_get - Gets a vault value by returning an int setting a byref float or setting a string & maxlength.
nvault_set - Sets a vault value with current timestamp.
nvault_pset - Sets a permanent vault value with no timestamp.
nvault_remove - Remove an entry from vault.
nvault_touch - "Touches" a key to update its timestamp value. 
nvault_prune - Prunes the vault for entries that are within the given timestamps.
nvault_open
Before doing any transactions with a vault, it must first be opened. This is done with the nvault_open command; it takes 1 string parameter which is the name of the file that is created on the servers hard-disk ([name].vault). When you call the nvault_open() command, it will return a handle (integer value) that is used by all of the other nvault functions as a reference to that particular vault. If an error occurs when opening the vault, nvault_open() will return -1 (INVALID_HANDLE) so it is a good idea to verify if it opened correctly prior to using any other commands.

Code:
nvault_open( const szVaultName[] )

szVaultName = This will be the name of your vault. Every time you want to communicate with this vault you must always use the same name to access that vault. A file will be created in data\vault folder named [szVaultName].vault

Return value: Vault id on success, -1 on failure.
PHP Code:
//Open a vault and throw a plugin error if INVALID_HANDLE is returned.
new iVaultHandle nvault_open"testvault" );

if ( 
iVaultHandle == INVALID_HANDLE )
    
set_fail_state"Error opening nVault" ); 
nvault_close
This function will close the vault. It takes the vault handle to close as a parameter. Once a vault is closed you cannot do any transactions with the vault until it is re-opened. In most circumstances it is best to put nvault_close() in plugin_end(). Failure to close a vault file will cause it to be corrupt and you will lose all data.
Code:
nvault_close( iHandle )

iHandle = The handle of the vault that we want to close

Return value: 1 on success, 0 on failure
PHP Code:
//Open and close a vault.
new iVaultHandle nvault_open"testvault" );

nvault_closeiVaultHandle ); 
nvault_lookup
This function will lookup data using a string key and will place the found data into szValue by-reference for a max of iMaxLength characters. If data is found, the function will return 1 (true), if no data found 0 (false). Timestamp will hold the time at which the entry was written/updated or touched last. This function can only retrieve data from the vault and store it into a string variable. See timestamps section below for an explanation of how timestamps work. This function should be used if you would like to see if a particular key exists in the vault.

Code:
nvault_lookup( iHandle , const szKey[] , szValue[] , iMaxLength , iTimestamp )

iHandle = The handle returned from nvault_open.
szKey = The key you want to use for the data lookup.
szValue = The string variable that will store the data we are retrieving.
iMaxLength = The max length of the string we want read into szValue.
iTimestamp = Will hold a timestamp for when entry was written or last touched.

Return value: 1 if data exists, 0 if no data exists.
PHP Code:
//Lookup a string stored in a vault using the players steamid as the key.
new szAuthID[35];
new 
szData[30];
new 
iTimestamp;
new 
iVault;
new 
iDataExists

get_user_authid
id szAuthID charsmaxszAuthID ) );

iVault nvault_open"testvault" );
iDataExists nvault_lookupiVault szAuthID szData charsmaxszData ) , iTimestamp );

//An entry was found, the data for this key is now stored in szData.
if ( iDataExists )
{
    
client_printid print_chat "Data=%s Timestamp=%d" szData iTimestamp );
}
else
{
    
client_printid print_chat "No entry found with key %s" szAuthID );

nvault_get
This function is very similar to nvault_lookup; it looks up data in a vault using the specified key. However, nvault_get is a bit more flexible than nvault_lookup because it allows you to retrieve data directly into a variable other than string. This will negate the need for you to do any data conversion once the data is retrieved as you would need to do if you use nvault_lookup to retrieve a float or int. Note, nvault_get does not allow you to retrieve the timestamp so if you do need the timestamp then you will need to use nvault_lookup.

Code:
nvault_get( handle , const szKey[] , ... )

handle = The handle returned from nvault_open.
key = The key you want to use for the data lookup.
[...] = [Variable # of parameters] This can either be a float variable, string & maxlen, or empty. See below

The number of parameters tells the function what type of data you wish to retrieve. Parameter count starts after szKey[]
0 parameters = nvault_get will return the integer value.
1 parameters = the float value will be passed by reference.
2 parameters = the string value will be passed by ref for maxlen characters. 

Integer: iValue = nvault_get( iHandle , szKey[] );
Return value: Integer value that was found, or 0 if the key was not found or if the data value is non-numerical (ie. a string).

Float: nvault_get( iHandle , szKey[] , float );
Return value: 1 if data found, or 0 if key was not found.

String: nvault_get( iHandle , szKey[] , szValue[] , iMaxLen );
Return value: Length of string data retrieved, or 0 if key was not found.
PHP Code:
//Retrieve an integer, float, and string value from a vault.
new iVault;
new 
szAuthID[35];
new 
szData[30];

iVault nvault_open"testvault" );
get_user_authidid szAuthID charsmaxszAuthID ) );

//To retrieve a number that is stored as the data
new iNumber nvault_getiVault szAuthID );

//To retrieve a float that is stored as the data
new FloatfValue;
nvault_getiVault szAuthID fValue );

//To retrieve a string that is stored as the data
new szDataString[10];
nvault_getiVault szAuthID szDataString charsmaxszDataString ) ); 
nvault_set
This will write data to the vault and timestamp the entry.

Code:
nvault_set( handle , const key[] , const value[] )

handle = The handle returned from nvault_open.
key = The key you want to use for the data lookup.
value = The string you want to write to vault

Return value: 1 on success, 0 on failure.
PHP Code:
//Save the phrase "hello world" to vault using steamid as the key.
new iVault;
new 
szAuthID[35];
new 
szData[30];

iVault nvault_open"testvault" );
get_user_authidid szAuthID charsmaxszAuthID ) );

//Pass the value directly with no variable
nvault_setiVault szAuthID "hello world" );

//Pass the value with a string variable
new szText[] = "hello world";
nvault_setiVault szAuthID szText ); 
nvault_pset
The same as nvault_set() except this writes an entry without a timestamp so the entry will not be removed by the nvault_prune() function (if called). The timestamp value is 0 when permanent.
Code:
Return value: 1 on success, 0 on failure.
nvault_remove
This removes an entry from the vault that has the specified key value.
Code:
nvault_remove( handle , const key[] )

handle = The handle returned from nvault_open.
key = The key of the vault entry to remove.

Return value: 1 on success, 0 on failure.
PHP Code:
//Remove an entry from vault
new iVault;

iVault nvault_open"testvault" );

//Set a test entry with key "test entry"
nvault_setiVault "test entry" "test value" );

//Remove the entry that was just saved
nvault_removeiVault "test entry" ); 
nvault_touch
This function will 'touch' an entry, updating it's timestamp; the entry value will remain unchanged. If the key does not exist that is being touched, an empty entry for that key will be created. See timestamps section below for an explanation of timestamps.

Code:
nvault_touch( iHandle , const szKey[] , [ iTimestamp = -1 ] ) 

iHandle = The handle of the vault
szKey = The key for which we want to update timestamp
iTimeStamp - [Optional param] If not passed to the function (or -1 is passed) 
it will update the key with the current time. Otherwise it will update the 
key with the timestamp specified.

Return value: 1 on success, 0 on failure.
PHP Code:
//Touch the entry
new iVault;
new 
szAuthID[35];

iVault nvault_open"testvault" );

get_user_authidid szAuthID charsmaxszAuthID ) );

//Touch the entry with current timestamp
nvault_touchiVault szAuthID );

//Touch entry with timestamp 1 hour ago. (60 * 60) = 3600
nvault_touchiVault szAuthID get_systime() - 3600 ); 
nvault_prune
This function is used to remove entries that fall within the specified start and end timestamps. A timestamp value is in seconds so keep this in consideration when pruning entries. See timestamps section below for an explanation of timestamps.

Code:
nvault_prune( iHandle , iStart , iEnd )

iHandle = The handle returned from nvault_open.
iStart = The timestamp where to begin removing entries.
iEnd = The timestamp where to stop removing entries.

Return value: Number of vault entries pruned on success, 0 on failure.
PHP Code:
new iVault;

iVault nvault_open"testvault" );

//Remove all entries in vault. 0 = earliest possible time, get_systime() = now.
nvault_pruneiVault get_systime() );

//Remove entries in vault that are 15 days old or more.
//get_systime() returns the current timestamp
//1 day = 86400 seconds = 60 secs * 60 mins * 24 hours
nvault_pruneiVault get_systime() - ( 15 86400 ) ); 
Timestamps
Timestamps in nvault are in unix-time format (aka POSIX time) which is equal to the number of seconds that have elapsed since midnight January 1, 1970. To prune or compare a timestamp retrieved in nvault_lookup, you can do simple multiplication to convert seconds to minutes, hours, days, or weeks. Example: Day = 60 * 60 * 24 = 86400.

In the above nvault_prune example it shows how to prune entries that are 15 days old or more. If you wanted to prune entries that are 10+ minutes old, you would do nvault_prune( iHandle , 0 , get_systime() - ( 60 * 10 ) ).

See this link for info on Unix Time: http://en.wikipedia.org/wiki/Unix_time
AMX-X include file for converting Unix Time <-> Normal Time: http://forums.alliedmods.net/showthread.php?t=91915
Convert Unix Time <-> Normal Time on the web: http://www.onlineconversion.com/unix_time.htm

Using nVault in your plugin
If you will be using nvault functions constantly throughout your plugin, it is best to keep the nvault file open while your plugin is running. To do this, use a global variable to hold the handle and call nvault_open() in plugin_init() or plugin_config() (or anywhere you choose). To close the vault, call nvault_close() in plugin_end().

nVault Limitations
The major things (IMO) that are missing in nVault is the ability to determine the number of entries in a vault, the ability to cycle through entries in a vault, and storing arrays. I created an include file, nVault Utility which provides this missing functionality. Just be advised, the nVault handle used with nVault and nVault Utility are *NOT* interchangeable, which means you will have 2 separate handles if you are working with both at the same time (ie. you cannot use the handle returned by nvault_open() with functions in nVault utility and vice-versa. The only exception for this is for the two functions nvault_set_array() and nvault_get_array(), which do use the handle returned by nvault_open().

Example Plugin
The below plugin shows how to do save a players money and score to the vault. When a user disconnects, these items are saved and when he re-connects they get restored.
Plugin
__________________

Last edited by Bugsy; 05-31-2015 at 12:32. Reason: Added nvault_remove() that was missed and add return values for all functions.
Bugsy is offline
fysiks
Veteran Member
Join Date: Sep 2007
Location: Flatland, USA
Old 05-02-2009 , 01:14   Re: nVault
Reply With Quote #2

Sweet, I was just looking for this tutorial the other day . I hope it's good .

EDIT: Read it.

Would there be file access issues if you tried to access a single nVault from two plugins? Just curious really.
__________________

Last edited by fysiks; 05-02-2009 at 01:30.
fysiks is offline
--kml--
Senior Member
Join Date: Jan 2009
Old 05-02-2009 , 03:30   Re: nVault
Reply With Quote #3

wooT thx for this tuto :O

+karma

edit:

seems like i cant give now, will try give later

and thx for the tut
--kml-- is offline
SchlumPF*
Veteran Member
Join Date: Mar 2007
Old 05-02-2009 , 07:46   Re: nVault
Reply With Quote #4

so many tutorials in such a small periode of time... gj although i never needed to use nvault, sql <3
__________________
SchlumPF* is offline
Send a message via ICQ to SchlumPF*
Nextra
Veteran Member
Join Date: Apr 2008
Location: Germany
Old 05-02-2009 , 08:22   Re: nVault
Reply With Quote #5

Well done. Nice to know but I will stay with (My)SQL(ite)
__________________
In Flames we trust!
Nextra is offline
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
Old 05-02-2009 , 10:18   Re: nVault
Reply With Quote #6

The overhead for SQL isn't always necessary for basic data storage. nVault also does not require the knowledge of how to write queries. nVault provides a very basic and easy to understand means of saving\retrieving data to an external file.
__________________

Last edited by Bugsy; 05-02-2009 at 10:44.
Bugsy is offline
SchlumPF*
Veteran Member
Join Date: Mar 2007
Old 05-02-2009 , 13:11   Re: nVault
Reply With Quote #7

Quote:
Originally Posted by Bugsy View Post
The overhead for SQL isn't always necessary for basic data storage. nVault also does not require the knowledge of how to write queries. nVault provides a very basic and easy to understand means of saving\retrieving data to an external file.
ofc it does but most things i did were very simple to create using ordinary textfiles. i mostly use sql cuz the data is shown in huge motd which are php files... i think you understand
__________________
SchlumPF* is offline
Send a message via ICQ to SchlumPF*
Exolent[jNr]
Veteran Member
Join Date: Feb 2007
Location: Tennessee
Old 05-02-2009 , 13:34   Re: nVault
Reply With Quote #8

Good job! I always wanted to know how to use the prune function.

PHP Code:
public cmdSaveScore(id)
{
    
//Save 2 items into the value of the entry.
    //Example: STEAM_0:0:1234 15 5

    
new szData[8];
    new 
szKey[40];
    
formatexszKey 39 "%sMONEY" g_szAuthID[id] );
    
formatexszData "%d %d" get_user_kills(id) , get_user_deaths(id) );

    
nvault_setg_Vault szKey szData );

    
client_printid print_chat "* Your score was saved to vault." );
}

public 
cmdGetScore(id)
{
    
//Read 2 items that that are saved in the same entry
    //Example: STEAM_0:0:1234 15 5

    
new szData[8];
    new 
szKey[40];
    
formatexszKey 39 "%sMONEY" g_szAuthID[id] );

    if ( 
nvault_getg_Vault szKey szData ) )
    {
        new 
iSpacePos containszData " " );
        new 
szKills[4];
        new 
szDeaths[4];
        
        if ( 
iSpacePos > -)
        {    
            
formatexszKills iSpacePos "%s" szData );
            
formatexszDeaths "%s" szDataiSpacePos ] );

            
set_user_killsid str_to_numszKills );
            
set_user_deathsid str_to_numszDeaths );

            
client_printid print_chat "* Your score was loaded: %s kills, %s deaths" szKills szDeaths );
        }
    }
    else
    {
        
client_printid print_chat "* You have no score entry in vault." );
    }

Don't you mean:
PHP Code:
formatexszKey 39 "%sSCORE" g_szAuthID[id] ); 
__________________
No private work or selling mods.
Quote:
Originally Posted by xPaw View Post
I love you exolent!
Exolent[jNr] is offline
Nextra
Veteran Member
Join Date: Apr 2008
Location: Germany
Old 05-02-2009 , 14:59   Re: nVault
Reply With Quote #9

Quote:
Originally Posted by Bugsy View Post
The overhead for SQL isn't always necessary for basic data storage. nVault also does not require the knowledge of how to write queries. nVault provides a very basic and easy to understand means of saving\retrieving data to an external file.
This is why I said I'm going to stick with SQL, since I know how to query it is not a problem for me . It's definitely a helpful and nice tutorial for everyone else but as long as it is not extremely incomplex, temporary or limited data that has to be stored I will always use SQL.

Question: I have a bad opinion about vaults ever since my old WC3 Server suffered from a huge XP-database and crashed on every mapchange. Is this still possible with nVault?
__________________
In Flames we trust!
Nextra is offline
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
Old 05-02-2009 , 15:32   Re: nVault
Reply With Quote #10

Quote:
Originally Posted by Nextra View Post
This is why I said I'm going to stick with SQL, since I know how to query it is not a problem for me . It's definitely a helpful and nice tutorial for everyone else but as long as it is not extremely incomplex, temporary or limited data that has to be stored I will always use SQL.

Question: I have a bad opinion about vaults ever since my old WC3 Server suffered from a huge XP-database and crashed on every mapchange. Is this still possible with nVault?
Even if querying isn't a problem for you it could still be overkill depending on what you are storing. If you are only storing a single item and only need to retrieve it based on a single key then it is a waste of CPU to use SQL. Whatever floats your boat though.

I've never had any issues with nVault. I have used it for all of my data saving needs.
__________________
Bugsy 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 04:37.


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