Skip to content

fix(ini): replay user GameData.ini after SagePatch overrides - #264

Merged
fbraz3 merged 1 commit into
fbraz3:mainfrom
kumait:fix/sagepatch-gamedata-precedence
Aug 22, 2026
Merged

fix(ini): replay user GameData.ini after SagePatch overrides#264
fbraz3 merged 1 commit into
fbraz3:mainfrom
kumait:fix/sagepatch-gamedata-precedence

Conversation

@kumait

@kumait kumait commented Aug 22, 2026

Copy link
Copy Markdown

Problem

Values set in a user-authored loose Data/INI/GameData.ini are silently ignored. Reported symptom: setting MaxCameraHeight = 510.0 there had no effect in game.

Root cause

GameEngine::init() loads GameData in this order:

  1. Data\INI\Default\GameData (BIG-archived stub)
  2. Data\INI\GameData — a loose user file shadows the archived copy here, since FileSystem::openFile() resolves local before archive
  3. The auto-generated SagePatch.ini from the user data dir, with INI_LOAD_OVERWRITE

SagePatch ships a hardcoded GameData block (MaxCameraHeight = 350.0, MinCameraHeight = 100.0, EnforceMaxCameraHeight = No, ...), so its generated defaults overwrite whatever the user authored — with no error or log line. Since SagePatch.ini is recreated on every launch if deleted, there was no way for the standard loose-INI modding channel to win. This also affects mods, which ship loose INI files into the game directory and cannot edit per-user SagePatch files.

Fix

After loading SagePatch.ini, replay the loose Data/INI/GameData.ini if one exists locally (guarded by TheLocalFileSystem->doesFileExist(), matching the local-first resolution the load itself uses). Precedence becomes: archived defaults → SagePatch → user file.

  • Installs without a loose GameData.ini are unaffected (guard is false).
  • The archived original is never reloaded.
  • Reloading is safe: under INI_LOAD_OVERWRITE, parseGameDataDefinition() is plain field assignment with no newOverride() push. Determinism accounting slightly improves: the loose file is CRC'd by the initSubsystem load, while SagePatch is not, so effective values now match what xferCRC saw.

Also in this change:

  • Fixed the generated ~5% more terrain comment: the % was consumed as a fprintf format specifier, producing ~5more terrain in every SagePatch.ini written to date.
  • Updated the generated header comment to document the precedence rule.

Known trade-off: a loose GameData.ini must be a complete copy of the archived file (it shadows, it doesn't merge), so every key in it becomes authoritative — including stock values the user copied without meaning to change. Concretely, stock pins FramesPerSecondLimit = 30, which reverts SagePatch's 60 FPS default unless the user edits that line too. Keys absent from stock (e.g. TerrainDrawDistanceScale) keep their SagePatch values.

Applied to both Generals and Zero Hour. Both z_generals and g_generals build and link cleanly on macos-vulkan against current main.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • User-authored GameData.ini settings now correctly override default values from SagePatch.ini when both files are present.
    • Configuration loading is now consistent across Generals and Zero Hour.
    • CRC behavior remains unchanged.
  • Documentation

    • Updated configuration comments and documentation to clearly explain file precedence and correct formatting.

SagePatch.ini is loaded after Data\INI\GameData with INI_LOAD_OVERWRITE,
so its generated defaults silently clobbered values from a user-authored
loose Data/INI/GameData.ini (reported: MaxCameraHeight had no effect).

Replay the loose file after SagePatch.ini when it exists, restoring
user precedence. Installs without a loose GameData.ini are unaffected
and the BIG-archived original is never reloaded. Also fix the percent
sign in the generated terrain comment being eaten as a printf format
specifier, and document the precedence rule in the generated header.

Applied to both Generals and Zero Hour.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: Too big: expected string to have <=250 characters at "tone_instructions"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 52de6aef-b3cc-453d-b610-3be0f8cf82f0

📥 Commits

Reviewing files that changed from the base of the PR and between e7b4b7b and d637dca.

📒 Files selected for processing (3)
  • Generals/Code/GameEngine/Source/Common/GameEngine.cpp
  • GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp
  • docs/WORKLOG/2026-08-DIARY.md

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Changes

GameData.ini precedence

Layer / File(s) Summary
Reload loose GameData.ini after SagePatch
Generals/Code/GameEngine/Source/Common/GameEngine.cpp, GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp, docs/WORKLOG/*
Both game engines reload an existing loose GameData.ini after SagePatch.ini, allowing its values to override SagePatch values. Generated comments and the worklog document the load order and related corrections.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: 🔵 Low · up to d637d

The PR changes GameData precedence so loose user files can override generated settings, but debug builds may still apply a later override and produce different results. The change is otherwise mergeable with explicit owner awareness of this bounded debug-build behavior.

Suggested reviewers: fbraz3

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes replaying the user GameData.ini after SagePatch overrides, which is the main change.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. (1 skipped: 1 unsupported.)
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@fbraz3
fbraz3 merged commit bf98265 into fbraz3:main Aug 22, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants