public void Destroy(IMyReplicable obj)
        {
            Debug.Assert(obj != null);
            if (!IsTypeReplicated(obj.GetType()))
            {
                return;
            }

            var id = GetNetworkIdByObject(obj);

            if (id.IsInvalid)
            {
                Debug.Fail("Destroying object which is not present");
                return;
            }

            // Remove from client states, remove from client replicables, send destroy
            foreach (var client in m_clientStates)
            {
                // TODO: Postpone removing for client (we don't want to peak network when a lot of objects get removed)
                if (client.Value.Replicables.ContainsKey(obj))
                {
                    RemoveForClient(obj, client.Key, client.Value, true);
                }
            }

            RemoveStateGroups(obj);
            var netId = RemoveNetworkedObject(obj);

            m_replicables.Remove(netId);
        }
        bool PrepareForceReplicable(IMyReplicable obj)
        {
            Debug.Assert(obj != null);
            if (!IsTypeReplicated(obj.GetType()))
            {
                Debug.Fail(String.Format("Cannot replicate {0}, type is not replicated", obj));
                return(false);
            }

            NetworkId id;

            if (!TryGetNetworkIdByObject(obj, out id))
            {
                Replicate(obj);
            }
            return(true);
        }
        public void Replicate(IMyReplicable obj)
        {
            if (!IsTypeReplicated(obj.GetType()))
            {
                Debug.Fail(String.Format("Type '{0}' not replicated, this should be checked before calling Replicate", obj.GetType().Name));
                return;
            }

            NetworkId networkId = AddNetworkObjectServer(obj);

            m_replicables.Add(networkId, obj);

            AddStateGroups(obj);

            // HACK: test serialization
            //m_sendStream.ResetWrite(MessageIDEnum.REPLICATION_CREATE);
            //stateData.Replicate(m_sendStream);
        }
        void SendReplicationCreate(IMyReplicable obj, EndpointId clientEndpoint)
        {
            var typeId    = GetTypeIdByType(obj.GetType());
            var networkId = GetNetworkIdByObject(obj);

            var groups = m_replicableGroups[obj];

            Debug.Assert(groups.Count <= 255, "Unexpectedly high number of groups");

            m_sendStream.ResetWrite();
            m_sendStream.WriteTypeId(typeId);
            m_sendStream.WriteNetworkId(networkId);
            m_sendStream.WriteByte((byte)groups.Count);
            for (int i = 0; i < groups.Count; i++)
            {
                m_sendStream.WriteNetworkId(GetNetworkIdByObject(groups[i]));
            }
            obj.OnSave(m_sendStream);

            m_callback.SendReplicationCreate(m_sendStream, clientEndpoint);
            //Server.SendMessage(m_sendStream, clientId, PacketReliabilityEnum.RELIABLE, PacketPriorityEnum.LOW_PRIORITY, MyChannelEnum.Replication);
        }
        void SendReplicationCreate(IMyReplicable obj, EndpointId clientEndpoint)
        {
            var typeId = GetTypeIdByType(obj.GetType());
            var networkId = GetNetworkIdByObject(obj);

            var groups = m_replicableGroups[obj];
            Debug.Assert(groups.Count <= 255, "Unexpectedly high number of groups");

            m_sendStream.ResetWrite();
            m_sendStream.WriteTypeId(typeId);
            m_sendStream.WriteNetworkId(networkId);
            m_sendStream.WriteByte((byte)groups.Count);
            for (int i = 0; i < groups.Count; i++)
            {
                m_sendStream.WriteNetworkId(GetNetworkIdByObject(groups[i]));
            }
            obj.OnSave(m_sendStream);

            m_callback.SendReplicationCreate(m_sendStream, clientEndpoint);
            //Server.SendMessage(m_sendStream, clientId, PacketReliabilityEnum.RELIABLE, PacketPriorityEnum.LOW_PRIORITY, MyChannelEnum.Replication);
        }
        public void Destroy(IMyReplicable obj)
        {
            Debug.Assert(obj != null);
            if (!IsTypeReplicated(obj.GetType()))
            {
                return;
            }

            var id = GetNetworkIdByObject(obj);
            if (id.IsInvalid)
            {
                Debug.Fail("Destroying object which is not present");
                return;
            }

            // Remove from client states, remove from client replicables, send destroy
            foreach (var client in m_clientStates)
            {
                // TODO: Postpone removing for client (we don't want to peak network when a lot of objects get removed)
                if (client.Value.Replicables.ContainsKey(obj))
                {
                    RemoveForClient(obj, client.Key, client.Value, true);
                }
            }

            RemoveStateGroups(obj);
            var netId = RemoveNetworkedObject(obj);
            m_replicables.Remove(netId);
        }
        bool PrepareForceReplicable(IMyReplicable obj)
        {
            Debug.Assert(obj != null);
            if (!IsTypeReplicated(obj.GetType()))
            {
                Debug.Fail(String.Format("Cannot replicate {0}, type is not replicated", obj));
                return false;
            }

            NetworkId id;
            if (!TryGetNetworkIdByObject(obj, out id))
            {
                Replicate(obj);
            }
            return true;
        }
        public void Replicate(IMyReplicable obj)
        {
            if (!IsTypeReplicated(obj.GetType()))
            {
                Debug.Fail(String.Format("Type '{0}' not replicated, this should be checked before calling Replicate", obj.GetType().Name));
                return;
            }

            NetworkId networkId = AddNetworkObjectServer(obj);
            m_replicables.Add(networkId, obj);

            AddStateGroups(obj);

            // HACK: test serialization
            //m_sendStream.ResetWrite(MessageIDEnum.REPLICATION_CREATE);
            //stateData.Replicate(m_sendStream);
        }
        void SendReplicationCreate(IMyReplicable obj, ClientData clientData, EndpointId clientEndpoint)
        {
            
            if (m_replicationPaused)
            {
                clientData.PausedReplicables.Add(obj);
                return;
            }

            ProfilerShort.Begin("PrepareSave");
            var typeId = GetTypeIdByType(obj.GetType());
            var networkId = GetNetworkIdByObject(obj);

            var groups = m_replicableGroups[obj];
            Debug.Assert(groups.Count <= 255, "Unexpectedly high number of groups");

            m_sendStream.ResetWrite();
            m_sendStream.WriteTypeId(typeId);
            m_sendStream.WriteNetworkId(networkId);


            var streamable = obj as IMyStreamableReplicable;

            bool sendStreamed = streamable != null && streamable.NeedsToBeStreamed;
            if (streamable != null && streamable.NeedsToBeStreamed == false)
            {
                m_sendStream.WriteByte((byte)(groups.Count - 1));
            }
            else
            {
                m_sendStream.WriteByte((byte)groups.Count);
            }


            for (int i = 0; i < groups.Count; i++)
            {
                if (sendStreamed == false && groups[i].GroupType == StateGroupEnum.Streamining)
                {
                    continue;
                }
                m_sendStream.WriteNetworkId(GetNetworkIdByObject(groups[i]));
            }

            ProfilerShort.End();

            ProfilerShort.Begin("SaveReplicable");

            if (sendStreamed)
            {
                clientData.Replicables[obj].IsStreaming = true;
                m_callback.SendReplicationCreateStreamed(m_sendStream, clientEndpoint);
            }
            else
            {
                obj.OnSave(m_sendStream);
                ProfilerShort.Begin("Send");
                m_callback.SendReplicationCreate(m_sendStream, clientEndpoint);
                ProfilerShort.End();
            }
            ProfilerShort.End();
       
            //Server.SendMessage(m_sendStream, clientId, PacketReliabilityEnum.RELIABLE, PacketPriorityEnum.LOW_PRIORITY, MyChannelEnum.Replication);
        }
        private void RefreshReplicable(IMyReplicable replicable)
        {
            ProfilerShort.Begin("m_timeFunc");
            MyTimeSpan now = m_timeFunc();
            ProfilerShort.End();

            foreach (var client in m_clientStates)
            {
                ProfilerShort.Begin("RefreshReplicablePerClient");

                ProfilerShort.Begin("TryGetValue Replicables");
                MyReplicableClientData replicableInfo;
                bool hasObj = client.Value.Replicables.TryGetValue(replicable, out replicableInfo);
                ProfilerShort.End();

                ProfilerShort.Begin("GetPriority");
                ProfilerShort.Begin(replicable.GetType().Name);
                float priority = replicable.GetPriority(new MyClientInfo(client.Value));

                if (hasObj)
                {
                    replicableInfo.Priority = priority;
                }

                bool isRelevant = priority > 0;
                ProfilerShort.End();
                ProfilerShort.End();

                if (isRelevant && !hasObj)
                {
                    ProfilerShort.Begin("CheckReady");
                    var dependency = replicable.GetDependency();
                    isRelevant = dependency == null || client.Value.IsReplicableReady(dependency);
                    ProfilerShort.End();

                    if (isRelevant)
                    {
                        ProfilerShort.Begin("AddForClient");
                        AddForClient(replicable, client.Key, client.Value, priority, false);
                        ProfilerShort.End();
                    }
                }
                else if (hasObj)
                {
                    ProfilerShort.Begin("UpdateSleepAndRemove");
                    // Hysteresis
                    replicableInfo.UpdateSleep(isRelevant, now);
                    if (replicableInfo.ShouldRemove(now, MaxSleepTime))
                        RemoveForClient(replicable, client.Key, client.Value, true);
                    ProfilerShort.End();
                }

                ProfilerShort.End();
            }
        }
        public void Destroy(IMyReplicable obj)
        {
            Debug.Assert(obj != null);
            if (!IsTypeReplicated(obj.GetType()))
            {
                return;
            }

            var id = GetNetworkIdByObject(obj);
            if (id.IsInvalid)
            {
                Debug.Fail("Destroying object which is not present");
                return;
            }

            m_priorityUpdates.Remove(obj);
            bool isAnyClientPending = false;

            // Remove from client states, remove from client replicables, send destroy
            foreach (var client in m_clientStates)
            {
                // Damn, this id is blocked, i cannot remove it yet!
                if (client.Value.BlockedReplicables.ContainsKey(obj))
                {
                    // Mark for remove after replication ready.
                    client.Value.BlockedReplicables[obj].Remove = true;
                    if(!obj.IsChild && !m_priorityUpdates.Contains(obj))
                    {
                        m_priorityUpdates.Add(obj);
                    }
                    isAnyClientPending = true;
                    continue;
                }

                // TODO: Postpone removing for client (we don't want to peak network when a lot of objects get removed)
                if (client.Value.Replicables.ContainsKey(obj))
                {
                    RemoveForClient(obj, client.Key, client.Value, true);
                }
            }

            // if noone pending than remove replicable.
            if (!isAnyClientPending)
            {
                RemoveStateGroups(obj);
                var netId = RemoveNetworkedObject(obj);
                m_replicables.RemoveHierarchy(obj);
            }
        }
        bool PrepareForceReplicable(IMyReplicable obj)
        {
            Debug.Assert(obj != null);
            if (obj == null || !IsTypeReplicated(obj.GetType()))
            {
                Debug.Fail(String.Format("Cannot replicate {0}, type is not replicated", obj));
                return false;
            }

            NetworkId id;
            if (!TryGetNetworkIdByObject(obj, out id))
            {
                Debug.Fail("Force replicable dependency not replicated yet!");
                //Replicate(obj); // This would cause crashes
                return false;
            }
            return true;
        }
        public void Replicate(IMyReplicable obj)
        {
            if (!IsTypeReplicated(obj.GetType()))
            {
                Debug.Fail(String.Format("Type '{0}' not replicated, this should be checked before calling Replicate", obj.GetType().Name));
                return;
            }

            IMyReplicable parent;

            NetworkId networkId = AddNetworkObjectServer(obj);
            m_replicables.Add(obj, out parent);
            AddStateGroups(obj);

            if (parent != null)
            {
                // Replicate to all clients which has parent
                foreach (var client in m_clientStates)
                {
                    MyReplicableClientData parentInfo;
                    if (client.Value.Replicables.TryGetValue(parent, out parentInfo))
                    {
                        AddForClient(obj, client.Key, client.Value, parentInfo.Priority,false);
                    }
                }
            }
            else
            {
                m_priorityUpdates.Add(obj);
            }

            // HACK: uncomment this to test serialization
            //m_sendStream.ResetWrite(MessageIDEnum.REPLICATION_CREATE);
            //stateData.Replicate(m_sendStream);
        }