A placed model's client (1.10.64, UGCUSE3DSERVICES=7:0) always loads its
blueprint's NIF and HKX (its BlueprintComponent sets renderUserGen and
physicsUserGen itself) and its LXFML, asks the world for each file's
manifest first and waits for the answer with no timeout.
With ugc_manifest=1 and the new ugc_manifest_models=1 (default 0) the world:
- leaves the models whose mesh the UGC server made out of the LXFML it
sends when a property loads,
- answers their NIF with the UGC server's checksum, their LXFML with the
stored LXFML's (worked out once and kept) and their HKX as not known,
- sends a model that isn't made its LXFML (once for the three requests),
so the client builds it itself and no model is left waiting.
When the UGC server writes a model's mesh with a new checksum it sends
UGC_MODELS_MADE (a new master message, appended) to the master, which
passes it to every world; a world with that model placed sends its
players the new NIF checksum and NotifyClientUGCModelReady (game message
909, the blueprint id), so clients switch to the served mesh.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The dashboard shows worlds master has launched but that aren't connected
yet (Starting) and those shutting down, on the main page's world list
and in /api/worlds (state: starting|stopping), without a shutdown
button. Master's server list now carries each world's state (appended
after the UGC fields, one byte per world) and master pushes the list to
the dashboard whenever a world is launched, becomes ready, is told to
shut down or goes away, instead of the dashboard only seeing it on its
30 second poll. Starting worlds are kept apart from the running ones,
so counts, events and shutdown requests still only see running worlds.
prestart_worlds (masterconfig.ini, zone ids) lists the worlds master
starts when prestart_servers is on, instead of the hardcoded character
select (0) and Venture Explorer (1000), which stay the default when it
is missing or empty. It is on the Settings page as a zone list (restart
only), shown when prestart_servers is on.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
UgcIconPose holds the icon camera, model rotation (yaw/pitch/roll, YXZ) and
the crop to the projected bounds; RenderIcon uses it. The parameter list gains
the model's turn (defaults 0, so icons stay the same). POST /admin/assembly
returns a module combination's assembled .nif (turned by the build type's
AdditionalModelRotation), made on a worker and kept in a small cache.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The editor on the UGC page works for player models as well as cars and
rockets: its sliders come from /api/ugc/icon/params (UgcIconParams), it
shows the item's kind (player models, or the build type named from the
client's data), previews with the UGC server, and saves the kind's preset or
the item's own values, resets them and draws a kind's icons again.
The light settings whose defaults changed have new names (icon_world_light,
icon_sun_light, icon_shadow_strength), so the darker values in existing
ugcconfig.ini files no longer apply. Request ids are read safely (a missing
id crashed the dashboard).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brighter icons: a world light, a fill from the camera, a highlight, exposure
and contrast; with the defaults the icons' mean luminance matches the game's
own model icons (118 against 120 on a scratch set). Every icon parameter is
listed once (UgcIconParams: key, setting, range, default); the settings,
the dashboard's settings entries and the icon editor come from that list.
Presets per kind (player models, each car or rocket build type from
ModularBuildComponent) and overrides per model or module combination are in
ugc_icon_settings.
Saved models wait ugc_debounce_seconds (sharedconfig) after the owner's last
save before they're made (ugc.process_after); a client asking for one, the
owner leaving the world or a reset ends the wait.
Cars and rockets: one icon per combination of modules (sorted LOTs), shared
by every build of it; builds of a combination made already are marked made
right away, the client's per-blueprint downloads serve the shared files.
The dashboard can delete one item's files, purge by filter or all, preview
icons with any values on the UGC server (/admin routes, master password),
save presets and overrides, and draw a kind's icons again (icons only).
Migrations dlu/mysql/86 and dlu/sqlite/69. Not done yet: the dashboard
editor's lighting controls in the page script (routes are there), docs for
it, the empty-model state, /ugc?item= links, the shared fetch helper; the
storage size and property loading bugs are next.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
The /ugc page no longer needs the browser to reach the UGC server: the
dashboard fetches its status (/api/ugc/server/status), the files it made
(/api/ugc/files/<kind>/<id>/<file>) and its NIFs converted for the 3D view
(/api/ugc/mesh/<id>, NifFile like the scenery) from ugc_internal_url
(default http://127.0.0.1:2008) with libcurl on the worker threads, keeping
small answers briefly. ugc_public_url is only an "open on the UGC server"
link now.
The page gets an icon gallery beside the list, filtered by kind, state and a
search by id or owner (GetUgcProcessList/GetModularBuildProcessList take a
search), and a viewer: the generated NIF in 3D at any LOD, now or before it
was made again, with wireframe, vertex color and baked lighting switches, the
LXFML beside it, the icon now and before, and the stats with triangles before
and after hidden faces were removed. The status box shows CPU, memory, the
jobs' memory estimate with their limits, and throttling. The settings page
lists the UGC server's new settings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LU Toolbox's Combine Transparent is off by default, so each transparent brick
is its own object and shape (the client can sort them). combine_transparent=1
joins them as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Parity with LU Toolbox's Process Model, Bake Lighting and icon renderer, with
its defaults as the settings' defaults:
- Colors from its LU palette (UgcPalette: LU colors, LDD colors mapped to the
nearest LU one, unknown ones black), transparent bricks at 58.82% opacity, a
brick transparent only when all of its materials are.
- Color variation: each brick's material gets its HSV value shifted in a 2.224
gamma by up to 5% (times the color's own amount), from a random number of
the model, brick and material, so reprocessing gives the same colors in
every LOD. Icons get none, and the icon renderer's color corrections.
- LODs 0 and 2 with its distance logic, written as NiLODNode/NiRangeLODData
like its exports and the game's own brick models, shapes divided at 65535
vertices along the longest side like divide_mesh.
- Ambient occlusion like its AO-only bake: 64 rays per vertex, distance 5,
after hidden surface removal, transparent bricks neither baked nor
occluding, glow colors added.
- Icons from its icon scene: 50 mm lens at 53.4/19.5 degrees, sun of 2.5 at
21/50.3 degrees with soft shadows, grey world light with occlusion; LOD 0's
hidden surface removal and occlusion are reused for them.
- Optional ground plane for hidden surface removal; stats.json per model and
the previous version's previews kept for comparing.
Budgets, applied live on config reload: max_cpu_percent (workers account
their thread CPU time and sleep to stay under it, long renders included),
worker_nice, max_memory_mb (jobs are estimated from their brick count and
wait until they fit), max_model_bricks and pause_hours. /status and the
traffic report show CPU, memory and throttling.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mapped from the 1.10.64 client and live captures (docs/BuildWorkflow.md).
Model placement (PropertyManagementComponent):
- A brick built model placed from the inventory spawned at the world origin
with no rotation and without PlaceModelResponse/PreCreate, and was saved
to properties_contents with ugc_id 0; it is now placed where the client
put it, keeps its UGID and blueprint and is saved with them.
- Picking up, putting away and taking apart a brick built model gave it to
MODELS_IN_BBB and then deleted it; every way off the property now puts it
in MODELS (carried when picked up), as live, with its blueprint config.
Taking a premade model apart no longer deletes it either.
- Placing and removing a model saves the property at once, so a crash or a
disconnect before PropertyEditorEnd does not lose it.
- DoneArrangingWithItem only answers when something new is picked (not when
leaving), with the subject as build area; SetBuildModeConfirmed's
warnVisitors matches live.
Brick by brick (BrickByBrick):
- BBBLoadItemRequest moves the model to MODELS_IN_BBB keeping its id and
fails cleanly when the player has no such model.
- MoveInventoryBatch moves bricks between BRICKS and BRICKS_IN_BBB (it was
not handled, so the client and server disagreed until a relog).
- BBBSaveRequest uses up the opened models, places the new ones through the
property, returns the bricks (or uses them with bbb_consume_bricks=1),
clears the autosave and sends RequeryPropertyModels. Every save makes new
ugc rows (is_optimized 0, so the UGC server processes them).
- Quick save: SetBBBAutosave is stored per character (bbb_autosave).
- UnUseBBBModel puts a model back on the property where it was when it came
from there, otherwise back in MODELS.
- Leaving brick mode without a save, a disconnect or a crash: the autosave
is rebuilt into models (RebuildBBBAutosaveMsg) or the opened models go
back to MODELS. MODELS_IN_BBB is saved with the character now and loads
into MODELS, BRICKS_IN_BBB into BRICKS.
Fixes#1632Fixes#159Fixes#1565
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Counts, a paged list and failures of what the UGC server made of players'
models and modular builds, making one, the failed ones or everything again
(new ugc_manage permission), the UGC server's live status and icons from
ugc_public_url, and a 3D view of a model's LXFML. The UGC settings are in the
settings catalog.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A new server (dUgcServer, started by master with enable_ugc_server=1) that
takes unprocessed ugc and ugc_modular_build rows from the database and makes
what the client downloads with UGCUSE3DSERVICES: an optimized NIF (hidden
faces removed, ambient occlusion baked into vertex colors) and a 128px DDS
icon for player models, rendered by a software rasterizer from the client's
LDD brick primitives, and icons for cars and rockets assembled from their
modules per ModularBuildComponent/ModuleComponent. It serves them, with the
models' LXFML, over HTTP in the client's UGCC<dc>/3DOPTIMIZED and
IMAGE128DDS layout with .gz and .checksum files, and keeps its folder under
a size cap.
Processing state lives in ugc.is_optimized plus new processed_at,
process_attempts and process_error columns (and the same on
ugc_modular_build). ServiceType::UGC is appended. NifFile moves to dCommon
and records named node transforms for the modules' attach points.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bind_ip in sharedconfig.ini picks the local IPv4 address every server's
RakNet sockets listen on (auth, chat, master, world, the dashboard's
connection to master), separate from external_ip, the address players
are sent. Empty or 0.0.0.0 keeps listening on all interfaces; localhost
means 127.0.0.1. Anything that isn't an IPv4 address stops the server
with an error, and each server logs what it bound to.
Fixes#225
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>
* fix: security vulnerabilities
Tested that all functions related to the touched files work
will test sqlite on a CI build
* fix failing test
* ai feedback
* add buffer size checking
* use c_str
* dont log session key
* Try this for a mac definition
* be quiet apple
Tested that having the config option set to 1 and having an empty property auto-rejected it. Tested that having a model on the property or having the new config option set to 0 auto approved the property (as per live)
* replace linux calls
* windows api
* log child PIDs in parent process
* fix typo for windows
* functions now return the process ID
* use wchar_t for windows APIs
* Update Start.cpp
Try to fix MacOS issues
* Conditionally include unistd.h
* remove sudo config option and add error message for linux
* fix windows .exe extension
* REALLY fix windows
* try replacing c_str() with data()
* really REALLY fix Windows
* Update dNet/dServer.cpp
Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>
* Update dServer.cpp
* simplify leaderboard code, fully abstract database
* update exception catching
* update exception catching and sql references, remove ugc from gamemessages
fix deleting model
remove unrelated changes
Update GameMessages.cpp
* remove ugc from gamemessages
* Update GameMessages.cpp
* Update Leaderboard.cpp
* bug fixes
* fix racing leaderboard
* remove extra stuff
* update
* add sqlite
* use a default for optimizations
* update sqlite
* Fix limits on update and delete
* fix bugs
* use definition to switch between databases
* add switch for different backends
* fix include guard and includes
* always build both
* add mysql if block
* Update Database.cpp
* add new options and add check to prevent overriding mysql
* correct config names
* Update README.md
* Update README.md
* merge to 1 sql file for sqlite database
* move to sqlite folder
* add back mysql migrations
* Update README.md
* add migration to correct the folder name or mysql
* yes aron
* updates
* Update CMakeLists.txt
* dont use paths at all, add where check to only update if folder name still exist
check also doesnt check for slashes and assumes one will be there since it will be.
* default dont auto create account
for releases we can change this flag
* default 0
* add times played query
* fix leaderboard not incrementing on a not better score
* add env vars with defaults for docker
* use an "enum"
* default to mariadb
* Update .env.example
adds an announcement sent to the system address which had the mismatched FDB to let the developer know they have a mis-matched one.
Tested that if a civilian tries to login without a gm level > developer, they are kicked.
Tested that if a GM is found to have a mismatched FDB, they are let in but have an announcement sent to them.
Use auth packets for msg
added comment as to why
ff
remove default
add comment
Remove broadcast
* greatly simplify docker
* back to gcc since I can't the libs to load properly
* fix typo
add set -e to entrypoint
better copy of entrypoint.sh and use proper entrypoint
* use debian instead of gcc for runtime
comment and organize it a bit
drop gcc to 12 since we are using debian 12 as well
* explicitly include mariadb libs
* Make the server not crash in the case we are using only env-vars
make the dockerfile have configs in the expected location incase of bypassing entrypoint.sh
* remove unneede var from example, since it's in the container now
* coments to dockerfile
* Revert master server changes
* Resolve conflicting port options between chat, master, and world
move chat_server_port to shared since it's used by world and chat
* Don't error if file does not exists when updating a config option
move update before and use bin dir var
* feat: reward codes
this is for giving rewards across characters as the did in live.
Tested that the default config works
Tested that all claim codes work
Tested that saving and loading claim codes work
Tested that mail sends correctly
* newlines
* include array
* delete cascade
* newline
* address feedback
* feat: add configurable feature and versions
to allow for easily swithing it out to enable features in the client for funsies
tested that this doesn't break anything and added test
* cleanup
* fix: properly check friend list limits
added a config for friend list limit for the brave that want to mod the client to sanely go over 50
moved the best friend limit config to chatconfig.ini where it should be
cleanup loading these configs options a bit
Tested that the BFF limit works and that the new friend limit works as well
* fix typo
* fix member variable naming
* re-add x and z checking for height
Now that we have better navmeshes, this will result in much better results and as such we can re-enable this check.
* Always run navmesh extraction
waste of time most of the time, but no other way to force update to the meshes easily.
* Navmeshes Version 2
- Add all missing zones
- Drastically improve several zones and their navmeshes, cleaning them up, making them more accurate and generally using more features of detour/recast.
* Update CMakeLists.txt
* update meshes
* Navmesh: Add pet cove navmesh
* Navmesh: Fix navmesh for fv