30/06/2014, 02:41 AM
Hola. En este tutorial les haré entender cómo funciona FVault y cómo usarlo. Antes de empezar, si lo que deseas es CREAR algun sistema de guardado para tu plugin/mod, considera también SQL y Adv Vault. Cada uno tiene diferentes ventajas y puede que FVault no sea el más adecuado para tus necesidades.
1. Entendamos cómo funciona el guardado FVault.
Es todo por ahora. Saludos y hasta la próxima! It's me, Mario!
1. Entendamos cómo funciona el guardado FVault.
- FVault guarda los datos junto una clave (key). Para cargar estos datos, indicamos esta clave y nos entrega la información asociada a esta clave. Veamos un ejemplo de una base de datos FVault:
Código:"MarioAR" "9aeaed51f2b0f6680c4ed4b07fb1a83c" 1403687918
"paiche" "db78036eb6dbaf1d425338df125d5c71" 1403825292
"elotro" "3760ee6b2c91c54411bc87df5adf6f48" 1403825848 - Todas las lineas siguen el formato:
Código:"clave" "datos" 0000000000
- Lo que está entre las primeras " " es la clave. Con la clave podemos tener acceso a los datos asociados.
- Entre el segundo par de " " están los datos. En este caso, hay contraseñas encriptadas con md5.
- Después de los datos, sin comillas, está el timestamp. Esto es nada menos que la fecha y hora en la que se guardaron datos en esa clave por última vez (en formato Unix Time). Si no sabes qué es esto, puedes leer más aquí: Wikipedia.
- FVault nos facilita la vida con 2 stocks principales: fvault_get_data y fvault_set_data.
- Guardemos nuestros datos con fvault_set_data:
Código PHP:// fvault_set_data(const vaultname[], const key[], const data[])
// El primer parámetro es el nombre de nuestro vault.
// El segundo parámetro es la clave donde guardaremos datos.
// El tercer parámetro son los datos que guardaremos.
GuardarDatos(id)
{
// Guardaremos los datos usando el nombre del jugador como clave
static szName[32], szData[100];
get_user_name(id, szName, 31);
// Ahora vamos a poner nuestros datos
// FVault guarda y carga STRINGS
// Tenemos que poner nuestros datos en un string para guardarlos.
// En este caso, guardare la IP del jugador en los datos.
static szIP[25]; get_user_ip(ip, szIP, charsmax(szIP))
// Metemos los datos en un string
formatex(szData, charsmax(szData), "%s", szIP);
// Guardamos los datos
fvault_set_data(nuestro_vault, szName, szData);
// Qué pasará si la clave ya existe?
// Se sobreescribirán los datos, nada más.
} - Veamos cómo utilizar fvault_get_data:
Código PHP:// fvault_get_data(const vaultname[], const key[], data[], len, ×tamp=0)
// El primer parámetro es el nombre de nuestro vault.
// El segundo es la clave de la que obtendremos los datos.
// La clave tiene que ser EXACTAMENTE igual.
// El tercer parámetro es el array donde obtendremos los datos.
// El cuarto parámetro es la longitud máxima para los datos.
// El quinto parámetro (opcional) es para obtener la fecha y hora
// (Unix Time) del último guardado de datos.
// Retorna 1 si se cargaron datos, 0 si no se cargaron.
CargarDatos(id)
{
// En este caso, guardamos los datos usando el nombre como clave
static szName[32], szData[100]
get_user_name(id, szName, 31);
if (fvault_get_data(nuestro_vault, szName, szData, charsmax(szData))
{
// Cargue los datos en el condicional if
// Porque se retorna 1 (true) si se cargan datos
client_print(id, print_chat, "Tus datos: %s", szData);
}
else
{
// No se cargaron datos
client_print(id, print_chat, "No tienes datos");
}
} - Si queremos borrar datos:
Código PHP:// fvault_remove_key(const vaultname[], const key[])
// El primer parámetro es nuestra base de datos.
// El segundo la clave.
BorrarDatos(id)
{
// La clave es el nombre (EN ESTE EJEMPLO)
static szName[32];
get_user_name(id, szName, 31);
fvault_remove_key(nuestro_vault, szName);
}
- Antes de hacer esto, debemos tener en cuente que FVault tiene un límite de carácteres para los datos (512) pero en la práctica se reducen a 509. Si guardaremos números, en "teoría" pueden entrar como máximo 42 números enteros (Números de 10 cifras, con el signo - y dejando un espacio: 509/12) pero en la práctica pueden entrar muchos más.
- Aquí nos vamos a valer de 2 natives muy útiles: formatex y parse.
- Formatex() ya es conocido por la mayoría, pero veamos rápidamente cómo funciona.
Código PHP:new szName[32], szData[9999999999999999999];
get_user_name(id, szName, 31);
formatex(szData, charsmax(szData), "%d %d %s", get_user_frags(id), cs_get_user_money(id), szName)
// Simple, primero indicamos el array donde pondremos el texto.
// Segundo, la longitud máxima. (charsmax es la mejor opción aquí)
// Tercero, el texto a formatear que guardaremos:
// %d - %i nos sirve para insertar números enteros.
// %f - Números en coma flotante (decimales).
// %s - Strings.
// %c - Un carácter.
// %L - Multilenguaje de AMXX. No nos hace falta aquí
// PD: No sean tan **** de crear el array szData con 999999999 celdas, pensemos un poco
// Se introducen 2 números que no tienen más de 10 cifras (20 celdas)
// Un string de máximo 31, 2 espacios; sumando tenemos 53 carácteres.
// El máximo de celdas sería 53 + 1 del End of String = 54 - Ahora veamos parse():
Código PHP:// parse nos sirve para partir un string en cuantas partes se pueda/queramos.
// En este caso, formateé szData con 3 espacios, es decir, nos dará 4 partes.
// Si queremos que parse ignore algun espacio, tiene que estar entre comillas.
// Ej. si nuestro string contiene -> hola que tal "hola que tal" 5
// Al parsearlo obtendremos por separado (en strings):
// hola
// que
// tal
// hola que tal
// 5
static szDato1[10], szDato2[10], szDato3[32];
parse(szData, szDato1, charsmax(szDato1), szDato2, charsmax(szDato2), szDato3, charsmax(szDato3))
// Como utilizamos parse:
// El primer parámetro es el string que vamos a partir.
// Luego, los parámetros se introducen en este orden:
// 1. Array donde se guardará la parte del string que se partió.
// 2. Longitud máxima.
// Si saldrán 2 partes, entonces indicamos 2 strings y 2 longitudes, en orden.
// Ahora que tenemos los datos partidos como strings, los podemos entregar al jugador.
// Pero antes se tienen que convertir a números, para eso usamos str_to_num()
new frags = str_to_num(szDato1)
new money = str_to_num(szDato2)
// El dato 3 es un string, así que no tenemos que convertirlo.
client_print(id, print_chat, "Aprendiendo a usar formatex y parse, tienes %d frags, %d de dinero y tu nombre es %s",
frags, money, szDato3)
- FVault nos ofrece otros stocks útiles:
Código PHP:// Obtener una clave por el número de la linea del archivo donde está.
// fvault_get_keyname(const vaultname[], const keynum, key[], len)
// Primer parámetro: Nuestra base de datos.
// Segundo parámetro: La linea del archivo donde esta la clave que obtendremos.
// El tercer parámetro es el array donde obtendremos la clave.
// Está de más explicar len.
// Obtener el número de línea del archivo donde está nuestra clave
// fvault_get_keynum(const vaultname[], const key[])
// Primer parámetro: Nuestra base de datos.
// Segundo parámetro: Nuestra clave.
// Obtener la cantidad de entradas en nuestra base de datos.
// fvault_size(const vaultname[])
// El parámetro es nuestra base de datos.
// Retorna la cantidad de entradas creadas. - Qué utilidad podemos darle a estos stocks? Veamos un ejemplo: Eliminaré la última entrada creada en nuestra base de datos.
Explicación:Código PHP:new szKey[50], size = fvault_size(nuestro_vault)-1;
fvault_get_keyname(nuestro_vault, size, szKey, charsmax(szKey));
fvaut_remove_key(nuestro_vault, szKey);
Obtuvimos el nombre del key de la última entrada creada. Si tenemos 2 entradas, la primera será la linea 0 y la segunda la línea 1. Si tenemos 3 entradas, la primera la 0, segunda 1 y tercera 2. Se cumple que la línea de la última entrada es igual a la cantidad de entradas - 1.
- Ahora veamos como iterar a través de una base de datos.
Por supuesto que hay formas mucho más eficientes de hacer esto, pero implicaría leer el archivo no como una base de datos, sino como 'file' y me estaría escapando del tema de este tutorial. Si te interesa, puedes leer el código fuente de este plugin, función cargar_todos_los_datos() (No lo hagas si no tienes conocimientos sobre leer/modificar archivos desde un plugin, o podrías confundirte).Código PHP:new szKey[64], szData[512], size = fvault_size(nuestro_vault);
// Hacemos un bucle en todo lo largo de nuestro vault
for (new i = 0; i < size; i++)
{
// Obtenemos la clave
fvault_get_keyname(nuestro_vault, i, szKey, charsmax(szKey));
// Ahora que tenemos la clave podemos obtener los datos
fvault_get_data(nuestro_vault, szKey, szData, charsmax(szData));
console_print(0, "Clave %d : %s Datos: %s", i+1, szKey, szData);
}
- Las bases de datos de FVault se pueden editar con programas básicos de edición de texto, como el Bloc de Notas de Windows, WordPad, etc. Las claves y los datos están tal cual se guardaron, es decir, si guardaste una dirección IP (123.456.789.0) la encontrarás tal cual en la base de datos.
- Veamos un ejemplo de una base de datos que contiene nombres en las claves y una dirección IP con una cantidad de dinero en los datos:
Código:"Mario AR." "190.12.72.50 16000" 1404080472
"BAILOPAN" "255.255.255.255 99999" 946684799
- Ahora, haré que BAILOPAN tenga 800$ y su IP sea 8.8.8.8
Código:"Mario AR." "190.12.72.50 16000" 1404080472
"BAILOPAN" "8.8.8.8 800" 946684799
- ¿Tan fácil? Sí, así de fácil, pero la intención por la que explico esto es por el siguiente punto en esta lista.
- Si observamos detalladamente, veremos que la base de datos tiene una línea en blanco al final. ES IMPORTANTE NO BORRAR ESTA LÍNEA o podremos bugear nuestra base de datos.
- Si utilizas MUCHO los stocks de FVault en tu código, considera editar la librería (#include) fvault y cambiar los new por static.
- Un stock modificado para utilizar fvault de forma más eficiente. Comenta o borra la linea #define USAR_TIMESTAMP si no vas a usar el timestamp con este stock, mejorará el rendimiento. Funciona muy parecido a fvault_get_keyname pero también te obtiene los datos.
Código PHP:#define USAR_TIMESTAMP
/**
* Retrieves a key name and its data specified by its number
*
* @param vaultname Vault name to look in
* @param keynum Key number within the vault to find key name and data
* @param key String which key name will be copied to
* @param len_key Length of key name
* @param data String which data will be copied to
* @param len_data Length of data
* @param timestamp The unix time of when the data was last set ( -1 if permanent data, 0 if old fvault version ) ( optional param )
* @return Returns 1 on success, 0 on failue.
*/
fvault_get_key_and_data(const vaultname[], const keynum, key[], len_key, data[], len_data, ×tamp=0)
{
new _data[580];
_FormatVaultName(vaultname, _data, sizeof(_data) - 1);
if( !file_exists(_data) )
{
return 0;
}
new vault = fopen(_data, "rt");
new line = -1;
while( !feof(vault) )
{
fgets(vault, _data, sizeof(_data) - 1);
if( ++line == keynum )
{
parse(_data, key, len_key, data, len_data);
#if defined USAR_TIMESTAMP
new _time[32];
for( new i = strlen(data) - 1; i > 0; i-- )
{
if( data[i] == '"' ) break;
if( data[i] == ' '
&& data[i - 1] == '"' )
{
data[i - 1] = '^0';
copy(_time, sizeof(_time) - 1, data[i + 1]);
timestamp = str_to_num(_time);
break;
}
}
#endif
fclose(vault);
return 1;
}
}
fclose(vault);
return 0;
}
Es todo por ahora. Saludos y hasta la próxima! It's me, Mario!