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

New File Vault - A newer file vault system!


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Emp`
AMX Mod X Plugin Approver
Join Date: Aug 2005
Location: Decapod 10
Old 05-21-2009 , 22:02   New File Vault - A newer file vault system!
Reply With Quote #1

This is another version of FVault modified for several things.


About New File Vault [top]
With New File Vault (NFV) data can be set under a file, key, and name.
This is useful when a plugin needs to save multiple datas per player. Additionally, it helps centralize saved data for server administrators.
NFV also works with files not in the nfvault folder. So it can be used for .ini and .cfg files for plugins.
Lastly, it adds additional features to previous natives/functions from other vaults.


Comparison to Other Vaults [top]
Retrieving Data [comparison] [top]
  • Vault:
    Code:
    get_vaultdata(const key[], data[] = "", len = 0);
  • NVault:
    Code:
    nvault_get(vault, const key[], {Float,_}:...);
  • FVault:
    Code:
    fvault_get_data(const vaultname[], const key[], data[], len);
  • NFVault:
    PHP Code:
    nfv_get_data(const filename[], const key[], name[], data[]=""len=0, const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0key_copy[]="", const key_len=0name_copy[]="", const name_len=0); 

Setting Data [comparison] [top]
  • Vault:
    Code:
    set_vaultdata(const key[], const data[] = "");
  • NVault:
    Code:
    nvault_set(vault, const key[], const value[]);
  • FVault:
    Code:
    fvault_set_data(const vaultname[], const key[], const data[]);
  • NFVault:
    PHP Code:
    nfv_set_data(const filename[], const key[], name[], data[], const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';'); 

Removing Data [comparison] [top]
  • Vault:
    Code:
    remove_vaultdata(const key[]);
  • NVault:
    Code:
    nvault_remove(vault, const key[]);
  • FVault:
    Code:
    fvault_remove_key(const vaultname[], const key[])
  • NFVault:
    PHP Code:
    nfv_take_data(const filename[], const key[], name[], data[]=""len=0, const take_times=1, const identifier=';'name_copy[]="", const name_len=0); 

Existing Data [comparison] [top]
  • Vault:
    Code:
    vaultdata_exists(const key[]);
  • NVault:
    Code:
    nvault_lookup(vault, const key[], value[], maxlen, &timestamp);
  • FVault:
    Code:
    fvault_get_keynum(const vaultname[], const key[]);
  • NFVault:
    PHP Code:
    nfv_get_data(const filename[], const key[], name[], data[]=""len=0, const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0key_copy[]="", const key_len=0name_copy[]="", const name_len=0); 

Pruning Data [comparison] [top]
  • Vault: Not Capable
  • NVault:
    Code:
    nvault_prune(vault, start, end);
  • FVault: Not Capable
  • NFVault:
    PHP Code:
    nfv_prune(const key[], name[], const start=-1, const end=-1, const identifier=';'); 

Touching Little Boys Data [comparison] [top]
  • Vault: Not Capable
  • NVault:
    Code:
    nvault_touch(vault, const key[], timestamp=-1);
  • FVault: Not Capable
  • NFVault:
    PHP Code:
    nfv_touch(const filename[], const new_time=-1); 


Advantages to Other Vaults [top]
  • Easy player saving with player functions
  • Compatible with all files, not just Vault files
  • When setting data, several extra properties to change about the data
  • When removing data, ability to save the data removed
  • No need to open/close files


Example Script and Output [top]
Here is an example of a simple script and its output:
Code:
    new filename[128];     copy( filename, 127, nfv_file("file.txt") );     nfv_set_data( filename, "key", "name", "data" );     nfv_set_data( filename, "key", "name2", "data2" );     nfv_set_data( filename, "key", "name2", "data_2" );     nfv_set_data( filename, "key", "name3", "data3" );     nfv_set_data( filename, "key", "name4", "data4" );     new take_string[10];     nfv_take_data( filename, "key", "name4", take_string, 9 );     // take_string == "data4"     nfv_set_data( filename, "key2", "other_name", "even_more_data" );     nfv_set_data( filename, "key2", "other_name", "even_more_data2", false );     nfv_set_data( filename, "key3", "name", "more_data" );     new get_string[10];     nfv_get_data( filename, "key3", "*", get_string, 9 );     // get_string == "more_data"
Code:
"TimeStamp" "1234567890"
;key
"name" "data"
"name2" "data_2"
"name3" "data3"
;key2
"other_name" "even_more_data"
"other_name" "even_more_data2"
;key3
"name" "more_data"

Defines and Constants [top]
Code:
//Used as a wildcard when one does not know the key or name for data #define NFV_WILDCARD "*"
Code:
//Used only for take data functions. #define NFV_TAKEALL -1
Code:
//Used for Player Functions #define NFV_SAVETYPE 0 // 0 - steamid ; 1 - name
Code:
//These should only be used with nfv_add_key enum NFV_TYPE {     //Integer Type     NFVT_INT,     //Boolean Type     NFVT_BOOL,     //Floating Point Type     NFVT_FLOAT,     //Integer Array Type     NFVT_ARRAY,     //Floating Point Vector Type     NFVT_VECTOR,     //String Type     NFVT_STRING,     //Cell Array of Integers     NFVT_CELLARRAY,     //Cell Array of Strings     NFVT_CELLARRAY2, }
Code:
enum NFV_PROP ( <<= 1 ) {     //No properties, none of the following will apply     NFV_NONE = 0,     //If data is found, it will be replaced with the new data     NFV_OVERWRITE = 1,     //Will not place quotes around name and data in the file     NFV_NO_QUOTES,     //Will not replace quotation marks in name and data     NFV_NO_REPLACE_QUOTE,     //If data is found, new data will not be written     NFV_IF_NOT_EXIST, }
Code:
//Quotation marks can mess up NFV stock const quote_char = '"'; //What to replace quotation marks with: an unused character, in notepad it is a square stock const quote_replace_char = 30; //The temp file used when editing files stock const temp_file_name[] = "temp_data_file.txt";


Basic Data Functions [top]
Code:
/**  * Sets data in file under key and name.  *  * @param filename    The file location for the data.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The data to write.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  * @return        1 if successful.  */ nfv_set_data(const filename[], const key[], name[], data[], const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Retrieves data in file under key and name.  *  * @param filename      The file location to search for the data.  * @param key            The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.  * @param name        The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data        The string that will contain the data retrieved.  * @param len            The size of the data string.  * @param identifier        The character used to identify different keys.  * @param key_tell_start    Where to start searching for key.  * @param key_tell_find  Where the key was found.  * @param name_tell_start   Where to start searching for name.  * @param name_tell_find    Where the name was found.  * @param key_copy      The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.  * @param key_len         If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.  * @param name_copy   The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.  * @param name_len      If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.  * @return          1 if data found.  */ nfv_get_data(const filename[], const key[], name[], data[]="", len=0, const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)

Code:
/**  * Retrieves data in file under key and name with reference to line numbers.  *  * @param filename      The file location to search for the data.  * @param key            The key within the file to look for. Set to "" for no key.  * @param name        The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data        The string that will contain the data retrieved.  * @param len            The size of the data string.  * @param identifier        The character used to identify different keys.  * @param key_line_start    Where to start searching for key.  * @param key_line_find  Where the key was found.  * @param name_line_start   Where to start searching for name.  * @param name_line_find    Where the name was found.  * @param name_copy   The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.  * @param name_len      If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.  * @return          1 if successful, 0 on failure.  */ nfv_get_linedata(const filename[], const key[], name[], data[]="", len=0, const identifier=';', const key_line_start=0, &key_line_find=0, const name_line_start=0, &name_line_find=0, name_copy[], const name_len=0)

Code:
/**  * Removes data in file under key and name.  *  * @param filename    The file location to search for the data.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The string that will contain the data removed.  * @param len         The size of the data string.  * @param take_times    How many times to take out of the file. Set to NFV_TAKEALL for all.  * @param identifier    The character used to identify different keys.  * @param name_copy  The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.  * @param name_len    If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.  * @return        How many datas were removed.  */ nfv_take_data(const filename[], const key[], name[], data[]="", len=0, const take_times=1, const identifier=';', name_copy[]="", const name_len=0)


Advanced Data Functions [top]
Code:
/**  * Sets multiple datas in file under key and name.  *  * @param filename    The file location for the data.  * @param key         The key within the file to look for. Set to "" for no key.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  *  * @note                The optional parameters are to add names and datas. They should be provided in the form:  *              NFVT_*, name[], data  *            The type NFVT_ARRAY needs a size provided after the data:  *              NFVT_ARRAY, name[], data[], size  *  * @param ...         NFVT_* constant for what type of data it is.  * @param ...         The name under key to look for.  * @param ...         The data to write that matches with the NFV_* constant.  *  * @example    nfv_add_key( filename[], key[], NFV_NO_QUOTES|NFV_IF_NOT_EXIST, ';',  *              NFVT_INT, int_name[], 1,  *              NFVT_BOOL, bool_name[], true,  *              NFVT_FLOAT, float_name[], 1.0,  *              NFVT_ARRAY, array_name[], any:array[], sizeof array,  *              NFVT_VECTOR, vector_name[], Float:vec[3],  *              NFVT_STRING, string_name[], string[],  *              NFVT_CELLARRAY, cellarray_name[], Array:cellarray,  *              NFVT_CELLARRAY2, cellarray2_name[], Array:cellarray2  *            )  *  * @return        1 if successful.  */ nfv_add_key(const filename[], const key[], const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';', any:...)

Code:
/**  * Switches two key's in a file.  *  * @param filename    The file location for the data.  * @param key1      The first key to switch.  * @param key2      The second key to switch.  * @param identifier    The character used to identify different keys.  *  * @note                Data under key1 will switch to key2. Data under key2 will switch to key1.  *  * @return        1 if successful.  */ nfv_switch_keys(const filename[], const key1[], const key2[], const identifier=';')

Code:
/**  * Changes data from one key to another in a file.  *  * @param filename    The file location for the data.  * @param key1      The key to change from.  * @param key2      The key to change to.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  *  * @note                Data under key1 will change to key2.  *  * @return        Returns how many keys were switched.  */ nfv_change_key(const filename[], const key1[], const key2[], const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Removes all data under a key in a file.  *  * @param filename    The file location for the data.  * @param key         The key to remove from.  * @param identifier    The character used to identify different keys.  * @return        Returns how many datas were removed with the key.  */ nfv_remove_key(const filename[], const key[], const identifier=';')


Tagged Data Functions [top]
Code:
/**  * Sets data as number in file under key and name.  *  * @param filename    The file location for the data.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The number to write.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  * @return        1 if successful.  */ nfv_set_num(const filename[], const key[], name[], const data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Adds to a pre-existing data number in file under key and name.  *  * @param filename    The file location for the data.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The number to add.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  *  * @note                Will assume NFV_OVERWRITE is in nfv_prop and ignore NFV_IF_NOT_EXIST  *  * @return        Returns new data.  */ nfv_add_num(const filename[], const key[], name[], const data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Sets data as a floating point in file under key and name.  *  * @param filename    The file location for the data.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The floating point to write.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  * @return        1 if successful.  */ nfv_set_float(const filename[], const key[], name[], const Float:data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Adds to pre-existing floating point data in file under key and name.  *  * @param filename    The file location for the data.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The floating point to add.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  *  * @note                Will assume NFV_OVERWRITE is in nfv_prop and ignore NFV_IF_NOT_EXIST  *  * @return        Returns new data.  */ Float:nfv_add_float(const filename[], const key[], name[], const Float:data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Sets data as bool in file under key and name.  *  * @param filename    The file location for the data.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The boolean value to write.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  * @return        1 if successful.  */ nfv_set_bool(const filename[], const key[], name[], const bool:data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Sets data to the opposite of what it was in file under key and name.  *  * @param filename    The file location for the data.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  *  * @note                Will assume NFV_OVERWRITE is in nfv_prop and ignore NFV_IF_NOT_EXIST  *  * @return        Returns new data.  */ bool:nfv_xor_bool(const filename[], const key[], name[], const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Sets data as a vector in file under key and name.  *  * @param filename    The file location for the data.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The vector to write.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  * @return        1 if successful.  */ nfv_set_vec(const filename[], const key[], name[], const Float:data[3], const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Sets data as an array in file under key and name.  *  * @param filename    The file location for the data.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The array to write.  * @param array_size    The size of the array.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  *  * @note                This will save each element as the integer form  *  * @return        1 if successful.  */ nfv_set_array(const filename[], const key[], name[], const any:data[], const array_size, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Sets data as an array in file under key and name.  *  * @param filename    The file location for the data.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The cell array to write.  * @param array_size    The size of the array.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  *  * @note                This will save each element as the integer form  *  * @return        1 if successful.  */ nfv_set_cellarray(const filename[], const key[], name[], const Array:data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Sets data as array of strings in file under key and name.  *  * @param filename    The file location for the data.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The cell array to write.  * @param array_size    The size of the array.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  *  * @note                This will save in the form: "first","second","third","etc."  *  * @return        1 if successful.  */ nfv_set_cellarray2(const filename[], const key[], name[], const Array:data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Retrieves data as number form in file under key and name.  *  * @param filename      The file location to search for the data.  * @param key            The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.  * @param name        The name under key to look for. Set to NFV_WILDCARD for any name.  * @param identifier        The character used to identify different keys.  * @param key_tell_start    Where to start searching for key.  * @param key_tell_find  Where the key was found.  * @param name_tell_start   Where to start searching for name.  * @param name_tell_find    Where the name was found.  * @param key_copy      The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.  * @param key_len         If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.  * @param name_copy   The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.  * @param name_len      If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.  * @return          Numeric value of data found. 0 if no data.  */ nfv_get_num(const filename[], const key[], name[], const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)

Code:
/**  * Retrieves data as floating point form in file under key and name.  *  * @param filename      The file location to search for the data.  * @param key            The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.  * @param name        The name under key to look for. Set to NFV_WILDCARD for any name.  * @param identifier        The character used to identify different keys.  * @param key_tell_start    Where to start searching for key.  * @param key_tell_find  Where the key was found.  * @param name_tell_start   Where to start searching for name.  * @param name_tell_find    Where the name was found.  * @param key_copy      The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.  * @param key_len         If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.  * @param name_copy   The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.  * @param name_len      If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.  * @return          Floating point value of data found. 0.0 if no data.  */ Float:nfv_get_float(const filename[], const key[], name[], const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)

Code:
/**  * Retrieves data as boolean form in file under key and name.  *  * @param filename      The file location to search for the data.  * @param key            The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.  * @param name        The name under key to look for. Set to NFV_WILDCARD for any name.  * @param identifier        The character used to identify different keys.  * @param key_tell_start    Where to start searching for key.  * @param key_tell_find  Where the key was found.  * @param name_tell_start   Where to start searching for name.  * @param name_tell_find    Where the name was found.  * @param key_copy      The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.  * @param key_len         If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.  * @param name_copy   The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.  * @param name_len      If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.  * @return          Boolean value of data found. False if no data.  */ bool:nfv_get_bool(const filename[], const key[], name[], const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)

Code:
/**  * Retrieves data as array form in file under key and name.  *  * @param filename      The file location to search for the data.  * @param key            The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.  * @param name        The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data        The array that will contain the data retrieved.  * @param size        The size of the data array.  * @param identifier        The character used to identify different keys.  * @param key_tell_start    Where to start searching for key.  * @param key_tell_find  Where the key was found.  * @param name_tell_start   Where to start searching for name.  * @param name_tell_find    Where the name was found.  * @param key_copy      The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.  * @param key_len         If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.  * @param name_copy   The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.  * @param name_len      If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.  * @return          Whether or not data was found.  */ nfv_get_array(const filename[], const key[], name[], any:data[], const size, const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)

Code:
/**  * Retrieves data as vector form in file under key and name.  *  * @param filename      The file location to search for the data.  * @param key            The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.  * @param name        The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data        The vector that will contain the data retrieved.  * @param identifier        The character used to identify different keys.  * @param key_tell_start    Where to start searching for key.  * @param key_tell_find  Where the key was found.  * @param name_tell_start   Where to start searching for name.  * @param name_tell_find    Where the name was found.  * @param key_copy      The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.  * @param key_len         If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.  * @param name_copy   The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.  * @param name_len      If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.  * @return          Whether or not data was found.  */ nfv_get_vec(const filename[], const key[], name[], Float:data[3], const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)

Code:
/**  * Retrieves data as cellarray form in file under key and name.  *  * @param filename      The file location to search for the data.  * @param key            The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.  * @param name        The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data        The cell array that will contain the data retrieved.  * @param identifier        The character used to identify different keys.  * @param key_tell_start    Where to start searching for key.  * @param key_tell_find  Where the key was found.  * @param name_tell_start   Where to start searching for name.  * @param name_tell_find    Where the name was found.  * @param key_copy      The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.  * @param key_len         If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.  * @param name_copy   The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.  * @param name_len      If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.  *  * @note                    If an existing cell array is provided, it will push new data to the end of it.  *  * @return          The cell array handle. Invalid_Array if no data.  */ Array:nfv_get_cellarray(const filename[], const key[], name[], &Array:data=Invalid_Array, const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)

Code:
/**  * Retrieves data as cellarray string form in file under key and name.  *  * @param filename      The file location to search for the data.  * @param key            The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.  * @param name        The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data        The cell array that will contain the data retrieved.  * @param identifier        The character used to identify different keys.  * @param key_tell_start    Where to start searching for key.  * @param key_tell_find  Where the key was found.  * @param name_tell_start   Where to start searching for name.  * @param name_tell_find    Where the name was found.  * @param key_copy      The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.  * @param key_len         If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.  * @param name_copy   The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.  * @param name_len      If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.  *  * @note                    If an existing cell array is provided, it will push new strings to the end of it.  *  * @return          The cell array handle. Invalid_Array if no data.  */ Array:nfv_get_cellarray2(const filename[], const key[], name[], &Array:data=Invalid_Array, const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)


Prune and Touch [top]
Code:
/**  * Removes data in all files in the NFVault folder.  *  * @param key         The key within the file to remove data.  * @param start   Checks if last TimeStamp is after this UnixTime. Set to -1 to prune all.  * @param end         Checks if last TimeStamp is before this UnixTime. Set to -1 to prune all.  * @noreturn  */ nfv_prune(const key[], const start=-1, const end=-1)

Code:
/**  * Updates a file's TimeStamp  *  * @param filename    The file to be touched.  * @param new_time    Timestamp to set for the file in Unix time. Set to -1 for current time.  * @return        1 if successful.  */ nfv_touch(const filename[], const new_time=-1)


File Functions [top]
Code:
/**  * Finds a player's unique save key  *  * @param id            The index of the client.  * @return        Returns string containing the key.  */ PlayerSaveKey(id)

Code:
/**  * Returns a file in the nfvault folder  *  * @param filename    The filename and extension of the file.  * @param filepath    The entire path, filename and extension of the file is returned if size is > 0.  * @param size      The size to fill filepath with. Set to 0 to ignore.  * @return        Returns string containing the nfvault file.  */ nfv_file(const filename[], filepath[]="", const size=0)

Code:
/**  * Creates a file with a TimeStamp.  *  * @param filename    The file location for the data.  * @param new_time    Timestamp to set for the file in Unix time. Set to -1 for current time.  * @return        1 if created, -1 on existing, 0 on failure.  */ nfv_create_file(const filename[], const new_time=-1)


Player Functions [top]
Code:
/**  * Finds a player's unique save file  *  * @param id            The index of the client.  * @return        Returns string containing the file.  */ nfv_player_file(const id)

Code:
/**  * Sets data for a player under key and name.  *  * @param id            The index of the client.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The data to write.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  * @return        1 if successful.  */ player_set_data(const id, const key[], name[], data[], const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Retrieves data for a player under key and name.  *  * @param id            The index of the client.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The string that will contain the data retrieved.  * @param len         The size of the data string.  * @param identifier    The character used to identify different keys.  * @return        1 if successful.  */ player_get_data(const id, const key[], name[], data[]="", len=0, const identifier=';')

Code:
/**  * Removes data for a player under key and name.  *  * @param id            The index of the client.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The string that will contain the data removed.  * @param len         The size of the data string.  * @param take_times    How many times to take out of the file. Set to NFV_TAKEALL for all.  * @param identifier    The character used to identify different keys.  * @return        How many datas were removed.  */ player_take_data(const id, const key[], name[], data[]="", len=0, const take_times=1, const identifier=';')


Player Tagged Functions [top]
Code:
/**  * Sets number for a player under key and name.  *  * @param id            The index of the client.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The number to write.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  * @return        1 if successful.  */ player_set_num(const id, const key[], name[], const data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Adds number for a player under key and name.  *  * @param id            The index of the client.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The number to write.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  * @return        1 if successful.  */ player_add_num(const id, const key[], name[], const data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Sets float for a player under key and name.  *  * @param id            The index of the client.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The floating point to write.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  * @return        1 if successful.  */ player_set_float(const id, const key[], name[], const Float:data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Adds a float for a player under key and name.  *  * @param id            The index of the client.  * @param key         The key within the file to look for. Set to "" for no key.  * @param name      The name under key to look for. Set to NFV_WILDCARD for any name.  * @param data      The floating point to write.  * @param nfv_prop    Properties to apply to the saved data in a bitsum.  * @param identifier    The character used to identify different keys.  * @return        1 if successful.  */ player_add_float(const id, const key[], name[], const Float:data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')

Code:
/**  * Retrieves data as a number for a player under key and name.  *  * @param id                The index of the client.  * @param key            The key within the file to look for. Set to "" for no key.  * @param name        The name under key to look for. Set to NFV_WILDCARD for any name.  * @param identifier        The character used to identify different keys.  * @return          Numeric value of data found. 0 if no data.  */ player_get_num(const id, const key[], name[], const identifier=';')

Code:
/**  * Retrieves data as a float for a player under key and name.  *  * @param id                The index of the client.  * @param key            The key within the file to look for. Set to "" for no key.  * @param name        The name under key to look for. Set to NFV_WILDCARD for any name.  * @param identifier        The character used to identify different keys.  * @return          Floating point value of data found. 0.0 if no data.  */ Float:player_get_float(const id, const key[], name[], const identifier=';')


Extra String Functions [top]
Code:
/**  * Cleans a filename of invalid characters  *  * @param string        The string to clean.  * @param output        The cleaned string.  * @param len         The length of output to fill.  * @return        Returns 1 on success.  */ nfv_string_clean( const string[], output[], len )

Code:
/**  * Replaces quotation marks with the replacement character.  *  * @param string        The string to clean.  * @noreturn  */ nfv_replace_quote( string[] )

Code:
/**  * Replaces replacement characters with a quotation mark.  *  * @param string        The string to clean.  * @noreturn  */ nfv_return_quote( string[] )

Code:
/**  * Returns whether a string should be true or false  *  * @param string        The string to look at.  * @return        Returns true or false.  */ bool:str_to_bool( const string[] )

Code:
/**  * Fills an array with numbers from a string  *  * @param string        The string to look at.  * @param array   The array to fill.  * @param size      The size of the array.  * @noreturn  */ str_to_array( const string[], array[], const size )

Code:
/**  * Fills a vector with numbers from a string  *  * @param string        The string to look at.  * @param vec         The vector to fill.  * @noreturn  */ str_to_vector( const string[], Float:vec[3] )

Code:
/**  * Pushes cells into a cell array with numbers from a string  *  * @param string        The string to look at.  * @param array   The cell array to push into. If none provided, it creates one.  * @return        Returns the cell array handle.  */ Array:str_to_cellarray( const string[], &Array:array=Invalid_Array )

Code:
/**  * Pushes strings into a cell array with substrings from a string  *  * @param string        The string to look at.  * @param array   The cell array to push into. If none provided, it creates one.  * @return        Returns the cell array handle.  */ Array:str_to_cellarray2( const string[], &Array:array=Invalid_Array )


nfvault.inc [top]
Code:
#if defined _nfvault_included
	#endinput
#endif
#define _nfvault_included

#if !defined NFV_WILDCARD
	#define NFV_WILDCARD "*"
#endif

#if !defined NFV_TAKEALL
	#define NFV_TAKEALL -1
#endif

#if !defined NFV_SAVETYPE
	#define NFV_SAVETYPE 0 // 0 - steamid ; 1 - name
#endif



/* This is an example script for using the basic nfvault stocks

	new filename[128];
	copy( filename, charsmax(filename), nfv_file("file.txt") );
	nfv_set_data( filename, "key", "name", "data" );
	nfv_set_data( filename, "key", "name2", "data2" );
	nfv_set_data( filename, "key", "name2", "data_2" );
	nfv_set_data( filename, "key", "name3", "data3" );
	nfv_set_data( filename, "key", "name4", "data4" );
	new take_string[10];
	nfv_take_data( filename, "key", "name4", take_string, 9 );
	// take_string == "data4"

	nfv_set_data( filename, "key2", "other_name", "even_more_data" );
	nfv_set_data( filename, "key2", "other_name", "even_more_data2", false );

	nfv_set_data( filename, "key3", "name", "more_data" );
	new get_string[10];
	nfv_get_data( filename, "key3", NFV_WILDCARD, get_string, 9 );
	// get_string == "more_data"

// This is an example of the file for the preceding script

"TimeStamp" "1234567890"
;key
"name" "data"
"name2" "data_2"
"name3" "data3"
;key2
"other_name" "even_more_data"
"other_name" "even_more_data2"
;key3
"name" "more_data"

*/

enum NFV_TYPE
{
	NFVT_INT,
	NFVT_BOOL,
	NFVT_FLOAT,
	NFVT_ARRAY,
	NFVT_VECTOR,
	NFVT_STRING,
	NFVT_CELLARRAY,
	NFVT_CELLARRAY2,
}

enum NFV_PROP ( <<= 1 )
{
	NFV_NONE = 0,
	NFV_OVERWRITE = 1,
	NFV_NO_QUOTES,
	NFV_NO_REPLACE_QUOTE,
	NFV_IF_NOT_EXIST,
}

stock const quote_char = '"'; 			//this can mess up NFV
stock const quote_replace_char = 30; 	//an unused character, in notepad it is a square
stock const temp_file_name[] = "temp_data_file.txt";
stock DataDir[128];

/**
 * Sets multiple datas in file under key and name.
 *
 * @param filename		The file location for the data.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 *
 * @note				The optional parameters are to add names and datas. They should be provided in the form:
 *							NFVT_*, name[], data
 *						The type NFVT_ARRAY needs a size provided after the data:
 *							NFVT_ARRAY, name[], data[], size
 *
 * @param ...			NFVT_* constant for what type of data it is.
 * @param ...			The name under key to look for.
 * @param ...			The data to write that matches with the NFV_* constant.
 *
 * @example				nfv_add_key( filename[], key[], NFV_NO_QUOTES|NFV_IF_NOT_EXIST, ';',
 *							NFVT_INT, int_name[], 1,
 *							NFVT_BOOL, bool_name[], true,
 *							NFVT_FLOAT, float_name[], 1.0,
 *							NFVT_ARRAY, array_name[], any:array[], sizeof array,
 *							NFVT_VECTOR, vector_name[], Float:vec[3],
 *							NFVT_STRING, string_name[], string[],
 *							NFVT_CELLARRAY, cellarray_name[], Array:cellarray,
 *							NFVT_CELLARRAY2, cellarray2_name[], Array:cellarray2
 *						)
 *
 * @return				1 if successful.
 */
stock nfv_add_key(const filename[], const key[], const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';', any:...)
{
	new argnum = numargs();
	if( argnum == 4 )
	{
		nfv_set_data(filename, key, "", "", nfv_prop, identifier);
	}
	else
	{
		new tempname[64], tempdata[128], Float:vec[3], tempsize;
		for( new i=4, j=0; i<argnum; i+=3 )
		{
			j=0;
			do tempname[j] = getarg(i+1, j);
			while( tempname[j++] != '^0' && j < 64 );
			switch( getarg(i) )
			{
				case NFVT_INT:
				{
					nfv_set_num(filename, key, tempname, getarg(i+2), nfv_prop, identifier);
				}
				case NFVT_BOOL:
				{
					nfv_set_bool(filename, key, tempname, bool:getarg(i+2), nfv_prop, identifier);
				}
				case NFVT_FLOAT:
				{
					nfv_set_float(filename, key, tempname, Float:getarg(i+2), nfv_prop, identifier);
				}
				case NFVT_ARRAY:
				{
					tempsize = min( 128, getarg(i+3) );
					for( j=0; j < tempsize; j++ )
						tempdata[j] = getarg(i+2, j);
					nfv_set_array(filename, key, tempname, tempdata, tempsize, nfv_prop, identifier);
					i++;	//increase by an extra one for the size
				}
				case NFVT_VECTOR:
				{
					for( j=0; j<3; j++ )
						vec[j] = Float:getarg(i+2, j);
					nfv_set_vec(filename, key, tempname, vec, nfv_prop, identifier);
				}
				case NFVT_STRING:
				{
					j=0;
					do tempdata[j] = getarg(i+2, j);
					while( tempdata[j++] != '^0' && j < 128 );
					nfv_set_data(filename, key, tempname, tempdata, nfv_prop, identifier);
				}
				case NFVT_CELLARRAY:
				{
					nfv_set_cellarray(filename, key, tempname, Array:getarg(i+2), nfv_prop, identifier);
				}
				case NFVT_CELLARRAY2:
				{
					nfv_set_cellarray2(filename, key, tempname, Array:getarg(i+2), nfv_prop, identifier);
				}
			}
		}
	}
}

/**
 * Sets data in file under key and name.
 *
 * @param filename		The file location for the data.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The data to write.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 * @return				1 if successful.
 */
stock nfv_set_data(const filename[], const key[], name[], data[], const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
{
	new g = fopen(temp_file_name, "wt");
	new f = fopen(filename, "rt");

	// lets put a time stamp
	fprintf(g, "^"TimeStamp^" ^"%d^"^n", get_systime() );

	new _data[512], _name[64], _other[3];

	new bool:wrote_data = false, bool:found_key = false, bool:found_time = false;

	if( !(nfv_prop&NFV_NO_REPLACE_QUOTE) )
	{
		nfv_replace_quote( name );
		nfv_replace_quote( data );
	}

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));

		if( !found_time )
		{
			if( equal(_data, "^"TimeStamp^"", 11) )
			{
				found_time = true;
				continue;
			}
		}
		if( _data[0] == identifier )
		{
			//if found key and wrote data continue and copy to g
			//    if didnt copy data, write data before copying to g
			if( found_key )
			{
				if( !wrote_data )
				{
					fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %s^n" : "^"%s^" ^"%s^"^n", name, data);
					wrote_data = true;
				}
			}
			//else check if correct key, copy to g
			else
			{
				//Make sure we get something parsed
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( _name, key ) )
						found_key = true;
				}
			}

			fputs(g, _data);
		}
		else
		{
			if( !wrote_data )
			{
				if( nfv_prop&NFV_OVERWRITE )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, write data to g, skip copy
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %s^n" : "^"%s^" ^"%s^"^n", name, data);
							wrote_data = true;
							continue;
						}
					}
				}
				else if( nfv_prop&NFV_IF_NOT_EXIST )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, stop, close files, delete temp file, return 0
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							fclose(g);
							fclose(f);

							delete_file(temp_file_name);

							return 0;
						}
					}
				}
			}

			//else copy to g
			fputs(g, _data);
		}
	}

	if( !found_key )
	{
		fprintf(g, "%c%s^n", identifier, key);
	}
	if( !wrote_data )
	{
		fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %s^n" : "^"%s^" ^"%s^"^n", name, data);
	}

	fclose(g);
	fclose(f);

	delete_file(filename);

	while( !rename_file(temp_file_name, filename, 1) ) { }

	return 1;
}

/**
 * Sets data as number in file under key and name.
 *
 * @param filename		The file location for the data.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The number to write.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 * @return				1 if successful.
 */
stock nfv_set_num(const filename[], const key[], name[], const data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
{
	new g = fopen(temp_file_name, "wt");
	new f = fopen(filename, "rt");

	// lets put a time stamp
	fprintf(g, "^"TimeStamp^" ^"%d^"^n", get_systime() );

	new _data[512], _name[64], _other[3];

	new bool:wrote_data = false, bool:found_key = false, bool:found_time = false;

	if( !(nfv_prop&NFV_NO_REPLACE_QUOTE) )
	{
		nfv_replace_quote( name );
	}

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));

		if( !found_time )
		{
			if( equal(_data, "^"TimeStamp^"", 11) )
			{
				found_time = true;
				continue;
			}
		}
		if( _data[0] == identifier )
		{
			//if found key and wrote data continue and copy to g
			//    if didnt copy data, write data before copying to g
			if( found_key )
			{
				if( !wrote_data )
				{
					fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %d^n" : "^"%s^" ^"%d^"^n", name, data);
					wrote_data = true;
				}
			}
			//else check if correct key, copy to g
			else
			{
				//Make sure we get something parsed
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( _name, key ) )
						found_key = true;
				}
			}

			fputs(g, _data);
		}
		else
		{
			if( !wrote_data )
			{
				if( nfv_prop&NFV_OVERWRITE )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, write data to g, skip copy
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %d^n" : "^"%s^" ^"%d^"^n", name, data);
							wrote_data = true;
							continue;
						}
					}
				}
				else if( nfv_prop&NFV_IF_NOT_EXIST )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, stop, close files, delete temp file, return 0
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							fclose(g);
							fclose(f);

							delete_file(temp_file_name);

							return 0;
						}
					}
				}
			}

			//else copy to g
			fputs(g, _data);
		}
	}

	if( !found_key )
	{
		fprintf(g, "%c%s^n", identifier, key);
	}
	if( !wrote_data )
	{
		fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %d^n" : "^"%s^" ^"%d^"^n", name, data);
	}

	fclose(g);
	fclose(f);

	delete_file(filename);

	while( !rename_file(temp_file_name, filename, 1) ) { }

	return 1;
}

/**
 * Adds to a pre-existing data number in file under key and name.
 *
 * @param filename		The file location for the data.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The number to add.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 *
 * @note				Will assume NFV_OVERWRITE is in nfv_prop and ignore NFV_IF_NOT_EXIST
 *
 * @return				Returns new data.
 */
stock nfv_add_num(const filename[], const key[], name[], const data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
{
	new g = fopen(temp_file_name, "wt");
	new f = fopen(filename, "rt");

	// lets put a time stamp
	fprintf(g, "^"TimeStamp^" ^"%d^"^n", get_systime() );

	new _data[512], _name[64], _other[64], _value = data;

	new bool:wrote_data = false, bool:found_key = false, bool:found_time = false;

	if( !(nfv_prop&NFV_NO_REPLACE_QUOTE) )
	{
		nfv_replace_quote( name );
	}

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));

		if( !found_time )
		{
			if( equal(_data, "^"TimeStamp^"", 11) )
			{
				found_time = true;
				continue;
			}
		}
		if( _data[0] == identifier )
		{
			//if found key and wrote data continue and copy to g
			//    if didnt copy data, write data before copying to g
			if( found_key )
			{
				if( !wrote_data )
				{
					fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %d^n" : "^"%s^" ^"%d^"^n", name, data);
					wrote_data = true;
				}
			}
			//else check if correct key, copy to g
			else
			{
				//Make sure we get something parsed
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( _name, key ) )
						found_key = true;
				}
			}

			fputs(g, _data);
		}
		else
		{
			if( found_key && !wrote_data )
			{
				//Make sure we get something parsed
				if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
				{
					//if name matches, write data to g, skip copy
					if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
					{
						_value = data + str_to_num(_other);
						fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %d^n" : "^"%s^" ^"%d^"^n", name, _value );
						wrote_data = true;
						continue;
					}
				}
			}
			//else copy to g
			fputs(g, _data);
		}
	}

	if( !found_key )
	{
		fprintf(g, "%c%s^n", identifier, key);
	}
	if( !wrote_data )
	{
		fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %d^n" : "^"%s^" ^"%d^"^n", name, data);
	}

	fclose(g);
	fclose(f);

	delete_file(filename);

	while( !rename_file(temp_file_name, filename, 1) ) { }

	return _value;
}

/**
 * Sets data as a floating point in file under key and name.
 *
 * @param filename		The file location for the data.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The floating point to write.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 * @return				1 if successful.
 */
stock nfv_set_float(const filename[], const key[], name[], const Float:data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
{
	new g = fopen(temp_file_name, "wt");
	new f = fopen(filename, "rt");

	// lets put a time stamp
	fprintf(g, "^"TimeStamp^" ^"%d^"^n", get_systime() );

	new _data[512], _name[64], _other[3];

	new bool:wrote_data = false, bool:found_key = false, bool:found_time = false;

	if( !(nfv_prop&NFV_NO_REPLACE_QUOTE) )
	{
		nfv_replace_quote( name );
	}

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));

		if( !found_time )
		{
			if( equal(_data, "^"TimeStamp^"", 11) )
			{
				found_time = true;
				continue;
			}
		}
		if( _data[0] == identifier )
		{
			//if found key and wrote data continue and copy to g
			//    if didnt copy data, write data before copying to g
			if( found_key )
			{
				if( !wrote_data )
				{
					fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %f^n" : "^"%s^" ^"%f^"^n", name, data);
					wrote_data = true;
				}
			}
			//else check if correct key, copy to g
			else
			{
				//Make sure we get something parsed
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( _name, key ) )
						found_key = true;
				}
			}

			fputs(g, _data);
		}
		else
		{
			if( !wrote_data )
			{
				if( nfv_prop&NFV_OVERWRITE )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, write data to g, skip copy
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %f^n" : "^"%s^" ^"%f^"^n", name, data);
							wrote_data = true;
							continue;
						}
					}
				}
				else if( nfv_prop&NFV_IF_NOT_EXIST )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, stop, close files, delete temp file, return 0
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							fclose(g);
							fclose(f);

							delete_file(temp_file_name);

							return 0;
						}
					}
				}
			}

			//else copy to g
			fputs(g, _data);
		}
	}

	if( !found_key )
	{
		fprintf(g, "%c%s^n", identifier, key);
	}
	if( !wrote_data )
	{
		fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %f^n" : "^"%s^" ^"%f^"^n", name, data);
	}

	fclose(g);
	fclose(f);

	delete_file(filename);

	while( !rename_file(temp_file_name, filename, 1) ) { }

	return 1;
}

/**
 * Adds to pre-existing floating point data in file under key and name.
 *
 * @param filename		The file location for the data.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The floating point to add.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 *
 * @note				Will assume NFV_OVERWRITE is in nfv_prop and ignore NFV_IF_NOT_EXIST
 *
 * @return				Returns new data.
 */
stock Float:nfv_add_float(const filename[], const key[], name[], const Float:data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
{
	new g = fopen(temp_file_name, "wt");
	new f = fopen(filename, "rt");

	// lets put a time stamp
	fprintf(g, "^"TimeStamp^" ^"%d^"^n", get_systime() );

	new _data[512], _name[64], _other[64], Float:_value=data;

	new bool:wrote_data = false, bool:found_key = false, bool:found_time = false;

	if( !(nfv_prop&NFV_NO_REPLACE_QUOTE) )
	{
		nfv_replace_quote( name );
	}

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));

		if( !found_time )
		{
			if( equal(_data, "^"TimeStamp^"", 11) )
			{
				found_time = true;
				continue;
			}
		}
		if( _data[0] == identifier )
		{
			//if found key and wrote data continue and copy to g
			//    if didnt copy data, write data before copying to g
			if( found_key )
			{
				if( !wrote_data )
				{
					fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %f^n" : "^"%s^" ^"%f^"^n", name, data);
					wrote_data = true;
				}
			}
			//else check if correct key, copy to g
			else
			{
				//Make sure we get something parsed
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( _name, key ) )
						found_key = true;
				}
			}

			fputs(g, _data);
		}
		else
		{
			if( found_key && !wrote_data )
			{
				//Make sure we get something parsed
				if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
				{
					//if name matches, write data to g, skip copy
					if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
					{
						_value = data + str_to_float(_other);
						fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %f^n" : "^"%s^" ^"%f^"^n", name, _value );
						wrote_data = true;
						continue;
					}
				}
			}
			//else copy to g
			fputs(g, _data);
		}
	}

	if( !found_key )
	{
		fprintf(g, "%c%s^n", identifier, key);
	}
	if( !wrote_data )
	{
		fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %f^n" : "^"%s^" ^"%f^"^n", name, data);
	}

	fclose(g);
	fclose(f);

	delete_file(filename);

	while( !rename_file(temp_file_name, filename, 1) ) { }

	return _value;
}

/**
 * Sets data as bool in file under key and name.
 *
 * @param filename		The file location for the data.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The boolean value to write.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 * @return				1 if successful.
 */
stock nfv_set_bool(const filename[], const key[], name[], const bool:data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
{
	new g = fopen(temp_file_name, "wt");
	new f = fopen(filename, "rt");

	// lets put a time stamp
	fprintf(g, "^"TimeStamp^" ^"%d^"^n", get_systime() );

	new _data[512], _name[64], _other[3];

	new bool:wrote_data = false, bool:found_key = false, bool:found_time = false;

	if( !(nfv_prop&NFV_NO_REPLACE_QUOTE) )
	{
		nfv_replace_quote( name );
	}

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));

		if( !found_time )
		{
			if( equal(_data, "^"TimeStamp^"", 11) )
			{
				found_time = true;
				continue;
			}
		}
		if( _data[0] == identifier )
		{
			//if found key and wrote data continue and copy to g
			//    if didnt copy data, write data before copying to g
			if( found_key )
			{
				if( !wrote_data )
				{
					if( nfv_prop&NFV_NO_QUOTES )
						fprintf(g, data ? "%s true^n" : "%s false^n", name);
					else
						fprintf(g, data ? "^"%s^" ^"true^"^n" : "^"%s^" ^"false^"^n", name);
					wrote_data = true;
				}
			}
			//else check if correct key, copy to g
			else
			{
				//Make sure we get something parsed
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( _name, key ) )
						found_key = true;
				}
			}

			fputs(g, _data);
		}
		else
		{
			if( !wrote_data )
			{
				if( nfv_prop&NFV_OVERWRITE )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, write data to g, skip copy
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							if( nfv_prop&NFV_NO_QUOTES )
								fprintf(g, data ? "%s true^n" : "%s false^n", name);
							else
								fprintf(g, data ? "^"%s^" ^"true^"^n" : "^"%s^" ^"false^"^n", name);
							wrote_data = true;
							continue;
						}
					}
				}
				else if( nfv_prop&NFV_IF_NOT_EXIST )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, stop, close files, delete temp file, return 0
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							fclose(g);
							fclose(f);

							delete_file(temp_file_name);

							return 0;
						}
					}
				}
			}

			//else copy to g
			fputs(g, _data);
		}
	}

	if( !found_key )
	{
		fprintf(g, "%c%s^n", identifier, key);
	}
	if( !wrote_data )
	{
		if( nfv_prop&NFV_NO_QUOTES )
			fprintf(g, data ? "%s true^n" : "%s false^n", name);
		else
			fprintf(g, data ? "^"%s^" ^"true^"^n" : "^"%s^" ^"false^"^n", name);
	}

	fclose(g);
	fclose(f);

	delete_file(filename);

	while( !rename_file(temp_file_name, filename, 1) ) { }

	return 1;
}

/**
 * Sets data to the opposite of what it was in file under key and name.
 *
 * @param filename		The file location for the data.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 *
 * @note				Will assume NFV_OVERWRITE is in nfv_prop and ignore NFV_IF_NOT_EXIST
 *
 * @return				Returns new data.
 */
stock bool:nfv_xor_bool(const filename[], const key[], name[], const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
{
	new g = fopen(temp_file_name, "wt");
	new f = fopen(filename, "rt");

	// lets put a time stamp
	fprintf(g, "^"TimeStamp^" ^"%d^"^n", get_systime() );

	new _data[512], _name[64], _other[64], bool:_value = true;

	new bool:wrote_data = false, bool:found_key = false, bool:found_time = false;

	if( !(nfv_prop&NFV_NO_REPLACE_QUOTE) )
	{
		nfv_replace_quote( name );
	}

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));

		if( !found_time )
		{
			if( equal(_data, "^"TimeStamp^"", 11) )
			{
				found_time = true;
				continue;
			}
		}
		if( _data[0] == identifier )
		{
			//if found key and wrote data continue and copy to g
			//    if didnt copy data, write data before copying to g
			if( found_key )
			{
				if( !wrote_data )
				{
					if( nfv_prop&NFV_NO_QUOTES )
						fprintf(g, "%s true^n", name);
					else
						fprintf(g, "^"%s^" ^"true^"^n", name);
					wrote_data = true;
				}
			}
			//else check if correct key, copy to g
			else
			{
				//Make sure we get something parsed
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( _name, key ) )
						found_key = true;
				}
			}

			fputs(g, _data);
		}
		else
		{
			if( found_key && !wrote_data )
			{
				//Make sure we get something parsed
				if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
				{
					//if name matches, write data to g, skip copy
					if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
					{
						_value = !str_to_bool( _other );
						if( nfv_prop&NFV_NO_QUOTES )
							fprintf(g, _value ? "%s true^n" : "%s false^n", name);
						else
							fprintf(g, _value ? "^"%s^" ^"true^"^n" : "^"%s^" ^"false^"^n", name);
						wrote_data = true;
						continue;
					}
				}
			}
			//else copy to g
			fputs(g, _data);
		}
	}

	if( !found_key )
	{
		fprintf(g, "%c%s^n", identifier, key);
	}
	if( !wrote_data )
	{
		if( nfv_prop&NFV_NO_QUOTES )
			fprintf(g, "%s true^n", name);
		else
			fprintf(g, "^"%s^" ^"true^"^n", name);
	}

	fclose(g);
	fclose(f);

	delete_file(filename);

	while( !rename_file(temp_file_name, filename, 1) ) { }

	return _value;
}

/**
 * Sets data as a vector in file under key and name.
 *
 * @param filename		The file location for the data.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The vector to write.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 * @return				1 if successful.
 */
stock nfv_set_vec(const filename[], const key[], name[], const Float:data[3], const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
{
	new g = fopen(temp_file_name, "wt");
	new f = fopen(filename, "rt");

	// lets put a time stamp
	fprintf(g, "^"TimeStamp^" ^"%d^"^n", get_systime() );

	new _data[512], _name[64], _other[3];

	new bool:wrote_data = false, bool:found_key = false, bool:found_time = false;

	if( !(nfv_prop&NFV_NO_REPLACE_QUOTE) )
	{
		nfv_replace_quote( name );
	}

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));

		if( !found_time )
		{
			if( equal(_data, "^"TimeStamp^"", 11) )
			{
				found_time = true;
				continue;
			}
		}
		if( _data[0] == identifier )
		{
			//if found key and wrote data continue and copy to g
			//    if didnt copy data, write data before copying to g
			if( found_key )
			{
				if( !wrote_data )
				{
					fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %f,%f,%f^n" : "^"%s^" ^"%f,%f,%f^"^n", name, data[0], data[1], data[2]);
					wrote_data = true;
				}
			}
			//else check if correct key, copy to g
			else
			{
				//Make sure we get something parsed
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( _name, key ) )
						found_key = true;
				}
			}

			fputs(g, _data);
		}
		else
		{
			if( !wrote_data )
			{
				if( nfv_prop&NFV_OVERWRITE )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, write data to g, skip copy
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %f,%f,%f^n" : "^"%s^" ^"%f,%f,%f^"^n", name, data[0], data[1], data[2]);
							wrote_data = true;
							continue;
						}
					}
				}
				else if( nfv_prop&NFV_IF_NOT_EXIST )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, stop, close files, delete temp file, return 0
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							fclose(g);
							fclose(f);

							delete_file(temp_file_name);

							return 0;
						}
					}
				}
			}

			//else copy to g
			fputs(g, _data);
		}
	}

	if( !found_key )
	{
		fprintf(g, "%c%s^n", identifier, key);
	}
	if( !wrote_data )
	{
		fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %f,%f,%f^n" : "^"%s^" ^"%f,%f,%f^"^n", name, data[0], data[1], data[2]);
	}

	fclose(g);
	fclose(f);

	delete_file(filename);

	while( !rename_file(temp_file_name, filename, 1) ) { }

	return 1;
}

/**
 * Sets data as an array in file under key and name.
 *
 * @param filename		The file location for the data.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The array to write.
 * @param array_size	The size of the array.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 *
 * @note				This will save each element as the integer form
 *
 * @return				1 if successful.
 */
stock nfv_set_array(const filename[], const key[], name[], const any:data[], const array_size, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
{
	new g = fopen(temp_file_name, "wt");
	new f = fopen(filename, "rt");

	// lets put a time stamp
	fprintf(g, "^"TimeStamp^" ^"%d^"^n", get_systime() );

	new _data[512], _name[64], _other[3], i;

	new bool:wrote_data = false, bool:found_key = false, bool:found_time = false;

	if( !(nfv_prop&NFV_NO_REPLACE_QUOTE) )
	{
		nfv_replace_quote( name );
	}

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));

		if( !found_time )
		{
			if( equal(_data, "^"TimeStamp^"", 11) )
			{
				found_time = true;
				continue;
			}
		}
		if( _data[0] == identifier )
		{
			//if found key and wrote data continue and copy to g
			//    if didnt copy data, write data before copying to g
			if( found_key )
			{
				if( !wrote_data )
				{
					fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %d" : "^"%s^" ^"%d", name, data[0]);
					for( i=1; i<array_size; i++ )
						fprintf(g, ",%d", data[i]);
					fputs(g, nfv_prop&NFV_NO_QUOTES ? "^n" : "^"^n");
					wrote_data = true;
				}
			}
			//else check if correct key, copy to g
			else
			{
				//Make sure we get something parsed
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( _name, key ) )
						found_key = true;
				}
			}

			fputs(g, _data);
		}
		else
		{
			if( !wrote_data )
			{
				if( nfv_prop&NFV_OVERWRITE )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, write data to g, skip copy
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %d" : "^"%s^" ^"%d", name, data[0]);
							for( i=1; i<array_size; i++ )
								fprintf(g, ",%d", data[i]);
							fputs(g, nfv_prop&NFV_NO_QUOTES ? "^n" : "^"^n");
							wrote_data = true;
							continue;
						}
					}
				}
				else if( nfv_prop&NFV_IF_NOT_EXIST )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, stop, close files, delete temp file, return 0
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							fclose(g);
							fclose(f);

							delete_file(temp_file_name);

							return 0;
						}
					}
				}
			}

			//else copy to g
			fputs(g, _data);
		}
	}

	if( !found_key )
	{
		fprintf(g, "%c%s^n", identifier, key);
	}
	if( !wrote_data )
	{
		fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %d" : "^"%s^" ^"%d", name, data[0]);
		for( i=1; i<array_size; i++ )
			fprintf(g, ",%d", data[i]);
		fputs(g, nfv_prop&NFV_NO_QUOTES ? "^n" : "^"^n");
	}

	fclose(g);
	fclose(f);

	delete_file(filename);

	while( !rename_file(temp_file_name, filename, 1) ) { }

	return 1;
}

/**
 * Sets data as an array in file under key and name.
 *
 * @param filename		The file location for the data.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The cell array to write.
 * @param array_size	The size of the array.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 *
 * @note				This will save each element as the integer form
 *
 * @return				1 if successful.
 */
stock nfv_set_cellarray(const filename[], const key[], name[], const Array:data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
{
	new g = fopen(temp_file_name, "wt");
	new f = fopen(filename, "rt");

	// lets put a time stamp
	fprintf(g, "^"TimeStamp^" ^"%d^"^n", get_systime() );

	new _data[512], _name[64], _other[3], i;

	new bool:wrote_data = false, bool:found_key = false, bool:found_time = false;
	new array_size = ArraySize(data);

	if( !(nfv_prop&NFV_NO_REPLACE_QUOTE) )
	{
		nfv_replace_quote( name );
	}

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));

		if( !found_time )
		{
			if( equal(_data, "^"TimeStamp^"", 11) )
			{
				found_time = true;
				continue;
			}
		}
		if( _data[0] == identifier )
		{
			//if found key and wrote data continue and copy to g
			//    if didnt copy data, write data before copying to g
			if( found_key )
			{
				if( !wrote_data )
				{
					fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %d" : "^"%s^" ^"%d", name, ArrayGetCell(data,0));
					for( i=1; i<array_size; i++ )
						fprintf(g, ",%d", ArrayGetCell(data,i));
					fputs(g, nfv_prop&NFV_NO_QUOTES ? "^n" : "^"^n");
					wrote_data = true;
				}
			}
			//else check if correct key, copy to g
			else
			{
				//Make sure we get something parsed
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( _name, key ) )
						found_key = true;
				}
			}

			fputs(g, _data);
		}
		else
		{
			if( !wrote_data )
			{
				if( nfv_prop&NFV_OVERWRITE )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, write data to g, skip copy
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %d" : "^"%s^" ^"%d", name, ArrayGetCell(data,0));
							for( i=1; i<array_size; i++ )
								fprintf(g, ",%d", ArrayGetCell(data,i));
							fputs(g, nfv_prop&NFV_NO_QUOTES ? "^n" : "^"^n");
							wrote_data = true;
							continue;
						}
					}
				}
				else if( nfv_prop&NFV_IF_NOT_EXIST )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, stop, close files, delete temp file, return 0
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							fclose(g);
							fclose(f);

							delete_file(temp_file_name);

							return 0;
						}
					}
				}
			}

			//else copy to g
			fputs(g, _data);
		}
	}

	if( !found_key )
	{
		fprintf(g, "%c%s^n", identifier, key);
	}
	if( !wrote_data )
	{
		fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %d" : "^"%s^" ^"%d", name, ArrayGetCell(data,0));
		for( i=1; i<array_size; i++ )
			fprintf(g, ",%d", ArrayGetCell(data,i));
		fputs(g, nfv_prop&NFV_NO_QUOTES ? "^n" : "^"^n");
	}

	fclose(g);
	fclose(f);

	delete_file(filename);

	while( !rename_file(temp_file_name, filename, 1) ) { }

	return 1;
}

/**
 * Sets data as array of strings in file under key and name.
 *
 * @param filename		The file location for the data.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The cell array to write.
 * @param array_size	The size of the array.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 *
 * @note				This will save in the form: "first","second","third","etc."
 *
 * @return				1 if successful.
 */
stock nfv_set_cellarray2(const filename[], const key[], name[], const Array:data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
{
	new g = fopen(temp_file_name, "wt");
	new f = fopen(filename, "rt");

	// lets put a time stamp
	fprintf(g, "^"TimeStamp^" ^"%d^"^n", get_systime() );

	new _data[512], _name[64], _other[3], i;
	new temp_string[64];

	new bool:wrote_data = false, bool:found_key = false, bool:found_time = false;
	new array_size = ArraySize(data);

	if( !(nfv_prop&NFV_NO_REPLACE_QUOTE) )
	{
		nfv_replace_quote( name );
	}

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));

		if( !found_time )
		{
			if( equal(_data, "^"TimeStamp^"", 11) )
			{
				found_time = true;
				continue;
			}
		}
		if( _data[0] == identifier )
		{
			//if found key and wrote data continue and copy to g
			//    if didnt copy data, write data before copying to g
			if( found_key )
			{
				if( !wrote_data )
				{
					ArrayGetString(data, 0, temp_string, charsmax(temp_string));
					nfv_replace_quote( temp_string );
					fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %s" : "^"%s^" ^"%s", name, temp_string);
					for( i=1; i<array_size; i++ )
					{
						ArrayGetString(data, i, temp_string, charsmax(temp_string));
						nfv_replace_quote( temp_string );
						fprintf(g, nfv_prop&NFV_NO_QUOTES ? ",%s" : "^",^"%s^"", temp_string);
					}
					fputs(g, nfv_prop&NFV_NO_QUOTES ? "^n" : "^"^n");
					wrote_data = true;
				}
			}
			//else check if correct key, copy to g
			else
			{
				//Make sure we get something parsed
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( _name, key ) )
						found_key = true;
				}
			}

			fputs(g, _data);
		}
		else
		{
			if( !wrote_data )
			{
				if( nfv_prop&NFV_OVERWRITE )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, write data to g, skip copy
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							ArrayGetString(data, 0, temp_string, charsmax(temp_string));
							nfv_replace_quote( temp_string );
							fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %s" : "^"%s^" ^"%s", name, temp_string);
							for( i=1; i<array_size; i++ )
							{
								ArrayGetString(data, i, temp_string, charsmax(temp_string));
								nfv_replace_quote( temp_string );
								fprintf(g, nfv_prop&NFV_NO_QUOTES ? ",%s" : "^",^"%s^"", temp_string);
							}
							fputs(g, nfv_prop&NFV_NO_QUOTES ? "^n" : "^"^n");
							wrote_data = true;
							continue;
						}
					}
				}
				else if( nfv_prop&NFV_IF_NOT_EXIST )
				{
					//Make sure we get something parsed
					if( parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
					{
						//if name matches, stop, close files, delete temp file, return 0
						if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
						{
							fclose(g);
							fclose(f);

							delete_file(temp_file_name);

							return 0;
						}
					}
				}
			}

			//else copy to g
			fputs(g, _data);
		}
	}

	if( !found_key )
	{
		fprintf(g, "%c%s^n", identifier, key);
	}
	if( !wrote_data )
	{
		ArrayGetString(data, 0, temp_string, charsmax(temp_string));
		nfv_replace_quote( temp_string );
		fprintf(g, nfv_prop&NFV_NO_QUOTES ? "%s %s" : "^"%s^" ^"%s", name, temp_string);
		for( i=1; i<array_size; i++ )
		{
			ArrayGetString(data, i, temp_string, charsmax(temp_string));
			nfv_replace_quote( temp_string );
			fprintf(g, nfv_prop&NFV_NO_QUOTES ? ",%s" : "^",^"%s^"", temp_string);
		}
		fputs(g, nfv_prop&NFV_NO_QUOTES ? "^n" : "^"^n");
	}

	fclose(g);
	fclose(f);

	delete_file(filename);

	while( !rename_file(temp_file_name, filename, 1) ) { }

	return 1;
}

/**
 * Retrieves data in file under key and name.
 *
 * @param filename			The file location to search for the data.
 * @param key				The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.
 * @param name				The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data				The string that will contain the data retrieved.
 * @param len				The size of the data string.
 * @param identifier		The character used to identify different keys.
 * @param key_tell_start	Where to start searching for key.
 * @param key_tell_find		Where the key was found.
 * @param name_tell_start	Where to start searching for name.
 * @param name_tell_find	Where the name was found.
 * @param key_copy			The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.
 * @param key_len			If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.
 * @param name_copy			The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.
 * @param name_len			If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.
 * @return					1 if data found.
 */
stock nfv_get_data(const filename[], const key[], name[], data[]="", len=0, const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)
{
	//Haven't found anything yet
	key_tell_find = name_tell_find = -1;

	if( key_tell_start <= -1 || name_tell_start <= -1 || !file_exists(filename) )
		return 0;

	new f = fopen(filename, "rt");

	new bool:found_key = false;
	new _data[512], _name[64], _other[2], _temp_tell;

	nfv_replace_quote( name );

	//Seek to key_tell_start
	if( key_tell_start )
		fseek(f, key_tell_start, SEEK_SET);

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		_temp_tell = ftell(f);
		fgets(f, _data, charsmax(_data));

		if( _data[0] == identifier )
		{
			if( found_key )
			{
				break;
			}
			else
			{
				//Make sure we get something parsed
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( key, _name ) || equal( key, NFV_WILDCARD ) )
					{
						if( key_len > 0 )
							copy( key_copy, key_len, _name );

						found_key = true;

						//Seek to name_tell_start
						if( name_tell_start )
							fseek(f, name_tell_start, SEEK_SET);

						key_tell_find = _temp_tell;
					}
				}
			}
		}
		else
		{
			if( found_key && parse(_data, _name, charsmax(_name), data, len) )
			{
				if( equal(_name, name) || equal( name, NFV_WILDCARD ) )
				{
					if( name_len > 0 )
					{
						copy( name_copy, name_len, _name );
						nfv_return_quote( name_copy );
					}

					name_tell_find = _temp_tell;
					nfv_return_quote( data );

					fclose(f);
					return 1;
				}
			}
		}
	}
	
	fclose(f);
	data[0] = '^0';
	return 0;
}

/**
 * Retrieves data as number form in file under key and name.
 *
 * @param filename			The file location to search for the data.
 * @param key				The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.
 * @param name				The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param identifier		The character used to identify different keys.
 * @param key_tell_start	Where to start searching for key.
 * @param key_tell_find		Where the key was found.
 * @param name_tell_start	Where to start searching for name.
 * @param name_tell_find	Where the name was found.
 * @param key_copy			The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.
 * @param key_len			If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.
 * @param name_copy			The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.
 * @param name_len			If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.
 * @return					Numeric value of data found. 0 if no data.
 */
stock nfv_get_num(const filename[], const key[], name[], const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)
{
	//Haven't found anything yet
	key_tell_find = name_tell_find = -1;

	if( key_tell_start <= -1 || name_tell_start <= -1 || !file_exists(filename) )
		return 0;

	new f = fopen(filename, "rt");

	new bool:found_key = false;
	new _data[512], _name[64], _other[64], _temp_tell;

	nfv_replace_quote( name );

	//Seek to key_tell_start
	if( key_tell_start )
		fseek(f, key_tell_start, SEEK_SET);

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		_temp_tell = ftell(f);
		fgets(f, _data, charsmax(_data));

		if( _data[0] == identifier )
		{
			if( found_key )
			{
				break;
			}
			else
			{
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( key, _name ) || equal( key, NFV_WILDCARD ) )
					{
						if( key_len > 0 )
							copy( key_copy, key_len, _name );

						found_key = true;

						//Seek to name_tell_start
						if( name_tell_start )
							fseek(f, name_tell_start, SEEK_SET);

						key_tell_find = _temp_tell;
					}
				}
			}
		}
		else
		{
			if( found_key && parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
			{
				if( equal(_name, name) || equal( name, NFV_WILDCARD ) )
				{
					if( name_len > 0 )
					{
						copy( name_copy, name_len, _name );
						nfv_return_quote( name_copy );
					}

					name_tell_find = _temp_tell;

					fclose(f);
					return str_to_num(_other);
				}
			}
		}
	}

	fclose(f);
	return 0;
}

/**
 * Retrieves data as floating point form in file under key and name.
 *
 * @param filename			The file location to search for the data.
 * @param key				The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.
 * @param name				The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param identifier		The character used to identify different keys.
 * @param key_tell_start	Where to start searching for key.
 * @param key_tell_find		Where the key was found.
 * @param name_tell_start	Where to start searching for name.
 * @param name_tell_find	Where the name was found.
 * @param key_copy			The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.
 * @param key_len			If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.
 * @param name_copy			The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.
 * @param name_len			If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.
 * @return					Floating point value of data found. 0.0 if no data.
 */
stock Float:nfv_get_float(const filename[], const key[], name[], const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)
{
	//Haven't found anything yet
	key_tell_find = name_tell_find = -1;

	if( key_tell_start <= -1 || name_tell_start <= -1 || !file_exists(filename) )
		return 0.0;

	new f = fopen(filename, "rt");

	new bool:found_key = false;
	new _data[512], _name[64], _other[64], _temp_tell;

	nfv_replace_quote( name );

	//Seek to key_tell_start
	if( key_tell_start )
		fseek(f, key_tell_start, SEEK_SET);

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		_temp_tell = ftell(f);
		fgets(f, _data, charsmax(_data));

		if( _data[0] == identifier )
		{
			if( found_key )
			{
				break;
			}
			else
			{
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( key, _name ) || equal( key, NFV_WILDCARD ) )
					{
						if( key_len > 0 )
							copy( key_copy, key_len, _name );

						found_key = true;

						//Seek to name_tell_start
						if( name_tell_start )
							fseek(f, name_tell_start, SEEK_SET);

						key_tell_find = _temp_tell;
					}
				}
			}
		}
		else
		{
			if( found_key && parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
			{
				if( equal(_name, name) || equal( name, NFV_WILDCARD ) )
				{
					if( name_len > 0 )
					{
						copy( name_copy, name_len, _name );
						nfv_return_quote( name_copy );
					}

					name_tell_find = _temp_tell;

					fclose(f);
					return str_to_float(_other);
				}
			}
		}
	}
	
	fclose(f);
	return 0.0;
}

/**
 * Retrieves data as boolean form in file under key and name.
 *
 * @param filename			The file location to search for the data.
 * @param key				The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.
 * @param name				The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param identifier		The character used to identify different keys.
 * @param key_tell_start	Where to start searching for key.
 * @param key_tell_find		Where the key was found.
 * @param name_tell_start	Where to start searching for name.
 * @param name_tell_find	Where the name was found.
 * @param key_copy			The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.
 * @param key_len			If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.
 * @param name_copy			The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.
 * @param name_len			If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.
 * @return					Boolean value of data found. False if no data.
 */
stock bool:nfv_get_bool(const filename[], const key[], name[], const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)
{
	//Haven't found anything yet
	key_tell_find = name_tell_find = -1;

	if( key_tell_start <= -1 || name_tell_start <= -1 || !file_exists(filename) )
		return false;

	new f = fopen(filename, "rt");

	new bool:found_key = false;
	new _data[512], _name[64], _other[64], _temp_tell;

	nfv_replace_quote( name );

	//Seek to key_tell_start
	if( key_tell_start )
		fseek(f, key_tell_start, SEEK_SET);

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		_temp_tell = ftell(f);
		fgets(f, _data, charsmax(_data));

		if( _data[0] == identifier )
		{
			if( found_key )
			{
				break;
			}
			else
			{
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( key, _name ) || equal( key, NFV_WILDCARD ) )
					{
						if( key_len > 0 )
							copy( key_copy, key_len, _name );

						found_key = true;

						//Seek to name_tell_start
						if( name_tell_start )
							fseek(f, name_tell_start, SEEK_SET);

						key_tell_find = _temp_tell;
					}
				}
			}
		}
		else
		{
			if( found_key && parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
			{
				if( equal(_name, name) || equal( name, NFV_WILDCARD ) )
				{
					if( name_len > 0 )
					{
						copy( name_copy, name_len, _name );
						nfv_return_quote( name_copy );
					}

					if( len )
					{
						copy( data, len, _other );
						nfv_return_quote( data );
					}

					name_tell_find = _temp_tell;

					fclose(f);

					return str_to_bool(_other);
				}
			}
		}
	}
	
	fclose(f);
	data[0] = '^0';
	return false;
}

/**
 * Retrieves data as array form in file under key and name.
 *
 * @param filename			The file location to search for the data.
 * @param key				The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.
 * @param name				The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data				The array that will contain the data retrieved.
 * @param size				The size of the data array.
 * @param identifier		The character used to identify different keys.
 * @param key_tell_start	Where to start searching for key.
 * @param key_tell_find		Where the key was found.
 * @param name_tell_start	Where to start searching for name.
 * @param name_tell_find	Where the name was found.
 * @param key_copy			The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.
 * @param key_len			If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.
 * @param name_copy			The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.
 * @param name_len			If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.
 * @return					Whether or not data was found.
 */
stock nfv_get_array(const filename[], const key[], name[], any:data[], const size, const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)
{
	//Haven't found anything yet
	key_tell_find = name_tell_find = -1;

	if( key_tell_start <= -1 || name_tell_start <= -1 || !file_exists(filename) )
		return false;

	new f = fopen(filename, "rt");

	new bool:found_key = false;
	new _data[512], _name[64], _other[64], _temp_tell;

	nfv_replace_quote( name );

	//Seek to key_tell_start
	if( key_tell_start )
		fseek(f, key_tell_start, SEEK_SET);

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		_temp_tell = ftell(f);
		fgets(f, _data, charsmax(_data));

		if( _data[0] == identifier )
		{
			if( found_key )
			{
				break;
			}
			else
			{
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( key, _name ) || equal( key, NFV_WILDCARD ) )
					{
						if( key_len > 0 )
							copy( key_copy, key_len, _name );

						found_key = true;

						//Seek to name_tell_start
						if( name_tell_start )
							fseek(f, name_tell_start, SEEK_SET);

						key_tell_find = _temp_tell;
					}
				}
			}
		}
		else
		{
			if( found_key && parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
			{
				if( equal(_name, name) || equal( name, NFV_WILDCARD ) )
				{
					if( name_len > 0 )
					{
						copy( name_copy, name_len, _name );
						nfv_return_quote( name_copy );
					}

					name_tell_find = _temp_tell;

					fclose(f);

					str_to_array(_other, data, size);

					return true;
				}
			}
		}
	}
	
	fclose(f);
	for( new i; i<size; i++ )
		data[i] = 0;
	return false;
}

/**
 * Retrieves data as vector form in file under key and name.
 *
 * @param filename			The file location to search for the data.
 * @param key				The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.
 * @param name				The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data				The vector that will contain the data retrieved.
 * @param identifier		The character used to identify different keys.
 * @param key_tell_start	Where to start searching for key.
 * @param key_tell_find		Where the key was found.
 * @param name_tell_start	Where to start searching for name.
 * @param name_tell_find	Where the name was found.
 * @param key_copy			The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.
 * @param key_len			If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.
 * @param name_copy			The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.
 * @param name_len			If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.
 * @return					Whether or not data was found.
 */
stock nfv_get_vec(const filename[], const key[], name[], Float:data[3], const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)
{
	//Haven't found anything yet
	key_tell_find = name_tell_find = -1;

	if( key_tell_start <= -1 || name_tell_start <= -1 || !file_exists(filename) )
		return false;

	new f = fopen(filename, "rt");

	new bool:found_key = false;
	new _data[512], _name[64], _other[64], _temp_tell;

	nfv_replace_quote( name );

	//Seek to key_tell_start
	if( key_tell_start )
		fseek(f, key_tell_start, SEEK_SET);

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		_temp_tell = ftell(f);
		fgets(f, _data, charsmax(_data));

		if( _data[0] == identifier )
		{
			if( found_key )
			{
				break;
			}
			else
			{
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( key, _name ) || equal( key, NFV_WILDCARD ) )
					{
						if( key_len > 0 )
							copy( key_copy, key_len, _name );

						found_key = true;

						//Seek to name_tell_start
						if( name_tell_start )
							fseek(f, name_tell_start, SEEK_SET);

						key_tell_find = _temp_tell;
					}
				}
			}
		}
		else
		{
			if( found_key && parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
			{
				if( equal(_name, name) || equal( name, NFV_WILDCARD ) )
				{
					if( name_len > 0 )
					{
						copy( name_copy, name_len, _name );
						nfv_return_quote( name_copy );
					}

					name_tell_find = _temp_tell;

					fclose(f);

					str_to_vector(_other, data);

					return true;
				}
			}
		}
	}
	
	fclose(f);
	for( new i; i<3; i++ )
		data[i] = 0.0;
	return false;
}

/**
 * Retrieves data as cellarray form in file under key and name.
 *
 * @param filename			The file location to search for the data.
 * @param key				The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.
 * @param name				The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data				The cell array that will contain the data retrieved.
 * @param identifier		The character used to identify different keys.
 * @param key_tell_start	Where to start searching for key.
 * @param key_tell_find		Where the key was found.
 * @param name_tell_start	Where to start searching for name.
 * @param name_tell_find	Where the name was found.
 * @param key_copy			The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.
 * @param key_len			If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.
 * @param name_copy			The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.
 * @param name_len			If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.
 *
 * @note					If an existing cell array is provided, it will push new data to the end of it.
 *
 * @return					The cell array handle. Invalid_Array if no data.
 */
stock Array:nfv_get_cellarray(const filename[], const key[], name[], &Array:data=Invalid_Array, const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)
{
	//Haven't found anything yet
	key_tell_find = name_tell_find = -1;

	if( key_tell_start <= -1 || name_tell_start <= -1 || !file_exists(filename) )
		return Invalid_Array;

	new f = fopen(filename, "rt");

	new bool:found_key = false;
	new _data[512], _name[64], _other[64], _temp_tell;

	nfv_replace_quote( name );

	//Seek to key_tell_start
	if( key_tell_start )
		fseek(f, key_tell_start, SEEK_SET);

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		_temp_tell = ftell(f);
		fgets(f, _data, charsmax(_data));

		if( _data[0] == identifier )
		{
			if( found_key )
			{
				break;
			}
			else
			{
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( key, _name ) || equal( key, NFV_WILDCARD ) )
					{
						if( key_len > 0 )
							copy( key_copy, key_len, _name );

						found_key = true;

						//Seek to name_tell_start
						if( name_tell_start )
							fseek(f, name_tell_start, SEEK_SET);

						key_tell_find = _temp_tell;
					}
				}
			}
		}
		else
		{
			if( found_key && parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
			{
				if( equal(_name, name) || equal( name, NFV_WILDCARD ) )
				{
					if( name_len > 0 )
					{
						copy( name_copy, name_len, _name );
						nfv_return_quote( name_copy );
					}

					name_tell_find = _temp_tell;

					fclose(f);

					return str_to_cellarray(_other, data);
				}
			}
		}
	}
	
	fclose(f);
	return Invalid_Array;
}

/**
 * Retrieves data as cellarray string form in file under key and name.
 *
 * @param filename			The file location to search for the data.
 * @param key				The key within the file to look for. Set to "" for no key. Set to NFV_WILDCARD for any key.
 * @param name				The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data				The cell array that will contain the data retrieved.
 * @param identifier		The character used to identify different keys.
 * @param key_tell_start	Where to start searching for key.
 * @param key_tell_find		Where the key was found.
 * @param name_tell_start	Where to start searching for name.
 * @param name_tell_find	Where the name was found.
 * @param key_copy			The string that will contain the key of the data retrieved. Only used with NFV_WILDCARD for key.
 * @param key_len			If specified, the size of the key found to copy. Only used with NFV_WILDCARD for key.
 * @param name_copy			The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.
 * @param name_len			If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.
 *
 * @note					If an existing cell array is provided, it will push new strings to the end of it.
 *
 * @return					The cell array handle. Invalid_Array if no data.
 */
stock Array:nfv_get_cellarray2(const filename[], const key[], name[], &Array:data=Invalid_Array, const identifier=';', const key_tell_start=0, &key_tell_find=0, const name_tell_start=0, &name_tell_find=0, key_copy[]="", const key_len=0, name_copy[]="", const name_len=0)
{
	//Haven't found anything yet
	key_tell_find = name_tell_find = -1;

	if( key_tell_start <= -1 || name_tell_start <= -1 || !file_exists(filename) )
		return Invalid_Array;

	new f = fopen(filename, "rt");

	new bool:found_key = false;
	new _data[512], _name[64], _other[64], _temp_tell;

	nfv_replace_quote( name );

	//Seek to key_tell_start
	if( key_tell_start )
		fseek(f, key_tell_start, SEEK_SET);

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		_temp_tell = ftell(f);
		fgets(f, _data, charsmax(_data));

		if( _data[0] == identifier )
		{
			if( found_key )
			{
				break;
			}
			else
			{
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( key, _name ) || equal( key, NFV_WILDCARD ) )
					{
						if( key_len > 0 )
							copy( key_copy, key_len, _name );

						found_key = true;

						//Seek to name_tell_start
						if( name_tell_start )
							fseek(f, name_tell_start, SEEK_SET);

						key_tell_find = _temp_tell;
					}
				}
			}
		}
		else
		{
			if( found_key && parse(_data, _name, charsmax(_name), _other, charsmax(_other)) )
			{
				if( equal(_name, name) || equal( name, NFV_WILDCARD ) )
				{
					if( name_len > 0 )
					{
						copy( name_copy, name_len, _name );
						nfv_return_quote( name_copy );
					}

					name_tell_find = _temp_tell;

					fclose(f);

					return str_to_cellarray2(_other, data);
				}
			}
		}
	}
	
	fclose(f);
	return Invalid_Array;
}

/**
 * Removes data in file under key and name.
 *
 * @param filename		The file location to search for the data.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The string that will contain the data removed.
 * @param len			The size of the data string.
 * @param take_times	How many times to take out of the file. Set to NFV_TAKEALL for all.
 * @param identifier	The character used to identify different keys.
 * @param name_copy		The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.
 * @param name_len		If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.
 * @return				How many datas were removed.
 */
stock nfv_take_data(const filename[], const key[], name[], data[]="", len=0, const take_times=1, const identifier=';', name_copy[]="", const name_len=0)
{
	if( !file_exists(filename) )
		return 0;

	new g = fopen(temp_file_name, "wt");
	new f = fopen(filename, "rt");

	// lets put a time stamp
	fprintf(g, "^"TimeStamp^" ^"%d^"^n", get_systime() );

	new _data[512], _name[64], _other[3];

	nfv_replace_quote( name );

	new took_data, bool:found_key = false, bool:found_time = false;

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));

		if( !found_time )
		{
			if( equal(_data, "^"TimeStamp^"", 11) )
			{
				found_time = true;
				continue;
			}
		}
		if( _data[0] == identifier )
		{
			//if found key and wrote data continue and copy to g
			//    if didnt copy data, write data before copying to g
			if( found_key )
			{
				//if we took the data, we still need to copy all the data
				if( !took_data )
				{
					break;
				}
			}
			//else check if correct key, copy to g
			else
			{
				//Make sure we get something parsed
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( _name, key ) )
					{
						found_key = true;
						//If taking all, don't put the key in
						if( take_times == NFV_TAKEALL )
							continue;
					}
				}
			}

			fputs(g, _data);
		}
		else
		{
			//only need to check the data to take if we havent taken anything
			if( found_key && ( took_data < take_times || take_times == NFV_TAKEALL ) )
			{

				//Make sure we get something parsed
				if( parse(_data, _name, charsmax(_name), data, len) )
				{
					//if name matches, save data, skip copy
					if( equal( _name, name ) || equal( name, NFV_WILDCARD ) )
					{
						if( name_len > 0 )
						{
							copy( name_copy, name_len, _name );
							nfv_return_quote( name_copy );
						}

						nfv_return_quote( data );
						took_data++;

						continue;
					}
				}
			}

			//else copy to g
			fputs(g, _data);
		}
	}

	fclose(g);
	fclose(f);

	if( took_data )
	{
		delete_file(filename);
		while( !rename_file(temp_file_name, filename, 1) ) { }
	}
	else
	{
		delete_file(temp_file_name);
		data[0] = '^0';
	}

	return took_data;
}

/**
 * Retrieves data in file under key and name with reference to line numbers.
 *
 * @param filename			The file location to search for the data.
 * @param key				The key within the file to look for. Set to "" for no key.
 * @param name				The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data				The string that will contain the data retrieved.
 * @param len				The size of the data string.
 * @param identifier		The character used to identify different keys.
 * @param key_line_start	Where to start searching for key.
 * @param key_line_find		Where the key was found.
 * @param name_line_start	Where to start searching for name.
 * @param name_line_find	Where the name was found.
 * @param name_copy			The string that will contain the name of the data retrieved. Only used with NFV_WILDCARD for name.
 * @param name_len			If specified, the size of the name found to copy. Only used with NFV_WILDCARD for name.
 * @return					1 if successful, 0 on failure.
 */
stock nfv_get_linedata(const filename[], const key[], name[], data[]="", len=0, const identifier=';', const key_line_start=0, &key_line_find=0, const name_line_start=0, &name_line_find=0, name_copy[], const name_len=0)
{
	if( key_line_start <= -1 || name_line_start <= -1 || !file_exists(filename) )
		return 0;

	new f = fopen(filename, "rt");

	new bool:found_key = false;
	new _data[512], _name[64], _other[2], _line = -1;

	//If using a blank key, detect it already
	if( !key[0]  )
		found_key = true;

	//Haven't found anything yet
	key_line_find = name_line_find = -1;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));
		_line++;

		if( _data[0] == identifier && _line > key_line_start )
		{
			if( found_key )
			{
				break;
			}
			else
			{
				//Make sure we get something parsed
				if( parse(_data[1], _name, charsmax(_name), _other, charsmax(_other)) )
				{
					if( equal( key, _name ) )
					{
						found_key = true;

						key_line_find = _line;
					}
				}
			}
		}
		else if( _line > name_line_start )
		{
			//Make sure we get something parsed
			if( parse(_data, _name, charsmax(_name), data, len) )
			{
				if( found_key )
				{
					if( equal(_name, name) || equal( name, NFV_WILDCARD ) )
					{
						if( name_len > 0 )
						{
							copy( name_copy, name_len, _name );
							nfv_return_quote( name_copy );
						}

						name_line_find = _line;
						nfv_return_quote( data );

						fclose(f);
						return 1;
					}
				}
			}
		}
	}
	
	fclose(f);
	data[0] = '^0';
	return 0;
}

/**
 * Removes data from all files in the NFVault folder.
 *
 * @param key			The key within the file to remove data.
 * @param name			The name within the key to remove data. Set to NFV_WILDCARD to prune all names.
 * @param start			Checks if last TimeStamp is after this UnixTime. Set to -1 to prune all.
 * @param end			Checks if last TimeStamp is before this UnixTime. Set to -1 to prune all.
 * @param identifier	The character used to identify different keys.
 * @noreturn
 */
stock nfv_prune(const key[], name[], const start=-1, const end=-1, const identifier=';')
{
	new directory[128], filename[128], fullfile[128];

	get_localinfo( "amxx_datadir", directory, charsmax(directory) );
	add( directory, charsmax(directory), "/nfvault/" );

	new dir = open_dir( directory, filename, charsmax(filename) );

	if( !dir )
		return;

	new bool:prune_all;
	if( start == -1 && end == -1 )
		prune_all = true;

	do
	{
		formatex( fullfile, charsmax(fullfile), "%s%s", directory, filename );
		if( !file_exists(fullfile) )
			break;

		if( prune_all )
		{
			while( nfv_take_data( filename, key, name, _, _, NFV_TAKEALL, identifier ) ) {}
		}
		else if( start < nfv_get_num( filename, "", "TimeStamp" ) < end )
		{
			while( nfv_take_data( filename, key, name, _, _, NFV_TAKEALL, identifier ) ) {}
		}
	}
	while( next_file(dir, filename, charsmax(filename)) )

	close_dir(dir);
}

/**
 * Updates a file's TimeStamp
 *
 * @param filename		The file to be touched.
 * @param new_time		Timestamp to set for the file in Unix time. Set to -1 for current time.
 * @return				1 if successful.
 */
stock nfv_touch(const filename[], const new_time=-1)
{
	new g = fopen(temp_file_name, "wt");
	new f = fopen(filename, "rt");

	// lets update the time stamp
	if( new_time == -1 )
		fprintf(g, "^"TimeStamp^" ^"%d^"^n", get_systime() );
	else
		fprintf(g, "^"TimeStamp^" ^"%d^"^n", new_time );

	new _data[512];

	new bool:found_time = false;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));

		if( !found_time )
		{
			if( equal(_data, "^"TimeStamp^"", 11) )
			{
				found_time = true;
				continue;
			}
		}
		fputs(g, _data);
	}

	fclose(g);
	fclose(f);

	delete_file(filename);

	while( !rename_file(temp_file_name, filename, 1) ) { }

	return 1;
}

/**
 * Finds a player's unique save key
 *
 * @param id			The index of the client.
 * @return				Returns string containing the key.
 */
stock PlayerSaveKey(id)
{
	new player_key[35];

	#if NFV_SAVETYPE == 0
	if( is_user_bot(id) )
	{
		new botname[32];
		get_user_name(id,botname,31);

		//Get Rid of BOT Tag

		//PODBot
		replace(botname,31,"[POD]","");
		replace(botname,31,"[P*D]","");
		replace(botname,31,"[P0D]","");

		//CZ Bots
		replace(botname,31,"[BOT] ","");

		//Attempt to get rid of the skill tag so we save with bots true name
		new lastchar = strlen(botname) - 1;
		if( equal(botname[lastchar],")",1) )
		{
			for( new x = lastchar - 1; x > 0; x-- )
			{
				if ( equal(botname[x],"(",1) )
				{
					botname[x - 1] = 0;
					break;
				}
				if ( !isdigit(botname[x]) )
					break;
			}
		}
		if( strlen(botname) > 0 )
			formatex( player_key, 34, "[BOT]%s", botname );
	}
	//Hack for STEAM's retardedness with listen servers
	else if( !is_dedicated_server() && id == 1 )
		copy( player_key, 34, "loopback" );
	else
	{
		static sv_lan;
		if( !sv_lan )
			sv_lan = get_cvar_pointer("sv_lan");
		if( get_pcvar_num(sv_lan) == 1 )
		{
			get_user_ip( id, player_key, 34, 1 );		// by ip without port
		}
		else
		{
			get_user_authid( id, player_key, 34 );		// by steamid
			if( equali(player_key,"STEAM_ID_LAN") || equali(player_key,"4294967295") )
				get_user_ip( id, player_key, 34, 1 );		// by ip without port
		}
	}
	#else
	get_user_name( id, player_key, 34 );
	#endif

	if( strlen(player_key) > 0 )
	{
		nfv_string_clean(player_key, player_key, 34);
	}

	//Check to make sure we got something useable
	if( equali(player_key, "STEAM_ID_PENDING") )
	{
		player_key[0] = '^0';
	}

	return player_key;
}

/**
 * Cleans a filename of invalid characters
 *
 * @param string		The string to clean.
 * @param output		The cleaned string.
 * @param len			The length of output to fill.
 * @return				Returns 1 on success.
 */
stock nfv_string_clean( const string[], output[], len )
{
	new i, j;
	while( i<len && j<len )
	{
		switch( string[i] )
		{
			case '/', '\', '*', ':', '?', '"', '<', '>', '|':
			{
				i++;
			}
			case ' ':
			{
				output[j++] = '_';
				i++;
			}
			case '^0':
			{
				output[j++] = string[i++];
				break;
			}
			default:
			{
				output[j++] = string[i++];
			}
		}
	}
	return 1;
}

/**
 * Replaces quotation marks with the replacement character.
 *
 * @param string		The string to clean.
 * @noreturn
 */
stock nfv_replace_quote( string[] )
{
	for( new i; string[i] != '^0'; i++ )
	{
		if( string[i] == quote_char )
			string[i] = quote_replace_char;
	}
}

/**
 * Replaces replacement characters with a quotation mark.
 *
 * @param string		The string to clean.
 * @noreturn
 */
stock nfv_return_quote( string[] )
{
	for( new i; string[i] != '^0'; i++ )
	{
		if( string[i] == quote_replace_char )
			string[i] = quote_char;
	}
}

/**
 * Returns a file in the nfvault folder
 *
 * @param filename		The filename and extension of the file.
 * @param filepath		The entire path, filename and extension of the file is returned if size is > 0.
 * @param size			The size to fill filepath with. Set to 0 to ignore.
 * @return				Returns string containing the nfvault file.
 */
stock nfv_file(const filename[], filepath[]="", const size=0)
{
	new file[128], _filename[128];
	if( !DataDir[0] )
	{
		get_localinfo( "amxx_datadir", DataDir, charsmax(DataDir) );
		add( DataDir, charsmax(DataDir), "/nfvault" );
		if( !dir_exists(DataDir) )
			mkdir(DataDir);
	}
	nfv_string_clean( filename, _filename, 127 );
	formatex( file, charsmax(file), "%s/%s", DataDir, _filename );

	if( size )
		copy( filepath, size, file );

	return file;
}
/**
 * Creates a file with a TimeStamp.
 *
 * @param filename		The file location for the data.
 * @param new_time		Timestamp to set for the file in Unix time. Set to -1 for current time.
 * @return				1 if created, -1 on existing, 0 on failure.
 */
stock nfv_create_file(const filename[], const new_time=-1)
{
	if( file_exists( filename ) )
		return -1;

	new f = fopen(filename, "wt");

	// lets put a time stamp
	if( new_time == -1 )
		fprintf(f, "^"TimeStamp^" ^"%d^"^n", get_systime() );
	else
		fprintf(f, "^"TimeStamp^" ^"%d^"^n", new_time );

	fclose(f);

	return 1;
}

/**
 * Finds a player's unique save file
 *
 * @param id			The index of the client.
 * @return				Returns string containing the file.
 */
stock nfv_player_file(const id)
{
	new file[128];
	if( !DataDir[0] )
	{
		get_localinfo( "amxx_datadir", DataDir, charsmax(DataDir) );
		add( DataDir, charsmax(DataDir), "/nfvault" );
		if( !dir_exists(DataDir) )
			mkdir(DataDir);
	}
	formatex( file, charsmax(file), "%s/%s.txt", DataDir, PlayerSaveKey(id) );
	return file;
}

/**
 * Sets data for a player under key and name.
 *
 * @param id			The index of the client.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The data to write.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 * @return				1 if successful.
 */
stock player_set_data(const id, const key[], name[], data[], const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
	return nfv_set_data(nfv_player_file(id), key, name, data, nfv_prop, identifier);

/**
 * Sets number for a player under key and name.
 *
 * @param id			The index of the client.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The number to write.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 * @return				1 if successful.
 */
stock player_set_num(const id, const key[], name[], const data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
	return nfv_set_num(nfv_player_file(id), key, name, data, nfv_prop, identifier);

/**
 * Adds number for a player under key and name.
 *
 * @param id			The index of the client.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The number to write.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 * @return				1 if successful.
 */
stock player_add_num(const id, const key[], name[], const data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
	return nfv_add_num(nfv_player_file(id), key, name, data, nfv_prop, identifier);

/**
 * Sets float for a player under key and name.
 *
 * @param id			The index of the client.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The floating point to write.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 * @return				1 if successful.
 */
stock player_set_float(const id, const key[], name[], const Float:data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
	return nfv_set_float(nfv_player_file(id), key, name, data, nfv_prop, identifier);

/**
 * Adds a float for a player under key and name.
 *
 * @param id			The index of the client.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The floating point to write.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 * @return				1 if successful.
 */
stock player_add_float(const id, const key[], name[], const Float:data, const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
	return nfv_add_float(nfv_player_file(id), key, name, data, nfv_prop, identifier);

/**
 * Retrieves data for a player under key and name.
 *
 * @param id			The index of the client.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The string that will contain the data retrieved.
 * @param len			The size of the data string.
 * @param identifier	The character used to identify different keys.
 * @return				1 if successful.
 */
stock player_get_data(const id, const key[], name[], data[]="", len=0, const identifier=';')
	return nfv_get_data(nfv_player_file(id), key, name, data, len, identifier);

/**
 * Retrieves data as a number for a player under key and name.
 *
 * @param id				The index of the client.
 * @param key				The key within the file to look for. Set to "" for no key.
 * @param name				The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param identifier		The character used to identify different keys.
 * @return					Numeric value of data found. 0 if no data.
 */
stock player_get_num(const id, const key[], name[], const identifier=';')
	return nfv_get_num(nfv_player_file(id), key, name, identifier);

/**
 * Retrieves data as a float for a player under key and name.
 *
 * @param id				The index of the client.
 * @param key				The key within the file to look for. Set to "" for no key.
 * @param name				The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param identifier		The character used to identify different keys.
 * @return					Floating point value of data found. 0.0 if no data.
 */
stock Float:player_get_float(const id, const key[], name[], const identifier=';')
	return nfv_get_float(nfv_player_file(id), key, name, identifier);

/**
 * Removes data for a player under key and name.
 *
 * @param id			The index of the client.
 * @param key			The key within the file to look for. Set to "" for no key.
 * @param name			The name under key to look for. Set to NFV_WILDCARD for any name.
 * @param data			The string that will contain the data removed.
 * @param len			The size of the data string.
 * @param take_times	How many times to take out of the file. Set to NFV_TAKEALL for all.
 * @param identifier	The character used to identify different keys.
 * @return				How many datas were removed.
 */
stock player_take_data(const id, const key[], name[], data[]="", len=0, const take_times=1, const identifier=';')
	return nfv_take_data(nfv_player_file(id), key, name, data, len, take_times, identifier);

/**
 * Switches two key's in a file.
 *
 * @param filename		The file location for the data.
 * @param key1			The first key to switch.
 * @param key2			The second key to switch.
 * @param identifier	The character used to identify different keys.
 *
 * @note				Data under key1 will switch to key2. Data under key2 will switch to key1.
 *
 * @return				1 if successful.
 */
stock nfv_switch_keys(const filename[], const key1[], const key2[], const identifier=';')
{
	new g = fopen(temp_file_name, "wt");
	new f = fopen(filename, "rt");

	// lets put a time stamp
	fprintf(g, "^"TimeStamp^" ^"%d^"^n", get_systime() );

	new _data[512], _key[64], _other[3];

	new bool:found_time = false;

	while( !feof(f) )
	{
		fgets(f, _data, charsmax(_data));

		if( !found_time )
		{
			if( equal(_data, "^"TimeStamp^"", 11) )
			{
				found_time = true;
				continue;
			}
		}
		if( _data[0] == identifier )
		{
			//Make sure we get something parsed
			if( parse(_data[1], _key, charsmax(_key), _other, charsmax(_other)) )
			{
				if( equal( _key, key1 ) )
				{
					fprintf(g, "%c%s^n", identifier, key2);
					continue;
				}
				if( equal( _key, key2 ) )
				{
					fprintf(g, "%c%s^n", identifier, key1);
					continue;
				}
			}
		}
		fputs(g, _data);
	}

	fclose(g);
	fclose(f);

	delete_file(filename);

	while( !rename_file(temp_file_name, filename, 1) ) { }

	return 1;
}

/**
 * Changes data from one key to another in a file.
 *
 * @param filename		The file location for the data.
 * @param key1			The key to change from. 
 * @param key2			The key to change to.
 * @param nfv_prop		Properties to apply to the saved data in a bitsum.
 * @param identifier	The character used to identify different keys.
 *
 * @note				Data under key1 will change to key2.
 *
 * @return				Returns how many keys were switched.
 */
stock nfv_change_key(const filename[], const key1[], const key2[], const NFV_PROP:nfv_prop=NFV_OVERWRITE, const identifier=';')
{
	new name[32], data[128], i;

	while( nfv_take_data( filename, key1, NFV_WILDCARD, data, 127, 1, identifier, name, 31) )
	{
		nfv_set_data( filename, key2, name, data, nfv_prop, identifier);
		i++;
	}

	return i;
}

/**
 * Removes all data under a key in a file.
 *
 * @param filename		The file location for the data.
 * @param key			The key to remove from. 
 * @param identifier	The character used to identify different keys.
 * @return				Returns how many datas were removed with the key.
 */
stock nfv_remove_key(const filename[], const key[], const identifier=';')
{
	return nfv_take_data( filename, key, NFV_WILDCARD, _, _, NFV_TAKEALL, identifier );
}

/**
 * Returns whether a string should be true or false
 *
 * @param string		The string to look at. 
 * @return				Returns true or false.
 */
stock bool:str_to_bool( const string[] )
{
	//Numeric values are true
	if( str_to_float( string ) != 0.0 )
		return true;

	//False, No, 0, "" are false
	//0.0 will be detected as 0
	switch( string[0] )
	{
		case 'F','f','N','n','0','^0':
			return false;
	}

	//Everything else is true
	return true;
}

/**
 * Fills an array with numbers from a string
 *
 * @param string		The string to look at.
 * @param array			The array to fill.
 * @param size			The size of the array.
 * @noreturn
 */
stock str_to_array( const string[], array[], const size )
{
	new left[32], right[128], i;
	copy(right, charsmax(right), string);

	while( i<size )
	{
		strtok(right, left, charsmax(left), right, charsmax(right), ',', 1);
		array[i++] = str_to_num( left );
	}
}

/**
 * Fills a vector with numbers from a string
 *
 * @param string		The string to look at.
 * @param vec			The vector to fill.
 * @noreturn
 */
stock str_to_vector( const string[], Float:vec[3] )
{
	new left[32], right[128], i;
	copy(right, charsmax(right), string);

	while( i<3 )
	{
		strtok(right, left, charsmax(left), right, charsmax(right), ',', 1);
		array[i++] = str_to_float( left );
	}
}

/**
 * Pushes cells into a cell array with numbers from a string
 *
 * @param string		The string to look at.
 * @param array			The cell array to push into. If none provided, it creates one.
 * @return				Returns the cell array handle.
 */
stock Array:str_to_cellarray( const string[], &Array:array=Invalid_Array )
{
	if( array == Invalid_Array )
		array = ArrayCreate(1,1);

	new left[32], right[128];
	copy(right, charsmax(right), string);

	while( strtok(right, left, charsmax(left), right, charsmax(right), ',', 1) )
	{
		ArrayPushCell(array, str_to_num( left ) );
	}

	return array;
}

/**
 * Pushes strings into a cell array with substrings from a string
 *
 * @param string		The string to look at.
 * @param array			The cell array to push into. If none provided, it creates one.
 * @return				Returns the cell array handle.
 */
stock Array:str_to_cellarray2( const string[], &Array:array=Invalid_Array )
{
	if( array == Invalid_Array )
		array = ArrayCreate(32,1);

	new left[128], right[256];
	copy(right, charsmax(right), string);
	replace_all( right, charsmax(right), ",", " " );

	while( strbreak(right, left, charsmax(left), right, charsmax(right)) )
	{
		nfv_return_quote( left );
		ArrayPushString(array, left );
	}

	return array;
}

Donations [top]

Attached Files
File Type: inc nfvault.inc (89.1 KB, 1723 views)

Last edited by Emp`; 12-05-2009 at 13:13. Reason: Updated December 5, 2009
Emp` is offline
Send a message via AIM to Emp` Send a message via MSN to Emp` Send a message via Yahoo to Emp` Send a message via Skype™ to Emp`
WhightKnight
Senior Member
Join Date: Jun 2008
Old 05-21-2009 , 22:28   Re: New File Vault - A newer file vault system!
Reply With Quote #2

Well I don't understand the post thoroughly, as I am not a scripter. However I do understand that this new system will be able to further the abilities of various mods. Great work Emp`
__________________

Last edited by WhightKnight; 05-21-2009 at 22:34.
WhightKnight is offline
--kml--
Senior Member
Join Date: Jan 2009
Old 05-21-2009 , 22:37   Re: New File Vault - A newer file vault system!
Reply With Quote #3

hmmm can u give an example?
like want to store a players frag in the fvault :O
__________________
wooT now is asking season
will ask you plenty of things for learning
--kml-- is offline
Emp`
AMX Mod X Plugin Approver
Join Date: Aug 2005
Location: Decapod 10
Old 05-21-2009 , 23:00   Re: New File Vault - A newer file vault system!
Reply With Quote #4

Retrieving:
Code:
new data[11];
player_get_data( id, "Stats", "Kills", data, 10);
Saving:
Code:
new data[11];
formatex(data, 10, "%d", kills);
player_set_data( id, "Stats", "Kills", data);
Emp` is offline
Send a message via AIM to Emp` Send a message via MSN to Emp` Send a message via Yahoo to Emp` Send a message via Skype™ to Emp`
stupok
Veteran Member
Join Date: Feb 2006
Old 05-21-2009 , 23:15   Re: New File Vault - A newer file vault system!
Reply With Quote #5

Looks like this could save me some work. I'll have to try it.
__________________
stupok is offline
Alka
AMX Mod X Plugin Approver
Join Date: Dec 2006
Location: malloc(null)
Old 05-22-2009 , 06:28   Re: New File Vault - A newer file vault system!
Reply With Quote #6

