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. |
||
|---|---|---|
| .. | ||
| 10-buttons.otui | ||
| 10-checkboxes.otui | ||
| 10-comboboxes.otui | ||
| 10-creaturebuttons.otui | ||
| 10-creatures.otui | ||
| 10-effect.otui | ||
| 10-items.otui | ||
| 10-labels.otui | ||
| 10-listboxes.otui | ||
| 10-missile.otui | ||
| 10-panels.otui | ||
| 10-progressbars.otui | ||
| 10-scrollbars.otui | ||
| 10-separators.otui | ||
| 10-splitters.otui | ||
| 10-textedits.otui | ||
| 10-windows.otui | ||
| 20-imageview.otui | ||
| 20-popupmenus.otui | ||
| 20-smallscrollbar.otui | ||
| 20-spinboxes.otui | ||
| 20-tabbars.otui | ||
| 20-tables.otui | ||
| 20-topmenu.otui | ||
| 30-calendar.otui | ||
| 30-inputboxes.otui | ||
| 30-messageboxes.otui | ||
| 30-minimap.otui | ||
| 30-miniwindow.otui | ||
| 30-statsbar.otui | ||
| 40-gamebuttons.otui | ||
| 40-outfitwindow.otui | ||
| custom.css | ||
| global_alias_test.otui | ||
| html.css | ||
| README.md | ||
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.otuifiles already use&as a prefix for Lua-backed widget fields (for example&minimizedHeight,&static). That syntax remains valid: lines like&minimizedHeight: 42inside 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
$primaryColorin 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
.otuiis also saved intoOTMLDocument::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
.otuifiles 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::parseBaseStyleevaluates expressions in Lua, rely on the resolver to deliver already-evaluated literal tokens for properties that only support strings, colors or file paths.