Skip to content

fix(recorder): evaluate __EVAL display names instead of recording their source - #131

Merged
smitt14ua merged 1 commit into
mainfrom
fix/eval-display-names
Oct 20, 2026
Merged

smitt14ua merged 1 commit into
mainfrom
fix/eval-display-names

Conversation

@smitt14ua

Copy link
Copy Markdown
Contributor

Problem

Some mods build an item's displayName with a config expression, for example VTGM's per-side radio backpacks:

displayName = __EVAL(format ["%1 [BLUE]", getText(configFile >> "CfgVehicles" >> "B_simc_US_Molle_sturm_OCP_RTO" >> "displayName")]);

Recordings showed the raw expression as the item's name. In the replay's unit tab, the player's backpack read:

format ["%1 [BLUE]", getText(configFile >> "CfgVehicles" >> "B_simc_US_Molle_sturm_OCP_RTO" >> "displayName")]

instead of [US] MOLLE Sturmgepak (OCP/Rajio) [BLUE], which is what the game shows.

Cause. HEMTT does not evaluate __EVAL at build time. It writes the entry into config.bin as an expression value (rap value subtype 4), and the engine runs it only when the entry is read with getText. OCAP deliberately reads names with getTextRaw, so a stringtable reference never gets resolved in the recording server's language. For an expression entry, getTextRaw returns the expression's source. It does not start with $, so the recorder treated it as an English literal and stored it.

The same pattern was copied across the recorder, so vehicle, magazine, explosion, static-weapon, fortification and Zeus-module names had the same bug.

Fix

  • Add OCAP_recorder_fnc_getConfigDisplayName, the one rule for a locale-safe config name. It returns "" when no safe name exists, and the caller falls back to the class name.
    • literal: returned as-is. For a literal, getText equals getTextRaw, so nothing changes here.
    • $STR_...: "", as before.
    • __EVAL(...): detected because getText differs from getTextRaw. The evaluated name is returned, unless it is non-ASCII, which means the expression pulled in a localized name.
  • Use it in every place on the server that read getTextRaw (... >> "displayName"): fnc_recordExplosion, fnc_submitStaticWeapon, fnc_trackServicing (vehicle and rearm magazine names) and fnc_trackConstructions (two places).
  • fnc_trackTrenches: the fallback for trench classes not in trenchTypes used plain getText, so it stored the server's localized name. It now uses the shared rule too.
  • Clients have none of our functions. fnc_installPlayerTrackingClients now passes the compiled function as the argument of the existing remoteExec ["call", ...] bootstrap and stores it in OCAP_recorder_client_getConfigDisplayName. Gear and Zeus-module names use it, so the rule exists only once. Zeus modules still apply their stricter isEnglishText filter on top, as before.
  • Docs: docs/player-detail-tracking.md and the comments in the sampler now describe the expression case.

Behaviour changes

  • Explosions: an ammo class whose name is a $STR_ reference now tries its default magazine's name before it falls back to the ammo class. Before, it went straight to the class name.
  • Array entries: a displayName[] entry written as an array is handled at every place on the server, not only in the client gear code.

Known limits

Only expression values are checked for non-ASCII characters, and that check is a heuristic:

  • A localized name that is plain ASCII, for example German without umlauts (Gewehr [BLUE]), still gets through. SQF cannot tell it apart from English. Cyrillic, Czech, Polish and similar names are caught.
  • An English expression result with a typographic character (×, –) is rejected and falls back to the class name.

These limits are documented in the function header.

Testing

  • hemtt check: no errors or warnings in the changed files.
  • Not tested in game yet. The fix assumes that getText evaluates an expression entry while getTextRaw returns its source. That matches the observed replay and the bytes in the built config.bin, but it should be confirmed on a mission with VTGM's radio backpacks. Also check that clients and JIP clients still install the sampler with the new bootstrap argument.
  • tests/*_regressions.sqf cover neither display names nor this path. They need a multiplayer mission, and I did not run them.

…ir source

getTextRaw returns the unevaluated source of a displayName written as __EVAL(...), so recordings showed e.g. 'format ["%1 [BLUE]", getText (...)]' as an item name. Add OCAP_recorder_fnc_getConfigDisplayName as the single rule for locale-safe config names, use it at every server site, and ship it to clients for gear and Zeus module names.
@smitt14ua
smitt14ua requested a review from fank October 20, 2026 17:20
@fank

fank commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Ratatoskr reviewed this pull request.

Approved on 6e09fde0. See the review.

Finished 2026-10-20 17:25 UTC.

@fank fank left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APPROVE — 0 blocking findings.

Review details

Reviewed head 6e09fde00d498a6a556971057490bec091cfefe7 against base 61269ee60f9a40bbd166365d95a554b3af0a2716, including the shared helper, server callers, and client bootstrap. No concrete correctness or safety blocker found. The helper is registered before use, retains stringtable-reference fallback, and the client bootstrap supplies it before installing its consumers. The documented ASCII heuristic remains a limitation, not a language guarantee.

Checks and limitations

  • git diff --check 61269ee60f9a40bbd166365d95a554b3af0a2716 HEAD passed.
  • GitHub's Build / build check completed successfully.
  • command -v hemtt, command -v arma3server, and command -v sqfvm found no local executables. I did not run HEMTT or multiplayer regression tests. tests/README.md requires an Arma multiplayer mission with two connected players.
  • In-game evaluation of expression entries (addons/recorder/fnc_getConfigDisplayName.sqf:56–63) and normal/JIP client installation (addons/recorder/fnc_installPlayerTrackingClients.sqf:75–81,1907) remain unverified; static review and CI do not establish these engine behaviours.

Optional, non-blocking: Add an engine-backed display-name fixture covering literal, stringtable, array, ASCII-expression and non-ASCII-expression entries, plus ordinary/JIP bootstrap checks. The existing regression scripts do not pin these new paths.

Earlier discussions: GitHub GraphQL returned no review threads (hasNextPage: false), so none required replies or resolution; resolved/still-open/skipped: 0/0/0. Authenticated reviewer: fank.

@smitt14ua
smitt14ua merged commit 5e855f3 into main Oct 20, 2026
1 check passed
@smitt14ua
smitt14ua deleted the fix/eval-display-names branch October 20, 2026 20:35
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