Files
EscapistsReintroduced/docs/player-lifecycle.md
T

30 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Player lifecycle and pending admission
The successor keeps one round-owned life record per authenticated account. A connection number is only the current binding to that record. A new life can enter during prison, radio search or radio defence; extraction and terminal phases refuse new admission. Successful initial assignment spends the life. Cancelling an unassigned preload never restores or spends a life.
Native reconnect reservation and handoff remain separate from new-character admission. A returning account may reclaim its surviving reserved actor through Reforger's reconnect system. A dead actor remains a spent life; unconsciousness is not death. Reserved living actors remain participants while their connections are absent. These policies are implemented, but real remote reconnect and reservation-expiry acceptance remains unfinished.
## Placement
Prison placement uses 25 candidates on a 5×5 grid, spaced 1.5m apart and bounded to 3m from the authored prison center. Candidates remain inside the existing enclosure. Terrain height and slope, physical scene/character occupancy, and pending reservations can reject a slot. Connection IDs 1 and 13 receive no special or shared position. Disconnected physical bodies still obstruct the native query.
If every candidate is occupied or pending, admission waits and retries. Lack of a clear slot does not consume the native spawn-failure budget. Later arrivals first search bounded clear ground near a conscious friendly survivor outside a vehicle, with terrain-height and line-of-sight checks, then try the same prison grid. Placement does not imply a navigable route or safe proximity to enemies.
A nominal 25-point grid does not prove 12-player physical capacity. Native scene bounds can reduce capacity; the opt-in fixture requires at least 11 additional available positions around one actual controlled prisoner. Manual crowding, movement, collision and spawn usability are still required.
## Finalization and cleanup
The server records each initial free-spawn admission in a ticket bound to the mission instance, account, connection, controller, native request, exact request data object and created actor. Immediately before native assignment it rechecks current phase, account binding, connection, spent life, controller and request ownership, absence of another controlled entity, actor health and placement. Horizontal drift is limited to 0.6m and vertical drift to 1m, allowing ordinary settling while refusing displaced or fallen preloads. The reserved location is checked against current terrain and physical occupancy again.
A refused ticket permits cleanup only of its owned unpossessed actor. An unknown or repeated request cannot claim an arbitrary actor for deletion. Stop, disconnect and closed-admission phases remove reservations, cancel the native repeated finalization callback and remove their pending actors. Pending/retry metadata is cleared before cancellation emits a response, so the response's failure callback cannot schedule a fresh admission. Cleanup rechecks actual player control: `ERR_Actors.DeleteSpawned` refuses any entity currently controlled by a player, regardless of its original ownership.
The native handler interception applies only to successor game modes or an existing handler whose owning respawn system still carries successor spawn logic during teardown. Other scenarios retain vanilla behavior. Delayed entity-loss observation also checks the captured controller and ignores a living actor that was reacquired before the callback runs.
## Validation status
`python3 tools/check.py` includes `tests/test_player_admission_policy.py`. It executes the actual source-local finalization and life-policy bodies plus the actual reservation rejection predicate through the existing C++ policy harness. Coverage includes every phase/life/connectivity/controller/request/identity combination, missing identities, displacement boundaries, radial distance, vertical reservation separation and own-reservation exclusion. The harness substitutes vector arithmetic and opaque identity equality; it does not emulate Enfusion collision, replication, native spawning or reconnect behavior.
`ERR_NativeLifecycleProbe` is an opt-in WORKBENCH fixture integrated by the central runner as `-errBaseSmoke 1 -errSmokeOutcome lifecycle`. It checks native prison capacity, physical character occupancy, actual local-controller handler rejection, exact request ownership, deferred deletion, cancellation without another life, delayed observer metadata protection and a native displaced actor. Movement checks wait 750ms and deletion checks wait 1000ms rather than assuming immediate native updates. Synthetic ticket creation is confined to WORKBENCH and never changes the real prisoner's life record or possession.
The native lifecycle fixture in [050403](evidence/native-2026-09-19-050403/report.json) completes 54 assertions, including an ordinary initial prisoner spawn. It finds 20 remaining clear positions around that prisoner. No script/VM exception occurs; seven inherited vanilla resource errors remain. Earlier reserved member-name and reflected-container failures are preserved in the validation archive. Normal Core/companion escape and restart regression remains a separate check. Remote 12-player concurrent join, slow client preload, disconnect during preload, recycled connection IDs, reconnect reservation handoff/expiry and spectator streaming cleanup remain separate multiplayer acceptance work.