fix(locale): swallow ApplyLocaleFontSubstitution exception - #57
Open
jmontenez wants to merge 1 commit into
Open
Conversation
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
marked this pull request as ready for review
May 2, 2026 14:14
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When the platform locale is non-English (reproduced on
fr-FR),MegaCrit.Sts2.Core.Localization.Fonts.FontControlUtils.ApplyLocaleFontSubstitution()throws aNullReferenceException. The error gets re-thrown throughLocString.GetFormattedText()during the static.cctorof UI nodes (NTopBarFloorIcon,NPotionHolder, …). Whether the engine survives the chain ofTypeInitializationExceptionit 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 newFontSubstitutionPatchesadds a finalizer to the buggy method that returnsnull, marking the exception as handled. The substitution call returns without effect, and the engine continues with the default (already-loaded) font set — which rendersfr-FR(and other affected locales) correctly. The first suppressed exception is logged viaPatchHelper.Log; subsequent occurrences are silenced to avoid spam.The patch is fully defensive: if the
FontControlUtilstype or the target method is not present in the linkedsts2.dll, it logs and skips rather than failing.Repro on a non-English Android device (without the patch)
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 currentmain.