From 1fb1f940cec6e16d1a54282a04508379bf777a26 Mon Sep 17 00:00:00 2001 From: tashcan Date: Thu, 15 Oct 2026 16:40:43 -0700 Subject: [PATCH 1/2] Rewrite install guides around feature settings User guides split into installation, feature reference and keyboard mappings. Defaults, reload behaviour and hook-group switches are described without mixing contributor build detail into user instructions. --- README.md | 171 +++---------------- docs/DAILY_FACTION_BULK_CLAIM.md | 2 +- docs/FEATURES.md | 285 ++++++++++++------------------- docs/INSTALL.md | 281 ++++++++++-------------------- docs/KEYMAPPING.md | 261 ++++++++++++++++++---------- 5 files changed, 393 insertions(+), 607 deletions(-) diff --git a/README.md b/README.md index f6856b3b1..95c4fce80 100644 --- a/README.md +++ b/README.md @@ -1,155 +1,40 @@ -# Star Trek Fleet Command - Community Mod - -## IMPORTANT NOTE: - -The latest full release will always be available on the GitHub site. However, for interim patches, please see the #info channel -on the [STFC Community Mod](https://discord.gg/PrpHgs7Vjs) discord server. This channel will always contain any hotfixes that -enable the game to work even if the full release does not. - -## BACK TO THE REGULAR STUFF: +# STFC Community Mod

- STFC Community Mod - License: GPLv3 - Sponsorship
- A community mod (patch) that adds a couple of tweaks to the mobile game Star Trek Fleet Command™ + STFC Community Mod

-## Contributing / Development - -If you wish to contribute to the project, or simply compile the DLL yourself, please see [CONTRIBUTING.md](CONTRIBUTING.md) - -There is a discord server with friendly, helpful people who will assist if you have issues (see the support section below). - -This project is maintained solely at my own cost of time, energy and money. Any contributions and help are greatly welcomed. - -## Features - -- Set system UI scale + adjustment factor -- Set viewer UI scale -- Set system zoom - - default - - maximum - - keyboard speed - - presets (1-5) -- Set transition time -- Disable various toast banners -- Disable galaxy chat -- Enable/Disable hotkeys (community mod or scopely) -- Enable extended donation slider (alliance) -- Extend tagged chest-purchase sliders up to 160 on Windows -- Show alternative cargo screens for: - - default - - player - - station - - hostile - - armada -- Press ESCAPE to remove pre-scan viewers -- Skip reveal sections when opening chests -- Exit section when collecting gifts -- Create default toml file settings file if none exists -- Create parsed toml file to show what settings have been applied -- Customise your keyboard shortcuts - -For a full list of features see our [FEATURES.md](docs/FEATURES.md) - -## Installing - -Please see the [INSTALL.md](docs/INSTALL.md) instructions which has steps on how to use this mod with Star Trek Fleet Command. - -For the Windows DLL identity marker, artifact-attestation trust boundary, and verification command, see -[Windows DLL provenance](docs/WINDOWS_DLL_PROVENANCE.md). - -Please note, that whilst Mac support was added in this version, it's supported on an as-is basis due to lack of Mac development environments. - -## Keyboard shortcuts - -Most keyboard shortcuts can be modified by updated your TOML file. If your -file is empty, see the VARS file which has all the runtime settings that have -been applied. Valid values for any short can be found in [KEYMAPPING.md](docs/KEYMAPPING.md) - -### UI shortcuts - -| Key | Shortcut | -| -----------: | -------------------------------- | -| F10 | Bug fixer (exits game) | -| F1-F5 | Zoom presets | -| Q | Zoom In | -| E | Zoom Out | -| MINUS | Zoom (min) | -| = | Zoom (default) | -| BACKSPACE | Zoom (max) | -| C | Open/Focus Chat - Full Screen | -| Alt-C | Open/Focus Chat - Side of Screen | -| ` | Open/Focus Chat - Side of Screen | -| PGUP | UI Scale Up | -| PGDOWN | UI Scale Down | -| SHIFT-PGUP | UI Viewer Scale Up | -| SHIFT-PGDOWN | UI Viewer Scale Down | - -### Combat/Navigation shorcuts - -| Key | Shortcut | -| --------------: | -------------------------------------------------------------------------- | -| SPACE or MOUSE1 | Perform default action (MOUSE1 = right mouse click) | -| SPACE or MOUSE1 | Add to Kir'Shara queue (if owned) and already attacking | -| 1-8 | Ship select/focus | -| R | When ship selected, recall ship | -| R | When clicking on mine/player/enemy, perform non-default action (eg, scan) | -| V | When clicking on mine/player/enemy, toggle view of cargo or default screen | -| CTRL-Q | Enable/Disable Kir'Shara queue (if owned) | -| CTRL-C | Clear Kir'Shara queue (if owned) | - -NOTE: There are some common changes made to allow both mouse and keyboard to -action items such as: - -- set action_queue, action_primary and action_recall_cancel to `SPACE|MOUSE1` - allowing both right mouse click and spacebar to action attacks on (or - queuing of) hostiles or cancel a warp. - -- set action_recall to `R|MOUSE3` to allow recalling using - both spacebar and the side mouse button - -### Section shortcuts - -| Key | Shortcut | -| ------: | ---------------- | -| T | Away Teams | -| G | Galaxy | -| Ctrl-G | Galaxy (native) | -| H | System | -| Shift-E | Events | -| Ctrl-E | Events (native) | -| Shift-G | Exterior View | -| Shift-H | Interior View | -| B | Bookmarks | -| F | Factions | -| Shift-F | Refinery | -| Shift-I | Artifact Gallery | -| U | Research | -| Y | Scrap Yard | -| I | Inventory | -| M | Active Missions | -| O | Command Center | -| Shift-O | Officers | -| Shift-Q | Q-Trials | -| X | ExoComp | -| Z | Daily Missions | - -## Support +A community mod for the desktop version of **Star Trek Fleet Command** on Windows and macOS. +It adds adjustable UI scaling, camera controls, keyboard shortcuts, cargo previews, and data sync. -For STFC Community Mod items, please visit the [STFC Community Mod](https://discord.gg/PrpHgs7Vjs) discord server. +## Start here -Tashcan has now retired all things STFC from [Ripper's Corner](https://discord.gg/gPuQ5sPYM9) but still swing by to say hello to the wonderful man. +| You want to | Read | +| --- | --- | +| Install or update the mod | [Install the mod](docs/INSTALL.md) | +| Change a setting | [Settings and file locations](docs/INSTALL.md#change-settings) | +| Find or change a shortcut | [Keyboard shortcuts](docs/KEYMAPPING.md) | +| See what the mod can do | [Features](docs/FEATURES.md) | +| Build or contribute code | [Contributing](CONTRIBUTING.md) | -## Disclaimer +Download the [latest release](https://github.com/STFC-Mod/mod/releases/latest/). +For test builds, use the [release list](https://github.com/STFC-Mod/mod/releases/). +If a game update breaks the mod, check **#info** in the +[STFC Community Mod Discord](https://discord.gg/PrpHgs7Vjs) for hotfixes. -This is intended to give people insight and possibility to add new things for QoL improvements. +## Get help -There is no guarantee or promise that using this for features outside of what is officially offered via this repository will not result actions against your account. +Use the [Discord server](https://discord.gg/PrpHgs7Vjs) for support. +Include your operating system, game version, mod version, and the relevant lines from `community_patch.log`. +The [installation guide](docs/INSTALL.md#fix-installation-problems) covers common problems. -All features and additions provided here via this repository are sanctioned by Scopely and thus aren't subject to account actions. +## Project details -## License +The project accepts [code contributions](CONTRIBUTING.md) and +[sponsorship](https://github.com/sponsors/netniV). +See the [changelog](CHANGELOG.md) for recorded releases. -- GPLv3 +The mod uses the [GPLv3 license](LICENSE). +[Third-party notices](docs/THIRD_PARTY.md) and +[Windows DLL verification](docs/WINDOWS_DLL_PROVENANCE.md) have their own references. +There is no account-safety guarantee for features added outside this repository. diff --git a/docs/DAILY_FACTION_BULK_CLAIM.md b/docs/DAILY_FACTION_BULK_CLAIM.md index 342471d75..29ed091c4 100644 --- a/docs/DAILY_FACTION_BULK_CLAIM.md +++ b/docs/DAILY_FACTION_BULK_CLAIM.md @@ -8,7 +8,7 @@ | `"federation,romulan"` | Federation and Romulan | | `"none"` | None of the three | -Other dailies remain eligible. Use `none` by itself. Restart after editing TOML. +Other dailies remain eligible. Use `none` by itself. Settings reload when the TOML file changes. On upgrade, existing blank configurations keep their all-factions behavior. The loader now resolves blank to the explicit default before populating the diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 059288f61..e63acb1d9 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -1,179 +1,108 @@ -# STFC Community Mod Features - -The STFC Community Mod adds configurable quality-of-life improvements to the desktop version of Star Trek Fleet Command. This catalog describes the user-facing features represented by the current source code and English example configuration. - -Most options are configured in `community_patch_settings.toml`. The mod creates a default settings file when one is missing and also writes a parsed settings file so you can see the values that were applied. Nearly every shortcut can be remapped; see [`KEYMAPPING.md`](docs/KEYMAPPING.md) for valid key names. - -## Display and window controls - -- Set the overall interface scale and the amount changed by each scale adjustment. -- Scale object viewers independently from the main interface. -- Scale ship models in System View independently from the interface. -- Adjust the interface, viewer, and ship scales while playing with configurable shortcuts. -- Enable freely resizable game windows on Windows. -- Enable borderless fullscreen mode and switch between fullscreen and windowed mode without restarting the game. -- Control whether the game replaces the system cursor. -- Adjust the frame-rate scaling factor used by visual effects. -- Set the duration of screen transitions. - -## System View camera and navigation - -- Increase the maximum System View zoom distance. -- Set the zoom level used when entering a system. -- Configure five System View zoom presets. -- Zoom in, zoom out, jump to minimum or maximum zoom, and reset zoom by shortcut. -- Save the current zoom or a preset as the new default. -- Configure keyboard zoom speed. -- Configure System View pan momentum and momentum falloff. -- Use keyboard movement controls for System View, or disable those movement keys. -- Configure player and non-player fleet labels to use native, expanded, compact, or zoom-threshold-based detail. -- Configure separate fleet-label zoom thresholds for player and non-player fleets. - -## Hotkeys and screen navigation - -- Enable or disable all hotkeys. -- Choose between the community mod hotkeys and Scopely's native hotkeys. -- Enable an extended set of mod shortcuts. -- Remap shortcuts in the settings file, including multiple keys or mouse buttons for one action. -- Open or focus commonly used screens directly, including: - - Alliance, Alliance Armada, and Alliance Help. - - Artifact Gallery, Away Teams, Battle Reports, Bookmarks, and Chat. - - Command Center, Daily Missions, Events, ExoComp, Factions, and Fleet Commander. - - Galaxy View, System View, Station Exterior, and Station Interior. - - Gifts, Haven, Inventory, Missions, Officers, Q Trials, Refinery, Research, and Scrap Yard. - - Settings, shield selection, ship construction, ship management, and ship swapping. -- Open Alliance, Galaxy, and Private chat tabs directly. -- Focus the current screen's search field with a shortcut. -- Use configurable primary-action, alternate-action, queue, recall, repair, and cancel shortcuts. -- Select ships 1 through 8 and configure the double-tap timing used to locate a selected ship. -- Recall a selected ship or perform context-sensitive actions against mines, players, hostiles, and other targets. -- Clear focused text or close chat with Escape. - -## Combat and ship interaction - -- Enable the Kir'Shara attack queue by default when the artifact is owned. -- Add targets to the Kir'Shara queue, clear the queue, or toggle queuing by shortcut. -- Use a configurable primary action for context-sensitive attacks, warps, and cancellations. -- Choose the automatic action for the instant-warp confirmation: show the dialog, use regular warp, or use instant jump. -- Configure ship-name lists that always use regular warp, always use instant jump, or always show the confirmation dialog. -- Cycle the current instant-warp behavior by shortcut. -- Keep the warp action label consistent with the selected automatic action. -- Automatically confirm Forbidden Tech level and tier upgrades when enabled. - -## Cargo and target previews - -- Show cargo or rewards automatically in the default target preview. -- Configure cargo visibility independently for player ships, stations, hostiles, and armadas. -- Toggle each cargo-preview mode while playing. -- Switch between cargo and the normal target view with a shortcut. -- Close pre-scan and target viewers with Escape. -- Allow or block locate and recall actions while previews are open, with runtime toggles for both behaviors. -- Show cargo totals immediately instead of playing the native count-up animation on supported Windows clients. -- Configure the number of decimal places used for abbreviated cargo values such as `1.25M`. - -## Fleet and officer management - -- Select the previous or next ship in the fleet-management dock with the Left and Right arrow keys. -- Double-click a ship in the fleet-management dock to assign it. -- Pin configured ship names to the front of the fleet-management dock while preserving the selected sort order. -- Restore the **Below Deck Ability** sorting option to officer roster and assignment screens. -- Show a ship's out-of-dock power while it is docked. - -## Rewards donations and Daily Goals - -- Skip chest-reveal animations and open rewards immediately. -- Extend the Alliance donation slider to a configurable maximum. -- Extend supported tagged chest-purchase sliders to a configurable maximum on Windows. -- Open the bulk gift-claim flyout automatically when entering Gifts. -- Exit the relevant section after gift collection through the mod's streamlined gift flow. -- Apply the Daily Goals **Claim All** behavior only to selected Federation, Klingon, or Romulan goals. -- Force the Daily Goals **Claim All** toggle on the first time the screen is opened in a session. - -## Chat interface and HUD - -- Hide Galaxy Chat. -- Hide Veil Chat. -- Open Chat full-screen or docked on either side by shortcut. -- Control the visibility of the Daily Goals, Field Training, Missions, Outposts, and Q Trials HUD buttons. -- Set each supported HUD item to native automatic behavior, always shown, or always hidden. -- Prevent Escape from opening the game-exit prompt. -- Optionally require a configurable double press of Escape before showing the exit prompt. - -## Banners audio and popups - -- Suppress selected toast-banner types. -- Send desktop notifications for selected banner types. -- Disable standard toast banners through the experimental global toggle. -- Suppress selected audio events by event name. -- Trace audio event names to the log to help build a suppression list. -- Automatically confirm Discovery prompts. - -## Loading and transition screens - -- Replace the login loading background with the mod's embedded artwork. -- Load a custom loading-screen image from a configured path. -- Scale the loading-screen logo. -- Show rotating community-mod tips on the loading screen. -- Reuse the loading artwork during transitions. -- Use a black transition background instead of artwork. - -## Data synchronization - -- Sync selected game data to one or more configured community services. -- Configure independent sync targets, including custom endpoints and access tokens. -- Sync any combination of: - - Battle logs. - - Buffs. - - Buildings. - - Inventory and resources. - - Jobs and missions. - - Owned officers, ships, and Forbidden Tech. - - Research. - - Slots. - - Traits. -- Use the built-in target definitions for STFC Data, Spock's Club, and Next Spock's Club. -- Route sync traffic through a proxy. -- Enable or disable SSL certificate verification. -- Configure resolver caching, diagnostic logging, and detailed debug logging. - -## Reliability and configuration support - -- Apply client-specific crash fixes and compatibility patches. -- Generate a default TOML settings file if no configuration exists. -- Generate a parsed TOML file showing the settings actually applied at runtime. -- Enable or disable patch groups independently in development builds. -- Log mod initialization, patch installation, and optional sync or audio diagnostics for troubleshooting. -- Support both Windows and macOS through platform-specific injection and loading components. - -## Platform and availability notes - -- Windows and macOS do not necessarily expose every feature in exactly the same way. -- Free window resizing and extended tagged chest-purchase sliders are Windows-specific. -- The instant cargo counter is guarded for a supported Windows client build; unsupported builds retain the native animation. -- Some settings are experimental or diagnostic and may be disabled, client-version-specific, or intended for troubleshooting. -- Patch availability can change when the game client changes because the mod hooks the native IL2CPP runtime. - -## Default shortcut overview - -The default shortcut map includes the following high-use controls. All of these can be changed in the settings file. - -| Action | Default shortcut | +# Features + +The mod adds controls and display options to the desktop game. +Change them in `community_patch_settings.toml`; the +[English example](configuration/example_community_patch_settings_en.toml) lists the settings and defaults. +See [installation](INSTALL.md#change-settings) for file locations and [keyboard shortcuts](KEYMAPPING.md) for controls. + +Features depend on the game client. A client update can break a hook until the mod is updated. + +## Display and camera + +| Area | Controls | +| --- | --- | +| UI scale | Adjust the main interface, object viewers, and system-view ship models separately. | +| System zoom | Set the maximum range, entry zoom, keyboard speed, and five presets. Save a preset or the current zoom as the default. | +| Camera movement | Pan with configurable keys and set momentum falloff. Keyboard panning can be disabled. The camera can also stop following a selected target, so you can pan away from it. | +| Haven | Extend camera range while keeping road surfaces above the ground. `graphics.haven_zoom = 0.0` uses the native range. | +| Fleet labels | Choose native, expanded, compact, or zoom-threshold detail separately for player and non-player fleets. | +| Window and cursor | Resize the game window freely on Windows and control whether the game replaces the system cursor. | +| Anomaly timer | Show the remaining time in a Galactic Anomaly system. Disabled by default. | + +`fr_scale` scales system-view backdrop renderables. +The code reads `transition_time`, `system_pan_momentum`, and `borderless_fullscreen`, but does not currently apply them. +F11 does not toggle borderless mode in this build. + +## Keyboard controls + +- Choose mod hotkeys or the game's native hotkeys. Remap actions, including alternatives for the same action. +- Open screens, select chat tabs, and focus a search field by shortcut. +- Select ships 1 through 8. Configure the double-tap interval that locates a selected ship. +- Use context-sensitive attack, warp, recall, repair, cancel, and cargo actions. The primary action also joins a wave + defense from its course or viewer card. +- Clear text focus with Escape and control whether Escape opens the exit prompt, including an optional double press. + +Extended shortcuts add controls such as cargo toggles and zoom-preset saving. +Experimental shortcuts require both extended and experimental controls to be enabled. +The [shortcut reference](KEYMAPPING.md) lists the defaults. + +## Combat, cargo, and fleets + +| Area | Behavior | +| --- | --- | +| Kir'Shara queue | Start with queuing enabled, add targets, clear the queue, or toggle it. Requires ownership of the artifact. | +| Instant warp | Show the confirmation, use regular warp, or jump automatically. Ship-name filters can override the choice. | +| Target previews | Show cargo by target type, toggle cargo view, and close viewers with Escape. Locate and recall can remain enabled while previews are open. | +| Cargo numbers | Choose decimal places for abbreviated totals. Supported Windows clients can skip the count-up animation. | +| Ship assignment | Select adjacent ships with arrow keys, double-click to assign, and pin named ships while preserving sort order. | +| Officer sorting | Restore **Below Deck Ability** in roster and assignment screens. | +| Ship power | Show out-of-dock power while a ship is docked. | +| Forbidden Tech | Automatically confirm level and tier upgrades when enabled. The selected item shows the ship it is equipped on, including ships without a dock. | + +## Rewards and interface + +- Skip chest reveals, open bulk gift claims, and leave the section after the supported gift-collection flow. +- Extend Alliance donations and, on Windows, supported tagged chest-purchase sliders. +- Limit Daily Goals **Claim All** to selected Federation, Klingon, or Romulan goals. Its toggle can start enabled each session. +- Hide Galaxy or Veil Chat. Set supported HUD buttons to automatic, always shown, or always hidden. +- Open alliance side chat once per login, once the station and chat have finished loading, and set side chat's + starting width. Both are off by default. +- Hide **Exchange All** in the artifact-shards popup while retaining single exchanges. +- Restore the native **Research** actions on Alliance Games Store items, and refresh the store's currencies and + visible offers after it reloads them. + +The supported HUD buttons are Field Training, Missions, Outposts, and Q Trials. +Other options show the newest Haven help-history entries first, limit ads to the first popup each session, and confirm Discovery prompts. + +## Banners and audio + +- Hide selected banner types or use the experimental global banner switch. +- Send desktop notifications for selected banners on Windows. +- Play optional victory, defeat, and Armada sounds on Windows and macOS. +- Suppress named audio events, or use `All` to block named events that start or resume audio. +- Log audio event names to help build a suppression list. + +If a notification's text binding is unavailable, unresolved placeholders remain visible and the mod logs a warning. +The log retains five previous sessions as `.log.1` through `.log.5`. + +## Loading screens + +Replace the login background with the embedded artwork or a custom image. +Adjust logo scale and show rotating mod tips. +Transitions can reuse the artwork or use a black background with logos. + +## Data sync + +Sync selected data to STFC Data, Spock's Club, Next Spock's Club, or custom endpoints. +Each target has its own options and access token. + +| Category | Data | | --- | --- | -| Zoom presets | `F1` to `F5` | -| Zoom in or out | `Q` or `E` | -| Minimum maximum or default zoom | `BACKSPACE` `MINUS` or `=` | -| Main interface scale | `PGUP` or `PGDOWN` | -| Viewer scale | `SHIFT-PGUP` or `SHIFT-PGDOWN` | -| Ship model scale | `CTRL-PGUP` or `CTRL-PGDOWN` | -| Open full-screen chat | `C` | -| Open side chat | `ALT-C` or `` ` `` | -| Select or focus ships | `1` to `8` | -| Primary action or queue action | `SPACE` or `MOUSE1` | -| Recall or alternate action | `R` | -| Toggle cargo view | `V` | -| Toggle Kir'Shara queue | `CTRL-Q` | -| Clear Kir'Shara queue | `CTRL-C` | -| Focus search | `CTRL-F` | -| Toggle borderless fullscreen | `F11` | - -For the complete shortcut list and the names accepted by the configuration parser, see [`README.md`](README.md) and [`KEYMAPPING.md`](docs/KEYMAPPING.md). +| Progress | Research, buffs, traits, jobs, and missions | +| Assets | Buildings, inventory, resources, officers, ships, Forbidden Tech, and slots | +| Haven | Owned building pieces and map buildings, with status and position. Maps identified as another player's are ignored. | +| Battles | Up to 300 recent battle journals per session | +| Fleets | Live fleet state: each state change with cargo, mining and timers, and the server's view of deployed fleets. Every change is sent, not just the latest; up to 300 per session. Off unless a target sets `fleets`. | +| Store | Faction store offers: favor level prices, requirements and remaining purchases. Off unless a target sets `store_offers`. | +| Profile | Your own level, XP, Power and Haven unlock. Other players' records are never sent. Off unless a target sets `profile`. | + +Failed uploads retry with the latest observed values. +Target changes apply on reload and trigger a fresh snapshot. +Recent battle journals can replay after a restart or login. +Proxy, certificate verification, name-cache, and diagnostic options are in the settings example. + +## Compatibility switches + +`[patches]` keys disable hook groups in every build. Changes require a restart. +Use them to isolate a broken hook or a conflict with another mod. +Normal feature settings remain separate and can change during play. diff --git a/docs/INSTALL.md b/docs/INSTALL.md index e27aa678c..f6a55147f 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -1,232 +1,125 @@ -# Star Trek Fleet Command - Community Mod +# Install the mod -

- License: GPLv3 - Sponsorship -

+Download a build from the [release list](https://github.com/STFC-Mod/mod/releases/). +Expand **Assets** to see the files. Versioned and unversioned ZIPs contain the same files. -

- A community mod (patch) for PC and macOS that adds a couple of tweaks to the Star Trek Fleet Command™ game -

+If a game update breaks the release, check **#info** in the +[STFC Community Mod Discord](https://discord.gg/PrpHgs7Vjs) for a hotfix. -## Downloads / Releases +Choose your platform: [Windows](#install-on-windows), [macOS](#install-on-macos), or [Wine](#install-under-wine). -The STFC Community Mod is available on GitHub. +## Install on Windows -You can download either the [latest official release](https://github.com/STFC-Mod/mod/releases/latest/) or any other -release, including [alpha/beta](https://github.com/STFC-Mod/mod/releases/) builds. +Close the game before you replace an existing mod. -In the event that a game update breaks the latest release, please visit the [STFC Community Mod](https://discord.gg/PrpHgs7Vjs) -discord server, and check the #INFO channel for the latest hotfixes. +1. Download `stfc-community-mod.zip` and extract `version.dll`. +2. Open the game folder that contains `prime.exe`. +3. Put `version.dll` beside `prime.exe`. +4. Start the game. A loaded mod creates `community_patch.log` and a settings file if one is missing. +5. To change the defaults, follow [Change settings](#change-settings). -**Notes:** +The usual game folder is: -- GitHub may require you to log in to see the downloads for - pre-releases, and you will need to expand the - assets section to see the downloads. +```text +C:\Games\Star Trek Fleet Command\Star Trek Fleet Command\default\game +``` -- There is no difference between the versioned and unversioned zip - files. They are simply named this way to allow people to store - multiple versions rather than overwriting or having a random - number appended by windows. +If your game is elsewhere, use [Find the Windows game folder](#find-the-windows-game-folder). +Keep `version.dll` out of the official launcher's folder. A DLL there can stop the launcher and game updates from working. -## Configuration +To verify an attested download, see [Windows DLL verification](WINDOWS_DLL_PROVENANCE.md). -**IMPORTANT**: Any desired configuration changes should **ONLY** be made in the -`community_patch_settings.toml` file. +## Install on macOS -When the game is launched: +Current source builds require **macOS 14.6 or later**. +Check the requirements of the release you download. -- If the configuration file does not exist, it will be created with default values. It - will not have any comments describing these settings. +1. Download `stfc-community-mod-installer.dmg`. +2. Open the DMG and drag **STFC Community Mod** to **Applications**. +3. Open **STFC Community Mod**. If macOS blocks the app, use **System Settings > Privacy & Security > Open Anyway**. +4. Start the game from this launcher. If prompted, let it re-sign the game to add the entitlements needed by the mod. +5. To change the defaults, follow [Change settings](#change-settings). -- The configuration file is read with any missing settings defaulting to predefined values. +Use the Community Mod launcher each time. Starting the game from the official launcher does not load the mod. +A game update can remove the required entitlements, so the Community Mod launcher may ask to re-sign it again. -- The finalized configuration – including any assumed default values – is written to - `community_patch_runtime.vars`. +## Install under Wine - **NOTE:** You should NOT make any changes to this file. This file is - constantly rewritten when the game starts, so any modifications to it are never used and will be - lost. +Use the Windows mod and follow the [Windows steps](#install-on-windows). +The game folder is inside your Wine prefix, usually at: -If you have any problems with a setting, check for that setting in the _.vars_ file to verify -that the parse value of that setting was correctly applied. You may also need to check the -`community_patch.log` file to see if any errors were encountered while parsing the _.toml_ file. +```text +drive_c/Games/Star Trek Fleet Command/Star Trek Fleet Command/default/game +``` -### Configuration example files +Set the `version` DLL override to **native, then builtin** in `winecfg` or your launcher's runner settings. +You can also set this environment variable before launch: -Commented example configurations are maintained separately for each supported language, using the same flags as -[ModConfig](https://modconfig.pages.dev): +```sh +export WINEDLLOVERRIDES="version.dll=n,b" +``` -- United Kingdom flag [English](example_community_patch_settings_en.toml) -- German flag [German](example_community_patch_settings_de.toml) -- French flag [French](example_community_patch_settings_fr.toml) -- Netherlands flag [Dutch](example_community_patch_settings_nl.toml) +## Change settings -Choose the example for your preferred language and save a copy in the appropriate settings folder as -`community_patch_settings.toml`. +Edit **`community_patch_settings.toml`**. The other files are outputs. -## Installation on Windows +| File | Purpose | +| --- | --- | +| `community_patch_settings.toml` | Your settings. Missing keys use defaults. | +| `community_patch_runtime.vars` | Parsed values, including defaults. Edits here have no effect. | +| `community_patch.log` | Startup, settings errors, and diagnostics. | -**NOTE:** The `Star Trek Fleet Command` game itself is located by default at: +By default, these files are beside `prime.exe` on Windows and Wine. +On macOS, they are in: -- `C:\Games\Star Trek Fleet Command\Star Trek Fleet Command\default\game` +```text +~/Library/Preferences/com.stfcmod.startrekpatch +``` -Installation of the Community Mod is a manual process for Windows (or Wine). +For commented settings, copy an example to that folder and name it `community_patch_settings.toml`. +Back up an existing settings file before replacing it. -1. Download the `stfc-community-mod.zip` file from your chosen [GitHub release](https://github.com/STFC-Mod/mod/releases/) and extract the `version.dll` file. +| Language | Example | +| --- | --- | +| English | [Current settings reference](configuration/example_community_patch_settings_en.toml) | +| German | [German example](configuration/example_community_patch_settings_de.toml) | +| French | [French example](configuration/example_community_patch_settings_fr.toml) | +| Dutch | [Dutch example](configuration/example_community_patch_settings_nl.toml) | -2. Open the game folder in Explorer. The default folder for the game also holds the settings file. +The English example tracks the current code. Translations can lag behind. - **NOTE:** If this folder isn't present, or no log files are created when running the game, - see the [Problems Under Windows](#problems-under-windows) section below. +Settings reload after you save the file. To reload manually, press `CTRL-SHIFT-F6`. +Changes under `[patches]` require a game restart. +Shortcuts that adjust settings during play do not save those changes to your TOML file. -3. Move the extracted `version.dll` file into this folder. +## Fix installation problems -4. Run the game! If all is well, and one does not already exist, the mod will - create `community_patch_settings.toml` and populate this with the default - values. +Start with the log and runtime values. -5. For first-time users of the Community Mod, it is recommended to choose one of the - [localized configuration examples](#configuration-example-files) and save a copy to the game folder as - `community_patch_settings.toml`. These examples contain additional comments that explain the available settings. +| Problem | Check | +| --- | --- | +| No mod log on Windows | Put `version.dll` beside the running game's `prime.exe`. Check **Properties > General > Unblock** on the DLL. | +| Mod does not load on macOS | Start the game through **STFC Community Mod** and accept its entitlement repair prompt. | +| Mod does not load under Wine | Set the `version` DLL override to `n,b`. | +| A setting has no effect | Check its section, spelling, and value type. Compare `community_patch_runtime.vars` and read the log for parse errors. | -## Installation on macOS - macOS 13.5 or later required +### Find the Windows game folder -**NOTE:** The `Star Trek Fleet Command` game itself is located at: +1. Start the game and open **Task Manager**. +2. Find the game process. Expand its group if needed. +3. Right-click `prime.exe` and choose **Open file location**. +4. Check that the folder contains `prime.exe`, then close the game before installing the DLL. -- `~/Library/Application Support/Star Trek Fleet Command/Games/Star Trek Fleet Command/Star Trek Fleet Command/default/game` +### Open the macOS settings folder -You should only need to access this folder if you need to view the `community_patch.log` file while troubleshooting a problem. +In Finder, press `Command-Shift-G` and enter: -1. Download the `stfc-community-mod-installer.dmg` file from your chosen [GitHub release](https://github.com/STFC-Mod/mod/releases/). +```text +~/Library/Preferences/com.stfcmod.startrekpatch +``` -2. Open the DMG, then drag and drop the `STFC Community Mod` to your `Applications` folder. The - STFC Community Mod launcher must be used to start the game to have the mod loaded. If - you start the game using the games Launcher, you will NOT have the mod loaded. +This works even when Finder hides `Library`. +If the launcher shows game version `-1`, reinstall the game, then open the Community Mod launcher again. +You do not need to reinstall the mod launcher. -3. Running the launcher for the first time will prompt a warning from macOS because the Community Mod is not signed with an Apple Developer ID certificate. - - > "STFC Community Mod" Not Opened - > - > Apple could not verify “STFC Community Mod” is free of malware that may harm your Mac or compromise your privacy - - Dismiss the warning by clicking `Done`, then go to **System Settings**, **Privacy & Security** and scroll down to the **Security** section - where you can override this behaviour by clicking `Open Anyway` next to `"STFC Community Mod" was blocked to protect your Mac.` - -4. Run the game from the launcher! - - Since M82.1, the **Star Trek Fleet Command** app ships with heightened security and lacks the entitlements to correctly load - the Community Mod. As a workaround, the Community Mod launcher will prompt you to re-sign the game if it detects - missing entitlements at startup. This process needs to be repeated with every game update. - - If all is well, the mod will create `community_patch_settings.toml` - in the settings folder `~/Library/Preferences/com.stfcmod.startrekpatch`. - - Note: By default, macOS hides the `~/Library` folder in Finder, so if it isn't visible, - see the [Problems under macOS](#problems-under-macos) section below for tips on opening it. - -5. For first-time users of the Community Mod, it is recommended to choose one of the - [localized configuration examples](#configuration-example-files) and save a copy to the settings folder as - `community_patch_settings.toml`. These examples contain additional comments that explain the available settings. - -## Installation on Wine/Linux - -**NOTE:** The `Star Trek Fleet Command` game itself is located at: - -- `~/Games/star-trek-fleet-command/drive_c/Games/Star Trek Fleet Command/Star Trek Fleet Command/default/game`. - -The Windows version of the mod, and the game itself, run well under Linux using the Wine compatability layer. - -If the game is installed using the [Lutris STFC installer](https://lutris.net/games/star-trek-fleet-command/), -the mod can be installed by following the [Windows](#installation-on-windows) directions -above. - -If the game is installed through other launchers or directly in an unmanaged `WINEPREFIX`, -an additional adjustment may be needed for it to load the mod library correctly; see the -[Problems Under Wine/Linux](#problems-under-winelinux) notes below. - -## Common Problems - -The most common problems getting the DLL to work are: - -1. Not installed in the correct location. This must be `game` folder where `prime.exe` also exists. - -2. Windows is blocking the DLL. Right-click the file and select Properties. On the `General` tab - there will be additional text at the bottom: - - ```console - This file can from another - computer and might be blocked to - help protect this computer - ``` - - To the right of this, there will be a tick box called `Unblock`. Tick the box and then click OK - to unblock the file. - -3. The configuration file has the wrong name (see above) - -4. The configuration file is not being parsed as you expect, which is normal because: - - Your configuration isn't being parsed - - The configuration option name is spelt wrong - - The configuration option name is in the wrong section - - The configuration option value is not a true or false - - You can verify your configuration by looking at `community_patch_runtime.vars` and/or the - log file `community_patch.log`. - -## Problems under Windows - -On Windows, sometimes the game is installed in a user's profile folder instead of the -default location. This happens when the STFC installer finds more than one user -attempted to install it, or if the current user doesn't have admin rights. - -If this is the case, to find the correct game location for the `version.dll` file, do the -following: - -1. Open _Task Manager_ while the game is running (press Ctrl-Alt-Delete) -2. Right-click `prime.exe` and select 'Expand' -3. Right-click `Star Trek Fleet Command` and select 'Open file location' - -An _Explorer_ window will open, and you can check for `prime.exe` to verify this is the -correct folder. - -**IMPORTANT**: The `version.dll` file should NOT be placed within the official STFC launcher's -folder as this will prevent the launcher from working and the ability to update the game. - -## Problems under macOS - -macOS hides the `Library` folder in Finder by default. There are several ways to open it: - -- Hold the `⌥ Option` key (or `Alt` on a PC keyboard) in **Finder** and click the **Go to** menu item - and then click the **Library** folder item - - or - -- Press `⌘ Command`+`⇧ Shift`+`G` in the **Finder** for the Goto box and type in `~/Library` - - or - -- Use **Terminal** and type: `open ~/Library` - -The Community Launcher shows the version of `Star Trek Fleet Command` that was detected -under the current user. If this shows as `-1`, then the recommended course of action is -to uninstall and reinstall `Star Trek Fleet Command` whcih can be done without needing -to reinstall the Community Mod launcher. - -### Problems under Wine/Linux - -To use the Windows version of the mod under Wine, the wine DLL override setting for -`version.dll` _must_ be set to `n,b` or it will not be loaded. - -When using the [Lutris STFC installer](https://lutris.net/games/star-trek-fleet-command/) -(which is recommended), this override will have already been set by the installer within -the runner configuration. - -Otherwise, it can be set in the `winecfg.exe` Libraries tab or by setting the `WINEDLLOVERRIDES` enviroment variable to `version.dll=n,b` before launching the game. - -If the game folder does not exist in the default location mentioned under [Installation on Wine/Linux](#installation-on-winelinux), it may exist under: - -- `drive_c/Games/Star Trek Fleet Command/Star Trek Fleet Command/default/game` - -**NOTE:** This is a relative path that starts at the wine environment (WINEPREFIX). +For further help, use the [Discord server](https://discord.gg/PrpHgs7Vjs). diff --git a/docs/KEYMAPPING.md b/docs/KEYMAPPING.md index ef43671a0..40f25c6c4 100644 --- a/docs/KEYMAPPING.md +++ b/docs/KEYMAPPING.md @@ -1,105 +1,184 @@ -# Star Trek Fleet Command - Community Mod +# Keyboard shortcuts -

- License: GPLv3 - Sponsorship -

+Set bindings under `[shortcuts]` in `community_patch_settings.toml`. +Names are case-insensitive. The mod writes the parsed bindings and their source to +`[shortcuts]` and `[shortcuts_source]` in `community_patch_runtime.vars`. -

- A community mod (patch) that adds a couple of tweaks to the mobile game Star Trek Fleet Command™ -

+## Binding format -## Valid shortcut key strings +| Value | Meaning | +| --- | --- | +| `"Q"` | Q with no modifier held | +| `"SHIFT-Q"` | Either Shift key and Q | +| `"ALT-LSHIFT-T"` | Either Alt key, left Shift, and T | +| `"SPACE\|MOUSE1"` | Space or the right mouse button | +| `"NONE"` or `""` | Disable this binding | -Each game function can be assigned a shortcut KEY (with the exception of escape that is fixed). +Use `-` between modifiers and one key. Use `|` between alternative bindings. +A modified binding requires its listed modifiers. A plain binding does not fire while a modifier is held. +After a modified binding fires, its plain-key action waits until you release the key. -To use a Modifier, combine it with a single KEY (and optionally other modifiers) separated by a minus symbol: +For example: -Value | Keys Required ---: | :-- -"SHIFT-Q" | (Left Or Right) Shift + Q -"ALT-LSHIFT-T" | (Left Or Right) Alt + Left Shift + T -"Q" | Q (no Shift, Ctrl, etc) +```toml +[shortcuts] +action_primary = "SPACE|MOUSE1" +action_recall = "R|MOUSE3" +move_left = "LEFT" +``` -### Screen shortcuts +An invalid alternative is ignored. If no alternative is valid, the action uses its default and logs a warning. +Escape's close and focus behavior is fixed, even though `ESCAPE` is also a valid key name for bindings. -These bindings can be changed in the `[shortcuts]` section of `community_patch_settings.toml`. +## Default controls -| Setting | Default | Action | +These are mod hotkeys. `[control].use_scopely_hotkeys = true` selects the game's controls instead. +Most actions wait while you type in a text field. + +### Camera and scale + +| Action | Default | Setting | +| --- | --- | --- | +| Move up, down, left, right | `W\|UP`, `S\|DOWN`, `A\|LEFT`, `D\|RIGHT` | `move_up`, `move_down`, `move_left`, `move_right` | +| Zoom in, out | `Q`, `E` | `zoom_in`, `zoom_out` | +| Maximum, minimum, default zoom | `MINUS`, `BACKSPACE`, `=` | `zoom_max`, `zoom_min`, `zoom_reset` | +| Zoom presets 1 to 5 | `F1` to `F5` | `zoom_preset1` to `zoom_preset5` | +| Main UI scale up, down | `PGUP`, `PGDOWN` | `ui_scaleup`, `ui_scaledown` | +| Viewer scale up, down | `SHIFT-PGUP`, `SHIFT-PGDOWN` | `ui_scaleviewerup`, `ui_scaleviewerdown` | +| Ship scale up, down | `CTRL-PGUP`, `CTRL-PGDOWN` | `ui_scaleshipup`, `ui_scaleshipdown` | + +`[ui].disable_move_keys = true` disables keyboard panning. +Existing bindings take precedence, so `move_left = "LEFT"` keeps movement on the left arrow only. + +### Ships and combat + +Actions depend on the selected ship and target. + +| Action | Default | Setting | +| --- | --- | --- | +| Select or locate ship 1 to 8 | `1` to `8` | `select_ship1` to `select_ship8` | +| Locate the selected ship | `CTRL-SPACE` | `select_current` | +| Primary action or add to queue | `SPACE\|MOUSE1` | `action_primary`, `action_queue` | +| Alternate action | `TAB\|MOUSE4` | `action_secondary` | +| Recall or repair | `R\|MOUSE3` | `action_recall`, `action_repair` | +| Cancel warp | `SPACE\|MOUSE1` | `action_recall_cancel` | +| Toggle cargo view | `V\|MOUSE2` | `action_view` | +| Toggle Kir'Shara queue | `CTRL-Q` | `toggle_queue` | +| Clear the queue | `CTRL-C` | `action_queue_clear` | +| Cycle instant-warp confirmation | `ALT-I` | `toggle_instant_warp` | + +The Kir'Shara queue requires the artifact. +`[control].select_timer` sets the ship-selection double-tap interval in milliseconds. + +### Screens and chat + +| Screen or action | Default | Setting | +| --- | --- | --- | +| Full-screen chat | `C` | `show_chat` | +| Side chat | `ALT-C`, backtick | `show_chatside1`, `show_chatside2` | +| Galaxy, Alliance, Private chat tabs | `CTRL-1`, `CTRL-2`, `CTRL-3` | `select_chatglobal`, `select_chatalliance`, `select_chatprivate` | +| Galaxy, System | `G`, `H` | `show_galaxy`, `show_system` | +| Native Galaxy, Events | `CTRL-G`, `CTRL-E` | `show_galaxy_native`, `show_events_native` | +| Station exterior, interior | `SHIFT-G`, `SHIFT-H` | `show_stationexterior`, `show_stationinterior` | +| Haven | `ALT-H` | `show_haven` | +| Away Teams, Gifts | `T`, `/` | `show_awayteam`, `show_gifts` | +| Artifact Gallery, Command Center | `SHIFT-I`, `O` | `show_artifacts`, `show_commander` | +| Daily Missions, active Missions | `Z`, `M` | `show_daily`, `show_missions` | +| Events, ExoComp | `SHIFT-E`, `X` | `show_events`, `show_exocomp` | +| Factions, Inventory | `F`, `I` | `show_factions`, `show_inventory` | +| Research, Scrap Yard | `U`, `Y` | `show_research`, `show_scrapyard` | +| Refinery, Q Trials | `SHIFT-F`, `SHIFT-Q` | `show_refinery`, `show_qtrials` | +| Settings, Officers | `SHIFT-S`, `SHIFT-O` | `show_settings`, `show_officers` | +| Officer Presets, Officer Swap | `CTRL-O`, `ALT-O` | `show_officerpresets`, `show_officerswap` | +| Manage ship, build ship, swap ship | `N`, `SHIFT-N`, `ALT-N` | `show_ships`, `show_shipconstruction`, `show_shipswap` | +| Peace Shield selection | `CTRL-S` | `show_shields` | +| Battle Reports | `SHIFT-B` | `show_battlelogs` | +| Focus search | `CTRL-F` | `focus_search` | +| Toggle shortcut hints | `HOME` | `toggle_shortcut_hints` | + +The shield shortcut opens the selection popup. You still choose the shield. +Ship Swap, Officer Swap, and Officer Presets wait for their destination button while a screen opens. +A new screen shortcut replaces the pending request. Disabling mod hotkeys or selecting native hotkeys cancels it. + +### Extended controls + +These require `[control].hotkeys_extended = true`, which is the default. + +| Action | Default | Setting | +| --- | --- | --- | +| Alliance, Bookmarks | `ALT-'`, `B` | `show_alliance`, `show_bookmarks` | +| Save zoom preset 1 to 5 | `SHIFT-F1` to `SHIFT-F5` | `set_zoom_preset1` to `set_zoom_preset5` | +| Save current zoom as default | `CTRL-=` | `set_zoom_default` | +| Toggle locate, recall while previews are open | `CTRL-R`, `CTRL-T` | `toggle_preview_locate`, `toggle_preview_recall` | +| Toggle default, player, station, hostile, armada cargo | `ALT-1` to `ALT-5` | `toggle_cargo_default`, `toggle_cargo_player`, `toggle_cargo_station`, `toggle_cargo_hostile`, `toggle_cargo_armada` | + +Alliance Help, Alliance Armada, and Lookup also require `[control].enable_experimental = true`. +Their defaults are `SHIFT-'`, `CTRL-'`, and `L`, with settings `show_alliance_help`, `show_alliance_armada`, and `show_lookup`. + +### Session and diagnostics + +| Action | Default | Setting | | --- | --- | --- | -| `show_officerpresets` | `CTRL-O` | Open Officer Presets. | -| `show_officerswap` | `ALT-O` | Open officer assignment for the selected ship. | -| `show_shipconstruction` | `SHIFT-N` | Open Ships / Ship Construction (Shipyard → Build Ship). | -| `show_shipswap` | `ALT-N` | Open Ship Swap for the selected ship. | -| `show_shields` | `CTRL-S` | Open the Peace Shield selection popup. | -| `show_battlelogs` | `SHIFT-B` | Open the Battle Reports inbox. | +| Disable, enable mod hotkeys | `CTRL-ALT-MINUS`, `CTRL-ALT-=` | `set_hotkeys_disabled`, `set_hotkeys_enabled` | +| Reload settings | `CTRL-SHIFT-F6` | `reload_settings` | +| Restart the game | `F9` | `restart` | +| Quit the game | `F10` | `quit` | +| Log trace, debug, info | `CTRL-SHIFT-F7`, `CTRL-SHIFT-F9`, `CTRL-SHIFT-F8` | `log_trace`, `log_debug`, `log_info` | +| Log warnings, errors, off | `CTRL-SHIFT-F10`, `CTRL-SHIFT-F11`, `CTRL-SHIFT-F12` | `log_warn`, `log_error`, `log_off` | -`show_ships = "N"` continues to manage the selected ship. The shield shortcut opens the selection popup; activating a shield still requires choosing one. +Hotkey enable and disable bindings are checked before the hotkey-mode switch. +The complete definitions are in [`shortcuts.def`](../src/mod/shortcuts.def). + +## Accepted key names ### Modifiers -Modifiers are not required, any specified must be used together: - -Value | Key | Value | Key | Value | Key ---: | :-- | --: | :-- | --: | :-- -"SHIFT" | LeftShirt or RightShift | "LSHIFT" | LeftShift | "RSHIFT" | RightShift -"CTRL" | LeftControl or RightControl | "LCTRL" | LeftControl | "RCTRL" | RightControl -"ALT" | LeftAlt or RightAlt | "LALT" | LeftAlt | "RALT" | RightAlt -"WIN" | LeftWindows or RightWindows | "LWIN" | LeftWindows | "RWIN" | RightWindows -"ALTGR" | AltGr - -### Keys - -Only key can be set at one time: - -Value | Key | Value | Key | Value | Key | Value | Key ---: | :-- | --: | :-- | --: | :-- | --: | :-- -"HOME" | Home | "END" | End | "PGUP" | PageUp | "PGDOWN" | PageDown -"LEFT" | LeftArrow | "RIGHT" | RightArrow | "UP" | UpArrow | "DOWN" | DownArrow -"BACKSPACE" | Backspace | "CLEAR" | Clear | "CAPS" | CapsLock | "BREAK" | Break -"INSERT" | Insert | "DELETE" | Delete | "HELP" | Help | "MENU" | Menu -"PAUSE" | Pause | "PRINT" | Print | "SPACE" | Space | "RETURN" | Return -"SCROLL" | ScrollLock | "SYSREQ" | SysReq | "TAB" | Tab | "SPACE" | Space -"MOUSE0" | Mouse0 | "MOUSE1" | Mouse1 | "MOUSE2" | Mouse2 | "MOUSE3" | Mouse3 -"MOUSE4" | Mouse4 | "MOUSE5" | Mouse5 | "MOUSE6" | Mouse6 | "MINUS" | Minus | -"'" | Quote | "_" | Underscore | "," | Comma | "." | Period -";" | Semicolon | ":" | Colon | "!" | Exclaim | "?" | Question -"(" | LeftParen | ")" | RightParen | "[" | LeftBracket | "]" | RightBracket -"{" | LeftCurlyBracket | "}" | RightCurlyBracket | "@" | At | "*" | Asterisk -"/" | Slash | "\" | Backslash | "\"" | DoubleQuote | "&" | Ampersand -"#" | Hash | "%" | Percent | "`" | BackQuote | "^" | Caret -"+" | Plus | "<" | Less | "=" | Equals | ">" | Greater -"|" | Pipe | "~" | Tilde | "$" | Dollar | - | - -"F1" | F1 | "F2" | F2 | "F3" | F3 | "F4" | F4 -"F5" | F5 | "F6" | F6 | "F7" | F7 | "F8" | F8 -"F9" | F9 | "F10" | F10 | "F11" | F11 | "F12" | F12 -"F13" | F13 | "F14" | F14 | "F15" | F15 -"0" | Alpha0 | "1" | Alpha1 | "2" | Alpha2 | "3" | Alpha3 -"4" | Alpha4 | "5" | Alpha5 | "6" | Alpha6 | "7" | Alpha7 -"8" | Alpha8 | "9" | Alpha9 -"A" | A | "B" | B | "C" | C | "D" | D -"E" | E | "F" | F | "G" | G | "H" | H -"I" | I | "J" | J | "K" | K | "L" | L -"M" | M | "N" | N | "O" | O | "P" | P -"Q" | Q | "R" | R | "S" | S | "T" | T -"U" | U | "V" | V | "W" | W | "X" | X -"Y" | Y | "Z" | Z -"KEY0" | Keypad0 | "KEY1" | Keypad1 | "KEY2" | Keypad2 | "KEY3" | Keypad3 -"KEY4" | Keypad4 | "KEY5" | Keypad5 | "KEY6" | Keypad6 | "KEY7" | Keypad7 -"KEY8" | Keypad8 | "KEY9" | Keypad9 | "KEYDIVIDE" | KeypadDivide | "KEYENTER" | KeypadEnter -"KEYEQUAL" | KeypadEquals | "KEYMINUS" | KeypadMinus | "KEYMULTI" | KeypadMultiply | "KEYPERIOD" | KeypadPeriod -"KEYPLUS" | KeypadPlus | "NUMLOCK" | Numlock - -**NOTE**: Default shortcuts are shown in the [README.md](README.md) - -## License - -- GPLv3 - -## Camera movement - -In mod-hotkey mode, system and galaxy panning uses `move_up`, `move_down`, `move_left`, and `move_right`. -Defaults are `W|UP`, `S|DOWN`, `A|LEFT`, and `D|RIGHT`. Existing configured values take precedence; -for example, `move_left = "LEFT"` keeps left-arrow-only movement until you add `A`. -Modifiers follow the normal shortcut rules, so `CTRL-S` does not also match plain `S` movement. -`disable_move_keys` disables keyboard panning; Scopely-hotkey mode retains native pan input. +| Modifier | Either side | Left only | Right only | +| --- | --- | --- | --- | +| Shift | `SHIFT` | `LSHIFT` | `RSHIFT` | +| Control | `CTRL` | `LCTRL` | `RCTRL` | +| Alt | `ALT` | `LALT` | `RALT` | +| Windows | `WIN` | `LWIN` | `RWIN` | +| Command | `CMD` or `APPLE` | `LCOM` or `LAPPLE` | `RCOM` or `RAPPLE` | + +`ALTGR` selects AltGr. On macOS, `CTRL` means Control; use `CMD` for Command. + +### Letters, numbers, and function keys + +| Group | Names | +| --- | --- | +| Letters | `A` to `Z` | +| Number row | `0` to `9` | +| Function keys | `F1` to `F15` | +| Number pad | `KEY0` to `KEY9` | +| Number-pad operations | `KEYDIVIDE`, `KEYENTER`, `KEYEQUAL`, `KEYMINUS`, `KEYMULTI`, `KEYPERIOD`, `KEYPLUS`, `NUMLOCK` | + +### Navigation and mouse + +| Group | Names | +| --- | --- | +| Arrows | `LEFT`, `RIGHT`, `UP`, `DOWN` | +| Navigation | `HOME`, `END`, `PGUP`, `PGDOWN`, `INSERT`, `DELETE` | +| Common keys | `BACKSPACE`, `ESCAPE`, `RETURN`, `SPACE`, `TAB` | +| Other keys | `BREAK`, `CAPS`, `CLEAR`, `HELP`, `MENU`, `PAUSE`, `PRINT`, `SCROLL`, `SYSREQ` | +| Mouse buttons | `MOUSE0` to `MOUSE6`. `MOUSE0` is left, `MOUSE1` is right, and `MOUSE2` is middle. | + +### Punctuation + +Use `MINUS` for the minus key because `-` separates modifiers. +The pipe character `|` separates alternatives and cannot be bound as a key. + +Other accepted symbols are: + +```text +_ , ; : ! ? . ' ( ) [ ] { } @ * / " \ & # % ` ^ + < = > ~ $ +``` + +TOML double-quoted strings need escapes for a backslash or double quote. +Literal strings avoid those escapes: + +```toml +[shortcuts] +show_gifts = '\' +show_chat = '"' +``` From 65a7927d34edb0ded64c7561bff3213f91cb47b9 Mon Sep 17 00:00:00 2001 From: tashcan Date: Thu, 15 Oct 2026 16:40:43 -0700 Subject: [PATCH 2/2] Document checks for bindings A focused IL2CPP reference covers member resolution, calls, hooks and GC ownership. Contributor guidance is rewritten around the domain modules and native regression fixtures. The changelog records the runtime, settings, sync and launcher work covered so far. --- AGENTS.md | 211 +++++++++++++++------------------ CHANGELOG.md | 219 +++++++++++++++-------------------- CONTRIBUTING.md | 172 +++++++++++++-------------- docs/IL2CPP.md | 172 +++++++++++++++++++++++++++ docs/THIRD_PARTY.md | 12 ++ docs/VERSION_SUBSTITUTION.md | 91 +-------------- 6 files changed, 463 insertions(+), 414 deletions(-) create mode 100644 docs/IL2CPP.md create mode 100644 docs/THIRD_PARTY.md diff --git a/AGENTS.md b/AGENTS.md index 2669b3627..c585bc274 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,123 +1,104 @@ -# AGENTS.md +# Agent guide -This file provides guidance to AI coding agents working with code in this repository. +STFC Community Mod hooks a Unity IL2CPP game to add desktop features on Windows and macOS. +Read [CONTRIBUTING.md](CONTRIBUTING.md) for builds and tests. +Before changing bindings or hooks, read the [IL2CPP reference](docs/IL2CPP.md). -## Project Overview +## Keep changes scoped -Community mod for Star Trek Fleet Command (STFC) — a desktop game that runs via Unity/IL2CPP. The mod hooks into the game's IL2CPP runtime to add QoL features (UI scaling, zoom controls, hotkeys, chat improvements, cargo viewers, data sync, etc.). Supports Windows (DLL proxy injection) and macOS (dylib injection). +- Stage only task-related files. Leave unrelated edits and generated artifacts alone. +- Preserve client enum catalogs in `src/mod/game/`, including unused IDs for future features. +- Run `git diff --check` and the narrowest relevant xmake build before finishing C++ or patch work. +- Review hooks, platform guards, config defaults, and the English settings example in the final diff. +- Put specialized subtree rules in a nearby `AGENTS.md`. -## Build System +## Build and check -This project uses **XMake** (not CMake). All build configuration is in `xmake.lua` files. Language standard is C++23 with multi-threaded static runtime (`/MT`). +The project uses xmake and C++23. Build on the target platform; the Swift launcher requires macOS and Xcode. -### Build Commands - -```bash -# Configure and build (command line) -xmake # Build default target -xmake f -p macosx -a arm64 -m debug --target_minver=14.6 # Configure for macOS ARM debug -xmake f -p windows -m release # Configure for Windows release - -# Generate Visual Studio solution -xmake project -k vsxmake -m "debug,release" - -# Clean -xmake clean -a - -# macOS dev script (build, run, debug, crashlogs) -scripts/mac-build-test-debug.sh [build|run|debug|crashlogs] [-m debug|release|releasedbg] +```sh +xmake f -c -p macosx -a arm64 -m release -y +xmake build -y +xmake build -y il2cpp-bindings-tests il2cpp-gc-tests mod-logic-tests sync-logic-tests config-reload-tests unity-tracker-tests launcher-rsync-tests ``` -### Build Modes -- `debug` — development -- `release` — production -- `releasedbg` — release with debug info, enables `_MODDBG` define - -### Reset Build -Delete the `build/` folder to reset. Also delete `.vs/` for a full Visual Studio reset. - -## Repository Expectations - -- Keep changes scoped. Do not stage unrelated dirty files or generated artifacts unless the user explicitly asks. -- Before finishing C++ or patch work, run `git diff --check` and the narrowest relevant xmake build. -- For macOS core mod changes, use `xmake f -p macosx -a arm64 -m debug --target_minver=14.6 -y && xmake -y mods`. -- Review the final diff for risky hooks, platform guards, config default mismatches, and missing example config updates. -- If a subtree such as `macos-launcher/` needs specialized guidance, prefer a nested `AGENTS.md` near that code instead of overloading this root file. - -## Architecture - -### Build Targets (xmake.lua files) - -| Target | Type | Platform | Description | -|---|---|---|---| -| `mods` | static lib | all | Core mod logic — patches, config, IL2CPP bindings | -| `stfc-community-mod` (win-proxy-dll) | shared DLL | Windows | Proxy DLL (`version.dll`) that loads into the game process | -| `stfc-community-mod` (macos-dylib) | shared dylib | macOS | Injected dylib equivalent | -| `stfc-community-mod-loader` | binary | macOS | Loader that injects the dylib into the game | -| `macOSLauncher` | Xcode app | macOS | Swift GUI launcher app | - -### Source Layout - -- **`src/mod/`** — Core mod code (the main codebase) - - `config.h/.cc` — Singleton `Config` class, loads TOML settings, controls which patches are enabled - - `patches/patches.cc` — Entry point: hooks `il2cpp_init`, then conditionally installs each patch - - `patches/parts/` — Individual patch implementations (zoom, hotkeys, chat, UI scale, sync, etc.) - - `patches/key.h`, `mapkey.h`, `modifierkey.h` — Keyboard input mapping system - - `prime/` — Header-only IL2CPP type definitions mirroring the game's C# classes - - `prime/proto/` — Protobuf definitions for game data sync - - `il2cpp/` — IL2CPP helper functions for resolving methods, classes, and icalls at runtime -- **`src/platform/windows/`** — Windows DLL proxy entry point -- **`src/platform/macos/dylib/`** — macOS dylib entry point -- **`src/platform/macos/loader/`** — macOS loader (finds game, injects dylib) -- **`macos-launcher/`** — Swift macOS GUI app -- **`third_party/libil2cpp/`** — IL2CPP SDK headers -- **`xmake-packages/`** — Custom xmake package definitions (e.g., `spud`) - -### Key Patterns - -**Hooking pattern** — All game function hooks use `spud` (function detour library) via `SPUD_STATIC_DETOUR`. Each hook function takes `auto original` as the first parameter to call through to the original: -```cpp -void SomeFunction_Hook(auto original, SomeClass* _this, ...) { - // custom logic - original(_this, ...); -} -``` -macOS does not tolerate repeated hooks of the same function. If multiple features need to intercept the same game method, consolidate the behavior behind one detour or add platform guards instead of installing overlapping hooks. -Do not over-focus on hidden IL2CPP `MethodInfo*` parameters during drift repair; match the game-visible signature from `dump.cs` unless there is concrete runtime evidence that the hidden parameter is the issue. -Before adding a detour to a small IL2CPP wrapper or thunk, verify its native method extent against SPUD's architecture-specific overwrite size on every supported architecture for the exact client build. A successful platform build does not validate hook fit; prefer a substantive downstream method when exact per-architecture extent is unavailable. - -**IL2CPP class resolution** — Game classes are resolved at runtime using helpers: -```cpp -static auto class_helper = il2cpp_get_class_helper("Assembly.Name", "Namespace", "ClassName"); -static auto method = class_helper.GetMethodInfo("MethodName"); -``` - -**Adding a new patch** — Create a `.cc` file in `src/mod/patches/parts/`, write an `InstallXxxHooks()` function, declare it in `patches.cc`, add a `bool installXxx` to `Config`, and register it in the `patches[]` array in `patches.cc`. Hook-install toggles are read from the `[patches]` TOML table in all build modes and should default to `true`; they exist as emergency compatibility switches for hook collisions or client drift. - -**Separate hook installation from feature enablement** — Do not use a user-facing feature setting to decide whether its hooks are installed. Normally install all supported hooks, then have each hook check the feature setting and immediately preserve native behavior (usually by calling `original`) when the feature is disabled. Keep hook-install switches under `[patches]` and feature settings in their relevant sections such as `[ui]`, `[graphics]`, or `[audio]`; never place a feature-only toggle under `[patches]`. If an installer contains an early return based on a feature setting, or a `patches[]` entry points directly at a feature setting, treat that as a design error. Helpers that install no hooks, such as shortcut-only behavior, do not belong in `patches[]` at all. - -**Config** — User settings are in TOML files. The `Config` singleton (`Config::Get()`) is loaded once during `il2cpp_init_hook`. Add new settings to `config.h`, add defaults in `defaultconfig.h`, and load them in `config.cc`. For user-facing settings, update only the English example (`example_community_patch_settings_en.toml`). Do not update the other localized examples unless the user explicitly asks for translation updates. The unsuffixed `example_community_patch_settings.toml` is only a pointer to these localized examples and should not be changed when adding or modifying settings. - -### Dependencies (via xmake packages) - -- `spud` — Function hooking/detour library -- `eastl` — EA's STL replacement -- `spdlog` — Logging -- `toml++` — TOML config parsing -- `nlohmann_json` — JSON handling -- `cpr` / `libcurl` — HTTP requests (for data sync) -- `protobuf` — Protocol buffers (game data) -- `simdutf` — UTF encoding -- `libil2cpp` — Local package pointing to `third_party/libil2cpp` - -## Code Style - -- Uses `.clang-format` — 2-space indent, 120 column limit, Linux brace style, aligned assignments/declarations -- Version is defined in `src/mod/version.h` (VERSION_MAJOR/MINOR/REVISION/PATCH) -- Prefer narrow platform guards such as `#if _WIN32`, `#if !_WIN32`, and `#if __APPLE__`; do not assume every non-Windows path is macOS. -- Logging via `spdlog::info()`, `spdlog::debug()`, etc. - -## Branches - -- `main` — stable releases -- `dev` — active development (PR target) +Run each matching test with `xmake run `. +The x64-only `spud-relocation-tests` target checks detour relocation. +See [contributor checks](CONTRIBUTING.md#run-checks-before-submitting) for coverage. + +## Source map + +| Path | Responsibility | +| --- | --- | +| `src/libs/il2cpp/` | Generic runtime bindings, calls, strings, GC handles, and detours | +| `src/libs/unity/` | Unity core, UI, TextMeshPro, input, and instance tracking | +| `src/mod/mod.h`, `mod.cc` | Startup, feature installation, and the frame tick | +| `src/mod/config.h`, `config.cc` | Typed settings, defaults, parsing, and reload | +| `src/mod/file.h`, `file.cc` | Settings, vars, log paths, and command-line flags | +| `src/mod/shortcuts.h`, `shortcuts.cc`, `shortcuts.def` | Chord parsing, matching, actions, defaults, tiers, and aliases | +| `src/mod/features/` | One file per feature domain, with its hooks, shortcuts, and state | +| `src/mod/game/` | Header-only STFC bindings, grouped by domain | +| `src/mod/game/proto/` | Protobuf definitions for sync | +| `src/mod/sync/` | Response processing, records, acknowledgements, uploads, battle journals, and fleet state | +| `src/mod/text.h`, `features/toast_text.h` | Game-free text helpers used by tests | +| `src/platform/` | Windows proxy DLL, macOS dylib entry point, and macOS loader | +| `src/launcher/macos/` | Swift launcher for updates, entitlements, and game launch | +| `tests/` | Controlled-runtime, mod, sync, detour, and launcher tests | +| `zig/`, `third_party/` | Build logic and vendored dependencies | +| `docs/`, `scripts/` | User guides, example settings, and release or verification tools | + +Features own behavior; bindings own game access. +Reusable IL2CPP or Unity helpers belong in their libraries. +Feature files never declare bindings or call raw `il2cpp_*` APIs. +Dependency pins and notices are listed in [THIRD_PARTY.md](docs/THIRD_PARTY.md). + +## Add or change a feature + +1. Extend the domain file in `src/mod/features/`, or add one named after the feature's purpose. +2. Keep installation private. Export a descriptor such as `const Feature kXxx{"Xxx", &Config::Patches::group, InstallXxx};`. +3. Declare the descriptor in `features/features.h` and add it to `kFeatures` in `mod.cc`. +4. For a new hook group, add a `[patches]` member defaulting to `true` and read it in `Config::Read`. + +Shortcut-only helpers need no descriptor. +Frame features supply their frame function as the descriptor's fourth member and return early when disabled. + +Only `[patches]` keys decide which hooks install. They are restart-only switches for conflicts and client drift. +Feature settings belong in sections such as `[ui]`, `[graphics]`, or `[audio]`. +Install hooks even when a feature is disabled. Each hook reads the current setting and cheaply calls `original` when off. + +## Hooks and frame work + +- Use `IL2CPP_HOOK` or `IL2CPP_DETOUR` from ``. Name callbacks `Class_Method_Hook` and take `auto original` first. +- Each macro expansion owns one target. Prefer one detour per game method; chained detours depend on installation order. +- Before hooking a small wrapper or thunk, verify its native extent against SPUD's overwrite size on every supported architecture for the exact client. A build does not prove fit. +- Match game-visible signatures from `dump.cs`. Change hidden `MethodInfo*` handling only with runtime evidence. +- Keep the single `ScreenManager.Update` hook in `mod.cc`. Other hooks that read keys must call `unity::Key::Poll()` first. + +The frame tick polls input, checks for settings changes, runs installed feature frame functions, then dispatches shortcuts. +Hooks run in no fixed order within a frame. Reads before polling see the previous frame's input. + +## Settings and shortcuts + +`Config::Get()` is game-thread-only. Call it where needed; a reload replaces the object, so do not retain its reference. +Background sync workers retain immutable `Config::Sync::Get()` snapshots. +`Config::Parse` reads a TOML table without touching files or live bindings. + +When changing settings: + +1. Add section members in `config.h`, named after TOML keys and initialized to their defaults. +2. Read them with `r.Read(section, key, member)` in `Config::Read`. +3. Update only the [English example](docs/configuration/example_community_patch_settings_en.toml). Update translations only when requested. +4. Run `zig build test-mod`; it checks agreement between the reader and English example. + +The unsuffixed example is a pointer to translations. Do not change it for new settings. +Actions, TOML keys, defaults, optional tiers, and aliases belong in `shortcuts.def`. +Feature files keep dispatch order and context checks. + +## Code and writing style + +- Use `.clang-format` through `zig build fmt`: two-space indentation, 120 columns, Linux braces, and aligned declarations. It skips `.mm` files. +- Use fixed-width numeric types. Prefer narrow platform guards such as `#if _WIN32`, `#if !_WIN32`, and `#if __APPLE__`. +- Log with `spdlog`. Version components live in `src/mod/version.h` as `VERSION_MAJOR`, `VERSION_MINOR`, `VERSION_REVISION`, and `VERSION_PATCH`. +- Keep docs task-first, concise, and written in plain technical English. Use short paragraphs and varied sentence lengths. + +`main` holds stable upstream releases. `dev` is the upstream development and pull-request target. diff --git a/CHANGELOG.md b/CHANGELOG.md index 07b393134..b8829b5c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,170 +1,133 @@ -# Star Trek Fleet Command - Community Mod +# Changelog -

- License: GPLv3 - Sponsorship -

+These are historical release notes. Settings, shortcuts, and build tools below describe those releases. +For current behavior, see [Features](docs/FEATURES.md), [Keyboard shortcuts](docs/KEYMAPPING.md), and [Contributing](CONTRIBUTING.md). -

- A community mod (patch) that adds a couple of tweaks to the mobile game Star Trek Fleet Command™ -

+## 1.1.0 + +### Features -# Change Log +- Standardized naming on "mod" and added `AGENTS.md`. By @a5ehren. +- Added tech-slot sync. By @lightbull-stfc. +- Added splash and transition artwork. By @ChronoXNL. +- Added macOS version-string substitution. By @ttimbul. -## 1.1.0 +### Fixes + +- Fixed global and per-target `verify_ssl` parsing, including use without a proxy. By @joelverhagen. +- Disabled faulty features in the example settings. By @Bloody142. +- Temporarily ignored `disable_first_popup`. By @a5ehren. +- Pinned the protobuf Abseil dependency to `20260107.1` to match its inline namespace. By @ChronoXNL. +- Restricted the `setDepth` hook to Windows and corrected macOS signing entitlements. By @a5ehren. + +### New contributors -## Features -- Update naming conventions to be consistent (mod vs patch) by @a5ehren -- Add support for syncing tech slots by @lightbull-stfc -- Add an AGENTS.md file to the repo by @a5ehren -- Add new splashscreen and transition image by @ChronoXNL -- MacOS Specific - - Include Version string substitution for MacOS build by @ttimbul - -## Fixes -- Fix: verify_ssl not working without proxy and not parsed per-target by @joelverhagen -- Fix: Set faulty features to false in example_community_patch_settings.toml by @Bloody142 -- Fix: temporarily ignore the disable_first_popup option by @a5ehren -- Fix: pin protobuf abseil dep to 20260107.1 to match inline namespace by @ChronoXNL -- MacOS specific - - Max sure setDepth hook is only registered on Windows by @a5ehren - - Correct entitlements for App Signing by @a5ehren - -## New Contributors -* @dependabot[bot] -* @ttimbul -* @joelverhagen -* @wycats +@dependabot[bot], @ttimbul, @joelverhagen, and @wycats. ## 1.0.0 ### Features -- Added support for macOS -- Added documentation for Wine and also for Mac -- Added maximum donation for alliance sliders -- Added prefix to title when using `-ccm` command line option to show which is being used [windows only] -- Added suppression of first message notification - -- Added new configuration options: - - `ui_scale_viewer` to scale the size of object viewers - - `select_current` hotkey to locate currently selected ship in dock - - `UiViewerScaleUp` and `UiViewerScaleDown` hotkeys to scale `ui_scale_viewer` in game - - `toggle_queue`, `action_queue` and `action_queue_cancel` for Kir'Shara artifact handling - - `action_quit` for instant game exit - - `select_timer` to adjust period in which double tap ship selection works [default 500ms] - - `disable_veil_chat` to disable the veil chat tab - -- Updated sync methods to: - - allow multi-targets - - better handle errors - - include missions - - include officer shard counts - - better handle battlelogs -- Added new key mappings: - - Y: Show Scrap Yard (`show_scrapyard`) +- Added macOS support and installation guides for macOS and Wine. +- Added maximum Alliance donation sliders and first-message notification suppression. +- Added a Windows title prefix for the `-ccm` profile. +- Improved multi-target sync, error handling, and battle logs. Added missions and officer shard counts. +- Added `Y` for Scrap Yard through `show_scrapyard`. + +New settings and controls: + +| Setting or control | Purpose | +| --- | --- | +| `ui_scale_viewer` | Scale object viewers | +| `select_current` | Locate the selected ship in dock | +| `UiViewerScaleUp`, `UiViewerScaleDown` | Adjust viewer scale during play | +| `toggle_queue`, `action_queue`, `action_queue_cancel` | Control the Kir'Shara queue | +| `action_quit` | Exit immediately | +| `select_timer` | Set the ship-selection double-tap interval, default 500 ms | +| `disable_veil_chat` | Hide Veil Chat | ### Fixes -- Fixed various unity engine upgrades causing issues -- Fixed `ui_scale` or `ui_scale_viewer` so when set to 0.0f disable those scaling features -- Fixed `zoom_min` and `zoom_max` no longer set default system zoom (only presets can) -- Fixed numerous method hooks to report when they are not found rather than crash -- Fixed issue where a widget may not have a visibility controller for some reason causing a crash -- Fixed warp cancellation so it works again +- Repaired compatibility after Unity upgrades and restored warp cancellation. +- Made `ui_scale = 0.0` and `ui_scale_viewer = 0.0` disable scaling. +- Stopped `zoom_min` and `zoom_max` from setting entry zoom. Only presets can do that. +- Reported missing hook methods instead of crashing. +- Prevented a crash when a widget has no visibility controller. -### Dev stuff +### Development -- Switch to xmake -- log names of log, configuration, vars and battlelog files -- update github source to netniV's repo +- Switched to XMake. +- Logged the paths for log, settings, vars, and battle-log files. +- Changed the GitHub source to netniV's repository. ## 0.6.0 -- Add customisable hotkeys -- Add example configuration file -- Make ui_scaleup/ui_scaldown operate like zoom and can now be held -- Add ui_scale_adjust to allow changes to "step" between ui_scale's -- Add option to disable: - - Ship locate when preview window open - - Ending program via escape - - Movement via keyboard -- Add session-based adjustments that last until game is restarted: - - Add toggle cargo views (ALT 1-5) - - Add set zoom preset (SHIFT F1-F5) -- Fix speed issues with ObjectFinder by writing our own -- Adjust runtime configuration output: - - Rename 'community_patch_settings_parsed.toml' to 'community_patch_runtime.vars' to avoid confusion - - Add a massive comment to top of community_patch_runtimes.vars - - When possible report bad configuration values -- Add new key mappings: - - N: Manage Ship - - R: Repair Ship - - U: Show Resarch - - CTRL-ALT-MINUS: Disable all hotkeys - - CTRL-ALT-EQUAL: Enable all hotkeys - - F9: Log level to Debug - - F11: Log level to Info - - SHIFT-T: Show Away Team - - SLASH (Forward): Show Gifts - - SLASH (Backward): Show Alliance - - CTRL-L: Toggle whether Locate will work when preview popup visible - - CTRL-R: Toggle whether Recall will work when preview popup visible - - ALT-1: Toggle whether Cargo will show for Default - - ALT-2: Toggle whether Cargo will show for Player - - ALT-3: Toggle whether Cargo will show for Station - - ALT-4: Toggle whether Cargo will show for Hostile - - ALT-5: Toggle whether Cargo will show for Armada -- Add new key mappings (alpha testing only due to implementation issues): - - SHIFT-SLASH (Backward): Show Alliance Help - - CTRL-SLASH (Backward): Show Alliance Armada - - l: Show Lookup +### Features and fixes -## 0.5.2 +- Added configurable hotkeys and an example settings file. +- Added held UI-scale controls and `ui_scale_adjust` for their step size. +- Added switches to block ship location while a preview is open, Escape-to-exit, and keyboard movement. +- Added session-only cargo toggles and zoom-preset saving. +- Replaced ObjectFinder to improve speed. + +Renamed `community_patch_settings_parsed.toml` to `community_patch_runtime.vars`, expanded its header comment, and improved invalid-value reporting. -- fix free resize not working anymore -- restrict the stay in bundle after summary behavior to officer and event store -- add player names to battle log sync -- fix trait sync not working -- add sync of active missions +### Shortcut additions -## 0.5.0 (future) +| Keys | Action | +| --- | --- | +| `N`, `R`, `U` | Manage ship, repair ship, show Research | +| `CTRL-ALT-MINUS`, `CTRL-ALT-EQUAL` | Disable, enable hotkeys | +| `F9`, `F11` | Set log level to debug, info | +| `SHIFT-T` | Show Away Team | +| Forward slash, backslash | Show Gifts, Alliance | +| `CTRL-L`, `CTRL-R` | Toggle locate, recall while a preview is open | +| `ALT-1` to `ALT-5` | Toggle default, player, station, hostile, and armada cargo | +| `SHIFT-F1` to `SHIFT-F5` | Save zoom presets for the session | + +Alpha-only additions were Shift-backslash for Alliance Help, Ctrl-backslash for Alliance Armada, and `L` for Lookup. + +## 0.5.2 -- add default toml config when none exists with default values +- Repaired free window resizing. +- Limited staying in a bundle after its summary to the officer and event stores. +- Added player names to battle-log sync. +- Fixed trait sync. +- Added active-mission sync. -- add parsed toml config output to show what settings are in use +## 0.5.0 -- add zoom shortcuts (minus, equals, backspace) to provide max, default and minimum zoom +Recorded as planned in the original notes: -- add more keyboard shortcuts for missions (daily, away, etc), station views, quick chat +- Generate a default TOML file and parsed output showing effective settings. +- Add minimum, default, and maximum zoom shortcuts. +- Add shortcuts for missions, station views, and chat. ## 0.4.0 -- who knows +No details recorded. ## 0.3.8 -- add drydock H hotkey +Added the drydock `H` hotkey. ## 0.3.2 -- add compatibility with Unity 2020.3 LTS +Added Unity 2020.3 LTS compatibility. ## 0.3.1 -- add option to disable galaxy chat -- fix a bug where [Space] didn't trigger correctly +- Added an option to hide Galaxy Chat. +- Fixed cases where Space did not trigger. ## 0.3.0 -- add recall option, this is bound to `R` when not having another item selected that has an `R` action -- remove fix for iss jellyfish as this is now fixed in the regular client (`fix_iss_jellyfish_warp` config no longer has any effect) -- remove fix for stella as this is now fixed in the regular client (`fix_stella` config no longer has any effect) -- remove fix for faction as this is now fixed in regular client (`fix_faction` config no longer has any effect) -- re-enable free resizing of window regardless of aspect ratio -- extend alliance donation slider to be the amount required to reach the next alliance level -- extend ship selection hotkeys to 7 +- Added `R` to recall when no other selected item uses that action. +- Retired `fix_iss_jellyfish_warp`, `fix_stella`, and `fix_faction` after fixes in the game client. +- Restored free window resizing. +- Extended Alliance donations to the amount needed for the next Alliance level. +- Extended ship-selection hotkeys to seven ships. -# 0.2.0 +## 0.2.0 -- initial release +Initial release. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 681f0d854..7c7129205 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,103 +1,103 @@ -# Star Trek Fleet Command - Community Mod +# Contribute to STFC Community Mod -

- License: GPLv3 - Sponsorship -

+Send pull requests to **`dev`**. Run commands from the repository root. -

- A community mod (patch) that adds a couple of tweaks to the mobile game Star Trek Fleet Command™ -

+## Build for your platform -# Contributing +Install xmake and the native C++ toolchain. On macOS, install Xcode and its command-line tools. +Initialize the launcher dependency before building: -This project is entirely maintained in my own personal free time, and updated as and when that time -is available. Any help by submitting pull requests is greatly welcome and any donations or -sponsorships are greatly appreciated. - -## Building - -First clone and initialize the repository: - -```bash -git clone https://github.com/STFC-Mod/mod.git stfc-mod -cd stfc-mod +```sh +git submodule update --init --recursive +xmake f -c -p macosx -a arm64 -m release -y +xmake build -y ``` -## Installing - -Please note that when this project compiles, it will create a DLL called `stfc-community-mod.dll`. This -file must be either copied to the `C:\Games\Star Trek Fleet Command\Star Trek Fleet Command\default\game` -folder as `version.dll` or create a symbolic link to the file using an elevated (administrator) command -prompt: - -```console -cd C:\Games\Star Trek Fleet Command\Star Trek Fleet Command\default\game -mklink version.dll [output folder]\stfc-community-mod.dll +For Intel macOS, use `-a x86_64`. On Windows, use an x64 Visual Studio developer shell and configure `-p windows -a x64`. +The default build includes the mod and platform entry points; macOS also builds the Swift launcher. +Outputs are under `build////`. +Copy `version.dll` beside the game's `prime.exe` on Windows. + +`--bg_image=` changes the embedded loading image; `--use_original_bg=y` keeps the game background. +Use `-m releasedbg` for diagnostic builds. `[patches]` switches work in every build. +Dependencies remain in `xmake/dependencies/`, the local package repository in `xmake-packages/`, and `xmake-requires.lock`. + +## Run checks before submitting + +Run `git diff --check` and the relevant platform build. +Build and run the native fixtures that cover your change: + +| Target | Coverage | +| --- | --- | +| `il2cpp-bindings-tests` | Typed runtime bindings and keyboard snapshots | +| `il2cpp-gc-tests` | Managed GC handles | +| `unity-tracker-tests` | Live instance tracking | +| `mod-logic-tests` | Settings reader, shortcut defaults, and text helpers | +| `config-reload-tests` | Configuration replacement and ownership | +| `sync-logic-tests` | Wire fixtures, retries, removals, target changes, and sessions | +| `spud-relocation-tests` | x64 detour relocation | +| `launcher-rsync-tests` | Real rsync deltas and I/O failures | + +For example: + +```sh +xmake build -y mod-logic-tests +xmake run mod-logic-tests +python3 scripts/validate-example-configs.py ``` -If you do link the file, please note you will need to close the game to recompile. +Tests need no game. Run them on the matching operating system and architecture. +Compilation and fake-runtime tests do not verify native hook fit or behavior in the running game. -### Visual Studio - -#### SDK Warning - -You may see the following error, and this normally occurs if your SDK is below the minimum required. - -``` -The and headers are only supported with /await and implement pre-C++20 coroutine support. Use for standard C++20 coroutines -``` +## Change code -If you have Visual Studio 2022, make sure to have the Windows 11 SDK selected as a minimum, even if you -are running the Visual Studio IDE on Windows 10. The Windows 11 SDK will also create targets that work -for Windows 10. +Read [AGENTS.md](AGENTS.md) for the source map and project rules. +The [IL2CPP reference](docs/IL2CPP.md) covers bindings, calls, hooks, and managed object lifetimes. -You can do this via the Visual Studio Installer. The Visual Studio Installer will show any other versions -of Visual Studio, so please make sure to use the `Modify` button on the correct one. You can launch the -Visual Studio Installer from within Visual Studio 2022 via the `Tools -> Get Tools and Features` menu -option, or through `Settings -> Apps -> Visual Studio -> Modify`. +Keep each feature's hooks, shortcuts, and state in its domain file under `src/mod/features/`. +Game bindings belong in `src/mod/game/`; reusable IL2CPP and Unity code belongs in the libraries. +Preserve client enum catalogs, including unused IDs needed for future work. -Once you are modifying the correct Visual Studio 2022 instance, select the `Individual Components` tab and -click into the Filter textbox. Enter the type `SDK` which should provided a minimal filtered list of SDK's -available. You should see Windows 11 SDK listed and has a tick. If not, please click the tick box and then -apply the changes to have the SDK downloaded and installed. This will take around 2-3GB of space. +Settings and defaults live in `config.h` and `Config::Read`. +Update the English example when changing a user-facing setting. +Shortcut definitions live in `src/mod/shortcuts.def`; feature files retain dispatch order and context checks. -#### Configure and building the project +### Repair bindings after a game update -Once they are installed, either standalone or via Visual Studio, you can configure the `stfc-mod` project. -We are using [XMake](https://xmake.io/#/). -To configure a Visual Studio solution, simple run the following on the Command Line. +Dump the new client with Il2CppDumper, then compare it with the previous dump: -```powershell -xmake project -k vsxmake -m "debug,release" +```sh +python3 scripts/check-il2cpp-dump.py check /path/to/new/dump.cs --old /path/to/old/dump.cs +python3 scripts/check-il2cpp-dump.py diff /path/to/old/dump.cs /path/to/new/dump.cs ``` -You will now find a `stfc-mod.sln` file inside `vsxmake2022`(or similarly named). You can simply open that in `Visual Studio` -and Build the solution. -**IMPORTANT**: To reset the build, you can remove the `build/` folder and all items beneath it. Visual -Studio will then rebuild the project. - -**IMPORTANT**: To fully reset the project, also remove the `.vs/` folder. - -### Visual Studio Code - -If you want to use Visual Studio Code, you may still need to make sure the various SDK's and MSVC runtimes -are available. - -Once they are installed, either standalone or via Visual Studio, you can open the `stfc-mod` folder inside -Visual Studio or by right clicking in a Windows Explorer via and selecting `Open with Visual Studio Code`. -When it first opens, it should ask you to install the XMake extension. Once the extensions are -installed, you can build the project by navigating to the XMake section in the Activity Bar and clicking `Build All` at the top. - -**IMPORTANT**: To reset the build, you can remove the `build/` folder and all items beneath it. Visual -Studio Code will then rebuild the project. - -### Command Line - -If you do not have Visual Studio Code, this project uses XMake, so the simplest way to build it on Windows: - -```ps1 -mkdir build -cd build -xmake -``` +The script finds missing classes, members, and hook targets, plus static and arity changes. +It uses text matching. Runtime type checks and in-game validation remain necessary. + +### Data sync ownership + +| File | Owns | +| --- | --- | +| `sync/sync.cc` | Game hooks and the raw response queue | +| `sync/records.cc` | Canonical records from game responses | +| `sync/state.cc` | Comparisons, removals, and per-target acknowledgements | +| `sync/upload.cc` | Sessions, the record store, target workers, and HTTP delivery | +| `sync/battlelogs.cc` | Battle-journal fetching | +| `sync/fleets.cc` | Client fleet records: state changes, snapshots, and late re-reads, on the game thread | +| `sync/fleet_watch.cc` | Fleet state polling, baselines, and transitions for fleet sync | + +Payload construction and HTTP run outside the store lock. +Session generations prevent old responses and acknowledgements from changing a new login. +Each target advances its cursor only after a 2xx response. Failures retry after one second, with exponential backoff up to one minute. + +The first full list establishes `X-PRIME-SYNC: 2`; retries retain it. +A delta before that list cannot claim a full baseline. +Removal records account for uploads that may have committed before a timeout. +After 1,024 unacknowledged new entities, delivery waits for an acknowledgement before introducing more. +Their latest values remain available. Version counters skip unchanged streams, and snapshots share record payloads. + +Ordinary categories retain observed state even while disabled, so a new target can receive a baseline. +Battle fetching is opt-in. Each target acknowledges the session's 300 recent journals independently; journals can replay after a restart or login. +Client fleet changes are a journal too: every state change is its own entry, delivered in order and never merged with a later one. A fleet snapshot entry is sent as a first sync. +The raw response queue holds 256 entries and drops the oldest on overflow. +Sync tests use controlled delivery results. They do not contact community services. diff --git a/docs/IL2CPP.md b/docs/IL2CPP.md new file mode 100644 index 000000000..3385c8d2c --- /dev/null +++ b/docs/IL2CPP.md @@ -0,0 +1,172 @@ +# IL2CPP binding reference + +The mod calls generated IL2CPP code through typed C++ bindings. +Bindings resolve members on first use, check metadata types, and cache the result for the process. +Runtime initialization must happen before resolution. + +## Library boundaries + +| Layer | Owns | +| --- | --- | +| `src/libs/il2cpp/` | Metadata, invocation, strings, boxing, allocation, GC handles, and detours. No engine or game dependency. | +| `src/libs/unity/` | UnityEngine, UI, TextMeshPro, input, and live MonoBehaviour tracking. No game dependency. | +| `src/mod/game/` | STFC class bindings, grouped by domain in headers. | + +Feature files call bindings. They do not declare bindings or use raw `il2cpp_*` APIs. +A helper that works for any IL2CPP game belongs in `il2cpp`; one that works for any Unity game belongs in `unity`. +The IL2CPP library reports errors through `il2cpp::SetErrorHandler`, without depending on mod settings or logging. + +## Binding shape + +A binding is an empty struct derived from `il2cpp::Object`. +Its pointer is the managed object itself. `Class` names the assembly, namespace, and managed type. + +```cpp +#include + +struct ShipView : il2cpp::Object { + using Class = il2cpp::Class<"Assembly-CSharp", "Digit.Prime.Ships", "ShipView">; + + float Scale() { return Get<"Scale", float>(); } + void SetScale(float scale) { Set<"Scale">(scale); } + int32_t count() { return Field<"_count", int32_t>(); } + void SetCount(int32_t count) { SetField<"_count">(count); } + bool Select(int32_t index) { return Call<"Select", bool>(index); } + bool TryPick(int32_t& slot) { return Call<"TryPick", bool(int32_t&)>(slot); } + + static ShipView* Current() { return Class::Get<"Current", ShipView*>(); } +}; +``` + +Accessor names follow managed members, without a leading `_` or `m_`. Setters use `SetX`. +Nested types use `"Outer/Inner"` as the class name. +Fixed-width numeric types keep the native ABI explicit. + +## Members and calls + +| Operation | API | +| --- | --- | +| Instance property | `Get<"Name", T>()`, `Set<"Name">(value)` | +| Instance field | `Field<"_name", T>()`, `SetField<"_name">(value)` | +| Instance method | `Call<"Name", R>(args...)` | +| Explicit signature | `Call<"Name", R(P...)>(args...)` | +| Static member | The same operation through `Class` | + +`R` defaults to `void`. +Calls jump to native code with a trailing `MethodInfo*`. Virtual calls dispatch on the receiver. +Fields use metadata offsets for reads and runtime setters for writes, including GC write barriers. + +Argument types select overloads. +`Foo::Class::TypeObject()` selects a `System.Type` overload rather than a string overload. +`std::ref(slot)` passes a `ref` or `out` argument. + +An explicit `R(P...)` signature converts arguments to `P` and rejects narrowing conversions. +`Call<"Select", void(int32_t)>(3)` accepts an integer literal but rejects an `int64_t` variable. +The conversion check runs after forwarding, so narrow integers and floats need typed values such as `uint8_t{7}` and `1.0f`. +A `T&` parameter binds the caller's variable directly, without `std::ref`. + +### Metadata checks + +| C++ type | Required metadata match | +| --- | --- | +| Pointer with a bound class | Managed reference related to the declared class, including named bindings, `Il2CppString*`, and `Il2CppReflectionType*`. | +| Untyped pointer | Managed reference, `IntPtr`, `UIntPtr`, or unmanaged pointer | +| Integer or enum | Managed integer of the same size | +| `bool`, `float`, `double`, or struct | Matching kind and size | + +A missing or drifted class or member is reported once. +Calls then do nothing and return a value-initialized result. +A managed exception is contained at the binding call, reported once per method, and produces the same default result. +It cannot unwind through the hook and skip the game's code. +`TryCall` is the same call for code that undoes its own changes when the game's code fails. +It returns an empty `std::optional`, or `false` for a void method, when the method is missing or threw. + +Receivers must be non-null. Check pointers returned by the game before calling methods through them. + +### Runtime classes and collections + +A binding without `Class` resolves against each receiver's runtime class, cached per class and thread. +This supports generic bases such as `Widget`, `MonoSingleton`, and `il2cpp::List`. +Some game bindings use this form when their managed class has moved between client builds. +They still belong in `src/mod/game/`. + +`il2cpp::List` supports indexed reads and `Set`, `Add`, `RemoveAt`, and `Clear`. +Its iterator reads `Count` once. Do not mutate the list during iteration. +`il2cpp::Array` views a managed array; its `Set` applies reference write barriers. + +### Unity internal calls + +Unity bindings use function-local static `il2cpp::ICall` objects for engine internal calls. +For example, `unity::Input` binds `UnityEngine.Input::GetKeyInt(UnityEngine.KeyCode)`. +Resolution happens on first use. Missing calls are reported once and return value-initialized results. +`operator bool` tests availability when a different fallback is needed. + +## Hooks + +`IL2CPP_HOOK` looks up a managed method and detours its native entry point through SPUD. +Hook names follow `Class_Method_Hook`. The first parameter is `auto original`. + +```cpp +#include + +void ShipView_Select_Hook(auto original, ShipView* _this, int32_t index) +{ + original(_this, index); +} + +void InstallShipView() +{ + IL2CPP_HOOK(ShipView::Class::Method("Select", 1), ShipView_Select_Hook); +} +``` + +The macro returns the original-call trampoline, or null on failure. +A missing method installs nothing. SPUD installation failures include the method name in the error. +`IL2CPP_DETOUR(address, hook, name)` handles native functions, including IL2CPP exports. + +| Lookup | Selects by | +| --- | --- | +| `Class::Method("Select")` | Name, any arity | +| `Class::Method("Select", 1)` | Name and parameter count | +| `Class::Method("Select", {"System.Int32"})` | Managed parameter type names | +| `Class::Method("Select")` | Complete instance signature | + +Each macro expansion owns one detour for the process. Use a separate expansion for each target. +Prefer one detour per game method, then route feature work through it. +SPUD can chain detours, but their order follows installation order. + +Before detouring a small wrapper or thunk, verify its native extent against SPUD's overwrite size. +Check every supported architecture for the exact client build. +A successful build does not prove the hook fits. Prefer a substantive downstream method when exact extents are unavailable. +During drift repair, match the game-visible signature in `dump.cs`. +Change hidden `MethodInfo*` handling only when runtime evidence points to it. + +## Objects and lifetimes + +| API | Behavior | +| --- | --- | +| `il2cpp::New(args...)` | Allocate and run the matching constructor | +| `il2cpp::Allocate()` | Allocate without a constructor, for classes whose parameterless constructor has no generated code | +| `NewString`, `ToUtf8`, `Equals` | Create, convert, or compare managed strings | +| `Box` | Box a primitive | +| `NewDelegate` | Bind a delegate to a static method, with an optional native redirect | +| `Guarded` | Contain Windows access violations when reading layouts that may have drifted | + +The GC scans native stacks, so managed pointers in local variables remain visible to it. +Pointers stored in C++ statics or heap objects need `GcHandle::Strong` roots. +`GcRoots` holds strong roots for the objects one operation touches and releases them together. +Its `healthy()` turns false once a root could not be taken. +Release roots before runtime shutdown. Roots do not destroy Unity native resources. + +`unity::Track()` tracks a class and its subclasses from hook installation onward. +It cannot discover instances created earlier. +`unity::Newest()` returns the newest tracked instance. +`unity::Instances()` owns a snapshot of borrowed pointers in creation order. +Use those pointers on the game thread within the current frame. + +The raw SDK is available to the libraries through ``. +On macOS, `il2cpp::Initialize` resolves exports from the loaded GameAssembly image. +Windows uses the checked-in import library. + +See [contributor checks](../CONTRIBUTING.md#run-checks-before-submitting) for tests and platform builds, +and [binding repair](../CONTRIBUTING.md#repair-bindings-after-a-game-update) for dump comparison commands. diff --git a/docs/THIRD_PARTY.md b/docs/THIRD_PARTY.md new file mode 100644 index 000000000..f52dcfb00 --- /dev/null +++ b/docs/THIRD_PARTY.md @@ -0,0 +1,12 @@ +# Third-party dependencies + +Preserve upstream licenses and notices when distributing source or binaries. + +The xmake dependency declarations live in `xmake/dependencies/`; local package definitions are in `xmake-packages/` and resolved versions are in `xmake-requires.lock`. +The launcher uses the PLzmaSDK submodule at `macos-launcher/deps/PLzmaSDK`. + +SPUD is vendored under `xmake-packages/packages/s/spud/spud-src` at `e4d0c78be89ef2587af33dd634ae5e8071935be7`. +Its upstream source and MIT license are unchanged. +`third_party/libil2cpp` contains the Unity SDK headers; the bundled sparsehash headers retain their BSD notices. + +Review dependency changes with their source provenance, platform configuration, and native build results. diff --git a/docs/VERSION_SUBSTITUTION.md b/docs/VERSION_SUBSTITUTION.md index e59213442..7847bcc48 100644 --- a/docs/VERSION_SUBSTITUTION.md +++ b/docs/VERSION_SUBSTITUTION.md @@ -1,87 +1,8 @@ -# Version Substitution in macOS Launcher +# Launcher version generation -## Overview +`src/mod/version.h` defines the four version components. +The launcher xmake target reads them during configuration and replaces `${VERSION}` in `src/launcher/macos/Info.plist.template`. +The generated `Info.plist` supplies `CFBundleShortVersionString` and `CFBundleVersion` to the app bundle. -The macOS launcher's `Info.plist` file now automatically uses the version defined in `src/mod/version.h` during the build process. This ensures consistency between the application version and the mod version. - -## Implementation - -### Files Involved - -- **Template**: `src/launcher/macos/Info.plist.template` - Contains version placeholders -- **Generated**: `src/launcher/macos/Info.plist` - Generated during build (not committed to git) -- **Source**: `src/mod/version.h` - Contains version definitions -- **Build**: `src/launcher/macos/xmake.lua` - Contains version extraction and substitution logic - -### Version Extraction - -The build process extracts version components from `src/mod/version.h`: - -```c -#define VERSION_MAJOR 0 -#define VERSION_MINOR 6 -#define VERSION_REVISION 1 -#define VERSION_PATCH 7 -``` - -These are combined into a version string like `0.6.1.7`. - -### Template Processing - -The `Info.plist.template` uses `${VERSION}` placeholders: - -```xml -CFBundleShortVersionString -${VERSION} -CFBundleVersion -${VERSION} -``` - -During build, these placeholders are replaced with the actual version. - -## Build Process - -1. **Configuration Phase**: `on_config` function in xmake.lua executes -2. **Version Extraction**: Reads and parses `src/mod/version.h` -3. **Template Processing**: Replaces `${VERSION}` in template with extracted version -4. **File Generation**: Writes processed `Info.plist` to source directory -5. **Build**: Xcode uses the generated `Info.plist` for app bundle creation -6. **Cleanup**: Generated file is removed after clean operation - -## Verification - -To test the implementation without a full build: - -```bash -python3 scripts/verify_version_substitution.py -``` - -This script simulates the build process and verifies: -- Version extraction from header file -- Template processing -- XML validity of generated Info.plist -- Correct version substitution - -## Maintenance - -### Updating Version - -Version updates are made in `src/mod/version.h` only. The macOS launcher will automatically pick up changes during the next build. - -### Modifying Info.plist - -Changes to the Info.plist should be made to `Info.plist.template`, not the generated `Info.plist` file. - -### Troubleshooting - -If version substitution fails: - -1. Check that `src/mod/version.h` exists and contains expected `VERSION_*` definitions -2. Verify `Info.plist.template` contains `${VERSION}` placeholders -3. Run the verification script to identify specific issues -4. Check xmake build output for error messages - -### File Patterns - -- `Info.plist.template` - **COMMIT** to git -- `Info.plist` - **DO NOT COMMIT** (generated file, in .gitignore) \ No newline at end of file +Run `python3 scripts/verify_version_substitution.py` to check template substitution against the header. +Generated plist files are build outputs and must not be committed.