diff --git a/core/msvc8/sourcemod_mm.vcproj b/core/msvc8/sourcemod_mm.vcproj index dc0f2b06..d945d2af 100644 --- a/core/msvc8/sourcemod_mm.vcproj +++ b/core/msvc8/sourcemod_mm.vcproj @@ -761,6 +761,10 @@ RelativePath="..\smn_functions.cpp" > </File> + <File + RelativePath="..\smn_gameconfigs.cpp" + > + </File> <File RelativePath="..\smn_halflife.cpp" > diff --git a/core/smn_gameconfigs.cpp b/core/smn_gameconfigs.cpp new file mode 100644 index 00000000..5102d9d6 --- /dev/null +++ b/core/smn_gameconfigs.cpp @@ -0,0 +1,122 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. + * =============================================================== + * + * This file is not open source and may not be copied without explicit + * written permission of AlliedModders LLC. This file may not be redistributed + * in whole or significant part. + * For information, see LICENSE.txt or http://www.sourcemod.net/license.php + * + * Version: $Id$ + */ + +#include "sourcemod.h" +#include "HandleSys.h" +#include "GameConfigs.h" + +HandleType_t g_GameConfigsType; + +class GameConfigsNatives : + public IHandleTypeDispatch, + public SourceModBase +{ +public: + void OnSourceModAllInitialized() + { + g_GameConfigsType = g_HandleSys.CreateType("GameConfigs", this, 0, NULL, NULL, g_pCoreIdent, NULL); + } + void OnSourceModShutdown() + { + g_HandleSys.RemoveType(g_GameConfigsType, g_pCoreIdent); + g_GameConfigsType = 0; + } + void OnHandleDestroy(HandleType_t type, void *object) + { + g_GameConfigs.CloseGameConfigFile(reinterpret_cast<IGameConfig *>(object)); + } +}; + +static cell_t smn_LoadGameConfigFile(IPluginContext *pCtx, const cell_t *params) +{ + IGameConfig *gc; + char *filename; + char error[128]; + + pCtx->LocalToString(params[1], &filename); + if (!g_GameConfigs.LoadGameConfigFile(filename, &gc, error, sizeof(error))) + { + return pCtx->ThrowNativeError("Unable to open %s: %s", filename, error); + } + + return g_HandleSys.CreateHandle(g_GameConfigsType, gc, pCtx->GetIdentity(), g_pCoreIdent, NULL); +} + +static cell_t smn_GameConfGetOffset(IPluginContext *pCtx, const cell_t *params) +{ + Handle_t hndl = static_cast<Handle_t>(params[1]); + HandleError herr; + HandleSecurity sec; + IGameConfig *gc; + + sec.pOwner = NULL; + sec.pIdentity = g_pCoreIdent; + + if ((herr=g_HandleSys.ReadHandle(hndl, g_GameConfigsType, &sec, (void **)&gc)) + != HandleError_None) + { + return pCtx->ThrowNativeError("Invalid game config handle %x (error %d)", hndl, herr); + } + + char *key; + int val; + pCtx->LocalToString(params[2], &key); + + if (!gc->GetOffset(key, &val)) + { + return -1; + } + + return val; +} + +static cell_t smn_GameConfGetKeyValue(IPluginContext *pCtx, const cell_t *params) +{ + Handle_t hndl = static_cast<Handle_t>(params[1]); + HandleError herr; + HandleSecurity sec; + IGameConfig *gc; + + sec.pOwner = NULL; + sec.pIdentity = g_pCoreIdent; + + if ((herr=g_HandleSys.ReadHandle(hndl, g_GameConfigsType, &sec, (void **)&gc)) + != HandleError_None) + { + return pCtx->ThrowNativeError("Invalid game config handle %x (error %d)", hndl, herr); + } + + char *key; + const char *val; + pCtx->LocalToString(params[2], &key); + + if ((val=gc->GetKeyValue(key)) == NULL) + { + return 0; + } + + pCtx->StringToLocalUTF8(params[3], params[4], val, NULL); + + return 1; +} + +static GameConfigsNatives s_GameConfigsNatives; + +REGISTER_NATIVES(gameconfignatives) +{ + {"LoadGameConfigFile", smn_LoadGameConfigFile}, + {"GameConfGetOffset", smn_GameConfGetOffset}, + {"GameConfGetKeyValue", smn_GameConfGetKeyValue}, + {NULL, NULL} +}; \ No newline at end of file diff --git a/core/smn_keyvalues.cpp b/core/smn_keyvalues.cpp index d0aae516..82d3d657 100644 --- a/core/smn_keyvalues.cpp +++ b/core/smn_keyvalues.cpp @@ -26,7 +26,7 @@ struct KeyValueStack CStack<KeyValues *> pCurRoot; }; -class KeyValuekNatives : +class KeyValueNatives : public SMGlobalClass, public IHandleTypeDispatch { @@ -636,7 +636,7 @@ static cell_t smn_KvSetEscapeSequences(IPluginContext *pCtx, const cell_t *param return 1; } -static KeyValuekNatives s_KeyValuekNatives; +static KeyValueNatives s_KeyValueNatives; REGISTER_NATIVES(keyvaluenatives) { diff --git a/plugins/include/sourcemod.inc b/plugins/include/sourcemod.inc index e1949353..425bb70a 100644 --- a/plugins/include/sourcemod.inc +++ b/plugins/include/sourcemod.inc @@ -406,5 +406,34 @@ native bool:IsSoundPrecached(const String:sound[]); */ native CreateDialog(client, Handle:kv, DialogType:type); +/** + * Loads a game config file. + * + * @param file File to load. The path must be relative to the 'gamedata' folder under the config folder + * and the extension should be omitted. + * @return A handle to the game config file or INVALID_HANDLE in failure. + */ +native Handle:LoadGameConfigFile(const String:file[]); + +/** + * Returns an offset value. + * + * @param gc Game config handle. + * @param key Key to retrieve from the offset section. + * @return An offset, or -1 on failure. + */ +native GameConfGetOffset(Handle:gc, const String:key[]); + +/** + * Gets the value of a key from the "Keys" section. + * + * @param gc 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. + */ +native bool:GameConfGetKeyValue(Handle:gc, const String:key[], String:buffer[], maxlen); + #include <helpers> #include <entity> diff --git a/public/IGameConfigs.h b/public/IGameConfigs.h index a98b7930..d9fb3cdf 100644 --- a/public/IGameConfigs.h +++ b/public/IGameConfigs.h @@ -33,28 +33,6 @@ class SendProp; namespace SourceMod { - /** - * @brief Details the property types. - */ - enum PropType - { - PropType_Unknown = 0, /**< Property type is not known */ - PropType_Send = 1, /**< Property type is a networkable property */ - PropType_Data = 2, /**< Property type is a data/save property */ - }; - - /** - * @brief Details the property states. - */ - enum PropError - { - PropError_Okay = 0, /**< No error */ - PropError_NotSet, /**< Property is not set in the config file */ - PropError_NotFound, /**< Property was not found in the game */ - }; - - #define INVALID_PROPERTY_VALUE -1 /**< Property value is not valid */ - /** * @brief Describes a game private data config file */ @@ -74,7 +52,7 @@ namespace SourceMod * @brief Returns information about a dynamic offset. * * @param key Key to retrieve from the property section. - * @return A PropError error code. + * @return A SendProp pointer, or NULL if not found. */ virtual SendProp *GetSendProp(const char *key) =0; @@ -106,7 +84,7 @@ namespace SourceMod * @brief Loads or finds an already loaded game config file. * * @param file File to load. The path must be relative to the 'gamedata' - * folder under the config folder, and the extension should be ommitted. + * folder under the config folder, and the extension should be omitted. * @param pConfig Pointer to store the game config pointer. Pointer will be valid even on failure. * @param error Optional error message buffer. * @param maxlength Maximum length of the error buffer.