Commit Graph

2536 Commits

Author SHA1 Message Date
Aaron Kimbrell
b7f8e2ba5d doc: README covers item source keys, pet walls and carver-only objects
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 07:50:05 -05:00
Aaron Kimbrell
1d2269257d Merge exp/loot-blocker-followups: item source keys, quickbuild cost source, pet blockers, carver_only walls 2026-09-30 07:49:50 -05:00
Aaron Kimbrell
f6659d35f9 test(ai): pets at pet blockers, carver_only walls and hedge sizes
A pet chasing across a "PR - Pet Blocker" stops in front of it; a
carver_only navmesh carver added without an object stops an enemy and goes
away with the physics world; carver_only alone blocks nothing; a Robot City
hedge's blocker has the size and offset of its collision shape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 07:49:19 -05:00
Aaron Kimbrell
da9ae3b3c4 feat(zone): don't spawn carver_only objects, keep them as walls
The client never loads a level object whose config has carver_only set (its
resource manager skips the load; LWOBasePhysComponent::LoadConfigData
0x00c495c9 reads the flag next to navmesh_carver), and live never sent one:
none of the 331 carver_only placements (mostly Crux Prime's trigger boxes)
shows up among the live constructions, where their zones' other objects do.
DLU spawned them as objects.

They are skipped now. The ones that carve the navmesh (53, in six zones,
among them the Avant Gardens Sentinel camp walls) still stop the server's movers: their shape
goes into the world's movement blockers without an object, owned by the
physics world (dpWorld::AddOwnedMovementBlocker) and freed when it shuts
down. None of them has a script, trigger or group.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 07:49:13 -05:00
Aaron Kimbrell
175d2930b7 feat(physics): real sizes for the navmesh carvers the server didn't know
Walls whose asset shape the server doesn't know are left out of the movement
blockers (a stand in cube would be a guess), which left out every navmesh
carver in Robot City (hedges, hedge corners, potted bushes, greebles, robot
statues) and the Ninjago Monastery benches. Their sizes now come from the
client's own collision shapes (res/physics): the bounds of all of a shape's
parts, with the offset of the box from the object's position. The hedge
corner is an L, so its box also covers the inside of the corner.

The same bounds match two shapes the server already had (misc_phys_10x1x5:
10 x 5 x 1; Trigger_Rectangle_Box: 8 x 8 x 4).

CreatePhysicsEntity's shape lookup becomes CreateAssetShape, which needs no
component, for walls without an object.

Still unknown: the Ninjago Monastery cave's primitive model carver (a 77.6
cube whose origin, centre or base, isn't known).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 07:48:56 -05:00
Aaron Kimbrell
53c03515a7 feat(ai): pets stop at the walls their group can't cross
Pets are walked by the server's MovementAI like enemies, but only enemies'
paths were cut at movement blockers, so pets walked through the Nimbus Station
pet ranch's "PR - Pet Blocker" walls. Their collision group (3) is the one
the pet blocker's group (18) touches in the client's collision filter, so a
pet's path now stops at them (and at navmesh carvers), whether wandering or
following its owner; a pet left behind still warps to its owner.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 07:46:20 -05:00
Aaron Kimbrell
e77535984d test(loot): item source keys and the quickbuild item cost's source
Covers the key names and name value types, a pickup from an object, from the
player and from an object that is gone, metrics after an item's config (and
not kept on the item), a removal's loot source, and a quickbuild taking its
item cost with itself as the source.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 07:46:13 -05:00
Aaron Kimbrell
a5126536a4 fix(quickbuild): the item cost is taken with the quickbuild as its source
Live's RemoveItemFromInventory for a quickbuild's item cost (the FV Stone
Warrior pedestal's 5 Maelstrom Infected Bricks, taken when the build starts)
had the loot source Quickbuild and the quickbuild's object ID as the loot
source object. DLU sent loot source None with no source.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 07:46:13 -05:00
Aaron Kimbrell
ed2d329781 feat(loot): rewards, purchases, mail and trades say where items came from
The other item sources live marked in AddItemToInventoryClientSync's extra
info, with the keys and values live sent:
- mission and achievement rewards: _Metric_Mission_ID_Int and source LOT 1,
  the player (225 of 225 live rewards)
- activity rewards: _Metric_Activity_ID_Int and the activity object's LOT
- vendor purchases: the vendor's LOT and _Metric_Currency_Delta_Int, the coins
  paid as a negative number (left out when the item costs no coins)
- mail attachments: _Metric_Mail_ID_Int64
- traded items: _Metric_Transaction_ID_Int64, the trade's ID

Loot::GiveLoot gains overloads that pass them on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 07:46:05 -05:00
Aaron Kimbrell
898ae024f0 feat(loot): a picked up item says which object it dropped from
Live's AddItemToInventoryClientSync for a picked up drop had
_Metric_Souce_LOT_Int in its extra info on all 2,344 live pickups: the LOT
of the DropClientLoot's source object, 1 when a player was the source
(activity rewards and chests, which drop from the player). DLU sent none.

The drop remembers its source object's LOT when it is registered for the
player, and the pickup sends it. A source object already gone when it drops sends
no key. Package contents keep sending none, as live's did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 07:45:59 -05:00
Aaron Kimbrell
a1ee18fce7 feat(inventory): items can carry where they came from to the client
Live servers put _Metric_ keys in AddItemToInventoryClientSync's extra info,
after the item's own config, saying where the items came from: the source
object's LOT (_Metric_Souce_LOT_Int, misspelt as live had it), the mission,
activity, coins paid, mail or trade. LootMetrics holds them and writes them
with the key names and name value types live used (the mail ID as type 8,
the trade ID as type 9). AddItem, ReceiveItem (its options), the new item
constructor and Item::SetCount pass them through to the message; the item
does not keep them.

RemoveItem and Item::SetCount can also say what took items away
(ItemRemovalSource), filling RemoveItemFromInventory's loot source and
source object instead of none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 07:45:50 -05:00
Aaron Kimbrell
f309cf0528 fix(dashboard): World 3D plays a packet capture at 1x
The replay speed saved for recorded positions (60x by default) is for scrubbing through hours of movement. A capture is minutes long and played too fast at that speed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 07:41:13 -05:00
Aaron Kimbrell
3018312f29 test(capture): decoders cover the matchmaking chat packets; position fields are under update
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 06:41:52 -05:00
Aaron Kimbrell
4d7bea6f06 test(capture): decoder coverage, replica read-back and generator check; docs
Every LU MessageType has a struct or is listed as never used by this server; every game message struct reads;
samples of each family and of sent game messages read back; replica constructions, updates and destructions written
by the server's own serializers read back. Generator finds constructors defined in the .cpp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 06:32:46 -05:00
Aaron Kimbrell
d1ea2992e4 feat(dashboard): capture viewer decodes game messages and replica packets
Links the game for its message structs, reads the components of every LOT at startup, and decodes a capture's
replica packets once, in timeline order, on a worker thread.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 06:32:35 -05:00
Aaron Kimbrell
5e40166cbd feat(capture): read replica constructions, serializations and destructions
ReplicaDecoder mirrors Entity::WriteBaseReplicaData and each component's Serialize, keeps what each network ID is
per world instance, and shows the rest as bits when no layout fits. CaptureTool links the game: game messages are
decoded (and compared in replays), and decode --cdserver reads replica packets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 06:32:35 -05:00
Aaron Kimbrell
8df9084a72 feat(capture): decode every game message both ways by its struct
GameMessageDecoder reads every NetGameMsg struct (generated member lists in GameMessageFields.inc) instead of 10
hand-written ones; DisplayTooltip gets the Deserialize it lacked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 06:32:35 -05:00
Aaron Kimbrell
19aa691ff7 feat(capture): decode every LU packet with its own struct
The capture viewer's LU packet fields come from each struct's Deserialize and a member list generated from the
struct definitions (tools/gen_game_message_fields.py -> dNet/PacketFields.inc), replacing the hand-written list of
25. Secret members are never listed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 06:32:35 -05:00
Aaron Kimbrell
951edfdde2 fix(master): a server list's outdated flags are read all or none
A list cut short inside the flags was read as if complete; an older master's list, which has none, still
reads. The test checks every cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 06:32:35 -05:00
Aaron Kimbrell
ebe77ee45c test(master): fix server list flag test compile
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 04:41:48 -05:00
Aaron Kimbrell
a919a57e5e test(master): server list outdated flags
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 04:35:45 -05:00
Aaron Kimbrell
5d3adfc683 docs: activity matchmaking across worlds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 04:29:59 -05:00
Aaron Kimbrell
289a1acfdf feat(world): activity lobbies join, ready and leave through the chat server
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 04:29:59 -05:00
Aaron Kimbrell
2ae086d933 feat(chat): keep activity lobbies of every world and start their instances through master
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 04:29:59 -05:00
Aaron Kimbrell
4a7cac4f35 feat(chat): activity lobby state machine for matchmaking across worlds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 04:29:59 -05:00
Aaron Kimbrell
e11493008d feat(net): MATCH_REQUEST and MATCH_TRANSFER chat packets and the chat server's MatchUpdate
MATCH_TRANSFER is appended after GUILD_DISBAND (71); the chat ids from
CREATE_TEAM on are pinned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 04:29:59 -05:00
Aaron Kimbrell
9a4282e6b3 docs: properties stay out of live updates and world reloads
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 04:29:54 -05:00
Aaron Kimbrell
4c93c8fea7 feat(dashboard): draining (old version) badge; properties update when empty
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 04:29:54 -05:00
Aaron Kimbrell
d71e44f3e1 feat(world-reload): keep properties until empty
Busy property instances on changed files are kept (KEEP_UNTIL_EMPTY) instead
of saved, frozen and moved. Every instance acted on is marked outdated; the
files status carries the flag (bit 4).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 04:29:54 -05:00
Aaron Kimbrell
891f21daa9 feat(live-update): never move properties; mark old instances outdated
Property instances are left out of the replace plan. Once the database is
up to date every instance running at the start is marked outdated, and a
zone that already got a new instance is not started again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 04:29:54 -05:00
Aaron Kimbrell
8f891229e6 feat(master): outdated instances take nobody new and stop once empty
Instances on an old binary or old zone files are marked outdated: routing,
private passwords and merges skip them. Outdated properties remind their
players every 10 minutes that an update is waiting (ANNOUNCE) and stop once
empty. A new instance of the same property waits for the old one to be gone
before its world server starts, so two worlds never save one property.
The server list carries the flag after the endpoints (read when present).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 04:29:54 -05:00
Aaron Kimbrell
c6831ac80e fix(dashboard): light the UGC model view like the game
Metal was drawn with metalness 1 in the room environment at half strength with one
sun, so metal groups came out nearly black. The game's metal keeps the vertex
color (lit, plus a reflection tinted by it), so metal is now part metal with a
stronger reflection, the environment is brighter and a sky over ground fill
lights the sides away from the sun.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 03:50:37 -05:00
Aaron Kimbrell
19b6443fb4 fix(ugc): metal look only from the client's material types
LU Toolbox's metallic table also has colors the client's Materials.xml types
shinyPlastic, such as 131, the grey of many baseplates, so whole baseplates went
into S88_Metal_Model. Metal now comes from the Materials.xml types (shinySteel)
and the settings' colors only; the table still gives colors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 03:50:37 -05:00
Aaron Kimbrell
5265da7b2e docs: following a player across worlds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 03:21:54 -05:00
Aaron Kimbrell
826ba058ff feat(dashboard): world change markers on the packet capture timeline
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 03:21:53 -05:00
Aaron Kimbrell
9bbdc45f4f feat(world3d): follow a player across worlds, live and in capture playback
Live: when the position feed reports the followed player only in another world,
load its scene, keep following and toast where they went. Capture playback: load
every zone's movement, switch the scene at the followed character's world change
(forward and when seeking back), follow a lone captured character from the start,
and mark world changes on the replay slider.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 03:21:53 -05:00
Aaron Kimbrell
12c5b34a5d feat(world3d): scene switch and world marker rules for following across worlds
followedMove (live feed), worldAt/captureSwitch (capture playback), worldMarkers and
markersHtml, with node tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 03:21:53 -05:00
Aaron Kimbrell
601a27343f feat(dashboard): capture worlds route, every zone's movement in positions
/api/inspector/sessions/:id/worlds lists the captured characters' moves between
world servers with the zone's name from the locale; /positions also returns them,
takes ?zone=all and names each track's character and zone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 03:21:53 -05:00
Aaron Kimbrell
d8900c5d68 feat(net): CaptureTools::Worlds lists each captured character's world visits
One entry each time the packets a character's client sends carry another zone or
instance, in time order, for following them across world servers in playback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 03:21:53 -05:00
Aaron Kimbrell
5658fb036f docs: world hot reload
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:51:21 -05:00
Aaron Kimbrell
139df9ab9a feat(dashboard): world files card with changed-on-disk badges and Reload
On the Instances page, behind world_reload; zone names from GameText.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:51:21 -05:00
Aaron Kimbrell
e054d1f4e4 feat(gm): /reloadworld with the world_reload permission (GM 9)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:51:21 -05:00
Aaron Kimbrell
16545d573e feat(master): watch world zone files and replace instances that loaded old ones
Master hashes each reported file on a worker, polls size and mtime every
world_watch_seconds (a change must hold still for one poll), and replaces
stale instances with the instance migration (Mythran shift, or seamless
with world_reload_seamless=1); empty ones are stopped. Also on WORLD_RELOAD.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:51:21 -05:00
Aaron Kimbrell
ab395a1af9 feat(net): WORLD_FILES, WORLD_RELOAD and WORLD_FILES_STATUS master messages
Appended at the end of MessageType::Master (47-49); the pin test is
updated. A world sends its zone file list to master once it is ready.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:51:21 -05:00
Aaron Kimbrell
e709855b7d feat(world): record the zone files a world loads, with sizes and hashes
ZoneFileLog keeps the .luz, .lvl, .lutriggers, terrain .raw and navmesh a
world read while loading its zone: absolute path of the loose file (or
the name in the pack), size and an FNV-1a hash of the bytes read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:51:21 -05:00
Aaron Kimbrell
b629766182 fix(mail): new mail notices in live's form
Live filled a NewMail notice with the mail it was about: the mail ID, the
player, the attachment (LOT -1 without one) and a count of 1, and at load sent
one notice per unread mail. DLU sent one notice with every field 0 and the
unread total as the count. The answer to NotificationRequest names the player
and no mail, with LOT -1 and the unread count, as live's did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:51:21 -05:00
Aaron Kimbrell
3f0e9bc336 fix(dashboard): the Network diagram keeps its width on phones and scrolls sideways
Six columns squeezed into a phone's width drew the boxes over each other; the diagram now keeps at least
1100 px and its card scrolls, with the lists and tooltips following the scroll.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:51:21 -05:00
Aaron Kimbrell
230e5b4841 docs(dashboard): Network ports and servers on several machines
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:39:24 -05:00
Aaron Kimbrell
b0819df5b6 feat(dashboard): Network summary has each server's port and machine
The dashboard keeps master's server list endpoints and joins them into the
Network summary: its listening port and its machine as a token, since the
summary goes to every open page. The connection list maps the tokens to
addresses for viewers with network_ips. The dashboard reports its web port.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:39:24 -05:00
Aaron Kimbrell
a93f5f810b feat(master): the server list names each server's port and machine
Master keeps the address and port auth, chat, the dashboard and the UGC
server report when they connect and sends them, with its own and every
world's, after the list's world states. A server's machine is the address
master sees its connection come from; loopback and master's external_ip are
master's machine. Servers can report another port than their RakNet one; the
UGC server reports its web port.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:39:24 -05:00