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);
                }
            }
        }