This looks very nice...is moar handy than others, and it's very good because you can work with any tipe of files. Gj.

Ah, i almost forgot, i can donate a for ya kittie.
__________________
Still...lovin' . Connor noob! Hello
Alka is offline
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
Old 05-22-2009 , 09:56   Re: New File Vault - A newer file vault system!
Reply With Quote #7

Nice work Emp
__________________
Bugsy is offline
Arkshine
AMX Mod X Plugin Approver
Join Date: Oct 2005
Old 05-22-2009 , 13:43   Re: New File Vault - A newer file vault system!
Reply With Quote #8

Good job !
Arkshine is offline
Simpler
Junior Member
Join Date: May 2009
Location: Sweden
Old 05-22-2009 , 13:48   Re: New File Vault - A newer file vault system!
Reply With Quote #9

Cool, seems very useful
__________________
Simpler is teh way!
Simpler is offline
Send a message via MSN to Simpler
Exolent[jNr]
Veteran Member
Join Date: Feb 2007
Location: Tennessee
Old 05-22-2009 , 14:07   Re: New File Vault - A newer file vault system!
Reply With Quote #10

What is the advantage of using a "name" along with the "key" rather than formatting all of the data into one to save it, and then breaking it apart to use it.
Also, what about just formatting the "name" and "key" into one key?
__________________
No private work or selling mods.
Quote:
Originally Posted by xPaw View Post
I love you exolent!
Exolent[jNr] 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 09:28.


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