Above the packet list: each property the capture was on, its owner, and every
model placed, moved or removed, each jumping to its packet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In a capture replay, each model stands where the capture saw it at the
playhead (the UGC server's mesh for a brick built model when it has one, a box
otherwise), appearing, moving and vanishing with the timeline both ways; the
Property tab shows the property data of that moment and the models standing,
and behavior messages are ticks on the timeline. In a replay of recorded
positions on one property instance, the models placed now are drawn and
labelled as now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The client's word check before sending is a light one; the server is the full filter. In normal (whitelist) chat, block list phrases are now stopped even when each word is allowed, and allowed phrases (from the dashboard or a line with spaces in the allowed words file) let their words through together. The dashboard can allow phrases and its message test explains both.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The account page lists the account's reports as a table and the Client System Info page lists every report (or each account's newest), sortable and searchable by account name or video card; a row opens every field. Values that say little about the real system are marked, and every caveat is a tooltip on the value and column.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blocked entries marked Phrase, no Allow for a phrase, phrase matches named
in the message test, and the Word files section says when blocklist.dcf
is in the old format and how to rebuild it from blocklist.txt. issue 215
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The replay speed saved for recorded positions (60x by default) is for scrubbing through hours of movement. A capture is minutes long and played too fast at that speed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Links the game for its message structs, reads the components of every LOT at startup, and decodes a capture's
replica packets once, in timeline order, on a worker thread.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Metal was drawn with metalness 1 in the room environment at half strength with one
sun, so metal groups came out nearly black. The game's metal keeps the vertex
color (lit, plus a reflection tinted by it), so metal is now part metal with a
stronger reflection, the environment is brighter and a sky over ground fill
lights the sides away from the sun.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Live: when the position feed reports the followed player only in another world,
load its scene, keep following and toast where they went. Capture playback: load
every zone's movement, switch the scene at the followed character's world change
(forward and when seeking back), follow a lone captured character from the start,
and mark world changes on the replay slider.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
followedMove (live feed), worldAt/captureSwitch (capture playback), worldMarkers and
markersHtml, with node tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Server boxes and instance rows carry the listening port, player rows their
remote ports when the list has them. With servers on more than one machine
the graph lists the machines with their totals, a zone on several machines
is a box per machine, a folded machine is one box, and the layout stacks
each machine's boxes in a framed band; links between machines are marked.
One machine lays out as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Packet Captures page (/inspector/packets, dev_message_inspector) arms captures with a
search picker (part of an account or character name, or a pasted account or object ID; online
ones marked; everything needs no pick), lists running and saved ones live (packet_capture
topic), and plays one back on its timeline: play, pause, seek and speed, packets appearing in
order with their decoded fields and bytes. World 3D takes ?capture=<id>&zone=<zone> and replays
the captured position updates in its replay mode; the capture page's playhead drives it over a
BroadcastChannel. Saved packet captures show in the Message Inspector's list and open there.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An open group (game clients, web clients, a zone's instances) keeps one box
that grows by its rows, at most 8 in view with the rest scrolled. Each row
in view is a link end of its own with only its member's traffic, and the
open box's header has none. Members are filtered by name, account or user,
instance and (with network_ips) address, in a steady order; web clients
show the dashboard user.
The filter and rows are HTML over the SVG, made once and then moved and
updated in place, so live updates keep the typed text, the focus and the
scroll; links follow the list's scroll. The box grows and shrinks with its
list, and the List view nests the members under their group with the same
filter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dashboard's own loop is framed too, with a scope per module update. Frame time and stacked phase charts per server, the servers' loop summary, longest frames, packet handling times, the last 50 slow frames with a nested timeline, and profiling sessions (profiling_run, GM 8) drawn as a flame graph with folded stacks to download. PerfHistory keeps it in memory and is unit tested; the layouts are tested with node. Task 96.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pages label the game's currencies and stats with the client's words
(UI_COINS, UI_UNIVERSE_SCORE, UI_IMAGINATION, UI_REPUTATION, UI_HEALTH)
through game.terms and GameText.term instead of writing them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Settings help names zones by locale key (expanded when served), the
Property Rent page and the Worlds table name zones in the viewer's
language, and the UGC page drops its own inventory name table.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dashboard loads every language in the client's locale; each request
runs in the viewer's language (Workers::Reply carries it to the worker),
templates get game.* and phrase()/zone_name(), scripts get GameText.* on
<body data-game>, and the user menu picks the game text language.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A labelled button (▸ 3 instances, ▸ each, ▾ group) or a double click opens a group; its members stack
where the group is (or was dragged to), boxes glide to their new places and new ones fade in. Rows keep
a fixed pitch, so opening a group only moves its own column, and open groups are remembered per browser.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Account pages get a Client system info (as reported) card (client_sysinfo):
every description the account's client sent at login, newest first, with the
raw values, the memory text split into numbers and each field's caveat. The
address is only shown with logs_audit. The Client System Info page (Logs &
Health) shows the spread across players from each account's newest report:
Windows version, video card, memory buckets, processor count and client build,
marked as client-reported and approximate.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Links leave and enter on the sides that face each other (top and bottom when one box is above the
other), so moving a box no longer leaves links ending in the air.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The layout the viewer makes is kept in the browser, with a Reset layout button. A link's colour now
compares it with the busiest link right now instead of its own recent peak, which made steady links
look saturated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Next to Diagnostics (health_view): game and web clients, auth, chat,
worlds per zone (expandable), other reporting servers, master, the
dashboard and the UGC server, with a lane each way per link sized by
bytes/s, animated by packets/s and coloured by load against its own
5 minute peak. Estimated links (servers without a split) are dashed.
Clicking a box shows its links, busiest message types and a sparkline,
with a link to Diagnostics (which now takes ?server=). A connections
table lists each remote address; single clients can be drawn too.
Narrow screens get a list. Drawing stops while the tab is hidden.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Staff flag chat for review (chat_flag): one message or several from one
conversation, with who it is about and a note. The flag keeps a copy of the
messages and 10 before and after. The Chat Flags page (Inbox, badge for open
flags) filters by status, character and account; a flag links to the character,
the account (mute, warn, ban), their player reports, their other flags and the
conversation, and shows its history. Reviewers (chat_flag_review) mark it
actioned or dismissed, change the note, link a player report or comment; all of
it is in the flag's history and the audit log. The sidebar adds Team Chat.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Guild chat per guild (/chat_log/guild/<id>, from the guild's card), team chat by
team (/chat_log/teams) and a character's whispers by conversation
(/characters/<id>/whispers, chat_dms; opening one is audited), paged on the
server. The Chat Log filters by account and time range, shows the conversation
around a message, links to its history and marks flagged messages; messages can
be picked (shift-click for a range) to flag. The character page links to all of
them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Make again gets a Made by picker, /api/ugc/options lists the processor
choices and default, the settings page has the toolbox_* settings, and
/reprocessproperty takes native or toolbox-blender.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The third ray backend, so every machine has a library for it: Embree on x86
CPUs (embree), HIPRT on AMD and NVIDIA GPUs (hiprt), Embree through SYCL on
Intel Arc and Xe GPUs (embree-gpu).
- CMake option DLU_EMBREE_SYCL (off). dUgcServer/EmbreeSycl is a project of
its own built by a SYCL compiler (DLU_SYCL_CXX; icpx through ONEAPI_ROOT or
the path, or the open source DPC++'s clang++ through DPCPP_ROOT) as an
external project: Embree 4.4 with EMBREE_SYCL_SUPPORT, linked statically and
bound inside (-Bsymbolic, only its C functions exported, so it never meets
the servers' own Embree), and the GPU kernels (nearest hit skipping a ray's
triangle, any hit), into libdlu_embree_sycl next to the servers
- UgcRaysEmbreeGpu loads it the first time embree-gpu is asked for; one GPU for
the process (embree_gpu_device picks it), the workers take turns, the
occlusion rays in batches as for hiprt
- without the build, the library or a supported Intel GPU it falls back to
embree and says why (the UGC server's log at start, --make-model on stderr)
- the option names, the settings page, the dashboard's picker, /reprocessproperty
Verified here: the default build and ctest; the SYCL build with the open source
DPC++ 7.1.0 (compiles, links against oneAPI's libsycl.so.9, exports only its C
functions); on this machine (no Intel GPU) it loads, finds no GPU and falls
back to embree. Not verified: tracing on an Intel GPU (none here).
Check: on a machine with an Intel Arc or Xe GPU and oneAPI, configure with
-DDLU_EMBREE_SYCL=ON and run UgcServer --make-model x.lxfml out embree-gpu;
the UGC tests then compare it with Embree.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Embree 4 (always built) replaces the UGC server's own bounding volume
hierarchies (the nearest-hit one and the occlusion rays' any-hit one), with no
fallback to them. ray_backend is embree (default) or hiprt (optional build;
Embree when it can't be used).
Settings, stored options and stats that say builtin still read: it is embree
(UgcRays::Parse, UgcProcessOptions::Parse). The dashboard's picker,
/reprocessproperty and --make-model offer embree and hiprt.
Tests: the backends are compared with Embree (hiprt when built), Embree against
rays whose hits are known, and the clutter's occlusion against what the old
hierarchy worked out (296 vertices summing to 114.5, 26 open, 183 dark); the
pinned model hashes are unchanged with Embree.
Check: ray_backend=builtin in an ini still starts and uses embree; the
settings page offers Embree and HIPRT.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The path tracer that imitated LU Toolbox's Remove Hidden Faces took 17 to 100
times as long as the renders from 42 directions around the model, too heavy to
use. It goes with its settings (hsr_method, hsr_samples, hsr_bounces,
hsr_sample_spacing, hsr_min_points), its side by side tracing for GPUs and its
tests. The renders (UgcRender::VisibleFromAround) remove hidden faces as before
that method existed; their size is hsr_resolution (1024), and the memory
estimate counts their buffers again.
The hidden-face method is no longer a processing option: the dashboard's picker,
/reprocessproperty and --make-model take only the ray backend (the occlusion's)
and denoising. Options stored before (made_options, process_options,
ugc_process_runs, --make-model arguments) that name toolbox or fast still
parse; the word is skipped.
Check: the settings page has no hsr_method or path settings and has
hsr_resolution; /reprocessproperty embree toolbox still works (toolbox
ignored); models made with the defaults keep their hashes (UGC tests).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The UGC page's Make again buttons (a model's, the failed ones, everything) use
the ray tracer, hidden-face method and denoising picked next to them (the
settings' when left alone). The List view's new Options column shows what made
each model and what its next make will use; "Processing options compared"
shows every combination the made models used with its makes, models and the
average time, CPU time, hidden faces', occlusion's and icon's time and share of
triangles removed per make.
Check: the three selects next to Make again (models only); make a model again
with embree fast and see its Options column and the comparison table.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dashboard snapshot counts guilds whose name waits for moderation; the moderation counts (WebSocket and
/api/moderation/counts) include it, the Review Queue badge adds it for staff with guilds_manage, and the Guilds menu
entry has its own badge. Check: create a guild with a name off the allow list: both badges go up; approve it: they
go down.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The UGC Search page and the UGC page searched the same things (owner,
account, property, the name and description a player gave a model, LOT,
UGC / blueprint id) with the same SQL. The UGC page's lists are now the
one search:
- models' List view has a Where column: placed on a property (with the
name given there and a link to the model in the property's 3D view),
in a mail or in the creator's inventories, or not found
(/api/ugc?where=1, UgcLinks::Whereabouts as before)
- owners link to their character and, with accounts_view, account
- while searching, the kind buttons say how many models and how many
cars and rockets match (/api/ugc "matches")
- /ugc_search?q= redirects to /ugc?view=list&q=; the menu's UGC Search
entry is now UGC, which opens the UGC page (it was only under Server
Admin, for ugc_manage)
- References lose their Find button (Where it is has the same) and name
the inventory a build is in
The ugc-search page and script are removed; /api/ugc_links/search stays
for API users.
Check: the menu's UGC entry; an old /ugc_search?q= link opens the UGC
list with the search filled in; owner:, account:, property:, name:,
lot: and id: searches, and the counts on the kind buttons; the Where
column's links (property, 3D, character, account).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The UGC page's assemblies (cars and rockets) list had its own columns.
It now has the models' columns and sorts, minus Saved: ID and Owner (the
newest build and its creator, and how many other owners), State, Made,
Took, CPU and RAM (the latest make of any build, and the cost of the make
the UGC server did for the combination; builds that shared the made icon
cost nothing), Size (the module count), File (the build type and its
modules) and Where (how many builds and owners use it, opening
References). The gallery sorts the same way.
Check: UGC page, Cars and rockets, List: every column sorts both ways on
the server, and the gallery's sort list has the same sorts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With the menu hidden on a wide screen the page had no name or link
home left; the top bar now shows "DarkflameServer" (linking home) then,
as it already does on narrow screens.
Check: hide the menu with the top bar's menu button on a wide window:
"DarkflameServer" appears beside it and opens Home; showing the menu
again hides it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Actions on an account (ban, mute, lock, GM level, email) and on a
character (edit, restoring a version, saving its XML) show the result
in place (reloadInPlace) instead of reloading the page. Deleting an
account goes back to Accounts without leaving the deleted account in
the history. After an in-place update (dash:refreshed) the pages show
the server's values again the way they do on load: last logins and the
mute end in the browser's time, and the GM level picker (unless a new
level is being picked).
Check: lock and unlock an account: the badge changes with no reload.
Change an account's GM level from another tab: the first tab's level
picker follows. Edit a character's items: the page updates when the
dialog closes. A character's last login updates when they log in.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
reloadInPlace() and goTo(url) (common.js) show the page again or open
another one through nav.js, or reload/load normally without it.
Resolving a bug report updates the page in place; deleting a bug
report or play key goes back to its list without leaving the deleted
page in the history. The System Log's server and file pickers and its
Refresh button swap the page in (Refresh keeps the scroll position).
The AI helper's "open the account" goes through nav.js too.
Check: resolve a bug report: the Resolved badge and text appear with no
reload. Delete a play key: back on Play Keys, and Back doesn't return
to the deleted key. System Log: picking a server or file and Refresh
change the log without a white flash.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nav.refresh() fetches the current page and compares the server's HTML
now with the HTML the page started from; only what differs is patched
into the live page (text, attributes, class changes, rows added or
taken away). Typed input stays (the browser keeps what the user
changed while the default value follows the server), and parts built
by the page's scripts are left alone. Where a patch would lose
script-built or script-bound parts, or the page's layout changed, the
page is swapped in again with its scripts, keeping the scroll
position, open tabs, open folding parts and typed input; while the
user is typing it offers a refresh instead.
Live.refreshPage (account, character, bug report and play key pages)
uses it instead of reloading the page, and the "This changed while you
were editing" banner's Refresh does too.
Check: open a play key; in another tab change its uses or active
switch: the first tab's values and badge change without a reload,
and notes typed there stay. Same on a bug report page with a half
typed resolution when it's resolved elsewhere. On a character page,
an in-game save updates it without losing the open tab or scroll.
Test: NavRulesJs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nav.js (loaded on every signed-in page) follows links and GET forms to
other dashboard pages by fetching the page and swapping in its <main>,
title, page styles and page scripts; the sidebar, top bar and live
WebSocket stay. History entries, back/forward (with scroll positions,
also kept for a reload), deep links, #hash filters and breadcrumbs keep
working. What the old page set up is taken down first: its
document/window listeners, setInterval timers, Live watchers and
topics, DataTables, dialogs and what it appended to <body>. Page
scripts run again in order; DOMContentLoaded/load handlers they add run
once they have all run. A thin bar shows while loading; a failed fetch
shows an inline error with Try again / Open it normally.
Falls back to a normal load for anything that isn't a signed-in
dashboard page, when the account or permissions changed, and for pages
with module scripts or an import map (World 3D, property view and 3D,
UGC server) or data-nav="reload", and when leaving those. Unsaved-change
prompts (beforeunload) are asked before swapping.
Check: click around the sidebar and into accounts/characters: no white
flash, the footer's live indicator stays "live", back/forward return to
the same scroll position, breadcrumbs follow the path (Accounts > an
account > a character). Activity Log links with #search= still filter.
System Log's server picker works. Leaving Settings with a change asks
first. World 3D and a property's 3D view still load (normally). Pages
that poll (Server Health, Instance Load) stop polling once left
(browser network tab). Test: NavRulesJs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The menu's groups stay open or closed from page to page
(localStorage "dash.sidebar", this browser only), applied by an inline
script right after the menu so the first paint already shows them. The
group of the current page opens and stays open until it is closed. A
new top bar button hides the menu on wide screens; that choice is
applied in <head>, also before the first paint.
Check: open and close a few menu groups, switch pages and reload; the
groups stay as left, with no flicker. On a wide window the menu button
left of the user menu hides the menu, and it stays hidden across pages
and reloads. Narrow screens: the Menu button still slides the menu out.
Test: SidebarStateJs (ctest, needs node).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Grants tab on the Permissions page (with grants_manage: every grant in force, the history, and a form that asks
whose it is, searching accounts or characters by name), and a Permission grants card on account and character pages
(the account's or character's grants and history; the form with grants_manage). The form picks the kind (dashboard
permission, in-game command, every permission of a category, every command up to a GM level) and searches what to
grant among only what the signed-in user may grant; grant or deny, an optional expiry and a note. In-force grants have
a Remove button when the user may remove them. Players see their own grants, read-only. The Permissions page (and its
menu entry) now opens with permissions_manage or grants_manage; the GM level tabs still need permissions_manage.
Check: as GM 9, add a grant and a deny from the Permissions page and from an account and a character page, with and
without an expiry; remove one; the lists and history update (also in a second tab). As a GM 8 given grants_manage:
only the Grants tab shows, and only permissions and commands GM 8 has are offered. As a player: your own account page
lists your grants without a form.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Three sections with one-line explanations instead of paragraphs:
- Test a message: normal or best friends' free chat, the verdict, each
word with why, and Block/Allow/Remove per word.
- Staff lists: one table for Blocked and Allowed with search, a list
filter and 50 per page. Block, Allow, move and Remove open a
confirmation showing where the word stands and the recent chat the
change affects (the old "What would blocking it stop?" checks).
- Word files: each file's size in one line; chatplus_en_us.txt words
searchable, 200 per page with Previous/Next; click a word to test it.
All existing APIs are unchanged and still used. docs/Dashboard.md
rewritten for the page.
Check: /chat_filter: test a message in both chats, add, move and remove
a word (confirm and cancel), search and page both lists, copy file
words into Allowed, Re-apply in running worlds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New Mail page (/mail, characters_mail, under Moderation): every in-game
mail newest first and live, with sender and receiver linked to their
character and account, the attachment with its icon and name (waiting
or claimed), and the state (unread, read, deleted by the player with
the time). Filters: state, character (sent or received), account,
text. Open shows the body, the attachment's item ID, subkey and data.
Locale keys in mail (%[MissionEmail_12_subjectText], the game's sender
name) are shown as the client shows them, from locale.xml; the stored
text stays under "Stored text". LocaleText::Expand, unit tested.
The character Mailbox uses the same view. Staff see mail the player
deleted (marked) and a link to the character's mail on the Mail page;
the owner sees only what is still in the mailbox, without account IDs.
/api/characters/:id/mail keeps its old fields and adds the new ones.
Check: /mail with each filter, Open on game, staff and player mail,
a mission mail's subject translated; a character's Mailbox as staff
and as the owner after deleting a mail in game.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The UGC page's model view now draws the glitter sparkle shapes (look
SPARKLE) flashing as the client's Distortion Directional shader makes
them: two layers of sparkles sliding at the client's rates (a tile in
24 s at three quarters the scale, a tile in 48 s), shown only where both
have one. Flecks are drawn as flat flakes of the fleck size and varied
brightness (addGlitter in scenery-core.js), no longer drifting (the game
never moves them). The LXFML views (the UGC page's second view, the
property and zone views) draw both on the glitter colors from
window.LDD_GLITTER, which now carries every glitter setting and is no
longer cached, so changing a glitter setting on the settings page
previews on any model's LXFML view without making it again.
Check in the dashboard (not the game): open a glitter model on the UGC
page; both views show still flecks and sparkles flashing on the glitter
bricks only; change glitter_sparkle_amount / glitter_fleck_size in the
settings and reopen the model: the LXFML view follows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Why the glitter never moved: player models (LOT 14) are wrapped in
weeblewobble.kfm (RenderComponentWrapper 9845), so the client makes them
an LWOSkinnedRenderComponent, whose Run (0x00d6d3d0) updates the scene
graph (and so any NiTextureTransformController) only while animation is
enabled, and LWOModelBehaviorComponent::EnableAnimation (0x00be2740)
turns it off for modelType 2, which every placed property model is. The
root flags 0x102 added earlier are only read by the base render
component. Nothing in a placed model's .nif can move.
What does move: shader classes set globals in their own per-frame Run.
Distortion Directional (Ocean) (mapShaders 79, Run 0x010b90c0) slides
its texture layers by fixed shares of a tile a second, as the game's own
pond ripples (S79__pond_ripplesShape). Glitter bricks now get a sparkle
group, S79_GlitterSparkle_Model: their triangles lifted 0.005 off the
brick, vertex colors white tinted by the brick, UVs placed per brick,
alpha tested (ShaderCommon's alpha test phase, GREATEREQUAL 127), with a
stored texture of flat sparkles at alpha 230: one layer's sparkle alone
averages under the test, two meeting pass, so sparkles flash and go out
as the layers cross. The flecks stay (LEGO-AnimUV, now without the
controllers and flags that never ran). The icon and the dashboard's 3D
view leave the sparkles out.
New settings: shader_glitter_sparkle (79, 0 off), glitter_sparkle_size,
glitter_sparkle_amount, glitter_sparkle_tint, glitter_sparkle_brightness;
glitter_speed is now how fast sparkles flash (the sparkle tile). Only
glitter output changes; non-glitter models are byte-identical.
Check in game: reprocess a property with glitter models, then look at
them from a few angles and distances, on each graphics quality:
- sparkles flash on and off all over the glitter bricks, continuously
- no flickering fight between the sparkles and the brick surface
- transparent glitter bricks still see-through, flecks still visible
- nothing drawn where there is no glitter brick; icons unchanged
apart from the flecks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>