feat: extend SaveMigration

This commit is contained in:
dualfroz committed 2026-09-09 14:41:56 +02:00
1 parent 966c022003
commit e4208f3a97
1 file changed
+77
+77
View File
@@ -628,3 +628,80 @@ MigrationPlan SaveMigrator::planFor(SaveVersion from, SaveVersion to) {
return plan; return plan;
} }
bool SaveMigrator::applyStep(const ByteBuffer& in, const MigrationStep& step,
MigrationResult& result, ByteBuffer& out) const {
SaveContainer container;
if (!readSaveContainer(in.data(), in.size(), container)) {
result.failure = "container is not readable at " + std::string(saveVersionName(step.from));
return false;
}
if (container.version != step.from) {
result.failure = "expected " + std::string(saveVersionName(step.from)) + " but found " +
saveVersionName(container.version);
return false;
}
for (SaveChunkRecord& record : container.chunks) {
if (step.to == SaveVersion::V2) {
std::vector<Block> palette;
std::vector<uint32_t> indices;
buildPalette(record.blocks, palette, indices);
result.paletteEntriesCreated += palette.size();
} else if (step.to == SaveVersion::V3) {
record.light = defaultChunkLight(record.blocks, skyLightForNewPlanes);
result.lightCellsInitialized += record.light.size();
} else {
record.meta = metadataDefaults;
++result.metadataRecordsCreated;
}
}
container.version = step.to;
container.compressPayloads = compressMigratedPayloads && step.to == currentSaveVersion;
out = writeSaveContainer(container);
return true;
}
MigrationResult SaveMigrator::migrate(const uint8_t* data, std::size_t size,
SaveVersion target) const {
MigrationResult result;
result.to = target;
SaveVersion from = currentSaveVersion;
if (!peekVersion(data, size, from)) {
result.failure = "save header is unreadable: bad magic, short buffer or unknown version";
return result;
}
result.from = from;
MigrationPlan plan = planFor(from, target);
if (!plan.possible) {
result.failure = plan.refusal;
return result;
}
SaveContainer source;
if (!readSaveContainer(data, size, source)) {
result.failure = "save body is unreadable at " + std::string(saveVersionName(from));
return result;
}
result.chunksMigrated = source.chunks.size();
ByteBuffer current(data, data + size);
for (const MigrationStep& step : plan.steps) {
ByteBuffer next;
if (!applyStep(current, step, result, next)) return result;
current = std::move(next);
result.applied.push_back(step);
}
result.output = std::move(current);
result.ok = true;
return result;
}
MigrationResult SaveMigrator::migrateToCurrent(const ByteBuffer& buffer) const {
return migrate(buffer.data(), buffer.size(), currentSaveVersion);
}
} // namespace vf