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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ jobs:
- name: Set protobuf compiler cache identity
shell: bash
run: |
echo "SCCACHE_C_CUSTOM_CACHE_BUSTER=stfc-protobuf-${{ env.PROTOBUF_SCCACHE_SCHEMA }}-xmake-${{ env.XMAKE_VERSION }}-macos-${{ matrix.arch }}-release-${{ env.MACOSX_DEPLOYMENT_TARGET }}-${{ hashFiles('mods/src/prime/proto/*.proto', 'mods/xmake.lua', 'xmake.lua', 'xmake-requires.lock', 'xmake/dependencies/common.lua', 'xmake/dependencies/macos.lua', 'xmake/rules/protobuf_sccache.lua') }}" >> "$GITHUB_ENV"
echo "SCCACHE_C_CUSTOM_CACHE_BUSTER=stfc-protobuf-${{ env.PROTOBUF_SCCACHE_SCHEMA }}-xmake-${{ env.XMAKE_VERSION }}-macos-${{ matrix.arch }}-release-${{ env.MACOSX_DEPLOYMENT_TARGET }}-${{ hashFiles('src/mod/prime/proto/*.proto', 'src/mod/xmake.lua', 'xmake.lua', 'xmake-requires.lock', 'xmake/dependencies/common.lua', 'xmake/dependencies/macos.lua', 'xmake/rules/protobuf_sccache.lua') }}" >> "$GITHUB_ENV"

- name: Locate XMake caches
id: xmake_cache_paths
Expand Down Expand Up @@ -434,7 +434,7 @@ jobs:
uses: actions/cache/restore@v6
with:
path: build/.swift-module-cache
key: macos-${{ matrix.arch }}-release-swift-modules-${{ env.SWIFT_MODULE_CACHE_SCHEMA }}-${{ env.MACOSX_DEPLOYMENT_TARGET }}-${{ steps.swift_toolchain.outputs.hash }}-${{ steps.xmake_cache_paths.outputs.plzma_sha }}-${{ hashFiles('macos-launcher/xmake.lua', 'macos-launcher/src/module.modulemap', 'xmake/dependencies/macos.lua', 'xmake-requires.lock', 'xmake-packages/packages/p/PLzmaSDK/**') }}
key: macos-${{ matrix.arch }}-release-swift-modules-${{ env.SWIFT_MODULE_CACHE_SCHEMA }}-${{ env.MACOSX_DEPLOYMENT_TARGET }}-${{ steps.swift_toolchain.outputs.hash }}-${{ steps.xmake_cache_paths.outputs.plzma_sha }}-${{ hashFiles('src/launcher/macos/xmake.lua', 'src/launcher/macos/module.modulemap', 'xmake/dependencies/macos.lua', 'xmake-requires.lock', 'xmake-packages/packages/p/PLzmaSDK/**') }}

- name: Restore XMake compiler cache
id: restore_build
Expand Down Expand Up @@ -568,9 +568,9 @@ jobs:

test -f build/macosx/arm64/release/macOSLauncher
test -f "$APP/Contents/Resources/Assets.car"
test -f macos-launcher/src/Info.plist
test -f src/launcher/macos/Info.plist

cp macos-launcher/src/Info.plist \
cp src/launcher/macos/Info.plist \
"$APP/Contents/Info.plist"

test -f "$APP/Contents/Info.plist"
Expand Down
12 changes: 6 additions & 6 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,17 @@ Delete the `build/` folder to reset. Also delete `.vs/` for a full Visual Studio

### Source Layout

- **`mods/src/`** — Core mod code (the main codebase)
- **`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
- **`win-proxy-dll/src/`** — Windows DLL proxy entry point
- **`macos-dylib/src/`** — macOS dylib entry point
- **`macos-loader/src/`** — macOS loader (finds game, injects dylib)
- **`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`)
Expand All @@ -92,7 +92,7 @@ static auto class_helper = il2cpp_get_class_helper("Assembly.Name", "Namespace",
static auto method = class_helper.GetMethodInfo("MethodName");
```

