Skip to content

[9/10] Align code with AGENTS.md conventions - #372

Merged
netniV merged 13 commits into
refactor/08-zig-buildfrom
refactor/09-alignment
Nov 14, 2026
Merged

netniV merged 13 commits into
refactor/08-zig-buildfrom
refactor/09-alignment

Conversation

@friendly-ripper

Copy link
Copy Markdown
Collaborator

Part 9 of 10 · base refactor/08-zig-build · 13 commits

Earlier PRs set the shape in AGENTS.md: detours owned by the IL2CPP library, one layout per feature file, settings read section by section. Parts of the tree still predate those rules, sync retries can spin forever, and the build only works on Zig 0.16. This PR brings the code in line and moves the build to Zig 0.17 as well.

What changes

Hooks and libraries:

  • Detours, checked lookups, and failure reporting move into the IL2CPP library. The old hook macros are gone. Every installer stages its hooks in one il2cpp::HookSet named after its feature and returns whether the set went in. A set applies under one suspend window and undoes itself if any step fails, so a feature installs whole or not at all.
  • Hooks two features share get their own set, committed once. Installers no longer pre-check members. A missing method is reported by the lookup and keeps the whole set out. Frame work runs only for installed features, and mod.cc logs each feature as installed, skipped, or not installed.
  • Unity bindings list accessors, calls, and statics in one order. Behaviour active checks go through the managed getter resolved once, instead of an internal call newer Unity builds no longer register. The instance tracker starts once. Input snapshots cache held and down reads, including negative results.
  • Game bindings get the same layout. Class, fields, and properties come first, with each setter beside its getter, then calls, composed helpers, and statics. Accessors are named after the managed member they read. Classes that are only hooked stay bare aliases. Game lists work with standard algorithms, null collections read as empty, and a bad index reads as zero. Dead accessors are removed.

Settings and shortcuts:

  • Each TOML section is read together through one validation helper that keeps the default on bad input. Rejected, renamed, and retired values are reported in one format, and the startup dump of effective settings to stdout is gone. Notification cue names parse like other setting choices, so the settings header no longer depends on the playback feature.
  • Shortcut problems are reported with the same wording and severity as other settings; only a broken built-in default is an error. Shortcut matching spells out the plain and modified cases, and dispatch runs under the same guard as other frame work so an exception cannot unwind into the game.

Features, written plainly:

  • Camera, Haven, UI scale, loading, window, anomaly, and mission features, then screen, dock, chat, shop, toast, and fleet features, walk game collections through shared helpers instead of hand-written null and bounds checks. Zoom units, Haven blend weights, and the DPI factor now say what they compute and why. File-scope names carry their feature name, since macOS release builds compile four feature files per translation unit. Behaviour is unchanged, including float NaN handling.
  • Shared queue fixes read queues through typed bindings instead of fixed offsets, and check every member whose default would change a decision before installing.

Sync, startup, and launcher:

  • A battle journal the server will not return retried every second forever and stalled the journals behind it. It now retries with a doubling wait, capped, for about four minutes, then drops. Every category is stored and filtered per target at delivery, so a target switched on by a reload receives data without waiting for the next login.
  • Both games discard stderr, so early startup failures went nowhere. Startup now reports through debugger output on Windows and the system log on macOS before the log exists. The log and the custom loading image open by their UTF-8 names on Windows, and a negative child count reads as no children.
  • The launcher no longer force-unwraps loader paths, update plan attributes, or the installed version; failures carry readable descriptions, entitlement repair signs the bundle the user actually selected, and a double click can no longer start two updates.

Build and docs:

  • Embedded images resolve from the repository root, so the build works from any directory. The macOS deployment target is one constant feeding Swift, assets, and packaging; macOS packaging goes through one script shared by CI and the development helper; CI runs the native tests on Windows and macOS plus a Linux job for the SDK-free fixtures.
  • The agent guide, contributor docs, and IL2CPP reference now state the shape every feature file follows, how hooks install and what the library reports, and how bindings are laid out.
  • The build graph works on Zig 0.17 as well as 0.16. One compat file, zig/compat.zig, holds the differences in configure behaviour, renamed options, and moved fields, and files the build reads while configuring are declared as configure dependencies.

Behavior changes

  • Settings and shortcut problems are reported in one format, and the effective-settings dump to stdout at startup is gone.
  • A battle journal the server will not return is dropped after about four minutes of capped, doubling retries instead of retrying every second forever. A sync target switched on by a settings reload now receives data without waiting for the next login.
  • Early startup failures are visible in debugger output on Windows and the system log on macOS, where before they were written to a stderr both games discard.
  • The macOS launcher reports loader and update failures with a readable message instead of crashing, and a double click no longer starts two updates at once.

Testing

Every commit passes zig build test-il2cpp test-mod test-sync on Zig 0.16, cross-builds the Windows mods with -Dtarget=x86_64-windows-msvc, and builds the macOS mods with -Dtarget=aarch64-macos.14.6. The last commit also passes the tests on Zig 0.17. Nothing was run in the game.

tashcan added 13 commits October 22, 2026 15:00
Each TOML section is read together through one validation
helper that keeps the default on bad input. Rejected, renamed
and retired values are reported in one format, and the startup
dump of effective settings to stdout is gone.

Notification cue names parse like other setting choices, so
the settings header no longer depends on the playback feature.
Invalid and deprecated shortcut values use the same wording
and severity as other settings; only a broken built-in default
is an error.

Shortcut matching spells out the plain and modified cases
instead of one dense conditional, and dispatch runs under the
same guard as other frame work so an exception cannot unwind
into the game.
Detours, checked lookups and failure reporting move into the
IL2CPP library. The old hook macros are gone, so every caller
moves to hook sets in the same change: a set applies under one
suspend window and undoes itself if any step fails, so a
feature installs whole or not at all.

- Each installer stages its hooks in one set named after its
  feature and returns whether the set went in.
- Hooks two features share get their own set, committed once.
- A missing method is reported by the lookup and keeps the
  whole set out; installers no longer pre-check members.
- The tracker installs each constructor with its release hook,
  so a pooled object is never tracked without its untrack path.

Frame work runs only for features whose set went in, and
mod.cc logs each feature as installed, skipped or not
installed. Static lookups no longer run a class constructor
early.
Both games discard stderr, so early startup failures went
nowhere. Startup now reports through debugger output on
Windows and the system log on macOS before the log exists.

The log and custom loading image open by their UTF-8 names on
Windows instead of through the ANSI code page, and the file
sink takes the wide name directly. A negative child count
reads as no children.
Camera, Haven, UI scale, loading, window, anomaly and mission
features walk game collections through shared helpers instead
of hand-written null and bounds checks. Zoom units, Haven blend
weights and the DPI factor now say what they compute and why.

File-scope names carry their feature name, since macOS release
builds compile four feature files per translation unit.
Behaviour is unchanged, including float NaN handling.
Unity bindings list accessors, calls and statics in one order,
and behaviour active checks go through the managed getter
resolved once, instead of an internal call newer Unity builds
no longer register.

The instance tracker starts once and its add and remove steps
live on the registry they guard. Input snapshots cache held
and down reads, including negative results.
Each binding reads class, fields and properties with each
setter beside its getter, then calls, composed helpers and
statics. Accessors are named after the managed member they
read, and classes that are only hooked stay bare aliases.

Game lists satisfy forward iterator requirements and work with
standard algorithms. Null collections read as empty and a bad
index reads as zero, replacing repeated caller checks. Dead
accessors are removed.
A battle journal the server will not return retried every
second forever and stalled the journals behind it. It now
retries with a doubling wait, capped, for about four minutes,
then drops.

Every category is stored and filtered per target at delivery,
so a target switched on by a reload receives data without
waiting for the next login. Sync bodies move to plainer
statements and shared helpers; wire output and threading are
unchanged.
Screen, dock, chat, shop, toast and fleet features move to
plainer statements and shared helpers for transform children,
vector scaling, the fleet bar panel and on-screen views. Index
loops and repeated null checks give way to the shared
collection helpers.

Shared queue fixes read queues through typed bindings instead
of fixed offsets, and check every member whose default would
change a decision before installing. Behaviour, settings and
log lines are unchanged.
The launcher no longer force-unwraps loader paths, update plan
attributes or the installed version. Failures carry readable
descriptions, and entitlement repair signs the bundle the user
actually selected.

Loader failures fail with a message instead of a crash, a
double click can no longer start two updates, and dead helpers
and the moot macOS 13 check are gone.
Embedded images resolve from the repository root, so the build
works from any directory. The macOS deployment target is one
constant feeding Swift, assets and packaging.

macOS packaging goes through one script shared by CI and the
development helper, and CI runs the native tests on Windows and
macOS plus a Linux job for the SDK-free fixtures. Build tools
name the binary fields behind their offsets and document their
arguments.
The agent guide, contributor docs and IL2CPP reference now
state the shape every feature file follows, how hooks install
and what the library reports, and how bindings are laid out.
One-off feature guides fold into the feature list.

Docs describe the shipped contracts only; no code changes.
The build graph works on Zig 0.17 as well as 0.16. One compat
file holds the differences in configure behaviour, renamed
options and moved fields, so dropping 0.16 later means inlining
one side of it.

Files the build reads while configuring are declared as
configure dependencies, so a new source file still triggers
reconfiguration.
@netniV
netniV added this pull request to the merge queue Nov 14, 2026
Merged via the queue into dev with commit a22b2ed Nov 14, 2026
7 of 8 checks passed
@netniV
netniV deleted the refactor/09-alignment branch November 14, 2026 00:06
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.

2 participants