Gameconfig: Add game configs natives
This commit is contained in:
parent
14513e6f70
commit
f38c726faf
|
@ -96,6 +96,7 @@ binary.sources = [
|
||||||
'../public/memtools/CDetour/asm/asm.c',
|
'../public/memtools/CDetour/asm/asm.c',
|
||||||
'CLibrarySys.cpp',
|
'CLibrarySys.cpp',
|
||||||
'CGameConfigs.cpp',
|
'CGameConfigs.cpp',
|
||||||
|
'gameconfigs.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
if builder.target_platform == 'windows':
|
if builder.target_platform == 'windows':
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
CGameConfigManager ConfigManager;
|
CGameConfigManager ConfigManager;
|
||||||
static CGameMasterReader MasterReader;
|
static CGameMasterReader MasterReader;
|
||||||
|
|
||||||
//
|
//
|
||||||
// GAME CONFIG
|
// GAME CONFIG
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@ enum
|
||||||
PSTATE_NONE,
|
PSTATE_NONE,
|
||||||
PSTATE_GAMES,
|
PSTATE_GAMES,
|
||||||
PSTATE_GAMEDEFS,
|
PSTATE_GAMEDEFS,
|
||||||
|
PSTATE_GAMEDEFS_CLASSES,
|
||||||
|
PSTATE_GAMEDEFS_CLASSES_CLASS,
|
||||||
PSTATE_GAMEDEFS_OFFSETS,
|
PSTATE_GAMEDEFS_OFFSETS,
|
||||||
PSTATE_GAMEDEFS_OFFSETS_OFFSET,
|
PSTATE_GAMEDEFS_OFFSETS_OFFSET,
|
||||||
PSTATE_GAMEDEFS_KEYS,
|
PSTATE_GAMEDEFS_KEYS,
|
||||||
|
@ -103,6 +105,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||||
m_ShouldBeReadingDefault = true;
|
m_ShouldBeReadingDefault = true;
|
||||||
strncopy(m_Game, name, sizeof(m_Game));
|
strncopy(m_Game, name, sizeof(m_Game));
|
||||||
|
|
||||||
|
m_Class[0] = '\0';
|
||||||
|
m_MatchedClasses = false;
|
||||||
m_ParseState = PSTATE_GAMEDEFS;
|
m_ParseState = PSTATE_GAMEDEFS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -112,8 +116,22 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PSTATE_GAMEDEFS:
|
case PSTATE_GAMEDEFS:
|
||||||
|
case PSTATE_GAMEDEFS_CLASSES_CLASS:
|
||||||
{
|
{
|
||||||
if (strcmp(name, "Offsets") == 0)
|
if (strcmp(name, "Classes") == 0)
|
||||||
|
{
|
||||||
|
if (!m_Class[0])
|
||||||
|
{
|
||||||
|
m_ParseState = PSTATE_GAMEDEFS_CLASSES;
|
||||||
|
m_MatchedClasses = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++m_IgnoreLevel;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "Offsets") == 0)
|
||||||
{
|
{
|
||||||
m_ParseState = PSTATE_GAMEDEFS_OFFSETS;
|
m_ParseState = PSTATE_GAMEDEFS_OFFSETS;
|
||||||
}
|
}
|
||||||
|
@ -149,14 +167,18 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_IgnoreLevel++;
|
++m_IgnoreLevel;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PSTATE_GAMEDEFS_CLASSES:
|
||||||
|
{
|
||||||
|
strncopy(m_Class, name, sizeof(m_Class));
|
||||||
|
m_ParseState = PSTATE_GAMEDEFS_CLASSES_CLASS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case PSTATE_GAMEDEFS_OFFSETS:
|
case PSTATE_GAMEDEFS_OFFSETS:
|
||||||
{
|
{
|
||||||
m_Class[0] = '\0';
|
|
||||||
|
|
||||||
strncopy(m_Offset, name, sizeof(m_Offset));
|
strncopy(m_Offset, name, sizeof(m_Offset));
|
||||||
|
|
||||||
m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET;
|
m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET;
|
||||||
|
@ -174,7 +196,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
||||||
}
|
}
|
||||||
case PSTATE_GAMEDEFS_CUSTOM:
|
case PSTATE_GAMEDEFS_CUSTOM:
|
||||||
{
|
{
|
||||||
m_CustomLevel++;
|
++m_CustomLevel;
|
||||||
return m_CustomHandler->ReadSMC_NewSection(states, name);
|
return m_CustomHandler->ReadSMC_NewSection(states, name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -228,11 +250,7 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
||||||
{
|
{
|
||||||
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
|
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
|
||||||
{
|
{
|
||||||
if (strcmp(key, "class") == 0)
|
if (g_LibSys.IsPlatformCompatible(key, &m_MatchedPlatform))
|
||||||
{
|
|
||||||
strncopy(m_Class, value, sizeof(m_Class));
|
|
||||||
}
|
|
||||||
else if (g_LibSys.IsPlatformCompatible(key, &m_MatchedPlatform))
|
|
||||||
{
|
{
|
||||||
if (m_Class[0])
|
if (m_Class[0])
|
||||||
{
|
{
|
||||||
|
@ -246,7 +264,7 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
||||||
{
|
{
|
||||||
ic->value = new OffsetClass;
|
ic->value = new OffsetClass;
|
||||||
ic->value->list.insert(m_Offset, atoi(value));
|
ic->value->list.insert(m_Offset, atoi(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -319,7 +337,7 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AMXXLOG_Error("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")",
|
AMXXLOG_Error("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")",
|
||||||
m_Address, limit, m_CurrentPath);
|
m_Address, limit, m_CurrentPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,6 +383,18 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||||
m_ParseState = PSTATE_GAMES;
|
m_ParseState = PSTATE_GAMES;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PSTATE_GAMEDEFS_CLASSES:
|
||||||
|
{
|
||||||
|
m_MatchedClasses = false;
|
||||||
|
m_ParseState = PSTATE_GAMEDEFS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PSTATE_GAMEDEFS_CLASSES_CLASS:
|
||||||
|
{
|
||||||
|
m_ParseState = PSTATE_GAMEDEFS_CLASSES;
|
||||||
|
m_Class[0] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
case PSTATE_GAMEDEFS_CUSTOM:
|
case PSTATE_GAMEDEFS_CUSTOM:
|
||||||
{
|
{
|
||||||
m_ParseState = PSTATE_GAMEDEFS;
|
m_ParseState = PSTATE_GAMEDEFS;
|
||||||
|
@ -372,9 +402,13 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PSTATE_GAMEDEFS_KEYS:
|
case PSTATE_GAMEDEFS_KEYS:
|
||||||
|
{
|
||||||
|
m_ParseState = m_MatchedClasses ? PSTATE_GAMEDEFS_CLASSES_CLASS : PSTATE_GAMEDEFS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case PSTATE_GAMEDEFS_OFFSETS:
|
case PSTATE_GAMEDEFS_OFFSETS:
|
||||||
{
|
{
|
||||||
m_ParseState = PSTATE_GAMEDEFS;
|
m_ParseState = m_MatchedClasses ? PSTATE_GAMEDEFS_CLASSES_CLASS : PSTATE_GAMEDEFS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
|
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
|
||||||
|
@ -389,7 +423,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||||
m_IgnoreLevel = 1;
|
m_IgnoreLevel = 1;
|
||||||
m_ParseState = PSTATE_GAMES;
|
m_ParseState = PSTATE_GAMES;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_ParseState = PSTATE_GAMEDEFS;
|
m_ParseState = PSTATE_GAMEDEFS;
|
||||||
}
|
}
|
||||||
|
@ -397,7 +431,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||||
}
|
}
|
||||||
case PSTATE_GAMEDEFS_SIGNATURES:
|
case PSTATE_GAMEDEFS_SIGNATURES:
|
||||||
{
|
{
|
||||||
m_ParseState = PSTATE_GAMEDEFS;
|
m_ParseState = m_MatchedClasses ? PSTATE_GAMEDEFS_CLASSES_CLASS : PSTATE_GAMEDEFS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PSTATE_GAMEDEFS_SIGNATURES_SIG:
|
case PSTATE_GAMEDEFS_SIGNATURES_SIG:
|
||||||
|
@ -413,7 +447,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||||
{
|
{
|
||||||
addressInBase = reinterpret_cast<void*>(MDLL_Spawn);
|
addressInBase = reinterpret_cast<void*>(MDLL_Spawn);
|
||||||
}
|
}
|
||||||
else if (strcmp(TempSig.library, "engine") == 0)
|
else if (strcmp(TempSig.library, "engine") == 0)
|
||||||
{
|
{
|
||||||
addressInBase = reinterpret_cast<void*>(gpGlobals);
|
addressInBase = reinterpret_cast<void*>(gpGlobals);
|
||||||
}
|
}
|
||||||
|
@ -442,7 +476,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||||
|
|
||||||
#elif defined PLATFORM_POSIX
|
#elif defined PLATFORM_POSIX
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
|
|
||||||
if (dladdr(addressInBase, &info) != 0)
|
if (dladdr(addressInBase, &info) != 0)
|
||||||
{
|
{
|
||||||
void *handle = dlopen(info.dli_fname, RTLD_NOW);
|
void *handle = dlopen(info.dli_fname, RTLD_NOW);
|
||||||
|
@ -457,7 +491,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||||
AMXXLOG_Error("Unable to load library \"%s\" (gameconf \"%s\")", TempSig.library, m_File);
|
AMXXLOG_Error("Unable to load library \"%s\" (gameconf \"%s\")", TempSig.library, m_File);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AMXXLOG_Error("Unable to find library \"%s\" in memory (gameconf \"%s\")", TempSig.library, m_File);
|
AMXXLOG_Error("Unable to find library \"%s\" in memory (gameconf \"%s\")", TempSig.library, m_File);
|
||||||
}
|
}
|
||||||
|
@ -477,7 +511,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
|
||||||
}
|
}
|
||||||
case PSTATE_GAMEDEFS_ADDRESSES:
|
case PSTATE_GAMEDEFS_ADDRESSES:
|
||||||
{
|
{
|
||||||
m_ParseState = PSTATE_GAMEDEFS;
|
m_ParseState = m_MatchedClasses ? PSTATE_GAMEDEFS_CLASSES_CLASS : PSTATE_GAMEDEFS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS:
|
case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS:
|
||||||
|
@ -516,13 +550,16 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
|
||||||
|
|
||||||
if (!g_LibSys.PathExists(path))
|
if (!g_LibSys.PathExists(path))
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
|
// Single config file without master
|
||||||
g_LibSys.PathFormat(path, sizeof(path), "%s.txt", m_File);
|
g_LibSys.PathFormat(path, sizeof(path), "%s.txt", m_File);
|
||||||
|
|
||||||
if (!EnterFile(path, error, maxlength))
|
if (!EnterFile(path, error, maxlength))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
// Allow customizations of default gamedata files
|
||||||
build_pathname_r(path, sizeof(path), "%s/gamedata/custom/%s.txt", dataDir, m_File);
|
build_pathname_r(path, sizeof(path), "%s/gamedata/custom/%s.txt", dataDir, m_File);
|
||||||
|
|
||||||
if (g_LibSys.PathExists(path))
|
if (g_LibSys.PathExists(path))
|
||||||
|
@ -605,10 +642,7 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
|
||||||
|
|
||||||
bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength)
|
bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength)
|
||||||
{
|
{
|
||||||
char path[PLATFORM_MAX_PATH];
|
build_pathname_r(m_CurrentPath, sizeof(m_CurrentPath), "%s/gamedata/%s", get_localinfo("amxx_datadir", "addons/amxmodx/data"), file);
|
||||||
build_pathname_r(path, sizeof(path), "%s/gamedata/%s", get_localinfo("amxx_datadir", "addons/amxmodx/data"), file);
|
|
||||||
|
|
||||||
strncopy(m_CurrentPath, path, sizeof(m_CurrentPath));
|
|
||||||
|
|
||||||
m_IgnoreLevel = 0;
|
m_IgnoreLevel = 0;
|
||||||
m_ShouldBeReadingDefault = true;
|
m_ShouldBeReadingDefault = true;
|
||||||
|
@ -698,7 +732,8 @@ bool CGameConfig::GetAddress(const char *key, void **retaddr)
|
||||||
*retaddr = nullptr;
|
*retaddr = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
address = *(reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(address) + offset));
|
|
||||||
|
address = reinterpret_cast<void*>(reinterpret_cast<uint8_t*>(address) + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
*retaddr = address;
|
*retaddr = address;
|
||||||
|
@ -723,7 +758,7 @@ bool CGameConfig::GetMemSig(const char *key, void **addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// CONFIG MASTER READER
|
// CONFIG MASTER READER
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -839,7 +874,7 @@ SMCResult CGameMasterReader::ReadSMC_LeavingSection(const SMCStates *states)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// CONFIG MANAGER
|
// CONFIG MANAGER
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,7 @@ class CGameConfig
|
||||||
char m_Offset[64];
|
char m_Offset[64];
|
||||||
char m_Game[256];
|
char m_Game[256];
|
||||||
|
|
||||||
|
bool m_MatchedClasses;
|
||||||
bool m_ShouldBeReadingDefault;
|
bool m_ShouldBeReadingDefault;
|
||||||
bool m_HadGame;
|
bool m_HadGame;
|
||||||
bool m_MatchedGame;
|
bool m_MatchedGame;
|
||||||
|
|
|
@ -67,6 +67,7 @@ extern AMX_NATIVE_INFO g_DataStructNatives[];
|
||||||
extern AMX_NATIVE_INFO g_StackNatives[];
|
extern AMX_NATIVE_INFO g_StackNatives[];
|
||||||
extern AMX_NATIVE_INFO g_TextParserNatives[];
|
extern AMX_NATIVE_INFO g_TextParserNatives[];
|
||||||
extern AMX_NATIVE_INFO g_CvarNatives[];
|
extern AMX_NATIVE_INFO g_CvarNatives[];
|
||||||
|
extern AMX_NATIVE_INFO g_GameConfigNatives[];
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#define DLLOAD(path) (DLHANDLE)LoadLibrary(path)
|
#define DLLOAD(path) (DLHANDLE)LoadLibrary(path)
|
||||||
|
|
174
amxmodx/gameconfigs.cpp
Normal file
174
amxmodx/gameconfigs.cpp
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
//
|
||||||
|
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||||
|
// Copyright (C) The AMX Mod X Development Team.
|
||||||
|
//
|
||||||
|
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||||
|
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||||
|
// https://alliedmods.net/amxmodx-license
|
||||||
|
|
||||||
|
#include "gameconfigs.h"
|
||||||
|
#include "amxmodx.h"
|
||||||
|
#include "CGameConfigs.h"
|
||||||
|
|
||||||
|
Handle<GameConfigNative> GameConfigHandle;
|
||||||
|
|
||||||
|
// native GameConfig:LoadGameConfigFile(const file[]);
|
||||||
|
static cell AMX_NATIVE_CALL LoadGameConfigFile(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
int length;
|
||||||
|
const char *filename = get_amxstring(amx, params[1], 0, length);
|
||||||
|
|
||||||
|
IGameConfig *config = nullptr;
|
||||||
|
char error[128];
|
||||||
|
|
||||||
|
if (!ConfigManager.LoadGameConfigFile(filename, &config, error, sizeof(error)))
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Unable to open %s: %s", filename, error);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int handle = GameConfigHandle.create();
|
||||||
|
|
||||||
|
auto configHandle = GameConfigHandle.lookup(handle);
|
||||||
|
|
||||||
|
if (!configHandle)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
configHandle->m_config = config;
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// native GameConfGetOffset(GameConfig:handle, const key[]);
|
||||||
|
static cell AMX_NATIVE_CALL GameConfGetOffset(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
GameConfigNative *handle = GameConfigHandle.lookup(params[1]);
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid game config handle %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length;
|
||||||
|
int value;
|
||||||
|
|
||||||
|
const char *key = get_amxstring(amx, params[2], 0, length);
|
||||||
|
|
||||||
|
if (!handle->m_config->GetOffset(key, &value))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// native GameConfGetClassOffset(GameConfig:handle, const classname[], const key[]);
|
||||||
|
static cell AMX_NATIVE_CALL GameConfGetClassOffset(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
GameConfigNative *handle = GameConfigHandle.lookup(params[1]);
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid game config handle %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length;
|
||||||
|
int value;
|
||||||
|
|
||||||
|
const char *classname = get_amxstring(amx, params[2], 0, length);
|
||||||
|
const char *key = get_amxstring(amx, params[3], 1, length);
|
||||||
|
|
||||||
|
if (!handle->m_config->GetOffsetByClass(classname, key, &value))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// native bool:GameConfGetKeyValue(GameConfig:handle, const key[], buffer[], maxlen);
|
||||||
|
static cell AMX_NATIVE_CALL GameConfGetKeyValue(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
GameConfigNative *handle = GameConfigHandle.lookup(params[1]);
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid game config handle %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length;
|
||||||
|
const char *value;
|
||||||
|
const char *key = get_amxstring(amx, params[2], 0, length);
|
||||||
|
|
||||||
|
if (!(value = handle->m_config->GetKeyValue(key)))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_amxstring_utf8(amx, params[3], value, strlen(value), params[4]);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// native GameConfGetAddress(GameConfig:handle, const name[]);
|
||||||
|
static cell AMX_NATIVE_CALL GameConfGetAddress(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
GameConfigNative *handle = GameConfigHandle.lookup(params[1]);
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
{
|
||||||
|
LogError(amx, AMX_ERR_NATIVE, "Invalid game config handle %d", params[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length;
|
||||||
|
void *value;
|
||||||
|
|
||||||
|
const char *key = get_amxstring(amx, params[2], 0, length);
|
||||||
|
|
||||||
|
if (!handle->m_config->GetAddress(key, &value))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<cell>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// native CloseGameConfigFile(&GameConfig:handle);
|
||||||
|
static cell AMX_NATIVE_CALL CloseGameConfigFile(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
cell *address = get_amxaddr(amx, params[1]);
|
||||||
|
|
||||||
|
GameConfigNative *handle = GameConfigHandle.lookup(*address);
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GameConfigHandle.destroy(*address))
|
||||||
|
{
|
||||||
|
*address = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AMX_NATIVE_INFO g_GameConfigNatives[] =
|
||||||
|
{
|
||||||
|
{ "LoadGameConfigFile" , LoadGameConfigFile },
|
||||||
|
{ "GameConfGetOffset" , GameConfGetOffset },
|
||||||
|
{ "GameConfGetClassOffset", GameConfGetClassOffset },
|
||||||
|
{ "GameConfGetKeyValue" , GameConfGetKeyValue },
|
||||||
|
{ "GameConfGetAddress" , GameConfGetAddress },
|
||||||
|
{ "CloseGameConfigFile" , CloseGameConfigFile },
|
||||||
|
{ nullptr , nullptr }
|
||||||
|
};
|
18
amxmodx/gameconfigs.h
Normal file
18
amxmodx/gameconfigs.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
//
|
||||||
|
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||||
|
// Copyright (C) The AMX Mod X Development Team.
|
||||||
|
//
|
||||||
|
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||||
|
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||||
|
// https://alliedmods.net/amxmodx-license
|
||||||
|
|
||||||
|
#include "IGameConfigs.h"
|
||||||
|
#include "natives_handles.h"
|
||||||
|
|
||||||
|
struct GameConfigNative
|
||||||
|
{
|
||||||
|
IGameConfig *m_config;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Handle<GameConfigNative> GameConfigHandle;
|
|
@ -27,6 +27,7 @@
|
||||||
#include "CvarManager.h"
|
#include "CvarManager.h"
|
||||||
#include "CLibrarySys.h"
|
#include "CLibrarySys.h"
|
||||||
#include "CFileSystem.h"
|
#include "CFileSystem.h"
|
||||||
|
#include "gameconfigs.h"
|
||||||
|
|
||||||
plugin_info_t Plugin_info =
|
plugin_info_t Plugin_info =
|
||||||
{
|
{
|
||||||
|
@ -408,6 +409,7 @@ int C_Spawn(edict_t *pent)
|
||||||
g_TrieSnapshotHandles.clear();
|
g_TrieSnapshotHandles.clear();
|
||||||
g_DataPackHandles.clear();
|
g_DataPackHandles.clear();
|
||||||
g_TextParsersHandles.clear();
|
g_TextParsersHandles.clear();
|
||||||
|
GameConfigHandle.clear();
|
||||||
|
|
||||||
char map_pluginsfile_path[256];
|
char map_pluginsfile_path[256];
|
||||||
char prefixed_map_pluginsfile[256];
|
char prefixed_map_pluginsfile[256];
|
||||||
|
|
|
@ -531,6 +531,7 @@ int set_amxnatives(AMX* amx, char error[128])
|
||||||
amx_Register(amx, g_StackNatives, -1);
|
amx_Register(amx, g_StackNatives, -1);
|
||||||
amx_Register(amx, g_TextParserNatives, -1);
|
amx_Register(amx, g_TextParserNatives, -1);
|
||||||
amx_Register(amx, g_CvarNatives, -1);
|
amx_Register(amx, g_CvarNatives, -1);
|
||||||
|
amx_Register(amx, g_GameConfigNatives, -1);
|
||||||
|
|
||||||
//we're not actually gonna check these here anymore
|
//we're not actually gonna check these here anymore
|
||||||
amx->flags |= AMX_FLAG_PRENIT;
|
amx->flags |= AMX_FLAG_PRENIT;
|
||||||
|
|
|
@ -278,6 +278,7 @@
|
||||||
<ClCompile Include="..\format.cpp">
|
<ClCompile Include="..\format.cpp">
|
||||||
<AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='JITRelease|Win32'">AssemblyAndSourceCode</AssemblerOutput>
|
<AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='JITRelease|Win32'">AssemblyAndSourceCode</AssemblerOutput>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\gameconfigs.cpp" />
|
||||||
<ClCompile Include="..\libraries.cpp" />
|
<ClCompile Include="..\libraries.cpp" />
|
||||||
<ClCompile Include="..\messages.cpp" />
|
<ClCompile Include="..\messages.cpp" />
|
||||||
<ClCompile Include="..\meta_api.cpp" />
|
<ClCompile Include="..\meta_api.cpp" />
|
||||||
|
@ -361,10 +362,12 @@
|
||||||
<ClInclude Include="..\debugger.h" />
|
<ClInclude Include="..\debugger.h" />
|
||||||
<ClInclude Include="..\fakemeta.h" />
|
<ClInclude Include="..\fakemeta.h" />
|
||||||
<ClInclude Include="..\format.h" />
|
<ClInclude Include="..\format.h" />
|
||||||
|
<ClInclude Include="..\gameconfigs.h" />
|
||||||
<ClInclude Include="..\libraries.h" />
|
<ClInclude Include="..\libraries.h" />
|
||||||
<ClInclude Include="..\messages.h" />
|
<ClInclude Include="..\messages.h" />
|
||||||
<ClInclude Include="..\modules.h" />
|
<ClInclude Include="..\modules.h" />
|
||||||
<ClInclude Include="..\natives.h" />
|
<ClInclude Include="..\natives.h" />
|
||||||
|
<ClInclude Include="..\natives_handles.h" />
|
||||||
<ClInclude Include="..\newmenus.h" />
|
<ClInclude Include="..\newmenus.h" />
|
||||||
<ClInclude Include="..\nongpl_matches.h" />
|
<ClInclude Include="..\nongpl_matches.h" />
|
||||||
<ClInclude Include="..\optimizer.h" />
|
<ClInclude Include="..\optimizer.h" />
|
||||||
|
@ -383,6 +386,7 @@
|
||||||
<None Include="..\..\plugins\include\cellstack.inc" />
|
<None Include="..\..\plugins\include\cellstack.inc" />
|
||||||
<None Include="..\..\plugins\include\cvars.inc" />
|
<None Include="..\..\plugins\include\cvars.inc" />
|
||||||
<None Include="..\..\plugins\include\datapack.inc" />
|
<None Include="..\..\plugins\include\datapack.inc" />
|
||||||
|
<None Include="..\..\plugins\include\gameconfig.inc" />
|
||||||
<None Include="..\..\plugins\include\textparse_ini.inc" />
|
<None Include="..\..\plugins\include\textparse_ini.inc" />
|
||||||
<None Include="..\..\plugins\include\textparse_smc.inc" />
|
<None Include="..\..\plugins\include\textparse_smc.inc" />
|
||||||
<None Include="..\amxdefn.asm" />
|
<None Include="..\amxdefn.asm" />
|
||||||
|
|
|
@ -288,6 +288,9 @@
|
||||||
<ClCompile Include="..\..\public\memtools\MemoryUtils.cpp">
|
<ClCompile Include="..\..\public\memtools\MemoryUtils.cpp">
|
||||||
<Filter>Memtools</Filter>
|
<Filter>Memtools</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\gameconfigs.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\amx.h">
|
<ClInclude Include="..\amx.h">
|
||||||
|
@ -497,6 +500,12 @@
|
||||||
<ClInclude Include="..\..\public\memtools\MemoryUtils.h">
|
<ClInclude Include="..\..\public\memtools\MemoryUtils.h">
|
||||||
<Filter>Memtools</Filter>
|
<Filter>Memtools</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\natives_handles.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\gameconfigs.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="..\version.rc">
|
<ResourceCompile Include="..\version.rc">
|
||||||
|
@ -594,6 +603,9 @@
|
||||||
<None Include="..\..\plugins\include\cvars.inc">
|
<None Include="..\..\plugins\include\cvars.inc">
|
||||||
<Filter>Pawn Includes</Filter>
|
<Filter>Pawn Includes</Filter>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="..\..\plugins\include\gameconfig.inc">
|
||||||
|
<Filter>Pawn Includes</Filter>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Object Include="..\Jit\helpers-x86.obj">
|
<Object Include="..\Jit\helpers-x86.obj">
|
||||||
|
|
88
amxmodx/natives_handles.h
Normal file
88
amxmodx/natives_handles.h
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
//
|
||||||
|
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||||
|
// Copyright (C) The AMX Mod X Development Team.
|
||||||
|
//
|
||||||
|
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||||
|
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||||
|
// https://alliedmods.net/amxmodx-license
|
||||||
|
|
||||||
|
#include <am-vector.h>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Handle
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
ke::Vector<T*> m_handles;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Handle() {}
|
||||||
|
~Handle()
|
||||||
|
{
|
||||||
|
this->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_handles.length(); ++i)
|
||||||
|
{
|
||||||
|
if (m_handles[i])
|
||||||
|
{
|
||||||
|
delete m_handles[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_handles.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
T *lookup(int handle)
|
||||||
|
{
|
||||||
|
--handle;
|
||||||
|
|
||||||
|
if (handle < 0 || handle >= static_cast<int>(m_handles.length()))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_handles[handle];
|
||||||
|
}
|
||||||
|
|
||||||
|
int create()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_handles.length(); ++i)
|
||||||
|
{
|
||||||
|
if (!m_handles[i])
|
||||||
|
{
|
||||||
|
m_handles[i] = new T;
|
||||||
|
|
||||||
|
return static_cast<int>(i) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_handles.append(new T);
|
||||||
|
|
||||||
|
return m_handles.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool destroy(int handle)
|
||||||
|
{
|
||||||
|
handle--;
|
||||||
|
|
||||||
|
if (handle < 0 || handle >= static_cast<int>(m_handles.length()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_handles[handle])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete m_handles[handle];
|
||||||
|
m_handles[handle] = nullptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
|
@ -30,6 +30,7 @@
|
||||||
#include <textparse_smc>
|
#include <textparse_smc>
|
||||||
#include <textparse_ini>
|
#include <textparse_ini>
|
||||||
#include <cvars>
|
#include <cvars>
|
||||||
|
#include <gameconfig>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called just after server activation.
|
* Called just after server activation.
|
||||||
|
|
93
plugins/include/gameconfig.inc
Normal file
93
plugins/include/gameconfig.inc
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
// vim: set ts=4 sw=4 tw=99 noet:
|
||||||
|
//
|
||||||
|
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
||||||
|
// Copyright (C) The AMX Mod X Development Team.
|
||||||
|
//
|
||||||
|
// This software is licensed under the GNU General Public License, version 3 or higher.
|
||||||
|
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||||
|
// https://alliedmods.net/amxmodx-license
|
||||||
|
|
||||||
|
//
|
||||||
|
// Game Config Functions
|
||||||
|
//
|
||||||
|
|
||||||
|
#if defined _gameconfigs_included
|
||||||
|
#endinput
|
||||||
|
#endif
|
||||||
|
#define _gameconfigs_included
|
||||||
|
|
||||||
|
enum GameConfig
|
||||||
|
{
|
||||||
|
Invalid_GameConfig = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a game config file.
|
||||||
|
*
|
||||||
|
* @note The file path must be relative to the 'gamedata' folder under the data folder
|
||||||
|
* and the extension should be omitted.
|
||||||
|
*
|
||||||
|
* @param file File to load
|
||||||
|
*
|
||||||
|
* @return A handle to the game config file
|
||||||
|
*/
|
||||||
|
native GameConfig:LoadGameConfigFile(const file[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an offset value.
|
||||||
|
*
|
||||||
|
* @param handle Game config handle
|
||||||
|
* @param key Key to retrieve from the offset section
|
||||||
|
*
|
||||||
|
* @return An offset, or -1 on failure
|
||||||
|
* @error Invalid game config handle
|
||||||
|
*/
|
||||||
|
native GameConfGetOffset(GameConfig:handle, const key[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an offset value given a classname.
|
||||||
|
*
|
||||||
|
* @param handle Game config handle
|
||||||
|
* @param classname Class name to match from the offset section
|
||||||
|
* @param key Key to retrieve from the offset section
|
||||||
|
*
|
||||||
|
* @return An offset, or -1 on failure
|
||||||
|
* @error Invalid game config handle
|
||||||
|
*/
|
||||||
|
native GameConfGetClassOffset(GameConfig:handle, const classname[], const key[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of a key from the "Keys" section.
|
||||||
|
*
|
||||||
|
* @param handle Game config handle
|
||||||
|
* @param key Key to retrieve from the Keys section
|
||||||
|
* @param buffer Destination string buffer
|
||||||
|
* @param maxlen Maximum length of output string buffer
|
||||||
|
*
|
||||||
|
* @return True if key existed, false otherwise
|
||||||
|
* @error Invalid game config handle
|
||||||
|
*/
|
||||||
|
native bool:GameConfGetKeyValue(GameConfig:handle, const key[], buffer[], maxlen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds an address calculation in a GameConfig file.
|
||||||
|
*
|
||||||
|
* @param handle Game config handle
|
||||||
|
* @param name Name of the property to find
|
||||||
|
*
|
||||||
|
* @return An address calculated on success, otherwise 0 on failure.
|
||||||
|
* @error Invalid game config handle
|
||||||
|
*/
|
||||||
|
native GameConfGetAddress(GameConfig:handle, const name[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys a game config and frees its memory.
|
||||||
|
*
|
||||||
|
* @note The function automatically sets the variable passed to it to 0 to aid
|
||||||
|
* in preventing accidental usage after destroy.
|
||||||
|
*
|
||||||
|
* @param handle Game config handle
|
||||||
|
*
|
||||||
|
* @return 1 on success, 0 if an invalid handle was passed in
|
||||||
|
*/
|
||||||
|
native CloseGameConfigFile(&GameConfig:handle);
|
|
@ -32,6 +32,8 @@
|
||||||
#ifndef _INCLUDE_SOURCEMOD_TEXTPARSERS_INTERFACE_H_
|
#ifndef _INCLUDE_SOURCEMOD_TEXTPARSERS_INTERFACE_H_
|
||||||
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_INTERFACE_H_
|
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_INTERFACE_H_
|
||||||
|
|
||||||
|
#include <string.h> // size_t
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file ITextParsers.h
|
* @file ITextParsers.h
|
||||||
* @brief Defines various text/file parsing functions, as well as UTF-8 support code.
|
* @brief Defines various text/file parsing functions, as well as UTF-8 support code.
|
||||||
|
|
|
@ -644,7 +644,7 @@ bool MemoryUtils::GetLibraryOfAddress(const void *libPtr, char *buffer, size_t m
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const char *dllpath = info.dli_fname;
|
const char *dllpath = info.dli_fname;
|
||||||
UTIL_Format(buffer, maxlength, "%s", dllpath);
|
Format(buffer, maxlength, "%s", dllpath);
|
||||||
if (base)
|
if (base)
|
||||||
{
|
{
|
||||||
*base = (uintptr_t)info.dli_fbase;
|
*base = (uintptr_t)info.dli_fbase;
|
||||||
|
@ -708,4 +708,20 @@ size_t MemoryUtils::DecodeHexString(unsigned char *buffer, size_t maxlength, con
|
||||||
}
|
}
|
||||||
|
|
||||||
return written;
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t MemoryUtils::Format(char *buffer, size_t maxlength, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
size_t len = vsnprintf(buffer, maxlength, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (len >= maxlength)
|
||||||
|
{
|
||||||
|
buffer[maxlength - 1] = '\0';
|
||||||
|
return (maxlength - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
}
|
}
|
|
@ -80,6 +80,7 @@ class MemoryUtils
|
||||||
|
|
||||||
public:
|
public:
|
||||||
size_t DecodeHexString(unsigned char *buffer, size_t maxlength, const char *hexstr);
|
size_t DecodeHexString(unsigned char *buffer, size_t maxlength, const char *hexstr);
|
||||||
|
size_t Format(char *buffer, size_t maxlength, const char *fmt, ...);
|
||||||
|
|
||||||
#if defined(__linux__) || defined(__APPLE__)
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -2377,7 +2377,7 @@ const char * MF_GetLocalInfo (const char *name, const char *def) { }
|
||||||
int MF_AmxReRegister (AMX *amx, AMX_NATIVE_INFO *list, int number) { return 0; }
|
int MF_AmxReRegister (AMX *amx, AMX_NATIVE_INFO *list, int number) { return 0; }
|
||||||
void * MF_RegisterFunctionEx (void *pfn, const char *description) { }
|
void * MF_RegisterFunctionEx (void *pfn, const char *description) { }
|
||||||
void * MF_MessageBlock (int mode, int msg, int *opt) { }
|
void * MF_MessageBlock (int mode, int msg, int *opt) { }
|
||||||
IGameConfigManager* MF_MessageBlock () { }
|
IGameConfigManager* MF_GetConfigManager (void) { }
|
||||||
#endif // MAY_NEVER_BE_DEFINED
|
#endif // MAY_NEVER_BE_DEFINED
|
||||||
|
|
||||||
#define MF_AddNatives g_fn_AddNatives
|
#define MF_AddNatives g_fn_AddNatives
|
||||||
|
|
|
@ -264,6 +264,7 @@ scripting_files = [
|
||||||
'include/file.inc',
|
'include/file.inc',
|
||||||
'include/float.inc',
|
'include/float.inc',
|
||||||
'include/fun.inc',
|
'include/fun.inc',
|
||||||
|
'include/gameconfig.inc',
|
||||||
'include/geoip.inc',
|
'include/geoip.inc',
|
||||||
'include/lang.inc',
|
'include/lang.inc',
|
||||||
'include/ns.inc',
|
'include/ns.inc',
|
||||||
|
|
Loading…
Reference in New Issue
Block a user