Repository navigation
[3/9] Move ownership into features and share Unity helpers - #3
Open
friendly-ripper wants to merge 24 commits into
Open
friendly-ripper wants to merge 24 commits into
friendly-ripper wants to merge 24 commits into
Conversation
added 24 commits
October 15, 2026 16:40
File becomes a namespace that parses the command line once instead of a class re-checking an init flag in every accessor. Path joining and legacy-file migration move with it, and the settings reader shrinks to reading values through one small reader type. Parsing the command line once fixes -debug and -trace being ignored as last arguments and a doubled directory for -ccm paths on macOS. The macOS Library path is copied before its autorelease pool can free it. Window state and UI scale handlers move to the files that use them.
About 120 single-class headers under prime become ten headers split by what they model: chat, fleet, inventory, navigation, server, UI, Unity, viewers and a few more. Binding bodies are unchanged; only includes move, and bindings nobody used are gone. String-view trimming now respects explicit lengths, so a trimmed ship name no longer keeps trailing text.
Keyboard and mouse state move into an input module cached per frame, keyed on the frame count instead of an explicit reset from the hotkey hook. Shortcuts gain one settings table with defaults, tiers and deprecated aliases. The shortcut tests link the production code against a fake input and run on any host. Per-frame feature updates now run whatever the hotkey mode, instead of only when the hotkey patch happened to be installed.
The hotkey file held the frame tick, a long dispatch chain and the fleet state machine in about 1500 lines. Dispatch, fleet actions and keybind badges are separate files now, with the same check order and the same keys swallowed. Navigation helpers return quietly when no section manager exists yet, as before login and during reloads, instead of dereferencing a null pointer.
Every entity group and realtime slot message used to start its own detached thread, so a delta could be applied before the full list. One thread now handles messages in arrival order, and each queue drops its oldest entry when full. Server timestamps parse without local-time conversion, and name caches overwrite stale entries, stay bounded and parse profiles one at a time so one bad record keeps the rest.
Toast queue hooks, Windows notification mirroring and battle result formatting served one feature from three files with duplicated guards. They are one file now, and the three loading screens share one implementation with explicit per-screen state instead of globals reset across files. Text formatting lives in a tested header. After a padded placeholder is filled, the next search continues after the inserted text instead of rescanning it.
The warp label lived in its own file and reached back into the confirmation code through a two-function header. Both are one feature now, and the resolver is private to the file. Cargo formatting merges the same way: both hooks looked for the same label and each carried its own clamp and string comparison, which now lives on the text binding.
The feature list becomes one table of name, install function and patch-group member, and logging setup and the startup banner leave the init hook for their own functions. Order, names and toggles are unchanged. Early setup runs before the logger exists, so its failures go to stderr where they can be seen. A failed executable-path lookup is reported instead of ignored.
Fleet labels were a widget map plus loose globals mutated from seven hooks. One owner type now tracks the widget lifecycle and answers depth, zoom and level questions, and the per-fleet switch collapses to player versus everyone else, which is what it already did. A preset of 0 no longer overwrites the default system zoom, and the zoom-to-default flag is cleared on frames that store a preset.
The roster and assignment comparators differed only in which below-deck predicate they chained and the sign of the index tiebreaker. One template takes both, and the delegate wiring still picks the same four combinations.
Config held about 130 flat fields whose names had drifted from the TOML keys, with defaults declared a second time elsewhere. Each section is now a struct whose members are named after their keys and carry their defaults. Keys, defaults and vars output are unchanged. Shortcut defaults live with the shortcut table, the only place they were used.
The frame tick checks the settings file once a second and reloads only after a change has held for a whole check, so a half-written file cannot reset everything to defaults. A reload parses first and keeps the current settings on failure. Replaced settings are never freed, because sync threads may still read them. Patch groups are decided at startup, so a change to them logs that it waits for a restart.
The per-frame toggle work gets one owner with plainly named state, and the tick returns early when the toggle default is off instead of relying on the hook not being installed. The dailies filter logs one summary line instead of one line per daily on every refresh, and a faction name is lower-cased once where it is read.
Unity liveness, placement and text helpers that several features each spelled out move into the shared Unity binding header, and feature files call that one copy. Bindings nothing used are removed. A stale binding is a member that can drift unnoticed, so the surface stays at what features actually call.
Ship-name matching splits from the game localisation call so its text half can be tested without the game. Warp, pinned ships and the window code share the one matcher. Pinned ship sorting warns once per unmatched entry instead of on every dock sort, and the window hook runs the original update unless free resizing is on.
The timer resolves its view and its drawer from the canvases the screen manager has registered for them while in system navigation, instead of searching globally from loose globals mutated by hooks. One owner holds the state. The label rebuilds only when the displayed second changes.
Hooks install in named groups, so a feature can be switched as one unit and a failure in early setup stays contained instead of stopping the features after it. Hooks install even when their setting starts disabled, and each hook reads the current switch at call time. The object tracker takes its lock when reading and tolerates repeat tracking, so a pooled object is neither lost nor double-counted.
The donation fix raised any slider whose maximum was 50 or 100 on one platform and a different hook on the other, so a use-items popup could offer the donation cap. Both platforms now adjust the popup context where its row renders: only donation popups, and never more than the player owns. Server address overrides are read once instead of on every call they affect.
Every key query used to ask Unity for the frame number, so an idle frame made about 190 input calls. Hooks that read keys now poll once, and with nothing held no key is asked about at all. A key claimed by a modified binding stays claimed until release, which stops a modified chord decaying into the plain key. Dock assignment fires once per Enter press, not per frame while held.
Entering a system while typing lost the jump to the default system zoom, because the flag was cleared every update but only keyboard zoom consumed it. The jump now happens in the camera update whether or not a field has focus. Each flat renderable remembers the size it was scaled to. Sharing one value made two planets of different sizes rescale each other on every zoom. The pan hook also moved the camera twice in a frame; a frame now moves by keys or by glide, not both.
Every login and transition decoded the background and logos again, about 4 MB per screen. Assets now stay while Unity reports them alive and decode again only after an unload. Sprites size from the loaded texture instead of a hand-parsed PNG header, so a JPG loader image no longer gets a cropped sprite rect. The forced black-background value is recorded before the vars file is written, so the file shows the value actually used.
A game login resets the sent state through the processing queue, in order. An account or server switch is no longer diffed against the previous account, which skipped the first full upload and reported old jobs as completed. Record processors and their routing table move out of the game hooks into their own file. Server JSON reads go through checked lookups instead of indexing const values, which was undefined for missing keys, and each record is read in full before anything is marked as sent.
The chat preview forced alliance chat on every panel change when a channel was disabled, so other chats could not be reached. It now moves only when opening on, or swiping onto, a disabled channel, and reads the setting per call. Mission HUD updates read the active setting instead of visibility kept from install time, so reloads take effect without reinstalling hooks.
Unity engine, UI, TextMeshPro and input types move out of the game folder into a Unity library, with the instance tracker that used to be mod code. Features call library helpers for strings, boxing and allocation instead of the raw runtime API. Every feature exports a descriptor with its patch group, install function and frame work: - mod.cc owns install order and the frame tick, which watches the settings file and runs installed features only. - The old per-mod object tracker, key code and Unity header are gone; tracked classes are listed with the features. - The binding checker now scans the library sources too. Keybind badges count as installed only when both detours went in. A feature with no hooks still gets a descriptor, so frame work never depends on a hook group.
friendly-ripper
force-pushed
the
stack/03-runtime-refactor
branch
from
October 18, 2026 18:49
18c2448 to
cb36809
Compare
friendly-ripper
force-pushed
the
stack/03-runtime-refactor
branch
2 times, most recently
from
October 19, 2026 22:19
395f491 to
8e49f94
Compare
friendly-ripper
force-pushed
the
stack/03-runtime-refactor
branch
2 times, most recently
from
October 21, 2026 21:39
4c0ce12 to
bd49c49
Compare
friendly-ripper
force-pushed
the
stack/03-runtime-refactor
branch
from
October 21, 2026 23:46
bd49c49 to
6cc2c47
Compare
friendly-ripper
force-pushed
the
stack/03-runtime-refactor
branch
from
October 22, 2026 00:43
6cc2c47 to
5f1b378
Compare
friendly-ripper
force-pushed
the
stack/03-runtime-refactor
branch
from
October 22, 2026 02:44
5f1b378 to
a4602c7
Compare
friendly-ripper
force-pushed
the
stack/03-runtime-refactor
branch
from
October 24, 2026 23:26
a4602c7 to
c291d43
Compare
friendly-ripper
force-pushed
the
stack/03-runtime-refactor
branch
from
October 25, 2026 01:36
c291d43 to
6080e77
Compare
friendly-ripper
force-pushed
the
stack/03-runtime-refactor
branch
from
October 28, 2026 18:15
6080e77 to
6cfe2b0
Compare
friendly-ripper
force-pushed
the
stack/03-runtime-refactor
branch
from
November 2, 2026 14:23
6cfe2b0 to
5758a3f
Compare
friendly-ripper
force-pushed
the
stack/03-runtime-refactor
branch
from
November 12, 2026 21:50
5758a3f to
9bb115a
Compare
friendly-ripper
force-pushed
the
stack/03-runtime-refactor
branch
from
November 13, 2026 15:17
9bb115a to
bde2809
Compare
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.
Part 3 of 9 · base
stack/02-il2cpp· 24 commitsFeature code, game bindings, and runtime helpers were tangled together. One hotkey file held the frame tick and the fleet state machine. Settings were a flat list of fields, and sync work ran on detached threads. This PR gives each feature ownership of its hooks, shortcuts, and state. Shared access moves into the IL2CPP and Unity libraries. The runtime fixes that this exposed land in the same stack.
What changes
Bindings and shared helpers:
primecollapse into ten domain headers (chat, fleet, inventory, navigation, server, UI, Unity, viewers, and a few more). Unused bindings are removed; binding bodies otherwise move unchanged.Settings, input, and installation:
Configheld about 130 flat fields whose names had drifted from their TOML keys, with defaults declared a second time elsewhere. Each TOML section is now a struct whose members are named after their keys and carry their defaults. Keys, defaults, and vars output are unchanged.Filebecomes a namespace that parses the command line once. Path joining and legacy-file migration move with it, and window state and UI scale handlers move to the files that use them.Sync:
Feature consolidation:
Behavior changes
[patches]groups, which still need one.-debugand-tracework as last arguments, and-ccmpaths on macOS no longer get a doubled directory.Testing
Built with xmake. Every commit was built on macOS arm64. Nothing was run in the game.