Improve runtime proxy slot lifecycle & spawn

Refine Stage 4 runtime proxy management: introduce explicit lifecycle states (HeldNoRemote, HeldDisconnected, HeldLeftCell, Reusable, SpawnFailed), add a 30s disconnected-slot reuse delay, and implement per-slot hidden holding positions with spacing. Add a held-position correction pass (correct drift >25 units) and make disconnected-held slots become reusable after the grace period; reusable slots can be reassigned to later playerIds. Capture a remote player's current transform before performing the PlaceAtMe-backed Stage 4 spawn and apply that transform immediately when the isolated proxy is promoted, preventing a brief visual spawn near the local player. Misc: improved logging/throttling, slot assignment/reassignment logic, and various helper functions. Docs updated (architecture.md, dev-log.md) and plugin/src/F4TProxyActorController.cpp implements the behavior.
This commit is contained in:
2026-06-03 10:47:15 +12:00
parent b4ec928c67
commit 5394250ef2
3 changed files with 540 additions and 61 deletions
+24 -3
View File
@@ -37,15 +37,21 @@ both send and receive paths:
13. Runtime proxies are demand-driven. A slot executes the Stage 3.7
PlaceAtMe-backed spawn flow only when that remote player needs a same-cell
representation, and only one PlaceAtMe spawn attempt may run at a time so
candidate isolation remains unambiguous.
candidate isolation remains unambiguous. Stage 4 captures the remote
player's current valid transform before spawning and moves the isolated
runtime actor to that transform immediately, so normal remote representation
does not visually start at the local player offset.
14. Proxy visual updates are independent per slot. Normal movement is smoothed
toward that player’s latest target, while `cell_change`, `worldspace_change`,
and `teleport` snap directly. Sneak state is still observed and logged only;
no visual crouch/sneak application is attempted.
15. When a remote player leaves the cell or disconnects, only that player’s
runtime proxy is moved to the hidden holding position inside
`F4TTestCell01`. Runtime actors are not disabled, deleted, or reassigned to a
different `playerId` during Stage 4.
`F4TTestCell01`. Runtime actors are not disabled or deleted. Connected
players who leave the cell keep their slot reserved, while disconnected
held slots become reusable only after the configured grace period. Runtime
slots use per-slot holding positions with spacing and a game-thread
correction check so held actors do not stack or drift back into view.
16. The placed fallback reference `F4TProxyRemotePlayer01REF` remains a single
backup representation. If runtime spawning fails for one deterministic
selected remote player, the fallback can represent that one player only; it
@@ -96,6 +102,9 @@ both send and receive paths:
The Fallout 4 plugin now dynamically spawns one runtime proxy actor per
represented remote `playerId` in the test cell, up to a small Stage 4 test cap.
Disconnected held slots can be reassigned to later server `playerId` values after
the grace period, but slots held for connected players outside the cell are not
reused.
The placed proxy reference remains as a single fallback path if runtime spawning
fails for one selected remote player.
@@ -117,11 +126,19 @@ The native plugin is responsible for:
for one selected player only if runtime spawning fails
- Holding only the affected proxy actor at a hidden in-cell position when its
remote player disconnects or leaves the same cell
- Assigning each runtime proxy slot a unique hidden holding position and
correcting held actors back to that position if collision, AI, or physics drift
moves them away
- Reusing only disconnected runtime proxy slots after a grace period; slots held
because a still-connected remote player left the cell remain reserved for that
original `playerId`
- Logging staged runtime proxy actor base lookup diagnostics on the same
game-thread controller path
- Attempting one game-thread-only PlaceAtMe-backed runtime spawn from the
selected Stage 3 actor base in `F4TTestCell01`, normally
`F4T_RemotePlayerProxy`
- Capturing the remote player's current valid transform before Stage 4 runtime
spawn and applying it as soon as the PlaceAtMe-backed actor is isolated
- Logging temporary Stage 3.1 visibility and movement diagnostics for the single
runtime proxy, including active proxy source, runtime FormID, local distance,
and safe loaded-3D checks
@@ -200,9 +217,13 @@ Game update validates transform data and same-cell compatibility
Game update creates or reuses a runtime proxy slot per eligible remote playerId
Game update attempts at most one PlaceAtMe-backed runtime actor spawn at a time
Game update snapshots matching candidates, isolates the new actor, and waits for the settle window
Game update moves isolated Stage 4 runtime spawn candidates to the remote player's current transform
Game update stores promoted runtime actors as ObjectRefHandle values in slots
Game update moves each valid proxy from its assigned remote player state
Game update holds only proxies whose assigned remote player left the cell or disappeared
Game update corrects held proxy slots back to their per-slot hidden positions
Game update marks disconnected held slots reusable after the grace period
Game update may reassign reusable disconnected slots to later server playerIds
Game update may use F4TProxyRemotePlayer01REF as one placed fallback if runtime spawning fails
```
+175
View File
@@ -1903,6 +1903,181 @@ proxy actors only when valid same-cell remote state needs representation.
---
## 2026-06-03 - Runtime Proxy Manager Cleanup and Stability Pass
### Summary
Cleaned up the Stage 4 runtime proxy slot lifecycle so disconnected held slots
can become reusable after a grace period instead of occupying the small runtime
proxy cap forever.
### Files Changed
- `plugin/src/F4TProxyActorController.cpp`
- `docs/architecture.md`
- `docs/dev-log.md`
### Details
- Refined runtime proxy slot lifecycle states to distinguish active, held because
no valid remote transform, held because the remote player left the cell, held
because the remote player disconnected/disappeared, reusable, and spawn-failed
slots.
- Added a 30 second disconnected-slot reuse delay. Disconnected slots are first
moved to the holding position and marked held; only after the delay do they
become reusable.
- Updated slot acquisition to prefer an existing slot for the same `playerId`,
create a new slot while under `kMaxRuntimeProxyActors`, and reuse an eligible
disconnected slot at the cap before logging a throttled max-cap warning.
- Preserved connected-but-left-cell slots for their original `playerId`, so
Leave Cell / Return To Cell keeps the same proxy assignment.
- Reset movement smoothing flags and sneak observation state when a reusable slot
is reassigned, then snap the proxy to the new remote player's current transform
before normal smoothing resumes.
- Kept server `playerId` allocation, networking packets, Python server code, fake
client tooling, placed fallback behavior, same-cell gating, movement
smoothing/snap behavior, and data-only sneak observation unchanged.
- Continued to avoid disabling, deleting, alpha-hiding, or otherwise marking
runtime actors for deletion; held actors remain at the hidden in-cell holding
position.
### Testing
- `xmake build` from the repository root prompts because there is no root
`xmake.lua`.
- Ran `xmake build` from `plugin`; it succeeded and rebuilt
`Fallout4Together.dll`.
- Pending manual validation: launch Fallout 4 through F4SE, load
`Fallout4Together_Test.esp`, `coc F4TTestCell01`, start the Dev Server GUI,
add fake clients up to the cap, disconnect clients, wait for the reuse delay,
and confirm a later higher `playerId` can reuse an old disconnected slot.
- Pending manual validation: confirm Leave Cell / Return To Cell preserves a
connected player's original slot and that Walk Circle, Walk To Player,
Teleport Test, and sneak-state logging still behave as before.
### Known Issues
- Runtime actors are still held instead of safely despawned or deleted.
- The placed fallback remains single-player only by design.
- In-game validation for this cleanup pass is still pending.
### Next Steps
- Run the manual GUI fake-client lifecycle test in `F4TTestCell01`.
- If reuse validates cleanly, keep the next milestone focused on diagnostics or
safe actor cleanup research rather than gameplay sync expansion.
---
## 2026-06-03 - Held Runtime Proxy Stability Patch
### Summary
After manual testing showed some disconnected held runtime proxies could visually
reappear even while their remote players were absent, tightened the held-proxy
positioning path.
### Files Changed
- `plugin/src/F4TProxyActorController.cpp`
- `docs/architecture.md`
- `docs/dev-log.md`
### Details
- Kept the hidden holding-position approach and continued to avoid disabling,
deleting, alpha-hiding, or marking actors for deletion.
- Moved the shared holding base farther away/lower and gave each runtime proxy
slot a stable holding-position index with 500 unit spacing so held actors do
not stack on the same coordinates.
- Added a game-thread held-position correction pass for `HeldNoRemote`,
`HeldLeftCell`, `HeldDisconnected`, and `Reusable` slots. If a held proxy
drifts more than 25 units from its assigned holding position, the controller
moves it back and logs a throttled correction message.
- Preserved disconnected-slot reuse behavior: `HeldDisconnected` still becomes
`Reusable` after the delay, reusable slots can still be reassigned, and
`HeldLeftCell` slots remain reserved for connected players.
- Networking, protocol, Python server code, fake-client tooling, placed fallback
behavior, movement smoothing/snap behavior, same-cell gating, and data-only
sneak observation were unchanged.
### Testing
- Ran `xmake build` from `plugin`; it succeeded and rebuilt
`Fallout4Together.dll`.
- Pending manual validation: repeat the GUI fake-client disconnect test that
previously caused held proxies to visually reappear.
### Known Issues
- Runtime actors are still held instead of safely despawned or deleted.
- The placed fallback remains single-player only by design.
- In-game validation of the held-position correction is still pending.
### Next Steps
- Re-test removing all fake clients and confirm held proxies stay out of view.
- Re-test reuse after the grace period and Leave Cell / Return To Cell.
---
## 2026-06-03 - Runtime Proxy Spawn Polish Patch
### Summary
Polished Stage 4 runtime proxy spawning so newly isolated runtime actors are
placed at the remote player's current transform immediately instead of visually
starting near the local player before snapping away.
### Files Changed
- `plugin/src/F4TProxyActorController.cpp`
- `docs/architecture.md`
- `docs/dev-log.md`
### Details
- Added slot-local initial remote spawn transform tracking for runtime proxy
slots.
- Captures the remote player's current valid same-cell transform before starting
the Stage 4 PlaceAtMe-backed spawn path.
- Applies that transform as soon as the new PlaceAtMe-backed actor is isolated
and again at promotion, setting both position and heading before normal remote
movement resumes.
- Reusable slot reassignment continues to snap directly to the newly assigned
remote player's current transform and resets movement/sneak observation state.
- Kept movement smoothing and snap behavior unchanged: normal movement still
lerps after initialization, while `cell_change`, `worldspace_change`, and
`teleport` still snap.
- Networking, protocol, Python server code, fake-client tooling, placed fallback
behavior, held/reusable slot behavior, same-cell gating, and data-only sneak
observation were unchanged.
### Testing
- Ran `xmake build` from `plugin`; it succeeded and rebuilt
`Fallout4Together.dll`.
- Pending manual validation: add a GUI fake client and confirm its proxy no
longer briefly appears near the local player before moving to the fake client's
remote transform.
- Pending manual validation: re-test reusable slot reassignment, Walk To Player,
Walk Circle, Leave Cell, Return To Cell, disconnect, and reconnect.
### Known Issues
- The Stage 4 spawn path still uses PlaceAtMe-backed candidate isolation, so the
actor is moved to the remote transform immediately after isolation rather than
replacing the underlying diagnostic spawn mechanism.
- Runtime actors are still held instead of safely despawned or deleted.
### Next Steps
- Manually verify new-client spawn visuals in `F4TTestCell01`.
- If a visible local-player flash remains before candidate isolation, investigate
replacing the PlaceAtMe-backed Stage 4 spawn backend in a separate milestone.
---
## Entry Template
Use this format for future updates: