/// <summary> /// Processes state sync sent by server. /// </summary> public void ProcessStateSync(MyPacket packet) { LastMessageFromServer = DateTime.UtcNow; // Simulated packet loss // if (MyRandom.Instance.NextFloat() > 0.3f) return; m_receiveStream.ResetRead(packet); bool isStreaming = m_receiveStream.ReadBool(); m_lastStateSyncPacketId = m_receiveStream.ReadByte(); try { while (m_receiveStream.BytePosition < m_receiveStream.ByteLength) { NetworkId networkID = m_receiveStream.ReadNetworkId(); IMyStateGroup obj = GetObjectByNetworkId(networkID) as IMyStateGroup; if (obj == null) { if (isStreaming == false) { Debug.Fail("IMyStateGroup not found by NetworkId"); break; } else { return; } } if (isStreaming && obj.GroupType != StateGroupEnum.Streamining) { Debug.Fail("group type mismatch !"); MyLog.Default.WriteLine("received streaming flag but group is not streaming !"); return; } if (!isStreaming && obj.GroupType == StateGroupEnum.Streamining) { Debug.Fail("group type mismatch !"); MyLog.Default.WriteLine("received non streaming flag but group wants to stream !"); return; } var pos = m_receiveStream.BytePosition; NetProfiler.Begin(obj.GetType().Name); obj.Serialize(m_receiveStream, ClientState.EndpointId, 0, m_lastStateSyncPacketId, 0); NetProfiler.End(m_receiveStream.ByteLength - pos); if (!m_acks.Contains(m_lastStateSyncPacketId)) { m_acks.Add(m_lastStateSyncPacketId); } } } catch (BitStreamException) { } }
private void ProcessMessage(byte[] data, int dataSize, ulong sender, TimeSpan timestamp) { Debug.Assert(data.Length >= dataSize, "Wrong size"); MyMessageId id = (MyMessageId)data[0]; MyPacket p = new MyPacket(); p.Data = data; p.PayloadOffset = 1; // First byte is message id p.PayloadLength = dataSize - p.PayloadOffset; p.Sender = new VRage.Network.EndpointId(sender); p.Timestamp = timestamp; Action <MyPacket> handler; if (m_handlers.TryGetValue(id, out handler)) { ProfilerShort.Begin(MyEnum <MyMessageId> .GetName(id)); NetProfiler.Begin(MyEnum <MyMessageId> .GetName(id)); handler(p); NetProfiler.End(p.PayloadLength); ProfilerShort.End(); } else { Debug.Fail("No handler for message type: " + id); } }
/// <summary> /// Processes state sync sent by server. /// </summary> public void ProcessStateSync(MyPacket packet) { // Simulated packet loss // if (MyRandom.Instance.NextFloat() > 0.05f) return; m_receiveStream.ResetRead(packet); m_lastStateSyncPacketId = m_receiveStream.ReadByte(); while (m_receiveStream.BytePosition < m_receiveStream.ByteLength) { NetworkId networkID = m_receiveStream.ReadNetworkId(); IMyNetObject obj = GetObjectByNetworkId(networkID); var pos = m_receiveStream.BytePosition; NetProfiler.Begin(obj.GetType().Name); Debug.Assert(obj != null && obj is IMyStateGroup, "IMyStateGroup not found by NetworkId"); ((IMyStateGroup)obj).Serialize(m_receiveStream, null, m_lastStateSyncPacketId, 0); NetProfiler.End(m_receiveStream.ByteLength - pos); } if (!m_acks.Contains(m_lastStateSyncPacketId)) { m_acks.Add(m_lastStateSyncPacketId); } }
public void ReportReplicatedObjects() { foreach (var obj in m_networkIDToObject) { NetProfiler.Begin(GetGroupName(obj.Value)); NetProfiler.Begin(obj.Value.GetType().Name); NetProfiler.End(1, 0, "", "{0.}", "{0}x"); NetProfiler.End(1, 0, "", "{0.}", "{0}x"); } }
void ProcessBuffer() { try { IsProcessingBuffer = true; NetProfiler.Begin("Processing buffered events"); foreach (var b in m_buffer) { ProcessMessage(b.Data, b.Data.Length, b.Sender, TimeSpan.Zero); } NetProfiler.End(); } finally { IsProcessingBuffer = false; } }
private void ProcessMessage(byte[] data, int dataSize, ulong sender, MyTimeSpan timestamp, MyTimeSpan receivedTime) { Debug.Assert(data.Length >= dataSize, "Wrong size"); MyMessageId id = (MyMessageId)data[0]; if (id == MyMessageId.CLIENT_CONNNECTED) { MyNetworkClient player; if (Sync.Layer != null && Sync.Layer.Clients != null) { bool playerFound = Sync.Layer.Clients.TryGetClient(sender, out player); if (!playerFound) { Sync.Layer.Clients.AddClient(sender); } } } MyPacket p = new MyPacket { Data = data, // First byte is message id PayloadOffset = 1, PayloadLength = dataSize - 1, Sender = new VRage.Network.EndpointId(sender), Timestamp = timestamp, ReceivedTime = receivedTime }; Action <MyPacket> handler; if (m_handlers.TryGetValue(id, out handler)) { ProfilerShort.Begin(MyEnum <MyMessageId> .GetName(id)); NetProfiler.Begin(MyEnum <MyMessageId> .GetName(id)); handler(p); NetProfiler.End(p.PayloadLength); ProfilerShort.End(); } else { Debug.Fail("No handler for message type: " + id); } }
private void HandleMessage(byte[] data, int dataSize, ulong sender, MyTimeSpan timestamp, MyTimeSpan receivedTime) { if (dataSize < sizeof(byte)) // This would cause crash, message has to contain at least MyMessageId { return; } ProfilerShort.Begin("Handle message"); if (sender != Sync.MyId) { ByteCountReceived += dataSize; } MyMessageId id = (MyMessageId)data[0]; LogStats(ReceiveStats, "", dataSize, 1, P2PMessageEnum.Reliable); m_thisFrameTraffic[(int)id] += dataSize; if (id == MyMessageId.OLD_GAME_EVENT_FLUSH) // Flush buffer { if (m_buffer != null) { m_buffer.Clear(); } } else if (IsBuffering && id != MyMessageId.JOIN_RESULT && id != MyMessageId.WORLD_DATA && id != MyMessageId.WORLD_BATTLE_DATA) // Buffer event { var buff = new Buffer(); buff.Sender = sender; buff.Data = new byte[dataSize]; Array.Copy(data, buff.Data, dataSize); buff.ReceivedTime = MyTimeSpan.FromTicks(Stopwatch.GetTimestamp()); m_buffer.Add(buff); } else // Process event { NetProfiler.Begin("Live data", 0); ProcessMessage(data, dataSize, sender, timestamp, receivedTime); NetProfiler.End(); } ProfilerShort.End(); }
void ReportObjects(string name, Type baseType) { int count = 0; NetProfiler.Begin(name); foreach (var pair in m_tmpReportedObjects) { Ref <int> num = pair.Value; if (num.Value > 0 && baseType.IsAssignableFrom(pair.Key)) { count += num.Value; NetProfiler.Begin(pair.Key.Name); NetProfiler.End(num.Value, 0, "", "{0:.} x", ""); num.Value = 0; } } NetProfiler.End(count, 0, "", "{0:.} x", ""); }
private void HandleMessage(byte[] data, int dataSize, ulong sender, TimeSpan timestamp) { if (dataSize < sizeof(byte)) // This would cause crash, message has to contain at least MyMessageId { return; } ProfilerShort.Begin("Handle message"); if (sender != Sync.MyId) { ByteCountReceived += dataSize; } MyMessageId id = (MyMessageId)data[0]; m_thisFrameTraffic[(int)id] += dataSize; if (id == MyMessageId.OLD_GAME_EVENT_FLUSH) // Flush buffer { if (m_buffer != null) { m_buffer.Clear(); } } else if (IsBuffering) // Buffer event { var buff = new Buffer(); buff.Sender = sender; buff.Data = new byte[dataSize]; Array.Copy(data, buff.Data, dataSize); m_buffer.Add(buff); } else // Process event { NetProfiler.Begin("Live data", 0); ProcessMessage(data, dataSize, sender, timestamp); NetProfiler.End(); } ProfilerShort.End(); }
public void HandleOldGameEvent(MyPacket packet) { m_receiveStream.Reset(packet.Data, packet.PayloadOffset + packet.PayloadLength); m_receiveStream.Position = packet.PayloadOffset; ushort msgId = m_receiveStream.ReadUShort(); CallbackInfo info; if (m_callbacks.TryGetValue(msgId, out info)) { var handler = info.Callback; ProfilerShort.Begin(GetGroupName(handler.MessageType)); ProfilerShort.Begin(handler.MessageType); NetProfiler.Begin(handler.MessageType); if (packet.Sender.Value != Sync.MyId) { if (!MySandboxGame.IsDedicated) { LogStats(ReceiveStats, handler.MessageType, packet.PayloadOffset + packet.PayloadLength, 1, info.SendType); } // TODO: Log stats here //info.Callback.MessageType; //info.SendType; //info.MessageId; } handler.Receive(m_receiveStream, packet.Sender.Value, packet.Timestamp); NetProfiler.End((int)m_receiveStream.Length); ProfilerShort.End(); ProfilerShort.End(); } else { Debug.Fail(String.Format("No handler defined for message {0}, of type {1}", msgId, FindDebugName(msgId))); } }
public unsafe void Tick() { foreach (var steamId in m_pendingFlushes) { byte data = 0; if (!Peer2Peer.SendPacket(steamId, &data, 0, P2PMessageEnum.Reliable, m_channel)) { System.Diagnostics.Debug.Fail("P2P packet send fail (flush)"); } } m_pendingFlushes.Clear(); int totalSum = 0; NetProfiler.Begin("Avg per frame (60 frames window)"); for (int i = 0; i < MessageTypeCount; i++) { var window = m_slidingWindows[i]; window.Enqueue(m_thisFrameTraffic[i]); m_thisFrameTraffic[i] = 0; while (window.Count > 60) { window.Dequeue(); } int sum = 0; foreach (var item in window) { sum += item; } if (sum > 0) { NetProfiler.Begin(MyEnum <MyMessageId> .GetName((MyMessageId)i)); NetProfiler.End(sum / 60.0f, sum / 1024.0f, "{0} KB/s"); } totalSum += sum; } NetProfiler.End(totalSum / 60.0f, totalSum / 1024.0f, "{0} KB/s"); }
//List<byte> m_alreadyReceivedPackets = new List<byte>(); /// <summary> /// Processes state sync sent by server. /// </summary> public void ProcessStateSync(MyPacket packet) { LastMessageFromServer = DateTime.UtcNow; // Simulated packet loss // if (MyRandom.Instance.NextFloat() > 0.3f) return; ReceiveStream.ResetRead(packet); bool isStreaming = ReceiveStream.ReadBool(); var packetId = ReceiveStream.ReadByte(); //if (m_alreadyReceivedPackets.Contains(packetId)) //{ //} //if (m_alreadyReceivedPackets.Count > 128) // m_alreadyReceivedPackets.RemoveAt(0); //m_alreadyReceivedPackets.Add(packetId); var serverOrder = m_serverTracker.Add(packetId); m_serverStats.Update(serverOrder); if (serverOrder == MyPacketTracker.OrderType.Duplicate) { return; } m_lastStateSyncPacketId = packetId; MyPacketStatistics stats = new MyPacketStatistics(); stats.Read(ReceiveStream); m_clientStatsFromServer.Add(stats); var serverTimeStamp = MyTimeSpan.FromMilliseconds(ReceiveStream.ReadDouble()); if (m_lastServerTimeStamp < serverTimeStamp) { m_lastServerTimeStamp = serverTimeStamp; } double lastClientRealtime = ReceiveStream.ReadDouble(); if (lastClientRealtime > 0) { var ping = packet.ReceivedTime - MyTimeSpan.FromMilliseconds(lastClientRealtime); if (ping.Milliseconds < 1000) { SetPing(ping); } } MyTimeSpan relevantTimeStamp = serverTimeStamp; m_callback.ReadCustomState(ReceiveStream); while (ReceiveStream.BytePosition < ReceiveStream.ByteLength) { NetworkId networkID = ReceiveStream.ReadNetworkId(); IMyStateGroup obj = GetObjectByNetworkId(networkID) as IMyStateGroup; if (obj == null) { if (isStreaming == false) { Debug.Fail("IMyStateGroup not found by NetworkId"); break; } else { return; } } if (isStreaming && obj.GroupType != StateGroupEnum.Streaming) { Debug.Fail("group type mismatch !"); MyLog.Default.WriteLine("received streaming flag but group is not streaming !"); return; } if (!isStreaming && obj.GroupType == StateGroupEnum.Streaming) { Debug.Fail("group type mismatch !"); MyLog.Default.WriteLine("received non streaming flag but group wants to stream !"); return; } if (VRage.MyCompilationSymbols.EnableNetworkPacketTracking) { Trace.MyTrace.Send(Trace.TraceWindow.MPackets, " ObjSync: " + obj.GetType().Name); } var pos = ReceiveStream.BytePosition; NetProfiler.Begin(obj.GetType().Name); obj.Serialize(ReceiveStream, ClientState.EndpointId, relevantTimeStamp, m_lastStateSyncPacketId, 0); NetProfiler.End(ReceiveStream.ByteLength - pos); if (!m_acks.Contains(m_lastStateSyncPacketId)) { m_acks.Add(m_lastStateSyncPacketId); } } }
public override void UpdateAfter() { if (!m_clientReady || !m_hasTypeTable || ClientState == null) { return; } NetProfiler.Begin("Replication client update", 0); var simulationTime = m_callback.GetUpdateTime(); if (m_clientStartTimeStamp == MyTimeSpan.Zero) { m_clientStartTimeStamp = simulationTime; // (uint)DateTime.Now.TimeOfDay.TotalMilliseconds; } var timeStamp = simulationTime - m_clientStartTimeStamp; UpdatePingSmoothing(); NetProfiler.CustomTime("Ping", (float)m_ping.Milliseconds, "{0} ms"); NetProfiler.CustomTime("SmoothPing", (float)m_smoothPing.Milliseconds, "{0} ms"); NetProfiler.Begin("Packet stats"); NetProfiler.CustomTime("Server Drops", (float)m_serverStats.Drops, "{0}"); NetProfiler.CustomTime("Server OutOfOrder", (float)m_serverStats.OutOfOrder, "{0}"); NetProfiler.CustomTime("Server Duplicates", (float)m_serverStats.Duplicates, "{0}"); NetProfiler.CustomTime("Client Drops", (float)m_clientStatsFromServer.Drops, "{0}"); NetProfiler.CustomTime("Client OutOfOrder", (float)m_clientStatsFromServer.OutOfOrder, "{0}"); NetProfiler.CustomTime("Client Duplicates", (float)m_clientStatsFromServer.Duplicates, "{0}"); m_serverStats.Reset(); m_clientStatsFromServer.Reset(); NetProfiler.End(); MyTimeSpan ping = UseSmoothPing ? m_smoothPing : m_ping; var diffCorrection = -ping.Milliseconds * m_callback.GetServerSimulationRatio(); var diffMS = timeStamp.Milliseconds - m_lastServerTimeStamp.Milliseconds; var correctionCurrent = diffMS + diffCorrection; int correction = 0, nextFrameDelta = 0; MyTimeSpan currentTime = MyTimeSpan.FromTicks(Stopwatch.GetTimestamp()); MyTimeSpan realtimeDelta = currentTime - m_lastTime; // try to be always one simulation step ahead correctionCurrent -= m_simulationTimeStep; //if (Math.Abs(correctionCurrent) > 200) // m_correctionSmooth = MyTimeSpan.FromMilliseconds(correctionCurrent); correctionCurrent = Math.Min(correctionCurrent, (int)(m_simulationTimeStep * 2 / m_callback.GetServerSimulationRatio())); if (diffMS < -MAX_TIMESTAMP_DIFF_LOW || diffMS > MAX_TIMESTAMP_DIFF_HIGH) { m_clientStartTimeStamp = MyTimeSpan.FromMilliseconds(m_clientStartTimeStamp.Milliseconds + diffMS); timeStamp = simulationTime - m_clientStartTimeStamp; m_correctionSmooth = MyTimeSpan.Zero; TimestampReset(); if (VRage.MyCompilationSymbols.EnableNetworkPositionTracking) { Trace.MyTrace.Send(Trace.TraceWindow.MTiming, "---------------------------------------------------------------- DESYNC"); } } else { var factor = Math.Min(realtimeDelta.Seconds / SmoothCorrectionAmplitude, 1.0); m_correctionSmooth = MyTimeSpan.FromMilliseconds(correctionCurrent * factor + m_correctionSmooth.Milliseconds * (1 - factor)); // special case: we really dont want the client timestamp to fall behind if (diffMS < 0) { correction = (int)correctionCurrent; } else { correction = UseSmoothCorrection ? (int)m_correctionSmooth.Milliseconds : (int)correctionCurrent; } NetProfiler.CustomTime("Correction", (float)correctionCurrent, "{0} ms"); NetProfiler.CustomTime("SmoothCorrection", (float)m_correctionSmooth.Milliseconds, "{0} ms"); if (ApplyCorrectionsDebug && (LastMessageFromServer - DateTime.UtcNow).Seconds < 1.0f) { if (diffMS < 0) { nextFrameDelta = correction; m_callback.SetNextFrameDelayDelta(nextFrameDelta); } else if (Math.Abs(correction) > TimestampCorrectionMinimum) { nextFrameDelta = (Math.Abs(correction) - TimestampCorrectionMinimum) * Math.Sign(correction); m_callback.SetNextFrameDelayDelta(nextFrameDelta); } } } NetProfiler.CustomTime("GameTimeDelta", (float)(timeStamp - Timestamp).Milliseconds, "{0} ms"); NetProfiler.CustomTime("RealTimeDelta", (float)realtimeDelta.Milliseconds, "{0} ms"); Timestamp = timeStamp; //if (VRage.MyCompilationSymbols.EnableNetworkPositionTracking) { string trace = "realtime delta: " + realtimeDelta + ", client: " + Timestamp + ", server: " + m_lastServerTimeStamp + ", diff: " + diffMS.ToString("##.#") + " => " + (Timestamp.Milliseconds - m_lastServerTimeStamp.Milliseconds).ToString("##.#") + ", Ping: " + m_ping.Milliseconds.ToString("##.#") + " / " + m_smoothPing.Milliseconds.ToString("##.#") + "ms, Correction " + correctionCurrent + " / " + m_correctionSmooth.Milliseconds + " / " + nextFrameDelta + ", ratio " + m_callback.GetServerSimulationRatio(); Trace.MyTrace.Send(Trace.TraceWindow.MTiming, trace); //Trace.MyTrace.Send(Trace.TraceWindow.MPositions2, trace); } m_lastTime = currentTime; NetProfiler.End(); if (StressSleep.X > 0) { int sleep; if (StressSleep.Z == 0) { sleep = MyRandom.Instance.Next(StressSleep.X, StressSleep.Y); } else { sleep = (int)(Math.Sin(simulationTime.Milliseconds * Math.PI / StressSleep.Z) * StressSleep.Y + StressSleep.X); } System.Threading.Thread.Sleep(sleep); } }