Skip to content

Complete SC5/SV5 round-trip serialization and editor support in ObjectEditor - #261

Merged
LeftofZen merged 3 commits into
masterfrom
copilot/complete-serialization-deserialization
Sep 5, 2026
Merged

Complete SC5/SV5 round-trip serialization and editor support in ObjectEditor#261
LeftofZen merged 3 commits into
masterfrom
copilot/complete-serialization-deserialization

Conversation

Copilot AI commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

This updates the partial SC5/SV5 implementation to support reliable load/save round-tripping for OpenLoco map files, including packed object chunks and tile-element data. It also fills key S5 structure gaps and wires map-file editing paths needed by the editor UI.

  • S5 binary model + serializer parity

    • Completed SCV5 write-path support for packed objects (S5Header + ObjectHeader + encoded payload).
    • Preserved packed-object chunk encoding/bytes on read so unchanged files can round-trip byte-identically.
    • Added tile-element serialization (TileElement.Write) and switched save logic to emit edited tile elements when available.
    • Corrected non-scenario game-state writing to emit the correct save struct variants (GameStateSave1/GameStateSave2).
    • Removed read-time state mutation that altered fix flags and broke binary stability.
  • S5 structure correctness fixes

    • Fixed ScenarioOptions.LandDistributionPatterns to the correct array shape.
    • Corrected scenario Orders sizing to kMaxOrders.
    • Made S5Header serializable as a nested loco struct to support chunk-based object serialization paths.
  • Editor behavior

    • Enabled SC5/SV5 save/save-as flow in the SCV5 view model.
    • Updated tile-element rendering/edit surface to expose subtype/sub-structure fields for in-editor modifications.
  • Regression coverage

    • Added SC5 and SV5 round-trip tests that assert load -> save yields byte-identical output.
// Packed object write format now mirrors OpenLoco S5 layout.
foreach (var packedObject in PackedObjects)
{
    bytes.AddRange(packedObject.Header.Write().ToArray());
    bytes.AddRange(
        packedObject.RawChunk
        ?? SawyerStreamWriter.WriteChunkCore(packedObject.Data, packedObject.Encoding));
}

Copilot AI and others added 2 commits September 2, 2026 06:55
Co-authored-by: LeftofZen <7483209+LeftofZen@users.noreply.github.com>
Co-authored-by: LeftofZen <7483209+LeftofZen@users.noreply.github.com>
@LeftofZen
LeftofZen marked this pull request as ready for review September 5, 2026 13:22
Copilot AI lite review requested due to automatic review settings September 5, 2026 13:22
@LeftofZen
LeftofZen merged commit 114e649 into master Sep 5, 2026
@LeftofZen
LeftofZen deleted the copilot/complete-serialization-deserialization branch September 5, 2026 13:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are a couple of correctness issues in newly added save logic (file extension selection and packed-object header/count consistency) that can produce malformed or mis-typed output files.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR completes SC5/SV5 (S5) map-file round-trip support across the Dat serializer and the ObjectEditor UI, aiming for byte-identical load -> save output while also enabling in-editor modifications (notably tile elements and required objects).

Changes:

  • Adds packed-object read/write support that preserves original encoded chunk bytes for byte-identical round-tripping.
  • Implements tile-element serialization (TileElement.Write) and updates S5File.Write() to emit edited tile elements when present.
  • Enables SCV5 Save/Save As in the editor and adds regression tests asserting byte-identical output for SC5/SV5.
File summaries
File Description
Tests/SCV5SerializationTests.cs Adds round-trip tests for SC5/SV5 asserting byte-identical load -> save.
Gui/Views/MainWindow.axaml Switches the TileElement editor template to a PropertyGrid-based editor.
Gui/ViewModels/Loco/SCV5ViewModel.cs Enables Save/Save As for SCV5 files and wires saving through S5File.Write().
Dat/Types/SCV5/TileElement.cs Preserves the raw type byte and adds Write() for tile-element serialization.
Dat/Types/SCV5/ScenarioOptions.cs Fixes LandDistributionPatterns to the correct array shape.
Dat/Types/SCV5/S5File.cs Implements packed-object chunk round-tripping, correct save-variant writing, and tile-element emission.
Dat/Types/SCV5/GameStateSave1.cs Fixes Orders array sizing to kMaxOrders.
Dat/Types/S5Header.cs Makes S5Header an ILocoStruct to support nested struct serialization paths.
Review details
  • Files reviewed: 8/8 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Dat/Types/SCV5/S5File.cs
Comment on lines 82 to +86
// packed
ReadOnlySpan<byte> packed = [];
byte[] packed = [];
if (Header.NumPackedObjects != 0)
{
// todo: add data here
// todo: copy ObjectManager::writePackedObjects
//packed = WritePackedObjects();
packed = WritePackedObjects();
Comment thread Dat/Types/SCV5/S5File.cs
Comment on lines +245 to +246
static byte[] SerializeTileElements(IEnumerable<TileElement> tileElements)
=> tileElements.SelectMany(x => x.Write()).ToArray();
Comment on lines 315 to +319
public override void Save()
=> Logger.LogWarning("Save is not currently implemented");
{
var savePath = CurrentFile.FileLocation == FileLocation.Local
? CurrentFile.FileName
: Path.Combine(EditorContext.Settings.DownloadFolder, Path.ChangeExtension($"{CurrentFile.DisplayName}-{CurrentFile.Id}", ".sv5"));
public const uint8_t FLAG_LAST = 1 << 7;

public ElementType Type { get; set; }
public uint8_t TypeByte { get; set; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants