Example #1
0
        protected bool ReadChunkHeader(DataStreamReader stream, ref DataStreamReader.Context ctx
                                       , out DataStreamReader chunk, out DataStreamReader.Context ctx2, out ushort targetPlayerId, out ushort senderPlayerId)
        {
            chunk          = default;
            ctx2           = default;
            targetPlayerId = 0;
            senderPlayerId = 0;

            int pos = stream.GetBytesRead(ref ctx);

            if (pos >= stream.Length)
            {
                return(false);
            }
            ushort dataLength = stream.ReadUShort(ref ctx);

            if (dataLength == 0)
            {
                return(false);
            }

            chunk          = stream.ReadChunk(ref ctx, dataLength);
            targetPlayerId = chunk.ReadUShort(ref ctx2);
            senderPlayerId = chunk.ReadUShort(ref ctx2);
            return(true);
        }
Example #2
0
        public unsafe void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            var entities     = chunk.GetNativeArray(entityType);
            var bufferAccess = chunk.GetBufferAccessor(bufferType);

            for (int i = 0; i < bufferAccess.Length; ++i)
            {
                var dynArray            = bufferAccess[i];
                DataStreamReader reader = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)dynArray.GetUnsafePtr(), dynArray.Length);
                var ctx = default(DataStreamReader.Context);
                while (reader.GetBytesRead(ref ctx) < reader.Length)
                {
                    int type = reader.ReadInt(ref ctx);
                    if (type < internalRpcCollectionLength)
                    {
                        internalRpcCollection.ExecuteRpc(type, reader, ref ctx, entities[i], commandBuffer, chunkIndex);
                    }
                    else
                    {
                        rpcCollection.ExecuteRpc(type - internalRpcCollectionLength, reader, ref ctx, entities[i], commandBuffer, chunkIndex);
                    }
                }

                dynArray.Clear();
            }
        }
Example #3
0
        protected unsafe override void OnUpdate()
        {
            // TODO: LZ:
            //      not use Allocator.Persistent
            var ents = m_RpcBufferQuery.ToEntityArray(Allocator.TempJob);

            for (var i = 0; i < ents.Length; ++i)
            {
                var ent    = ents[i];
                var rpcBuf = EntityManager.GetBuffer <IncomingRpcDataStreamBufferComponent>(ent);

                DataStreamReader reader = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)rpcBuf.GetUnsafePtr(), rpcBuf.Length);

                var ctx = default(DataStreamReader.Context);
                while (reader.GetBytesRead(ref ctx) < reader.Length)
                {
                    int type = reader.ReadInt(ref ctx);
                    if (type < m_InternalRpcCollectionLength)
                    {
                        m_InternalRpcCollection.ExecuteRpc(type, reader, ref ctx, ent, PostUpdateCommands);
                    }
                    else
                    {
                        m_RpcCollection.ExecuteRpc(type - m_InternalRpcCollectionLength, reader, ref ctx, ent, PostUpdateCommands);
                    }
                }

                rpcBuf.Clear();
            }
            ents.Dispose();
        }
        public bool Send(Room room, int toConnectionId, int fromConnectionId, DataStreamReader data)
        {
            if (ServerBehaviour.Config.BandwidthLimit > 0)
            {
                // Bandwidth control logic
                int taxedId = room.Server.ConnectionId == fromConnectionId ? toConnectionId : fromConnectionId;

                if (ContainsConnectedID(room.RoomId, taxedId))
                {
                    Client clientToBeTaxed = default(Client);
                    foreach (Client c in connectedClients.GetValuesForKey(room.RoomId))
                    {
                        if (c.ConnectionId == taxedId)
                        {
                            clientToBeTaxed = c;
                        }
                    }

                    int bandwidthLimit = clientToBeTaxed.IsInBandwidthGracePeriod ? ServerBehaviour.Config.GracePeriodBandwidthLimit : ServerBehaviour.Config.BandwidthLimit;

                    if (clientToBeTaxed.OutgoingBytes / (DateTime.UtcNow - clientToBeTaxed.ConnectTime).TotalSeconds > bandwidthLimit)
                    {
                        // Client used too much bandwidth. Disconnect them
                        Console.WriteLine("[INFO] Bandwidth exceeded, client disconnected for overdue. The client is " + (clientToBeTaxed.IsInBandwidthGracePeriod ? "" : "not ") + "on grace period");
                        HandleClientDisconnect(room, taxedId, true);

                        return(false);
                    }

                    // This includes relay overhead!!
                    // TODO: Strip overhead
                    clientToBeTaxed.OutgoingBytes += (ulong)data.Length;
                }
            }

            // Send the data
            DataStreamWriter writer;

            writer = driver.BeginSend(pipeline, connections[toConnectionId]);
            writer.WriteByte((byte)MessageType.Data);
            writer.WriteInt(fromConnectionId);
            unsafe
            {
                // Copy data from reader to writer
                byte *buffer;
                int   len = data.Length - data.GetBytesRead();
                data.ReadBytes((byte *)&buffer, len);
                writer.WriteBytes((byte *)&buffer, len);
            }
            driver.EndSend(writer);

            return(true);
        }
Example #5
0
        public unsafe void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            var entities     = chunk.GetNativeArray(entityType);
            var bufferAccess = chunk.GetBufferAccessor(bufferType);

            for (int i = 0; i < bufferAccess.Length; ++i)
            {
                var dynArray            = bufferAccess[i];
                DataStreamReader reader = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)dynArray.GetUnsafePtr(), dynArray.Length);
                var ctx = default(DataStreamReader.Context);
                while (reader.GetBytesRead(ref ctx) < reader.Length)
                {
                    int type = reader.ReadInt(ref ctx);
                    switch (type)
                    {
                    case 0:
                    {
                        var tmp = new RpcSetNetworkId();
                        tmp.Deserialize(reader, ref ctx);
                        tmp.Execute(entities[i], commandBuffer, chunkIndex);
                        break;
                    }

                    case 1:
                    {
                        var tmp = new RpcLoadLevel();
                        tmp.Deserialize(reader, ref ctx);
                        tmp.Execute(entities[i], commandBuffer, chunkIndex);
                        break;
                    }

                    case 2:
                    {
                        var tmp = new RpcLevelLoaded();
                        tmp.Deserialize(reader, ref ctx);
                        tmp.Execute(entities[i], commandBuffer, chunkIndex);
                        break;
                    }

                    case 3:
                    {
                        var tmp = new RpcSpawn();
                        tmp.Deserialize(reader, ref ctx);
                        tmp.Execute(entities[i], commandBuffer, chunkIndex);
                        break;
                    }
                    }
                }

                dynArray.Clear();
            }
        }
Example #6
0
        protected override void RecieveFragmentData(int hash, DataStreamReader stream, ref DataStreamReader.Context ctx, LargeBytesTransporter transporter)
        {
            int fragmentSize = stream.Length - stream.GetBytesRead(ref ctx);

            unsafe
            {
                fixed(byte *data = &transporter.data[transporter.pos])
                {
                    stream.ReadBytes(ref ctx, data, fragmentSize);
                    transporter.pos += fragmentSize;
                }
            }
            //Debug.Log ("RecieveFragmentData Hash=" + transporter.hash + ", Pos" + transporter.pos);
        }
Example #7
0
        public static unsafe void Add <T>(this DynamicBuffer <T> self, ref DataStreamReader reader)
            where T : struct, IBufferElementData
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (UnsafeUtility.SizeOf <T>() != 1)
            {
                throw new System.InvalidOperationException("Can only Add to DynamicBuffers of size 1 from DataStreamReaders");
            }
#endif
            var oldLen = self.Length;
            var length = reader.Length - reader.GetBytesRead();
            self.ResizeUninitialized(oldLen + length);
            reader.ReadBytes((byte *)self.GetUnsafePtr() + oldLen, length);
        }
Example #8
0
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                var entities              = chunk.GetNativeArray(entityType);
                var commandTargets        = chunk.GetNativeArray(commandTargetType);
                var snapshotAckComponents = chunk.GetNativeArray(snapshotAckType);

                var inBuffer = chunk.GetBufferAccessor(inBufferType);

                for (int i = 0; i < entities.Length; i++)
                {
                    if (commandTargets[i].Target == Entity.Null)
                    {
                        continue;
                    }

                    DynamicBuffer <TCommandData> cmdBuf      = commandDatas[commandTargets[i].Target];
                    NetworkSnapshotAckComponent  snapshotAck = snapshotAckComponents[i];

                    DataStreamReader reader = inBuffer[i].AsDataStreamReader();
                    while (reader.GetBytesRead() < reader.Length)
                    {
                        uint tick = reader.ReadUInt();

                        var          serilaizer = default(TCommandSerializer);
                        TCommandData cmd        = default;
                        cmd.Tick = tick;
                        serilaizer.Deserialize(ref reader, ref cmd);

                        int age = (int)(serverTick - cmd.Tick);
                        age *= 256;
                        snapshotAck.ServerCommandAge = (snapshotAck.ServerCommandAge * 7 + age) / 8;
                        cmdBuf.AddCommandData(cmd);

                        // 读取冗余输入
                        for (uint j = 1; j <= GlobalConstants.InputBufferSendSize; ++j)
                        {
                            cmd.Tick = tick - j;
                            serilaizer.Deserialize(ref reader, ref cmd);
                            cmdBuf.AddCommandData(cmd);
                        }
                    }

                    snapshotAckComponents[i] = snapshotAck;
                    inBuffer[i].Clear();
                }
            }
Example #9
0
        protected override LargeBytesTransporter RecieveStart(int hash, DataStreamReader stream, ref DataStreamReader.Context ctx)
        {
            string name        = stream.ReadString(ref ctx);
            int    dataSize    = stream.ReadInt(ref ctx);
            var    transporter = new LargeBytesTransporter(hash, new byte[dataSize]);

            transporter.name = name;
            int fragmentSize = stream.Length - stream.GetBytesRead(ref ctx);

            unsafe
            {
                fixed(byte *data = &transporter.data[transporter.pos])
                {
                    stream.ReadBytes(ref ctx, data, fragmentSize);
                    transporter.pos += fragmentSize;
                }
            }
            return(transporter);
        }
        protected override void RecieveFragmentData(int hash, DataStreamReader stream, ref DataStreamReader.Context ctx, FileTransporter transporter)
        {
            int fragmentSize = stream.Length - stream.GetBytesRead(ref ctx);

            while (transporter.bufferPos + fragmentSize > transporter.buffer.Length)
            {
                transporter.Resize(transporter.buffer.Length * 2);
                //Debug.Log ("Resize Buffer " + transporter.buffer.Length);
            }

            unsafe
            {
                fixed(byte *data = &transporter.buffer[transporter.bufferPos])
                {
                    stream.ReadBytes(ref ctx, data, fragmentSize);
                    transporter.bufferPos += fragmentSize;
                }
            }
            if (!transporter.isAwait)
            {
                var task = WriteBufferToFile(transporter);
            }
        }
