Venture vision from an equipped item was sent while the character loaded, before the client's UI existed, so after a
login the minimap stayed empty until the item was equipped again (a world transfer keeps the UI, so it worked
there). The player's active venture vision effects are sent again once the player has loaded. Check: wear the
Venture Vision helmet, log out and back in: the minimap shows the icons.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The table named commits by their hashes from before earlier rebases; each is now the current hash of the commit
with the same subject.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The client adds every event string of the login response as an enabled feature (AddFeatureGate from the login
response handler), so event_1..event_8 = guilds turns guilds on in a stock client; no client file needs changing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/Guilds.md gains what DLU does with the client's guild system: the chat server as the authority, the world <-> chat
packets, the rank rules, the invite and name rules, the slash commands, the dashboard page and what is not done (a
member's name change reaches guildmates only with the next GUILD_DATA; reputation is 0). docs/Commands.md lists the guild
commands, docs/Dashboard.md the Guilds page, the guild names in the Review Queue and guild chat under chat_private.
Check: nothing in game (documentation only).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/Guilds.md: what the client's guild system needs, from Ghidra and the client's Scaleform UI. The feature gate
(FeatureGating "guilds", missing from the shipped cdclient), the UI calls and messages, what the character component
serializes, every guild packet's layout and what the client does with it (including the ones it has no handler for),
GUILD_DATA's member records, DisplayGuildCreateBox, the guild chat channel (the chat box sends /g), rank names and the
limits the client enforces. No live capture has guild traffic.
Check in game: nothing (documentation only).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Checked for the "module textures in car and rocket icons" request: none
of the 399 render assets of the client's ModuleComponent LOTs (1.10.64;
the same in the other clients on disk) has an NiSourceTexture or
NiTexturingProperty. The modules' look is their vertex colors and
materials, which the icons draw already, so there is nothing to add.
Check: nothing to check in game; compare a car's and a rocket's icon with
the client's module icons (textures/ui/rebuilding/) if in doubt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A make's recorded time (process_ms, stats.json's ms.total) includes the
icon drawn at its end. Drawing only the icons again (the icon editor's
Draw all icons of this type again) left the stats and the rows with the
old icons' time. Now the icon-only job writes stats.json with the new
icon's time (ms.icon, ms.total changed by the difference,
UgcJobs::WithIconTime) and the main thread changes the row's process_ms
and process_cpu_ms by the same difference (the icon is drawn on one
thread, so its time is taken as its CPU time). The dashboard's Took,
CPU and totals follow.
Check: open a player model on the UGC page, Draw all icons of this type
again: afterwards its Took changes by the icon's difference and its
stats show the new icon time.
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>
The card had the UGC page's counts per state for both kinds, totals since
the server started and the last makes, which the UGC page's lists cover.
It now says whether the UGC server is up (throttled, paused), how many
items wait and failed (linking to the failed ones), its busy workers,
CPU, memory and stored files.
/api/diagnostics/ugc read the database on a worker thread; the counts are
now read on the web thread and the worker only fetches the UGC server's
status.
Check: Diagnostics with the UGC server enabled: the card is short, reads
right while it's up, throttled and stopped, and the failed link opens the
failed ones.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cars and rockets built before builds were recorded were saved with
subkey 0 and have no ugc_modular_build row, so the client has no
blueprint id to ask for their icon with. The runtime fix only reaches
characters that load again.
Migrations mysql 98 and sqlite 81 (98/81 because the guilds work takes
97/80) run ModularBuildIdMigration after the SQL: every saved item with
modules (x@ma) and no subkey gets what a new build gets, as the
character-load fix does: a persistent id from object_id_tracker (with
the character bit) as its subkey and a ugc_modular_build row with its
modules and the character as owner. The XML is written with
UpdateCharacterXml. Tried on a copy of a server's database with a
couple of thousand such items: every one got an id and a build row, in
seconds.
Check: after the migration, old cars and rockets show their icons in the
backpack (the UGC server makes them like any build) and still work
(equip, race, launch).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New section 7 in CaptureUnknowns.md: how DLU's constructions of the 200 most
common LOTs were compared with the live captures, what was fixed, and each
remaining difference with its evidence (quickbuild default destroyable,
enemy immunities, script network vars, construction effects and buffs, pet
state, moving platform path info, jetpack, character club/prop-mod/leave
fields, model UGC ids, parent position flag, item extra info, component
order notes).
Check in game: nothing (documentation only).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Check: docs/PacketArchitecture.md, game message differences: the
SetCurrency and PickupCurrency rows describe the fixed layouts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Live sent the launchpad's FireEventClientSide("RocketEquipped") to every
client in the zone: 1,196 of 1,265 captured were other players'
launches. On each client it starts that player's launch
(LWORocketLaunchComponentCommon::msgFireEventClientSide sends
BeginLaunch to the sender), so others see the rocket take off; DLU sent
it only to the launcher. param1 is the property clone for property
launches (7 of 7 equal the clone in the following TransferToZone) and
param2 the picked world of a LUP entrance (0-3, one pad only).
The capture notes read the RocketEquipped and ChangeObjectWorldState
seen before LEVEL_LOAD_COMPLETE as the arriving player's own rocket:
all 21 are other players launching (their sender is never the loading
player), so arrival itself is left as it is.
Check: with two players at a launchpad, launch one: the other sees the
rocket launch animation; launch to a property and to a LUP world and
land in the right place.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CaptureUnknowns.md section 4 lists what DLU now does with SetMissionTypeState,
SetTooltipFlag, SetLastCustomBuild, CasterDead, ResyncEquipment,
RequestRailActivatorState, ModifyGhostingDistance and UgcDownloadFailed,
and which ignored messages are left and why. New section 6: what the
server-only tables CollectibleComponent, EventGating, SmashableComponent
and RebuildSections hold, and that the last two are used by no object in
1.10.64.
Check in game: nothing (documentation).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The per-statistic triggers and amounts DLU now follows, with what the
captures showed and what is inferred (DistanceDriven's interval).
Check in game: nothing (documentation).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Check: docs/Dashboard.md, Live updates: the page-scripts paragraph names
goTo(url) and reloadInPlace() and says when dash:refreshed is used.
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>
Dashboard.md: what a grant and a deny are, how they combine with GM levels, what can't be granted, who may manage
them (grants_manage, nothing you don't hold, the rank rules), where they are managed, live changes, audit log entries
and the API. Commands.md: how grants and denies apply to slash commands.
Check: the new sections read correctly and the link from Commands.md to Dashboard.md#permission-grants works.
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>
The fleck texture was 50 soft round blobs of one size, bright in the
middle and fading out, which read as a smudgy dot pattern. LEGO's glitter
bricks have many small flat flakes (about half a millimetre) of which
most look faint and a few catch the light. The flecks are now flat
flakes of glitter_fleck_size (0.05 model units, i.e. 0.5 mm; 0.7 to 1.3
of it) with a one-pixel edge, each as bright as its facet catches the
light (0.3 to 1 of glitter_fleck_opacity, 80%, weighted towards dim),
80 a tile by default. The texture grows (128 to 512) to keep a fleck 3
pixels wide. New settings glitter_fleck_size and glitter_fleck_opacity;
glitter_density defaults to 80. Only glitter output changes.
Check in game: reprocess a glitter model; close up, the flecks are small
crisp flakes of varied brightness, not blurry dots; from a few metres
the brick still reads as its color with a fine glitter.
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>
Every glitter brick had the same flecks in the same places: the UVs were
the vertex positions projected on an axis plane, so bricks a whole tile
apart (and every brick of the same shape at the same spot in its own
model) looked identical. Each brick now has a number of its own
(UgcGlitter::BrickSeed, from the model's id and the brick's index, kept
per vertex in Mesh::brickSeeds) that turns the projection by an angle
and moves it by an offset under a tile, differently for each axis
plane. A model made again gets the same patterns; every LOD of a brick
the same one. The icon now draws the flecks on the UVs the .nif has
(Mesh::uvs read back by FromNif). New setting glitter_random (1; 0 puts
the same pattern on every brick as before). Non-glitter models are
byte-identical (hash tests unchanged).
Check in game: reprocess a model with several glitter bricks of the
same shape; the fleck patterns differ from brick to brick.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drops the analysis views (objects, loot odds, missions, skills, behavior
trees, activities, zones), the name search and the 3D preview, with
their API routes and CDClientRules.h. What stays: the table list,
paging, sort, any-column search, column filters, and linked values that
open the target table filtered to that ID. Old links such as
/cdclient#/object/<LOT> (UGC page, world view) now open the Objects
table filtered to that LOT.
Check in the dashboard: CDClient Browser lists every table; open one,
sort by a column, add a filter, search, page; click a LOT or loot
matrix value; /cdclient#/object/1727 opens Objects id = 1727.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A client asks for a served model's HKX and is answered with the model's
LXFML, so it builds its own collision. That build also writes the
client's own .nif over the served one it downloaded and caches that
file's MD5 as the NIF's manifest info (client 1.10.64:
LWOBBBInterface::GenerateModelFromLxfml 0x00b6c220, MainThread_Process-
ModelResponse 0x00b5a1e0; valid entries never expire, 0x010186d0). On the
next load of the property the client used its cached checksum and file
without asking, and drew its own build instead of the served mesh.
Now, before the property's objects are constructed for a player, the
world sends them the served NIF checksum of every made model placed there
(UgcManifest::OnPropertyLoading). A client whose cached checksum is its
own build's downloads the served mesh again; one that has it already
downloads nothing. Nothing is sent unless ugc_manifest and
ugc_manifest_models are 1.
Check in game (ugc_manifest=1, ugc_manifest_models=1): visit a property
with made models, leave, come back in the same session (and after a
client restart): the models show the served mesh every time, and still
have collision.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When a model finishes on the UGC server while players are on the property,
each client was sent the served NIF checksum, NotifyClientUGCModelReady and
the model constructed again at once. A client that was sent the model's
LXFML shortly before (the property load, a request for a model not made
yet, the owner's brick by brick save) is still building it then: the build
writes its own .nif over BrickModels/UserMade/<id>.nif and caches that
file's MD5 as the NIF's manifest info when it finishes (client 1.10.64:
LWOBBBInterface::GenerateModelFromLxfml 0x00b6c220, MainThread_Process-
ModelResponse 0x00b5a1e0), undoing the switch, so it kept its own build.
That is the usual case: another player's client asks for a model the owner
just placed, gets its LXFML, and that request makes the UGC server make the
model at once.
Now such a client is switched 30 seconds after the last LXFML sent to it
(UgcManifest::ServedMeshSwitches, BUILD_SETTLE); another LXFML sent
meanwhile starts the wait again. Other clients are switched at once, as
before. The served checksum is looked up when the switch happens. HKX
requests are still answered with the LXFML, so collision stays the
client's own.
Check in game (ugc_manifest=1, ugc_manifest_models=1, two accounts on one
property): the owner saves a new model; within about 30 s of the UGC
server making it, the other player's copy blinks out and back with the
served mesh (vertex AO, look of the dashboard's viewer), and still has
collision (walk into it). The owner's copy switches the same way. The
world log shows "Switching ... to the served mesh of model ...".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The three pages had in-page tabs linking to each other, the same links
as the Logs & Health sidebar group. Removed the tabs (health_tabs
template); each page is still in the sidebar. Diagnostics gets an
<h2> heading like the other two, since the tab was its only title. The
log pages had no tabs.
Check: Server Health, Instance Load and Diagnostics open from the
sidebar with no tab row; Diagnostics shows its heading; the range and
server controls still sit on the right.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The page held one-off repairs from Nexus Dashboard (approve known pet
names, find/delete orphaned pet names, remove every buff, fix property
clone IDs, list mission rewards without a commendation price). Removed
the page, its sidebar entry, its /api/maintenance/* routes, the
`maintenance` permission and the two database calls only it used
(GetAllPetNames, FixPropertyCloneIds). The scheduled tasks (lift expired
bans, fill in pet owners, approve known pet names) and property model
import/removal stay.
Check: the Admin sidebar group has no Maintenance link; /maintenance is
a 404; the Tasks page still lists "Approve known pet names" and "Fill in
pet owners"; property import still works; the Permissions page no
longer lists "Data maintenance".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- IUgc::GetUgcProcessTotals sums what the UGC server made, for models and
for car and rocket builds: count, time spent (and how many are timed),
CPU time, average and slowest, average and most memory (estimate),
bricks, triangles and triangles saved (models whose count before hidden
face removal is known). /api/ugc returns them as totals and the UGC page
shows a card for each kind. Parity tested.
- Player models no longer have a shared icon preset: every one is a
different size and shape, so its icon is fitted to it from the settings.
The UGC server ignores a kind:model preset, the dashboard refuses to save
one, and the icon editor hides the type buttons for models. One model's
own icon values still work. Car and rocket build types keep theirs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Flair tints are the terrain file's color bytes over 255, times the flair
model's own vertex colors (FlairAssets::AppendRenderBuffer divides by
255.0). The manifests said 63, so in the game shaders' sRGB maths tints
of up to 4 turned the flairs white (Battle Against Frakjaw's leaves).
Conversion format 6, so flair manifests kept by browsers are fetched
again.
- BasicShaders, AlphaAsAlpha and Flair.fx multiply the light by the vertex
color and only then clamp, as the COLOR0 output; the views clamped the
light first, so a light brighter than 1 no longer lifted darker vertex
colors.
- Docs: the flair tint, the clamp, and that AlphaAsAlpha cards show their
backs (Cullmode none) from outside a playable area.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The game shader views looked up each shader's technique in the manifest's
"techniques". Property scenery manifests are cached by browsers for a day
(world ones for an hour), so after the update a browser drew the property
view from the manifest the older server had sent, which has no
techniques: every shader fell back to LEGO, whose decal texture alpha
laid the see-through tree, rock and water textures over white vertex
colors. Nimbus Isle came out with white trees, rocks and water, a yellow
build surface and a solid white build border.
- Manifest URLs carry the conversion format the views are written for
(?format=5, scenery-core.js SCENERY_FORMAT), so a kept manifest from
an older server is never used; SceneryCoreJs checks it matches
Scenery.cpp FORMAT_VERSION.
- A manifest without techniques (an older server's) is drawn with the
viewer's own lights and its textureAlpha table instead of every
shader guessed as LEGO.
- A material whose NiAlphaController animates its alpha is drawn at its
highest key. The AnimAlpha shaders now use the material alpha, and
effects resting at 0 in the file (the Venture Explorer's lightning)
had vanished. Conversion format 5.
Checked by rendering the world view of every zone with models and the
property view of every property template (headless, fixed cameras)
before and after, and the Nimbus Isle property with a manifest stripped
of its techniques, which reproduced the white look.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
game-shaders.js ports the client's techniques to one ShaderMaterial
program per family and variant: LEGOPPLighting (hemisphere lit sun,
ambient, fresnel rim, N.H^320 specular, the default reflection cube;
decal and non-decal textures, emissive, super emissive, glow, grayscale,
no ambient, AnimUV), BasicShaders and AlphaAsAlpha (lit or unlit, both
sides, alpha blend, alpha test, additive, animated alpha, two layers),
Metallic.fx polished metal and brushed steel with the client's metal
cubes, clear plastic, the Distortion (Ocean) layers, Flat Surf,
BrickWater, darklings, terrain meshes, flairs and the sky. The maths runs
on sRGB values as Direct3D 9 did; lights, specular, hemisphere and fog
blend between scenes; textures move by the .nif's texture transforms.
Programs are shared by every material with the same defines.
A Fog switch (off by default) adds the zone's fog to scenery and
terrain. Shaders the game doesn't draw in the world (footprints, drop
shadows, post-processing) are left out. Docs list the families, their
gameValues and what's approximated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 42 depth renders only saw faces in direct view, so faces reached only by
bounced light (interiors, recesses, rooms seen through openings) were removed.
UgcHsr traces the paths LU Toolbox's Cycles bake traces, directly from points
on each opaque triangle, and removes a triangle only when none of its paths
reaches the sky:
- points in rows along the triangle's longest side, hsr_sample_spacing apart
(0.1143, 7 x 7 on a stud-sized square), at least hsr_min_points (28, the
texels LU Toolbox bakes for a triangle), at most 4096
- hsr_samples (8) paths from each point, at most hsr_bounces (8) bounces, as
Cycles 3.1 samples the bake material (Principled BSDF defaults: Burley
diffuse and GGX specular, defensive sampling, Filter Glossy, 4 glossy
bounces, Russian roulette from the second bounce, ensure_valid_reflection);
no direct sky sampling (Cycles doesn't sample a flat world as a light)
- hsr_ground_plane: LU Toolbox's black box under LDD's floor
- decided per triangle, deterministic per model; triangles without area removed
- the VC pre-pass isn't done
Checked against LU Toolbox's operator in Blender 3.1.2 on the same meshes (27
models, 937,814 triangles): 501,362 removed there, 501,172 here, differences
as large as LU Toolbox's own between seeds. optimize_resolution is retired;
remove_hidden_faces=0 makes the same files as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- resources/*.ini list the 73 settings the catalog knew but the files left
out (dashboard AI helper, backups, metrics, public status, strikes,
property rent and reputation, chat log, contraband, logins...), with
their title, description and default. The test
ShippedFilesListEveryCatalogSetting keeps it that way; with
DLU_WRITE_INI_TEMPLATES=1 it writes the missing ones.
- ConfigSync forgets a setting row when its key has left a file the
server read: from the file, no value set on the dashboard, not a
permission level. Before, rows of removed keys stayed forever.
- Docs: where setting rows come from and when they go, the templates.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/LiveUpdate.md: how to start one, the order, each kind of instance, the
states, routing, moving players and properties, messages, settings, what a
player sees and the limits. SeamlessTransfer.md, Commands.md and Dashboard.md
point to it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>