**Adding a new patch** — Create a `.cc` file in `mods/src/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.
**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.

Expand All @@ -113,7 +113,7 @@ static auto method = class_helper.GetMethodInfo("MethodName");
## Code Style

- Uses `.clang-format` — 2-space indent, 120 column limit, Linux brace style, aligned assignments/declarations
- Version is defined in `mods/src/version.h` (VERSION_MAJOR/MINOR/REVISION/PATCH)
- 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.

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ This project is maintained solely at my own cost of time, energy and money. Any
- 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](FEATURES.md)
For a full list of features see our [FEATURES.md](docs/FEATURES.md)

## Installing

Please see the [INSTALL.md](INSTALL.md) instructions which has steps on how to use this mod with Star Trek Fleet Command.
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).
Expand All @@ -66,7 +66,7 @@ Please note, that whilst Mac support was added in this version, it's supported o

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](KEYMAPPING.md)
been applied. Valid values for any short can be found in [KEYMAPPING.md](docs/KEYMAPPING.md)

### UI shortcuts

Expand Down
2 changes: 0 additions & 2 deletions create-contrib.sh

This file was deleted.

2 changes: 1 addition & 1 deletion docs/FASTER_QUEUE_RECOVERY.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ The older off-screen Kir'Shara combat-completion repair was fixed by Scopely. Th

## Validation

Run `tests/run-action-queue.ps1` on Windows, or compile `tests/action_queue.cc` with a C++23 compiler and `-Imods/src`. Tests use the production policy and request store with fake weak handles. They cover one-shot recovery, reordered/still-present targets, cross-fleet rejection, stale attempts, replaced/collected queues, expiry, reentrant cancellation, bounded capacity and cleanup. They do not model game ABI or network scheduling.
Run `tests/run-action-queue.ps1` on Windows, or compile `tests/action_queue.cc` with a C++23 compiler and `-Isrc/mod`. Tests use the production policy and request store with fake weak handles. They cover one-shot recovery, reordered/still-present targets, cross-fleet rejection, stale attempts, replaced/collected queues, expiry, reentrant cancellation, bounded capacity and cleanup. They do not model game ABI or network scheduling.

The prototype produced two observed handoffs with the next target attempted 1–2 ms later and successful responses within 388–532 ms. Those timings are observations, not a latency guarantee. The final adapter requires its own smoke test: normal queued combat; removal of the outstanding target; removal before the first successful course response; queue clear/rebuild; recall; and session restart. Group-wave behavior needs additional coverage when available.
4 changes: 2 additions & 2 deletions FEATURES.md → docs/FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

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`](KEYMAPPING.md) for valid key names.
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

Expand Down Expand Up @@ -176,4 +176,4 @@ The default shortcut map includes the following high-use controls. All of these
| 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`](KEYMAPPING.md).
For the complete shortcut list and the names accepted by the configuration parser, see [`README.md`](README.md) and [`KEYMAPPING.md`](docs/KEYMAPPING.md).
File renamed without changes.
File renamed without changes.
18 changes: 9 additions & 9 deletions docs/VERSION_SUBSTITUTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@

## Overview

The macOS launcher's `Info.plist` file now automatically uses the version defined in `mods/src/version.h` during the build process. This ensures consistency between the application version and the mod version.
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**: `macos-launcher/src/Info.plist.template` - Contains version placeholders
- **Generated**: `macos-launcher/src/Info.plist` - Generated during build (not committed to git)
- **Source**: `mods/src/version.h` - Contains version definitions
- **Build**: `macos-launcher/xmake.lua` - Contains version extraction and substitution logic
- **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 `mods/src/version.h`:
The build process extracts version components from `src/mod/version.h`:

```c
#define VERSION_MAJOR 0
Expand All @@ -42,7 +42,7 @@ 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 `mods/src/version.h`
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
Expand All @@ -66,7 +66,7 @@ This script simulates the build process and verifies:

### Updating Version

Version updates are made in `mods/src/version.h` only. The macOS launcher will automatically pick up changes during the next build.
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

Expand All @@ -76,7 +76,7 @@ Changes to the Info.plist should be made to `Info.plist.template`, not the gener

If version substitution fails:

