Repository navigation
feat: sltool dte build compiles mission source into a mission file - #1137
Merged
Merged
Conversation
The compiler reads the declarations in the file's one namespace, builds each kind's records in the order of its declarations, and compiles the code of parts and triggers through the statements model. Errors stop the build with their line and column. The shipped missions number their objects in the order their authors made them, with gaps, which the source doesn't keep. The compiler numbers the objects that last_event names first, since the script names those by a byte, then the ships, flight groups and squads. Unread fields take what most shipped records hold (the records' blank values, which mission 0 now shares), and unread sections stay empty. dte/same.zig defines the round trip's "same mission": the records and code decoded, objects by the records the game takes them for. sltool dte check decompiles each mission, builds it again, compares the two and binds the result. Every mission in the game folder comes back as the same mission. The decompiler now names objects, lists squad members and lists formation points as the game finds them, and keeps triggers, squads and formations to 100 columns. source.Symbols, the YAML plan's table, goes unused and is removed. Closes #1136
The format, the engine and the decompiler each walked a squad's members and a formation's points. The walks now live once in dte.zig (SquadMember.run, FormationPoint.Walk), which the binder and the formation orders use too. The formation walk is OpenReliant's fix of the original's, so its description says so. Mission 0 and the compiler share one string pool builder (dte.write.Strings), the executor looks a command up by name at run time next to its comptime lookup, and the decompiler writes fields and lists through one table writer. The compiler's messages take their limits from the constants they describe, such as the assembler's longest text, which is 253 bytes, not 254. The test mission now covers the layouts of a line that doesn't fit.
…d the environment effects Decompiling the shipped missions left numbers where names belong: 66 markers, most pilots, two game variables and the environment effects. - Every pilot of pilotstats.bin has a name, spelled out from its record, and the pilots past it with faces of their own, after their face films. Pilots 15 and 16 are Ivan and Nicolai Petrov, as the radio's aces are numbered by their pilots; the radio now names its aces by these names. - Types 991 to 994 are the deathmatch maps' markers. The game lists the players' spawn points, type 993, as a multiplayer game starts (multiplayer_list_spawns, now in the Ghidra names). - Variable 6 is Nicolai Petrov's alive flag, which the Dreamcast's mission 12 clears as he dies, and 35 the Red Dragon's, which brings him into mission 26. - SetEnvironmentFX takes its effect by name in mission source. Scripts see the new pilot, ship type and variable names, and make definitions wrote them into the API's docs.
The pilots' names are written by hand, while the faces table is generated from the payload, and nothing tied the two together. The test checks that each pilot whose face no earlier pilot has gets a name, and that every name is a pilot in the table, so a pilot left without a name now fails the tests.
vdmkenny
pushed a commit
that referenced
this pull request
Oct 13, 2026
🤖 I have created a release *beep* *boop* --- ## [0.13.0](v0.12.0...v0.13.0) (2026-10-13) ### Features * CANCEL stops a download on the GET MODS screen ([#1133](#1133)) ([0f7ef45](0f7ef45)), closes [#1040](#1040) * definitions of mission source for luau-lsp ([#1143](#1143)) ([3232a4b](3232a4b)), closes [#1142](#1142) * Luau's own parser reads mission source ([#1134](#1134)) ([466f5cd](466f5cd)), closes [#1132](#1132) * mission scripts read as statements and lower back to the same bytes ([#1128](#1128)) ([3e0b0e8](3e0b0e8)), closes [#1127](#1127) * OpenReliant has an icon ([#1161](#1161)) ([cb84620](cb84620)), closes [#670](#670) * releases list checksums and attest their builds ([#1158](#1158)) ([a861aaa](a861aaa)), closes [#1157](#1157) * scripts can have a missile home, as the AI's Screamers do ([#1154](#1154)) ([f8eec1e](f8eec1e)), closes [#1119](#1119) * sltool dte build compiles mission source into a mission file ([#1137](#1137)) ([6830dd2](6830dd2)), closes [#1136](#1136) * sltool dte decompile writes a mission as Luau source ([#1131](#1131)) ([38e85b5](38e85b5)), closes [#1130](#1130) * the mods screen says which installed mods have an update ([#1135](#1135)) ([a5542d6](a5542d6)), closes [#1041](#1041) * the music example replaces the main menu's piece and keeps its loop point ([#1129](#1129)) ([98a5f9a](98a5f9a)) * the reference of mission source, generated from the game's tables ([#1147](#1147)) ([e061179](e061179)), closes [#1146](#1146) * the Windows executables carry version information and a manifest ([#1156](#1156)) ([022abc2](022abc2)), closes [#1138](#1138) ### Fixes * GET MODS gives up on stalled servers, never holds up quitting, and keeps remote links off the player's machine ([#1124](#1124)) ([0d05d1e](0d05d1e)), closes [#1114](#1114) [#1069](#1069) [#1070](#1070) * the scripting API's definitions load in current luau-lsp ([#1141](#1141)) ([87fa067](87fa067)), closes [#1140](#1140) * the scripting definitions load in luau-lsp's new type solver ([#1152](#1152)) ([b049449](b049449)), closes [#1139](#1139) ### Documentation * a guide to writing missions, for beginners ([#1149](#1149)) ([04289ef](04289ef)), closes [#1148](#1148) * the mission guide shows how to change one of the game's missions ([#1151](#1151)) ([fb7d9e7](fb7d9e7)), closes [#1150](#1150) * why a trigger's code and fields aren't typed by its condition ([#1153](#1153)) ([3a08501](3a08501)), closes [#1144](#1144) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The compiler step of #1126: mission source back into a standard
.DTE, on top of the parser (#1132).formats/dte/source/compile.zig, andcompile/code.zigfor the script): declarations in the file's one namespace, each kind's records in the order of its declarations, and code through the statements model. It stops at the first error, with its line and column.last_eventnames first, since the script names those by a byte (mission 271 needs this), then ships, flight groups and squads.dte.Ship.blankand the others, which mission 0 now shares), and unread sections stay empty.sltool dte build <source> <mission>.formats/dte/same.zig): the same records and code, decoded, with objects compared by the records the game takes them for.sltool dte checkdecompiles, builds again, compares and binds. Every mission in the game folder comes back as the same mission.resolveObjects), squad members and formation points as the game walks them, and triggers, squads and formations kept to 100 columns.source.Symbols, the YAML plan's table, had no users and is removed.nicolai_petrov_alive) and 35 (red_dragon_alive), and the environment effectsSetEnvironmentFXtakes. Scripts see the new pilot, ship type and variable names;make definitionsupdated the API docs, andmultiplayer_list_spawnsjoins the Ghidra names. A test ties the hand-written pilot names to the generated faces table, so a pilot with a face of its own can't be left without a name.Left: mission 0 still fails
dte check's byte-exact statements step, as before, because its script is assembled by hand; #610 builds it from source. The.d.luau, the guide and the worked example follow in #1126.Closes #1136