Example #11
0
        protected override void OnUpdate()
        {
            if (m_PlayerQuery.IsEmptyIgnoreFilter)
            {
                m_DeserializeData.Entities.Clear();
                m_DeserializeData.GhostIds.Clear();
                m_DeserializeData.KnownArchetypes.Clear();
                m_DeserializeData.GhostToEntityMap.Clear();

                using (var replicatedEntities = m_ReplicatedQuery.ToEntityArray(Allocator.TempJob))
                {
                    foreach (var ent in replicatedEntities)
                    {
                        EntityManager.DestroyEntity(ent);
                    }
                }

                return;
            }

            var player       = m_PlayerQuery.GetSingletonEntity();
            var incomingData = EntityManager.GetBuffer <IncomingSnapshotDataStreamBufferComponent>(player).Reinterpret <byte>();

            if (incomingData.Length == 0)
            {
                return;
            }

            m_Dependency.Complete();
            m_Dependency = default;

            var snapshot      = incomingData.ToNativeArray(Allocator.TempJob);
            var reader        = new DataStreamReader(snapshot);
            var ctx           = default(DataStreamReader.Context);
            var snapshotCount = 0;

            while (reader.GetBytesRead(ref ctx) < reader.Length)
            {
                var safetyData = reader.ReadByte(ref ctx);
                var tick       = reader.ReadUInt(ref ctx);
                var needDelay  = false;

                Profiler.BeginSample("Apply Delayed");
                if (tick != m_PreviousTick + 1 && m_PreviousTick != uint.MaxValue)
                {
                    var isReliable = false;
                    using (var snapshotEntities = m_Delayed.ToEntityArray(Allocator.TempJob))
                        using (var snapshotInfoArray = m_Delayed.ToComponentDataArray <DelayedSnapshotInfo>(Allocator.TempJob))
                        {
                            var min = uint.MaxValue;
                            var max = 0u;
                            // get min-max first
                            foreach (var info in snapshotInfoArray)
                            {
                                if (info.tick < min)
                                {
                                    min = info.tick;
                                }
                                if (info.tick > max)
                                {
                                    max = info.tick;
                                }
                            }

                            // we can only continue if the incoming snapshot is right after the previous one
                            if (max + 1 == tick)
                            {
                                isReliable = true;

                                var targets = new NativeList <Entity>(snapshotEntities.Length, Allocator.Temp);
                                var p       = min;
                                for (var index = 0; index < snapshotInfoArray.Length;)
                                {
                                    var info = snapshotInfoArray[index];
                                    if (p != info.tick)
                                    {
                                        index++;
                                        continue;
                                    }

                                    targets.Add(snapshotEntities[index]);
                                    p++;

                                    // reset index
                                    index = 0;
                                }

                                if (targets.Length != snapshotEntities.Length)
                                {
                                    Debug.LogWarning("Did not get enough snapshots...");
                                    isReliable = false;
                                }

                                if (isReliable)
                                {
                                    for (var index = 0; index < targets.Length; index++)
                                    {
                                        using (var data = EntityManager.GetBuffer <DelayedSnapshotBuffer>(targets[index])
                                                          .Reinterpret <byte>()
                                                          .ToNativeArray(Allocator.TempJob))
                                        {
                                            var info = EntityManager.GetComponentData <DelayedSnapshotInfo>(targets[index]);
                                            ApplySnapshot(info.tick, data);
                                        }
                                    }

                                    EntityManager.DestroyEntity(m_Delayed);
                                }
                            }
                        }

                    if (!isReliable)
                    {
                        Debug.LogError($"Reliability issue, s={safetyData} p={m_PreviousTick} n={tick}");
                        needDelay = true;
                    }
                }
                Profiler.EndSample();

                Profiler.BeginSample("Apply current snapshot");
                {
                    var compressedSize   = reader.ReadInt(ref ctx);
                    var uncompressedSize = reader.ReadInt(ref ctx);
                    var compressedMemory = new NativeArray <byte>(compressedSize, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
                    reader.ReadBytes(ref ctx, (byte *)compressedMemory.GetUnsafePtr(), compressedSize);

                    var uncompressedMemory = new NativeArray <byte>(uncompressedSize, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);

                    LastCompressedSnapshotSize   = compressedSize;
                    LastUncompressedSnapshotSize = uncompressedSize;

                    Profiler.BeginSample("Decompress");
                    LZ4Codec.Decode((byte *)compressedMemory.GetUnsafePtr(), compressedSize,
                                    (byte *)uncompressedMemory.GetUnsafePtr(), uncompressedSize);
                    Profiler.EndSample();

                    if (!needDelay)
                    {
                        ApplySnapshot(tick, uncompressedMemory);
                    }
                    else
                    {
                        var delayed = EntityManager.CreateEntity(typeof(DelayedSnapshotInfo), typeof(DelayedSnapshotBuffer));
                        EntityManager.GetBuffer <DelayedSnapshotBuffer>(delayed)
                        .Reinterpret <byte>()
                        .AddRange(uncompressedMemory);
                        EntityManager.SetComponentData(delayed, new DelayedSnapshotInfo {
                            tick = tick
                        });
                        Debug.Log("Add delayed snapshot to the table...");
                    }

                    uncompressedMemory.Dispose();
                    compressedMemory.Dispose();

                    snapshotCount++;
                }
                Profiler.EndSample();
            }

            EntityManager.GetBuffer <IncomingSnapshotDataStreamBufferComponent>(player).Clear();
            snapshot.Dispose();
        }
Example #12
0
        private void ReadDataEvent(NetworkConnection connection, DataStreamReader streamReader)
        {
            try
            {
                int senderActorNumber = connection.InternalId;
                int command           = streamReader.ReadInt();
                switch (command)
                {
                case Commands.AcknowledgeActorNumber:
                {
                    if (_acceptAllPlayers)
                    {
                        AcceptPlayer(senderActorNumber);
                    }
                    break;
                }

                case Commands.PlayerData:
                {
                    string playerData = streamReader.ReadManagedString();
                    PlayerDataReceived?.Invoke(senderActorNumber, playerData);
                    break;
                }

                case Commands.Ping:
                    _lastPingTimes[connection] = Time;
                    float            sendLocalTime = streamReader.ReadFloat();
                    DataStreamWriter writer        = _serverDriver.BeginSend(_unreliablePipeline, connection);
                    writer.WriteInt(Commands.Ping);
                    writer.WriteFloat(sendLocalTime);
                    writer.WriteFloat(Time);
                    writer.WriteFloat(UnityEngine.Time.deltaTime);
                    _serverDriver.EndSend(writer);
                    break;

                case Commands.RequestSpawnMessage:
                {
                    var connections = new NativeList <NetworkConnection>(1, Allocator.Temp)
                    {
                        connection
                    };
                    SendSpawnMessage(NetObjectManager.Instance.NetObjects, connections);
                    connections.Dispose();
                    break;
                }

                case Commands.UpdateNetObjects:
                {
                    int objectsInMessage = streamReader.ReadInt();
                    for (var obj = 0; obj < objectsInMessage; obj++)
                    {
                        int       netObjID  = streamReader.ReadInt();
                        int       size      = streamReader.ReadInt();
                        NetObject netObject = NetObjectManager.Instance.Exists(netObjID)
                                ? NetObjectManager.Instance.Get(netObjID)
                                : null;

                        // ignore illegal updates and those from local host client
                        if (netObject == null ||
                            netObject.OwnerActorNumber != senderActorNumber ||     // cheater?
                            Client.IsHost && Client.Instance.ActorNumber == senderActorNumber)
                        {
                            streamReader.DiscardBytes(size);
                        }
                        else
                        {
                            int bytesRead = streamReader.GetBytesRead();
                            try
                            {
                                netObject.Deserialize(ref streamReader, b => b.ClientAuthoritative);
                            }
                            catch (Exception e)
                            {
                                Debug.LogException(e);
                                int remainingBytes = size + bytesRead - streamReader.GetBytesRead();
                                streamReader.DiscardBytes(remainingBytes);
                            }
                        }
                    }

                    break;
                }

                case Commands.GameAction:
                {
                    int   gameActionID = streamReader.ReadInt();
                    int   actorNumber  = streamReader.ReadInt();
                    float triggerTime  = streamReader.ReadFloat();
                    try
                    {
                        GameAction             gameAction = GameActionManager.Instance.Get(gameActionID);
                        GameAction.IParameters parameters =
                            gameAction.DeserializeParameters(ref streamReader);
                        gameAction.ReceiveOnServer(parameters, actorNumber, senderActorNumber,
                                                   triggerTime);
                        break;
                    }
                    catch (Exception e)
                    {
                        Debug.LogException(e);
                        break;
                    }
                }

                case Commands.NetAssetRPC:
                {
                    float        sentServerTime = streamReader.ReadFloat();
                    int          netAssetID     = streamReader.ReadInt();
                    NetAsset     netAsset       = NetAssetManager.Instance.Get(netAssetID);
                    NetAsset.RPC rpc            = netAsset.DeserializeRPC(ref streamReader);
                    var          messageInfo    = new MessageInfo
                    {
                        SentServerTime = sentServerTime, SenderActorNumber = senderActorNumber
                    };
                    rpc.Invoke(messageInfo);
                    break;
                }

                case Commands.NetObjectRPC:
                {
                    float sentServerTime = streamReader.ReadFloat();
                    int   netObjectID    = streamReader.ReadInt();
                    if (!NetObjectManager.Instance.Exists(netObjectID))
                    {
                        Debug.LogWarning("Ignoring received RPC, because NetObject was not found.");
                        break;
                    }

                    NetObject            netObject      = NetObjectManager.Instance.Get(netObjectID);
                    ushort               netBehaviourID = streamReader.ReadUShort();
                    NetBehaviour         netBehaviour   = netObject.Get(netBehaviourID);
                    NetObjectManager.RPC rpc            =
                        NetObjectManager.Instance.DeserializeRPC(ref streamReader, netBehaviour);
                    var messageInfo = new MessageInfo
                    {
                        SentServerTime = sentServerTime, SenderActorNumber = senderActorNumber
                    };
                    rpc.Invoke(messageInfo);
                    break;
                }

                default:
                    Debug.LogException(new NetException($"Unknown command {command}"));
                    break;
                }
            }
            catch (Exception e)
            {
                Debug.LogException(new NetException("Failed to handle data event", e));
            }
        }