feat(runtime): FA2 -- RuntimeFellowshipState + RuntimeAllegianceState sibling J-owners
Two new sibling Runtime owners under GameRuntime per the Slice-J pattern (D2): RuntimeFellowshipState is session-scoped (a new RuntimeGenerationResetStage.Fellowship clears it at every generation reset, matching the ExternalContainer precedent); RuntimeAllegianceState survives reconnect behind a HasServerSeed-style one-way latch and participates in NO reset stage (its data persists like a real disconnect does not sever allegiance membership). Fellowship: full-update REPLACE, incremental-fellow UPSERT, self-vs- other quit/dismiss removal (self clears the whole snapshot), disband clear, and retail's leader hand-off rule for the Quit button (RequiresLeaderHandoffBeforeQuit -- the current leader quitting WITHOUT disbanding must send 0x0290 AssignNewLeader before 0x00A3, lane B §2.5/§3.6). Allegiance: seeded by AllegianceUpdate (0x0020, always self) and, self-gated on TargetGuid == playerGuid(), by AllegianceInfoResponse (0x027C); wraps the FA1-assembled flat AllegianceMemberRecord list directly (AllegianceTree was deleted at FA1 -- nothing left to wrap). Both apply the full 8-edit J-owner template: construction + fault points + Owner/View properties + CaptureOwnership + a new GameRuntimeTeardownStage pair (FellowshipDisposed/AllegianceDisposed, stage count 11->13) + RuntimeGameplayOwnershipSnapshot inclusion + RuntimeStateCheckpoint/trace fields. IRuntimeFellowshipCommands/ IRuntimeAllegianceCommands added to IGameRuntimeCommands and implemented on DirectGameRuntimeCommandAdapter. No IRuntimeEventObserver member added (D2) -- consumers poll Snapshot.Revision. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
1c40104896
commit
369729f06a
19 changed files with 1949 additions and 35 deletions
|
|
@ -32,15 +32,23 @@ public enum RuntimeGenerationResetStage
|
|||
Friends = 9,
|
||||
Squelch = 10,
|
||||
NegotiatedChannels = 11,
|
||||
BeginEntityRetirement = 12,
|
||||
RetireEntities = 13,
|
||||
DrainHostProjection = 14,
|
||||
CompleteCanonicalEntities = 15,
|
||||
CompleteHostProjection = 16,
|
||||
ChatIdentity = 17,
|
||||
PlayerSnapshots = 18,
|
||||
PlayerIdentity = 19,
|
||||
Complete = 20,
|
||||
/// <summary>
|
||||
/// Campaign FA slice FA2 (2026-08-12): the fellowship roster is
|
||||
/// session-scoped (a disconnect drops you from the fellowship
|
||||
/// server-side) — clear it here, alongside the other social-list
|
||||
/// stages. Allegiance is deliberately NOT a reset stage — it survives
|
||||
/// reconnect (see <see cref="RuntimeAllegianceState"/>'s class doc).
|
||||
/// </summary>
|
||||
Fellowship = 12,
|
||||
BeginEntityRetirement = 13,
|
||||
RetireEntities = 14,
|
||||
DrainHostProjection = 15,
|
||||
CompleteCanonicalEntities = 16,
|
||||
CompleteHostProjection = 17,
|
||||
ChatIdentity = 18,
|
||||
PlayerSnapshots = 19,
|
||||
PlayerIdentity = 20,
|
||||
Complete = 21,
|
||||
}
|
||||
|
||||
public readonly record struct RuntimeGenerationResetSnapshot(
|
||||
|
|
@ -88,6 +96,7 @@ public sealed class RuntimeGenerationReset
|
|||
private readonly RuntimeEntityObjectLifetime _entityObjects;
|
||||
private readonly RuntimeCharacterState _character;
|
||||
private readonly RuntimeLocalPlayerIdentityState _identity;
|
||||
private readonly RuntimeFellowshipState _fellowship;
|
||||
private ResetState? _state;
|
||||
private RuntimeGenerationToken _lastCompletedGeneration;
|
||||
private bool _hasCompletedGeneration;
|
||||
|
|
@ -102,7 +111,8 @@ public sealed class RuntimeGenerationReset
|
|||
RuntimeLocalPlayerMovementState movement,
|
||||
RuntimeEntityObjectLifetime entityObjects,
|
||||
RuntimeCharacterState character,
|
||||
RuntimeLocalPlayerIdentityState identity)
|
||||
RuntimeLocalPlayerIdentityState identity,
|
||||
RuntimeFellowshipState fellowship)
|
||||
{
|
||||
_transit = transit ?? throw new ArgumentNullException(nameof(transit));
|
||||
_communication = communication
|
||||
|
|
@ -118,6 +128,8 @@ public sealed class RuntimeGenerationReset
|
|||
?? throw new ArgumentNullException(nameof(character));
|
||||
_identity = identity
|
||||
?? throw new ArgumentNullException(nameof(identity));
|
||||
_fellowship = fellowship
|
||||
?? throw new ArgumentNullException(nameof(fellowship));
|
||||
}
|
||||
|
||||
public RuntimeGenerationToken? ActiveRetiringGeneration =>
|
||||
|
|
@ -285,6 +297,9 @@ public sealed class RuntimeGenerationReset
|
|||
state,
|
||||
_communication.ResetNegotiatedChannels);
|
||||
break;
|
||||
case RuntimeGenerationResetStage.Fellowship:
|
||||
Advance(state, _fellowship.ResetSession);
|
||||
break;
|
||||
case RuntimeGenerationResetStage.BeginEntityRetirement:
|
||||
_ = _entityObjects.BeginSessionClear();
|
||||
state.Retirements = _entityObjects
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue