Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions design/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
39 changes: 21 additions & 18 deletions design/debugger.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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 |
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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.

Expand Down
3 changes: 2 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 3 additions & 4 deletions src/commands.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand All @@ -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 {
Expand Down Expand Up @@ -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 },

Expand Down
32 changes: 30 additions & 2 deletions src/debug/session.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
Loading