コード例 #1
0
    static NetworkConnection ProcessSingleConnection(UdpNetworkDriver.Concurrent driver, NetworkConnection connection)
    {
        DataStreamReader strm;

        NetworkEvent.Type cmd;
        // Pop all events for the connection
        while ((cmd = driver.PopEventForConnection(connection, out strm)) != NetworkEvent.Type.Empty)
        {
            if (cmd == NetworkEvent.Type.Data)
            {
                // For ping requests we reply with a pong message
                // A DataStreamReader.Context is required to keep track of current read position since
                // DataStreamReader is immutable
                var readerCtx = default(DataStreamReader.Context);
                int id        = strm.ReadInt(ref readerCtx);
                // Create a temporary DataStreamWriter to keep our serialized pong message
                var pongData = new DataStreamWriter(4, Allocator.Temp);
                pongData.Write(id);
                // Send the pong message with the same id as the ping
                driver.Send(NetworkPipeline.Null, connection, pongData);
            }
            else if (cmd == NetworkEvent.Type.Disconnect)
            {
                // When disconnected we make sure the connection return false to IsCreated so the next frames
                // DriverUpdateJob will remove it
                return(default(NetworkConnection));
            }
        }

        return(connection);
    }
コード例 #2
0
    public void Execute(int index)
    {
        DataStreamReader stream;

        if (!connections[index].IsCreated)
        {
            Assert.IsTrue(true);
        }

        NetworkEvent.Type cmd;
        while ((cmd = driver.PopEventForConnection(connections[index], out stream)) !=
               NetworkEvent.Type.Empty)
        {
            if (cmd == NetworkEvent.Type.Data)
            {
                var  readerCtx = default(DataStreamReader.Context);
                uint number    = stream.ReadUInt(ref readerCtx);

                Debug.Log("Got " + number + " from the Client adding + 2 to it.");
                number += 2;

                using (var writer = new DataStreamWriter(4, Allocator.Temp))
                {
                    writer.Write(number);
                    driver.Send(pipeline, connections[index], writer);
                }
            }
            else if (cmd == NetworkEvent.Type.Disconnect)
            {
                Debug.Log("Client disconnected from server");
                connections[index] = default(NetworkConnection);
            }
        }
    }
コード例 #3
0
        public unsafe void Execute(Entity entity, int index, ref NetworkStreamConnection connection)
        {
            if (!connection.Value.IsCreated)
            {
                return;
            }
            var buffer = rpcBufferFromEntity[entity];

            if (buffer.Length > 0)
            {
                DataStreamWriter tmp = new DataStreamWriter(buffer.Length, Allocator.Temp);
                tmp.WriteBytes((byte *)buffer.GetUnsafePtr(), buffer.Length);
                driver.Send(reliablePipeline, connection.Value, tmp);
                buffer.Clear();
            }

            var cmdBuffer = cmdBufferFromEntity[entity];

            if (cmdBuffer.Length > 0)
            {
                DataStreamWriter tmp = new DataStreamWriter(cmdBuffer.Length, Allocator.Temp);
                tmp.WriteBytes((byte *)cmdBuffer.GetUnsafePtr(), cmdBuffer.Length);
                driver.Send(unreliablePipeline, connection.Value, tmp);
                cmdBuffer.Clear();
            }

            var snapBuffer = snapshotBufferFromEntity[entity];

            if (snapBuffer.Length > 0)
            {
                DataStreamWriter tmp = new DataStreamWriter(snapBuffer.Length, Allocator.Temp);
                tmp.WriteBytes((byte *)snapBuffer.GetUnsafePtr(), snapBuffer.Length);
                driver.Send(unreliablePipeline, connection.Value, tmp);
                snapBuffer.Clear();
            }
        }
コード例 #4
0
            public unsafe void Execute(Entity entity, int index, DynamicBuffer <TBufferElementData> buffer, ref NetworkConnection connection)
            {
                //if (!connection.value.IsCreated)
                //    return;

                if (buffer.Length > 0)
                {
                    driver.Send(pipeline, connection.value, (System.IntPtr)buffer.GetUnsafePtr(), buffer.Length);
                    buffer.Clear();

                    /*DataStreamWriter tmp = new DataStreamWriter(buffer.Length, Allocator.Temp);
                     * tmp.WriteBytes((byte*)buffer.GetUnsafePtr(), buffer.Length);
                     * driver.Send(unreliablePipeline, connection.Value, tmp);
                     * buffer.Clear();*/
                }
            }
コード例 #5
0
            public void Execute([ReadOnly] ref NetworkStreamConnection connection,
                                [ReadOnly] ref NetworkSnapshotAckComponent ack, [ReadOnly] ref CommandTargetComponent state)
            {
                if (typeof(TCommandData) == typeof(NullCommandData) && state.targetEntity != Entity.Null)
                {
                    return;
                }
                if (typeof(TCommandData) != typeof(NullCommandData) && !inputFromEntity.Exists(state.targetEntity))
                {
                    return;
                }
                DataStreamWriter writer = new DataStreamWriter(1200, Allocator.Temp);

                writer.Write((byte)NetworkStreamProtocol.Command);
                writer.Write(ack.LastReceivedSnapshotByLocal);
                writer.Write(ack.ReceivedSnapshotByLocalMask);
                writer.Write(localTime);
                uint returnTime = ack.LastReceivedRemoteTime;

                if (returnTime != 0)
                {
                    returnTime -= (localTime - ack.LastReceiveTimestamp);
                }
                writer.Write(returnTime);
                writer.Write(inputTargetTick);
                if (state.targetEntity != Entity.Null)
                {
                    var          input = inputFromEntity[state.targetEntity];
                    TCommandData baselineInputData;
                    input.GetDataAtTick(inputTargetTick, out baselineInputData);
                    baselineInputData.Serialize(writer);
                    for (uint inputIndex = 1; inputIndex < k_InputBufferSendSize; ++inputIndex)
                    {
                        TCommandData inputData;
                        input.GetDataAtTick(inputTargetTick - inputIndex, out inputData);
                        inputData.Serialize(writer, baselineInputData, compressionModel);
                    }

                    writer.Flush();
                }
#if UNITY_EDITOR || DEVELOPMENT_BUILD
                netStats[0] = inputTargetTick;
                netStats[1] = (uint)writer.Length;
#endif

                driver.Send(unreliablePipeline, connection.Value, writer);
            }
コード例 #6
0
    public void Execute(int i)
    {
        SoakMessage inbound  = default(SoakMessage);
        SoakMessage outbound = default(SoakMessage);

        if (connections[i].Connection.IsCreated)
        {
            var ctx = connections[i];
            DataStreamReader  strm;
            NetworkEvent.Type cmd;
            bool close = false;
            while ((cmd = driver.PopEventForConnection(ctx.Connection, out strm)) != NetworkEvent.Type.Empty)
            {
                if (cmd == NetworkEvent.Type.Data)
                {
                    var readerCtx = default(DataStreamReader.Context);
                    unsafe
                    {
                        strm.ReadBytes(ref readerCtx, inbound.data, strm.Length);
                        Assert.AreEqual(strm.Length, inbound.length + SoakMessage.HeaderLength);

                        outbound.id       = inbound.id;
                        outbound.sequence = ctx.NextSequenceId++;

                        var soakData = new DataStreamWriter(SoakMessage.HeaderLength, Allocator.Temp);
                        soakData.WriteBytes(outbound.data, SoakMessage.HeaderLength);

                        driver.Send(pipeline, connections[i].Connection, soakData);
                    }
                }
                else if (cmd == NetworkEvent.Type.Disconnect)
                {
                    close = true;
                }
            }

            if (close)
            {
                ctx.Connection     = default(NetworkConnection);
                ctx.NextSequenceId = -1;
            }
            connections[i] = ctx;
        }
    }
コード例 #7
0
        public void Execute(ref PingServerConnectionComponentData connection)
        {
            DataStreamReader strm;

            NetworkEvent.Type cmd;
            while ((cmd = driver.PopEventForConnection(connection.connection, out strm)) != NetworkEvent.Type.Empty)
            {
                if (cmd == NetworkEvent.Type.Data)
                {
                    var readerCtx = default(DataStreamReader.Context);
                    int id        = strm.ReadInt(ref readerCtx);
                    var pongData  = new DataStreamWriter(4, Allocator.Temp);
                    pongData.Write(id);
                    driver.Send(NetworkPipeline.Null, connection.connection, pongData);
                }
                else if (cmd == NetworkEvent.Type.Disconnect)
                {
                    connection = new PingServerConnectionComponentData {
                        connection = default(NetworkConnection)
                    };
                }
            }
        }
コード例 #8
0
        public unsafe void Execute(Entity entity, int index, [ReadOnly] ref CommandTargetComponent state)
        {
            DataStreamWriter writer = new DataStreamWriter(128, Allocator.Temp);
            var ack = ackSnapshot[entity];

            writer.Write((byte)NetworkStreamProtocol.Command);
            writer.Write(ack.LastReceivedSnapshotByLocal);
            writer.Write(ack.ReceivedSnapshotByLocalMask);
            writer.Write(localTime);
            writer.Write(ack.LastReceivedRemoteTime - (localTime - ack.LastReceiveTimestamp));
            if (state.targetEntity != Entity.Null && inputFromEntity.Exists(state.targetEntity))
            {
                var          input = inputFromEntity[state.targetEntity];
                TCommandData inputData;
                if (input.GetDataAtTick(inputTargetTick, out inputData) && inputData.Tick == inputTargetTick)
                {
                    writer.Write(inputTargetTick);
                    inputData.Serialize(writer);
                }
            }

            driver.Send(unreliablePipeline, connectionFromEntity[entity].Value, writer);
        }
コード例 #9
0
    public void Execute(int index)
    {
        DataStreamReader stream;

        if (!connections[index].IsCreated)
        {
            Assert.IsTrue(true);
        }

        NetworkEvent.Type cmd;
        while ((cmd = driver.PopEventForConnection(connections[index], out stream)) !=
               NetworkEvent.Type.Empty)
        {
            if (cmd == NetworkEvent.Type.Data)
            {
                var    readerCtx = default(DataStreamReader.Context);
                byte[] value     = stream.ReadBytesAsArray(ref readerCtx, stream.Length);

                CustomType ct = cts.DeSerialize(value);
                Debug.Log("Got " + ct.val + " from the Client adding + 2 to it.");
                ct.val += 2;


                var buff = cts.Serialize(ct);
                using (var writer = new DataStreamWriter(buff.Length, Allocator.Temp))
                {
                    writer.Write(buff);
                    driver.Send(NetworkPipeline.Null, connections[index], writer);
                }
            }
            else if (cmd == NetworkEvent.Type.Disconnect)
            {
                Debug.Log("Client disconnected from server");
                connections[index] = default(NetworkConnection);
            }
        }
    }
コード例 #10
0
            public unsafe void Execute(Entity entity, int index, [ReadOnly] ref CommandTargetComponent state)
            {
                DataStreamWriter writer = new DataStreamWriter(128, Allocator.Temp);
                var ack = ackSnapshot[entity];

                writer.Write((byte)NetworkStreamProtocol.Command);
                writer.Write(ack.LastReceivedSnapshotByLocal);
                writer.Write(ack.ReceivedSnapshotByLocalMask);
                writer.Write(localTime);

                // writer.Write(ack.LastReceivedRemoteTime - (localTime - ack.LastReceiveTimestamp));
                // TODO: LZ:
                //      to be confirmed
                //      we should send "t0 + (T1 - T0)", but not "t0 - (T1 - T0)"
                //
                // because:
                //      RTT should equals to : (t1 - t0) - (T1 - T0) = t1 - [t0 + (T1 - T0)]
                //      t0: A send time         // ack.LastReceivedRemoteTime
                //      T0: B receive time      // ack.LastReceiveTimestamp
                //      T1: B send time         // localTime
                //      t1: A receive time
                writer.Write(ack.LastReceivedRemoteTime + (localTime - ack.LastReceiveTimestamp));

                if (state.targetEntity != Entity.Null && inputFromEntity.Exists(state.targetEntity))
                {
                    var          input = inputFromEntity[state.targetEntity];
                    TCommandData inputData;
                    if (input.GetDataAtTick(inputTargetTick, out inputData) && inputData.Tick == inputTargetTick)
                    {
                        writer.Write(inputTargetTick);
                        inputData.Serialize(writer);
                    }
                }

                driver.Send(unreliablePipeline, connectionFromEntity[entity].Value, writer);
            }
コード例 #11
0
            public unsafe void Execute()
            {
                var snapshotAck = ackFromEntity[connectionEntity];
                var ackTick     = snapshotAck.LastReceivedSnapshotByRemote;

                DataStreamWriter dataStream = new DataStreamWriter(2048, Allocator.Temp);

                dataStream.Clear();
                dataStream.Write((byte)NetworkStreamProtocol.Snapshot);

                dataStream.Write(localTime);

                // dataStream.Write(snapshotAck.LastReceivedRemoteTime - (localTime - snapshotAck.LastReceiveTimestamp));
                // TODO: LZ:
                //      to be confirmed
                //      we should send "t0 + (T1 - T0)", but not "t0 - (T1 - T0)"
                //
                // because:
                //      RTT should equals to : (t1 - t0) - (T1 - T0) = t1 - [t0 + (T1 - T0)]
                //      t0: A send time         // snapshotAck.LastReceivedRemoteTime
                //      T0: B receive time      // snapshotAck.LastReceiveTimestamp
                //      T1: B send time         // localTime
                //      t1: A receive time
                dataStream.Write(snapshotAck.LastReceivedRemoteTime + (localTime - snapshotAck.LastReceiveTimestamp));

                dataStream.Write(currentTick);

                int entitySize = UnsafeUtility.SizeOf <Entity>();

                var  despawnLenWriter = dataStream.Write((uint)0);
                var  updateLenWriter  = dataStream.Write((uint)0);
                uint despawnLen       = 0;

                // TODO: if not all despawns fit, sort them based on age and maybe time since last send
                // TODO: only resend despawn on nack
                // FIXME: the TargetPacketSize cannot be used since CleanupGhostJob relies on all ghosts being sent every frame
                for (var chunk = 0; chunk < despawnChunks.Length /*&& dataStream.Length < TargetPacketSize*/; ++chunk)
                {
                    var entities = despawnChunks[chunk].GetNativeArray(entityType);
                    var ghosts   = despawnChunks[chunk].GetNativeArray(ghostSystemStateType);
                    for (var ent = 0; ent < entities.Length /*&& dataStream.Length < TargetPacketSize*/; ++ent)
                    {
                        if (ackTick == 0 || SequenceHelpers.IsNewer(ghosts[ent].despawnTick, ackTick))
                        {
                            dataStream.WritePackedUInt((uint)ghosts[ent].ghostId, compressionModel);
                            ++despawnLen;
                        }
                    }
                }

                uint updateLen    = 0;
                var  serialChunks = new NativeList <PrioChunk>(ghostChunks.Length + serialSpawnChunks.Length, Allocator.Temp);

                serialChunks.AddRange(serialSpawnChunks);
                var existingChunks = new NativeHashMap <ArchetypeChunk, int>(ghostChunks.Length, Allocator.Temp);
                // TODO: LZ:
                //      temp hack, fix me
                int maxCount = serialSpawnChunks.Length;

                for (int chunk = 0; chunk < ghostChunks.Length; ++chunk)
                {
                    SerializationState chunkState;
                    var addNew = !chunkSerializationData.TryGetValue(ghostChunks[chunk], out chunkState);
                    // FIXME: should be using chunk sequence number instead of this hack
                    if (!addNew && chunkState.arch != ghostChunks[chunk].Archetype)
                    {
                        UnsafeUtility.Free(chunkState.snapshotData, Allocator.Persistent);
                        chunkSerializationData.Remove(ghostChunks[chunk]);
                        addNew = true;
                    }
                    if (addNew)
                    {
                        chunkState.lastUpdate = currentTick - 1;
                        chunkState.startIndex = 0;
                        chunkState.ghostType  = serializers.FindSerializer(ghostChunks[chunk].Archetype);
                        chunkState.arch       = ghostChunks[chunk].Archetype;

                        chunkState.snapshotWriteIndex = 0;
                        int serializerDataSize = serializers.GetSnapshotSize(chunkState.ghostType);
                        chunkState.snapshotData = (byte *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <int>() * GhostSystemConstants.SnapshotHistorySize + GhostSystemConstants.SnapshotHistorySize * ghostChunks[chunk].Capacity * (UnsafeUtility.SizeOf <Entity>() + serializerDataSize), 16, Allocator.Persistent);

                        // Just clear snapshot index
                        UnsafeUtility.MemClear(chunkState.snapshotData, UnsafeUtility.SizeOf <int>() * GhostSystemConstants.SnapshotHistorySize);

                        chunkSerializationData.TryAdd(ghostChunks[chunk], chunkState);
                    }

                    existingChunks.TryAdd(ghostChunks[chunk], 1);
                    // FIXME: only if modified or force sync
                    var ghostType = chunkState.ghostType;
                    var pc        = new PrioChunk
                    {
                        chunk      = ghostChunks[chunk],
                        ghostState = null,
                        priority   = serializers.CalculateImportance(ghostType, ghostChunks[chunk]) * (int)(currentTick - chunkState.lastUpdate),
                        startIndex = chunkState.startIndex,
                        ghostType  = ghostType
                    };
                    serialChunks.Add(pc);
                    if (ghostChunks[chunk].Count > maxCount)
                    {
                        maxCount = ghostChunks[chunk].Count;
                    }
                }

                var oldChunks = chunkSerializationData.GetKeyArray(Allocator.Temp);

                for (int i = 0; i < oldChunks.Length; ++i)
                {
                    int val;
                    if (!existingChunks.TryGetValue(oldChunks[i], out val))
                    {
                        SerializationState chunkState;
                        chunkSerializationData.TryGetValue(oldChunks[i], out chunkState);
                        UnsafeUtility.Free(chunkState.snapshotData, Allocator.Persistent);
                        chunkSerializationData.Remove(oldChunks[i]);
                    }
                }

                NativeArray <PrioChunk> serialChunkArray = serialChunks;

                serialChunkArray.Sort();
                var availableBaselines = new NativeList <SnapshotBaseline>(GhostSystemConstants.SnapshotHistorySize, Allocator.Temp);
                var baselinePerEntity  = new NativeArray <int>(maxCount * 3, Allocator.Temp);

                for (int pc = 0; pc < serialChunks.Length && dataStream.Length < TargetPacketSize; ++pc)
                {
                    var chunk     = serialChunks[pc].chunk;
                    var ghostType = serialChunks[pc].ghostType;

                    Entity *           currentSnapshotEntity = null;
                    byte *             currentSnapshotData   = null;
                    SerializationState chunkState;
                    int dataSize = 0;
                    availableBaselines.Clear();
                    if (chunkSerializationData.TryGetValue(chunk, out chunkState))
                    {
                        dataSize = serializers.GetSnapshotSize(chunkState.ghostType);

                        uint *snapshotIndex = (uint *)chunkState.snapshotData;
                        snapshotIndex[chunkState.snapshotWriteIndex] = currentTick;
                        int baseline = (GhostSystemConstants.SnapshotHistorySize + chunkState.snapshotWriteIndex - 1) % GhostSystemConstants.SnapshotHistorySize;
                        while (baseline != chunkState.snapshotWriteIndex)
                        {
                            if (snapshotAck.IsReceivedByRemote(snapshotIndex[baseline]))
                            {
                                byte *dataBase = chunkState.snapshotData +
                                                 UnsafeUtility.SizeOf <int>() * GhostSystemConstants.SnapshotHistorySize +
                                                 baseline * (dataSize + entitySize) * chunk.Capacity;
                                availableBaselines.Add(new SnapshotBaseline
                                {
                                    tick     = snapshotIndex[baseline],
                                    snapshot = dataBase + entitySize * chunk.Capacity,
                                    entity   = (Entity *)(dataBase)
                                });
                            }

                            baseline = (GhostSystemConstants.SnapshotHistorySize + baseline - 1) % GhostSystemConstants.SnapshotHistorySize;
                        }
                        // Find the acked snapshot to delta against, setup pointer to current and previous entity* and data*
                        // Remember to bump writeIndex when done
                        currentSnapshotData   = chunkState.snapshotData + UnsafeUtility.SizeOf <int>() * GhostSystemConstants.SnapshotHistorySize;
                        currentSnapshotData  += chunkState.snapshotWriteIndex * (dataSize + entitySize) * chunk.Capacity;
                        currentSnapshotEntity = (Entity *)currentSnapshotData;
                        currentSnapshotData  += entitySize * chunk.Capacity;
                    }

                    var ghosts = serialChunks[pc].ghostState;
                    if (ghosts == null)
                    {
                        ghosts = (GhostSystemStateComponent *)chunk.GetNativeArray(ghostSystemStateType).GetUnsafeReadOnlyPtr();
                    }

                    var ghostEntities = chunk.GetNativeArray(entityType);
                    int ent;
                    if (serialChunks[pc].startIndex < chunk.Count)
                    {
                        dataStream.WritePackedUInt((uint)ghostType, compressionModel);
                        dataStream.WritePackedUInt((uint)(chunk.Count - serialChunks[pc].startIndex), compressionModel);
                    }

                    // First figure out the baselines to use per entity so they can be sent as baseline + maxCount instead of one per entity
                    int targetBaselines = serializers.WantsPredictionDelta(ghostType) ? 3 : 1;
                    for (ent = serialChunks[pc].startIndex; ent < chunk.Count; ++ent)
                    {
                        int foundBaselines = 0;
                        for (int baseline = 0; baseline < availableBaselines.Length; ++baseline)
                        {
                            if (availableBaselines[baseline].entity[ent] == ghostEntities[ent])
                            {
                                baselinePerEntity[ent * 3 + foundBaselines] = baseline;
                                ++foundBaselines;
                                if (foundBaselines == targetBaselines)
                                {
                                    break;
                                }
                            }
                            // Only way an entity can be missing from a snapshot but be available in an older is if last snapshot was partial
                            else if (availableBaselines[baseline].entity[ent] != Entity.Null)
                            {
                                break;
                            }
                        }

                        if (foundBaselines == 2)
                        {
                            foundBaselines = 1;
                        }
                        while (foundBaselines < 3)
                        {
                            baselinePerEntity[ent * 3 + foundBaselines] = -1;
                            ++foundBaselines;
                        }
                    }
                    ent = serializers.Serialize(ghostType, chunk, serialChunks[pc].startIndex, currentTick,
                                                currentSnapshotEntity, currentSnapshotData, ghosts, ghostEntities,
                                                baselinePerEntity, availableBaselines, dataStream, compressionModel);
                    updateLen += (uint)(ent - serialChunks[pc].startIndex);

                    // Spawn chunks are temporary and should not be added to the state data cache
                    if (serialChunks[pc].ghostState == null)
                    {
                        // Only append chunks which contain data
                        if (ent > serialChunks[pc].startIndex)
                        {
                            if (serialChunks[pc].startIndex > 0)
                            {
                                UnsafeUtility.MemClear(currentSnapshotEntity, entitySize * serialChunks[pc].startIndex);
                            }
                            if (ent < chunk.Capacity)
                            {
                                UnsafeUtility.MemClear(currentSnapshotEntity + ent, entitySize * (chunk.Capacity - ent));
                            }
                            chunkState.snapshotWriteIndex = (chunkState.snapshotWriteIndex + 1) % GhostSystemConstants.SnapshotHistorySize;
                        }

                        if (ent >= chunk.Count)
                        {
                            chunkState.lastUpdate = currentTick;
                            chunkState.startIndex = 0;
                        }
                        else
                        {
                            // TODO: should this always be run or should partial chunks only be allowed for the highest priority chunk?
                            //if (pc == 0)
                            chunkState.startIndex = ent;
                        }
                        chunkSerializationData.Remove(chunk);
                        chunkSerializationData.TryAdd(chunk, chunkState);
                    }
                }

                dataStream.Flush();
                despawnLenWriter.Update(despawnLen);
                updateLenWriter.Update(updateLen);

                driver.Send(unreliablePipeline, connectionFromEntity[connectionEntity].Value, dataStream);
            }
コード例 #12
0
        public void Execute(Entity entity, int index, ref NetworkServerConnection serverConnection)
        {
            DataStreamReader stream;

            NetworkEvent.Type command;
            while ((command = driver.PopEventForConnection(serverConnection.connection, out stream)) != NetworkEvent.Type.Empty)
            {
                if (command == NetworkEvent.Type.Data)
                {
                    /*
                     * Structure of a message to be sent over the server
                     * [size of message, not including this part, sizeof(int)][command type sizeof(int)][other data]
                     */
                    Debug.Log("data command on server");
                    DataStreamReader.Context readerCtx = default(DataStreamReader.Context);
                    byte[] lengthOfDataAsBytes         = stream.ReadBytesAsArray(ref readerCtx, sizeof(int));
                    if (BitConverter.IsLittleEndian)
                    {
                        Array.Reverse(lengthOfDataAsBytes);
                    }
                    int lengthOfData = BitConverter.ToInt32(lengthOfDataAsBytes, 0);

                    byte[] dataRead = stream.ReadBytesAsArray(ref readerCtx, lengthOfData);


                    byte[] cmdTypeRead = new byte[sizeof(int)];
                    Buffer.BlockCopy(dataRead, 0, cmdTypeRead, 0, sizeof(int));
                    if (BitConverter.IsLittleEndian)
                    {
                        Array.Reverse(cmdTypeRead);
                    }
                    int commandType = BitConverter.ToInt32(cmdTypeRead, 0);

                    Debug.Log("command type received " + commandType);
                    if (commandType == CommandType.SpawnNewPlayer)
                    {
                        int    networkId      = id[0];
                        byte[] cmdTypeAsBytes = BitConverter.GetBytes(CommandType.SpawnNewPlayer);
                        byte[] idAsBytes      = BitConverter.GetBytes(networkId);
                        if (BitConverter.IsLittleEndian)
                        {
                            Array.Reverse(cmdTypeAsBytes);
                            Array.Reverse(idAsBytes);
                        }

                        byte[] result        = NetworkingUtils.CombineBytes(cmdTypeAsBytes, idAsBytes);
                        int    lengthOfMsg   = result.Length * sizeof(byte); // in bytes, one int, just for the command type and the id
                        byte[] lengthAsBytes = BitConverter.GetBytes(lengthOfMsg);
                        if (BitConverter.IsLittleEndian)
                        {
                            Array.Reverse(lengthAsBytes);
                        }
                        result = NetworkingUtils.CombineBytes(lengthAsBytes, result);
                        DataStreamWriter data = new DataStreamWriter(sizeof(byte) * result.Length, Allocator.Temp);
                        data.Write(result);

                        id[0] += 1;

                        driver.Send(NetworkPipeline.Null, serverConnection.connection, data);

                        commandBuffer.SetComponent(index, entity, new NetworkServerConnection
                        {
                            networkId = networkId
                        });
                    }
                }
                else if (command == NetworkEvent.Type.Disconnect)
                {
                    commandBuffer.DestroyEntity(index, entity);
                }
            }
        }
コード例 #13
0
            public unsafe void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                var entities     = chunk.GetNativeArray(entityType);
                var rpcInBuffer  = chunk.GetBufferAccessor(inBufferType);
                var rpcOutBuffer = chunk.GetBufferAccessor(outBufferType);
                var connections  = chunk.GetNativeArray(connectionType);

                for (int i = 0; i < rpcInBuffer.Length; ++i)
                {
                    if (driver.GetConnectionState(connections[i].Value) != NetworkConnection.State.Connected)
                    {
                        continue;
                    }

                    var dynArray = rpcInBuffer[i];
                    var reader   = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)dynArray.GetUnsafePtr(),
                                                                                        dynArray.Length);
                    var parameters = new RpcExecutor.Parameters
                    {
                        Reader        = reader,
                        ReaderContext = default(DataStreamReader.Context),
                        CommandBuffer = commandBuffer,
                        Connection    = entities[i],
                        JobIndex      = chunkIndex
                    };
                    while (reader.GetBytesRead(ref parameters.ReaderContext) < reader.Length)
                    {
                        var rpcIndex = reader.ReadUShort(ref parameters.ReaderContext);
                        if (rpcIndex == ushort.MaxValue)
                        {
                            // Special value for NetworkProtocolVersion
                            var netCodeVersion = reader.ReadInt(ref parameters.ReaderContext);
                            var gameVersion    = reader.ReadInt(ref parameters.ReaderContext);
                            var rpcVersion     = reader.ReadULong(ref parameters.ReaderContext);
                            if (netCodeVersion != protocolVersion.NetCodeVersion ||
                                gameVersion != protocolVersion.GameVersion ||
                                rpcVersion != protocolVersion.RpcCollectionVersion)
                            {
                                commandBuffer.AddComponent(chunkIndex, entities[i], new NetworkStreamRequestDisconnect {
                                    Reason = NetworkStreamDisconnectReason.BadProtocolVersion
                                });
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                                throw new InvalidOperationException("Network protocol mismatch");
#else
                                return;
#endif
                            }
                        }
                        else if (rpcIndex >= execute.Length)
                        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                            throw new InvalidOperationException("Received an invalid RPC");
#else
                            return;
#endif
                        }
                        else
                        {
                            execute[rpcIndex].Execute.Ptr.Invoke(ref parameters);
                        }
                    }

                    dynArray.Clear();

                    var sendBuffer = rpcOutBuffer[i];
                    if (sendBuffer.Length > 0)
                    {
                        DataStreamWriter tmp = new DataStreamWriter(sendBuffer.Length, Allocator.Temp);
                        tmp.WriteBytes((byte *)sendBuffer.GetUnsafePtr(), sendBuffer.Length);
                        driver.Send(reliablePipeline, connections[i].Value, tmp);
                        sendBuffer.Clear();
                    }
                }
            }
コード例 #14
0
        public void Execute(Entity entity, int index, ref NetworkClientConnection clientConnection)
        {
            if (!serverEndPoint.IsValid)
            {
                // TODO: disconnect if the server is not running on the end point
                commandBuffer.DestroyEntity(index, entity);
            }
            else
            {
                DataStreamReader  stream;
                NetworkEvent.Type command;
                while ((command = driver.PopEventForConnection(clientConnection.connection, out stream)) != NetworkEvent.Type.Empty)
                {
                    if (command == NetworkEvent.Type.Connect)
                    {
                        int    lengthOfMsg    = sizeof(int); // in bytes, one int, just for the command type, not including the length integer itself
                        byte[] lengthAsBytes  = BitConverter.GetBytes(lengthOfMsg);
                        byte[] cmdTypeAsBytes = BitConverter.GetBytes(CommandType.SpawnNewPlayer);

                        if (BitConverter.IsLittleEndian)
                        {
                            Array.Reverse(lengthAsBytes);
                            Array.Reverse(cmdTypeAsBytes);
                        }
                        byte[] result = NetworkingUtils.CombineBytes(lengthAsBytes, cmdTypeAsBytes);

                        DataStreamWriter data = new DataStreamWriter(sizeof(byte) * result.Length, Allocator.Temp);
                        data.Write(result);
                        Debug.Log("size of result " + sizeof(byte) * result.Length);
                        Debug.Log("Sending confirmation of connection to server");
                        driver.Send(NetworkPipeline.Null, clientConnection.connection, data);
                    }
                    else if (command == NetworkEvent.Type.Data)
                    {
                        /*
                         * Structure of a message to be sent over the server
                         * [size of message, not including this part, sizeof(int)][command type sizeof(int)][other data]
                         */
                        DataStreamReader.Context readerCtx = default(DataStreamReader.Context);
                        byte[] lengthOfDataAsBytes         = stream.ReadBytesAsArray(ref readerCtx, sizeof(int));
                        if (BitConverter.IsLittleEndian)
                        {
                            Array.Reverse(lengthOfDataAsBytes);
                        }
                        int lengthOfData = BitConverter.ToInt32(lengthOfDataAsBytes, 0);

                        byte[] dataRead = stream.ReadBytesAsArray(ref readerCtx, lengthOfData);


                        byte[] cmdTypeRead = new byte[sizeof(int)];
                        Buffer.BlockCopy(dataRead, 0, cmdTypeRead, 0, sizeof(int));
                        if (BitConverter.IsLittleEndian)
                        {
                            Array.Reverse(cmdTypeRead);
                        }
                        int commandType = BitConverter.ToInt32(cmdTypeRead, 0);
                        if (commandType == CommandType.SpawnNewPlayer)
                        {
                            byte[] idAsBytes = new byte[sizeof(int)];
                            Buffer.BlockCopy(dataRead, sizeof(int), idAsBytes, 0, sizeof(int));
                            if (BitConverter.IsLittleEndian)
                            {
                                Array.Reverse(idAsBytes);
                            }
                            int id = BitConverter.ToInt32(idAsBytes, 0);
                            Debug.Log("player id from server " + id);

                            commandBuffer.SetComponent(index, entity, new NetworkClientConnection
                            {
                                networkId = id
                            });
                        }
                    }
                    else if (command == NetworkEvent.Type.Disconnect)
                    {
                        commandBuffer.DestroyEntity(index, entity);
                    }
                }
            }
        }