diff --git a/Client/mods/deathmatch/logic/CDownloadableResource.cpp b/Client/mods/deathmatch/logic/CDownloadableResource.cpp index 23098b790bf..80ff7e55dd3 100644 --- a/Client/mods/deathmatch/logic/CDownloadableResource.cpp +++ b/Client/mods/deathmatch/logic/CDownloadableResource.cpp @@ -14,6 +14,21 @@ CDownloadableResource::CDownloadableResource(CResource* pResource, eResourceType resourceType, const char* szName, const char* szNameShort, uint uiDownloadSize, CChecksum serverChecksum, bool bAutoDownload) { + switch (resourceType) + { + case eResourceType::RESOURCE_FILE_TYPE_SCRIPT: + case eResourceType::RESOURCE_FILE_TYPE_CLIENT_SCRIPT: + m_resourceCategoryType = eResourceCategory::SCRIPTS; + case eResourceType::RESOURCE_FILE_TYPE_MAP: + m_resourceCategoryType = eResourceCategory::MAPS; + case eResourceType::RESOURCE_FILE_TYPE_CONFIG: + case eResourceType::RESOURCE_FILE_TYPE_CLIENT_CONFIG: + m_resourceCategoryType = eResourceCategory::CONFIGS; + case eResourceType::RESOURCE_FILE_TYPE_CLIENT_FILE: + case eResourceType::RESOURCE_FILE_TYPE_HTML: + m_resourceCategoryType = eResourceCategory::FILES; + } + m_pResource = pResource; m_resourceType = resourceType; m_strName = szName; diff --git a/Client/mods/deathmatch/logic/CDownloadableResource.h b/Client/mods/deathmatch/logic/CDownloadableResource.h index 5a1a9d41054..2ed0c2f104f 100644 --- a/Client/mods/deathmatch/logic/CDownloadableResource.h +++ b/Client/mods/deathmatch/logic/CDownloadableResource.h @@ -35,6 +35,15 @@ class CDownloadableResource RESOURCE_FILE_TYPE_CLIENT_FILE, }; + enum class eResourceCategory + { + ALL, + SCRIPTS, + MAPS, + CONFIGS, + FILES, + }; + public: CDownloadableResource(CResource* pResource, eResourceType resourceType, const char* szName, const char* szNameShort, uint uiDownloadSize, CChecksum serverChecksum, bool bAutoDownload); @@ -43,6 +52,7 @@ class CDownloadableResource bool DoesClientAndServerChecksumMatch(); eResourceType GetResourceType() { return m_resourceType; }; + eResourceCategory GetResourceCategoryType() const noexcept { return m_resourceCategoryType; } const char* GetName() { return m_strName; }; const char* GetShortName() { return m_strNameShort; }; CResource* GetResource() { return m_pResource; } @@ -66,6 +76,7 @@ class CDownloadableResource protected: CResource* m_pResource; eResourceType m_resourceType; + eResourceCategory m_resourceCategoryType; SString m_strName; SString m_strNameShort; diff --git a/Client/mods/deathmatch/logic/CResource.h b/Client/mods/deathmatch/logic/CResource.h index 8100d3fc79e..807936c70e7 100644 --- a/Client/mods/deathmatch/logic/CResource.h +++ b/Client/mods/deathmatch/logic/CResource.h @@ -90,6 +90,8 @@ class CResource const auto& GetExportedFunctions() const noexcept { return m_exportedFunctions; } + std::list& GetResourceFiles() noexcept { return m_ResourceFiles; } + const std::list& GetResourceFiles() const noexcept { return m_ResourceFiles; } std::list::iterator IterBeginResourceFiles() { return m_ResourceFiles.begin(); } std::list::iterator IterEndResourceFiles() { return m_ResourceFiles.end(); } diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp index 64708dea0ca..478a22e1521 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp @@ -896,6 +896,14 @@ ADD_ENUM(WEATHER_SANDSTORM, "Sandstorm") ADD_ENUM(WEATHER_RAINBOW, "Rainbow") IMPLEMENT_ENUM_END("world-property") +IMPLEMENT_ENUM_CLASS_BEGIN(CResourceFile::eResourceCategory) +ADD_ENUM(CResourceFile::eResourceCategory::ALL, "all") +ADD_ENUM(CResourceFile::eResourceCategory::CONFIGS, "config") +ADD_ENUM(CResourceFile::eResourceCategory::FILES, "file") +ADD_ENUM(CResourceFile::eResourceCategory::MAPS, "map") +ADD_ENUM(CResourceFile::eResourceCategory::SCRIPTS, "script") +IMPLEMENT_ENUM_CLASS_END("resource-category-type") + IMPLEMENT_ENUM_CLASS_BEGIN(eModelLoadState) ADD_ENUM(eModelLoadState::LOADSTATE_NOT_LOADED, "unloaded") ADD_ENUM(eModelLoadState::LOADSTATE_LOADED, "loaded") diff --git a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h index e134a73bea9..721480e511b 100644 --- a/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h +++ b/Client/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h @@ -15,6 +15,7 @@ #include #include #include +#include "CResourceFile.h" enum eLuaType { @@ -86,6 +87,7 @@ DECLARE_ENUM_CLASS(eRenderStage); DECLARE_ENUM_CLASS(eFxParticleSystems); DECLARE_ENUM(ePools); DECLARE_ENUM(eWorldProperty); +DECLARE_ENUM_CLASS(CResourceFile::eResourceCategory); DECLARE_ENUM_CLASS(eModelLoadState); DECLARE_ENUM_CLASS(PreloadAreaOption); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp index e2a072307c5..7e220685e17 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp @@ -16,7 +16,8 @@ using std::list; void CLuaResourceDefs::LoadFunctions() { - constexpr static const std::pair functions[]{ + constexpr static const std::pair functions[] + { {"call", Call}, {"getThisResource", GetThisResource}, {"getResourceConfig", GetResourceConfig}, @@ -29,6 +30,7 @@ void CLuaResourceDefs::LoadFunctions() {"getResourceState", GetResourceState}, {"loadstring", LoadString}, {"load", Load}, + {"getResourceFiles", ArgumentParser}, }; // Add functions @@ -52,6 +54,7 @@ void CLuaResourceDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getDynamicElementRoot", "getResourceDynamicElementRoot"); lua_classfunction(luaVM, "getExportedFunctions", "getResourceExportedFunctions"); lua_classfunction(luaVM, "getState", "getResourceState"); + lua_classfunction(luaVM, "getFiles", "getResourceFiles"); lua_classvariable(luaVM, "config", NULL, "getResourceConfig"); lua_classvariable(luaVM, "dynamicElementRoot", NULL, "getResourceDynamicElementRoot"); @@ -60,6 +63,7 @@ void CLuaResourceDefs::AddClass(lua_State* luaVM) lua_classvariable(luaVM, "state", NULL, "getResourceState"); lua_classvariable(luaVM, "name", NULL, "getResourceName"); lua_classvariable(luaVM, "rootElement", NULL, "getResourceRootElement"); + lua_classvariable(luaVM, "files", nullptr, "getResourceFiles"); lua_registerclass(luaVM, "Resource"); } @@ -545,3 +549,32 @@ int CLuaResourceDefs::Load(lua_State* luaVM) lua_pushboolean(luaVM, false); return 1; } + +std::vector CLuaResourceDefs::GetResourceFiles(lua_State* luaVM, std::optional type, + std::optional resource) noexcept +{ + using eResourceCategory = CResourceFile::eResourceCategory; + + if (!type) + type = eResourceCategory::ALL; + + if (!resource) + resource = &lua_getownerresource(luaVM); + + const auto resourceFiles = (*resource)->GetResourceFiles(); + + std::unordered_set files; + for (const auto& file : resourceFiles) + { + if (file->GetResourceCategoryType() != type.value() && type.value() != eResourceCategory::ALL) + continue; + files.insert(file->GetName()); + } + + // TODO: Upgrade ArgumentParser so it would accept + // std::set and std::unordered_set as return values + return std::vector( + std::make_move_iterator(files.begin()), + std::make_move_iterator(files.end()) + ); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h index eba15fa6c78..a68707fbcc5 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h @@ -31,4 +31,6 @@ class CLuaResourceDefs : public CLuaDefs LUA_DECLARE(Load); static std::string GetResourceName(lua_State* luaVM, std::optional resourceElement); + static std::vector GetResourceFiles(lua_State* luaVM, std::optional type, + std::optional resource) noexcept; }; diff --git a/Server/mods/deathmatch/logic/CResource.h b/Server/mods/deathmatch/logic/CResource.h index 1a622be3cf6..56a16b7239c 100644 --- a/Server/mods/deathmatch/logic/CResource.h +++ b/Server/mods/deathmatch/logic/CResource.h @@ -256,8 +256,8 @@ class CResource : public EHS const std::string& GetResourceDirectoryPath() const { return m_strResourceDirectoryPath; } const std::string& GetResourceCacheDirectoryPath() const { return m_strResourceCachePath; } - std::list& GetFiles() { return m_ResourceFiles; } - size_t GetFileCount() const noexcept { return m_ResourceFiles.size(); } + std::list& GetResourceFiles() noexcept { return m_ResourceFiles; } + const std::list& GetResourceFiles() const noexcept { return m_ResourceFiles; } time_t GetTimeStarted() const noexcept { return m_timeStarted; } time_t GetTimeLoaded() const noexcept { return m_timeLoaded; } diff --git a/Server/mods/deathmatch/logic/CResourceClientConfigItem.cpp b/Server/mods/deathmatch/logic/CResourceClientConfigItem.cpp index 6f31d314987..8d0dd79ab27 100644 --- a/Server/mods/deathmatch/logic/CResourceClientConfigItem.cpp +++ b/Server/mods/deathmatch/logic/CResourceClientConfigItem.cpp @@ -28,6 +28,8 @@ CResourceClientConfigItem::CResourceClientConfigItem(CResource* resource, const m_pXMLRootNode = NULL; m_bInvalid = false; m_type = RESOURCE_FILE_TYPE_CLIENT_CONFIG; + m_resourceCategoryType = eResourceCategory::CONFIGS; + } CResourceClientConfigItem::~CResourceClientConfigItem() diff --git a/Server/mods/deathmatch/logic/CResourceClientFileItem.cpp b/Server/mods/deathmatch/logic/CResourceClientFileItem.cpp index a86341248e3..6dfab9087d8 100644 --- a/Server/mods/deathmatch/logic/CResourceClientFileItem.cpp +++ b/Server/mods/deathmatch/logic/CResourceClientFileItem.cpp @@ -22,6 +22,7 @@ CResourceClientFileItem::CResourceClientFileItem(CResource* resource, const char : CResourceFile(resource, szShortName, szResourceFileName, xmlAttributes) { m_type = RESOURCE_FILE_TYPE_CLIENT_FILE; + m_resourceCategoryType = eResourceCategory::FILES; m_bClientAutoDownload = bClientAutoDownload; } diff --git a/Server/mods/deathmatch/logic/CResourceClientScriptItem.cpp b/Server/mods/deathmatch/logic/CResourceClientScriptItem.cpp index 714db9538c9..cf67764c4c0 100644 --- a/Server/mods/deathmatch/logic/CResourceClientScriptItem.cpp +++ b/Server/mods/deathmatch/logic/CResourceClientScriptItem.cpp @@ -25,6 +25,7 @@ CResourceClientScriptItem::CResourceClientScriptItem(CResource* resource, const : CResourceFile(resource, szShortName, szResourceFileName, xmlAttributes) { m_type = RESOURCE_FILE_TYPE_CLIENT_SCRIPT; + m_resourceCategoryType = eResourceCategory::SCRIPTS; // Check if this file should be cached by the client if (MapGet(m_attributeMap, "protected") == "true" || MapGet(m_attributeMap, "cache") == "false") diff --git a/Server/mods/deathmatch/logic/CResourceConfigItem.cpp b/Server/mods/deathmatch/logic/CResourceConfigItem.cpp index db96d28f569..bb21f705f51 100644 --- a/Server/mods/deathmatch/logic/CResourceConfigItem.cpp +++ b/Server/mods/deathmatch/logic/CResourceConfigItem.cpp @@ -30,6 +30,7 @@ CResourceConfigItem::CResourceConfigItem(CResource* resource, const char* szShor m_bInvalid = true; m_type = RESOURCE_FILE_TYPE_CONFIG; + m_resourceCategoryType = eResourceCategory::CONFIGS; } CResourceConfigItem::~CResourceConfigItem() diff --git a/Server/mods/deathmatch/logic/CResourceFile.h b/Server/mods/deathmatch/logic/CResourceFile.h index b61f332f36d..64c97aa6bc7 100644 --- a/Server/mods/deathmatch/logic/CResourceFile.h +++ b/Server/mods/deathmatch/logic/CResourceFile.h @@ -37,12 +37,22 @@ class CResourceFile RESOURCE_FILE_TYPE_NONE, }; // TODO: sort all client-side enums and use >= (instead of each individual type) on comparisons that use this enum? + enum class eResourceCategory + { + ALL, + SCRIPTS, + MAPS, + CONFIGS, + FILES, + }; + protected: class CResource* m_resource; std::string m_strResourceFileName; // full path std::string m_strShortName; // just the filename std::string m_strWindowsName; // the name with backwards slashes eResourceType m_type; + eResourceCategory m_resourceCategoryType; class CLuaMain* m_pVM; CChecksum m_checksum; // Checksum last time this was loaded, generated by GenerateChecksum() uint m_uiFileSize; @@ -59,6 +69,7 @@ class CResourceFile virtual bool IsNoClientCache() const { return false; } eResourceType GetType() { return m_type; } + eResourceCategory GetResourceCategoryType() const noexcept { return m_resourceCategoryType; } const char* GetName() { return m_strShortName.c_str(); } const char* GetFullName() { return m_strResourceFileName.c_str(); } const char* GetWindowsName() { return m_strWindowsName.c_str(); } diff --git a/Server/mods/deathmatch/logic/CResourceHTMLItem.cpp b/Server/mods/deathmatch/logic/CResourceHTMLItem.cpp index 978f2f4a3a6..c353a84bdba 100644 --- a/Server/mods/deathmatch/logic/CResourceHTMLItem.cpp +++ b/Server/mods/deathmatch/logic/CResourceHTMLItem.cpp @@ -29,6 +29,7 @@ CResourceHTMLItem::CResourceHTMLItem(CResource* resource, const char* szShortNam { m_bIsRaw = bIsRaw; m_type = RESOURCE_FILE_TYPE_HTML; + m_resourceCategoryType = eResourceCategory::FILES; m_bDefault = bIsDefault; m_pVM = NULL; m_bIsBeingRequested = false; diff --git a/Server/mods/deathmatch/logic/CResourceManager.cpp b/Server/mods/deathmatch/logic/CResourceManager.cpp index b3b2d2f9c10..f5ee11e4d05 100644 --- a/Server/mods/deathmatch/logic/CResourceManager.cpp +++ b/Server/mods/deathmatch/logic/CResourceManager.cpp @@ -338,7 +338,7 @@ void CResourceManager::ListResourcesLoaded(const SString& strListType) else { if (strListType == "stopped" || strListType == "all") - CLogger::LogPrintf("%-20.20s STOPPED (%d files)\n", res->GetName().c_str(), res->GetFileCount()); + CLogger::LogPrintf("%-20.20s STOPPED (%d files)\n", res->GetName().c_str(), res->GetResourceFiles().size()); } uiCount++; } diff --git a/Server/mods/deathmatch/logic/CResourceMapItem.cpp b/Server/mods/deathmatch/logic/CResourceMapItem.cpp index 653d192ac2e..9563c6cc141 100644 --- a/Server/mods/deathmatch/logic/CResourceMapItem.cpp +++ b/Server/mods/deathmatch/logic/CResourceMapItem.cpp @@ -45,6 +45,7 @@ CResourceMapItem::CResourceMapItem(CResource* pResource, const char* szShortName m_pElementGroup = nullptr; m_iDimension = iDimension; m_type = RESOURCE_FILE_TYPE_MAP; + m_resourceCategoryType = eResourceCategory::MAPS; m_pMapElement = nullptr; } diff --git a/Server/mods/deathmatch/logic/CResourceScriptItem.cpp b/Server/mods/deathmatch/logic/CResourceScriptItem.cpp index c1f183c8599..cbe5193698b 100644 --- a/Server/mods/deathmatch/logic/CResourceScriptItem.cpp +++ b/Server/mods/deathmatch/logic/CResourceScriptItem.cpp @@ -23,6 +23,7 @@ CResourceScriptItem::CResourceScriptItem(CResource* resource, const char* szShor : CResourceFile(resource, szShortName, szResourceFileName, xmlAttributes) { m_type = RESOURCE_FILE_TYPE_SCRIPT; + m_resourceCategoryType = eResourceCategory::SCRIPTS; } CResourceScriptItem::~CResourceScriptItem() diff --git a/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp b/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp index ef25750c053..31cf77baacb 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp +++ b/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp @@ -285,6 +285,14 @@ ADD_ENUM(ESyncType::LOCAL, "local") ADD_ENUM(ESyncType::SUBSCRIBE, "subscribe") IMPLEMENT_ENUM_CLASS_END("sync-mode") +IMPLEMENT_ENUM_CLASS_BEGIN(CResourceFile::eResourceCategory) +ADD_ENUM(CResourceFile::eResourceCategory::ALL, "all") +ADD_ENUM(CResourceFile::eResourceCategory::CONFIGS, "config") +ADD_ENUM(CResourceFile::eResourceCategory::FILES, "file") +ADD_ENUM(CResourceFile::eResourceCategory::MAPS, "map") +ADD_ENUM(CResourceFile::eResourceCategory::SCRIPTS, "script") +IMPLEMENT_ENUM_CLASS_END("resource-category-type") + // // CResource from userdata // diff --git a/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h b/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h index 52a4536012e..8b2e100c849 100644 --- a/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h +++ b/Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.h @@ -8,13 +8,14 @@ #pragma once +#include #include "LuaCommon.h" #include "CElementIDs.h" #include "CConsoleClient.h" #include "CAccount.h" #include "CEasingCurve.h" #include "CAccessControlListRight.h" -#include +#include "CResourceFile.h" class CLuaVector2D; class CLuaVector3D; @@ -38,6 +39,7 @@ DECLARE_ENUM(CAccessControlListRight::ERightType); DECLARE_ENUM(CElement::EElementType); DECLARE_ENUM(CAccountPassword::EAccountPasswordType); DECLARE_ENUM_CLASS(ESyncType); +DECLARE_ENUM_CLASS(CResourceFile::eResourceCategory); enum eHudComponent { diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp index 81d66a3280a..b0666320e7f 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.cpp @@ -73,6 +73,8 @@ void CLuaResourceDefs::LoadFunctions() {"getResourceACLRequests", getResourceACLRequests}, {"loadstring", LoadString}, {"load", Load}, + + {"getResourceFiles", ArgumentParser}, }; // Add functions @@ -129,6 +131,7 @@ void CLuaResourceDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getACLRequests", "getResourceACLRequests"); lua_classfunction(luaVM, "isArchived", "isResourceArchived"); lua_classfunction(luaVM, "isProtected", "isResourceProtected"); + lua_classfunction(luaVM, "getFiles", "getResourceFiles"); lua_classvariable(luaVM, "dynamicElementRoot", NULL, "getResourceDynamicElementRoot"); lua_classvariable(luaVM, "exportedFunctions", NULL, "getResourceExportedFunctions"); @@ -142,6 +145,7 @@ void CLuaResourceDefs::AddClass(lua_State* luaVM) lua_classvariable(luaVM, "archived", NULL, "isResourceArchived"); lua_classvariable(luaVM, "protected", nullptr, "isResourceProtected"); lua_classvariable(luaVM, "loadFailureReason", NULL, "getResourceLoadFailureReason"); + lua_classvariable(luaVM, "files", nullptr, "getResourceFiles"); lua_registerclass(luaVM, "Resource"); } @@ -804,7 +808,7 @@ int CLuaResourceDefs::getResourceConfig(lua_State* luaVM) CheckCanModifyOtherResource(argStream, pThisResource, pResource); if (!argStream.HasErrors()) { - for (CResourceFile* pResourceFile : pResource->GetFiles()) + for (CResourceFile* pResourceFile : pResource->GetResourceFiles()) { if (pResourceFile->GetType() != CResourceFile::RESOURCE_FILE_TYPE_CONFIG) continue; @@ -1468,3 +1472,32 @@ bool CLuaResourceDefs::isResourceProtected(CResource* const resource) { return resource->IsProtected(); } + +std::vector CLuaResourceDefs::GetResourceFiles(lua_State* luaVM, std::optional type, + std::optional resource) noexcept +{ + using eResourceCategory = CResourceFile::eResourceCategory; + + if (!type) + type = eResourceCategory::ALL; + + if (!resource) + resource = &lua_getownerresource(luaVM); + + const auto resourceFiles = (*resource)->GetResourceFiles(); + + std::unordered_set files; + for (const auto& file : resourceFiles) + { + if (file->GetResourceCategoryType() != type.value() && type.value() != eResourceCategory::ALL) + continue; + files.insert(file->GetName()); + } + + // TODO: Upgrade ArgumentParser so it would accept + // std::set and std::unordered_set as return values + return std::vector( + std::make_move_iterator(files.begin()), + std::make_move_iterator(files.end()) + ); +} diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h index 29304f402ad..6dcc29cd6aa 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaResourceDefs.h @@ -69,4 +69,7 @@ class CLuaResourceDefs : public CLuaDefs LUA_DECLARE(LoadString); LUA_DECLARE(Load); + + static std::vector GetResourceFiles(lua_State* luaVM, std::optional type, + std::optional resource) noexcept; };