LWOSCENEID and LWOSCENEID_INVALID move from dCommonVars.h to
dZoneManager/LWOSCENEID.h; only the zone code uses them. The layer half
is the scene's layer, now the new eSceneType (dCommon/dEnums) instead of
a uint32_t: General (0), Audio (1, the *_audio.lvl scenes named
"Audio") and FX (2, Nexus Tower's *_fxs.lvl scenes named "FXs"), the
three layers the zone files of every client on disk use. ZoneScene's
sceneType is an eSceneType too, so a scene's LWOSCENEID is built from it
directly, and the dashboard compares against eSceneType::General instead
of 0. The zone checksum still hashes the layer's number.
Check in game: every world loads (the zone checksum the client checks is
unchanged), Nexus Tower included.
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>
NifFile::TechniqueFor maps every mapShaders gameValue to the client's
technique family (fixed function, LEGO, Basic/AlphaAsAlpha, metal, clear
plastic, ocean distortion, flat surf, BrickWater, darkling, terrain mesh),
its eShaderLook bits, texture alpha and eTechniqueFlag bits (moving
texture, both sides, blend, alpha test, additive, no ambient, glow,
super emissive, grayscale, shiny glint, not drawn, ...), from res/shaders
and the verified technique setups. Values it lacks are the LEGO shader,
as the client falls back to it. TextureAlphaFor and ShaderLookFor read it.
The scenery manifests carry it as "techniques" (replacing textureAlpha
and shaderLooks), the flairs' manifest a Flair.fx technique, the
lighting its specular color. /api/scenery/env/:name serves the
environment cubes the client's shaders load themselves (default
reflection, polished and brushed metal, brushed noise). Conversion
format 4.
scenery-core.js: techniqueOf, gameLook with the family and flags,
blendingOf, parseDdsCube; its test checks the flag and look bits against
NifFile.h.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"Clear threat list Trigger Wall" (LOT 13632) on the NS medium property was
drawn as a big red wall: nothing in its data hides it, its client script
does (scripts/02_client/map/general/l_set_invisible.lua sets it invisible in
onRenderComponentReady). The scenery now reads each object's client script
once and treats an object as hidden, like renderDisabled, when a
self:SetVisible{visible = false} is directly in onStartup or
onRenderComponentReady (not under a condition). 12 LOTs match: trigger
volumes, effect containers, a scripted camera, dummies, booty chests (shown
once dug). They show with Hidden objects on.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NifFile::TechniqueFor maps every mapShaders gameValue to the client's
technique family (fixed function, LEGO, Basic/AlphaAsAlpha, metal, clear
plastic, ocean distortion, flat surf, BrickWater, darkling, terrain mesh),
its eShaderLook bits, texture alpha and eTechniqueFlag bits (moving
texture, both sides, blend, alpha test, additive, no ambient, glow,
super emissive, grayscale, shiny glint, not drawn, ...), from res/shaders
and the verified technique setups. Values it lacks are the LEGO shader,
as the client falls back to it. TextureAlphaFor and ShaderLookFor read it.
The scenery manifests carry it as "techniques" (replacing textureAlpha
and shaderLooks), the flairs' manifest a Flair.fx technique, the
lighting its specular color. /api/scenery/env/:name serves the
environment cubes the client's shaders load themselves (default
reflection, polished and brushed metal, brushed noise). Conversion
format 4.
scenery-core.js: techniqueOf, gameLook with the family and flags,
blendingOf, parseDdsCube; its test checks the flag and look bits against
NifFile.h.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NifFile::ShaderLookFor knows Polished Metal (98), Brushed Steel (99) and
LEGO-Emissive (53). The UGC mesh route sends each mesh's look (from its
multishader tag), and the UGC 3D view draws metal as reflective and glow
unlit. The zone views draw LEGO-Emissive objects going to their vertex
color by its alpha, as the shader does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Shader 94 ("Basic") draws with vertex colors: its class's technique setup
names Technique_Basic_Lighting_VertColor, as 38 "Basic VC" does. The views
treated it as having none, so Nimbus Station's glom pines (tag S84) came
out as their grey texture, white. The other shader looks in use were
checked the same way (33, 35, 37, 70, 82, 84, 105 hold).
- Two layer shaders: NiTexturingProperty's dark texture and the UV set each
texture's flags name are read, and the views draw "Two Layers Blended" as
the dark texture under the base one by the vertex alpha (no longer as
opacity) and "Two Textures Added" as in TwoLayersAdded_PS. Avant Gardens'
snowy grass mounds were see-through hills. The client ships no technique
for the blended ones, so that blend follows the meshes' data.
- The near plane follows how far out the camera is (distance / 400, 0.5 to
20) instead of a fixed 0.5 over a far plane in the thousands, so ground
overlays, floor rings and road pieces stop fighting in far views.
- Conversion format 3 (new model data), so kept conversions are made again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A "Scenes" choice in the world and property 3D views: every scene (as
before), the scenes the game keeps loaded around the camera or the followed
player (the scene under it from the terrain's scene map, the scenes its
transitions connect to, and the global scene, following as it moves), or
scenes picked from a list (world view). The lighting blends to the lighting
of the scene under the focus, as the client blends between scenes.
The scenery manifest now carries each object's scene, the zone's scenes with
their neighbours and lighting, and the scene map as runs (37 KB for Avant
Gardens); scenery-core.js finds the scene at a point exactly as ZoneScenes
does (checked against it on 2000 points of Avant Gardens).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Glom models (multishader) drew their trees, rocks, fences and water white.
Their conversions kept on disk from before meshes carried their multishader
tag were still served (the cache format version was never bumped), so every
part fell back to the LEGO shader, whose texture alpha lays the (mostly grey)
texture over the vertex colors that hold the actual colors. Browsers also
kept those models for a week.
- Bump the conversion format so old conversions are made again, and put it
in the manifests; the viewers add it to model and texture URLs.
- Light scenery as the client's shaders do: the scene's sun and ambient
light from its .lvl (read as level_read_lighting_info, 0x0102f8f0, and
EnvironmentManager::SetLightEnv, 0x01088aa0, do), per vertex, clamped,
instead of the view's own lights, environment map and tone mapping. The
zone takes the lighting most of its objects' scenes have.
- Programmable shaders read vertex colors and ignore NiMaterialProperty's
color and alpha; unlit and untextured shaders (by mapShaders gameValue)
leave out lighting or the texture. Fixed function stays as it was.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The viewer treated every blended texture's alpha as opacity, so models
whose shader uses the alpha for something else rendered see-through. The
scenery manifest now carries each model's shader (RenderComponent.
shader_id via mapShaders) and the multishader tag table; meshes carry
their S##__ tag, read the way LWOBaseRenderComponent::AddObjectToRenderPipe
does (S%d, else _S%d, outside 3..108 the LEGO shader). Per res/shaders:
the LEGO lighting shaders lerp the texture over the vertex colors
(decal), LEGO items and terrain meshes ignore its alpha, everything else
keeps opacity. Pure rules unit tested.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opening a zone the first time built its terrain, scene objects and manifests
and ran ImageMagick on the web thread, stalling the dashboard for seconds.
- Workers: the shared pool plus Workers::Reply (answer at once when built,
else from a worker via Web::Defer).
- terrain_chunks/terrain_layers/scene/paths/scenery/flairs (world3d, property
and showcase routes) and terrain textures go through it; results are built
once in OnceCaches, the .raw is read once per zone for chunks, layers and
flairs, deflated bodies are cached thread-safely.
- ImageMagick conversions are deduplicated and written under a temporary name.
- Workers don't query the CDClient, read settings or call mongoose: ZoneTable,
render components, flairs, object names, LOT kinds and terrain texture names
are read at startup; client_location is read once; base64 is plain C++.
- Logger writes one line at a time (mutex; localtime's buffer is shared).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dashboard's web server answers one request at a time, so converting a big
.nif (glom files up to tens of MB) held up every other request, flairs included.
- dWeb: Web::Defer hands a request to another thread; the reply is sent from the
web thread on its next poll (DeferredQueue). A client that leaves first cancels
it and the late reply is dropped. The synchronous route API is unchanged.
- Web::Shutdown closes connections while the state their close events touch is
still alive; the destructor no longer runs handlers during static destruction
(stopping the dashboard aborted in ~WSClient).
- WorkerPool: priority lanes, with one thread only for urgent work (flairs,
small models, textures), and limited background work.
- Scenery: mesh and texture routes (and the showcase's) convert on the pool;
thread-safe memory and disk caches, one conversion per model at a time with
waiters sharing it; zones are converted ahead onto the disk cache while viewed.
- Setting scenery_workers (0: half the cores, 2 to 4).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The NexusDashboard-parity dashboard (dDashboardServer) and everything built on it on the experimental branch:
accounts, characters, properties and moderation tools, permissions shared with in-game slash commands, economy
reports, World 3D and property 3D views with client scenery, scheduled events (features, vanity changes, live
events, announcements, restarts), vanity files and events, the CDClient browser, the message inspector with saved
captures, chat filter tools, community challenges, live ops, the AI moderator helper, and the server-side changes
they need.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>