Exemple #1
0
        public unsafe void Execute(Entity entity, int index, [ReadOnly] ref CommandTargetComponent commandTarget)
        {
            if (commandTarget.targetEntity == Entity.Null)
            {
                return;
            }

            var buffer = cmdBuffer[entity];

            if (buffer.Length == 0)
            {
                return;
            }
            DataStreamReader reader = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)buffer.GetUnsafePtr(), buffer.Length);
            var ctx             = default(DataStreamReader.Context);
            var tick            = reader.ReadUInt(ref ctx);
            var receivedCommand = default(TCommandData);

            receivedCommand.Deserialize(tick, reader, ref ctx);
            buffer.Clear();

            // Store received commands in the network command buffer
            var command = commandData[commandTarget.targetEntity];

            command.AddCommandData(receivedCommand);
        }
Exemple #2
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();
        }
Exemple #3
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();
            }
        }
            public unsafe void Execute(Entity entity, int index, [ReadOnly] ref PlayerStateComponentData playerState)
            {
                if (playerState.PlayerShip == Entity.Null)
                {
                    return;
                }

                var buffer = cmdBuffer[entity];

                if (buffer.Length == 0)
                {
                    return;
                }
                DataStreamReader reader = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)buffer.GetUnsafePtr(), buffer.Length);
                var ctx       = default(DataStreamReader.Context);
                var inputTick = reader.ReadUInt(ref ctx);
                var left      = reader.ReadByte(ref ctx);
                var right     = reader.ReadByte(ref ctx);
                var thrust    = reader.ReadByte(ref ctx);
                var shoot     = reader.ReadByte(ref ctx);

                buffer.Clear();
                //Debug.Log("Input delay: " + (int)(currentTick - inputTick));

                // If ship, store commands in network command buffer
                var input = shipInput[playerState.PlayerShip];

                input.mostRecentPos               = (input.mostRecentPos + 1) % 32;
                input.tick[input.mostRecentPos]   = inputTick;
                input.left[input.mostRecentPos]   = left;
                input.right[input.mostRecentPos]  = right;
                input.thrust[input.mostRecentPos] = thrust;
                input.shoot[input.mostRecentPos]  = shoot;
                shipInput[playerState.PlayerShip] = input;
            }
 //TODO できればScene単位でパケットをまとめて、type(1byte) sceneHash(4byte)の5byteのデータを削減したい
 private void CreateRpcPacket(ref DataStreamWriter writer, ref DataStreamWriter rpcPacket, byte componentIndex, byte methodId)
 {
     unsafe {
         byte *dataPtr = DataStreamUnsafeUtility.GetUnsafeReadOnlyPtr(rpcPacket);
         writer.Write((byte)BuiltInPacket.Type.BehaviourRpc);
         writer.Write(sceneHash);
         writer.Write(netId);
         writer.Write(componentIndex);
         writer.Write(methodId);
         writer.WriteBytes(dataPtr, rpcPacket.Length);
     }
 }
 protected DataStreamWriter CreateSendPacket(DataStreamWriter data, QosType qos, ushort targetId, ushort senderId)
 {
     unsafe {
         byte * dataPtr    = DataStreamUnsafeUtility.GetUnsafeReadOnlyPtr(data);
         ushort dataLength = (ushort)data.Length;
         var    writer     = new DataStreamWriter(data.Length + 4, Allocator.Temp);
         writer.Write(targetId);
         writer.Write(senderId);
         writer.WriteBytes(dataPtr, data.Length);
         return(writer);
     }
 }
        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();
            }
        }
            public unsafe void Execute(Entity entity, int index, [ReadOnly] ref CommandTargetComponent commandTarget,
                                       ref NetworkSnapshotAckComponent snapshotAck)
            {
                if (typeof(TCommandData) == typeof(NullCommandData) && commandTarget.targetEntity != Entity.Null)
                {
                    return;
                }
                if (typeof(TCommandData) != typeof(NullCommandData) && !commandData.Exists(commandTarget.targetEntity))
                {
                    return;
                }

                var buffer = cmdBuffer[entity];

                if (buffer.Length < 4)
                {
                    return;
                }
                DataStreamReader reader =
                    DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)buffer.GetUnsafePtr(), buffer.Length);
                var ctx  = default(DataStreamReader.Context);
                var tick = reader.ReadUInt(ref ctx);

                int age = (int)(serverTick - tick);

                age *= 256;
                snapshotAck.ServerCommandAge = (snapshotAck.ServerCommandAge * 7 + age) / 8;

                if (commandTarget.targetEntity != Entity.Null && buffer.Length > 4)
                {
                    var command = commandData[commandTarget.targetEntity];
                    var baselineReceivedCommand = default(TCommandData);
                    baselineReceivedCommand.Deserialize(tick, reader, ref ctx);
                    // Store received commands in the network command buffer
                    command.AddCommandData(baselineReceivedCommand);
                    for (uint i = 1; i < CommandSendSystem <TCommandData> .k_InputBufferSendSize; ++i)
                    {
                        var receivedCommand = default(TCommandData);
                        receivedCommand.Deserialize(tick - i, reader, ref ctx, baselineReceivedCommand,
                                                    compressionModel);
                        // Store received commands in the network command buffer
                        command.AddCommandData(receivedCommand);
                    }
                }
#if UNITY_EDITOR || DEVELOPMENT_BUILD
                netStats[0]  = serverTick;
                netStats[1] += (uint)buffer.Length + 16u; // 16 is the ack fields which are already processed
#endif
                buffer.Clear();
            }
Exemple #9
0
 protected DataStreamWriter CreateSendPacket(DataStreamWriter data, QosType qos, NativeList <ushort> targetIdList, ushort senderId)
 {
     unsafe {
         byte * dataPtr    = DataStreamUnsafeUtility.GetUnsafeReadOnlyPtr(data);
         ushort dataLength = (ushort)data.Length;
         var    writer     = new DataStreamWriter(data.Length + 6 + targetIdList.Length * 2, Allocator.Temp);
         writer.Write(ushort.MaxValue - 1);
         writer.Write(senderId);
         writer.Write((ushort)targetIdList.Length);
         for (int i = 0; i < targetIdList.Length; i++)
         {
             writer.Write(targetIdList[i]);
         }
         writer.WriteBytes(dataPtr, data.Length);
         return(writer);
     }
 }
        private unsafe void OnArrayProcess(NativeArray <Entity> entities, NativeArray <CommandTargetComponent> targetArray)
        {
            var serverTick = World.GetExistingSystem <ServerSimulationSystemGroup>().ServerTick;

            for (var ent = 0; ent < entities.Length; ent++)
            {
                var target = targetArray[ent];
                if (target.targetEntity == default)
                {
                    continue;
                }

                var buffer = EntityManager.GetBuffer <IncomingCommandDataStreamBufferComponent>(entities[ent]);
                if (buffer.Length <= 0)
                {
                    continue;
                }

                var reader = DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)buffer.GetUnsafePtr(), buffer.Length);
                var ctx    = default(DataStreamReader.Context);

                var tick = reader.ReadUInt(ref ctx);
                var age  = (int)(serverTick - tick);
                age *= 256;

                var snapshotAck = EntityManager.GetComponentData <NetworkSnapshotAckComponent>(entities[ent]);
                snapshotAck.ServerCommandAge = (snapshotAck.ServerCommandAge * 7 + age) / 8;
                EntityManager.SetComponentData(entities[ent], snapshotAck);

                while (reader.GetBytesRead(ref ctx) < reader.Length)
                {
                    var type = reader.ReadByte(ref ctx);
                    if (!m_CommandCollectionSystem.SystemProcessors.TryGetValue(type, out var processor))
                    {
                        throw new KeyNotFoundException($"No processor with type '{type}' found!");
                    }

                    processor.BeginDeserialize(target.targetEntity, type);
                    processor.ProcessReceive(serverTick, reader, ref ctx, m_NetworkCompressionModel);
                }

                buffer.Clear();
            }
        }
Exemple #11
0
            public unsafe void Execute()
            {
                // FIXME: should handle any number of connections with individual ghost mappings for each
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (players.Length > 1)
                {
                    throw new InvalidOperationException("Ghost receive system only supports a single connection");
                }
#endif
                while (delayedDespawnQueue.Count > 0 &&
                       !SequenceHelpers.IsNewer(delayedDespawnQueue.Peek().tick, targetTick))
                {
                    commandBuffer.RemoveComponent(delayedDespawnQueue.Dequeue().ghost, replicatedEntityType);
                }

                var snapshot = snapshotFromEntity[players[0]];
                if (snapshot.Length == 0)
                {
                    return;
                }

                var dataStream =
                    DataStreamUnsafeUtility.CreateReaderFromExistingData((byte *)snapshot.GetUnsafePtr(), snapshot.Length);
                // Read the ghost stream
                // find entities to spawn or destroy
                var readCtx    = new DataStreamReader.Context();
                var serverTick = dataStream.ReadUInt(ref readCtx);
                var ack        = snapshotAckFromEntity[players[0]];
                if (ack.LastReceivedSnapshotByLocal != 0 && !SequenceHelpers.IsNewer(serverTick, ack.LastReceivedSnapshotByLocal))
                {
                    return;
                }
                if (ack.LastReceivedSnapshotByLocal != 0)
                {
                    ack.ReceivedSnapshotByLocalMask <<= (int)(serverTick - ack.LastReceivedSnapshotByLocal);
                }
                ack.ReceivedSnapshotByLocalMask  |= 1;
                ack.LastReceivedSnapshotByLocal   = serverTick;
                snapshotAckFromEntity[players[0]] = ack;

                uint despawnLen = dataStream.ReadUInt(ref readCtx);
                uint updateLen  = dataStream.ReadUInt(ref readCtx);

#if ENABLE_UNITY_COLLECTIONS_CHECKS
                int startPos = dataStream.GetBitsRead(ref readCtx);
#endif
                for (var i = 0; i < despawnLen; ++i)
                {
                    int         ghostId = (int)dataStream.ReadPackedUInt(ref readCtx, compressionModel);
                    GhostEntity ent;
                    if (!ghostEntityMap.TryGetValue(ghostId, out ent))
                    {
                        continue;
                    }

                    ghostEntityMap.Remove(ghostId);
                    // if predicted, despawn now, otherwise wait
                    if (predictedFromEntity.Exists(ent.entity))
                    {
                        commandBuffer.RemoveComponent(ent.entity, replicatedEntityType);
                    }
                    else
                    {
                        delayedDespawnQueue.Enqueue(new DelayedDespawnGhost {
                            ghost = ent.entity, tick = serverTick
                        });
                    }
                }

#if ENABLE_UNITY_COLLECTIONS_CHECKS
                netStats[0] = despawnLen;
                netStats[1] = (uint)(dataStream.GetBitsRead(ref readCtx) - startPos);
                netStats[2] = 0;
                for (int i = 0; i < serializers.Length; ++i)
                {
                    netStats[i * 3 + 3] = 0;
                    netStats[i * 3 + 4] = 0;
                    netStats[i * 3 + 5] = 0;
                }
                uint statCount         = 0;
                uint uncompressedCount = 0;
#endif

                uint targetArch    = 0;
                uint targetArchLen = 0;
                uint baselineTick  = 0;
                uint baselineTick2 = 0;
                uint baselineTick3 = 0;
                uint baselineLen   = 0;
                int  newGhosts     = 0;
                for (var i = 0; i < updateLen; ++i)
                {
                    if (targetArchLen == 0)
                    {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                        int curPos = dataStream.GetBitsRead(ref readCtx);
                        if (statCount > 0)
                        {
                            int statType = (int)targetArch;
                            netStats[statType * 3 + 3] = netStats[statType * 3 + 3] + statCount;
                            netStats[statType * 3 + 4] = netStats[statType * 3 + 4] + (uint)(curPos - startPos);
                            netStats[statType * 3 + 5] = netStats[statType * 3 + 5] + uncompressedCount;
                        }

                        startPos          = curPos;
                        statCount         = 0;
                        uncompressedCount = 0;
#endif
                        targetArch    = dataStream.ReadPackedUInt(ref readCtx, compressionModel);
                        targetArchLen = dataStream.ReadPackedUInt(ref readCtx, compressionModel);
                    }
                    --targetArchLen;

                    if (baselineLen == 0)
                    {
                        baselineTick  = serverTick - dataStream.ReadPackedUInt(ref readCtx, compressionModel);
                        baselineTick2 = serverTick - dataStream.ReadPackedUInt(ref readCtx, compressionModel);
                        baselineTick3 = serverTick - dataStream.ReadPackedUInt(ref readCtx, compressionModel);
                        baselineLen   = dataStream.ReadPackedUInt(ref readCtx, compressionModel);
                    }
                    --baselineLen;

                    int         ghostId = (int)dataStream.ReadPackedUInt(ref readCtx, compressionModel);
                    GhostEntity gent;
                    if (ghostEntityMap.TryGetValue(ghostId, out gent))
                    {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                        if (gent.ghostType != targetArch)
                        {
                            throw new InvalidOperationException("Received a ghost with an invalid ghost type");
                        }
                        //throw new InvalidOperationException("Received a ghost with an invalid ghost type " + targetArch + ", expected " + gent.ghostType);
#endif
                        serializers.Deserialize((int)targetArch, gent.entity, serverTick, baselineTick, baselineTick2, baselineTick3,
                                                dataStream, ref readCtx, compressionModel);
                    }
                    else
                    {
                        ++newGhosts;
                        serializers.Spawn((int)targetArch, ghostId, serverTick, dataStream, ref readCtx, compressionModel);
                    }

#if ENABLE_UNITY_COLLECTIONS_CHECKS
                    ++statCount;
                    if (baselineTick == serverTick)
                    {
                        ++uncompressedCount;
                    }
#endif
                }
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (statCount > 0)
                {
                    int curPos   = dataStream.GetBitsRead(ref readCtx);
                    int statType = (int)targetArch;
                    netStats[statType * 3 + 3] = netStats[statType * 3 + 3] + statCount;
                    netStats[statType * 3 + 4] = netStats[statType * 3 + 4] + (uint)(curPos - startPos);
                    netStats[statType * 3 + 5] = netStats[statType * 3 + 5] + uncompressedCount;
                }
#endif
                while (ghostEntityMap.Capacity < ghostEntityMap.Length + newGhosts)
                {
                    ghostEntityMap.Capacity += 1024;
                }
            }
            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();
                    }
                }
            }
Exemple #13
0
            public void Execute()
            {
                DataStreamReader stream;

                NetworkEvent.Type cmd;

                //前フレームで解決できなかったbufferedからuncheckedに登録.
                if (!savedUncheckedReliableDataStream.IsCreated)
                {
                    stream = new DataStreamReader(savedUncheckedReliableDataStream, 0, savedUncheckedReliableDataStream.Length);
                    int offset = 0;
                    while (offset < savedUncheckedReliableDataStream.Length)
                    {
                        var    readerCtx = default(DataStreamReader.Context);
                        ushort length    = stream.ReadUShort(ref readerCtx);
                        if (0 < length && length <= savedUncheckedReliableDataStream.Length - offset - 2)
                        {
                            uncheckedreliableStreams.Add(
                                new DataStreamReader(savedUncheckedReliableDataStream, offset + 2, length));
                            offset += length + 2;
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                while ((cmd = connection.PopEvent(driver, out stream)) != NetworkEvent.Type.Empty)
                {
                    if (cmd == NetworkEvent.Type.Connect)
                    {
                        flags[(int)FlagDef.IsConnected] = 1;
                        Debug.Log("Connect : " + connection.InternalId);
                    }
                    else if (cmd == NetworkEvent.Type.Disconnect)
                    {
                        flags[(int)FlagDef.IsDisconnected] = 1;
                        Debug.Log("Disconnect : " + connection.InternalId);
                    }
                    else if (cmd == NetworkEvent.Type.Data)
                    {
                        if (!stream.IsCreated)
                        {
                            continue;
                        }

                        var    readerCtx = default(DataStreamReader.Context);
                        byte   qosType   = stream.ReadByte(ref readerCtx);
                        ushort seqNum    = stream.ReadUShort(ref readerCtx);
                        ushort ackNum    = stream.ReadUShort(ref readerCtx);

                        //if (qosType != (byte)QosType.MeasureLatency) {
                        //	Debug.Log ("Recieve Data Len=" + stream.Length + ",QoS=" + qosType + ",Seq=" + seqNum + ",Ack=" + ackNum);
                        //}
                        //最初のregister packetはseqNumに

                        bool isInitialUpdate = flags[(int)FlagDef.IsNotInitialUpdate] == 0;

                        //ackNumの更新
                        if (seqNumbers[(int)SeqNumberDef.OtherAck] != ackNum)
                        {
                            seqNumbers[(int)SeqNumberDef.OtherAck] = ackNum;
                            //Debug.Log ("update OtherAck = " + ackNum + " first=" + isInitialUpdate);
                        }

                        switch ((QosType)qosType)
                        {
                        case QosType.MeasureLatency:
                            long currentUnixTime = System.DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                            long otherUnixTime   = stream.ReadLong(ref readerCtx);
                            seqNumbers[(int)SeqNumberDef.Latency] = (ushort)(currentUnixTime - otherUnixTime);
                            break;

                        case QosType.Unreliable:
                            dataStreams.Add(stream);
                            break;

                        case QosType.Reliable:
                            int seqNumberDiff = (int)seqNum - seqNumbers[(int)SeqNumberDef.OtherSeq];
                            if (!isInitialUpdate && seqNumberDiff > 1)
                            {
                                //Debug.Log ("Reliable seqNumberDiff > 1 recieve");
                                //順番が入れ替わってるからバッファに貯める
                                if (seqNumberDiff - 2 < uncheckedreliableStreams.Length)
                                {
                                    if (uncheckedreliableStreams[seqNumberDiff - 2].IsCreated)
                                    {
                                        uncheckedreliableStreams[seqNumberDiff - 2] = stream;
                                    }
                                }
                                else
                                {
                                    uncheckedreliableStreams.Add(stream);
                                }
                            }
                            else if (isInitialUpdate || (seqNumberDiff == 1 || seqNumberDiff == -ushort.MaxValue))
                            {
                                flags[(int)FlagDef.IsNotInitialUpdate] = 1;
                                //次の順のパケットなら確定する
                                seqNumbers[(int)SeqNumberDef.OtherSeq] = seqNum;
                                //Debug.Log ("update OtherSeq = " + seqNumbers[(int)SeqNumberDef.OtherSeq] + " first=" + isInitialUpdate);
                                //AddChunksInDataStream (stream, ref readerCtx);
                                dataStreams.Add(stream);

                                //順番待ちのパケットを確定する
                                while (uncheckedreliableStreams.Length != 0)
                                {
                                    if (!uncheckedreliableStreams[0].IsCreated)
                                    {
                                        IncrementSequenceNumber(SeqNumberDef.OtherSeq);
                                        //Debug.Log ("update OtherSeq = " + seqNumbers[(int)SeqNumberDef.OtherSeq]);
                                        //AddChunksInDataStream (uncheckedreliableStreams[0], ref readerCtx);
                                        dataStreams.Add(uncheckedreliableStreams[0]);
                                        uncheckedreliableStreams.RemoveAtSwapBack(0);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                //受信済みのSeqNumのパケットなら無視
                                //Debug.Log ("Reliable same recieve");
                            }
                            break;
                        }
                    }
                }

                //uncheckedreliableStreamsに残ったパケットはnetworkdriverから実態が消される前にコピーしておく
                unsafe {
                    //uncheckedreliableStreamsはsavedUncheckedReliableDataStreamに実態を持つ場合があるので
                    //直接savedUncheckedReliableDataStream書き込むと実態が消えてしまうのでtempまず書く
                    tempUncheckedReliableDataStream.Clear();
                    for (int i = 0; i < uncheckedreliableStreams.Length; i++)
                    {
                        int dataLength = uncheckedreliableStreams[i].Length;
                        if (tempUncheckedReliableDataStream.Capacity - tempUncheckedReliableDataStream.Length < dataLength + 2)
                        {
                            tempUncheckedReliableDataStream.Capacity *= 2;
                        }
                        byte *dataPtr = DataStreamUnsafeUtility.GetUnsafeReadOnlyPtr(uncheckedreliableStreams[i]);
                        tempUncheckedReliableDataStream.Write(dataLength);
                        tempUncheckedReliableDataStream.WriteBytes(dataPtr, dataLength);
                    }
                    savedUncheckedReliableDataStream.Clear();
                    if (savedUncheckedReliableDataStream.Capacity < tempUncheckedReliableDataStream.Capacity)
                    {
                        savedUncheckedReliableDataStream.Capacity *= tempUncheckedReliableDataStream.Capacity;
                    }
                    savedUncheckedReliableDataStream.WriteBytes(
                        tempUncheckedReliableDataStream.GetUnsafeReadOnlyPtr(), tempUncheckedReliableDataStream.Length);
                }

                //次に自分が送るパケットでどこまで受け取ったか伝える.
                seqNumbers[(int)SeqNumberDef.SelfAck] = seqNumbers[(int)SeqNumberDef.OtherSeq];
            }