Inventory the present selection, interaction, combat, movement, physics, and projectile owners; pin named-retail ordering; and define independently reversible J5.1-J5.7 gates without moving presentation into Runtime. Co-authored-by: Codex <noreply@openai.com>
207 lines
9.4 KiB
Markdown
207 lines
9.4 KiB
Markdown
# Slice J5 owner and retail-order inventory
|
|
|
|
**Date:** 2026-07-26
|
|
**Scope:** presentation-free selection, interaction, combat/magic intent,
|
|
movement/outbound cadence, physics, and projectile ownership
|
|
**Parent plan:** `docs/plans/2026-07-26-modern-runtime-slice-j5.md`
|
|
|
|
## Purpose
|
|
|
|
Slice J5 moves gameplay simulation and intent out of the graphical App and into
|
|
`AcDream.Runtime`. This note pins the current production owners and the retail
|
|
ordering that cannot change while those owners move.
|
|
|
|
This is an ownership refactor, not a new movement, combat, interaction, or
|
|
projectile implementation. Existing retail ports remain the behavioral oracle.
|
|
|
|
## Current source ownership
|
|
|
|
| Concern | Current canonical state | Construction/root | Presentation coupling to split |
|
|
|---|---|---|---|
|
|
| Selection identity | `AcDream.Core.Selection.SelectionState` | `Program` constructs; `GameWindow` retains | world ray picking, lighting pulse, vivid markers, status/UI projections |
|
|
| Combat notifications/mode | `AcDream.Core.Combat.CombatState` | `GameWindow` constructs | combat/spell bars, camera target tracking, feedback |
|
|
| Pointer target mode | `AcDream.App.UI.InteractionState` | optional private construction inside `ItemInteractionController` | cursor image only; state itself is presentation-free |
|
|
| Item-use/appraisal/pickup intent | `ItemInteractionController`, `SelectionInteractionController`, `InventoryTransactionState` | App retained-UI and live-presentation composition | world picking, retained drag/drop, toasts, pending-slot mesh |
|
|
| Combat attack intent | `CombatAttackController`, `LiveCombatModeCommandController` | App retained-UI/session composition | input action mapping and combat-bar projection |
|
|
| Spell-cast intent | `SpellCastingController` inside App `MagicRuntime` | App content/UI composition | DAT catalog loading, component icons/text, spell bar |
|
|
| Local movement | `PlayerMovementController` plus Core `PhysicsBody`, `MotionInterpreter`, `MovementManager` | App player-mode composition | Silk/input sampling, camera/mouse-look device state, animated pose publication |
|
|
| Outbound movement cadence | `LocalPlayerOutboundController` | `GameWindow` constructs | App diagnostic sink only |
|
|
| Per-session collision | Core `PhysicsEngine`, `ShadowObjectRegistry`, transition scratch | `GameWindow` constructs | streaming publishers and debug visualization |
|
|
| Remote movement/physics | App `RemotePhysicsUpdater`, `RemoteInboundMotionDispatcher`, live sidecars | App composition | `WorldEntity`, render projection, animation pose/effect publication |
|
|
| Projectile simulation | Core `ProjectilePhysicsStepper` plus App `ProjectileController.Runtime` | App live-presentation composition | `WorldEntity`, effect pose, shadow publication |
|
|
|
|
`RuntimeEntityRecord` already owns canonical accepted identity, timestamps,
|
|
full cell, raw/final physics state, object clock, `PhysicsBody`, and
|
|
`IPhysicsObjHost`. The App `LiveEntityRecord` is a projection sidecar. J5 must
|
|
extend the canonical record rather than add another entity or physics model.
|
|
|
|
`RuntimeInventoryState` already owns the exact inventory transaction/busy/use
|
|
reservation state. J5 interaction work must borrow that owner and must not
|
|
recreate a busy counter or pending inventory request.
|
|
|
|
## Current reset ordering
|
|
|
|
`LiveSessionResetManifest` currently performs the relevant stages in this
|
|
order:
|
|
|
|
1. mouse/input capture;
|
|
2. player presentation and teleport transit;
|
|
3. dialogs/chat/settings;
|
|
4. equipped children and external container;
|
|
5. interaction plus selection;
|
|
6. inventory transactions;
|
|
7. selection presentation and object table;
|
|
8. spellbook/magic;
|
|
9. combat attack and combat state;
|
|
10. local-player and remaining session state;
|
|
11. live entity teardown;
|
|
12. render projection drain and session identity;
|
|
13. network effects/presentation tails.
|
|
|
|
Runtime ownership may combine internal stages, but App acknowledgements must
|
|
retain the same dependency order: presentation releases references before the
|
|
canonical owner is destroyed, while old session identity remains available
|
|
until exact-incarnation teardown converges.
|
|
|
|
## Named-retail ordering matrix
|
|
|
|
### Selection
|
|
|
|
`ACCWeenieObject::SetSelectedObject @ 0x0058C2E0`
|
|
|
|
1. If forced or changed, clear the old object's selected flag.
|
|
2. Commit the new selected ID.
|
|
3. Set the new object's selected flag.
|
|
4. If the ID changed, commit previous and previous-valid IDs.
|
|
5. Publish the UI selection notice.
|
|
6. Publish the shared item-holder selection change.
|
|
7. Notify the plugin API.
|
|
|
|
The state commit precedes every observer. Deduplicated selection does not
|
|
publish the changed notice.
|
|
|
|
### Session combat initialization
|
|
|
|
`ClientCombatSystem::Begin @ 0x0056A460`
|
|
|
|
1. Commit NonCombat and clear pending mode.
|
|
2. Clear jump, build, response, attack, repeat, and tracking transients.
|
|
3. Restore medium attack height and UI requested power `0.5`.
|
|
4. Register the global notice handler.
|
|
|
|
Runtime combat reset must clear the complete intent transaction before App
|
|
projects the peace-mode UI.
|
|
|
|
### Ordinary use and target mode
|
|
|
|
`ItemHolder::UseObject @ 0x00588A80`
|
|
|
|
1. Enforce the strict 0.2-second local use gate.
|
|
2. Verify inventory-request readiness and vendor restrictions.
|
|
3. Resolve automatic wield/use policy and targeted-use policy.
|
|
4. For ordinary use, emit `CM_Inventory::Event_UseEvent`.
|
|
5. Increment the shared UI busy reference.
|
|
6. Invoke `CPlayerSystem::UsingItem` and publish local text.
|
|
7. For a targeted item without an acquired target, store the source object and
|
|
enter `TARGET_MODE_USE_TARGET`; do not emit the use-with-target packet yet.
|
|
8. Once a compatible target is acquired, emit
|
|
`Event_UseWithTargetEvent`, increment busy, then invoke `UsingItem`.
|
|
|
|
`ClientUISystem::Handle_Item__UseDone @ 0x00564900`
|
|
|
|
1. Decrement exactly one busy reference.
|
|
2. Refresh cursor state only when the count reaches zero.
|
|
3. Present a nonzero server error afterward.
|
|
|
|
The current production correction remains authoritative for local ACE:
|
|
ordinary Use is sent immediately and ACE owns spatial approach. Pickup retains
|
|
the existing ordered local approach transaction and post-arrival send.
|
|
|
|
### Local movement output
|
|
|
|
`CommandInterpreter::SendMovementEvent @ 0x006B4680`
|
|
|
|
1. Require player, SmartBox, raw motion state, and nonzero autonomy.
|
|
2. Read the player's current raw state, canonical `Position`, contact state,
|
|
long-jump state, and four retail timestamps.
|
|
3. build/send `MoveToStatePack`.
|
|
4. Stamp `last_sent_position_time` only after send.
|
|
|
|
`CommandInterpreter::SendPositionEvent @ 0x006B4770`
|
|
|
|
1. Require SmartBox, player, active/in-world transient state, and valid
|
|
canonical `Position`.
|
|
2. Read current contact and timestamps.
|
|
3. build/send `AutonomousPositionPack`.
|
|
4. After send, stamp time and copy the complete sent `Position` and contact
|
|
plane as the next comparison baseline.
|
|
|
|
The existing pre-inbound movement/jump and post-inbound autonomous-position
|
|
slots remain unchanged.
|
|
|
|
### Object physics
|
|
|
|
`CPhysicsObj::UpdatePositionInternal @ 0x00512C30`,
|
|
`CPhysicsObj::transition @ 0x00512DC0`,
|
|
`CPhysicsObj::SetPositionInternal(CTransition const*) @ 0x00515330`,
|
|
and the ordered object tail recorded in
|
|
`docs/research/2026-07-19-r6-update-object-order-pseudocode.md` remain the
|
|
simulation oracle.
|
|
|
|
Runtime owns the canonical body and simulation. App may publish the final
|
|
accepted root/part poses only after that simulation result commits. A render
|
|
callback must never become position, cell, velocity, or collision authority.
|
|
|
|
### Projectile collision exclusion
|
|
|
|
`OBJECTINFO::missile_ignore @ 0x0050CEB0`
|
|
|
|
The existing Core `ProjectilePhysicsStepper` port remains unchanged:
|
|
|
|
- ignore other missiles;
|
|
- ignore ethereal weenies unless they are the designated target;
|
|
- with a nonzero designated target, ignore other creatures;
|
|
- do not infer a designated target from UI selection.
|
|
|
|
## Fixed dependency direction
|
|
|
|
```text
|
|
Silk / retained UI / camera
|
|
|
|
|
v
|
|
App typed input + presentation adapters
|
|
|
|
|
v
|
|
AcDream.Runtime intent/simulation owners
|
|
|
|
|
v
|
|
Core algorithms + Core.Net transport/content seams
|
|
```
|
|
|
|
Runtime never references App, Silk, OpenGL, OpenAL, ImGui, Arch, or retained
|
|
UI. App may synchronously acknowledge a committed runtime mutation and project
|
|
it; it may not keep a second mutable copy.
|
|
|
|
## Source hazards
|
|
|
|
1. `ItemInteractionController` can currently create a private
|
|
`InteractionState`; this is a duplicate-owner seam and must be removed when
|
|
J5.1 lands.
|
|
2. `Program` currently constructs selection while `GameWindow` constructs
|
|
combat. Both must move under one Runtime owner before higher-level
|
|
controllers move.
|
|
3. `PlayerMovementController` contains environment reads for test-era default
|
|
skills. A Runtime move must use typed construction options and the existing
|
|
Runtime character skill projection.
|
|
4. `LocalPlayerOutboundController` directly accepts `WorldSession` and an App
|
|
diagnostic sink. Runtime may use Core.Net, but diagnostics must cross a
|
|
narrow optional interface.
|
|
5. App `LiveEntityRecord` still stores remote/projectile component interfaces.
|
|
Simulation components must migrate to `RuntimeEntityRecord`; only
|
|
animation/effect/render projection belongs in the App sidecar.
|
|
6. Remote/projectile callbacks can synchronously delete or replace a GUID.
|
|
Every split-phase commit must retain the existing exact-record,
|
|
incarnation, authority-version, and object-clock-epoch revalidation.
|
|
7. `PhysicsEngine` transition scratch is per engine and same-thread LIFO.
|
|
Immutable prepared collision content may be shared; the engine and scratch
|
|
may not be shared by concurrent sessions.
|