diff --git a/Runtime/Backends/P2PBackrollSession.cs b/Runtime/Backends/P2PBackrollSession.cs index d3624ddf..b209a78f 100644 --- a/Runtime/Backends/P2PBackrollSession.cs +++ b/Runtime/Backends/P2PBackrollSession.cs @@ -46,23 +46,6 @@ public unsafe class P2PBackrollSession : BackrollSession where T : struct BackrollSessionCallbacks _callbacks; Sync _sync; - public bool IsSynchronizing { - get { - for (var i = 0; i < _players.Length; i++) { - if (!_players[i].IsLocal && !_players[i].IsSynchronized && - !_localConnectStatus[i].Disconnected) { - return false; - } - } - for (var i = 0; i < _spectators.Length; i++) { - if (!_spectators[i].IsLocal && !_spectators[i].IsSynchronized) { - return false; - } - } - return true; - } - } - int _next_recommended_sleep; int _next_spectator_frame; @@ -76,6 +59,17 @@ public P2PBackrollSession(BackrollSessionConfig config) { _callbacks = config.Callbacks; + _players = InitializeConnections(config.Players); + _spectators = InitializeConnections(config.Spectators); + + _localConnectStatus = new BackrollConnectStatus[PlayerCount]; + for (int i = 0; i < _localConnectStatus.Length; i++) { + _localConnectStatus[i].LastFrame = -1; + } + + SetupConnections(_players); + SetupConnections(_spectators); + // Initialize the synchronziation layer _sync = new Sync(_localConnectStatus, new Sync.Config { NumPlayers = config.Players.Length, @@ -83,16 +77,7 @@ public P2PBackrollSession(BackrollSessionConfig config) { Callbacks = _callbacks, NumPredictionFrames = BackrollConstants.kMaxPredictionFrames, }); - - _localConnectStatus = new BackrollConnectStatus[PlayerCount]; - for (int i = 0; i < _localConnectStatus.Length; i++) { - unchecked { - _localConnectStatus[i].LastFrame = ~0; - } - } - - _players = InitializeConnections(config.Players); - _spectators = InitializeConnections(config.Spectators); + } BackrollConnection[] InitializeConnections(LobbyMember[] members) { @@ -100,13 +85,20 @@ BackrollConnection[] InitializeConnections(LobbyMember[] members) { var connections = new BackrollConnection[members.Length]; for (var i = 0; i < connections.Length; i++) { var connection = new BackrollConnection(members[i], i, _localConnectStatus); + connections[i] = connection; + } + return connections; + } + + void SetupConnections(BackrollConnection[] connections) { + for (var i = 0; i < connections.Length; i++) { + ref BackrollConnection connection = ref connections[i]; SetupConnection(connection); connection.SetDisconnectTimeout((uint)DEFAULT_DISCONNECT_TIMEOUT); connection.SetDisconnectNotifyStart((uint)DEFAULT_DISCONNECT_NOTIFY_START); connection.Synchronize(); connections[i] = connection; } - return connections; } void UpdateConnections() { @@ -119,7 +111,8 @@ void UpdateConnections() { } public override void Idle(int timeout) { - if (_sync.InRollback || IsSynchronizing) return; + + if (_sync.InRollback) return; UpdateConnections(); _sync.CheckSimulation(timeout); @@ -137,12 +130,12 @@ public override void Idle(int timeout) { minFrame = PollNPlayers(current_frame); } - Debug.LogFormat("last confirmed frame in p2p backend is {}.", minFrame); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("last confirmed frame in p2p backend is {0}.", minFrame); if (minFrame >= 0) { Assert.IsTrue(minFrame != int.MaxValue); if (SpectatorCount > 0) { while (_next_spectator_frame <= minFrame) { - Debug.LogFormat("pushing frame {} to spectators.", _next_spectator_frame); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("pushing frame {0} to spectators.", _next_spectator_frame); GameInput input; input.Frame = _next_spectator_frame; @@ -154,7 +147,7 @@ public override void Idle(int timeout) { _next_spectator_frame++; } } - Debug.LogFormat("setting confirmed frame in sync to {}.", minFrame); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("setting confirmed frame in sync to {0}.", minFrame); _sync.SetLastConfirmedFrame(minFrame); } @@ -185,17 +178,18 @@ protected int Poll2Players(int current_frame) { int ignore = 0; connected = _players[i].GetPeerConnectStatus(i, ref ignore); } + if (!_localConnectStatus[i].Disconnected) { minFrame = (int)Math.Min(_localConnectStatus[i].LastFrame, minFrame); } - Debug.LogFormat(" local endp: connected = {}, last_received = {}, minFrame = {}.", + if (Backroll.LOG_BACKROLL) Debug.LogFormat(" local endp: connected = {0}, last_received = {1}, minFrame = {2}.", !_localConnectStatus[i].Disconnected, _localConnectStatus[i].LastFrame, minFrame); if (!connected && !_localConnectStatus[i].Disconnected) { - Debug.LogFormat("disconnecting i {} by remote request.", i); + Debug.LogFormat("disconnecting i {0} by remote request.", i); DisconnectPlayerQueue(i, minFrame); } - Debug.LogFormat(" minFrame = {}.", minFrame); + if (Backroll.LOG_BACKROLL) Debug.LogFormat(" minFrame = {0}.", minFrame); } return minFrame; } @@ -208,7 +202,7 @@ protected int PollNPlayers(int current_frame) { for (var queue = 0; queue < PlayerCount; queue++) { bool connected = true; int minConfirmed = Int32.MaxValue; - Debug.LogFormat("considering queue {}.", queue); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("considering queue {0}.", queue); for (var i = 0; i < _players.Length; i++) { // we're going to do a lot of logic here in consideration of endpoint i. // keep accumulating the minimum confirmed point for all n*n packets and @@ -217,17 +211,17 @@ protected int PollNPlayers(int current_frame) { bool peer_connected = _players[i].GetPeerConnectStatus(queue, ref last_received); connected = connected && peer_connected; minConfirmed = Mathf.Min(last_received, minConfirmed); - Debug.Log( + if (Backroll.LOG_BACKROLL) Debug.Log( $" endpoint {i}: connected = {connected}, last_received = {last_received}, minConfirmed = {minConfirmed}."); } else { - Debug.Log($" endpoint {i}: ignoring... not running."); + if (Backroll.LOG_BACKROLL) Debug.Log($" endpoint {i}: ignoring... not running."); } } // merge in our local status only if we're still connected! if (!_localConnectStatus[queue].Disconnected) { minConfirmed = (int)Math.Min(_localConnectStatus[queue].LastFrame, minConfirmed); } - Debug.LogFormat(" local endp: connected = {}, last_received = {}, minConfirmed = {}.", + if (Backroll.LOG_BACKROLL) Debug.LogFormat(" local endp: connected = {0}, last_received = {1}, minConfirmed = {2}.", !_localConnectStatus[queue].Disconnected, _localConnectStatus[queue].LastFrame, minConfirmed); if (connected) { @@ -237,11 +231,11 @@ protected int PollNPlayers(int current_frame) { // so, we need to re-adjust. This can happen when we detect our own disconnect at frame n // and later receive a disconnect notification for frame n-1. if (!_localConnectStatus[queue].Disconnected || _localConnectStatus[queue].LastFrame > minConfirmed) { - Debug.LogFormat("disconnecting queue {} by remote request.", queue); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("disconnecting queue {0} by remote request.", queue); DisconnectPlayerQueue(queue, minConfirmed); } } - Debug.LogFormat(" minFrame = {}.", minFrame); + if (Backroll.LOG_BACKROLL) Debug.LogFormat(" minFrame = {0}.", minFrame); } return minFrame; } @@ -252,17 +246,18 @@ public override void AddLocalInput(BackrollPlayerHandle player, GameInput input; if (_sync.InRollback) { + // Debug.Log("BackrollException: InRollback"); + // return; throw new BackrollException(BackrollErrorCode.InRollback); } - if (IsSynchronizing) { - throw new BackrollException(BackrollErrorCode.NotSynchronized); - } queue = PlayerHandleToQueue(player); input = GameInput.Create(GameInput.kNullFrame, ref playerInput); // Feed the input for the current frame into the synchronzation layer. if (!_sync.AddLocalInput(queue, ref input)) { + // Debug.Log("BackrollException PredictionThreshold"); + // return; throw new BackrollException(BackrollErrorCode.PredictionThreshold); } @@ -272,7 +267,7 @@ public override void AddLocalInput(BackrollPlayerHandle player, // confirmed local frame for this player. this must come first so it // gets incorporated into the next packet we send. - Debug.LogFormat("setting local connect status for local queue {} to {}", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("setting local connect status for local queue {0} to {1}", queue, input.Frame); _localConnectStatus[queue].LastFrame = input.Frame; @@ -286,14 +281,11 @@ public override void AddLocalInput(BackrollPlayerHandle player, public override int SyncInput(void *values, int size) { // Wait until we've started to return inputs. - if (IsSynchronizing) { - throw new BackrollException(BackrollErrorCode.NotSynchronized); - } return _sync.SynchronizeInputs(values, size); } public override void AdvanceFrame() { - Debug.LogFormat("End of frame ({})...", _sync.FrameCount); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("End of frame ({0})...", _sync.FrameCount); _sync.IncrementFrame(); Idle(0); } @@ -310,28 +302,46 @@ static int GetIndex(INetworkReciever reciever, BackrollConnection[] connections) void SetupConnection(BackrollConnection connection) { var member = connection.LobbyMember; var queue = GetIndex(connection.LobbyMember, _players); - member.OnDisconnected += () => { - if (queue >= 0) { - DisconnectPlayer(QueueToPlayerHandle(queue)); - } - var spectator = GetIndex(member, _spectators); - if (spectator >= 0) { - _spectators[spectator].Disconnect(); - } - }; + + Action action = new Action(() => + { + if (queue >= 0) + { + try + { + DisconnectPlayer(QueueToPlayerHandle(queue)); + } + catch (BackrollException e) + { + Debug.Log(e.Message); + } + + } + var spectator = GetIndex(member, _spectators); + if (spectator >= 0) + { + _spectators[spectator].Disconnect(); + } + }); + member.OnDisconnected += action; + if (queue < 0) return ; var handle = QueueToPlayerHandle(queue); connection.OnInput += (input) => { if (_localConnectStatus[queue].Disconnected) return; int current_remote_frame = _localConnectStatus[queue].LastFrame; int new_remote_frame = input.Frame; + + if (Backroll.LOG_BACKROLL) Debug.Log($"[BackrollConnection][Nibblet][Read] Use Me! Remote Frame {new_remote_frame}, Last Frame {current_remote_frame}"); Assert.IsTrue(current_remote_frame == -1 || new_remote_frame == (current_remote_frame + 1)); _sync.AddRemoteInput(queue, ref input); // Notify the other endpoints which frame we received from a peer - Debug.LogFormat("setting remote connect status for queue {} to {}", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("setting remote connect status for queue {0} to {1}", queue, new_remote_frame); _localConnectStatus[queue].LastFrame = new_remote_frame; + + if (Backroll.LOG_BACKROLL) Debug.Log($"[BackrollConnection][Nibblet][Read] Use Me! New Remote Frame {_localConnectStatus[queue].LastFrame}"); }; connection.OnSynchronizing += (total, count) => { @@ -367,16 +377,21 @@ void SetupConnection(BackrollConnection connection) { // blob in every endpoint periodically. public override void DisconnectPlayer(BackrollPlayerHandle player) { int queue = PlayerHandleToQueue(player); - if (_localConnectStatus[queue].Disconnected) { - throw new BackrollException(BackrollErrorCode.PlayerDisconnected); + // Note that throwing error code will pause execution. Have to make sure that + // Debug.Log("BackrollException: Player Disconnected"); + // return; + // I re-enabled the exception after adding a try catch in other parts of the code. + // Note that any exception occuring is not good and something we need to make sure we either fix or + // handle since it might have weird issues. + throw new BackrollException(BackrollErrorCode.PlayerDisconnected); } if (_players[queue].IsLocal) { int current_frame = _sync.FrameCount; // xxx: we should be tracking who the local player is, but for now assume // that if the endpoint is not initalized, this must be the local player. - Debug.LogFormat("Disconnecting local player {} at frame {} by user request.", + Debug.LogFormat("Disconnecting local player {0} at frame {1} by user request.", queue, _localConnectStatus[queue].LastFrame); for (int i = 0; i < PlayerCount; i++) { if (!_players[i].IsLocal) { @@ -384,7 +399,7 @@ public override void DisconnectPlayer(BackrollPlayerHandle player) { } } } else { - Debug.LogFormat("Disconnecting queue {} at frame {} by user request.", + Debug.LogFormat("Disconnecting queue {0} at frame {1} by user request.", queue, _localConnectStatus[queue].LastFrame); DisconnectPlayerQueue(queue, _localConnectStatus[queue].LastFrame); } @@ -395,14 +410,14 @@ protected void DisconnectPlayerQueue(int queue, int syncto) { _players[queue].Disconnect(); - Debug.LogFormat("Changing queue {} local connect status for last frame from {} to {} on disconnect request (current: {}).", + Debug.LogFormat("Changing queue {0} local connect status for last frame from {1} to {2} on disconnect request (current: {3}).", queue, _localConnectStatus[queue].LastFrame, syncto, framecount); _localConnectStatus[queue].Disconnected = true; _localConnectStatus[queue].LastFrame = syncto; if (syncto < framecount) { - Debug.LogFormat("adjusting simulation to account for the fact that {} Disconnected @ {}.", queue, syncto); + Debug.LogFormat("adjusting simulation to account for the fact that {0} Disconnected @ {1}.", queue, syncto); _sync.AdjustSimulation(syncto); Debug.LogFormat("finished adjusting simulation."); } @@ -435,6 +450,8 @@ public override void SetDisconnectNotifyStart(int disconnect_notify_start) { protected int PlayerHandleToQueue(BackrollPlayerHandle player) { int offset = ((int)player.Id - 1); if (offset < 0 || offset >= PlayerCount) { + // Debug.Log("BackrollException InvalidPlayerHandle"); + // return offset; throw new BackrollException(BackrollErrorCode.InvalidPlayerHandle); } return offset; diff --git a/Runtime/Backends/SyncTestBackrollSession.cs b/Runtime/Backends/SyncTestBackrollSession.cs index 3ecd8384..e0fed658 100644 --- a/Runtime/Backends/SyncTestBackrollSession.cs +++ b/Runtime/Backends/SyncTestBackrollSession.cs @@ -2,6 +2,7 @@ using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using UnityEngine; +using System.Collections.Generic; namespace HouraiTeahouse.Backroll { @@ -10,8 +11,9 @@ public unsafe class SyncTestsBackrollSession : BackrollSession where T : s unsafe struct SavedInfo { public int Frame; public int Checksum; - public byte* Buffer; - public int Size; + // public byte* Buffer; + // public int Size; + public List GameState; public GameInput Input; }; @@ -35,9 +37,11 @@ public SyncTestsBackrollSession(BackrollSessionConfig config, int frames) { _rollingback = false; _running = false; _current_input.Clear(); + _saved_frames = new RingBuffer(64); _sync = new Sync(null, new Sync.Config { - NumPredictionFrames = BackrollConstants.kMaxPredictionFrames + Callbacks = _callbacks, + NumPredictionFrames = BackrollConstants.kMaxPredictionFrames, }); } @@ -47,7 +51,11 @@ public override void Idle(int timeout) { _running = true; } - public override void AddLocalInput(BackrollPlayerHandle player, ref T input) {} + public override void AddLocalInput(BackrollPlayerHandle player, ref T input) { + GameInput gameInput; + gameInput = GameInput.Create(GameInput.kNullFrame, ref input); + _current_input = gameInput; + } public override int SyncInput(void *values, int size) { if (_rollingback) { @@ -68,9 +76,11 @@ public override void AdvanceFrame() { _sync.IncrementFrame(); _current_input.Clear(); - Debug.Log($"End of frame({_sync.FrameCount})..."); + if (Backroll.LOG_BACKROLL) Debug.Log($"End of frame({_sync.FrameCount})..."); if (_rollingback) return; + + _callbacks.OnLogState("save", new IntPtr(0), _sync.FrameCount); int frame = _sync.FrameCount; // Hold onto the current frame in our queue of saved states. We'll need @@ -79,15 +89,26 @@ public override void AdvanceFrame() { var info = new SavedInfo { Frame = frame, Input = _last_input, - Size = _sync.GetLastSavedFrame().Size, - Buffer = (byte*)UnsafeUtility.Malloc(_sync.GetLastSavedFrame().Size, - UnsafeUtility.AlignOf(), - Allocator.Temp), + // Size = _sync.GetLastSavedFrame().Size, + // Buffer = (byte*)UnsafeUtility.Malloc(_sync.GetLastSavedFrame().Size, + // UnsafeUtility.AlignOf(), + // Allocator.Temp), + GameState = _sync.GetLastSavedFrame().GameState, Checksum = _sync.GetLastSavedFrame().Checksum, }; - UnsafeUtility.MemCpy(info.Buffer, _sync.GetLastSavedFrame().Buffer, info.Size); + // UnsafeUtility.MemCpy(info.Buffer, _sync.GetLastSavedFrame().Buffer, info.Size); + if (info.GameState == null) + { + info.GameState = new List(); + } + else + { + info.GameState = new List(info.GameState); + } + _saved_frames.Push(info); + // frame = current frame in game? if (frame - _last_verified == _check_distance) { // We've gone far enough ahead and should now start replaying frames. // Load the last verified frame and set the rollback flag to true. @@ -107,14 +128,22 @@ public override void AdvanceFrame() { } int Checksum = _sync.GetLastSavedFrame().Checksum; if (info.Checksum != Checksum) { - _callbacks.OnLogState?.Invoke($"Original f{_sync.FrameCount}:", (IntPtr)info.Buffer, info.Size); - _callbacks.OnLogState?.Invoke($"Replay f{_sync.FrameCount}:", (IntPtr)_sync.GetLastSavedFrame().Buffer, - _sync.GetLastSavedFrame().Size); - Debug.LogWarning($"SyncTest: Checksum for frame {frame} does not match saved ({Checksum} != {Checksum})"); - } else { - Debug.Log($"Checksum {Checksum} for frame {info.Frame} matches."); + Debug.LogWarning($"SyncTest: Checksum for frame {frame} does not match saved ({info.Checksum} != {Checksum})"); + + _callbacks.OnLogState("log", new IntPtr(0), frame); + + Debug.Log($"================================= Logging Reloaded Frame { _sync.FrameCount} ================================="); + _callbacks.OnLogState("save", new IntPtr(0), _sync.FrameCount); + _callbacks.OnLogState("log", new IntPtr(0), frame); + + Debug.Log($"================================= Frame Dump Ended ================================="); + + Debug.Break(); + } else { + // Debug.Log($"Checksum {Checksum} for frame {info.Frame} matches: {info.Checksum} and {Checksum}"); } - UnsafeUtility.Free(info.Buffer, Allocator.Temp); + // UnsafeUtility.Free(info.Buffer, Allocator.Temp); + info.GameState = null; } _last_verified = frame; _rollingback = false; diff --git a/Runtime/BackrollConnection.cs b/Runtime/BackrollConnection.cs index a74d3f75..c89d488f 100644 --- a/Runtime/BackrollConnection.cs +++ b/Runtime/BackrollConnection.cs @@ -17,8 +17,27 @@ public bool Disconnected { set => data = (uint)((data & ~1u) | (value ? 1u : 0u)); } public int LastFrame { - get => (int)(data << 1); - set => data = (uint)((data & 1) | (uint)(value << 1)); + // LastFrame is formatted as an uint (after throwing out the first bit) unless... + // if all bits are set, then it represents -1 (the initial frame number). + get { + if ((data | 1) == ~(uint)0) + { + return -1; + } + else { + return (int) (data >> 1); + } + } + set { + if (value == -1) + { + data = (data & 1) | unchecked ((uint)(~0 << 1)); + } + else + { + data = (data & 1) | (uint)(value << 1); + }; + } } public void Serialize(ref T serializer) where T : struct, ISerializer @@ -52,6 +71,8 @@ public enum MessageCodes : byte { QualityReport = 3, QualityReply = 4, KeepAlive = 5, + SyncRequest = 6, + SyncReply = 7, } [StructLayout(LayoutKind.Explicit, Size=12)] @@ -140,9 +161,20 @@ public BackrollConnection(LobbyMember lobbyMember, int queue, BackrollConnectSta _messageHandlers.RegisterHandler((byte)MessageCodes.QualityReport, OnQualityReport); _messageHandlers.RegisterHandler((byte)MessageCodes.QualityReply, OnQualityReply); _messageHandlers.RegisterHandler((byte)MessageCodes.KeepAlive, OnKeepAlive); + _messageHandlers.RegisterHandler((byte)MessageCodes.SyncRequest, OnSyncRequest); + _messageHandlers.RegisterHandler((byte)MessageCodes.SyncReply, OnSyncReply); _messageHandlers.Listen(LobbyMember); LobbyMember.OnNetworkMessage += OnNetworkMessage; + + // Initializing ack frame to -1 + _last_acked_input.Frame = -1; + + // Initializing LastRecievedFrame to -1 too + _lastRecievedInput.Frame = -1; + + // Setting max encoding size to 1200 for UDP + SerializationConstants.kMaxMessageSize = 1200; } public void Dispose() => _messageHandlers.Dispose(); @@ -151,7 +183,10 @@ public void Synchronize() { if (LobbyMember != null) { _current_state = State.Syncing; _state.Sync.RoundTripsRemaining = NUM_SYNC_PACKETS; - SendSyncRequest(); + + // Steam is always synchronized already! + _current_state = State.Running; + //SendSyncRequest(); } } @@ -192,7 +227,7 @@ public void SendInputAck() { unsafe void Send(in T msg, Reliability reliability = Reliability.Unreliable) where T : struct, ISerializable { - Span buffer = stackalloc byte[SerializationConstants.kMaxMessageSize]; + Span buffer = stackalloc byte[HouraiTeahouse.Serialization.SerializationConstants.kMaxMessageSize]; var serializer = FixedSizeSerializer.Create(buffer); _messageHandlers.Serialize(msg, ref serializer); @@ -258,22 +293,32 @@ protected void SendPendingOutput() { msg.StartFrame = _pending_output.Peek().Frame; msg.InputSize = _pending_output.Peek().Size; + if (Backroll.LOG_BACKROLL) Debug.Log($"[BackrollConnection] Last: {last.Frame}, StartFrame: {msg.StartFrame}"); Assert.IsTrue(last.Frame == -1 || last.Frame + 1 == msg.StartFrame); - for (var j = 0; j < _pending_output.Size; j++) { + for (var j = 0; j < _pending_output.Size; j++) + { ref GameInput current = ref _pending_output[j]; + if (Backroll.LOG_BACKROLL) Debug.Log($"[BackrollConnection] Encoding frame {current.Frame}"); fixed (byte* currentPtr = current.bits) { - if (UnsafeUtility.MemCmp(currentPtr, last.bits, current.Size) == 0) continue; - } - for (var i = 0; i < current.Size * 8; i++) { - Assert.IsTrue(i < (1 << BitVector.kNibbleSize)); - if (current[i] == last[i]) continue; - BitVector.SetBit(msg.bits, ref offset); - if (current[i]) { - BitVector.SetBit(msg.bits, ref offset); - } else { - BitVector.ClearBit(msg.bits, ref offset); - } - BitVector.WriteNibblet(msg.bits, i, ref offset); + if (UnsafeUtility.MemCmp(currentPtr, last.bits, current.Size) != 0) + { + for (var i = 0; i < current.Size * 8; i++) + { + Assert.IsTrue(i < (1 << BitVector.kNibbleSize)); + if (current[i] == last[i]) continue; + BitVector.SetBit(msg.bits, ref offset); + if (current[i]) + { + BitVector.SetBit(msg.bits, ref offset); + } + else + { + BitVector.ClearBit(msg.bits, ref offset); + } + BitVector.WriteNibblet(msg.bits, i, ref offset); + if (Backroll.LOG_BACKROLL) Debug.Log($"[BackrollConnection][Nibblet][Set] Nibblet Set! Frame {j + msg.StartFrame}, Bit: {i}, On: {current[i]}"); + } + } } BitVector.ClearBit(msg.bits, ref offset); last = _lastSentInput = current; @@ -292,6 +337,7 @@ protected void SendPendingOutput() { UnsafeUtility.MemClear(msg.connect_status, size); } + if (Backroll.LOG_BACKROLL) Debug.LogFormat($"[BackrollConnection][Ack] SendAckFrame {msg.AckFrame}"); Assert.IsTrue(offset < InputMessage.kMaxCompressedBits); Send(msg); } @@ -304,7 +350,7 @@ public void Update() { case State.Syncing: int next_interval = (_state.Sync.RoundTripsRemaining == NUM_SYNC_PACKETS) ? SYNC_FIRST_RETRY_INTERVAL : SYNC_RETRY_INTERVAL; if (_lastSendTime != 0 && _lastSendTime + next_interval < now) { - Debug.LogFormat("No luck syncing after {} ms... Resending sync packet.", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("No luck syncing after {0} ms... Resending sync packet.", next_interval); SendSyncRequest(); } @@ -314,7 +360,7 @@ public void Update() { // xxx: rig all this up with a timer wrapper if (_state.Running.LastInputPacketRecieveTime == 0|| _state.Running.LastInputPacketRecieveTime + RUNNING_RETRY_INTERVAL < now) { - Debug.LogFormat("Haven't exchanged packets in a while (last received:{} last sent:{}). Resending.", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("Haven't exchanged packets in a while (last received:{0} last sent:{1}). Resending.", _lastRecievedInput.Frame, _lastSentInput.Frame); SendPendingOutput(); _state.Running.LastInputPacketRecieveTime = now; @@ -337,13 +383,13 @@ public void Update() { if (_lastSendTime == 0 && _lastSendTime + KEEP_ALIVE_INTERVAL < now) { - Debug.Log("Sending keep alive packet"); + if (Backroll.LOG_BACKROLL) Debug.Log("Sending keep alive packet"); Send(new KeepAliveMessage()); } if (_disconnectTimeout != 0 && _disconnectNotifyStart != 0 && !_disconnect_notify_sent && (_lastReceiveTime + _disconnectNotifyStart < now)) { - Debug.LogFormat("Endpoint has stopped receiving packets for {} ms. Sending notification.", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("Endpoint has stopped receiving packets for {0} ms. Sending notification.", _disconnectNotifyStart); uint disconnectTimeout = _disconnectTimeout - _disconnectNotifyStart; OnNetworkInterrupted?.Invoke(disconnectTimeout); @@ -352,7 +398,7 @@ public void Update() { if (_disconnectTimeout != 0 && (_lastReceiveTime + _disconnectTimeout < now)) { if (!_disconnect_event_sent) { - Debug.LogFormat("Endpoint has stopped receiving packets for {} ms. Disconnecting.", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("Endpoint has stopped receiving packets for {0} ms. Disconnecting.", _disconnectTimeout); OnDisconnected?.Invoke(); _disconnect_event_sent = true; @@ -362,7 +408,7 @@ public void Update() { case State.Disconnected: if (_shutdown_timeout < now) { - Debug.Log("Shutting down udp connection."); + if (Backroll.LOG_BACKROLL) Debug.Log("Shutting down udp connection."); LobbyMember = null; _shutdown_timeout = 0; } @@ -378,12 +424,12 @@ void OnSyncRequest(ref SyncRequestMessage msg) { void OnSyncReply(ref SyncReplyMessage msg) { if (_current_state != State.Syncing) { - Debug.Log("Ignoring SyncReply while not synching."); + if (Backroll.LOG_BACKROLL) Debug.Log("Ignoring SyncReply while not synching."); return; } if (msg.RandomReply != _state.Sync.Random) { - Debug.LogFormat("sync reply {} != {}. Keep looking...", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("sync reply {0} != {1}. Keep looking...", msg.RandomReply, _state.Sync.Random); return; } @@ -393,10 +439,10 @@ void OnSyncReply(ref SyncReplyMessage msg) { _connected = true; } - Debug.LogFormat("Checking sync state ({} round trips remaining).", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("Checking sync state ({0} round trips remaining).", _state.Sync.RoundTripsRemaining); if (--_state.Sync.RoundTripsRemaining == 0) { - Debug.Log("Synchronized!"); + if (Backroll.LOG_BACKROLL) Debug.Log("Synchronized!"); OnSynchronized?.Invoke(); _current_state = State.Running; _lastRecievedInput.Frame = -1; @@ -409,11 +455,12 @@ void OnSyncReply(ref SyncReplyMessage msg) { } void OnInputMessage(ref InputMessage msg) { + if (Backroll.LOG_BACKROLL) Debug.Log("[BackrollConnection] Recieved Input"); // If a disconnect is requested, go ahead and disconnect now. bool disconnect_requested = msg.DisconnectRequested; if (disconnect_requested) { if (_current_state != State.Disconnected && !_disconnect_event_sent) { - Debug.Log("Disconnecting endpoint on remote request."); + if (Backroll.LOG_BACKROLL) Debug.Log("Disconnecting endpoint on remote request."); OnDisconnected?.Invoke(); _disconnect_event_sent = true; } @@ -448,6 +495,7 @@ void OnInputMessage(ref InputMessage msg) { Assert.IsTrue(currentFrame <= (_lastRecievedInput.Frame + 1)); bool useInputs = currentFrame == _lastRecievedInput.Frame + 1; + if (Backroll.LOG_BACKROLL) Debug.Log($"[BackrollConnection][Nibblet][Read] Use? {useInputs} Frame {currentFrame}, lastRecievedInputFrame {_lastRecievedInput.Frame}"); while (BitVector.ReadBit(ptr, ref offset)) { bool bit = BitVector.ReadBit(ptr, ref offset); int button = BitVector.ReadNibblet(ptr, ref offset); @@ -458,6 +506,7 @@ void OnInputMessage(ref InputMessage msg) { _lastRecievedInput.Clear(button); } } + if (Backroll.LOG_BACKROLL) Debug.Log($"[BackrollConnection][Nibblet][Read] Nibblet Read! Frame {currentFrame}, Bit: {button}, On: {bit}, Offset{offset}"); } Assert.IsTrue(offset <= numBits); @@ -473,10 +522,10 @@ void OnInputMessage(ref InputMessage msg) { _state.Running.LastInputPacketRecieveTime = BackrollTime.GetTime(); - Debug.LogFormat("Sending frame {} to emu queue {} ({}).", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("[BackrollConnection][Nibblet][Read] Sending frame {0} to emu queue {1} ({2}).", _lastRecievedInput.Frame, _queue, _lastRecievedInput); } else { - Debug.LogFormat("Skipping past frame:({}) current is {}.", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("[BackrollConnection][Nibblet][Read] Skipping past frame:({0}) current is {1}.", currentFrame, _lastRecievedInput.Frame); } @@ -486,6 +535,7 @@ void OnInputMessage(ref InputMessage msg) { } } Assert.IsTrue(_lastRecievedInput.Frame >= last_received_frame_number); + if (Backroll.LOG_BACKROLL) Debug.LogFormat($"[BackrollConnection][Ack] GotAckFrame {msg.AckFrame}"); // Get rid of our buffered input FlushOutputs(msg.AckFrame); @@ -498,7 +548,7 @@ void OnInputAck(ref InputAckMessage msg) { void FlushOutputs(int ackFrame) { while (!_pending_output.IsEmpty && _pending_output.Peek().Frame < ackFrame) { - Debug.LogFormat("Throwing away pending output frame {}", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("Throwing away pending output frame {0}", _pending_output.Peek().Frame); _last_acked_input = _pending_output.Peek(); _pending_output.Pop(); @@ -534,7 +584,7 @@ void UpdateNetworkStats() { _kbps_sent = (int)(Bps / 1024); - Debug.LogFormat("Network Stats -- Bandwidth: %.2f KBps Packets Sent: %5d (%.2f pps) " + + if (Backroll.LOG_BACKROLL) Debug.LogFormat("Network Stats -- Bandwidth: %.2f KBps Packets Sent: %5d (%.2f pps) " + "KB Sent: %.2f UDP Overhead: %.2f %%.", _kbps_sent, _packets_sent, diff --git a/Runtime/BackrollConstants.cs b/Runtime/BackrollConstants.cs index 2cd789e3..7532bd7e 100644 --- a/Runtime/BackrollConstants.cs +++ b/Runtime/BackrollConstants.cs @@ -1,7 +1,7 @@ namespace HouraiTeahouse.Backroll { public static class BackrollConstants { - public const int kMaxPlayers = 8; + public const int kMaxPlayers = 2; public const int kMaxPredictionFrames = 8; public const int kMaxSpectators = 32; public const int kSpectatorInputInterval = 4; diff --git a/Runtime/BackrollEvents.cs b/Runtime/BackrollEvents.cs index ce5d0fa3..33788534 100644 --- a/Runtime/BackrollEvents.cs +++ b/Runtime/BackrollEvents.cs @@ -3,7 +3,7 @@ namespace HouraiTeahouse.Backroll { public unsafe delegate void SaveGameStateCallback(ref Sync.SavedFrame frame); -public unsafe delegate void LoadGameStateCallback(void* buffer, int len); +public unsafe delegate void LoadGameStateCallback(ref Sync.SavedFrame state); public unsafe delegate void LogGameStateCallback(string filename, void* buffer, int len); public class BackrollSessionCallbacks { diff --git a/Runtime/BackrollSession.cs b/Runtime/BackrollSession.cs index 7a6d7155..da47318f 100644 --- a/Runtime/BackrollSession.cs +++ b/Runtime/BackrollSession.cs @@ -8,6 +8,8 @@ namespace HouraiTeahouse.Backroll { public static class Backroll { + public static bool LOG_BACKROLL = false; + // Starts a new Backroll session. // // num_players - The number of players which will be in this game. The number diff --git a/Runtime/GameInput.cs b/Runtime/GameInput.cs index 8d567c18..d0d0548d 100644 --- a/Runtime/GameInput.cs +++ b/Runtime/GameInput.cs @@ -99,14 +99,14 @@ public void Log(string prefix, bool show_frame = true) { public bool Equals(in GameInput other, bool bitsonly) { if (!bitsonly && Frame != other.Frame) { - Debug.LogFormat("frames don't match: {}, {}", Frame, other.Frame); + Debug.LogFormat("frames don't match: {0}, {1}", Frame, other.Frame); } if (Size != other.Size) { - Debug.LogFormat("sizes don't match: {}, {}", Size, other.Size); + Debug.LogFormat("sizes don't match: {0}, {1}", Size, other.Size); } fixed (byte* ptr = bits, otherPtr = other.bits) { if (UnsafeUtility.MemCmp(ptr, otherPtr, Size) != 0) { - Debug.Log("bits don't match"); + if (Backroll.LOG_BACKROLL) Debug.Log("bits don't match"); } Assert.IsTrue(Size > 0 && other.Size > 0); return (bitsonly || Frame == other.Frame) && diff --git a/Runtime/InputQueue.cs b/Runtime/InputQueue.cs index 63c87e11..3613e51f 100644 --- a/Runtime/InputQueue.cs +++ b/Runtime/InputQueue.cs @@ -40,7 +40,7 @@ public InputQueue(int queue_size, uint input_size, int id = -1) { } public int GetLastConfirmedFrame() { - Debug.LogFormat("returning last confirmed frame {}.", _lastAddedFrame); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("returning last confirmed frame {0}.", _lastAddedFrame); return _lastAddedFrame; } @@ -55,28 +55,28 @@ public void DiscardConfirmedFrames(int frame) { frame = Mathf.Min(frame, _lastFrameRequested); } - Debug.LogFormat("discarding confirmed frames up to {} (last_added:{} length:{} [head:{} tail:{}]).", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("discarding confirmed frames up to {0} (last_added:{1} length:{2} [head:{3} tail:{4}]).", frame, _lastAddedFrame, _length, _head, _tail); if (frame >= _lastAddedFrame) { _tail = _head; } else { int offset = frame - _inputs[_tail].Frame + 1; - Debug.LogFormat("difference of {} frames.", offset); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("difference of {0} frames.", offset); Assert.IsTrue(offset >= 0); _tail = (_tail + offset) % _inputs.Length; _length -= offset; } - Debug.LogFormat("after discarding, new tail is {} (frame:{}).", _tail, _inputs[_tail].Frame); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("after discarding, new tail is {0} (frame:{1}).", _tail, _inputs[_tail].Frame); Assert.IsTrue(_length >= 0); } public void ResetPrediction(int frame) { Assert.IsTrue(_firstIncorrectFrame == GameInput.kNullFrame || frame <= _firstIncorrectFrame); - Debug.LogFormat("resetting all prediction errors back to frame {}.", frame); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("resetting all prediction errors back to frame {0}.", frame); // There's nothing really to do other than reset our prediction // state and the incorrect frame counter... @@ -94,7 +94,7 @@ public bool GetConfirmedInput(int requested_frame, ref GameInput input) { } public bool GetInput(int requested_frame, out GameInput input) { - Debug.LogFormat("requesting input frame {}.", requested_frame); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("requesting input frame {0}.", requested_frame); // No one should ever try to grab any input when we have a prediction // error. Doing so means that we're just going further down the wrong @@ -116,7 +116,7 @@ public bool GetInput(int requested_frame, out GameInput input) { offset = (offset + _tail) % _inputs.Length; Assert.IsTrue(_inputs[offset].Frame == requested_frame); input = _inputs[offset]; - Debug.LogFormat("returning confirmed frame number {}.", input.Frame); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("returning confirmed frame number {0}.", input.Frame); return true; } @@ -124,13 +124,13 @@ public bool GetInput(int requested_frame, out GameInput input) { // to return a prediction frame. Predict that the user will do the // same thing they did last time. if (requested_frame == 0) { - Debug.Log("basing new prediction frame from nothing, you're client wants frame 0."); + if (Backroll.LOG_BACKROLL) Debug.Log("basing new prediction frame from nothing, you're client wants frame 0."); _prediction.Clear(); } else if (_lastAddedFrame == GameInput.kNullFrame) { - Debug.Log("basing new prediction frame from nothing, since we have no frames yet."); + if (Backroll.LOG_BACKROLL) Debug.Log("basing new prediction frame from nothing, since we have no frames yet."); _prediction.Clear(); } else { - Debug.LogFormat("basing new prediction frame from previously added frame (queue entry:{}, frame:{}).", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("basing new prediction frame from previously added frame (queue entry:{0}, frame:{1}).", PreviousFrame(_head), _inputs[PreviousFrame(_head)].Frame); _prediction = _inputs[PreviousFrame(_head)]; } @@ -144,7 +144,7 @@ public bool GetInput(int requested_frame, out GameInput input) { // frame number requested by the client, though. input = _prediction; input.Frame = requested_frame; - Debug.LogFormat("returning prediction frame number {} ({}).", input.Frame, _prediction.Frame); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("returning prediction frame number {0} ({1}).", input.Frame, _prediction.Frame); return false; } @@ -152,10 +152,11 @@ public bool GetInput(int requested_frame, out GameInput input) { public void AddInput(ref GameInput input) { int new_frame; - Debug.LogFormat("adding input frame number {} to queue.", input.Frame); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("adding input frame number {0} to queue.", input.Frame); // These next two lines simply verify that inputs are passed in // sequentially by the user, regardless of frame delay. + if (Backroll.LOG_BACKROLL) Debug.Log($"[InputQueue] _lastUserAddedFrame: {_lastUserAddedFrame}, input.Frame: {input.Frame}"); Assert.IsTrue(_lastUserAddedFrame == GameInput.kNullFrame || input.Frame == _lastUserAddedFrame + 1); _lastUserAddedFrame = input.Frame; @@ -174,7 +175,7 @@ public void AddInput(ref GameInput input) { } protected void AddDelayedInputToQueue(in GameInput input, int frame_number) { - Debug.LogFormat("adding delayed input frame number {} to queue.", frame_number); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("adding delayed input frame number {0} to queue.", frame_number); Assert.IsTrue(input.Size == _prediction.Size); Assert.IsTrue(_lastAddedFrame == GameInput.kNullFrame || frame_number == _lastAddedFrame + 1); @@ -197,7 +198,7 @@ protected void AddDelayedInputToQueue(in GameInput input, int frame_number) { // remember the first input which was incorrect so we can report it // in GetFirstIncorrectFrame() if (_firstIncorrectFrame == GameInput.kNullFrame && !_prediction.Equals(input, true)) { - Debug.LogFormat("frame {} does not match prediction. marking error.", frame_number); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("frame {0} does not match prediction. marking error.", frame_number); _firstIncorrectFrame = frame_number; } @@ -206,7 +207,7 @@ protected void AddDelayedInputToQueue(in GameInput input, int frame_number) { // of predition mode entirely! Otherwise, advance the prediction frame // count up. if (_prediction.Frame == _lastFrameRequested && _firstIncorrectFrame == GameInput.kNullFrame) { - Debug.Log("prediction is correct! dumping out of prediction mode."); + if (Backroll.LOG_BACKROLL) Debug.Log("prediction is correct! dumping out of prediction mode."); _prediction.Frame = GameInput.kNullFrame; } else { _prediction.Frame++; @@ -216,7 +217,7 @@ protected void AddDelayedInputToQueue(in GameInput input, int frame_number) { } protected int AdvanceQueueHead(int frame) { - Debug.LogFormat("advancing queue head to frame {}.", frame); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("advancing queue head to frame {0}.", frame); int expected_frame = _firstFrame ? 0 : _inputs[PreviousFrame(_head)].Frame + 1; @@ -226,7 +227,7 @@ protected int AdvanceQueueHead(int frame) { // This can occur when the frame delay has dropped since the last // time we shoved a frame into the system. In this case, there's // no room on the queue. Toss it. - Debug.LogFormat("Dropping input frame {} (expected next frame to be {}).", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("Dropping input frame {0} (expected next frame to be {1}).", frame, expected_frame); return GameInput.kNullFrame; } @@ -236,7 +237,7 @@ protected int AdvanceQueueHead(int frame) { // time we shoved a frame into the system. We need to replicate the // last frame in the queue several times in order to fill the space // left. - Debug.LogFormat("Adding padding frame {} to account for change in frame delay.", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("Adding padding frame {0} to account for change in frame delay.", expected_frame); ref GameInput last_frame = ref _inputs[PreviousFrame(_head)]; AddDelayedInputToQueue(last_frame, expected_frame); diff --git a/Runtime/Sync.cs b/Runtime/Sync.cs index 772f9c69..1fc45d16 100644 --- a/Runtime/Sync.cs +++ b/Runtime/Sync.cs @@ -2,14 +2,18 @@ using Unity.Collections.LowLevel.Unsafe; using UnityEngine; using UnityEngine.Assertions; +using System.Collections.Generic; namespace HouraiTeahouse.Backroll { public unsafe class Sync : IDisposable { public struct SavedFrame { - public byte* Buffer; - public int Size; + // public byte* Buffer; + // public int Size; + + public List GameState; + public int Frame; public int Checksum; @@ -69,7 +73,8 @@ public void Dispose() { // Delete frames manually here rather than in a destructor of the SavedFrame // structure so we can efficently copy frames via weak references. for (int i = 0; i < _savedstate.Frames.Length; i++) { - _callbacks.FreeBuffer?.Invoke((IntPtr)_savedstate.Frames[i].Buffer); + // _callbacks.FreeBuffer?.Invoke((IntPtr)_savedstate.Frames[i].Buffer); + _savedstate.Frames[i].GameState = null; } _inputQueues = null; } @@ -87,7 +92,7 @@ public bool AddLocalInput(int queue, ref GameInput input) { int frames_behind = FrameCount - _lastConfirmedFrame; if (FrameCount >= _maxPredictionFrames && frames_behind >= _maxPredictionFrames) { - Debug.Log("Rejecting input from emulator: reached prediction barrier."); + if (Backroll.LOG_BACKROLL) Debug.Log("Rejecting input from emulator: reached prediction barrier."); return false; } @@ -95,7 +100,7 @@ public bool AddLocalInput(int queue, ref GameInput input) { SaveCurrentFrame(); } - Debug.LogFormat("Sending undelayed local frame {} to queue {}.", FrameCount, queue); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("Sending undelayed local frame {0} to queue {1}.", FrameCount, queue); input.Frame = FrameCount; _inputQueues[queue].AddInput(ref input); @@ -162,7 +167,7 @@ public void AdjustSimulation(int seek_to) { int framecount = FrameCount; int count = FrameCount - seek_to; - Debug.Log("Catching up"); + if (Backroll.LOG_BACKROLL) Debug.Log("Catching up"); InRollback = true; // Flush our input queue and load the last frame. @@ -179,7 +184,7 @@ public void AdjustSimulation(int seek_to) { InRollback = false; - Debug.Log("---"); + if (Backroll.LOG_BACKROLL) Debug.Log("---"); } protected void ResetPrediction(int frameNumber) { @@ -191,7 +196,7 @@ protected void ResetPrediction(int frameNumber) { public void LoadFrame(int frame) { // find the frame in question if (frame == FrameCount) { - Debug.Log("Skipping NOP."); + if (Backroll.LOG_BACKROLL) Debug.Log("Skipping NOP."); return; } @@ -199,11 +204,13 @@ public void LoadFrame(int frame) { _savedstate.Head = FindSavedFrameIndex(frame); ref SavedFrame state = ref _savedstate.Frames[_savedstate.Head]; - Debug.LogFormat("=== Loading frame info {} (size: {} checksum: %08x).", - state.Frame, state.Size, state.Checksum); + // if (Backroll.LOG_BACKROLL) Debug.LogFormat("=== Loading frame info {0} (size: {1} checksum: {2}).", + // state.Frame, state.Size, state.Checksum); - Assert.IsTrue(state.Buffer != null && state.Size != 0); - _callbacks.LoadGameState(state.Buffer, state.Size); + // Assert.IsTrue(state.Buffer != null && state.Size != 0); + Assert.IsTrue(state.GameState != null); + // _callbacks.LoadGameState(state.Buffer, state.Size); + _callbacks.LoadGameState(ref state); // Reset framecount and the Head of the state ring-buffer to point in // advance of the current frame (as if we had just finished executing it). @@ -215,15 +222,15 @@ public void SaveCurrentFrame() { // See StateCompress for the real save feature implemented by FinalBurn. // Write everything into the Head, then advance the Head pointer. ref SavedFrame state = ref _savedstate.Frames[_savedstate.Head]; - if (state.Buffer != null) { - _callbacks.FreeBuffer((IntPtr)state.Buffer); - state.Buffer = null; - } + // if (state.Buffer != null) { + // _callbacks.FreeBuffer((IntPtr)state.Buffer); + // state.Buffer = null; + // } _callbacks.SaveGameState(ref state); state.Frame = FrameCount; - Debug.LogFormat("=== Saved frame info {} (size: {} checksum: %08x).", - state.Frame, state.Size, state.Checksum); + // if (Backroll.LOG_BACKROLL) Debug.LogFormat("=== Saved frame info {0} (size: {1} checksum: {2}).", + // state.Frame, state.Size, state.Checksum); _savedstate.Head = (_savedstate.Head + 1) % _savedstate.Frames.Length; } @@ -259,7 +266,7 @@ bool CheckSimulationConsistency(int *seekTo) { int first_incorrect = GameInput.kNullFrame; for (int i = 0; i < _config.NumPlayers; i++) { int incorrect = _inputQueues[i].GetFirstIncorrectFrame(); - Debug.LogFormat("considering incorrect frame {} reported by queue {}.", incorrect, i); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("considering incorrect frame {0} reported by queue {1}.", incorrect, i); if (incorrect != GameInput.kNullFrame && (first_incorrect == GameInput.kNullFrame || @@ -269,7 +276,7 @@ bool CheckSimulationConsistency(int *seekTo) { } if (first_incorrect == GameInput.kNullFrame) { - Debug.Log("prediction ok. proceeding."); + if (Backroll.LOG_BACKROLL) Debug.Log("prediction ok. proceeding."); return true; } *seekTo = first_incorrect; diff --git a/Runtime/TimeSync.cs b/Runtime/TimeSync.cs index a474a5a2..8c3cd4eb 100644 --- a/Runtime/TimeSync.cs +++ b/Runtime/TimeSync.cs @@ -26,6 +26,7 @@ public TimeSync(int frameWindowSize = kDefaultFrameWindowSize, int maxFrameAdvantage = kDefaultMaxFrameAdvantage) { _local = new int[frameWindowSize]; _remote = new int[frameWindowSize]; + _last_inputs = new GameInput[frameWindowSize]; _next_prediction = frameWindowSize * 3; _minFrameAdvantage = minFrameAdvantage; @@ -68,7 +69,7 @@ public int RecommendFrameWaitDuration(bool require_idle_input) { // sleep for. int sleep_frames = (int)(((radvantage - advantage) / 2) + 0.5); - Debug.LogFormat("iteration {}: sleep frames is {}", count, sleep_frames); + if (Backroll.LOG_BACKROLL) Debug.LogFormat("iteration {0}: sleep frames is {1}", count, sleep_frames); // Some things just aren't worth correcting for. Make sure // the difference is relevant before proceeding. @@ -83,7 +84,7 @@ public int RecommendFrameWaitDuration(bool require_idle_input) { if (require_idle_input) { for (i = 1; i < _last_inputs.Length; i++) { if (!_last_inputs[i].Equals(_last_inputs[0], true)) { - Debug.LogFormat("iteration {}: rejecting due to input stuff at position {}...!!!", + if (Backroll.LOG_BACKROLL) Debug.LogFormat("iteration {0}: rejecting due to input stuff at position {1}...!!!", count, i); return 0; }