private void AddForClient(IMyReplicable replicable, EndpointId clientEndpoint, ClientData clientData, float priority,bool force) { if (clientData.HasReplicable(replicable)) return; // already added ProfilerShort.Begin("AddClientReplicable"); AddClientReplicable(replicable, clientData, priority,force); ProfilerShort.End(); ProfilerShort.Begin("SendReplicationCreate"); SendReplicationCreate(replicable, clientData, clientEndpoint); ProfilerShort.End(); }
private void SendStateSync(ClientData clientData) { var now = m_timeFunc(); if (clientData.StateGroups.Count == 0) return; EndpointId endpointId = clientData.State.EndpointId; // TODO: Limit events clientData.EventQueue.Send(); using (m_tmpStreamingEntries) { using (m_tmpSortEntries) { ProfilerShort.Begin("UpdateGroupPriority"); foreach (var entry in clientData.StateGroups.Values) { // No state sync for pending or sleeping replicables if (entry.Owner != null && !clientData.Replicables[entry.Owner].HasActiveStateSync) continue; entry.FramesWithoutSync++; entry.Priority = entry.Group.GetGroupPriority(entry.FramesWithoutSync, new MyClientInfo(clientData)); if (entry.Priority > 0) { if (entry.Owner != null) { m_tmpSortEntries.Add(entry); } else { if (entry.Group.GroupType != StateGroupEnum.Streamining) { Debug.Fail("Non streaming group !"); } else { m_tmpStreamingEntries.Add(entry); } } } } ProfilerShort.End(); ProfilerShort.Begin("Sort entities"); m_tmpSortEntries.Sort(MyStateDataEntryComparer.Instance); ProfilerShort.End(); byte firstWaitingPacket = (byte)(clientData.LastReceivedAckId - m_outOfOrderAcceptThreshold); byte nextPacketId = (byte)(clientData.StateSyncPacketId + 1); if (clientData.WaitingForReset || nextPacketId == firstWaitingPacket) { clientData.WaitingForReset = true; return; } int numSent = 0; while (SendStateSync(clientData, ref endpointId) && numSent <= MAX_NUM_STATE_SYNC_PACKETS_PER_CLIENT) { foreach (var entry in m_tmpSentEntries) { m_tmpSortEntries.Remove(entry); } numSent++; m_tmpSentEntries.Clear(); } m_tmpSentEntries.Clear(); if (m_tmpStreamingEntries.Count > 0) { int messageBitSize = m_callback.GetMTRSize(endpointId) * 8; ProfilerShort.Begin("Sort streaming entities"); m_tmpStreamingEntries.Sort(MyStateDataEntryComparer.Instance); clientData.StateSyncPacketId++; ProfilerShort.End(); var entry = m_tmpStreamingEntries.FirstOrDefault(); m_sendStream.ResetWrite(); m_sendStream.WriteBool(true); m_sendStream.WriteByte(clientData.StateSyncPacketId); var oldWriteOffset = m_sendStream.BitPosition; m_sendStream.WriteNetworkId(entry.GroupId); ProfilerShort.Begin("serialize streaming entities"); entry.Group.Serialize(m_sendStream, clientData.State.EndpointId, clientData.State.ClientTimeStamp, clientData.StateSyncPacketId, messageBitSize); ProfilerShort.End(); int bitsWritten = m_sendStream.BitPosition - oldWriteOffset; if (m_limits.Add(entry.Group.GroupType, bitsWritten)) { clientData.PendingStateSyncAcks[clientData.StateSyncPacketId].Add(entry.Group); entry.FramesWithoutSync = 0; } else { // When serialize returns false, restore previous bit position and tell group it was not delivered entry.Group.OnAck(clientData.State, clientData.StateSyncPacketId, false); } m_callback.SendStateSync(m_sendStream, endpointId,true); IMyReplicable groupReplicable = entry.Parent; if (groupReplicable != null) { foreach (var child in m_replicables.GetChildren(groupReplicable)) { if (!clientData.HasReplicable(child)) { AddForClient(child, endpointId, clientData, groupReplicable.GetPriority(new MyClientInfo(clientData),true), false); } } } } //Server.SendMessage(m_sendStream, guid, PacketReliabilityEnum.UNRELIABLE, PacketPriorityEnum.MEDIUM_PRIORITY, MyChannelEnum.StateDataSync); } } }