otclient-redemption/data/styles
Eduardo Dantas ef446a9d0c
feat(client): add automatic modern asset installation (#1727)
Add automatic client-asset installation for modern Tibia versions in OTC, with the UI and runtime support needed for a safe download-and-install flow.

Main changes:
- Add modules/client_assets to orchestrate descriptor and release resolution, downloads, retries, cancellation, archive extraction, optional LZMA handling, and SHA-256 integrity checks.
- Add richer install logs in the console, including download phases, install phases, and final install paths.
- Add support for packaged runtime files, including large DLLs distributed through archives.
- Make client_entergame depend on client_assets.
- Check required assets during login for modern clients version 1281 and newer.
- Prompt the user to download missing modern assets instead of requiring manual setup.
- Allow the client list and version selection to work with installed modern asset sets.

Install layout:
- Install things assets under data/things/<version>.
- Install sound assets under data/sounds/<version>.
- Keep extra runtime files in the existing client root/bin flow.
- Preserve the existing OTC asset layout as the source of truth instead of introducing a separate permanent path.

UI improvements:
- Improve missing-assets and progress dialog sizing and text wrapping.
- Improve progress behavior for downloads without Content-Length.
- Add indeterminate progress behavior for unknown-length phases.
- Add an hourglass busy indicator for indeterminate phases.
- Reduce the perception that the installer is stuck during long extraction steps.

Runtime and build support:
- Add libarchive usage and linking for archive extraction.
- Add SHA-256 helpers and Lua bindings used by client_assets.
- Add safer extraction and path normalization in ResourceManager.
- Adjust the Emscripten HTTP login path to follow the same HTTP/HTTPS fallback behavior used by native login.

Security and integrity:
- Enable strictManifestSha256 by default.
- Disable raw fallback on hash mismatch by default.
- Key releasesCache per source URL and repository to avoid stale cross-source cache reuse.
- Add an LZMA decompression output cap to reduce memory-exhaustion risk.

Compatibility:
- Keep existing classic asset behavior unchanged.
- Use the new auto-install flow only for modern versions when required assets are missing.
- Keep the scope limited to client-side asset automation and required runtime support.
- No server-side Canary behavior is changed by this PR.

This makes modern client setup safer and more automatic by downloading, validating, extracting, and installing missing assets directly from OTC while preserving the existing classic asset flow.
2026-05-28 16:18:44 -03:00
..
10-buttons.otui feat: game_market (#1539) 2026-01-06 09:13:52 -03:00
10-checkboxes.otui feat: game_market (#1539) 2026-01-06 09:13:52 -03:00
10-comboboxes.otui feat: game analysers and fix: cooldown bars (#1310) 2025-10-13 10:18:54 -07:00
10-creaturebuttons.otui feat: player / monster Icons 12.81 (#973) 2025-06-25 18:35:55 -03:00
10-creatures.otui Refactor modules, closes #223 2013-01-18 20:46:36 -02:00
10-effect.otui feature: support effect and missile in UI 2024-10-18 20:41:12 -03:00
10-items.otui perf: item expiry/charges rendering in C++ UIItem (#1712) 2026-05-11 14:58:02 -03:00
10-labels.otui New skin from https://github.com/Mignari/otc-gray-skin 2014-07-02 13:20:02 -03:00
10-listboxes.otui New skin from https://github.com/Mignari/otc-gray-skin 2014-07-02 13:20:02 -03:00
10-missile.otui feature: support effect and missile in UI 2024-10-18 20:41:12 -03:00
10-panels.otui feat: new layout (#749) 2024-06-21 18:10:07 -03:00
10-progressbars.otui feat: imbuement system (#1616) 2026-05-20 11:16:46 -03:00
10-scrollbars.otui feat: game_market (#1539) 2026-01-06 09:13:52 -03:00
10-separators.otui New skin from https://github.com/Mignari/otc-gray-skin 2014-07-02 13:20:02 -03:00
10-splitters.otui Refactor modules, closes #223 2013-01-18 20:46:36 -02:00
10-textedits.otui feat: game analysers and fix: cooldown bars (#1310) 2025-10-13 10:18:54 -07:00
10-windows.otui feat: game analysers and fix: cooldown bars (#1310) 2025-10-13 10:18:54 -07:00
20-imageview.otui UIImageView, fixes to minimap 2013-01-31 14:20:04 -02:00
20-popupmenus.otui feat: Quest Log tracker and Style 14.10 in html/css (#1144) 2025-05-07 19:40:03 -03:00
20-smallscrollbar.otui fix: vbot UI (#1718) 2026-05-16 22:19:28 -03:00
20-spinboxes.otui Style fixes and added dontSignal to UIRadioGroup. 2014-07-13 07:38:44 +12:00
20-tabbars.otui fix: vbot UI (#1718) 2026-05-16 22:19:28 -03:00
20-tables.otui Added Market column sorting (fixes #429), updated UITable and fixed not working methods 2015-01-21 23:40:15 +01:00
20-topmenu.otui feat: proficiency (#1593) 2026-05-20 07:45:27 -03:00
30-calendar.otui feat: new layout (#749) 2024-06-21 18:10:07 -03:00
30-inputboxes.otui Refactor modules, closes #223 2013-01-18 20:46:36 -02:00
30-messageboxes.otui feat(client): add automatic modern asset installation (#1727) 2026-05-28 16:18:44 -03:00
30-minimap.otui fix: split modules from game_mainpanel and small fix (#790) 2024-06-23 21:30:04 -03:00
30-miniwindow.otui improve: UI, Styles, MiniWindow General, see Roadmap 2025-08-27 18:42:18 -03:00
30-statsbar.otui feat: proficiency (#1593) 2026-05-20 07:45:27 -03:00
40-gamebuttons.otui feat: v8 Bot 2023-11-21 22:27:20 -03:00
40-outfitwindow.otui feat: game_market (#1539) 2026-01-06 09:13:52 -03:00
custom.css feat: protocol 15.24 packets and features (#1604) 2026-05-20 11:26:11 -03:00
global_alias_test.otui feat: add otml alias resolution (#1634) 2026-02-25 18:00:53 -03:00
html.css feat: protocol 15.24 packets and features (#1604) 2026-05-20 11:26:11 -03:00
README.md feat: add otml alias resolution (#1634) 2026-02-25 18:00:53 -03:00

OTML Variables for OTClient Styles

OTML files can now expose lightweight variables that keep palettes, spacing tokens and theme tweaks in sync without rewriting the same literals across styles. In this context, a standalone OTML node whose tag begins with & is treated as a variable definition and is skipped by UIManager when instantiating widgets; its value is made available to subsequent nodes through $name references.

Note on existing & syntax: Older .otui files already use & as a prefix for Lua-backed widget fields (for example &minimizedHeight, &static). That syntax remains valid: lines like &minimizedHeight: 42 inside a widget definition still define Lua fields on the widget. With the current resolver, nested & nodes can also participate as local OTML aliases, while root-level aliases are additionally exported globally. This overloading of & is intentional and backward-compatible.

How it works

  • Declare a variable by prefixing a node tag with & and assigning a literal value, for example &primaryColor: #33AAFF.
  • Use that variable later in the file by writing $primaryColor in fields that expect literals (colors, borders, paddings, etc.). The parser resolves these references before Lua expression evaluation occurs.
  • Variables inherit down the tree. A definition near the root of a .otui is also saved into OTMLDocument::globalAliases, which allows other files loaded afterward to reuse the same tokens.
  • A variable can reference another variable (&accentColor: $primaryColor). Cycles and undefined references are reported in the console so you can catch mistakes early.
  • Outer quotes are stripped during resolution; the unquoted literal is substituted directly, which keeps the value from being re-evaluated as a Lua expression.

Example file

data/styles/global_alias_test.otui is not tied to a real in-game window—it exists solely to demonstrate and exercise the alias resolution path. If the resolver were broken, this file would trigger an error in otclient.log when UIManager loads it, so it acts as a lightweight sanity check.

&primaryColor: #33AAFF
&secondaryColor: $primaryColor
&lightText: '#FFFFFF'

TestGlobalStyle < UIWidget
  color: $lightText
  background-color: $secondaryColor
  border-color: $primaryColor

DerivedPanel < UIWidget
  &panelAccent: $secondaryColor
  color: $primaryColor
  background-color: $lightText
  text-color: $secondaryColor
  padding: $panelAccent
  PanelHeader < UIWidget
    &headerAccent: $panelAccent
    background-color: $headerAccent
    padding: $headerAccent

The alias nodes never create widgets; they only populate the resolver so the colors above resolve to the expected literals. Within DerivedPanel we define &panelAccent (a node-scoped alias) before any style fields to show aliases can live inside a node and feed sibling properties like padding. PanelHeader takes the same alias and redefines it locally via &headerAccent to demonstrate nested alias chains without introducing actual windows.

Best practices

  • Keep palette and spacing variables in dedicated .otui files and import them from your screens to ensure consistency.
  • Avoid overlapping names across scopes when you intend to share tokens globally—reusing the same name in the document root makes the value available to every style file that loads afterward.
  • Since UIWidget::parseBaseStyle evaluates expressions in Lua, rely on the resolver to deliver already-evaluated literal tokens for properties that only support strings, colors or file paths.