feat: extend SaveMigration
This commit is contained in:
1 parent
966c022003
commit
e4208f3a97
1 file changed
+77
@@ -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
|
||||||
Reference in new issue
Block a user