27/07/2020, 11:31 PM
API: SETTINGS SYSTEM
Buenas noches, hacia mucho tiempo que no pasaba por aqui.
Queria compartir con ustedes esta API que diseñe hacia unas semanas ya.
• ¿EN QUE CONSISTE?
Basicamente esta API nos permite interactuar con archivos de configuracion de una manera mas sencilla.
Los "archivos de configuracion" son aquellos utilizados por la mayoria de los MODs para customizar sus modos de juego de manera "exterior", sin necesidad de re-compilar el MOD (en conclusion = archivos INI, aunque puede ser usado con cualquier archivo permitido).
No esta demas decir que la idea de esta API esta fundamentada en base a esto: Settings API (load/save data to INI files). Sin embargo la manera en como lo hace es muy diferente, optando por cargar los archivos en memoria, en lugar de leerlos cada vez que se requiere cargar un dato (para mayor informacion, leer el codigo fuente).
• ¿COMO SE UTILIZA?
Actualmente cuenta con 7 natives, las cuales son las siguientes:
Código PHP:
/*
==================================================
native: settings_open_file()
usage: opens a file
params:
- szFileName[]: name of file that will be open
return: int
- -1: file can't be open (the reason will be shown)
- 0+: file's id (it is not the same that fopen() returns)
==================================================
*/
native settings_open_file(const szFileName[]);
/*
==================================================
native: settings_load_bool()
usage: loads a value (bool) from a file
params:
- iFileId: the file-id
- szSectionName[]: the section where value is located
- szKey[]: the key that holds the value
- &bValueOut: variable to store result (bool-type)
return: bool
- true: value has been loaded successfully
- false: value can't be loaded (the reason will be shown)
==================================================
*/
native bool:settings_load_bool(const iFileId, const szSection[], const szKey[], &bool:bValueOut);
/*
==================================================
native: settings_load_int()
usage: loads a value (int) from a file
params:
- iFileId: the file-id
- szSectionName[]: the section where value is located
- szKey[]: the key that holds the value
- &iValueOut: variable to store result (int-type)
return: bool
- true: value has been loaded successfully
- false: value can't be loaded (the reason will be shown)
==================================================
*/
native bool:settings_load_int(const iFileId, const szSection[], const szKey[], &iValueOut);
/*
==================================================
native: settings_load_float()
usage: loads a value (float) from a file
params:
- iFileId: the file-id
- szSectionName[]: the section where value is located
- szKey[]: the key that holds the value
- &fValueOut: variable to store result (float-type)
return: bool
- true: value has been loaded successfully
- false: value can't be loaded (the reason will be shown)
==================================================
*/
native bool:settings_load_float(const iFileId, const szSection[], const szKey[], &Float:fValueOut);
/*
==================================================
native: settings_load_string()
usage: loads a value (string) from a file
params:
- iFileId: the file-id
- szSectionName[]: the section where value is located
- szKey[]: the key that holds the value
- szValueOut: buffer to store result
- iValueOut: max buffer's length
return: bool
- true: value has been loaded successfully
- false: value can't be loaded (the reason will be shown)
==================================================
*/
native bool:settings_load_string(const iFileId, const szSection[], const szKey[], szValueOut[], const iValueOutLen);
/*
==================================================
native: settings_load_darray()
usage: loads a value (dyn-array) from a file
params:
- iFileId: the file-id
- szSectionName[]: the section where value is located
- szKey[]: the key that holds the value
- &aValueOut: dyn-array to store result (dynamic array)
return: bool
- true: value has been loaded successfully
- false: value can't be loaded (the reason will be shown)
==================================================
*/
native bool:settings_load_darray(const iFileId, const iDynamicArrayType, const szKey[], const szSection[], &Array:aValueOut);
/*
==================================================
native: settings_close()
usage: closes a file
params:
- iFileId: the file-id
return: bool
- true: file has been closed successfully
- false: file can't be closed (the reason will be shown)
==================================================
*/
native bool:settings_close_file(const iFileId);
Creo que las mismas son auto-explicables.
De igual manera, cualquier duda no teman en postearla.
• CODIGO
Código PHP:
/*===============================================================================================
SETTINGS API SYSTEM
===============================================================================================*/
#include <AMXMODX>
#include <AMXMISC>
/*========================================
MISC
========================================*/
#define IS_IN_RANGE(%1,%2,%3) (%2 <= %1 <= %3)
new const bool:KEEP_LOOPING = true;
/*============================================
SETTINGS
============================================*/
#define FILES_COUNT() g_iFilesCount
#define SECTIONS_COUNT() g_CurrentFileData[em_iFileSectionsCount]
#define KEYS_COUNT(%1) %1[em_iSectionKeysCount]
#define IS_FILE_CLOSED() g_CurrentFileData[em_bFileClosed]
#define IS_FILE_LOADED(%1) TrieKeyExists(g_tFilesFastList, %1)
#define SECTION_EXISTS(%1) TrieKeyExists(g_CurrentFileData[em_tFileSectionsFastList], %1)
#define KEY_EXISTS(%1,%2) TrieKeyExists(%1[em_tSectionKeysFastList], %2)
#define GET_FILE_ID(%1,%2) TrieGetCell(g_tFilesFastList, %1, %2)
#define GET_SECTION_ID(%1,%2) TrieGetCell(g_CurrentFileData[em_tFileSectionsFastList], %1, %2)
#define GET_KEY_ID(%1,%2,%3) TrieGetCell(%1[em_tSectionKeysFastList], %2, %3)
#define ALLOCATE_FILES_LIST() g_aFilesList = ArrayCreate(file_s)
#define ALLOCATE_FILES_FAST_LIT() g_tFilesFastList = TrieCreate()
#define ALLOCATE_SECTIONS_LIST() g_CurrentFileData[em_aFileSectionsList] = ArrayCreate(section_s)
#define ALLOCATE_SECTION_FAST_LIST() g_CurrentFileData[em_tFileSectionsFastList] = TrieCreate()
#define ALLOCATE_KEYS_LIST(%1) %1[em_aSectionKeysList] = ArrayCreate(key_s)
#define ALLOCATE_KEYS_FAST_LIST(%1) %1[em_tSectionKeysFastList] = TrieCreate()
#define ALLOCATE_KEY_VALUES(%1) %1[em_tKeyValues] = TrieCreate()
#define ADD_FILE_TO_LIST() ArrayPushArray(g_aFilesList, g_CurrentFileData)
#define ADD_FILE_TO_FAST_LIST(%1) TrieSetCell(g_tFilesFastList, %1, FILES_COUNT()++)
#define ADD_SECTION_TO_LIST(%1) ArrayPushArray(g_CurrentFileData[em_aFileSectionsList], %1)
#define ADD_SECTION_TO_FAST_LIST(%1) TrieSetCell(g_CurrentFileData[em_tFileSectionsFastList], %1, SECTIONS_COUNT()++)
#define ADD_KEY_TO_LIST(%1,%2) ArrayPushArray(%1[em_aSectionKeysList], %2)
#define ADD_KEY_TO_FAST_LIST(%1,%2,%3) TrieSetCell(%1[em_tSectionKeysFastList], %2, %3)
#define ADD_KEY_VALUE(%1,%2) TrieSetString(%1[em_tKeyValues], %2, g_szValue)
#define LOAD_FILE_DATA(%1) ArrayGetArray(g_aFilesList, %1, g_CurrentFileData)
#define LOAD_SECTION_DATA(%1,%2) ArrayGetArray(g_CurrentFileData[em_aFileSectionsList], %1, %2)
#define LOAD_KEY_DATA(%1,%2,%3) ArrayGetArray(%1[em_aSectionKeysList], %2, %3)
#define LOAD_KEY_VALUE(%1,%2) TrieGetString(%1[em_tKeyValues], %2, g_szValue, charsmax(g_szValue))
#define UPDATE_FILE_DATA(%1) ArraySetArray(g_aFilesList, %1, g_CurrentFileData)
#define CLEAR_FILES_DATA() ArrayDestroy(g_aFilesList)
#define CLEAR_FILES_FAST_DATA() TrieDestroy(g_tFilesFastList)
#define CLEAR_FILE_DATA(%1) ArrayDestroy(g_CurrentFileData[em_aFileSectionsList])
#define CLEAR_FILE_FAST_DATA(%1) TrieDestroy(g_CurrentFileData[em_tFileSectionsFastList])
#define CLEAR_SECTION_DATA(%1) ArrayDestroy(%1[em_aSectionKeysList])
#define CLEAR_SECTION_FAST_DATA(%1) TrieDestroy(%1[em_tSectionKeysFastList])
#define CLEAR_KEY_DATA(%1) TrieDestroy(%1[em_tKeyValues])
#define CLOSE_FILE() g_CurrentFileData[em_bFileClosed] = true
#define REOPEN_FILE() g_CurrentFileData[em_bFileClosed] = false
#define MAX_FILE_NAME_LEN 40
#define MAX_SECTION_NAME_LEN 20
#define MAX_KEY_NAME_LEN 30
#define MAX_KEY_VALUE_LEN 256
#define MAX_LINE_LEN MAX_KEY_VALUE_LEN + MAX_KEY_NAME_LEN
// this will close (free) all files data
// keep in mind that when you used this
// you will need to RE-ALLOCATE files data again
// I mean:
// ALLOCATE_FILES_LIST()
// ALLOCATE_FILES_FAST_LIT()
const CLOSE_ALL_FILES = -(1<<30);
enum file_s
{
bool:em_bFileClosed,
em_iFileSectionsCount,
em_szFileName[MAX_FILE_NAME_LEN],
Array:em_aFileSectionsList,
Trie:em_tFileSectionsFastList // same of above, but for sections ids (fast-lookup)
};
enum section_s
{
em_iSectionKeysCount,
em_szSectionName[MAX_SECTION_NAME_LEN],
Array:em_aSectionKeysList,
Trie:em_tSectionKeysFastList // same as the sections uses, but for keys
};
enum key_s
{
em_szKeyName[MAX_KEY_NAME_LEN],
Trie:em_tKeyValues // values are stored in a hash-map for fast-lookup searchs
};
// value-types for LoadFileValue()
enum _:ValueTypes
{
VALUE_TYPE_BOOL = 0,
VALUE_TYPE_INT,
VALUE_TYPE_FLOAT,
// "DARR" stands for dynamic array
// the same as used on ArrayCreate native
VALUE_TYPE_DARR_BOOL, // array of bools
VALUE_TYPE_DARR_INT, // array of ints
VALUE_TYPE_DARR_FLOAT, // array of floats
VALUE_TYPE_DARR_STRING // array of strings
};
new g_iFilesCount;
new g_iCurrentFile;
new g_szLine[MAX_LINE_LEN];
new g_szValue[MAX_KEY_VALUE_LEN];
new g_CurrentFileData[file_s];
new Array:g_aFilesList;
new Trie:g_tFilesFastList; // same as above, but for files ids (fast lookup)
/*=======================================
API
=======================================*/
#define MAX_FUNCTION_NAME 30
/*============================
EXPORTED NATIVES
============================*/
#define MAX_NATIVE_NAME 30
enum exported_native_s
{
em_szNativeName[MAX_NATIVE_NAME],
em_szNativeFunc[MAX_FUNCTION_NAME],
em_iNativeParams
};
enum _:NativesList
{
/* SETTINGS API NATIVES */
NATIVE_OPEN_FILE = 0,
NATIVE_LOAD_BOOL,
NATIVE_LOAD_INT,
NATIVE_LOAD_FLOAT,
NATIVE_LOAD_STRING,
NATIVE_LOAD_DARRAY,
NATIVE_CLOSE_FILE
};
new const c_ExportedNatives[NativesList][exported_native_s] =
{
/* SETTINGS API NATIVES */
{ "settings_open_file", "API_OpenFile", 1, },
{ "settings_load_bool", "API_LoadBool", 4, },
{ "settings_load_int", "API_LoadInt", 4, },
{ "settings_load_float", "API_LoadFloat", 4, },
{ "settings_load_string", "API_LoadString", 5, },
{ "settings_load_darray", "API_LoadDynamicArray", 5, },
{ "settings_close_file", "API_CloseFile", 1, }
};
/*===============================================================================
API
===============================================================================*/
/*====================================================
EXPORTED NATIVES
====================================================*/
public bool:API_CloseFile(const iPluginId, const iParams)
{
new iExpected = c_ExportedNatives[NATIVE_CLOSE_FILE][em_iNativeParams];
if (iParams != iExpected)
{
log_amx("API_CloseFile(): invalid params-count (expected: %d | got: %d)", iExpected, iParams);
return false;
}
new iFileId = get_param(1);
if (!IS_IN_RANGE(iFileId, 0, FILES_COUNT() - 1))
{
log_amx("API_CloseFile(): invalid file-id (%d)", iFileId);
return false;
}
CloseFile(iFileId);
return true;
}
public bool:API_LoadDynamicArray(const iPluginId, const iParams)
{
new iExpected = c_ExportedNatives[NATIVE_LOAD_DARRAY][em_iNativeParams];
if (iParams != iExpected)
{
log_amx("API_LoadDynamicArray(): invalid params-count (expected: %d | got: %d)", iExpected, iParams);
return false;
}
new iId = get_param(1);
if (!IS_IN_RANGE(iId, 0, FILES_COUNT() - 1))
{
log_amx("API_LoadDynamicArray(): invalid file-id (%d)", iId);
return false;
}
new iType = get_param(2);
if (!IS_IN_RANGE(iType, VALUE_TYPE_DARR_BOOL, VALUE_TYPE_DARR_STRING))
{
log_amx("API_LoadDynamicArray(): invalid darray-type (%d)", iType);
return false;
}
new szSection[MAX_SECTION_NAME_LEN];
get_string(3, szSection, charsmax(szSection));
if (!szSection[0] || strlen(szSection) <= 1)
{
log_amx("API_LoadDynamicArray(): invalid section-name (^"%s^")", szSection);
return false;
}
new szKey[MAX_SECTION_NAME_LEN];
get_string(4, szKey, charsmax(szKey));
if (!szKey[0] || strlen(szKey) <= 1)
{
log_amx("API_LoadDynamicArray(): invalid key-name (^"%s^")", szKey);
return false;
}
new Array:aValueOut = Array:get_param_byref(5);
if (aValueOut == Invalid_Array)
{
log_amx("API_LoadDynamicArray(): invalid array-handle (%d)", aValueOut);
return false;
}
if (LoadFileValue(iId, iType, szSection, szKey, aValueOut))
return true;
return true;
}
public bool:API_LoadString(const iPluginId, const iParams)
{
new iExpected = c_ExportedNatives[NATIVE_LOAD_STRING][em_iNativeParams];
if (iParams != iExpected)
{
log_amx("API_LoadString(): invalid params-count (expected: %d | got: %d)", iExpected, iParams);
return false;
}
new iId = get_param(1);
if (!IS_IN_RANGE(iId, 0, FILES_COUNT() - 1))
{
log_amx("API_LoadString(): invalid file-id (%d)", iId);
return false;
}
new szSection[MAX_SECTION_NAME_LEN];
get_string(2, szSection, charsmax(szSection));
if (!szSection[0] || strlen(szSection) <= 1)
{
log_amx("API_LoadString(): invalid section-name (^"%s^")", szSection);
return false;
}
new szKey[MAX_SECTION_NAME_LEN];
get_string(3, szKey, charsmax(szKey));
if (!szKey[0] || strlen(szKey) <= 1)
{
log_amx("API_LoadString(): invalid key-name (^"%s^")", szKey);
return false;
}
new iLenOut = get_param(5);
// single-strings are handle on a different way
if (LoadFileValueString(iId, szSection, szKey))
{
set_string(4, g_szValue, iLenOut);
return true;
}
return false;
}
public bool:API_LoadFloat(const iPluginId, const iParams)
{
new iExpected = c_ExportedNatives[NATIVE_LOAD_FLOAT][em_iNativeParams];
if (iParams != iExpected)
{
log_amx("API_LoadInt(): invalid params-count (expected: %d | got: %d)", iExpected, iParams);
return false;
}
new iId = get_param(1);
if (!IS_IN_RANGE(iId, 0, FILES_COUNT() - 1))
{
log_amx("API_LoadFloat(): invalid file-id (%d)", iId);
return false;
}
new szSection[MAX_SECTION_NAME_LEN];
get_string(2, szSection, charsmax(szSection));
if (!szSection[0] || strlen(szSection) <= 1)
{
log_amx("API_LoadFloat(): invalid section-name (^"%s^")", szSection);
return false;
}
new szKey[MAX_SECTION_NAME_LEN];
get_string(3, szKey, charsmax(szKey));
if (!szKey[0] || strlen(szKey) <= 1)
{
log_amx("API_LoadFloat(): invalid key-name (^"%s^")", szKey);
return false;
}
new Float:fValueOut;
if (LoadFileValue(iId, VALUE_TYPE_FLOAT, szSection, szKey, fValueOut))
{
set_float_byref(4, fValueOut);
return true;
}
return false;
}
public bool:API_LoadInt(const iPluginId, const iParams)
{
new iExpected = c_ExportedNatives[NATIVE_LOAD_INT][em_iNativeParams];
if (iParams != iExpected)
{
log_amx("API_LoadInt(): invalid params-count (expected: %d | got: %d)", iExpected, iParams);
return false;
}
new iId = get_param(1);
if (!IS_IN_RANGE(iId, 0, FILES_COUNT() - 1))
{
log_amx("API_LoadInt(): invalid file-id (%d)", iId);
return false;
}
new szSection[MAX_SECTION_NAME_LEN];
get_string(2, szSection, charsmax(szSection));
if (!szSection[0] || strlen(szSection) <= 1)
{
log_amx("API_LoadInt(): invalid section-name (^"%s^")", szSection);
return false;
}
new szKey[MAX_SECTION_NAME_LEN];
get_string(3, szKey, charsmax(szKey));
if (!szKey[0] || strlen(szKey) <= 1)
{
log_amx("API_LoadInt(): invalid key-name (^"%s^")", szKey);
return false;
}
new iValueOut;
if (LoadFileValue(iId, VALUE_TYPE_INT, szSection, szKey, iValueOut))
{
set_param_byref(4, iValueOut);
return true;
}
return false;
}
public bool:API_LoadBool(const iPluginId, const iParams)
{
new iExpected = c_ExportedNatives[NATIVE_LOAD_BOOL][em_iNativeParams];
if (iParams != iExpected)
{
log_amx("API_LoadBool(): invalid params-count (expected: %d | got: %d)", iExpected, iParams);
return false;
}
new iId = get_param(1);
if (!IS_IN_RANGE(iId, 0, FILES_COUNT() - 1))
{
log_amx("API_LoadBool(): invalid file-id (%d)", iId);
return false;
}
new szSection[MAX_SECTION_NAME_LEN];
get_string(2, szSection, charsmax(szSection));
if (!szSection[0] || strlen(szSection) <= 1)
{
log_amx("API_LoadBool(): invalid section-name (^"%s^")", szSection);
return false;
}
new szKey[MAX_SECTION_NAME_LEN];
get_string(3, szKey, charsmax(szKey));
if (!szKey[0] || strlen(szKey) <= 1)
{
log_amx("API_LoadBool(): invalid key-name (^"%s^")", szKey);
return false;
}
new bool:bValueOut;
if (LoadFileValue(iId, VALUE_TYPE_BOOL, szSection, szKey, bValueOut))
{
set_param_byref(4, bValueOut);
return true;
}
return false;
}
public API_OpenFile(const iPluginId, const iParams)
{
new iExpected = c_ExportedNatives[NATIVE_OPEN_FILE][em_iNativeParams];
if (iParams != iExpected)
{
log_amx("API_OpenFile(): invalid params-count (expected: %d | got: %d)", iExpected, iParams);
return -1;
}
new szFile[MAX_FILE_NAME_LEN];
get_string(1, szFile, charsmax(szFile));
return OpenFile(szFile);
}
/*================================================================================
MAIN
================================================================================*/
SetFailState(const szMessage[], any:...)
{
static szText[128];
if (numargs() == 1)
copy(szText, charsmax(szText), szMessage);
else
vformat(szText, charsmax(szText), szMessage, 2);
set_fail_state(szText);
}
/*============================================
SETTINGS
============================================*/
/*
==================================================
CloseFile()
==================================================
*/
CloseFile(const iFileId)
{
// close all files?
if (iFileId == CLOSE_ALL_FILES)
{
new SectionData[section_s];
new KeyData[key_s];
for (new iFile; iFile < FILES_COUNT(); iFile++)
{
LOAD_FILE_DATA(iFile);
for (new iSection; iSection < SECTIONS_COUNT(); iSection++)
{
LOAD_SECTION_DATA(iSection, SectionData);
for (new iKey; iKey < KEYS_COUNT(SectionData); iKey++)
{
LOAD_KEY_DATA(SectionData, iKey, KeyData);
CLEAR_KEY_DATA(KeyData);
}
CLEAR_SECTION_DATA(SectionData);
CLEAR_SECTION_FAST_DATA(SectionData);
}
CLEAR_FILE_DATA();
CLEAR_FILE_FAST_DATA();
}
CLEAR_FILES_DATA();
CLEAR_FILES_FAST_DATA();
return;
}
LoadFileData(iFileId);
CLOSE_FILE();
UPDATE_FILE_DATA(iFileId);
g_iCurrentFile = -1;
}
/*
==================================================
IsFileClosed()
==================================================
*/
bool:IsFileClosed(const iFileId)
{
LoadFileData(iFileId);
if (IS_FILE_CLOSED())
return true;
return false;
}
/*
==================================================
ReOpenFile()
==================================================
*/
ReOpenFile(const iFileId)
{
LoadFileData(iFileId);
REOPEN_FILE();
UPDATE_FILE_DATA(iFileId);
}
/*
==================================================
CanReOpenFile()
==================================================
*/
bool:CanReOpenFile(const iFileId)
{
if (iFileId == -1 || !IsFileClosed(iFileId))
return false;
return true;
}
/*
==================================================
ParseValueToArray()
==================================================
*/
ParseValueToArray(const iDynamicArrayType, &Array:aValueOut)
{
static szValue[20];
while (g_szValue[0] != 0)
{
strtok(g_szValue, szValue, charsmax(szValue), g_szValue, charsmax(g_szValue), ',');
trim(g_szValue);
trim(szValue);
switch(iDynamicArrayType)
{
case VALUE_TYPE_DARR_BOOL: ArrayPushCell(aValueOut, bool:equal(szValue, "true"));
case VALUE_TYPE_DARR_INT: ArrayPushCell(aValueOut, str_to_num(szValue));
case VALUE_TYPE_DARR_FLOAT: ArrayPushCell(aValueOut, str_to_float(szValue));
case VALUE_TYPE_DARR_STRING: ArrayPushString(aValueOut, szValue);
}
}
}
/*
==================================================
GetKeyId()
==================================================
*/
GetKeyId(const szKeyName[], const iAssociatedSection)
{
new iId = -1;
new SectionData[section_s];
{
LOAD_SECTION_DATA(iAssociatedSection, SectionData);
}
GET_KEY_ID(SectionData, szKeyName, iId);
return iId;
}
/*
==================================================
GetSectionId()
==================================================
*/
GetSectionId(const szSectionName[])
{
new iId = -1;
GET_SECTION_ID(szSectionName, iId);
return iId;
}
/*
==================================================
LoadFileData()
==================================================
*/
LoadFileData(const iFileId)
{
if (g_iCurrentFile != iFileId)
{
LOAD_FILE_DATA(iFileId);
g_iCurrentFile = iFileId;
}
}
/*
==================================================
LoadFileValueString()
==================================================
*/
bool:LoadFileValueString(const iFileId, const szSectionName[], const szKeyName[])
{
// file closed?
if (IsFileClosed(iFileId))
{
log_amx("LoadFileValueString(): file already closed (you need to open it again)");
return false;
}
LoadFileData(iFileId);
new iSectionId = GetSectionId(szSectionName); // get section's id
if (iSectionId == -1) // section doesn't exists
{
log_amx("LoadFileValueString(): section ^"%s^" doesn't exists", szSectionName);
return false;
}
new iKeyId = GetKeyId(szKeyName, iSectionId); // get key's id
if (iKeyId == -1) // key doesn't exists
{
log_amx("LoadFileValueString(): key ^"%s^" doesn't belong to ^"%s^" section", szKeyName, szSectionName);
return false;
}
new SectionData[section_s];
LOAD_SECTION_DATA(iSectionId, SectionData);
new KeyData[key_s];
LOAD_KEY_DATA(SectionData, iKeyId, KeyData);
LOAD_KEY_VALUE(KeyData, szKeyName);
return true;
}
/*
==================================================
LoadFileValue()
==================================================
*/
bool:LoadFileValue(const iFileId, const iValueType, const szSectionName[], const szKeyName[], &any:ValueOut)
{
// file closed?
if (IsFileClosed(iFileId))
{
log_amx("LoadFileValue(): file already closed (you need to open it again)");
return false;
}
// invalid value-type? (see ValueTypes enum)
if (!IS_IN_RANGE(iValueType, VALUE_TYPE_BOOL, VALUE_TYPE_DARR_STRING))
{
SetFailState("LoadFileValue(): invalid value-type (%d)", iValueType);
return false;
}
LoadFileData(iFileId);
new iSectionId = GetSectionId(szSectionName); // get section's id
if (iSectionId == -1) // section doesn't exists
{
log_amx("LoadFileValue(): section ^"%s^" doesn't exists", szSectionName);
return false;
}
new iKeyId = GetKeyId(szKeyName, iSectionId); // get key's id
if (iKeyId == -1) // key doesn't exists on section
{
log_amx("LoadFileValue(): key ^"%s^" doesn't belong to ^"%s^" section", szKeyName, szSectionName);
return false;
}
new SectionData[section_s];
LOAD_SECTION_DATA(iSectionId, SectionData);
new KeyData[key_s];
LOAD_KEY_DATA(SectionData, iKeyId, KeyData);
LOAD_KEY_VALUE(KeyData, szKeyName);
switch (iValueType)
{
case VALUE_TYPE_BOOL: ValueOut = bool:equal(g_szValue, "true");
case VALUE_TYPE_INT: ValueOut = str_to_num(g_szValue);
case VALUE_TYPE_FLOAT: ValueOut = str_to_float(g_szValue);
case VALUE_TYPE_DARR_BOOL..VALUE_TYPE_DARR_STRING: ParseValueToArray(iValueType, ValueOut);
}
return true;
}
/*
==================================================
IsKeyLine()
==================================================
*/
bool:IsKeyLine()
{
return bool:(contain(g_szLine, "=") != -1);
}
/*
==================================================
IsSectionLine()
==================================================
*/
bool:IsSectionLine()
{
new iPos = contain(g_szLine, "]");
return bool:(g_szLine[0] == '[' && iPos != -1);
}
/*
==================================================
IsCommentLine()
==================================================
*/
bool:IsCommentLine()
{
return bool:(g_szLine[0] == ';' || equal(g_szLine, "//", 2));
}
/*
==================================================
ReadFileLine()
==================================================
*/
bool:ReadFileLine(const iFile)
{
if (!iFile)
{
SetFailState("ReadFileLine(): invalid file (%d)", iFile);
return false;
}
if (feof(iFile))
return false;
fgets(iFile, g_szLine, charsmax(g_szLine));
replace(g_szLine, charsmax(g_szLine), "^n", "");
return true;
}
/*
==================================================
LoadFile()
==================================================
*/
bool:LoadFile(const iFile)
{
arrayset(g_CurrentFileData, 0, file_s);
// allocate file's sections lists (normal & fast-lookup)
ALLOCATE_SECTIONS_LIST();
ALLOCATE_SECTION_FAST_LIST();
new SectionData[section_s];
new KeyData[key_s];
static szKey[MAX_KEY_NAME_LEN];
new bool:bSaveSection; // are inside a section? then need to be saved
// only used for search the "]" character
// this is the section's name-end character
new iPos;
// read next line
while (KEEP_LOOPING)
{
// we have reach file's end
if (!ReadFileLine(iFile))
{
// check for some section to be saved
if (bSaveSection)
{
// save section
ADD_SECTION_TO_LIST(SectionData);
ADD_SECTION_TO_FAST_LIST(SectionData[em_szSectionName]);
bSaveSection = false;
}
break;
}
// comment line?
if (IsCommentLine())
continue;
// section line?
if (IsSectionLine())
{
// check for some section to be saved
if (bSaveSection)
{
// save section
ADD_SECTION_TO_LIST(SectionData);
ADD_SECTION_TO_FAST_LIST(SectionData[em_szSectionName]);
bSaveSection = false;
}
// clear previous section data
arrayset(SectionData, 0, section_s);
iPos = contain(g_szLine, "]"); // find "]" character
// check if section name-lenght is greather than size assigned to it
if (iPos > MAX_SECTION_NAME_LEN)
{
// copy only the assigned size
copy(SectionData[em_szSectionName], MAX_SECTION_NAME_LEN - 1, g_szLine[1]);
}
else
{
// copy full-name, but ignore the "]" character
copy(SectionData[em_szSectionName], iPos - 1, g_szLine[1]);
}
// check if a section with same name has been registered previously
if (SECTION_EXISTS(SectionData[em_szSectionName]))
{
SetFailState("LoadFile(): there can't be two sections with the same name (section named ^"%s^" already exists)", SectionData[em_szSectionName]);
return false;
}
// allocate section's keys lists (normal & fast-lookup)
ALLOCATE_KEYS_LIST(SectionData);
ALLOCATE_KEYS_FAST_LIST(SectionData);
bSaveSection = true;
}
else if (IsKeyLine())
{
// clear previous
arrayset(KeyData, 0, key_s);
strtok(g_szLine, szKey, charsmax(szKey), g_szValue, charsmax(g_szValue), '=');
trim(szKey);
trim(g_szValue);
if (KEY_EXISTS(SectionData, szKey))
{
SetFailState("LoadFile(): there can't be two keys equals on a section");
return false;
}
copy(KeyData[em_szKeyName], MAX_KEY_NAME_LEN - 1, szKey);
// allocate key's values
ALLOCATE_KEY_VALUES(KeyData);
// save key-value
ADD_KEY_VALUE(KeyData, szKey);
// save key
ADD_KEY_TO_LIST(SectionData, KeyData);
ADD_KEY_TO_FAST_LIST(SectionData, szKey, SectionData[em_iSectionKeysCount]++);
}
}
fclose(iFile);
return true;
}
/*
==================================================
OpenFile()
==================================================
*/
OpenFile(const szFileName[])
{
// add space for base-address: "addons/amxmodx/configs"
new szPath[MAX_FILE_NAME_LEN + 25];
get_configsdir(szPath, charsmax(szPath));
format(szPath, charsmax(szPath), "%s/%s", szPath, szFileName);
if (!file_exists(szPath))
{
log_amx("OpenFile(): file ^"%s^" doesn't exists", szPath);
return -1;
}
// check if file was previously loaded
if (IS_FILE_LOADED(szFileName))
{
new iFileId = -1;
GET_FILE_ID(szFileName, iFileId);
// can re-open file?
if (CanReOpenFile(iFileId))
{
// do it, and return it's id
ReOpenFile(iFileId);
return iFileId;
}
// file is attempt to be opened twice
log_amx("OpenFile:() file ^"%s^" already loaded", szPath);
return -1;
}
new iFile = fopen(szPath, "rt");
if (!iFile)
{
log_amx("OpenFile(): can't read file ^"%s^"", szPath);
return -1;
}
// go to load file's data
if (LoadFile(iFile))
{
// file loaded successfully, so add it to the both: normal & fast-lookup lists
ADD_FILE_TO_LIST();
ADD_FILE_TO_FAST_LIST(szFileName);
return FILES_COUNT() - 1;
}
return -1; // should never reach here
}
/*=========================================================================================
AMXX FORWARDS
=========================================================================================*/
/*
==================================================
plugin_end()
==================================================
*/
public plugin_end()
{
CloseFile(CLOSE_ALL_FILES);
}
/*
==================================================
plugin_precache()
==================================================
*/
public plugin_precache()
{
ALLOCATE_FILES_LIST();
ALLOCATE_FILES_FAST_LIT();
}
/*
==================================================
plugin_natives()
==================================================
*/
public plugin_natives()
{
new szNative[MAX_NATIVE_NAME];
new szFunc[MAX_FUNCTION_NAME];
for (new i; i < sizeof c_ExportedNatives; i++)
{
copy(szNative, charsmax(szNative), c_ExportedNatives[i][em_szNativeName]);
copy(szFunc, charsmax(szFunc), c_ExportedNatives[i][em_szNativeFunc]);
if (szNative[0] && szFunc[0])
register_native(szNative, szFunc);
}
}
• CREDITOS
Principalmente los creditos van para MeRcyLeZZ debido a lo anteriormente mencionado, sin contar porciones de codigo de su Zombie Plague Mod
No duden en postear cualquier inconveniente que presenten.
Adios.