Skip to content

fix(locale): swallow ApplyLocaleFontSubstitution exception - #57

Open
jmontenez wants to merge 1 commit into
Ekyso:mainfrom
jmontenez:fix/swallow-locale-font-substitution-error
Open

fix(locale): swallow ApplyLocaleFontSubstitution exception#57
jmontenez wants to merge 1 commit into
Ekyso:mainfrom
jmontenez:fix/swallow-locale-font-substitution-error

Conversation

@jmontenez

Copy link
Copy Markdown

Summary

When the platform locale is non-English (reproduced on fr-FR), MegaCrit.Sts2.Core.Localization.Fonts.FontControlUtils.ApplyLocaleFontSubstitution() throws a NullReferenceException. The error gets re-thrown through LocString.GetFormattedText() during the static .cctor of UI nodes (NTopBarFloorIcon, NPotionHolder, …). Whether the engine survives the chain of TypeInitializationException it produces depends on the host (the launcher itself starts fine; the visible symptom downstream is a hard black screen on first launch on some devices).

Approach

The bug is inside the shipping sts2.dll — the launcher can only work around it via Harmony. The new FontSubstitutionPatches adds a finalizer to the buggy method that returns null, marking the exception as handled. The substitution call returns without effect, and the engine continues with the default (already-loaded) font set — which renders fr-FR (and other affected locales) correctly. The first suppressed exception is logged via PatchHelper.Log; subsequent occurrences are silenced to avoid spam.

The patch is fully defensive: if the FontControlUtils type or the target method is not present in the linked sts2.dll, it logs and skips rather than failing.

Repro on a non-English Android device (without the patch)

E/godot: System.NullReferenceException
   at MegaCrit.Sts2.Core.Localization.LocString.GetFormattedText()
   at MegaCrit.Sts2.Core.HoverTips.HoverTip..ctor(LocString, LocString, Texture2D)
   at MegaCrit.sts2.Core.Nodes.TopBar.NTopBarFloorIcon..cctor()
[…and similar chains for NPotionHolder, NDailyRunScreen, NTopBar*Button…]

After the patch: the suppression line shows up once in the log, the engine boots through to the main menu, and gameplay works in fr-FR.

Honest scope note

The exception cascade above is one ingredient in the full black-screen outcome users see — there are other contributing factors (build completeness on the publish side, asset packaging on first run) that I have not isolated. This PR removes one well-defined cause and makes the launcher resilient to it; it does not claim to be the only thing needed.

Build dependency

Built on top of #56 (ModLoaderPatches API drift fix). Without that PR merged first, the launcher does not compile against the shipping sts2.dll, so this patch can't be tested in isolation against current main.

When the platform locale is non-English (reproduced with fr-FR), the
sts2.dll method MegaCrit.Sts2.Core.Localization.Fonts.FontControlUtils.
ApplyLocaleFontSubstitution() throws a NullReferenceException through
LocString.GetFormattedText() during the static .cctor of UI nodes
(NTopBarFloorIcon / NPotionHolder). The unhandled exception aborts
engine startup and the user gets a hard black screen on launch — the
launcher itself starts fine, the crash only fires once the game scene
begins to initialize.

The bug lives inside the shipping sts2.dll, so it can only be worked
around from the launcher side via Harmony. Adding a finalizer to the
buggy method that returns null marks the exception as handled, lets
the substitution call return without effect, and the engine continues
with the default (already-loaded) font set — which renders fr-FR (and
other affected locales) correctly.

src/STS2Mobile/Patches/FontSubstitutionPatches.cs is new and is wired
into ModEntry alongside the other game patches. The patch is fully
defensive: if the FontControlUtils type or the target method are not
present in the linked sts2.dll, it logs and skips rather than failing.
The first suppressed exception is logged for visibility; subsequent
ones are silenced to avoid log spam.

Repro on a non-English Android device:

  E/godot: System.NullReferenceException
    at MegaCrit.Sts2.Core.Localization.LocString.GetFormattedText()
    at MegaCrit.Sts2.Core.HoverTips.HoverTip..ctor(LocString, ...)
    at MegaCrit.sts2.Core.Nodes.TopBar.NTopBarFloorIcon..cctor()

After the patch: the game boots normally and the suppression is
reported once via PatchHelper.Log.

Note: building this patch on top of current origin/main also requires
the ModLoaderPatches API-drift fix submitted as a separate PR; that
PR restores the launcher's ability to compile against the shipping
sts2.dll in the first place.
@jmontenez
jmontenez marked this pull request as ready for review May 2, 2026 14:14
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.

1 participant