From fef815e70886899fe966c98a7063dc707124a44f Mon Sep 17 00:00:00 2001 From: Jan Date: Wed, 7 Feb 2024 00:53:52 +0100 Subject: [PATCH] feat: recognize indirect asset refs when marking assets --- .../T6/AssetDumpers/AssetDumperWeapon.cpp | 4 ++ .../Game/T6/XAssets/WeaponVariantDef.txt | 1 + .../Domain/Information/MemberInformation.cpp | 3 +- .../Domain/Information/MemberInformation.h | 1 + .../Generating/Templates/ZoneLoadTemplate.cpp | 3 +- .../Generating/Templates/ZoneMarkTemplate.cpp | 28 +++++++- .../Parsing/Commands/Impl/CommandsParser.cpp | 2 + .../Commands/Sequence/SequenceAssetRef.cpp | 72 +++++++++++++++++++ .../Commands/Sequence/SequenceAssetRef.h | 17 +++++ .../MarkingRequiredPostProcessor.cpp | 4 +- src/ZoneLoading/Loading/AssetLoader.cpp | 10 +-- src/ZoneLoading/Loading/AssetLoader.h | 6 +- src/ZoneLoading/Loading/AssetMarker.cpp | 29 ++++++++ src/ZoneLoading/Loading/AssetMarker.h | 5 ++ 14 files changed, 175 insertions(+), 10 deletions(-) create mode 100644 src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceAssetRef.cpp create mode 100644 src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceAssetRef.h diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp index e9451278..40803c60 100644 --- a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperWeapon.cpp @@ -243,6 +243,10 @@ namespace T6 break; } + case WFT_ANIM_NAME: + FillFromString(std::string(field.szName), field.iOffset); + break; + case WFT_NUM_FIELD_TYPES: default: assert(false); diff --git a/src/ZoneCode/Game/T6/XAssets/WeaponVariantDef.txt b/src/ZoneCode/Game/T6/XAssets/WeaponVariantDef.txt index 4778378c..590bbb7c 100644 --- a/src/ZoneCode/Game/T6/XAssets/WeaponVariantDef.txt +++ b/src/ZoneCode/Game/T6/XAssets/WeaponVariantDef.txt @@ -14,6 +14,7 @@ set reusable attachments; set count attachmentUniques 95; set reusable attachmentUniques; set string szXAnims; +set assetref szXAnims ASSET_TYPE_XANIMPARTS; set count szXAnims NUM_WEAP_ANIMS; set reusable szXAnims; set scriptstring hideTags; diff --git a/src/ZoneCodeGeneratorLib/Domain/Information/MemberInformation.cpp b/src/ZoneCodeGeneratorLib/Domain/Information/MemberInformation.cpp index a19fc05c..ab4b5323 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Information/MemberInformation.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Information/MemberInformation.cpp @@ -8,6 +8,7 @@ MemberInformation::MemberInformation(StructureInformation* parent, StructureInfo m_is_script_string(false), m_is_reusable(false), m_is_leaf(false), - m_fast_file_block(nullptr) + m_fast_file_block(nullptr), + m_asset_ref(nullptr) { } diff --git a/src/ZoneCodeGeneratorLib/Domain/Information/MemberInformation.h b/src/ZoneCodeGeneratorLib/Domain/Information/MemberInformation.h index 1c93235a..ee421c35 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Information/MemberInformation.h +++ b/src/ZoneCodeGeneratorLib/Domain/Information/MemberInformation.h @@ -23,6 +23,7 @@ public: std::unique_ptr m_condition; std::unique_ptr m_alloc_alignment; const FastFileBlock* m_fast_file_block; + const EnumMember* m_asset_ref; MemberInformation(StructureInformation* parent, StructureInformation* type, Variable* member); }; diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp index 7866f580..ce5c3b5a 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp @@ -1075,7 +1075,8 @@ class ZoneLoadTemplate::Internal final : BaseTemplate LINE("marker.Mark(*pAsset);") LINE("") LINE("m_asset_info = reinterpret_castm_definition->GetFullName() << ">*>(LinkAsset(GetAssetName(*pAsset), *pAsset, marker.GetUsedScriptStrings(), marker.GetDependencies()));") + << info->m_definition->GetFullName() + << ">*>(LinkAsset(GetAssetName(*pAsset), *pAsset, marker.GetDependencies(), marker.GetUsedScriptStrings(), marker.GetIndirectAssetReferences()));") LINE("*pAsset = m_asset_info->Asset();") m_intendation--; diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp index 45eacaa6..0a62f1a4 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp @@ -225,6 +225,27 @@ class ZoneMarkTemplate::Internal final : BaseTemplate } } + void MarkMember_AssetRef(StructureInformation* info, + MemberInformation* member, + const DeclarationModifierComputations& modifier, + const MemberLoadType loadType) const + { + if (loadType == MemberLoadType::POINTER_ARRAY) + { + LINE("MarkArray_IndirectAssetRef(" << member->m_asset_ref->m_name << ", " << MakeMemberAccess(info, member, modifier) << ", " + << MakeEvaluation(modifier.GetArrayPointerCountEvaluation()) << ");") + } + else if (loadType == MemberLoadType::SINGLE_POINTER) + { + LINE("Mark_IndirectAssetRef(" << member->m_asset_ref->m_name << ", " << MakeMemberAccess(info, member, modifier) << ");") + } + else + { + assert(false); + LINE("#error unsupported loadType " << static_cast(loadType) << " for scriptstring") + } + } + void MarkMember_Asset(StructureInformation* info, MemberInformation* member, const DeclarationModifierComputations& modifier, @@ -308,6 +329,10 @@ class ZoneMarkTemplate::Internal final : BaseTemplate { MarkMember_ScriptString(info, member, modifier, loadType); } + else if (member->m_asset_ref) + { + MarkMember_AssetRef(info, member, modifier, loadType); + } else if (member->m_type && StructureComputations(member->m_type).IsAsset()) { MarkMember_Asset(info, member, modifier, loadType); @@ -541,7 +566,8 @@ class ZoneMarkTemplate::Internal final : BaseTemplate if (computations.ShouldIgnore() || computations.IsInRuntimeBlock()) return; - if (member->m_is_script_string || member->m_type && (member->m_type->m_requires_marking || StructureComputations(member->m_type).IsAsset())) + if (member->m_is_script_string || member->m_asset_ref + || member->m_type && (member->m_type->m_requires_marking || StructureComputations(member->m_type).IsAsset())) { if (info->m_definition->GetType() == DataDefinitionType::UNION) MarkMember_Condition_Union(info, member); diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParser.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParser.cpp index f86e1f8f..617d2ca6 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParser.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParser.cpp @@ -6,6 +6,7 @@ #include "Parsing/Commands/Sequence/SequenceArrayCount.h" #include "Parsing/Commands/Sequence/SequenceArraySize.h" #include "Parsing/Commands/Sequence/SequenceAsset.h" +#include "Parsing/Commands/Sequence/SequenceAssetRef.h" #include "Parsing/Commands/Sequence/SequenceBlock.h" #include "Parsing/Commands/Sequence/SequenceCondition.h" #include "Parsing/Commands/Sequence/SequenceCount.h" @@ -33,6 +34,7 @@ const std::vector& CommandsParser::GetTestsForState new SequenceArrayCount(), new SequenceArraySize(), new SequenceAsset(), + new SequenceAssetRef(), new SequenceBlock(), new SequenceCondition(), new SequenceCount(), diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceAssetRef.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceAssetRef.cpp new file mode 100644 index 00000000..e15512e2 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceAssetRef.cpp @@ -0,0 +1,72 @@ +#include "SequenceAssetRef.h" + +#include "Parsing/Commands/Matcher/CommandsCommonMatchers.h" +#include "Parsing/Commands/Matcher/CommandsMatcherFactory.h" + +#include + +SequenceAssetRef::SequenceAssetRef() +{ + const CommandsMatcherFactory create(this); + + AddLabeledMatchers(CommandsCommonMatchers::Typename(this), CommandsCommonMatchers::LABEL_TYPENAME); + AddMatchers({ + create.Keyword("set"), + create.Keyword("assetref"), + create.Label(CommandsCommonMatchers::LABEL_TYPENAME).Capture(CAPTURE_TYPE), + create.Identifier().Capture(CAPTURE_ASSET_TYPE_ENUM_ENTRY), + create.Char(';'), + }); +} + +void SequenceAssetRef::ProcessMatch(CommandsParserState* state, SequenceResult& result) const +{ + const auto& enumEntryToken = result.NextCapture(CAPTURE_ASSET_TYPE_ENUM_ENTRY); + const auto* enumMember = state->GetRepository()->GetEnumMemberByName(enumEntryToken.IdentifierValue()); + if (enumMember == nullptr) + throw ParsingException(enumEntryToken.GetPos(), "Unknown asset type enum entry"); + + const auto& typeNameToken = result.NextCapture(CAPTURE_TYPE); + + StructureInformation* type; + std::vector members; + if (!state->GetTypenameAndMembersFromTypename(typeNameToken.TypeNameValue(), type, members)) + throw ParsingException(typeNameToken.GetPos(), "Unknown type"); + + if (members.empty()) + throw ParsingException(typeNameToken.GetPos(), "Need to specify a member when trying to mark as string."); + + auto* lastMember = members.back(); + const auto* typeDecl = lastMember->m_member->m_type_declaration.get(); + auto hasPointerRef = false; + + while (true) + { + if (!hasPointerRef) + { + const auto& modifiers = typeDecl->m_declaration_modifiers; + hasPointerRef = std::any_of(modifiers.begin(), + modifiers.end(), + [](const std::unique_ptr& modifier) + { + return modifier->GetType() == DeclarationModifierType::POINTER; + }); + } + + if (typeDecl->m_type->GetType() == DataDefinitionType::TYPEDEF) + { + const auto* typedefDef = dynamic_cast(typeDecl->m_type); + typeDecl = typedefDef->m_type_declaration.get(); + } + else + break; + } + + if (!hasPointerRef) + throw ParsingException(typeNameToken.GetPos(), "Invalid type for string, must be a pointer"); + + if (typeDecl->m_type->GetType() != DataDefinitionType::BASE_TYPE) + throw ParsingException(typeNameToken.GetPos(), "Invalid type for string, must be a base type"); + + lastMember->m_asset_ref = enumMember; +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceAssetRef.h b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceAssetRef.h new file mode 100644 index 00000000..1feeffbf --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceAssetRef.h @@ -0,0 +1,17 @@ +#pragma once + +#include "Parsing/Commands/Impl/CommandsParser.h" + +class SequenceAssetRef final : public CommandsParser::sequence_t +{ + static constexpr auto TAG_DEFAULT = 1; + + static constexpr auto CAPTURE_TYPE = 1; + static constexpr auto CAPTURE_ASSET_TYPE_ENUM_ENTRY = 2; + +protected: + void ProcessMatch(CommandsParserState* state, SequenceResult& result) const override; + +public: + SequenceAssetRef(); +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/MarkingRequiredPostProcessor.cpp b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/MarkingRequiredPostProcessor.cpp index 439b41ff..1eeb9fbd 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/MarkingRequiredPostProcessor.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/MarkingRequiredPostProcessor.cpp @@ -44,8 +44,8 @@ bool MarkingRequiredPostProcessor::CalculateRequiresMarking(std::unordered_setm_is_script_string || member->m_type && member->m_type->m_asset_enum_entry) + // Any script strings, asset refs and assets need to be processed. + if (member->m_is_script_string || member->m_asset_ref || member->m_type && member->m_type->m_asset_enum_entry) { info->m_requires_marking = true; return true; diff --git a/src/ZoneLoading/Loading/AssetLoader.cpp b/src/ZoneLoading/Loading/AssetLoader.cpp index 4c1885f5..c61e1f2a 100644 --- a/src/ZoneLoading/Loading/AssetLoader.cpp +++ b/src/ZoneLoading/Loading/AssetLoader.cpp @@ -10,12 +10,14 @@ AssetLoader::AssetLoader(const asset_type_t assetType, Zone* zone, IZoneInputStr { } -XAssetInfoGeneric* - AssetLoader::LinkAsset(std::string name, void* asset, std::vector scriptStrings, std::vector dependencies) const +XAssetInfoGeneric* AssetLoader::LinkAsset(std::string name, + void* asset, + std::vector dependencies, + std::vector scriptStrings, + std::vector indirectAssetReferences) const { - // TODO: Add indirect asset references here return m_zone->m_pools->AddAsset( - m_asset_type, std::move(name), asset, std::move(dependencies), std::move(scriptStrings), std::vector()); + m_asset_type, std::move(name), asset, std::move(dependencies), std::move(scriptStrings), std::move(indirectAssetReferences)); } XAssetInfoGeneric* AssetLoader::GetAssetInfo(std::string name) const diff --git a/src/ZoneLoading/Loading/AssetLoader.h b/src/ZoneLoading/Loading/AssetLoader.h index 47246188..d4ec283e 100644 --- a/src/ZoneLoading/Loading/AssetLoader.h +++ b/src/ZoneLoading/Loading/AssetLoader.h @@ -16,7 +16,11 @@ protected: AssetLoader(asset_type_t assetType, Zone* zone, IZoneInputStream* stream); - XAssetInfoGeneric* LinkAsset(std::string name, void* asset, std::vector scriptStrings, std::vector dependencies) const; + XAssetInfoGeneric* LinkAsset(std::string name, + void* asset, + std::vector dependencies, + std::vector scriptStrings, + std::vector indirectAssetReferences) const; _NODISCARD XAssetInfoGeneric* GetAssetInfo(std::string name) const; }; diff --git a/src/ZoneLoading/Loading/AssetMarker.cpp b/src/ZoneLoading/Loading/AssetMarker.cpp index ecf14dd9..c6ce0d17 100644 --- a/src/ZoneLoading/Loading/AssetMarker.cpp +++ b/src/ZoneLoading/Loading/AssetMarker.cpp @@ -39,6 +39,22 @@ void AssetMarker::MarkArray_ScriptString(const scr_string_t* scrStringArray, con Mark_ScriptString(scrStringArray[index]); } +void AssetMarker::Mark_IndirectAssetRef(asset_type_t type, const char* assetRefName) +{ + if (!assetRefName || !assetRefName[0]) + return; + + m_indirect_asset_references.emplace(type, assetRefName); +} + +void AssetMarker::MarkArray_IndirectAssetRef(const asset_type_t type, const char** assetRefNames, const size_t count) +{ + assert(assetRefNames != nullptr); + + for (size_t index = 0; index < count; index++) + Mark_IndirectAssetRef(type, assetRefNames[index]); +} + XAssetInfoGeneric* AssetMarker::GetAssetInfoByName(std::string name) const { return m_zone->m_pools->GetAsset(m_asset_type, std::move(name)); @@ -71,3 +87,16 @@ std::vector AssetMarker::GetUsedScriptStrings() const return usedScriptStrings; } + +std::vector AssetMarker::GetIndirectAssetReferences() const +{ + std::vector assetReferences; + if (!m_indirect_asset_references.empty()) + { + assetReferences.reserve(m_indirect_asset_references.size()); + for (const auto& assetReference : m_indirect_asset_references) + assetReferences.emplace_back(assetReference); + } + + return assetReferences; +} diff --git a/src/ZoneLoading/Loading/AssetMarker.h b/src/ZoneLoading/Loading/AssetMarker.h index cb3837bd..92cc449d 100644 --- a/src/ZoneLoading/Loading/AssetMarker.h +++ b/src/ZoneLoading/Loading/AssetMarker.h @@ -13,6 +13,7 @@ class AssetMarker std::unordered_set m_dependencies; std::unordered_set m_used_script_strings; + std::unordered_set m_indirect_asset_references; protected: AssetMarker(asset_type_t assetType, Zone* zone); @@ -22,6 +23,9 @@ protected: void Mark_ScriptString(scr_string_t scrString); void MarkArray_ScriptString(const scr_string_t* scrStringArray, size_t count); + void Mark_IndirectAssetRef(asset_type_t type, const char* assetRefName); + void MarkArray_IndirectAssetRef(asset_type_t type, const char** assetRefNames, size_t count); + _NODISCARD XAssetInfoGeneric* GetAssetInfoByName(std::string name) const; Zone* m_zone; @@ -29,4 +33,5 @@ protected: public: _NODISCARD std::vector GetDependencies() const; _NODISCARD std::vector GetUsedScriptStrings() const; + _NODISCARD std::vector GetIndirectAssetReferences() const; };