Add COVault109 solo-cell handling
Implement solo-cell logic to suppress transform packet sends and remote proxy representation while the local player is in COVault109, allowing first-time character creation to remain visually single-player. One entry location update is sent so other clients can hold stale proxies before suppression begins. Added F4TSoloCell.h helper for load-order-independent solo cell recognition by editor ID and cached FormID.
This commit is contained in:
+23
-15
@@ -37,23 +37,29 @@ both send and receive paths:
|
||||
`serverWorldState` to all clients for admin weather (`fw`) and time
|
||||
(`set gamehour to HHmm`) commands. Promoted hosts continue with their
|
||||
already-synced local time and weather so remaining clients should not see a jump.
|
||||
12. On the game-thread update path, the proxy controller reads a copied
|
||||
12. The plugin treats `COVault109` as a solo cell for first-time character
|
||||
creation. On entry it can send one location update so other clients hold any
|
||||
stale proxy, then outgoing transform packets are suppressed and remote proxy
|
||||
representation is skipped while the local player remains inside. Looks and
|
||||
SPECIAL setup therefore stay visually single-player. The relay protocol is
|
||||
unchanged; the rule is enforced client-side by the plugin.
|
||||
13. On the game-thread update path, the proxy controller reads a copied
|
||||
remote-player snapshot before attempting any actor work. The snapshot is
|
||||
sorted by `playerId`, and only remote players with valid transform data in
|
||||
the same cell are eligible for runtime proxy representation.
|
||||
13. For each eligible remote `playerId`, the controller maintains a
|
||||
14. For each eligible remote `playerId`, the controller maintains a
|
||||
`remotePlayerId -> runtime proxy slot` mapping. Each slot stores its
|
||||
`ObjectRefHandle`, lifecycle state, PlaceAtMe-backed spawn/candidate state,
|
||||
movement smoothing state, and data-only animation debug state. Stage 4 caps runtime
|
||||
proxy slots at four actors for testing.
|
||||
14. Runtime proxies are demand-driven. A slot executes the Stage 3.7
|
||||
15. 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. 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.
|
||||
15. Runtime proxies receive a small game-thread neutralization pass when a
|
||||
16. Runtime proxies receive a small game-thread neutralization pass when a
|
||||
PlaceAtMe-backed actor is promoted, when a reusable slot is reassigned, while
|
||||
active on a throttle, and when moved or kept in holding. The pass only uses
|
||||
confirmed CommonLibF4 actor APIs/fields to stop combat, clear combat target
|
||||
@@ -63,60 +69,60 @@ both send and receive paths:
|
||||
alarm, bump, or package movement intent is observed. It does not disable,
|
||||
hide, delete, despawn, alpha-fade, or force animation graph events on the
|
||||
actor.
|
||||
16. Proxy visual updates are independent per slot. Normal movement is smoothed
|
||||
17. 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. Movement and animation-related remote state is
|
||||
still observed and logged only; no visual crouch/sneak, jump, weapon drawn,
|
||||
locomotion, animation graph, or actor-state application is attempted.
|
||||
17. When a remote player leaves the cell or disconnects, only that player’s
|
||||
18. 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 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.
|
||||
18. The placed fallback reference `F4TProxyRemotePlayer01REF` remains a single
|
||||
19. 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
|
||||
is not used for multiple remote players.
|
||||
19. As part of the staged runtime proxy actor manager work, the same game-thread
|
||||
20. As part of the staged runtime proxy actor manager work, the same game-thread
|
||||
proxy controller also logs whether `Fallout4Together_Test.esp` is loaded and
|
||||
whether the actor base `F4T_RemotePlayerProxy` resolves by editor ID.
|
||||
20. Stage 3.1 adds a temporary diagnostic layer around the single runtime proxy:
|
||||
21. Stage 3.1 adds a temporary diagnostic layer around the single runtime proxy:
|
||||
post-spawn visibility data, loaded-3D pointer checks where safe, console
|
||||
helper logs, active source logs, and throttled post-movement diagnostics.
|
||||
The diagnostic mode can force the runtime proxy near the local player to
|
||||
prove whether the created actor is visibly renderable.
|
||||
21. Stage 3.2 adds a temporary near-player visibility hold for that same single
|
||||
22. Stage 3.2 adds a temporary near-player visibility hold for that same single
|
||||
runtime proxy. During the hold, remote state is still selected and validated,
|
||||
but runtime proxy restore and remote movement are deferred long enough to
|
||||
test whether a runtime-created actor ref can load visible 3D while kept near
|
||||
the local player.
|
||||
22. Stage 3.3 adds a temporary vanilla actor-base diagnostic layer. It attempts
|
||||
23. Stage 3.3 adds a temporary vanilla actor-base diagnostic layer. It attempts
|
||||
to resolve Codsworth as a visible vanilla `TESNPC` candidate, then passes
|
||||
that actor base into the same runtime spawn, handle validation, near-player
|
||||
hold, and visibility diagnostic path. This isolates custom actor-base issues
|
||||
from runtime-spawn/init issues without changing the final architecture.
|
||||
23. Stage 3.4 adds a temporary absolute FormID and existing-reference diagnostic
|
||||
24. Stage 3.4 adds a temporary absolute FormID and existing-reference diagnostic
|
||||
layer. It compares Codsworth base-form runtime spawning against moving the
|
||||
existing placed Codsworth reference near the local player as a visibility
|
||||
control. This separates runtime actor creation/init problems from vanilla
|
||||
actor-base or placed-reference movement problems and does not change the
|
||||
final architecture.
|
||||
24. Stage 3.5 adds a temporary PlaceAtMe-equivalent diagnostic after manual
|
||||
25. Stage 3.5 adds a temporary PlaceAtMe-equivalent diagnostic after manual
|
||||
console validation proved `player.placeatme 000179FF 1` can spawn visible
|
||||
Codsworth in `F4TTestCell01`. The plugin executes that console placement path
|
||||
from the local player, resolves the newly created Codsworth actor near the
|
||||
player, and holds/logs it separately from the `CreateReferenceAtLocation`
|
||||
runtime proxy path.
|
||||
25. Stage 3.6 refines that temporary PlaceAtMe diagnostic layer. It snapshots
|
||||
26. Stage 3.6 refines that temporary PlaceAtMe diagnostic layer. It snapshots
|
||||
known Codsworth refs before executing `player.placeatme 000179FF 1`, accepts
|
||||
only a newly isolated Codsworth ref for the primary diagnostic, and preserves
|
||||
that actor at the original console-spawned location during a short settle
|
||||
window. This tests whether the actor becomes visible naturally or requires a
|
||||
render/process refresh such as the manually observed pause-menu or alt-tab
|
||||
behavior. Stage 3.6 does not change the final architecture.
|
||||
26. Stage 3.7 promotes the working PlaceAtMe-style spawn pattern into the
|
||||
27. Stage 3.7 promotes the working PlaceAtMe-style spawn pattern into the
|
||||
preferred single runtime proxy spawn path. The proxy controller uses the
|
||||
resolved runtime FormID for `F4T_RemotePlayerProxy` when available, falls
|
||||
back to Codsworth only for diagnostics, defers active proxy selection during
|
||||
@@ -155,6 +161,8 @@ The native plugin is responsible for:
|
||||
- Loading into Fallout 4
|
||||
- Reading local player state
|
||||
- Sending local player data to the server
|
||||
- Suppressing local transform sends and remote proxy representation while the
|
||||
local player is in solo cells such as `COVault109`
|
||||
- Adding basic data-only movement state to transform packets
|
||||
- Throttling normal transform sends separately from readable local movement logs
|
||||
- Receiving server packets on a background thread
|
||||
|
||||
@@ -9,6 +9,41 @@ failed experiments, successful tests, and next steps.
|
||||
|
||||
---
|
||||
|
||||
## 2026-06-29 - `COVault109` Solo Cell
|
||||
|
||||
### Summary
|
||||
Made the first-time `COVault109` starting cell single-player from the multiplayer sync perspective so character customization and SPECIAL setup are not disturbed by remote player proxies.
|
||||
|
||||
### Files Changed
|
||||
- `plugin/include/F4TSoloCell.h`
|
||||
- `plugin/src/main.cpp`
|
||||
- `plugin/src/F4TProxyActorController.cpp`
|
||||
- `changelog.md`
|
||||
- `docs/dev-log.md`
|
||||
- `docs/architecture.md`
|
||||
- `protocol/player-sync.md`
|
||||
|
||||
### Details
|
||||
- Added a shared solo-cell helper that recognizes `COVault109` by editor ID and cached runtime FormID, avoiding load-order-dependent hardcoded IDs.
|
||||
- Sends one entry location update for `COVault109`, then suppresses outgoing local transform packets while the local player remains inside so other clients can hold stale proxies and stop receiving fresh position updates for a player in character creation.
|
||||
- Suppressed remote proxy representation while the local player is inside `COVault109`; existing proxy slots are held instead of being moved or restored in the starting cell.
|
||||
- Kept the Python relay and transform packet structure unchanged.
|
||||
|
||||
### Testing
|
||||
- Not run in-game in this session.
|
||||
- Expected result: two connected clients can both be in `COVault109` without seeing runtime proxies in that cell.
|
||||
- Expected result: leaving `COVault109` resumes transform sending and normal same-cell proxy behavior outside the solo cell.
|
||||
|
||||
### Known Issues
|
||||
- The solo-cell list is currently code-defined and contains only `COVault109`.
|
||||
|
||||
### Next Steps
|
||||
- Run two Fallout 4 instances through first-time character creation and confirm no proxy actors appear in `COVault109`.
|
||||
- Check `CommonwealthOnline.log` for solo-cell suppression/resume messages.
|
||||
- Verify normal transform and proxy sync still works after leaving `COVault109`.
|
||||
|
||||
---
|
||||
|
||||
## 2026-06-28 - Papyrus Build Integration
|
||||
|
||||
### Summary
|
||||
|
||||
Reference in New Issue
Block a user