1. Check that `mods/src/version.h` exists and contains expected `VERSION_*` definitions
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
Expand Down
16 changes: 16 additions & 0 deletions docs/configuration/example_community_patch_settings.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Localized example configuration files are generated from the languages
# supported by https://modconfig.pages.dev:
#
# English (en): https://github.com/STFC-Mod/mod/blob/dev/docs/configuration/example_community_patch_settings_en.toml
# Deutsch (de): https://github.com/STFC-Mod/mod/blob/dev/docs/configuration/example_community_patch_settings_de.toml
# Nederlands (nl): https://github.com/STFC-Mod/mod/blob/dev/docs/configuration/example_community_patch_settings_nl.toml
# Français (fr): https://github.com/STFC-Mod/mod/blob/dev/docs/configuration/example_community_patch_settings_fr.toml
# Español (es): https://github.com/STFC-Mod/mod/blob/dev/docs/configuration/example_community_patch_settings_es.toml
# Русский (ru): https://github.com/STFC-Mod/mod/blob/dev/docs/configuration/example_community_patch_settings_ru.toml
# Dansk (da): https://github.com/STFC-Mod/mod/blob/dev/docs/configuration/example_community_patch_settings_da.toml
# tlhIngan Hol (tlh): https://github.com/STFC-Mod/mod/blob/dev/docs/configuration/example_community_patch_settings_tlh.toml
# Minionese (en-x-minionese): https://github.com/STFC-Mod/mod/blob/dev/docs/configuration/example_community_patch_settings_en-x-minionese.toml
# Cockney (en-GB-x-cockney): https://github.com/STFC-Mod/mod/blob/dev/docs/configuration/example_community_patch_settings_en-GB-x-cockney.toml
#
# Choose the example for your preferred language and save a copy as
# community_patch_settings.toml in the appropriate settings folder.
16 changes: 0 additions & 16 deletions example_community_patch_settings.toml

This file was deleted.

Binary file removed macos-launcher/src/launcher.icns
Binary file not shown.
5 changes: 2 additions & 3 deletions scripts/check-il2cpp-dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import re
from collections import defaultdict

SRC_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')
SRC_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'src')

TYPE_HEAD = re.compile(
r'^(?:\[.*\]\s*)?(?:(?:public|private|protected|internal|static|sealed|abstract|readonly|ref|unsafe|partial)\s+)*'
Expand Down Expand Up @@ -161,8 +161,7 @@ def call_arity(text):
def scan_source(root):
"""Returns ({binding name: (asm, ns, class)}, [(file, owner, kind, member, static, arity)])."""
classes, uses = {}, []
for dirpath, _, files in (entry for directory in ('mods/src', 'libs')
for entry in os.walk(os.path.join(root, directory))):
for dirpath, _, files in os.walk(root):
if os.sep + 'proto' in dirpath:
continue
for f in files:
Expand Down
2 changes: 1 addition & 1 deletion scripts/create-mac-dmg.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ lipo -create build/macosx/$ARCH/$CONFIG/macOSLauncher build/macosx/x86_64/$CONFI
lipo -create build/macosx/$ARCH/$CONFIG/stfc-community-mod-loader build/macosx/x86_64/$CONFIG/stfc-community-mod-loader -output build/macosx/$ARCH/$CONFIG/macOSLauncher.app/Contents/stfc-community-mod-loader
lipo -create build/macosx/$ARCH/$CONFIG/libstfc-community-mod.dylib build/macosx/x86_64/$CONFIG/libstfc-community-mod.dylib -output build/macosx/$ARCH/$CONFIG/macOSLauncher.app/Contents/libstfc-community-mod.dylib
cp assets/launcher.icns build/macosx/$ARCH/$CONFIG/macOSLauncher.app/Contents/Resources/
cp macos-launcher/src/Info.plist build/macosx/$ARCH/$CONFIG/macOSLauncher.app/Contents/
cp src/launcher/macos/Info.plist build/macosx/$ARCH/$CONFIG/macOSLauncher.app/Contents/

rm -rf build/macosx/$ARCH/$CONFIG/*.dSYM || true
rm -rf build/macosx/$ARCH/$CONFIG/STFC\ Community\ Mod.app || true
Expand Down
2 changes: 1 addition & 1 deletion scripts/mac-build-test-debug.sh
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ package_app_bundle() {
exit 1
fi

local info_plist_path="${PROJECT_ROOT}/macos-launcher/src/Info.plist"
local info_plist_path="${PROJECT_ROOT}/src/launcher/macos/Info.plist"
if [[ ! -f "$info_plist_path" ]]; then
print_error "Generated Info.plist not found at: $info_plist_path"
print_info "Run the configure/build step so xmake can generate it from Info.plist.template"
Expand Down
2 changes: 1 addition & 1 deletion scripts/stamp-version-hash.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def main() -> None:
parser.add_argument(
"--header",
type=Path,
default=Path("mods/src/version.h"),
default=Path("src/mod/version.h"),
help="version header to update",
)
args = parser.parse_args()
Expand Down
2 changes: 1 addition & 1 deletion scripts/validate-example-configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

def main() -> int:
root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
pattern = os.path.join(root, "example_community_patch_settings*.toml")
pattern = os.path.join(root, "docs/configuration/example_community_patch_settings*.toml")
files = sorted(glob.glob(pattern))
if not files:
print(f"no example config files matched {pattern!r}", file=sys.stderr)
Expand Down
Loading