public MyReplicationClient(IReplicationClientCallback callback, MyClientStateBase clientState)
     : base(false)
 {
     m_callback = callback;
     ClientState = clientState;
     m_eventHandler = base.ProcessEvent;
 }
示例#2
0
 private MyEventContext(EndpointId sender, MyClientStateBase clientState, bool validate)
 {
     Sender               = sender;
     ClientState          = clientState;
     IsValidationRequired = validate;
     m_validationFailed   = false;
 }
        public void Serialize(BitStream stream, MyClientStateBase forClient, byte packetId, int maxBitPosition)
        {
            SmallBitField dirtyFlags;
            if (stream.Writing)
            {
                var data = m_clientData[forClient];
                dirtyFlags = data.DirtyProperties;
                stream.WriteUInt64(dirtyFlags.Bits, m_properties.Count);
            }
            else
            {
                dirtyFlags.Bits = stream.ReadUInt64(m_properties.Count);
            }

            for (int i = 0; i < m_properties.Count; i++)
            {
                if (dirtyFlags[i])
                {
                    m_properties[i].Serialize(stream, false); // Received from server, don't validate
                    if (stream.Reading) // Received from server, it's no longer dirty
                        m_dirtyProperties[i] = false;
                }
            }
            if (stream.Writing && stream.BitPosition <= maxBitPosition)
            {
                var data = m_clientData[forClient];
                data.PacketId = packetId;
                data.SentProperties.Bits = data.DirtyProperties.Bits;
                data.DirtyProperties.Bits = 0;
            }
        }
 public MyReplicationClient(IReplicationClientCallback callback, MyClientStateBase clientState)
     : base(false)
 {
     m_callback     = callback;
     ClientState    = clientState;
     m_eventHandler = base.ProcessEvent;
 }
 public void OnClientReady(EndpointId endpointId, MyClientStateBase clientState)
 {
     Debug.Assert(!m_clientStates.ContainsKey(endpointId), "Client entry already exists, bad call to OnClientJoined?");
     clientState.EndpointId = endpointId;
     m_clientStates.Add(endpointId, new ClientData(clientState, m_eventQueueSender));
     SendServerData(endpointId);
 }
 private MyEventContext(EndpointId sender, MyClientStateBase clientState, bool validate)
 {
     Sender = sender;
     ClientState = clientState;
     IsValidationRequired = validate;
     m_validationFailed = false;
 }
        protected override float GetGroupPriority(int frameCountWithoutSync, MyClientStateBase client, PrioritySettings settings)
        {
            if (IsSlaveGrid())
                return 0;

            return base.GetGroupPriority(frameCountWithoutSync, client, settings);
        }
示例#8
0
 public MyReplicationClient(IReplicationClientCallback callback, MyClientStateBase clientState,
                            float simulationTimeStep)
     : base(false)
 {
     m_simulationTimeStep = simulationTimeStep;
     m_callback           = callback;
     ClientState          = clientState;
     m_eventHandler       = base.ProcessEvent;
     m_isBlockedHandler   = this.IsBlocked;
 }
        protected override float GetGroupPriority(int frameCountWithoutSync, MyClientStateBase client, PrioritySettings settings)
        {
            const float HighQualityDistance = 8; // under 8m, character physics sync gets high priority to have smooth movement

            var clientPos = ((MyClientState)client).Position;
            var characterPos = Entity.PositionComp.GetPosition();
            bool isHighQuality = Vector3D.DistanceSquared(clientPos, characterPos) < HighQualityDistance * HighQualityDistance;
            isHighQuality = isHighQuality && !Entity.IsDead;

            return base.GetGroupPriority(frameCountWithoutSync, client, isHighQuality ? m_highQuality : settings);
        }
        public void DestroyClientData(MyClientStateBase forClient)
        {
            if (m_serverClientData != null)
            {
                m_serverClientData.Remove(forClient.EndpointId.Value);
            }

            if (m_clientUpdateFlag != null)
            {
                m_clientUpdateFlag.Remove(forClient.EndpointId.Value);
            }
        }
        /// <summary>
        /// Takes into account:
        /// Static body (zero priority for static),
        /// ResponsibilityForUpdate by client (zero priority for not responsible),
        /// otherwise returns OwnerReplicable priority.
        /// </summary>
        protected float GetBasicPhysicsPriority(MyClientStateBase client)
        {
            // Called only on server
            if (Entity.Physics.IsStatic)
                return 0;

            // TODO: Rewrite and move 'ResponsibleForUpdate' to this class (when on trunk)
            var sync = (MySyncEntity)Entity.SyncObject;
            if (sync.ResponsibleForUpdate(client.GetClient()))
                return 0;

            return OwnerReplicable.GetPriority(client);
        }
        public void CreateClientData(MyClientStateBase forClient)
        {
            if(m_serverClientData == null)
            {
                m_serverClientData = new Dictionary<ulong, ClientData>();
            }
            if (m_clientUpdateFlag == null)
            {
                m_clientUpdateFlag = new Dictionary<ulong, bool>();
            }

            m_clientUpdateFlag[forClient.EndpointId.Value] = false;
        }
        public void CreateClientData(MyClientStateBase forClient)
        {
            if (m_clientInventoryUpdate == null)
            {
                m_clientInventoryUpdate = new Dictionary<ulong, InventoryClientData>();
            }

            InventoryClientData data;
            if (m_clientInventoryUpdate.TryGetValue(forClient.EndpointId.Value, out data) == false)
            {
                m_clientInventoryUpdate[forClient.EndpointId.Value] = new InventoryClientData();
            }
            m_clientInventoryUpdate[forClient.EndpointId.Value].Dirty = true;
        }
示例#14
0
 public static bool IsRelevant(this IMyReplicable obj, MyClientStateBase state, out float priority)
 {
     priority = obj.GetPriority(state);
     return(priority > 0);
 }
示例#15
0
 public float GetPriority(MyClientStateBase client)
 {
     return GetPriorityStateGroup(client);
 }
 public void CreateClientData(MyClientStateBase forClient)
 {
     m_clientData.Add(forClient.EndpointId, new ClientData());
     m_clientData[forClient.EndpointId].DirtyProperties.Reset(true);
 }
示例#17
0
 public void DestroyClientData(MyClientStateBase forClient)
 {
 }
 public static Token Set(EndpointId endpoint, MyClientStateBase client, bool validate)
 {
     return new Token(new MyEventContext(endpoint, client, validate));
 }
示例#19
0
 public static bool IsRelevant(this IMyReplicable obj, MyClientStateBase state)
 {
     return(obj.GetPriority(state) > 0);
 }
 /// <summary>
 /// Reads arguments from stream and invokes event. Returns false when validation failed, otherwise true.
 /// </summary>
 public bool Invoke(CallSite callSite, BitStream stream, object obj, EndpointId source, MyClientStateBase clientState, bool validate)
 {
     using (MySerializerNetObject.Using(this))
         using (MyEventContext.Set(source, clientState, validate))
         {
             return(callSite.Invoke(stream, obj, validate) && !(validate && MyEventContext.Current.HasValidationFailed));
         }
 }
 public void DestroyClientData(MyClientStateBase forClient)
 {
     if (m_clientInventoryUpdate != null)
     {
         m_clientInventoryUpdate.Remove(forClient.EndpointId.Value);
     }
 }
 public void DestroyClientData(MyClientStateBase forClient)
 {
     m_clientData.Remove(forClient);
 }
 public ClientData(MyClientStateBase emptyState, Action <BitStream, EndpointId> sender)
 {
     State      = emptyState;
     EventQueue = new MyPacketQueue(512, sender);
 }
 public void CreateClientData(MyClientStateBase forClient)
 {
     m_clientData.Add(forClient, new ClientData());
 }
 public bool IsDirty(MyClientStateBase forClient)
 {
     return m_clientData[forClient].DirtyProperties.Bits != 0;
 }
        public void OnAck(MyClientStateBase forClient, byte packetId, bool delivered)
        {
            var data = m_clientData[forClient];
            Debug.Assert(data.PacketId == packetId, "Packet ID does not match, error in replication server, reporting ACK for something invalid");

            if (delivered)
            {
                data.SentProperties.Bits = 0; // Nothing sent now
            }
            else
            {
                // Not delivered, add sent to dirty
                data.DirtyProperties.Bits |= data.SentProperties.Bits;
            }
            data.PacketId = null;
        }
