diff --git a/core/msvc8/sourcemod_mm.vcproj b/core/msvc8/sourcemod_mm.vcproj index 03076cea..e39ce9ba 100644 --- a/core/msvc8/sourcemod_mm.vcproj +++ b/core/msvc8/sourcemod_mm.vcproj @@ -1,7 +1,7 @@ (params[1]); + Handle_t hndl_parent = static_cast(params[2]); + HandleError herr; + HandleSecurity sec; + KeyValueStack *pStk_copied, *pStk_parent; + + sec.pOwner = NULL; + sec.pIdentity = g_pCoreIdent; + + if ((herr=g_HandleSys.ReadHandle(hndl_copied, g_KeyValueType, &sec, (void **)&pStk_copied)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl_copied, herr); + } + if ((herr=g_HandleSys.ReadHandle(hndl_parent, g_KeyValueType, &sec, (void **)&pStk_parent)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl_parent, herr); + } + + pStk_copied->pCurRoot.front()->CopySubkeys(pStk_parent->pCurRoot.front()); + + return 1; +} + +static cell_t smn_GetNameSymbol(IPluginContext *pContext, const cell_t *params) +{ + Handle_t hndl = static_cast(params[1]); + HandleError herr; + HandleSecurity sec; + KeyValueStack *pStk; + cell_t *val; + char *key; + + sec.pOwner = NULL; + sec.pIdentity = g_pCoreIdent; + + if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr); + } + + if (pStk->pCurRoot.size() < 2) + { + return 0; + } + + pContext->LocalToString(params[2], &key); + + KeyValues *pKv = pStk->pCurRoot.front()->FindKey(key); + if (!pKv) + { + return 0; + } + pContext->LocalToPhysAddr(params[3], &val); + *val = pKv->GetNameSymbol(); + + return 1; +} + +static cell_t smn_FindKeyById(IPluginContext *pContext, const cell_t *params) +{ + Handle_t hndl = static_cast(params[1]); + HandleError herr; + HandleSecurity sec; + KeyValueStack *pStk; + + sec.pOwner = NULL; + sec.pIdentity = g_pCoreIdent; + + if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr); + } + + KeyValues *pKv = pStk->pCurRoot.front()->FindKey(params[2]); + if (!pKv) + { + return 0; + } + + pContext->StringToLocalUTF8(params[3], params[4], pKv->GetName(), NULL); + + return 1; +} + static KeyValueNatives s_KeyValueNatives; REGISTER_NATIVES(keyvaluenatives) @@ -863,5 +953,8 @@ REGISTER_NATIVES(keyvaluenatives) {"KvDeleteKey", smn_KvDeleteKey}, {"KvNodesInStack", smn_KvNodesInStack}, {"KvSavePosition", smn_KvSavePosition}, + {"KvCopySubkeys", smn_CopySubkeys}, + {"KvFindKeyById", smn_FindKeyById}, + {"KvGetNameSymbol", smn_GetNameSymbol}, {NULL, NULL} }; diff --git a/plugins/include/keyvalues.inc b/plugins/include/keyvalues.inc index 5e9bce3c..715ddc44 100644 --- a/plugins/include/keyvalues.inc +++ b/plugins/include/keyvalues.inc @@ -350,3 +350,38 @@ native KvSetEscapeSequences(Handle:kv, bool:useEscapes); * @error Invalid Handle. */ native KvNodesInStack(Handle:kv); + +/** + * Makes a new copy of all subkeys in the origin KeyValues to + * the destination KeyValues. + * NOTE: All KeyValues are processed from the current location not the root one. + * + * @param origin Origin KeyValues Handle. + * @param dest Destination KeyValues Handlee. + * @noreturn + * @error Invalid Handle. + */ +native KvCopySubkeys(Handle:origin, Handle:dest); + +/** + * Finds a KeyValues name by id. + * + * @param kv KeyValues Handle. + * @param id KeyValues id. + * @param name Buffer to store the name. + * @param maxlength Maximum length of the value buffer. + * @return True on success, false if id not found. + * @error Invalid Handle. + */ +native bool:KvFindKeyById(Handle:kv, id, String:name[], maxlength); + +/** + * Finds a KeyValues id inside a KeyValues tree. + * + * @param kv KeyValues Handle. + * @param key Key name. + * @param id Id of the found KeyValue. + * @return True on success, false if key not found. + * @error Invalid Handle. + */ +native bool:KvGetNameSymbol(Handle:kv, const String:key[], &id);