From d185b0c6c2b7769dbbd17258fe41e6046dc20fb7 Mon Sep 17 00:00:00 2001 From: Kenny Van de Maele Date: Thu, 15 Oct 2026 09:02:53 +0200 Subject: [PATCH] fix: OpenReliant 0.16.0 links without a protocol failure OpenReliant 0.16.0 raises the link's protocol to 2, which only adds messages and keys. The editor noted any protocol other than its own as a failure; it now notes only an older game's, and says to update OpenReliant. The design and the docs now say what OpenReliant 0.16.0 gives the editor: the live scene from Mission file and State, the timeline from State's events, the console from Console line and the game's log, and playing a mod on its own with --mods. Reload scripts and Play with this mod only pointed at OpenReliant issues that are now done; they point at Mod mode, where the editor's side of them belongs. --- design/README.md | 25 +++++++++++++++++++------ design/debugger.md | 39 +++++++++++++++++++++------------------ docs/architecture.md | 3 ++- src/commands.zig | 7 +++---- src/debug/session.zig | 32 ++++++++++++++++++++++++++++++-- 5 files changed, 75 insertions(+), 31 deletions(-) diff --git a/design/README.md b/design/README.md index e595f4e..b0706ca 100644 --- a/design/README.md +++ b/design/README.md @@ -206,14 +206,27 @@ make it in. | Icons | Lucide, through IconFontCppHeaders | | Blocks | ImGui's draw lists and drag and drop | -## What the screens need from OpenReliant +## What the screens use from OpenReliant + +The screens talk to the game over OpenReliant's editor link +([The editor link](https://github.com/OpenReliant/openreliant/blob/main/docs/engine/editor-link.md)), +and start it with its options. From OpenReliant 0.16.0, the link carries what the live scene, the +timeline and the console need: + +| Screen | From OpenReliant | +|---|---| +| The live scene, and the Scene view's ships where they are now | `Mission file`, which the editor asks for with `Get mission`: the game keeps each ship's place and heading in the mission's records, and marks a destroyed ship. `State` gives each ship's order and target | +| The Debugging screen's timeline | `State`: the triggers fired and the commands run since the last state, each with its time on the script's clock. The holds are the editor's own | +| The Code view's console | `Console line` runs a line in the game's console, and the answers come from the game's log, `openreliant.log`. The console needs `--developer-mode` and a mod with scripts | +| Reload scripts | The console line `reload`. With `--developer-mode`, a folder mod's scripts also reload when they're saved | +| Play with this mod only, and trying a packed `.hog` | `--mods` with the mod's folder or `.hog` | + +The Share view's export for the catalogue is the editor's own work. + +Still to come in OpenReliant: -- The live scene: [#1059](https://github.com/OpenReliant/openreliant/issues/1059) - The editor's live changes to the mission: [#1057](https://github.com/OpenReliant/openreliant/issues/1057) -- Playing a mission from a part: [#577](https://github.com/OpenReliant/openreliant/issues/577) -- The game's console and reloading mods' scripts: [#1201](https://github.com/OpenReliant/openreliant/issues/1201) -- Starting with a chosen set of mods: [#1202](https://github.com/OpenReliant/openreliant/issues/1202) -- Exporting a mod for the catalogue: [#1203](https://github.com/OpenReliant/openreliant/issues/1203) +- Playing from a part with the variables the earlier parts set: [#577](https://github.com/OpenReliant/openreliant/issues/577) ## Changing the design diff --git a/design/debugger.md b/design/debugger.md index 2523c4b..a44c8b2 100644 --- a/design/debugger.md +++ b/design/debugger.md @@ -20,8 +20,8 @@ it fills are [Script](README.md#script), held at a breakpoint, and [Debugging](R - **Shows the script listing beside the source**, with the held instruction and the breakpoints in both. -Later, as OpenReliant carries them: a timeline of the run, the live scene, and live changes, which -send each build into the running game. +Later: a timeline of the run and the live scene, which OpenReliant carries from 0.16.0, and live +changes, which send each build into the running game once OpenReliant takes them. ## The link @@ -39,7 +39,8 @@ its library exports, so the two can't drift apart. | `0x09` Script flags | Editor | A byte for each byte of the script, bit 0 set where it stops | Sent for each attempt at the mission, and as breakpoints change | | `0x1A` Stopped | Game | The offset in the script of the byte it stopped before | Holds: the line, then the state | | `0x105` Get state | Editor | | Sent on each hold, and for watches while the script runs | -| `0x106` State | Game | The script's clock, hold, step and pause, threads, globals and variables | Fills Threads, Variables, Watch and the values shown inline | +| `0x106` State | Game | The script's clock, hold, step and pause, threads, globals and variables. From OpenReliant 0.16.0, also each ship's order and target, and the triggers fired and the commands run since the last state | Fills Threads, Variables, Watch, the values shown inline, the timeline, and the live scene's orders | +| `0x103` Get mission | Editor | | Sent for the live scene, a few times a second while it shows. Only the file that comes with `Mission started` is answered with the flags | | `0x15` Run control | Editor | Pause or go on, run on, step into, step over, run a part | Continue, the steps, Pause | | `0x1B` First finished | Game | Whether the start parts' first thread has finished | Says when the start parts are done | | `0x102` Mission ended | Game | | Says no mission plays, and keeps the link | @@ -175,7 +176,9 @@ timeline under them. The listing marks the held instruction and the breakpoints' on a line of either side selects its counterpart in the other. Its own gutter sets breakpoints by offset. `@@` and an offset in the command palette goes to the offset's line. -The timeline waits for the game's events (below), and shows a note until then. +The timeline has a row each for the triggers fired, the commands run and the holds, on the script's +clock. Each state gives the triggers and commands since the one before; the holds are the editor's +own. ### Settings: Editor link @@ -212,17 +215,17 @@ StarLancer's offsets or opcodes: kind; - the names of the state's globals, from the outline. -## What OpenReliant needs +## What OpenReliant gives -| Need | For | Issue | +| What | For | In OpenReliant | |---|---|---| -| The compiler's map of source lines to the script's statements, from its library | Line breakpoints, the held line, the listing's lines | [#1206](https://github.com/OpenReliant/openreliant/issues/1206) | -| The link's text payloads read into records in its library, which `openreliant debug` reads them with now | The editor and `openreliant debug` reading them alike | [#1206](https://github.com/OpenReliant/openreliant/issues/1206) | -| The start of a mission waiting for the editor's flags, rather than for a fifth of a second | Breakpoints in the start parts, on a slow computer too | [#1206](https://github.com/OpenReliant/openreliant/issues/1206) | -| The script's events: a trigger firing, a part starting, a command running, a hold | The timeline | [#1207](https://github.com/OpenReliant/openreliant/issues/1207) | -| The live scene | The Live scene panel, the inspector's Live section, watches of ranges | [#1059](https://github.com/OpenReliant/openreliant/issues/1059) | -| The editor's live changes to the mission | Live changes, the status bar's switch | [#1057](https://github.com/OpenReliant/openreliant/issues/1057) | -| Starting a mission partway through | Play from part, linked | [#577](https://github.com/OpenReliant/openreliant/issues/577) | +| The compiler's map of source lines to the script's statements, from its library | Line breakpoints, the held line, the listing's lines | 0.15.0 ([#1206](https://github.com/OpenReliant/openreliant/issues/1206)) | +| The link's text payloads read into records in its library, which `openreliant debug` reads them with too | The editor and `openreliant debug` reading them alike | 0.15.0 ([#1206](https://github.com/OpenReliant/openreliant/issues/1206)) | +| The start of a mission waiting for the editor's flags, rather than for a fifth of a second | Breakpoints in the start parts, on a slow computer too | 0.15.0 ([#1206](https://github.com/OpenReliant/openreliant/issues/1206)) | +| The script's events in `State`: the triggers fired and the commands run | The timeline | 0.16.0 ([#1207](https://github.com/OpenReliant/openreliant/issues/1207)) | +| Each ship's place and heading in `Mission file`, kept up to date every frame, and its order and target in `State` | The Live scene panel, the inspector's Live section, watches of ranges | 0.16.0 ([#1059](https://github.com/OpenReliant/openreliant/issues/1059)) | +| The editor's live changes to the mission | Live changes, the status bar's switch | Not yet ([#1057](https://github.com/OpenReliant/openreliant/issues/1057)) | +| Starting a mission partway through, with the variables the earlier parts set | The `earlier parts` box of Play from part | Not yet ([#577](https://github.com/OpenReliant/openreliant/issues/577)) | The compiler keeps each statement's place in the source until the script is written, and writes down the offset of the instruction the VM stops before. The start's wait is an improvement on the @@ -241,11 +244,11 @@ Each stage is a release of its own, with OpenReliant's part merged first. Conditions, hit counts, log points, breakpoints by offset and the kinds of entry, the breakpoint's editor, Watch, the values shown inline, the Debugging screen with the listing beside the source, and `@@` offsets in the palette. -3. **The timeline** ([#20](https://github.com/OpenReliant/openreliant-editor/issues/20)), once - OpenReliant sends the script's events. -4. **The live scene** ([#21](https://github.com/OpenReliant/openreliant-editor/issues/21)), once - OpenReliant carries it: the Live scene panel, the inspector's Live section, watches of ranges, - and the Scene view's ships where they are now in the game. +3. **The timeline** ([#20](https://github.com/OpenReliant/openreliant-editor/issues/20)), from the + script's events in OpenReliant 0.16.0's `State`. +4. **The live scene** ([#21](https://github.com/OpenReliant/openreliant-editor/issues/21)), from + OpenReliant 0.16.0's `Mission file` and `State`: the Live scene panel, the inspector's Live + section, watches of ranges, and the Scene view's ships where they are now in the game. 5. **Live changes** ([#22](https://github.com/OpenReliant/openreliant-editor/issues/22)), once OpenReliant takes them: each build sent into the running game, with the status bar's switch. diff --git a/docs/architecture.md b/docs/architecture.md index bdf7fa3..c06f102 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -81,7 +81,8 @@ Each shows in the interface, greyed out, with its issue: - the Scene view ([#2](https://github.com/OpenReliant/openreliant-editor/issues/2)) and the Blocks view ([#3](https://github.com/OpenReliant/openreliant-editor/issues/3)); -- Mod mode ([#4](https://github.com/OpenReliant/openreliant-editor/issues/4)); +- Mod mode, with Reload scripts and Play with this mod only + ([#4](https://github.com/OpenReliant/openreliant-editor/issues/4)); - the debugger's conditions, log points, Watch, values inline and Debugging screen ([#19](https://github.com/OpenReliant/openreliant-editor/issues/19)), its timeline ([#20](https://github.com/OpenReliant/openreliant-editor/issues/20)), the live scene diff --git a/src/commands.zig b/src/commands.zig index 5f9ca7e..7f366f3 100644 --- a/src/commands.zig +++ b/src/commands.zig @@ -195,6 +195,7 @@ fn defaults(comptime windows_linux: []const []const u8, comptime macos: []const pub const plans = struct { pub const scene: Plan = .{ .issue = 2 }; pub const blocks: Plan = .{ .issue = 3 }; + /// Mod mode's views, Reload scripts, and Play with this mod only. pub const mod_mode: Plan = .{ .issue = 4 }; /// Conditions, log points, Watch, the values inline, the Debugging screen and offsets. pub const watches: Plan = .{ .issue = 19 }; @@ -207,8 +208,6 @@ pub const plans = struct { pub const settings: Plan = .{ .issue = 10 }; pub const live_scene: Plan = .{ .issue = 21 }; pub const play_from_part: Plan = .{ .issue = 577, .repository = .openreliant }; - pub const chosen_mods: Plan = .{ .issue = 1202, .repository = .openreliant }; - pub const reload_scripts: Plan = .{ .issue = 1201, .repository = .openreliant }; }; pub fn info(command: Command) Info { @@ -265,8 +264,8 @@ pub fn info(command: Command) Info { .play => .{ .label = "Play in game", .icon = .play, .when = .not_held, .keys = defaults(&.{"F5"}, &.{"Cmd+R"}), .key_group = .build_and_play }, .play_from_part => .{ .label = "Play from part…", .icon = .play, .keys = defaults(&.{"Ctrl+F5"}, &.{"Ctrl+Cmd+R"}), .key_group = .build_and_play }, - .play_mod_only => .{ .label = "Play with this mod only", .icon = .play, .planned = plans.chosen_mods }, - .reload_scripts => .{ .label = "Reload scripts", .icon = .refresh_cw, .keys = defaults(&.{"Ctrl+R"}, &.{"Cmd+Shift+R"}), .key_group = .build_and_play, .planned = plans.reload_scripts }, + .play_mod_only => .{ .label = "Play with this mod only", .icon = .play, .planned = plans.mod_mode }, + .reload_scripts => .{ .label = "Reload scripts", .icon = .refresh_cw, .keys = defaults(&.{"Ctrl+R"}, &.{"Cmd+Shift+R"}), .key_group = .build_and_play, .planned = plans.mod_mode }, .link => .{ .label = "Link to game", .icon = .cable }, .game_settings => .{ .label = "Game settings", .icon = .sliders_horizontal }, diff --git a/src/debug/session.zig b/src/debug/session.zig index c047517..a98c0c4 100644 --- a/src/debug/session.zig +++ b/src/debug/session.zig @@ -260,8 +260,10 @@ pub const Session = struct { session.note(.failure, "No profile for {s} · unlinked", .{hello.game.name}); return session.closeLink(); } - if (hello.protocol != link.protocol_version) { - session.note(.failure, "Link protocol {d}, editor's {d}", .{ hello.protocol, link.protocol_version }); + // Each version of the protocol only adds messages and keys, which a reader passes over, so + // a newer game links as it is. An older one lacks what the editor reads. + if (hello.protocol < link.protocol_version) { + session.note(.failure, "Link protocol {d}, editor's {d} · update OpenReliant", .{ hello.protocol, link.protocol_version }); } const text = std.mem.concat(session.gpa, u8, &.{ hello.game.name, hello.game.vm, hello.openreliant }) catch return; const vm_end = hello.game.name.len + hello.game.vm.len; @@ -755,6 +757,32 @@ test "the editor answers a mission it has no build of with no flags" { session.freeNotes(); } +test "a newer game links quietly, and an older one says to update" { + const gpa = std.testing.allocator; + const io = std.testing.io; + for ([_]struct { protocol: u32, failures: usize }{ + .{ .protocol = link.protocol_version + 1, .failures = 0 }, + .{ .protocol = link.protocol_version - 1, .failures = 1 }, + }) |case| { + var fake: FakeGame = try .listen(io); + defer fake.deinit(); + var session: Session = .init(gpa, io, &game.starlancer.profile, connection_mod.testing.noWake); + defer session.deinit(); + session.connect(fake.port(), .waiting); + try fake.accept(); + try fake.sendRecord(.hello, link.Hello{ .protocol = case.protocol, .openreliant = "9.9.9", .game = .{ .name = "StarLancer", .vm = "starlancer" } }); + try settle(&session, io, struct { + fn done(s: *const Session) bool { + return s.link_state == .linked; + } + }.done); + var failures: usize = 0; + for (session.takeNotes()) |note| failures += @intFromBool(note.kind == .failure); + try std.testing.expectEqual(case.failures, failures); + session.freeNotes(); + } +} + test "a game that isn't there: the editor gives up" { const gpa = std.testing.allocator; const io = std.testing.io;