Commit Graph

67 Commits

Author SHA1 Message Date
Aaron Kimbrell
6f4fd4054a feat(entity): the object's interaction distance, preconditions and world state, as the client
LWOGameObject loads these itself: interactionDistance from its Objects row
(16 without one) and the level's interaction_distance over it,
CheckPrecondition and objectWorldState from the level config, before its
components load theirs. The quickbuild, the pet and the race instancer read
them from the object; the race instancer now uses the Objects row's
distance like the client does, instead of a fixed 16.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 08:44:53 -05:00
Aaron Kimbrell
0c215de446 fix(entity): send updatesWithParentPosition from the spawn behavior, as live
The parent info always said the object doesn't move with its parent. Live
sent true for objects a spawn behavior made with updatePositionWithParent
(all 70 Engineer Personal Fortress constructions in the captures, LOT 9479,
and the Summoner's Scratch, 9644); the client then moves them with the
player. Every other construction in the captures sent false, and none sent
an object world state, which stays unsent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 08:30:23 -05:00
Aaron Kimbrell
9aa06f349c fix(entity): message handlers run in the order they registered, as the client
Handlers sat in an unordered_multimap, whose order for one message is up to
the standard library: GCC ran them newest first, so the components loaded
last answered a RequestUse first, and Windows builds could differ. They are
now kept per message in registration order: the object's own handlers, then
its components' in load order (LWOGameObject::PassMessageToComponents).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 08:19:18 -05:00
Aaron Kimbrell
260e6cb1b1 refactor(entity): each component type has an allocator, as the client
DoObjectComponentLoad walks the client's load order and calls the type's
allocator from a table, like ObjectLoader2, instead of one 76-case switch.
Components with rules of their own have a static Allocator (the client's
LWOxComponent::Allocator); the rest share a registry allocator. The load
state moves to ObjectLoadState.h so the allocators can take it.

Construction bytes are identical for all 15,962 LOTs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 08:11:58 -05:00
Aaron Kimbrell
b81ffb2d28 refactor(entity): components load their config and save after all exist, as the client
LWOGameObject::MakeReadyForSerialization runs each component's
LoadConfigData and then a character's LoadFromSaveData, in the order the
components were made, once DoObjectComponentLoad has made them all; then
their Startup. Entity::Initialize now does the same with a component list in
creation order (the client's componentList); the walk's own save calls
(mission, physics, destroyable, level, character, skill, ghost) and the
destroyable's call into the buff go. A model's behaviors load in its
LoadConfigData; controllable physics places a non-character at
construction, as the client's physics takes the spawn position. A component
added later still loads at once. Same bytes for every LOT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 17:47:30 -05:00
Aaron Kimbrell
1481bb7b32 feat(entity): movement AI for scripted objects and ones with a path, as the client
ApplyMovementAiIfNeeded gives an object with a script (its registry's or a
custom script) or an attached_path a movement AI component (id 0); 1843 LOTs
gain one. It follows its attached path only when that is a movement path (a
moving platform's path stays the platform's). Not on spawner objects, which
the client never loads. Nothing sent changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 17:07:47 -05:00
Aaron Kimbrell
477dd9f3e3 refactor(entity): load an object in the client's two steps
Entity::Initialize now runs DoObjectPreLoad (what the components will be:
the player's own components, markedAsPhantom, model behaviors, the
component whitelist) and DoObjectComponentLoad (the walk in the client's
order and what the client adds after it), as ObjectLoader2 does, with an
ObjectLoadState that answers the registry through the whitelist. Same
components and bytes for every LOT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 16:52:15 -05:00
Aaron Kimbrell
432f4f6ff9 fix(component): send a script component only when the client makes one
The client makes a script component for a registry script with a non-zero
id, or for a custom script in the config it is sent (LOT 176 never):
ApplyScriptComponentIfHasScript and LWOScriptComponent's allocator. A
character's script and a server-only custom_script_server stay on the
server and send nothing. The 5 LOTs whose registry script id is 0 (e.g. the
AG concert fan, LOT 3002: live sent no config and no script) lose the bit
the client never read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 16:38:56 -05:00
Aaron Kimbrell
7a0dba22a5 refactor(component): use is a RequestUse message handler
Components no longer have a virtual OnUse; each component that reacts to a
use registers a RequestUse handler, like the client's components. The entity
runs the INTERACT trigger and the script, then delivers a RequestUseEvent
(carrying the user) to the handlers. The mission choice of a multi-interact
use goes only to the mission offer, as before. Switches keep a direct
EnterIfResponding for touches and pets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 07:55:55 -05:00
Aaron Kimbrell
50bfa623ca refactor(component): the client's component lifecycle
Components get the client's per-component functions: LoadDataFromTemplate,
PrepareConfigData, LoadConfigData, LoadFromSaveData, Startup, Run,
OnEnterScope, OnLeaveScope, Preshutdown and Shutdown, called by the entity in
the client's order. Update is renamed Run, LoadFromXml LoadFromSaveData and
UpdateXml WriteSaveData. Nothing sent changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 07:45:16 -05:00
Aaron Kimbrell
d4e9423264 feat(servers): time the main loops' phases and the known heavy spots
Frames and phase scopes in the world, auth, chat and UGC loops (packets per type, entities, physics, ghosting, replica, spawners, log flush, saves, web requests by route). Scopes at LoadPlayer, CreateEntity, each component's construction, InventoryComponent::LoadXml, script timers and a world's zone load; game database queries in the query helpers; CDClient statements timed through sqlite3_trace_v2 as CDClient <table> (CppSQLite3DB gets a handle accessor). Task 96.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:26:17 -05:00
Aaron Kimbrell
b035f60e72 fix(replica): send each object's real age as time_since_created_on_server
Live sent the milliseconds since the object was created on the server in
every construction header (nonzero in 142,258 of 145,677 captured
constructions; the same object constructed again later carries a larger
value by the time elapsed; the local player's own construction on load is
0). DLU always wrote 0. The client stores it in the object's config
(LWOGameObject::time_since_created_on_server).

Entities now remember when they were created (steady clock) and write
their age.

Test: ReplicaConstructionTest.TimeSinceCreatedOnServerIsTheObjectsAge.

Check in game: zone in and walk around several worlds; objects, NPCs,
enemies and other players appear and animate as before (no objects
popping, stuck or misplaced animations on platforms/spinners).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 05:39:56 -05:00
Aaron Kimbrell
83b87744c1 feat: scene ghosting, as the client streams a zone's scenes
The client keeps the scene under the player loaded, the scenes the zone
file's transitions connect to it, and the global scene
(Zone::StreamScenesAroundPosition 0x0108a3f0, TerrainManager::GetSceneAtPos
0x01069010, the connected scenes at 0x01066500; transitions naming a
missing scene dropped as Zone::FixupInvalidTransitions 0x010842e0 does).

- ZoneScenes (dCommon): the terrain's scene map lookup and the scene graph,
  shared by the world server and the dashboard.
- Objects remember the scene they were placed in (spawners pass theirs on).
- ghosting_scenes=1 (world config, off by default): players get the objects
  of their loaded scenes instead of the ones within the ghosting distances;
  objects from no scene go by the scene under them. Zones without a scene
  map keep distance ghosting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:17 -05:00
Aaron Kimbrell
63e85d396d fix(pets): tamed pandas and crabs leave their spawn groups
The live server scripts (l_fv_panda_server.lua, l_crab_server.lua, in
the client's res/scripts) take a tamed pet out of the groups it was
spawned into: the panda leaves "pandas" and "panda<tamer>", the crab
"crab<tamer>". The panda spawner counts "pandas" (at most five) and
"panda<player>" (one per player), so tamed pandas used to keep counting
against both. Entity gets RemoveFromGroup for it.

The dig and object pet scripts keep their TODO: their live server
scripts are not shipped with the client.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:31:01 -05:00
Aaron Kimbrell
5d3c2e6f9a fix: filter physics volumes like the client's collision groups
Volumes on the server touched far more than in the client:

- An enemy's body in the physics world was a sphere the size of its aggro
  radius, so trigger and damage volumes caught enemies from far away
  (Cavalry Hill enemies taking damage on spawn). It is now the enemy's
  own radius and collision group from its physics component.
- Trigger volumes ignored their collision group and caught everything.
  dpEntity now filters with the client's collision filter
  (PeCollisionFilter, 1.10.64 0x00fb6940, group table from 0x00fcf9a0):
  POI walls ignore enemies, threat clearing walls ignore players, and
  so on. The aggro sensor keeps seeing only players.
- Rotated boxes were tested as the axis aligned box around them, which
  for a turned wall covers a big square (the AG survival boundary).
  Sphere and point tests now use the box's own axes.

Proximity monitors take an optional collision group like live's
SetProximityRadius; the AM shield generators use live's (10 finds
enemies, 1 finds players).

Fixes #1127
Refs #1971

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:30:54 -05:00
Aaron Kimbrell
350d35dab5 chore: foundations for struct based packets and game messages
First step of moving hand written bitstream code to struct based
messages (see docs/PacketArchitecture.md). No wire changes.

- GameMsg is now only a server-internal event (delivered to handlers
  registered with RegisterMsg); NetGameMsg is a wire message with
  Send(sysAddr) (UNASSIGNED broadcasts), SendToClient(sysAddr) (one
  client, never broadcasts), WritePacket, Serialize, Deserialize and
  Handle. Mixing them up is now a compile error. NetGameMsgEvent<T> /
  DeliverLocally carry a wire message to local handlers; loot drops,
  pickup, the object debugger, GM invisibility and model RequestUse
  use them. The GM invisibility message keeps its target, so its bytes
  are unchanged.
- Behaviour change: GameMessageHandler logs and drops messages whose
  Deserialize fails instead of handling them with default fields (the
  4 messages already registered: RequestUse, RequestServerObjectInfo,
  ShootingGalleryFire, PickupItem).
- LUBitStream (kept as on main) gets a virtual destructor (Mail deleted
  derived packets through the base) and WritePacket, also used by
  ChatPackets::SendRoutedMsg with identical bytes.
- BitStreamUtils::WriteOptional/ReadOptional for default-flag fields
  and WriteLengthPrefixed/ReadLengthPrefixed for length prefixed
  strings.
- Every message ID enumerator (MessageType::*, ServiceType, Mail's
  wire enums) is pinned with static_asserts, so renumbering or removing
  one fails to compile.
- Tests: dServerMock copies each sent packet (it kept a pointer to the
  caller's destroyed BitStream); PacketTestUtils.h compares packets bit
  for bit; helper tests use hand computed golden bytes and equality
  with the hand written patterns they replace; compile-time checks
  keep the wire/internal split in place.
- docs/PacketArchitecture.md: survey, target architecture,
  conventions, verification method and migration plan.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:30:35 -05:00
David Markowitz
0101933f5c chore: cleanup pointer management for LDF data (#1995)
* change network settings from vector to LwoNameValue

* move settings on Entity to managed memory

* Migrate more members

* chore: remove pointer leakage from raw ldf pointers

* feedback

* fix ci
2026-06-14 20:54:52 -07:00
David Markowitz
a156a8fcba fix: security vulnerabilities (#1980)
* 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
2026-06-07 20:59:11 -07:00
David Markowitz
4ef9f43266 feat: make gm registration simpler and safer (#1932)
* gm registration re-work

* fix errors

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* remove duplicate message

* Remove duplicate function

* add null check

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-05-19 13:42:56 -05:00
David Markowitz
2fb16420f3 fix: ape anchor not respawning (#1927)
* fix: ape anchor not respawning

* add return

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-15 13:30:02 -08:00
David Markowitz
74630b56c8 feat: Loot rework (#1909)
* feat: Loot rework

* Allow dupe powerup pickups

* change default team loot to shared
2025-10-15 00:53:39 -05:00
David Markowitz
f6c13d9ee6 Replace Quaternion with glm math (#1868) 2025-09-06 19:18:03 -07:00
David Markowitz
6b52cf67a0 feat: debug features and implement ObjectDebugger (#1846)
Move the -s and base features of inspect to the object debugger (this file is present in an unmodified, live client)
2025-07-19 05:11:32 -05:00
David Markowitz
5e9fe40bec feat: Add GetComponents(Mut) functions to Entity (#1842)
Allows for a really neat way of getting components using structured binding.  Tested that powerups still function

do it again because its neat
2025-07-01 07:26:05 -05:00
David Markowitz
0f0d0a6dee optimizations (#1829) 2025-06-24 22:13:48 -05:00
David Markowitz
2f315d9288 feat: Movement behaviors (#1815)
* Move in all directions is functional

* feat: add movement behaviors

the following behaviors will function
MoveRight
MoveLeft
FlyUp
FlyDown
MoveForward
MoveBackward

The behavior of the behaviors is once a move in an axis is active, that behavior must finish its movement before another one on that axis can do another movement on it.
2025-06-11 12:52:15 -07:00
David Markowitz
e4c2eecbc7 add msg handling (#1737) 2025-01-20 00:42:15 -06:00
David Markowitz
fb32534ae3 implement rest of equipment scripts (#1714) 2025-01-03 16:44:20 -06:00
David Markowitz
021db0ecd1 add child loading (#1706)
Tested that the NT combat challenge, am skullkin towers and qa wall in avant gardens all function as before.
2025-01-01 00:46:00 -06:00
David Markowitz
0b261e934f fix shooting gallery bugs (#1702) 2024-12-29 18:21:22 -06:00
David Markowitz
0f8c5b436d fix: implement enemy clear threat script (#1678)
* brother

* use some better logic
2024-12-15 23:44:57 -06:00
Wincent Holm
fedd039e00 Proposal for observers and deferred implementations (#1599) 2024-11-17 18:46:08 -06:00
David Markowitz
28ce8ac54d remove usage of xmldoc as a ptr (#1538)
resolves a memory leak in BrickDatabase, adds stability to character save doc.

Tested that saving manually via force-save, logout and /crash all saved my position and my removed banana as expected.
The doc was always deleted on character destruction and on any updates, so this is just a semantic change (and now we no longer have new'd tinyxml2::documents on the heap)
2024-04-08 15:13:49 -05:00
David Markowitz
fcb89b3c7a Remove multiple Script syntax (#1496) 2024-03-06 19:49:29 -06:00
Aaron Kimbrell
43707952d2 feat: move all ldf config to be in xml (#1482)
* feat: move all ldf config to be in xml
cleanup dev-tribute.xml
add comments to atm.xml
remove custom script tag in favor of ldfconfig for it

* replace sto* calls with tryParse's

* remove unesessary .has_value() calls and check for null_lot

* remove member variable naming that on on-member vars

* move max's vendor inventory to be configurable via vanity

* Consolidate triplecated vendor code

* don't write name if one is not given

* Updates to vanity xml's and demo for later docs

* rename vars
2024-02-28 17:16:47 -06:00
jadebenn
b261e63233 chore: Change entity and component logic to use bitstream references (#1468)
* chore: Change entity and component logic to use bitstream references

* merge
2024-02-27 01:25:44 -06:00
Aaron Kimbrell
192c8cf974 feat: refactor vanity (#1477)
* feat: refactor vanity
cleanup code to be generalized for objects
remove unused party feature
add fallback to data to text
Allow for better organizing data in multiple files
remove special case flag values in favor of config data
general cleanup and fixes

* newline at eof's
2024-02-25 16:59:10 -06:00
jadebenn
0c1ee0513d refactor: Change TryParse implementation (#1442)
* Changed how the TryParse function works (and also did some general cleanup along the way)

* Update noexcept attributes (verified these are correct)

* Add fp overload for MacOS functionality

* resolving some feedback

* Split out unrelated changes to CleanupRoundup branch

* Update in response to feedback

* the consequences of emo's member variable renaming request

* Revert "the consequences of emo's member variable renaming request"

This reverts commit bf318caeda.

* Fully revert renaming attempt

* Revert "the consequences of emo's member variable renaming request"

This reverts commit bf318caeda.

Fully revert renaming attempt

* Created ClientVersion.h and moved the client version defaults to it

* Fix partial parsing and MacOS floating point errors

* attempting fix to MacOS compiler error

* syntax pass (should be the last commit unless the CI fails)

* ah, wait, forgot to uncomment the preprocessor statements for MacOS. THIS should be the last commit pending CI

* Okay, one last thing I noticed: We were including C headers here. Now they're C++ headers. Pinky swear this is it!

* typo and I am OCD. please let this be the last

* hash is usally but not always noexcept, so the specifier should go

* Address MOST of the feedback

* address the claim codes issue
2024-02-10 05:05:25 -06:00
David Markowitz
f0b6ad89d9 chore: Player class removal (#1445)
* SystemAddress and destructor

* move respawn logic to character comp

Tested that respawn pos and rot can be set as per previously by crossing a respawn point and smashing to see if I would respawn at the new place.

* Move loot cheat checking

* Remove GetParentUser overload

Tested completing missions
control behaviors
collecting life crate
completing a bunch of missions using macros
loading into worlds
brick-by-brick
placing models
digging the x spot in gnarled forest
can still ban and mute players
cheat detection is still doing its thing
flags are still set (checked with flag 45)
claim codes still work (created new char, checked the lego club mail was there)

* Move player constructor logic

Its now at the bottom of Entity constructor.  Time to remove Player

* Remove Player class

Removes the Player class.  Tested that I can still login and see another player in Venture Explorer and logging out a few times still works as well as smashing enemies

* store ptr

* Update SlashCommandHandler.cpp
2024-02-04 06:29:05 -08:00
jadebenn
a0d51e21ca refactor: allow usage of NiPoint3 and NiQuaternion in constexpr context (#1414)
* allow usage of NiPoint3 and NiQuaternion in constexpr context

* removed .cpp files entirely

* moving circular dependency circumvention stuff to an .inl file

* real world usage!!!!!

* reverting weird branch cross-pollination

* removing more weird branch cross-pollination

* remove comment

* added inverse header guard to inl file

* Update NiPoint3.inl

* trying different constructor syntax

* reorganize into .inl files for readability

* uncomment include

* moved non-constexpr definitions to cpp file

* moved static definitions back to inl files

* testing fix

* moved constants into seperate namespace

* Undo change in build-and-test.yml

* nodiscard
2024-01-29 01:53:12 -06:00
David Markowitz
2f247b1fc9 fix: faction changes not allowing updated targets (#1437)
* fix faction change issue

fixes an issue where enemies who would have their faction changed would not change aggro targets.

Tested that stromling mechs and ronin/horsemen in forbidden valley still aggro on spawn as expected.

* use erase remove if
2024-01-29 01:52:59 -06:00
Aaron Kimbrell
99b3705a76 Revert "fix: Remove pending timer logic" (#1417) 2024-01-14 22:05:50 +01:00
David Markowitz
0a30430c4f fix: Remove pending timer logic (#1416)
* remove pending timers

they serve no purpose anymore since iterator invalidation is a non-issue.  I added this initially to make it so if you added a timer this frame, there would be at least 1 frame before you would start it, but this in practice doesnt serve a purpose

* timers still work
2024-01-14 03:46:56 -06:00
David Markowitz
929d029f12 chore: Simplify and move Player functionality to relevant component (#1408)
* Moving and organizing Player code

- Move code to CharacterComponent
- Remove extraneous interfaces
- Simplify some code greatly
- Change some types to return and take in const ref (only structs larger than 8 bytes benefit from this change.)
- Update code to use CharacterComponent for sending to zone instead of Player*.

* Moving and organizing Player code

- Move code to CharacterComponent
- Remove extraneous interfaces
- Simplify some code greatly
- Change some types to return and take in const ref (only structs larger than 8 bytes benefit from this change.)
- Update code to use CharacterComponent for sending to zone instead of Player*.
- Remove static storage container (static containers can be destroyed before exit/terminate handler executes)

* remove player cast

* Remove extra includes
2024-01-12 11:39:51 -06:00
David Markowitz
b683413a60 Remove deps from dNet (#1401) 2024-01-07 08:05:57 +01:00
David Markowitz
14c20fbd62 change timers to not use ptrs (#1399)
add comments as to why logic may seem confusing.
2024-01-06 03:45:23 -06:00
Aaron Kimbrell
15954413ae chore: rename rebuild to quickbuild (#1364)
* rename rebuild to quickbuild

* fix includes
2023-12-28 22:24:30 -06:00
David Markowitz
a1f8ab763d Entity: Fix death behavior of 0 (#1319) 2023-11-25 22:50:28 -06:00
David Markowitz
ae349d6b15 feat: Add isolated and simplified path to add components (#1204)
* Components: Make ComponentType inline

Prevents the next commits ODR violation

* Components: Add new components

* Entity: Add headers

inline script component ComponentType

* Components: Flip constructor argument order

Entity comes first always

* Entity: Add generic AddComponent

Allows for much easier adding of components and is error proof by not allowing the user to add more than 1 of a specific component type to an Entity.

* Entity: Migrate all component constructors

Move all to the new variadic templates AddComponent function to reduce clutter and ways the component map is modified.
The new function makes no assumptions.  Component is assumed to not exist and is checked for with operator[].  This will construct a null component which will then be newed if the component didnt exist, or it will just get the current component if it does already exist.  No new component will be allocated or constructed if the component already exists and the already existing pointer is returned instead.

* Entity: Add placement new

For the case where the component may already exist, use a placement new to construct the component again, it would be constructed again, but would not need to go through the allocator.

* Entity: Add comments on likely new code

* Tests: Fix tests

* Update Entity.cpp

* Update SGCannon.cpp

* Entity: call destructor when re-constructing

* Update Entity.cpp

Update Entity.cpp

---------

Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
2023-10-22 20:08:49 -05:00
David Markowitz
2cc13c6499 chore: Make serialize actually virtual (#1156)
* Make serialize actually virtual

* fix serialize and make update virutal

* Update VendorComponent.h

* Remove flag var

* Update SoundTriggerComponent.h

---------

Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
2023-08-10 14:33:15 -07:00