using System.Globalization; namespace AcDream.Runtime.World; /// /// Canonical presentation-independent owner of local F751/Position /// correlation and one login/portal reveal generation. The graphical or /// headless host supplies typed destination readiness acknowledgements; /// Runtime owns which teleport sequence, generation, and destination those /// acknowledgements are allowed to advance. /// /// /// Retail ordering follows /// SmartBox::HandlePlayerTeleport @ 0x00452150, /// SmartBox::TeleportPlayer @ 0x00453910, /// SmartBox::UseTime @ 0x00455410, and /// gmSmartBoxUI::EndTeleportAnimation @ 0x004D65A0. Destination /// materialization resumes simulation before the later normal-world viewport /// edge. /// public sealed class RuntimeWorldTransitState : IRuntimePortalView { public static readonly TimeSpan RetailWaitCueDelay = TimeSpan.FromSeconds(5); private readonly Action _log; private readonly Dictionary _bufferedDestinations = []; private RuntimePortalSnapshot _snapshot = RuntimePortalSnapshot.Idle; private long _nextGeneration; private bool _hasLastTeleportStart; private ushort _lastTeleportStartSequence; private bool _hasPendingTeleportStart; private ushort _pendingTeleportStartSequence; private bool _teleportActive; private ushort _activeTeleportSequence; private bool _destinationAccepted; private bool _hasAcceptedDestination; private RuntimeTeleportDestination _acceptedDestination; public RuntimeWorldTransitState(Action? log = null) { _log = log ?? (_ => { }); } public RuntimePortalSnapshot Snapshot => _snapshot; public bool IsWorldSimulationAvailable => _snapshot.WorldSimulationAvailable; public bool IsTeleportActive => _teleportActive; public ushort ActiveTeleportSequence => _teleportActive ? _activeTeleportSequence : (ushort)0; public bool HasPendingTeleportStart => _hasPendingTeleportStart; public bool HasAcceptedTeleportDestination => _hasAcceptedDestination; public int BufferedTeleportDestinationCount => _bufferedDestinations.Count; public int DiagnosticFailureCount { get; private set; } public Exception? LastDiagnosticFailure { get; private set; } /// /// Starts initial-login reveal. Portal reveals must instead claim the /// exact F751-correlated destination through /// . /// public long BeginLoginReveal(uint destinationCell) => BeginRevealCore(RuntimePortalKind.Login, destinationCell); /// /// Atomically claims the one accepted Position paired with the active F751 /// sequence and starts its reveal generation. /// public bool TryBeginPortalReveal( ushort teleportSequence, uint destinationCell, out long generation) { generation = 0; if (!_teleportActive || teleportSequence != _activeTeleportSequence || !_hasAcceptedDestination) { LogRejected( "portal-begin-without-destination", $"active={_teleportActive} " + $"expectedSequence={_activeTeleportSequence} " + $"actualSequence={teleportSequence} " + $"accepted={_hasAcceptedDestination}"); return false; } RuntimeTeleportDestination destination = _acceptedDestination; if (destination.TeleportSequence != teleportSequence || destination.CellId == 0u || destination.CellId != destinationCell) { FailInvariant( "portal-begin-destination-mismatch", $"sequence={teleportSequence} " + $"acceptedSequence={destination.TeleportSequence} " + $"expectedCell=0x{destination.CellId:X8} " + $"actualCell=0x{destinationCell:X8}"); return false; } generation = BeginRevealCore( RuntimePortalKind.Portal, destinationCell); _hasAcceptedDestination = false; _acceptedDestination = default; return true; } private long BeginRevealCore( RuntimePortalKind kind, uint destinationCell) { if (kind is RuntimePortalKind.None) throw new ArgumentOutOfRangeException(nameof(kind)); if (destinationCell == 0u) throw new ArgumentOutOfRangeException(nameof(destinationCell)); if (_snapshot.Generation != 0 && !_snapshot.Cancelled && !_snapshot.WorldViewportObserved) { Log("superseded", _snapshot); } long generation = checked(++_nextGeneration); int failures = _snapshot.InvariantFailureCount; int materializations = _snapshot.PortalMaterializationCount; _snapshot = new RuntimePortalSnapshot( generation, kind, new RuntimeDestinationReadiness( generation, destinationCell, IsIndoor: IsIndoor(destinationCell), IsUnhydratable: false, RequiredRenderRadius: 0, IsRenderNeighborhoodReady: false, AreCompositeTexturesReady: false, IsCollisionReady: false), Materialized: false, Completed: false, Cancelled: false, WorldViewportObserved: false, WorldSimulationAvailable: false, InvariantFailureCount: failures, WaitCueShown: false, PortalMaterializationCount: materializations); Log("begin", _snapshot); return generation; } /// /// Returns whether an F751 sequence is newer than this transit owner's /// already-observed notification history. Canonical player TELEPORT_TS is /// checked independently by the Runtime entity/physics owner. /// public bool CanQueueTeleportStart(ushort sequence) => !_hasLastTeleportStart || IsNewer(_lastTeleportStartSequence, sequence); /// /// Records one fresh F751 notification without advancing canonical /// TELEPORT_TS. Presentation activation is a separate host edge. /// public bool TryQueueTeleportStart(ushort sequence) { if (!CanQueueTeleportStart(sequence)) return false; PruneDestinationsOlderThan(sequence); _teleportActive = false; _activeTeleportSequence = 0; _hasPendingTeleportStart = true; _pendingTeleportStartSequence = sequence; _hasLastTeleportStart = true; _lastTeleportStartSequence = sequence; _destinationAccepted = false; _hasAcceptedDestination = false; _acceptedDestination = default; return true; } /// /// Promotes the queued F751 lifetime once its host can enter portal space. /// A Position accepted before that host edge becomes the same active /// destination; no position or physics state is applied here. /// public bool ActivateQueuedTeleport() { if (!_hasPendingTeleportStart) return false; _teleportActive = true; _activeTeleportSequence = _pendingTeleportStartSequence; _hasPendingTeleportStart = false; _pendingTeleportStartSequence = 0; _destinationAccepted = false; _hasAcceptedDestination = false; _acceptedDestination = default; if (!_bufferedDestinations.Remove( _activeTeleportSequence, out RuntimeTeleportDestination buffered)) { return true; } _destinationAccepted = true; _hasAcceptedDestination = true; _acceptedDestination = buffered; return true; } /// /// Offers a destination only after canonical Runtime physics has accepted /// and applied its Position packet. Ordinary, non-advancing movement can /// never become a future portal destination. /// public bool OfferTeleportDestination( in RuntimeTeleportDestination destination, bool teleportTimestampAdvanced) { ushort sequence = destination.TeleportSequence; if (destination.CellId == 0u) return false; if (teleportTimestampAdvanced) PruneDestinationsOlderThan(sequence); if (_teleportActive && sequence == _activeTeleportSequence) { if (_destinationAccepted) return false; _destinationAccepted = true; _hasAcceptedDestination = true; _acceptedDestination = destination; return true; } if (_hasPendingTeleportStart && sequence == _pendingTeleportStartSequence) { _bufferedDestinations.TryAdd(sequence, destination); return false; } ushort correlationSequence = _hasPendingTeleportStart ? _pendingTeleportStartSequence : _activeTeleportSequence; bool mayBelongToFutureStart = (!_teleportActive && !_hasPendingTeleportStart) || IsNewer(correlationSequence, sequence); if (!teleportTimestampAdvanced || !mayBelongToFutureStart) return false; _bufferedDestinations.TryAdd(sequence, destination); return false; } public bool TryGetAcceptedTeleportDestination( out RuntimeTeleportDestination destination) { destination = _acceptedDestination; return _teleportActive && _hasAcceptedDestination; } /// /// Read-only preflight used immediately before the host mutates its /// presentation placement. The post-placement acknowledgement repeats the /// same exact validation. /// public bool CanPlacePortalDestination( long generation, ushort teleportSequence, uint destinationCell) => IsCurrentPortalDestination( generation, teleportSequence, destinationCell); /// /// Ends one graphical/headless portal consumer while preserving /// duplicate/reorder history for the current network session. /// public void EndTeleport() { _teleportActive = false; _activeTeleportSequence = 0; _hasPendingTeleportStart = false; _pendingTeleportStartSequence = 0; _destinationAccepted = false; _hasAcceptedDestination = false; _acceptedDestination = default; } public bool AcknowledgeDestinationReadiness( in RuntimeDestinationReadiness acknowledgement) { if (!ValidateActive( acknowledgement.Generation, acknowledgement.DestinationCell, "readiness")) { return false; } if (_snapshot.Readiness.IsReady) return false; bool isIndoor = IsIndoor(acknowledgement.DestinationCell); int requiredRenderRadius = isIndoor ? 0 : 1; if (acknowledgement.IsIndoor != isIndoor || acknowledgement.RequiredRenderRadius != requiredRenderRadius) { FailInvariant( "invalid-readiness-shape", $"indoor={acknowledgement.IsIndoor} " + $"expectedIndoor={isIndoor} " + $"radius={acknowledgement.RequiredRenderRadius} " + $"expectedRadius={requiredRenderRadius}"); return false; } if (_snapshot.Readiness == acknowledgement) return false; _snapshot = _snapshot with { Readiness = acknowledgement }; Log("readiness", _snapshot); return true; } public bool AcknowledgePortalMaterialized( long generation, ushort teleportSequence, uint destinationCell) { if (!IsCurrentPortalDestination( generation, teleportSequence, destinationCell)) { LogRejected( "materialized-portal-mismatch", $"generation={generation} " + $"sequence={teleportSequence} " + $"cell=0x{destinationCell:X8}"); return false; } if (!ValidateActive(generation, destinationCell, "materialized")) return false; if (_snapshot.Materialized) return false; if (!_snapshot.Readiness.IsReady) { FailInvariant("materialized-before-ready", null); return false; } int count = _snapshot.PortalMaterializationCount; if (_snapshot.Kind == RuntimePortalKind.Portal) count = checked(count + 1); _snapshot = _snapshot with { Materialized = true, WorldSimulationAvailable = true, PortalMaterializationCount = count, }; Log("materialized", _snapshot); return true; } public bool AcknowledgeWorldViewportVisible(long generation) { if (!ValidateGeneration( generation, "world-visible", allowCompleted: true)) { return false; } if (_snapshot.WorldViewportObserved) return false; if (!_snapshot.Readiness.IsReady) { FailInvariant("viewport-before-ready", null); return false; } _snapshot = _snapshot with { WorldViewportObserved = true }; Log("world-visible", _snapshot); return true; } public bool ObserveWait(long generation, TimeSpan elapsed) { if (generation == 0 || generation != _snapshot.Generation || _snapshot.Cancelled || _snapshot.Completed || elapsed < RetailWaitCueDelay) { return false; } if (!_snapshot.WaitCueShown) { _snapshot = _snapshot with { WaitCueShown = true }; SafeLog( $"[world-reveal] event=wait-cue " + $"elapsedMs={elapsed.TotalMilliseconds:F0} " + Describe(_snapshot)); } return true; } public bool Complete(long generation) { if (!ValidateGeneration( generation, "complete", allowCompleted: true)) { return false; } if (_snapshot.Completed) return false; if (!_snapshot.Readiness.IsReady) { FailInvariant("complete-before-ready", null); return false; } if (_snapshot.Kind == RuntimePortalKind.Portal && !_snapshot.Materialized) { FailInvariant("portal-complete-before-materialized", null); return false; } _snapshot = _snapshot with { Completed = true, WorldSimulationAvailable = true, }; Log("complete", _snapshot); return true; } public bool Cancel(long generation) { if (generation == 0 || generation != _snapshot.Generation || _snapshot.Cancelled || _snapshot.Completed) { return false; } _snapshot = _snapshot with { Cancelled = true, WorldSimulationAvailable = true, }; Log("cancel", _snapshot); return true; } /// /// Clears session-visible state while retaining the monotonically /// increasing generation counter so a delayed prior-session host /// acknowledgement cannot match a future generation. /// public void ResetSession() { _snapshot = RuntimePortalSnapshot.Idle; EndTeleport(); _hasLastTeleportStart = false; _lastTeleportStartSequence = 0; _bufferedDestinations.Clear(); } private bool IsCurrentPortalDestination( long generation, ushort teleportSequence, uint destinationCell) => _teleportActive && teleportSequence == _activeTeleportSequence && generation != 0 && generation == _snapshot.Generation && _snapshot.Kind == RuntimePortalKind.Portal && !_snapshot.Cancelled && !_snapshot.Completed && destinationCell != 0u && destinationCell == _snapshot.DestinationCell; private bool ValidateActive( long generation, uint destinationCell, string eventName) { if (!ValidateGeneration( generation, eventName, allowCompleted: false)) { return false; } if (destinationCell == 0u || destinationCell != _snapshot.DestinationCell) { FailInvariant( $"{eventName}-destination-mismatch", $"expected=0x{_snapshot.DestinationCell:X8} " + $"actual=0x{destinationCell:X8}"); return false; } return true; } private bool ValidateGeneration( long generation, string eventName, bool allowCompleted) { if (generation == 0 || generation != _snapshot.Generation) { LogRejected( $"{eventName}-generation-mismatch", $"expected={_snapshot.Generation} actual={generation}"); return false; } if (_snapshot.Cancelled || (!allowCompleted && _snapshot.Completed)) { LogRejected( $"{eventName}-after-terminal", $"completed={_snapshot.Completed} " + $"cancelled={_snapshot.Cancelled}"); return false; } return true; } private void FailInvariant(string reason, string? detail) { _snapshot = _snapshot with { InvariantFailureCount = checked(_snapshot.InvariantFailureCount + 1), }; string suffix = string.IsNullOrWhiteSpace(detail) ? string.Empty : $" {detail}"; SafeLog( $"[world-reveal] event=invariant-failure " + $"reason={reason}{suffix} {Describe(_snapshot)}"); } private void LogRejected(string reason, string? detail) { string suffix = string.IsNullOrWhiteSpace(detail) ? string.Empty : $" {detail}"; SafeLog( $"[world-reveal] event=rejected " + $"reason={reason}{suffix} {Describe(_snapshot)}"); } private void Log(string eventName, RuntimePortalSnapshot snapshot) => SafeLog($"[world-reveal] event={eventName} {Describe(snapshot)}"); private void SafeLog(string message) { try { _log(message); } catch (Exception error) { DiagnosticFailureCount = checked(DiagnosticFailureCount + 1); LastDiagnosticFailure = error; } } private static string Describe(RuntimePortalSnapshot snapshot) { RuntimeDestinationReadiness ready = snapshot.Readiness; return string.Create( CultureInfo.InvariantCulture, $"generation={snapshot.Generation} kind={snapshot.Kind} " + $"cell=0x{ready.DestinationCell:X8} " + $"indoor={ready.IsIndoor} " + $"radius={ready.RequiredRenderRadius} " + $"unhydratable={ready.IsUnhydratable} " + $"render={ready.IsRenderNeighborhoodReady} " + $"composites={ready.AreCompositeTexturesReady} " + $"collision={ready.IsCollisionReady} ready={ready.IsReady} " + $"materialized={snapshot.Materialized} " + $"completed={snapshot.Completed} " + $"cancelled={snapshot.Cancelled} " + $"visible={snapshot.WorldViewportObserved} " + $"simulation={snapshot.WorldSimulationAvailable} " + $"failures={snapshot.InvariantFailureCount}"); } private static bool IsNewer(ushort current, ushort incoming) => AcDream.Core.Physics.PhysicsTimestampGate.IsNewer( current, incoming); private void PruneDestinationsOlderThan(ushort sequence) { foreach (ushort bufferedSequence in _bufferedDestinations.Keys.ToArray()) { if (IsNewer(bufferedSequence, sequence)) _bufferedDestinations.Remove(bufferedSequence); } } private static bool IsIndoor(uint cellId) => (cellId & 0xFFFFu) >= 0x0100u; }