Commit Graph

104 Commits

Author SHA1 Message Date
Aaron Kimbrell
93f4b051c6 fix(dashboard): flair tints and Basic lighting as the client computes them
- 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>
2026-09-28 22:31:25 -05:00
Aaron Kimbrell
4bd34dc087 fix(dashboard): 3D views never draw a kept manifest with the game shaders
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>
2026-09-28 22:31:24 -05:00
Aaron Kimbrell
f45a21c15f feat(dashboard): the game's own shaders in the world and property 3D views
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>
2026-09-28 22:31:24 -05:00
Aaron Kimbrell
bea6b17b25 feat(ugc): hidden faces removed as LU Toolbox's Remove Hidden Faces decides them
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>
2026-09-28 22:31:24 -05:00
Aaron Kimbrell
7f0c0c23d0 chore(settings): every catalog setting in the shipped .ini files; forget settings taken out of a file
- 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>
2026-09-28 22:31:23 -05:00
Aaron Kimbrell
ffcf01e43b docs: live updates
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>
2026-09-28 22:31:23 -05:00
Aaron Kimbrell
bfc45dc662 docs(ugc): processing at a glance, how the AO is cast, shader groups, queue order, newer columns
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:23 -05:00
Aaron Kimbrell
51cd1ddfba fix(ugc): moving glitter is updated every frame
The client updates an object's scene graph each frame only when its root
NiNode has the selective update bit (0x02; LWOBaseRenderComponent::Run
0x00d5d770 via NiAVObject::GetSelectiveUpdate 0x00413050). Our roots had
0x110, so a glitter model was updated once when it loaded and its texture
controllers never moved. A model with moving glitter now has 0x102 on its
root and the glitter group's nodes and 0x1A on the glitter shapes, as the
client's own AG ocean; still glitter and everything else keep the flags
they had.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:22 -05:00
Aaron Kimbrell
c3b52545b5 Revert "feat(dashboard): the game's own shaders in the world and property 3D views"
This reverts commit acc4853756.
2026-09-28 22:31:22 -05:00
Aaron Kimbrell
e0ccd3a016 Revert "feat(ugc): glitter flecks still by default"
This reverts commit 752c918311.
2026-09-28 22:31:22 -05:00
Aaron Kimbrell
fa563a558a feat(ugc): glitter flecks still by default
Glitter plastic has its flecks set in it; they catch the light as the view
moves, which LEGO-AnimUV can't do (it can only slide the texture). Drifting
flecks read as something flowing over the brick, so glitter_speed defaults
to 0: still flecks and no controllers. 1 and up still drift.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:22 -05:00
Aaron Kimbrell
d817697ab2 feat(dashboard): the game's own shaders in the world and property 3D views
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>
2026-09-28 22:31:22 -05:00
Aaron Kimbrell
7bba8344fc feat(ugc): glitter flecks (LEGO-AnimUV) and milky satin in made models
Glitter colors (Materials.xml type glitter, glitter_colors 114,117) go into
S21_Glitter_Model and, transparent, S21_GlitterAlpha_Model (shader_glitter,
default 21, LEGO-AnimUV). Their shapes get box-projected UVs, an
NiTexturingProperty with a stored 128 px mipmapped fleck texture
(NiSourceTexture + NiPersistentSrcTextureRendererData, as the client's own
env_ag_ocean-maelstrom.nif) and two NiTextureTransformControllers looping
the base map's translation (glitter_size, glitter_density, glitter_speed).
The shader lays the texture over the vertex color by its alpha and outputs
the vertex alpha, so transparent glitter blends as S01_Alpha does.

Satin colors (satin_colors, LEGO's opal colors) stay in S01_Alpha but get
satin_opacity and are whitened by satin_whiten.

NifFile reads the base map's scroll speed (uvScroll) from the controllers;
the icon draws still flecks, the UGC 3D view and the LXFML viewers moving
ones. stats.json counts the glitter groups. With shader_glitter 0 and no
satin colors the files are the same bytes as before (tested). Also keeps
glow_emissive for the icon (it was reset by the icon settings).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:21 -05:00
Aaron Kimbrell
9e4f2818c3 feat(ugc): staff reprocessing of a property goes to the front of the queue
/reprocessproperty and the dashboard's Reprocess all models mark the
property's models as priority (ugc.priority, migrations mysql 94 and sqlite
77). The UGC server takes priority models first, polls them even when its
queue is full, and puts them at its front, as it does cars and rockets. The
flag clears once a model is made.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:21 -05:00
Aaron Kimbrell
8d57cc82cf feat: /reprocessproperty, make a property's models again and reload it
A GM 8 command: every brick built model on the property you are on goes
back to the UGC server's queue. Once all are made (at most 15 minutes),
everyone on the property is sent the new mesh checksums and transferred
back into the same zone and clone, so their game loads the property again
and downloads the new meshes. Swapping a model's mesh in place doesn't
work in the client, so the whole property is loaded again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:21 -05:00
Aaron Kimbrell
ebf3a05704 feat(property): best friends of the owner can build on the property
property_bff_build (off by default, as live): while the owner is in build
mode, their best friends can join it and place, move and pick up models,
build brick by brick and edit behaviors, each from their own inventory.
Only the owner starts build mode; a best friend still in it when the owner
leaves keeps building until they leave it.

The client lets only the property's owner edit, so each player now gets
their own DownloadPropertyData, with their own id as the owner while they
can build, sent again whenever that changes. SetBuildModeConfirmed and
GetModelsOnProperty go to each player instead of everyone. The first
builder makes the property private and pauses the models; the last one
restores them. Saving no longer needs the owner in the world.

A model taken off the property goes to whoever placed it; if they aren't
here it stays placed. Privacy and the property's name stay owner only
(neither was checked before).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:20 -05:00
Aaron Kimbrell
462a152a66 feat(ugc): metal, brushed steel and glow shaders on by default
Tested in game: shader_metal 88, shader_brushed 89 and shader_glow 46 are
now the defaults, with brushed_colors defaulting to the drum lacquered
298,300,1002,1004 and transparent_colors to 129. Empty list settings take
the default; none turns a list off. The three shader ids set to 0 still
write live's all-plastic models byte for byte.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:20 -05:00
Aaron Kimbrell
5396594690 fix(ugc): served models keep the served mesh; physics from the LXFML sent for the HKX
Sending every model's LXFML at property load and then switching to the
served mesh (served checksum, NotifyClientUGCModelReady, the model
constructed again) left the client drawing its own build. Now made models'
LXFML is left out of the property load again: the client downloads and
draws the served mesh, and when it asks for the HKX it gets the LXFML,
builds the model and loads its own HKX, so the model has collision while
the mesh drawn stays the served one. The load-time switch is removed; the
switch for a model made again while players are there stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:20 -05:00
Aaron Kimbrell
e27f2085dc fix(ugc): construct the model again a second after taking it down
Taken down and constructed again in the same batch, the client dropped the
construction of the object it hadn't deleted yet, and most models
disappeared. The construction now follows a second later.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:20 -05:00
Aaron Kimbrell
d1a61450f9 fix(ugc): construct the model again only after the client's flush
Constructed right after NotifyClientUGCModelReady, the flush the client does
on its load thread could land after the new object had loaded its mesh, and
most models disappeared. The model is now constructed again 1.5 seconds
later.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:19 -05:00
Aaron Kimbrell
b118ecfb73 fix(ugc): swap to the served mesh by constructing the model again
NotifyClientUGCModelReady only flushes the client's cached NIF, HKX and
LXFML and loads them again as preloads (0x00ca6430): an object already
drawn keeps its mesh, so the switch to the served mesh after a property
load (and a model made again) changed nothing on screen. Now each player
also has the model taken down and constructed again: the new object loads
the NIF, whose cached checksum is the served one (sent first), and the HKX,
whose checksum is still the one the client built, so it keeps collision.
Only models shown to that player are constructed again. Each switch is
logged.

Also corrects the address of the client's brushed steel texture
registration in the docs: 0x00467090 (RegisterBrushedSteelTextures) in
the 1.10.64 client.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:19 -05:00
Aaron Kimbrell
0c5ef380d3 feat(ugc): color_brightness and transparent_colors
color_brightness (percent, default 100: unchanged) scales the models' vertex
colors, not the icons', for servers where the made models look brighter than
they should. transparent_colors names color ids drawn transparent whatever
Materials.xml says: 129 (Tr. Bright Bluish Violet with Glitter) has alpha
255 there, so it came out opaque; a named color gets transparent_opacity.
Both default to off, so models come out byte for byte as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:19 -05:00
Aaron Kimbrell
e5a230e6a3 fix(ugc): served player models keep the client's own collision
With ugc_manifest_models the world left made models out of the LXFML it
sends when a property loads, so the client never built them and had no HKX:
the UGC server makes no physics, and the HKX request got a 404, so served
models had no collision.

Now every model's LXFML is sent and the client builds each one (NIF and
HKX). For the models whose mesh the UGC server made, once the client has
loaded and 3 seconds after, the world sends it the served NIF's checksum and
NotifyClientUGCModelReady: the client drops what it cached for the model and
asks again, downloads the served mesh (its own NIF no longer matches) and
keeps its own HKX (still matching). An HKX request is answered with the LXFML
too, followed by the same switch, at most 3 times per client and model.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:19 -05:00
Aaron Kimbrell
f3922b3bcb feat(ugc): brushed_colors, LEGO color ids drawn as brushed steel
The client's Materials.xml has no brushedSteel or matteSteel colors, so the
Brushed Steel shader (mapShaders 89) was never used. brushed_colors names
color ids to draw with it whatever their type (e.g. the drum lacquered
298, 300, 1002, 1004); a named color wins over the metal and glow colors.
Empty by default. The docs note that the client registers the brushed
reflection and noise textures itself (0x00453730), so the .nif needs none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:18 -05:00
Aaron Kimbrell
c39b7ee935 feat(ugc): opt-in metal and glow shader groups in made models
Player models are multishader (RenderComponent shader 100): the client
wraps each NiLODNode and draws it with the mapShaders id in its name.
With shader_metal, shader_brushed or shader_glow set, the opaque bricks
are split by look into S<id>_Metal_Model, S<id>_Brushed_Model and
S<id>_Glow_Model beside S01_Opaque_Model and S01_Alpha_Model, each with
every LOD level. Metal is LU Toolbox's metallic colors plus Materials.xml
types (shinySteel; brushedSteel and matteSteel for brushed), glow its
glow colors. Glow shapes get an emissive material (glow_emissive) and
their plain color, not the baked one. Transparent glow stays in S01_Alpha.

All off by default, which writes the same bytes as before (tested). Not
how live looked; models already made change only when made again.

The icon renderer reads the groups back by tag and draws glow at its
plain color and metal with a tinted reflection and highlight.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:18 -05:00
Aaron Kimbrell
cc67fc7e42 docs(ugc): boot.cfg for the UGC server and models without 3D services
The earlier finding that the client ignores the UGCSERVER* lines of its
boot.cfg was wrong: the test clients' boot.cfg had a line without its
trailing comma, so the client rejected the whole file and used its
defaults. Documents the boot.cfg a server owner needs, what the client
does with a placed model's files (checked in the client) and what the
worlds now send.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:15 -05:00
Aaron Kimbrell
1d72766330 feat(ugc): icons as DXT5 DDS like the client's own
The client's 128x128 UI icons are almost all DXT5 without mipmaps, with
header flags caps|height|width|pixel format|linear size (0x81007) and
caps 0x1000. The UGC server's icon.dds is now written the same way
instead of as uncompressed 32-bit BGRA with a pitch.