示例#27
0
        public float GetPriorityStateGroup(MyClientStateBase client)
        {
            MyClientState state = client as MyClientState;
            if (state.Context == Sandbox.Engine.Multiplayer.MyClientState.MyContextKind.Inventory || state.Context == Sandbox.Engine.Multiplayer.MyClientState.MyContextKind.Production)
            {
                if (state.ContextEntity != null)
                {
                    MyCubeGrid parent = state.ContextEntity.GetTopMostParent() as MyCubeGrid;

                    if (parent != null)
                    {
                        foreach (var block in parent.GridSystems.TerminalSystem.Blocks)
                        {
                            if (block == m_owner)
                            {
                                if (state.Context == Sandbox.Engine.Multiplayer.MyClientState.MyContextKind.Production && (block is MyAssembler) == false)
                                {
                                    continue;
                                }
                                return 1.0f;
                            }
                        }
                    }
                }
            }
            return 0;
        }
        public void CreateClientData(MyClientStateBase forClient)
        {
            if (m_clientInventoryUpdate == null)
            {
                m_clientInventoryUpdate = new Dictionary<ulong, InventoryClientData>();
            }

            InventoryClientData data;
            if (m_clientInventoryUpdate.TryGetValue(forClient.EndpointId.Value, out data) == false)
            {
                m_clientInventoryUpdate[forClient.EndpointId.Value] = new InventoryClientData();
                data = m_clientInventoryUpdate[forClient.EndpointId.Value];
            }
            data.Dirty = false;

            List<MyPhysicalInventoryItem> items = Inventory.GetItems();

            foreach (var serverItem in items)
            {
                MyFixedPoint amount = serverItem.Amount;

                var gasItem = serverItem.Content as MyObjectBuilder_GasContainerObject;
                if (gasItem != null)
                {
                    amount = (MyFixedPoint)gasItem.GasLevel;
                }

                ClientInvetoryData item = new ClientInvetoryData() { Item = serverItem, Amount = amount };
                data.ClientItemsSorted[serverItem.ItemId] = item;
                data.ClientItems.Add(item);
            }
            
        }
        public override void Serialize(BitStream stream, MyClientStateBase forClient, byte packetId, int maxBitPosition)
        {
            // Client does not care about slave grids, he always synced group through controlled object
            Debug.Assert(stream.Reading || !Sync.IsServer || Entity == GetMasterGrid(Entity), "Writing data from SlaveGrid!");

            bool apply = !IsControlledLocally;

            bool moving = false;
            if (stream.Writing)
            {
                moving = IsMoving(Entity);
                stream.WriteBool(moving);
            }
            else
            {
                moving = stream.ReadBool();
            }

            // Serialize this grid
            apply = SerializeTransform(stream, Entity, null, m_lowPrecisionOrientation, apply,moving, m_positionValidation, MoveHandler);
            SerializeVelocities(stream, Entity, EffectiveSimulationRatio, apply, moving,VelocityHandler);

     
            // Serialize other grids in group
            Vector3D basePos = Entity.WorldMatrix.Translation;
            if (stream.Writing)
            {
                UpdateGridMaxSpeed(Entity, Sync.IsServer);
                var g = MyCubeGridGroups.Static.PhysicalDynamic.GetGroup(Entity);
                if (g == null)
                {
                    stream.WriteByte(0);
                }
                else
                {
                    m_groups.Clear();
                    int i= -1;
                    foreach (var node in g.Nodes)
                    {
                        i++;
                        if(i < m_currentSentPosition)
                        {
                            continue;
                        }
                        if (i == m_currentSentPosition + NUM_NODES_TO_SEND_ALL)
                        {
                            break;
                        }
                        var target = MyMultiplayer.Static.ReplicationLayer.GetProxyTarget((IMyEventProxy)node.NodeData);
                        if (node.NodeData != Entity && !node.NodeData.IsStatic && target != null)
                        {
                            m_groups.Add(node.NodeData);
                        }
                    }

                    m_currentSentPosition = i;
                    if (m_currentSentPosition >= g.Nodes.Count-1)
                    {
                        m_currentSentPosition = 0;
                    }
                    stream.WriteByte((byte)m_groups.Count); // Ignoring self
                    foreach (var node in m_groups)
                    {
                        var target = MyMultiplayer.Static.ReplicationLayer.GetProxyTarget((IMyEventProxy)node);

                        // ~26.5 bytes per grid, not bad
                        NetworkId networkId = MyMultiplayer.Static.ReplicationLayer.GetNetworkIdByObject(target);
                        stream.WriteNetworkId(networkId); // ~2 bytes

                        moving = IsMoving(node);
                        stream.WriteBool(moving);
               
                        SerializeTransform(stream, node, basePos, true, apply, moving,null, null); // 12.5 bytes
                        SerializeVelocities(stream, node, EffectiveSimulationRatio, apply, moving); // 12 byte
                        UpdateGridMaxSpeed(node, Sync.IsServer);
                    }
                }

                SerializeRopeData(stream, apply, gridsGroup: m_groups);
            }
            else
            {
                UpdateGridMaxSpeed(Entity, !Sync.IsServer);

                byte numRecords = stream.ReadByte();
                for (int i = 0; i < numRecords; i++)
                {               
                    NetworkId networkId = stream.ReadNetworkId(); // ~2 bytes
                    MyCubeGridReplicable replicable = MyMultiplayer.Static.ReplicationLayer.GetObjectByNetworkId(networkId) as MyCubeGridReplicable;
                    MyCubeGrid grid = replicable != null ? replicable.Grid : null;

                    moving = stream.ReadBool();
                    SerializeTransform(stream, grid, basePos, true, apply && grid != null,moving, null, null); // 12.5 bytes
                    SerializeVelocities(stream, grid, EffectiveSimulationRatio, apply && grid != null, moving); // 12 bytes
                   
                    UpdateGridMaxSpeed(grid,!Sync.IsServer);
                }

                SerializeRopeData(stream, apply);
            }
        }
 public void ForceSend(MyClientStateBase clientData)
 {
    
 }
        public void OnAck(MyClientStateBase forClient, byte packetId, bool delivered)
        {
            if (!VRage.Game.MyFinalBuildConstants.IS_OFFICIAL)
                Console.WriteLine(String.Format("delivery: {0}, {1}", packetId, delivered));
            InventoryClientData clientData = m_clientInventoryUpdate[forClient.EndpointId.Value];
            InventoryDeltaInformation packetInfo;
            if (clientData.SendPackets.TryGetValue(packetId, out packetInfo))
            {
                if (delivered == false)
                {

                    clientData.FailedIncompletePackets.Add(packetInfo);
                }

                clientData.SendPackets.Remove(packetId);
            }
        }
        private void SendStateSync(MyClientStateBase state)
        {
            var now = m_timeFunc();

            ClientData clientData;

            if (m_clientStates.TryGetValue(state.EndpointId, out clientData))
            {
                if (clientData.StateGroups.Count == 0)
                {
                    return;
                }

                EndpointId endpointId = state.EndpointId;

                // TODO: Limit events
                clientData.EventQueue.Send();

                using (m_tmpSortEntries)
                {
                    foreach (var entry in clientData.StateGroups.Values)
                    {
                        // No state sync for pending or sleeping replicables
                        if (!clientData.Replicables[entry.Owner].HasActiveStateSync)
                        {
                            continue;
                        }

                        entry.FramesWithoutSync++;
                        entry.Priority = entry.Group.GetGroupPriority(entry.FramesWithoutSync, state);

                        if (entry.Priority > 0)
                        {
                            m_tmpSortEntries.Add(entry);
                        }
                    }

                    m_tmpSortEntries.Sort(MyStateDataEntryComparer.Instance);

                    byte firstWaitingPacket = (byte)(clientData.LastReceivedAckId - m_outOfOrderAcceptThreshold);
                    byte nextPacketId       = (byte)(clientData.StateSyncPacketId + 1);

                    if (clientData.WaitingForReset || nextPacketId == firstWaitingPacket)
                    {
                        clientData.WaitingForReset = true;
                        return;
                    }

                    clientData.StateSyncPacketId++;

                    m_sendStream.ResetWrite();
                    m_sendStream.WriteByte(clientData.StateSyncPacketId);

                    int MTUBytes       = (int)m_callback.GetMTUSize(endpointId);
                    int messageBitSize = 8 * (MTUBytes - 8 - 1); // MTU - headers

                    // TODO: Rewrite
                    int maxToSend = MTUBytes / 8; // lets assume the shortest message is 8 Bytes long
                    int sent      = 0;

                    // TODO:SK limit to N in panic entries per packet
                    foreach (var entry in m_tmpSortEntries)
                    {
                        var oldWriteOffset = m_sendStream.BitPosition;
                        m_sendStream.WriteNetworkId(entry.GroupId);
                        entry.Group.Serialize(m_sendStream, state, clientData.StateSyncPacketId, messageBitSize);
                        if (m_sendStream.BitPosition > oldWriteOffset && m_sendStream.BitPosition <= messageBitSize)
                        {
                            clientData.PendingStateSyncAcks[clientData.StateSyncPacketId].Add(entry.Group);
                            sent++;
                            entry.FramesWithoutSync = 0;
                        }
                        else
                        {
                            // When serialize returns false, restore previous bit position
                            m_sendStream.SetBitPositionWrite(oldWriteOffset);
                        }

                        if (sent >= maxToSend)
                        {
                            break;
                        }
                    }
                    m_callback.SendStateSync(m_sendStream, endpointId);
                    //Server.SendMessage(m_sendStream, guid, PacketReliabilityEnum.UNRELIABLE, PacketPriorityEnum.MEDIUM_PRIORITY, MyChannelEnum.StateDataSync);
                }
            }
        }
 public void OnAck(MyClientStateBase forClient, byte packetId, bool delivered)
 {
     
 }
        private void SendStateSync(MyClientStateBase state)
        {
            var now = m_timeFunc();

            ClientData clientData;
            if (m_clientStates.TryGetValue(state.EndpointId, out clientData))
            {
                if (clientData.StateGroups.Count == 0)
                    return;

                EndpointId endpointId = state.EndpointId;

                // TODO: Limit events
                clientData.EventQueue.Send();

                using (m_tmpSortEntries)
                {
                    foreach (var entry in clientData.StateGroups.Values)
                    {
                        // No state sync for pending or sleeping replicables
                        if (!clientData.Replicables[entry.Owner].HasActiveStateSync)
                            continue;

                        entry.FramesWithoutSync++;
                        entry.Priority = entry.Group.GetGroupPriority(entry.FramesWithoutSync, state);

                        if (entry.Priority > 0)
                            m_tmpSortEntries.Add(entry);
                    }

                    m_tmpSortEntries.Sort(MyStateDataEntryComparer.Instance);

                    byte firstWaitingPacket = (byte)(clientData.LastReceivedAckId - m_outOfOrderAcceptThreshold);
                    byte nextPacketId = (byte)(clientData.StateSyncPacketId + 1);

                    if (clientData.WaitingForReset || nextPacketId == firstWaitingPacket)
                    {
                        clientData.WaitingForReset = true;
                        return;
                    }

                    clientData.StateSyncPacketId++;

                    m_sendStream.ResetWrite();
                    m_sendStream.WriteByte(clientData.StateSyncPacketId);

                    int MTUBytes = (int)m_callback.GetMTUSize(endpointId);
                    int messageBitSize = 8 * (MTUBytes - 8 - 1); // MTU - headers

                    // TODO: Rewrite
                    int maxToSend = MTUBytes / 8; // lets assume the shortest message is 8 Bytes long
                    int sent = 0;

                    // TODO:SK limit to N in panic entries per packet
                    foreach (var entry in m_tmpSortEntries)
                    {
                        var oldWriteOffset = m_sendStream.BitPosition;
                        m_sendStream.WriteNetworkId(entry.GroupId);
                        entry.Group.Serialize(m_sendStream, state, clientData.StateSyncPacketId, messageBitSize);
                        if (m_sendStream.BitPosition > oldWriteOffset && m_sendStream.BitPosition <= messageBitSize)
                        {
                            clientData.PendingStateSyncAcks[clientData.StateSyncPacketId].Add(entry.Group);
                            sent++;
                            entry.FramesWithoutSync = 0;
                        }
                        else
                        {
                            // When serialize returns false, restore previous bit position
                            m_sendStream.SetBitPositionWrite(oldWriteOffset);
                        }

                        if (sent >= maxToSend)
                        {
                            break;
                        }
                    }
                    m_callback.SendStateSync(m_sendStream, endpointId);
                    //Server.SendMessage(m_sendStream, guid, PacketReliabilityEnum.UNRELIABLE, PacketPriorityEnum.MEDIUM_PRIORITY, MyChannelEnum.StateDataSync);
                }
            }
        }
 public abstract float GetPriority(MyClientStateBase client);
示例#36
0
 public void CreateClientData(MyClientStateBase forClient)
 {
 }
示例#37
0
 public static Token Set(EndpointId endpoint, MyClientStateBase client, bool validate)
 {
     return(new Token(new MyEventContext(endpoint, client, validate)));
 }
示例#38
0
 public void OnClientJoined(EndpointId endpointId,MyClientStateBase clientState)
 {
     OnClientConnected(endpointId,clientState);
 }
 public void OnClientReady(EndpointId endpointId, MyClientStateBase clientState)
 {
     Debug.Assert(!m_clientStates.ContainsKey(endpointId), "Client entry already exists, bad call to OnClientJoined?");
     clientState.EndpointId = endpointId;
     m_clientStates.Add(endpointId, new ClientData(clientState, m_eventQueueSender));
     SendServerData(endpointId);
 }
 public ClientData(MyClientStateBase emptyState, Action<BitStream, EndpointId> sender)
 {
     State = emptyState;
     EventQueue = new MyPacketQueue(512, sender);
 }