static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, PAKRouter<PAKBridge>& pakRouter, const PAK::Entry& entry, bool force, std::function<void(const hecl::SystemChar*)> fileChanged) { MLVL mlvl; mlvl.read(rs); FILE* fp = hecl::Fopen(outPath.getWithExtension(_S(".yaml"), true).getAbsolutePath().c_str(), _S("wb")); mlvl.toYAMLFile(fp); fclose(fp); hecl::BlenderConnection& conn = hecl::BlenderConnection::SharedConnection(); return DNAMLVL::ReadMLVLToBlender(conn, mlvl, outPath, pakRouter, entry, force, fileChanged); }
PAKBridge::PAKBridge(const nod::Node& node, bool doExtract) : m_node(node), m_pak(true, GetNoShare(node.getName())), m_doExtract(doExtract) { nod::AthenaPartReadStream rs(node.beginReadStream()); m_pak.read(rs); /* Append Level String */ for (const auto& entry : m_pak.m_entries) { const DNAMP2::PAK::Entry& e = entry.second; if (e.type == FOURCC('MLVL')) { PAKEntryReadStream rs = e.beginReadStream(m_node); MLVL mlvl; mlvl.read(rs); const DNAMP2::PAK::Entry* nameEnt = m_pak.lookupEntry(mlvl.worldNameId); if (nameEnt) { PAKEntryReadStream rs = nameEnt->beginReadStream(m_node); STRG mlvlName; mlvlName.read(rs); if (m_levelString.size()) m_levelString += _SYS_STR(", "); m_levelString += mlvlName.getSystemString(FOURCC('ENGL'), 0); } } } }
void PAKBridge::build() { /* First pass: build per-area/per-layer dependency map */ for (const auto& entry : m_pak.m_entries) { const DNAMP2::PAK::Entry& e = entry.second; if (e.type == FOURCC('MLVL')) { Level& level = m_levelDeps[e.id]; MLVL mlvl; { PAKEntryReadStream rs = e.beginReadStream(m_node); mlvl.read(rs); } bool named; std::string bestName = m_pak.bestEntryName(m_node, e, named); level.name = hecl::SystemStringConv(bestName).sys_str(); level.areas.reserve(mlvl.areaCount); unsigned layerIdx = 0; /* Make MAPW available to lookup MAPAs */ const DNAMP2::PAK::Entry* worldMapEnt = m_pak.lookupEntry(mlvl.worldMap); std::vector<UniqueID32> mapw; if (worldMapEnt) { PAKEntryReadStream rs = worldMapEnt->beginReadStream(m_node); rs.seek(8, athena::Current); atUint32 areaCount = rs.readUint32Big(); mapw.reserve(areaCount); for (atUint32 i = 0; i < areaCount; ++i) mapw.emplace_back(rs); } /* Index areas */ unsigned ai = 0; for (const MLVL::Area& area : mlvl.areas) { Level::Area& areaDeps = level.areas[area.areaMREAId]; MLVL::LayerFlags& layerFlags = mlvl.layerFlags[ai]; const DNAMP2::PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId); if (areaNameEnt) { STRG areaName; { PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node); areaName.read(rs); } areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0); areaDeps.name = hecl::StringUtils::TrimWhitespace(areaDeps.name); } if (areaDeps.name.empty()) { areaDeps.name = hecl::SystemStringConv(area.internalAreaName).sys_str(); if (areaDeps.name.empty()) { std::string idStr = area.areaMREAId.toString(); areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str(); } } hecl::SystemChar num[16]; hecl::SNPrintf(num, 16, _SYS_STR("%02u "), ai); areaDeps.name = num + areaDeps.name; areaDeps.layers.reserve(area.depLayerCount - 1); unsigned r = 0; for (unsigned l = 1; l < area.depLayerCount; ++l) { areaDeps.layers.emplace_back(); Level::Area::Layer& layer = areaDeps.layers.back(); layer.name = LayerName(mlvl.layerNames[layerIdx++]); layer.active = layerFlags.flags >> (l - 1) & 0x1; layer.name = hecl::StringUtils::TrimWhitespace(layer.name); hecl::SNPrintf(num, 16, _SYS_STR("%02u "), l - 1); layer.name = num + layer.name; layer.resources.reserve(area.depLayers[l] - r); for (; r < area.depLayers[l]; ++r) layer.resources.emplace(area.deps[r].id); } areaDeps.resources.reserve(area.depCount - r + 2); for (; r < area.depCount; ++r) areaDeps.resources.emplace(area.deps[r].id); areaDeps.resources.emplace(area.areaMREAId); if (mapw.size() > ai) areaDeps.resources.emplace(mapw[ai]); ++ai; } } }