The BC3 encoder fits each block's colour endpoints along the principal
axis of its visible pixels (transparent ones are never seen), refines
them by least squares, and stores alpha with the block's own range.
Tests check the header against the client's format and decode the
result back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:14 -05:00
Aaron Kimbrell
79235702b3 feat(ugc): answer the client's UGC manifest requests without 3D services
With UGCUSE3DSERVICES=7:0 (the client's default) the client asks its world for
a blueprint file's MD5 and size (REQUEST_UGC_MANIFEST_INFO, world 27) and then
downloads BrickModels/UserMade/<id % 1000>/<id>.<ext>.sd0. Layouts checked in
the 1.10.64 client: the request is a u64 blueprint id and a u8 resource type;
the answer (UGC_MANIFEST_RESPONSE, client 60) repeats them and adds a u8 valid,
the u32 size and the 16 byte MD5 of the inflated file, 37 bytes after the 0x53
exactly or the client drops it.

- dNet: WorldPackets::RequestUgcManifestInfo, ClientPackets::UgcManifestResponse
  (eUgcResourceType), with byte tests against the client's layouts.
- Database: ugc_file_checksums (per model or module combination and file) and
  ugc_modular_build.combination_id (migrations 89 / 72), GetUgcFileChecksum
  looks a blueprint up as a model, else as a build through its combination.
- UGC server: every download is also written as .sd0 (Sd0::Compress); workers
  hand the checksums back and the main thread stores them; old items get their
  sd0 icon and checksum, and builds their combination id, once at start-up, a
  few per tick; serves <dir>/BrickModels/UserMade/<bucket>/<id>.<ext>.sd0 under
  client_path, /<folder>/UserBrickModels and the root (.hkx 404).
- World: UgcManifest answers on the main thread with one indexed query per
  request; files not made yet are answered when they are (looked at again
  every 5 seconds), and a model in its quiet period is made right away. No
  worker threads, HTTP or file reads in the world.

Off by default (ugc_manifest=0): checked in game, the client then downloads
from http://127.0.0.1:80/lwoclient/UserBrickModels/ whatever its boot.cfg says
and logs the player out when it can't connect, so icons need the UGC server on
port 80 of each player's machine. docs/UgcServer.md has the details.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:14 -05:00
Aaron Kimbrell
36cefc1ede feat(ugc): brick data through the client's assets; colours from Materials.xml everywhere
The UGC server reads brickdb.zip and brickprimitives through DLU's
AssetManager (loose files first, then the client's packs, as the game
does), so packed clients and bricks added to a client work. It falls
back to loose files under res/ as before.

In the LU Toolbox palette (the default), a colour LU Toolbox doesn't
know but the client's Materials.xml has, such as one added to the brick
database, is drawn in its Materials.xml colour instead of black. Ids
neither knows stay LU Toolbox's black.

The dashboard's 3D viewers get the brick colours from the client's
Materials.xml (/api/bricks/materials.js) instead of a hardcoded copy, so
added colours show there too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:13 -05:00
Aaron Kimbrell
5bb05775ee chore: remove the brickdb notes and repack tool
They belong with the local client patching work, not the server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:13 -05:00
Aaron Kimbrell
888168ff55 docs: the UGC icon pose, the assembled mesh, the UGC page's assemblies, search, editor and settings
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:12 -05:00
Aaron Kimbrell
ae03a91fa5 docs: how the client reads brickdb.zip, and a tool to rebuild it
The client mounts brickdb.zip with LDD's own zip reader. It is lenient about
compression, order and extra entries, but loses the whole brick database
when the files sit under a wrapping folder or "./", use backslashes, carry
ZIP64 end records, or set the data descriptor flag with sizes still in the
local header. tools/brickdb/repack.py rebuilds the shipped layout (a
round trip gives the identical file), adds or replaces entries from an
overlay folder, and checks a zip against the reader's rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:11 -05:00
Aaron Kimbrell
8ab7e496b0 feat(bbb): answer FetchModelMetadataRequest for brick built models
The client asks for a model's metadata (name, owner, behaviors and its blueprint's
bricks and box) when it shows a brick built model item's tooltip, a model on a
property or an exhibit, and shows BBB_LOADING_BLUEPRINT until it gets it. The
world server never answered. It now does as live did: UG data for the model
(found among the player's items by subkey, else among placed models) and, for a
brick built model, the blueprint data from its ugc row and LXFML.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:10 -05:00
Aaron Kimbrell
962797d6a2 docs: UGC server page with both the dashboard links and the client findings
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:10 -05:00
Aaron Kimbrell
5de59b99ef feat(ugc): models with no bricks are "empty", not failed
A model with no bricks has nothing to make: it gets its own state
(is_optimized = 3), isn't counted as a failure or retried, shows as Empty
on the UGC page (with its own filter and count), in the status and in
Prometheus, and its downloads answer 404 like HKX. State names come from
the enum (magic_enum). Migrations dlu/mysql/87 and dlu/sqlite/70 move the
rows that failed only because they had no bricks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:10 -05:00
Aaron Kimbrell
76cbbcc4ea feat(ugc): draw player models' icons from their generated NIF
The icon was rendered from a second mesh built only for it (the icon
renderer's color corrections, no variation, occlusion worked out again). It
is now drawn from the .nif just made, read back with NifFile at LOD 0, so it
shows exactly what the game shows: the color variation, the removed faces and
the lighting baked into the vertex colors (so it adds no occlusion of its
own). icon_correct_colors and icon_color_variation are gone; the camera and
light settings stay. Cars and rockets are drawn as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:09 -05:00
Aaron Kimbrell
27955d8cc6 docs: UGC search and creations on property and character pages
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:08 -05:00
Aaron Kimbrell
8ddd55463a docs: downloading log bundles from the dashboard and its API
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:08 -05:00
Aaron Kimbrell
05d6f55e25 docs: UGC server parity with LU Toolbox, CPU and memory limits, viewer
A step by step table of LU Toolbox's pipeline against the UGC server's, the
new settings and their defaults, the measured effect of max_cpu_percent and
max_memory_mb, and the dashboard's gallery, viewer and internal address.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:07 -05:00
Aaron Kimbrell
0de9decc7c fix(ugc): name crash dumps like the other servers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:06 -05:00
Aaron Kimbrell
5828fe99c7 docs: describe the UGC server on the dashboard
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:06 -05:00
Aaron Kimbrell
f7eee4a395 docs: track issues 764, 960 and 1129
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:05 -05:00
Aaron Kimbrell
7fb1e404f0 fix(wire): write SetStatusImmunity flags in the client's order
WIRE FIX. The 1.10.64 client writes and reads the immunity flags in
alphabetical order after the u32 state (GameMessage::SetStatusImmunity::
Serialize @ 0x00d8f140; the field offsets are named by the Flash export
at 0x00d8f410): BasicAttack, DOT, ImaginationGain, ImaginationLoss,
Interrupt, Knockback, PullToPoint, QuickbuildInterrupt, Speed. DLU wrote
them in declaration order, so e.g. a knockback immunity reached the
client as an imagination-gain immunity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:04 -05:00
Aaron Kimbrell
e3a75a689e fix(wire): send NotifyNotEnoughInvSpace with its own message ID
WIRE FIX. DLU sent NotifyNotEnoughInvSpace with the ID of
VehicleNotifyFinishedRace (1396). The 1.10.64 client registers it as
NOTIFY_NOT_ENOUGH_INV_SPACE (1516, 0x00545c90) and reads freeSlotsNeeded
followed by the optional inventoryType (0x00d8b850), which is what the
payload already was. Only the message ID changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:04 -05:00
Aaron Kimbrell
3dd4ebf853 docs: API keys, their scopes, limits and audit
Also sends key creation, rotation and revocation to security webhooks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:03 -05:00
Aaron Kimbrell
d457df0c5f docs: traffic diagnostics
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:02 -05:00
Aaron Kimbrell
623ab58afb docs: track the pet issues
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:01 -05:00
Aaron Kimbrell
6c414cec48 feat(dashboard): check uploaded character XML before storing it
The XML upload is the one place hand-written XML reaches the game, whose
load path trusts the XML because the server writes it itself. Instead of
making the game skip bad data at load, the upload is checked against
what the load path assumes and refused (400, with the problems) when the
game couldn't load it: required elements, attributes that must parse
(flags read with std::stoul/stoull), required item and mission fields,
known inventory types, mission states and character versions, items and
missions that exist in the CDClient, unique item IDs and slots, and the
acct attribute matching the owner.

Suspicious but loadable content is returned as warnings that need
confirm=true (409 otherwise): contraband (same matching as the world,
now shared in ContrabandRules.h), stacks above the stack size, coins,
level or u-score out of reach, a GM level above the account's.
Contraband marked flag-and-remove is removed only if the uploader asks;
once stored, findings are flagged (CONTRABAND) and audited. The XML
editor shows the findings and offers "Save anyway". Related: issue 1332.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:30:59 -05:00
Aaron Kimbrell
0b88d5b5c5 docs: track the upstream issues this branch works on
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:30:59 -05:00
Aaron Kimbrell
68a810ea7b docs: the property building and brick by brick workflow
Messages in order with directions, what the server does at each step, the
inventories and how model ids change, quick save and recovery, undo, and
the client functions they were mapped from (1.10.64).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:30:59 -05:00