From e60f987fffb8232e4466380ca55fb2e9da36670b Mon Sep 17 00:00:00 2001 From: Diavolo Date: Mon, 20 Feb 2023 16:20:06 +0100 Subject: [PATCH] feat: listassetpool --- src/game/game.cpp | 4 ++++ src/game/game.hpp | 6 +++++ src/game/structs.hpp | 3 ++- src/module/fastfiles.cpp | 50 ++++++++++++++++++++++++++++++++++++++++ src/utils/string.cpp | 7 ++++++ src/utils/string.hpp | 2 ++ 6 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/game/game.cpp b/src/game/game.cpp index c0f823f..1701c3c 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -18,6 +18,8 @@ namespace game DB_LoadXAssets_t DB_LoadXAssets; DB_FindXAssetHeader_t DB_FindXAssetHeader; DB_IsXAssetDefault_t DB_IsXAssetDefault; + DB_EnumXAssets_t DB_EnumXAssets; + DB_GetXAssetName_t DB_GetXAssetName; Dvar_RegisterBool_t Dvar_RegisterBool; Dvar_RegisterFloat_t Dvar_RegisterFloat; @@ -741,6 +743,8 @@ namespace game native::DB_LoadXAssets = native::DB_LoadXAssets_t(SELECT_VALUE(0x48A8E0, 0x4CD020)); native::DB_FindXAssetHeader = native::DB_FindXAssetHeader_t(SELECT_VALUE(0x4FF000, 0x4CA620)); native::DB_IsXAssetDefault = native::DB_IsXAssetDefault_t(SELECT_VALUE(0x4868E0, 0x4CA800)); + native::DB_EnumXAssets = native::DB_EnumXAssets_t(SELECT_VALUE(0x50A0D0, 0x4CA2D0)); + native::DB_GetXAssetName = native::DB_GetXAssetName_t(SELECT_VALUE(0x438100, 0x4B7C10)); native::Dvar_RegisterBool = native::Dvar_RegisterBool_t(SELECT_VALUE(0x4914D0, 0x5BE9F0)); native::Dvar_RegisterFloat = native::Dvar_RegisterFloat_t(SELECT_VALUE(0x4F9CC0, 0x5BEA80)); diff --git a/src/game/game.hpp b/src/game/game.hpp index c9556e6..6b72a84 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -38,6 +38,12 @@ namespace game typedef int (*DB_IsXAssetDefault_t)(XAssetType type, const char* name); extern DB_IsXAssetDefault_t DB_IsXAssetDefault; + typedef void (*DB_EnumXAssets_t)(int type, void(*func)(XAssetHeader, void*), const void* inData, bool includeOverride); + extern DB_EnumXAssets_t DB_EnumXAssets; + + typedef const char* (*DB_GetXAssetName_t)(const XAsset* asset); + extern DB_GetXAssetName_t DB_GetXAssetName; + typedef const dvar_t* (*Dvar_RegisterBool_t)(const char* dvarName, bool value, unsigned __int16 flags, const char* description); extern Dvar_RegisterBool_t Dvar_RegisterBool; diff --git a/src/game/structs.hpp b/src/game/structs.hpp index 1a350d7..fdeced7 100644 --- a/src/game/structs.hpp +++ b/src/game/structs.hpp @@ -377,6 +377,7 @@ namespace game enum XAssetType { ASSET_TYPE_SCRIPTFILE = 0x27, + ASSET_TYPE_COUNT = 0x2E, }; struct ScriptFile @@ -406,7 +407,7 @@ namespace game struct XAsset { - XAssetType type; + int type; XAssetHeader header; }; diff --git a/src/module/fastfiles.cpp b/src/module/fastfiles.cpp index 8639399..1a85a75 100644 --- a/src/module/fastfiles.cpp +++ b/src/module/fastfiles.cpp @@ -2,10 +2,12 @@ #include #include "game/game.hpp" +#include "command.hpp" #include "console.hpp" #include #include +#include namespace { @@ -76,6 +78,15 @@ namespace } } +void enum_assets(const int type, const std::function& callback, const bool include_override) +{ + game::native::DB_EnumXAssets(type, static_cast([](game::native::XAssetHeader header, void* data) + { + const auto& cb = *static_cast*>(data); + cb(header); + }), &callback, include_override); +} + class fastfiles final : public module { public: @@ -86,6 +97,45 @@ public: db_find_x_asset_header_hook.create(game::native::DB_FindXAssetHeader, &db_find_x_asset_header_stub); g_dump_scripts = game::native::Dvar_RegisterBool("g_dumpScripts", false, game::native::DVAR_NONE, "Dump GSC scripts to binary format"); + + command::add("listassetpool", [](const command::params& params) + { + if (params.size() < 2) + { + console::info("listassetpool [filter]: list all the assets in the specified pool\n"); + + for (auto i = 0; i < game::native::ASSET_TYPE_COUNT; ++i) + { + console::info("%d %s\n", i, game::native::g_assetNames[i]); + } + } + else + { + const auto type = std::strtol(params.get(1), nullptr, 0); + + if (type < 0 || type >= game::native::ASSET_TYPE_COUNT) + { + console::error("Invalid pool passed must be between [%d, %d]\n", 0, game::native::ASSET_TYPE_COUNT - 1); + return; + } + + console::info("Listing assets in pool %s\n", game::native::g_assetNames[type]); + + const std::string filter = params.get(2); + enum_assets(type, [type, filter](game::native::XAssetHeader header) + { + const auto asset = game::native::XAsset{ type, header }; + const auto* const asset_name = game::native::DB_GetXAssetName(&asset); + + if (!filter.empty() && !utils::string::match_compare(filter, asset_name, false)) + { + return; + } + + console::info("%s\n", asset_name); + }, true); + } + }); } private: diff --git a/src/utils/string.cpp b/src/utils/string.cpp index 50abd4f..db26a23 100644 --- a/src/utils/string.cpp +++ b/src/utils/string.cpp @@ -36,6 +36,13 @@ namespace utils::string return text; } + bool match_compare(const std::string& input, const std::string& text, const bool exact) + { + if (exact && text == input) return true; + if (!exact && text.find(input) != std::string::npos) return true; + return false; + } + std::wstring convert(const std::string& str) { std::wstring result; diff --git a/src/utils/string.hpp b/src/utils/string.hpp index 5874629..25bad5c 100644 --- a/src/utils/string.hpp +++ b/src/utils/string.hpp @@ -77,6 +77,8 @@ namespace utils::string std::string to_lower(std::string text); std::string to_upper(std::string text); + bool match_compare(const std::string& input, const std::string& text, bool exact); + std::wstring convert(const std::string& str); std::string dump_hex(const std::string& data, const std::string& separator = " ");