mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-17 11:57:01 +02:00
Mod merge: placeholder archive indexes are reserved; carry() keeps one list
A mod archive numbered 65534 or 65535 is placed under a free index, so no real placement is read as a placeholder. carry() records every payload in one list (settle() still writes each once per install chunk) and keeps one archive index, as write() does.
This commit is contained in:
1 parent
cec00f412e
commit
3feeaa3893
4 files changed
+17
-21
No files matched your search
@@ -289,8 +289,8 @@ MergeReport merge_mods(const Catalog& catalog, const MergeObserver& observe, con
|
||||
// Archive 1 stays the patch's own file, never a link to a mod's:
|
||||
// a live apply appends manifests and new mods to it while the
|
||||
// game has it open, and a linked file cannot be swapped for a
|
||||
// private copy then (Windows keeps it in use).
|
||||
claimed.insert(manifestArchive);
|
||||
// private copy then (Windows keeps it in use). Placeholder indexes name no file.
|
||||
claimed.insert({manifestArchive, CasStore::waiting_archive, CasStore::carried_archive});
|
||||
if (number == manifestArchive) {
|
||||
if (const auto free = claim(directory); free) {
|
||||
spot.archive = *free;
|
||||
|
||||
@@ -84,19 +84,19 @@ CasStore CasStore::waiting() const {
|
||||
copy.held_.clear();
|
||||
copy.offsets_.clear();
|
||||
copy.carried_.clear();
|
||||
copy.carriedIndex_.clear();
|
||||
copy.carriedAt_.clear();
|
||||
return copy;
|
||||
}
|
||||
|
||||
fb::BundleFileInfo CasStore::carry(std::uint32_t installChunk, std::uint16_t archive, std::span<const std::byte> encoded) {
|
||||
if (!waiting_) throw std::logic_error("Only a waiting store carries payloads");
|
||||
// An install chunk no package names fails here, for this payload alone, and not when it settles.
|
||||
(void)archive_path(installChunk, archive);
|
||||
const std::pair key{installChunk, sha1_of(encoded)};
|
||||
const auto [found, fresh] = carriedIndex_.try_emplace(key, carried_.size());
|
||||
if (fresh) carried_.push_back({installChunk, archive, key.second, encoded, {}});
|
||||
return {{true, installChunk, carried_archive}, static_cast<std::uint32_t>(found->second),
|
||||
if (placeholder(archive) || (archive_ && *archive_ != archive))
|
||||
throw std::logic_error("A waiting store writes to one archive index");
|
||||
// An install chunk no package names fails here, for this payload alone.
|
||||
(void)directory(installChunk);
|
||||
archive_ = archive;
|
||||
carried_.push_back({installChunk, sha1_of(encoded), encoded, {}});
|
||||
return {{true, installChunk, carried_archive}, static_cast<std::uint32_t>(carried_.size() - 1),
|
||||
static_cast<std::uint32_t>(encoded.size())};
|
||||
}
|
||||
|
||||
@@ -106,13 +106,12 @@ void CasStore::settle(CasStore& waiting) {
|
||||
held.at = append(fs::path(path), held.bytes);
|
||||
held.bytes = {};
|
||||
}
|
||||
// Then the carried assets, in the order the superbundle first named them. An asset an
|
||||
// earlier superbundle settled in this install chunk is not written again.
|
||||
// Then the carried assets, each written once per install chunk.
|
||||
for (auto& carried : waiting.carried_) {
|
||||
const std::pair key{carried.installChunk, carried.sha1};
|
||||
auto found = carriedAt_.find(key);
|
||||
if (found == carriedAt_.end())
|
||||
found = carriedAt_.emplace(key, write(carried.installChunk, carried.archive, carried.bytes)).first;
|
||||
found = carriedAt_.emplace(key, write(carried.installChunk, *waiting.archive_, carried.bytes)).first;
|
||||
carried.at = found->second;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,8 +370,7 @@ fb::TocDocument combine(const fs::path& baseToc, const fs::path& baseRoot,
|
||||
else if (addition.asset.kind == fb::AssetKind::resource)
|
||||
companions.emplace(std::tuple{bundleName, addition.mod, lower(addition.asset.name)}, &addition);
|
||||
}
|
||||
// Where an addition's payload already went in this superbundle's patch
|
||||
// archive, by install chunk: every copy that is given it reads the one.
|
||||
// The carried place each addition got in this superbundle, by install chunk.
|
||||
std::map<std::pair<std::uint32_t, const AssetAddition*>, fb::BundleFileInfo> carriedAt;
|
||||
// The names any mod changed, to rule the rest out without a copy of each (name_hash).
|
||||
std::unordered_set<std::uint64_t> changedNames, scriptNames;
|
||||
|
||||
@@ -132,8 +132,7 @@ public:
|
||||
// own has been settled, settle() appends what it holds to the real archives, and
|
||||
// settled() then moves a placement that points into it to where that went.
|
||||
static constexpr std::uint16_t waiting_archive = 0xFFFF;
|
||||
// An asset carried into copies in several superbundles. A waiting store names it by its
|
||||
// place in the store's carried list, and settle() writes it once per install chunk.
|
||||
// A carried payload, by its index in the waiting store's list: settle() writes it once per install chunk.
|
||||
static constexpr std::uint16_t carried_archive = 0xFFFE;
|
||||
[[nodiscard]] CasStore waiting() const;
|
||||
[[nodiscard]] bool holding() const noexcept { return !held_.empty() || !carried_.empty(); }
|
||||
@@ -169,16 +168,15 @@ private:
|
||||
bool waiting_{};
|
||||
std::optional<std::uint16_t> archive_;
|
||||
std::map<std::wstring, Held> held_;
|
||||
// Carried payloads (waiting store) and where each landed (settling store).
|
||||
struct Carried {
|
||||
std::uint32_t installChunk{};
|
||||
std::uint16_t archive{};
|
||||
fb::Sha1 sha1;
|
||||
std::span<const std::byte> bytes;
|
||||
fb::BundleFileInfo at; // where settle() put it
|
||||
fb::BundleFileInfo at;
|
||||
};
|
||||
std::vector<Carried> carried_; // waiting: first-reference order
|
||||
std::map<std::pair<std::uint32_t, fb::Sha1>, std::size_t> carriedIndex_; // waiting: into carried_
|
||||
std::map<std::pair<std::uint32_t, fb::Sha1>, fb::BundleFileInfo> carriedAt_; // settled: one per install chunk
|
||||
std::vector<Carried> carried_;
|
||||
std::map<std::pair<std::uint32_t, fb::Sha1>, fb::BundleFileInfo> carriedAt_;
|
||||
};
|
||||
|
||||
using ArchiveUse = std::set<std::pair<std::uint32_t, std::uint16_t>>;
|
||||
|
||||
Reference in new issue
Block a user