feat: report on unlinking progress

This commit is contained in:
Jan Laupetin
2025-10-14 23:20:56 +01:00
parent 9fa41ca0d3
commit c6e9cbedda
159 changed files with 686 additions and 802 deletions
@@ -77,19 +77,14 @@ namespace image
}
}
bool DumperIW5::ShouldDump(XAssetInfo<GfxImage>* asset)
void DumperIW5::DumpAsset(AssetDumpingContext& context, const XAssetInfo<GfxImage>& asset)
{
return true;
}
void DumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo<GfxImage>* asset)
{
const auto* image = asset->Asset();
const auto* image = asset.Asset();
const auto texture = LoadImageData(context.m_obj_search_path, *image);
if (!texture)
return;
const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset->m_name, m_writer->GetFileExtension()));
const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset.m_name, m_writer->GetFileExtension()));
if (!assetFile)
return;
@@ -14,8 +14,7 @@ namespace image
DumperIW5();
protected:
bool ShouldDump(XAssetInfo<IW5::GfxImage>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<IW5::GfxImage>* asset) override;
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW5::GfxImage>& asset) override;
private:
std::unique_ptr<IImageWriter> m_writer;
@@ -94,19 +94,14 @@ namespace
namespace leaderboard
{
bool JsonDumperIW5::ShouldDump(XAssetInfo<LeaderboardDef>* asset)
void JsonDumperIW5::DumpAsset(AssetDumpingContext& context, const XAssetInfo<LeaderboardDef>& asset)
{
return true;
}
void JsonDumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo<LeaderboardDef>* asset)
{
const auto assetFile = context.OpenAssetFile(GetJsonFileNameForAsset(asset->m_name));
const auto assetFile = context.OpenAssetFile(GetJsonFileNameForAsset(asset.m_name));
if (!assetFile)
return;
Dumper dumper(*assetFile);
dumper.Dump(*asset->Asset());
dumper.Dump(*asset.Asset());
}
} // namespace leaderboard
@@ -8,7 +8,6 @@ namespace leaderboard
class JsonDumperIW5 final : public AbstractAssetDumper<IW5::LeaderboardDef>
{
protected:
[[nodiscard]] bool ShouldDump(XAssetInfo<IW5::LeaderboardDef>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<IW5::LeaderboardDef>* asset) override;
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW5::LeaderboardDef>& asset) override;
};
} // namespace leaderboard
@@ -11,9 +11,14 @@ using namespace IW5;
namespace localize
{
void DumperIW5::DumpPool(AssetDumpingContext& context, AssetPool<IW5::LocalizeEntry>* pool)
size_t DumperIW5::GetProgressTotalCount(const AssetPool<IW5::LocalizeEntry>& pool) const
{
if (pool->m_asset_lookup.empty())
return pool.m_asset_lookup.empty() ? 0uz : 1uz;
}
void DumperIW5::DumpPool(AssetDumpingContext& context, const AssetPool<LocalizeEntry>& pool)
{
if (pool.m_asset_lookup.empty())
return;
const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone.m_language);
@@ -30,7 +35,7 @@ namespace localize
stringFileDumper.SetNotes("");
for (auto* localizeEntry : *pool)
for (const auto* localizeEntry : pool)
{
stringFileDumper.WriteLocalizeEntry(localizeEntry->m_name, localizeEntry->Asset()->value);
}
@@ -41,5 +46,7 @@ namespace localize
{
con::error("Could not create string file for dumping localized strings of zone '{}'", context.m_zone.m_name);
}
context.IncrementProgress();
}
} // namespace localize
@@ -8,6 +8,7 @@ namespace localize
class DumperIW5 final : public IAssetDumper<IW5::LocalizeEntry>
{
public:
void DumpPool(AssetDumpingContext& context, AssetPool<IW5::LocalizeEntry>* pool) override;
[[nodiscard]] size_t GetProgressTotalCount(const AssetPool<IW5::LocalizeEntry>& pool) const override;
void DumpPool(AssetDumpingContext& context, const AssetPool<IW5::LocalizeEntry>& pool) override;
};
} // namespace localize
@@ -7,15 +7,10 @@ using namespace IW5;
namespace addon_map_ents
{
bool DumperIW5::ShouldDump(XAssetInfo<AddonMapEnts>* asset)
void DumperIW5::DumpAsset(AssetDumpingContext& context, const XAssetInfo<AddonMapEnts>& asset)
{
return true;
}
void DumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo<AddonMapEnts>* asset)
{
const auto* addonMapEnts = asset->Asset();
const auto assetFile = context.OpenAssetFile(asset->m_name);
const auto* addonMapEnts = asset.Asset();
const auto assetFile = context.OpenAssetFile(asset.m_name);
if (!assetFile)
return;
@@ -8,7 +8,6 @@ namespace addon_map_ents
class DumperIW5 final : public AbstractAssetDumper<IW5::AddonMapEnts>
{
protected:
bool ShouldDump(XAssetInfo<IW5::AddonMapEnts>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<IW5::AddonMapEnts>* asset) override;
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW5::AddonMapEnts>& asset) override;
};
} // namespace addon_map_ents
+8 -13
View File
@@ -15,10 +15,10 @@ using namespace IW5;
namespace
{
const MenuList* GetParentMenuList(XAssetInfo<menuDef_t>* asset)
const MenuList* GetParentMenuList(const XAssetInfo<menuDef_t>& asset)
{
const auto* menu = asset->Asset();
const auto* gameAssetPool = dynamic_cast<GameAssetPoolIW5*>(asset->m_zone->m_pools.get());
const auto* menu = asset.Asset();
const auto* gameAssetPool = dynamic_cast<GameAssetPoolIW5*>(asset.m_zone->m_pools.get());
for (const auto* menuList : *gameAssetPool->m_menu_list)
{
const auto* menuListAsset = menuList->Asset();
@@ -33,32 +33,27 @@ namespace
return nullptr;
}
std::string GetPathForMenu(XAssetInfo<menuDef_t>* asset)
std::string GetPathForMenu(const XAssetInfo<menuDef_t>& asset)
{
const auto* list = GetParentMenuList(asset);
if (!list)
return std::format("ui_mp/{}.menu", asset->Asset()->window.name);
return std::format("ui_mp/{}.menu", asset.Asset()->window.name);
const fs::path p(list->name);
std::string parentPath;
if (p.has_parent_path())
parentPath = p.parent_path().string() + "/";
return std::format("{}{}.menu", parentPath, asset->Asset()->window.name);
return std::format("{}{}.menu", parentPath, asset.Asset()->window.name);
}
} // namespace
namespace menu
{
bool MenuDumperIW5::ShouldDump(XAssetInfo<menuDef_t>* asset)
void MenuDumperIW5::DumpAsset(AssetDumpingContext& context, const XAssetInfo<menuDef_t>& asset)
{
return true;
}
void MenuDumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo<menuDef_t>* asset)
{
const auto* menu = asset->Asset();
const auto* menu = asset.Asset();
const auto menuFilePath = GetPathForMenu(asset);
if (ObjWriting::ShouldHandleAssetType(ASSET_TYPE_MENULIST))
+1 -2
View File
@@ -9,7 +9,6 @@ namespace menu
class MenuDumperIW5 final : public AbstractAssetDumper<IW5::menuDef_t>
{
protected:
bool ShouldDump(XAssetInfo<IW5::menuDef_t>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<IW5::menuDef_t>* asset) override;
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW5::menuDef_t>& asset) override;
};
} // namespace menu
@@ -106,15 +106,10 @@ namespace
namespace menu
{
bool MenuListDumperIW5::ShouldDump(XAssetInfo<MenuList>* asset)
void MenuListDumperIW5::DumpAsset(AssetDumpingContext& context, const XAssetInfo<MenuList>& asset)
{
return true;
}
void MenuListDumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo<MenuList>* asset)
{
const auto* menuList = asset->Asset();
const auto assetFile = context.OpenAssetFile(asset->m_name);
const auto* menuList = asset.Asset();
const auto assetFile = context.OpenAssetFile(asset.m_name);
if (!assetFile)
return;
@@ -8,7 +8,6 @@ namespace menu
class MenuListDumperIW5 final : public AbstractAssetDumper<IW5::MenuList>
{
protected:
bool ShouldDump(XAssetInfo<IW5::MenuList>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<IW5::MenuList>* asset) override;
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW5::MenuList>& asset) override;
};
} // namespace menu
+15 -1
View File
@@ -25,10 +25,20 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const
if (assetPools->poolName && ObjWriting::ShouldHandleAssetType(assetType)) \
{ \
dumperType dumper; \
dumper.DumpPool(context, assetPools->poolName.get()); \
totalProgress += dumper.GetProgressTotalCount(*assetPools->poolName); \
dumpingFunctions.emplace_back( \
[](AssetDumpingContext& funcContext, const GameAssetPoolIW5* funcPools) \
{ \
dumperType dumper; \
dumper.DumpPool(funcContext, *funcPools->poolName); \
}); \
}
const auto* assetPools = dynamic_cast<GameAssetPoolIW5*>(context.m_zone.m_pools.get());
size_t totalProgress = 0uz;
std::vector<std::function<void(AssetDumpingContext & context, const GameAssetPoolIW5*)>> dumpingFunctions;
// DUMP_ASSET_POOL(AssetDumperPhysPreset, m_phys_preset, ASSET_TYPE_PHYSPRESET)
// DUMP_ASSET_POOL(AssetDumperPhysCollmap, m_phys_collmap, ASSET_TYPE_PHYSCOLLMAP)
// DUMP_ASSET_POOL(AssetDumperXAnimParts, m_xanim_parts, ASSET_TYPE_XANIMPARTS)
@@ -70,6 +80,10 @@ bool ObjWriter::DumpZone(AssetDumpingContext& context) const
// DUMP_ASSET_POOL(AssetDumperVehicleDef, m_vehicle, ASSET_TYPE_VEHICLE)
DUMP_ASSET_POOL(addon_map_ents::DumperIW5, m_addon_map_ents, ASSET_TYPE_ADDON_MAP_ENTS)
context.SetTotalProgress(totalProgress);
for (const auto& func : dumpingFunctions)
func(context, assetPools);
return true;
#undef DUMP_ASSET_POOL
@@ -10,15 +10,10 @@ using namespace IW5;
namespace raw_file
{
bool DumperIW5::ShouldDump(XAssetInfo<RawFile>* asset)
void DumperIW5::DumpAsset(AssetDumpingContext& context, const XAssetInfo<RawFile>& asset)
{
return true;
}
void DumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo<RawFile>* asset)
{
const auto* rawFile = asset->Asset();
const auto assetFile = context.OpenAssetFile(asset->m_name);
const auto* rawFile = asset.Asset();
const auto assetFile = context.OpenAssetFile(asset.m_name);
if (!assetFile)
return;
@@ -8,7 +8,6 @@ namespace raw_file
class DumperIW5 final : public AbstractAssetDumper<IW5::RawFile>
{
protected:
bool ShouldDump(XAssetInfo<IW5::RawFile>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<IW5::RawFile>* asset) override;
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW5::RawFile>& asset) override;
};
} // namespace raw_file
@@ -4,16 +4,11 @@ using namespace IW5;
namespace script
{
bool DumperIW5::ShouldDump(XAssetInfo<IW5::ScriptFile>* asset)
{
return true;
}
// See https://github.com/xensik/gsc-tool#file-format for an in-depth explanation about the .gscbin format
void DumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo<IW5::ScriptFile>* asset)
void DumperIW5::DumpAsset(AssetDumpingContext& context, const XAssetInfo<ScriptFile>& asset)
{
auto* scriptFile = asset->Asset();
const auto assetFile = context.OpenAssetFile(asset->m_name + ".gscbin");
auto* scriptFile = asset.Asset();
const auto assetFile = context.OpenAssetFile(asset.m_name + ".gscbin");
if (!assetFile)
return;
@@ -21,10 +16,10 @@ namespace script
auto& stream = *assetFile;
// Dump the name and the numeric fields
stream.write(asset->m_name.c_str(), asset->m_name.size() + 1);
stream.write(reinterpret_cast<char*>(&scriptFile->compressedLen), sizeof(scriptFile->compressedLen));
stream.write(reinterpret_cast<char*>(&scriptFile->len), sizeof(scriptFile->len));
stream.write(reinterpret_cast<char*>(&scriptFile->bytecodeLen), sizeof(scriptFile->bytecodeLen));
stream.write(asset.m_name.c_str(), asset.m_name.size() + 1);
stream.write(reinterpret_cast<const char*>(&scriptFile->compressedLen), sizeof(scriptFile->compressedLen));
stream.write(reinterpret_cast<const char*>(&scriptFile->len), sizeof(scriptFile->len));
stream.write(reinterpret_cast<const char*>(&scriptFile->bytecodeLen), sizeof(scriptFile->bytecodeLen));
// Dump the buffers
stream.write(scriptFile->buffer, scriptFile->compressedLen);
@@ -8,7 +8,6 @@ namespace script
class DumperIW5 final : public AbstractAssetDumper<IW5::ScriptFile>
{
protected:
bool ShouldDump(XAssetInfo<IW5::ScriptFile>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<IW5::ScriptFile>* asset) override;
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW5::ScriptFile>& asset) override;
};
} // namespace script
@@ -25,15 +25,10 @@ namespace
namespace sound
{
bool LoadedSoundDumperIW5::ShouldDump(XAssetInfo<LoadedSound>* asset)
void LoadedSoundDumperIW5::DumpAsset(AssetDumpingContext& context, const XAssetInfo<LoadedSound>& asset)
{
return true;
}
void LoadedSoundDumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo<LoadedSound>* asset)
{
const auto* loadedSound = asset->Asset();
const auto assetFile = context.OpenAssetFile(std::format("sound/{}", asset->m_name));
const auto* loadedSound = asset.Asset();
const auto assetFile = context.OpenAssetFile(std::format("sound/{}", asset.m_name));
if (!assetFile)
return;
@@ -8,7 +8,6 @@ namespace sound
class LoadedSoundDumperIW5 final : public AbstractAssetDumper<IW5::LoadedSound>
{
protected:
bool ShouldDump(XAssetInfo<IW5::LoadedSound>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<IW5::LoadedSound>* asset) override;
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW5::LoadedSound>& asset) override;
};
} // namespace sound
@@ -6,15 +6,10 @@ using namespace IW5;
namespace string_table
{
bool DumperIW5::ShouldDump(XAssetInfo<StringTable>* asset)
void DumperIW5::DumpAsset(AssetDumpingContext& context, const XAssetInfo<StringTable>& asset)
{
return true;
}
void DumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo<StringTable>* asset)
{
const auto* stringTable = asset->Asset();
const auto assetFile = context.OpenAssetFile(asset->m_name);
const auto* stringTable = asset.Asset();
const auto assetFile = context.OpenAssetFile(asset.m_name);
if (!assetFile)
return;
@@ -8,7 +8,6 @@ namespace string_table
class DumperIW5 final : public AbstractAssetDumper<IW5::StringTable>
{
protected:
bool ShouldDump(XAssetInfo<IW5::StringTable>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<IW5::StringTable>* asset) override;
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW5::StringTable>& asset) override;
};
} // namespace string_table
@@ -395,19 +395,14 @@ namespace
namespace attachment
{
bool JsonDumperIW5::ShouldDump(XAssetInfo<WeaponAttachment>* asset)
void JsonDumperIW5::DumpAsset(AssetDumpingContext& context, const XAssetInfo<WeaponAttachment>& asset)
{
return true;
}
void JsonDumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo<WeaponAttachment>* asset)
{
const auto assetFile = context.OpenAssetFile(GetJsonFileNameForAssetName(asset->m_name));
const auto assetFile = context.OpenAssetFile(GetJsonFileNameForAssetName(asset.m_name));
if (!assetFile)
return;
const JsonDumperImpl dumper(context, *assetFile);
dumper.Dump(asset->Asset());
dumper.Dump(asset.Asset());
}
} // namespace attachment
@@ -8,7 +8,6 @@ namespace attachment
class JsonDumperIW5 final : public AbstractAssetDumper<IW5::WeaponAttachment>
{
protected:
bool ShouldDump(XAssetInfo<IW5::WeaponAttachment>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<IW5::WeaponAttachment>* asset) override;
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW5::WeaponAttachment>& asset) override;
};
} // namespace attachment
@@ -681,31 +681,31 @@ namespace
}
}
InfoString CreateInfoString(XAssetInfo<WeaponCompleteDef>* asset)
InfoString CreateInfoString(const XAssetInfo<WeaponCompleteDef>& asset)
{
const auto fullDef = std::make_unique<WeaponFullDef>();
memset(fullDef.get(), 0, sizeof(WeaponFullDef));
CopyToFullDef(asset->Asset(), fullDef.get());
CopyToFullDef(asset.Asset(), fullDef.get());
InfoStringFromWeaponConverter converter(fullDef.get(),
weapon_fields,
std::extent_v<decltype(weapon_fields)>,
[asset](const scr_string_t scrStr) -> std::string
{
assert(scrStr < asset->m_zone->m_script_strings.Count());
if (scrStr >= asset->m_zone->m_script_strings.Count())
assert(scrStr < asset.m_zone->m_script_strings.Count());
if (scrStr >= asset.m_zone->m_script_strings.Count())
return "";
return asset->m_zone->m_script_strings[scrStr];
return asset.m_zone->m_script_strings[scrStr];
});
return converter.Convert();
}
void DumpAccuracyGraphs(AssetDumpingContext& context, XAssetInfo<WeaponCompleteDef>* asset)
void DumpAccuracyGraphs(AssetDumpingContext& context, const XAssetInfo<WeaponCompleteDef>& asset)
{
auto* accuracyGraphWriter = context.GetZoneAssetDumperState<AccuracyGraphWriter>();
const auto weapon = asset->Asset();
const auto weapon = asset.Asset();
const auto* weapDef = weapon->weapDef;
if (!weapDef)
@@ -733,12 +733,7 @@ namespace
namespace weapon
{
bool DumperIW5::ShouldDump(XAssetInfo<WeaponCompleteDef>* asset)
{
return true;
}
void DumperIW5::DumpAsset(AssetDumpingContext& context, XAssetInfo<WeaponCompleteDef>* asset)
void DumperIW5::DumpAsset(AssetDumpingContext& context, const XAssetInfo<WeaponCompleteDef>& asset)
{
// TODO: only dump infostring fields when non-default
@@ -746,13 +741,13 @@ namespace weapon
if (context.m_gdt)
{
const auto infoString = CreateInfoString(asset);
GdtEntry gdtEntry(asset->m_name, ObjConstants::GDF_FILENAME_WEAPON);
GdtEntry gdtEntry(asset.m_name, ObjConstants::GDF_FILENAME_WEAPON);
infoString.ToGdtProperties(ObjConstants::INFO_STRING_PREFIX_WEAPON, gdtEntry);
context.m_gdt->WriteEntry(gdtEntry);
}
else
{
const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset->m_name));
const auto assetFile = context.OpenAssetFile(GetFileNameForAssetName(asset.m_name));
if (!assetFile)
return;
@@ -9,7 +9,6 @@ namespace weapon
class DumperIW5 final : public AbstractAssetDumper<IW5::WeaponCompleteDef>
{
protected:
bool ShouldDump(XAssetInfo<IW5::WeaponCompleteDef>* asset) override;
void DumpAsset(AssetDumpingContext& context, XAssetInfo<IW5::WeaponCompleteDef>* asset) override;
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW5::WeaponCompleteDef>& asset) override;
};
} // namespace weapon