예제 #1
0
            public unsafe void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                var entities    = chunk.GetNativeArray(entityType);
                var connections = chunk.GetNativeArray(connectionType);
                var inBuffers   = chunk.GetBufferAccessor(InBufferType);
                var outBuffers  = chunk.GetBufferAccessor(OutBufferType);

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

                    var parameters = new RpcExecutor.Parameters
                    {
                        Reader        = inBuffers[i].AsDataStreamReader(),
                        CommandBuffer = commandBuffer,
                        Connection    = entities[i],
                        JobIndex      = chunkIndex
                    };

#if UNITY_EDITOR || DEVELOPMENT_BUILD
                    RpcMS2(parameters.Reader.Length);
#endif
                    while (parameters.Reader.GetBytesRead() < parameters.Reader.Length)
                    {
                        var rpcIndex = parameters.Reader.ReadUShort();
                        if (rpcIndex >= execute.Length)
                        {
                        }
                        else
                        {
                            //TODO 安卓调用闪退
                            execute[rpcIndex].Execute.Ptr.Invoke(ref parameters);
                        }
                    }

                    inBuffers[i].Clear();

                    var sendBuf = outBuffers[i];
                    if (sendBuf.Length > 0)
                    {
                        DataStreamWriter tmp = driver.BeginSend(reliablePipeline, connections[i].Value);
                        if (!tmp.IsCreated)
                        {
                            return;
                        }
                        tmp.WriteBytes((byte *)sendBuf.GetUnsafePtr(), sendBuf.Length);

#if UNITY_EDITOR || DEVELOPMENT_BUILD
                        RpcMS1(tmp.Length);
#endif
                        driver.EndSend(tmp);
                        sendBuf.Clear();
                    }
                }
            }
예제 #2
0
        internal unsafe void UpdateSend(NetworkDriver.Concurrent driver, out int updateCount)
        {
            // Clear the send lock since it cannot be kept here and can be lost if there are exceptions in send
            NativeArray <byte> tmpBuffer = m_SendBuffer;
            int *sendBufferLock          = (int *)tmpBuffer.GetUnsafePtr();

            for (int connectionOffset = 0; connectionOffset < m_SendBuffer.Length; connectionOffset += sizePerConnection[SendSizeOffset])
            {
                sendBufferLock[connectionOffset / 4] = 0;
            }

            NativeArray <UpdatePipeline> sendUpdates = new NativeArray <UpdatePipeline>(m_SendStageNeedsUpdateRead.Count + m_SendStageNeedsUpdate.Length, Allocator.Temp);

            UpdatePipeline updateItem;

            updateCount = 0;
            while (m_SendStageNeedsUpdateRead.TryDequeue(out updateItem))
            {
                if (driver.GetConnectionState(updateItem.connection) == NetworkConnection.State.Connected)
                {
                    sendUpdates[updateCount++] = updateItem;
                }
            }

            int startLength = updateCount;

            for (int i = 0; i < m_SendStageNeedsUpdate.Length; i++)
            {
                if (driver.GetConnectionState(m_SendStageNeedsUpdate[i].connection) == NetworkConnection.State.Connected)
                {
                    sendUpdates[updateCount++] = m_SendStageNeedsUpdate[i];
                }
            }

            NativeList <UpdatePipeline> currentUpdates = new NativeList <UpdatePipeline>(128, Allocator.Temp);

            // Move the updates requested in this iteration to the concurrent queue so it can be read/parsed in update routine
            for (int i = 0; i < updateCount; ++i)
            {
                updateItem = sendUpdates[i];
                ToConcurrent().ProcessPipelineSend(driver, updateItem.stage, updateItem.pipeline, updateItem.connection, default, 0, currentUpdates);
예제 #3
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);
                var deserializeState = new RpcDeserializerState {
                    ghostMap = ghostMap
                };

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

                    var dynArray   = rpcInBuffer[i];
                    var parameters = new RpcExecutor.Parameters
                    {
                        Reader        = dynArray.AsDataStreamReader(),
                        CommandBuffer = commandBuffer,
                        State         = (IntPtr)UnsafeUtility.AddressOf(ref deserializeState),
                        Connection    = entities[i],
                        JobIndex      = chunkIndex
                    };
                    int msgHeaderLen = dynamicAssemblyList ? 10 : 4;
                    while (parameters.Reader.GetBytesRead() < parameters.Reader.Length)
                    {
                        int rpcIndex = 0;
                        if (dynamicAssemblyList)
                        {
                            ulong rpcHash = parameters.Reader.ReadULong();
                            if (rpcHash == 0)
                            {
                                rpcIndex = ushort.MaxValue;
                                protocolVersion.RpcCollectionVersion       = 0;
                                protocolVersion.ComponentCollectionVersion = 0;
                            }
                            else if (rpcHash != 0 && !hashToIndex.TryGetValue(rpcHash, out rpcIndex))
                            {
                                errors.Enqueue(new RpcReceiveError
                                {
                                    connection = entities[i],
                                    error      = ErrorCodes.InvalidRpc
                                });
                                break;
                            }
                        }
                        else
                        {
                            rpcIndex = parameters.Reader.ReadUShort();
                        }

                        var rpcSize = parameters.Reader.ReadUShort();
                        if (rpcIndex == ushort.MaxValue)
                        {
                            // Special value for NetworkProtocolVersion
                            var netCodeVersion   = parameters.Reader.ReadInt();
                            var gameVersion      = parameters.Reader.ReadInt();
                            var rpcVersion       = parameters.Reader.ReadULong();
                            var componentVersion = parameters.Reader.ReadULong();
                            if (netCodeVersion != protocolVersion.NetCodeVersion ||
                                gameVersion != protocolVersion.GameVersion ||
                                rpcVersion != protocolVersion.RpcCollectionVersion ||
                                componentVersion != protocolVersion.ComponentCollectionVersion)
                            {
                                errors.Enqueue(new RpcReceiveError
                                {
                                    connection = entities[i],
                                    error      = ErrorCodes.ProtocolMismatch
                                });
                                break;
                            }
                            //The connection has received the version. RpcSystem can't accept any rpc's if the NetworkProtocolVersion
                            //has not been received first.
                            var connection = connections[i];
                            connection.ProtocolVersionReceived = 1;
                            connections[i] = connection;
                        }
                        else if (rpcIndex >= execute.Length)
                        {
                            //If this is the server, we must disconnect the connection
                            errors.Enqueue(new RpcReceiveError
                            {
                                connection = entities[i],
                                error      = ErrorCodes.InvalidRpc
                            });
                            break;
                        }
                        else if (connections[i].ProtocolVersionReceived == 0)
                        {
                            errors.Enqueue(new RpcReceiveError
                            {
                                connection = entities[i],
                                error      = ErrorCodes.VersionNotReceived
                            });
                            break;
                        }
                        else
                        {
                            execute[rpcIndex].Execute.Ptr.Invoke(ref parameters);
                        }
                    }

                    dynArray.Clear();

                    var sendBuffer = rpcOutBuffer[i];
                    while (sendBuffer.Length > 0)
                    {
                        if (driver.BeginSend(reliablePipeline, connections[i].Value, out var tmp) == 0)
                        {
                            // If sending failed we stop and wait until next frame
                            if (sendBuffer.Length > tmp.Capacity)
                            {
                                var sendArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray <byte>(sendBuffer.GetUnsafePtr(), sendBuffer.Length, Allocator.Invalid);
    #if ENABLE_UNITY_COLLECTIONS_CHECKS
                                var safety = NativeArrayUnsafeUtility.GetAtomicSafetyHandle(sendBuffer.AsNativeArray());
                                NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref sendArray, safety);
    #endif
                                var reader = new DataStreamReader(sendArray);
                                reader.ReadByte();
                                reader.ReadUShort();
                                var len = reader.ReadUShort() + msgHeaderLen + 1;
                                if (len > tmp.Capacity)
                                {
                                    sendBuffer.Clear();
                                    // Could not fit a single message in the packet, this is a serious error
                                    throw new InvalidOperationException("An RPC was too big to be sent, reduce the size of your RPCs");
                                }
                                tmp.WriteBytes((byte *)sendBuffer.GetUnsafePtr(), len);
                                // Try to fit a few more messages in this packet
                                while (true)
                                {
                                    var subArray = sendArray.GetSubArray(tmp.Length, sendArray.Length - tmp.Length);
                                    reader = new DataStreamReader(subArray);
                                    reader.ReadUShort();
                                    len = reader.ReadUShort() + msgHeaderLen;
                                    if (tmp.Length + len > tmp.Capacity)
                                    {
                                        break;
                                    }
                                    tmp.WriteBytes((byte *)subArray.GetUnsafeReadOnlyPtr(), len);
                                }
                            }
                            else
                            {
                                tmp.WriteBytes((byte *)sendBuffer.GetUnsafePtr(), sendBuffer.Length);
                            }
                            // If sending failed we stop and wait until next frame
                            var result = 0;
                            if ((result = driver.EndSend(tmp)) <= 0)
                            {
                                UnityEngine.Debug.LogWarning($"An error occured during EndSend. ErrorCode: {result}");
                                break;
                            }
                            if (tmp.Length < sendBuffer.Length)
                            {
                                // Compact the buffer, removing the rpcs we did send
                                for (int cpy = tmp.Length; cpy < sendBuffer.Length; ++cpy)
                                {
                                    sendBuffer[1 + cpy - tmp.Length] = sendBuffer[cpy];
                                }
                                // Remove all but the first byte of the data we sent, first byte is identifying the packet as an rpc
                                sendBuffer.ResizeUninitialized(1 + sendBuffer.Length - tmp.Length);
                            }
                            else
                            {
                                sendBuffer.Clear();
                            }
                        }
                    }
                }
            }
예제 #4
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);
                var errors       = new NativeArray <RpcReceiveError>(rpcInBuffer.Length, Allocator.Temp);
                var errorCount   = 0;

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

                    var dynArray   = rpcInBuffer[i];
                    var parameters = new RpcExecutor.Parameters
                    {
                        Reader        = dynArray.AsDataStreamReader(),
                        CommandBuffer = commandBuffer,
                        Connection    = entities[i],
                        JobIndex      = chunkIndex
                    };
                    while (parameters.Reader.GetBytesRead() < parameters.Reader.Length)
                    {
                        var rpcIndex = parameters.Reader.ReadUShort();
                        if (rpcIndex == ushort.MaxValue)
                        {
                            // Special value for NetworkProtocolVersion
                            var netCodeVersion = parameters.Reader.ReadInt();
                            var gameVersion    = parameters.Reader.ReadInt();
                            var rpcVersion     = parameters.Reader.ReadULong();
                            if (netCodeVersion != protocolVersion.NetCodeVersion ||
                                gameVersion != protocolVersion.GameVersion ||
                                rpcVersion != protocolVersion.RpcCollectionVersion)
                            {
                                commandBuffer.AddComponent(chunkIndex, entities[i], new NetworkStreamRequestDisconnect {
                                    Reason = NetworkStreamDisconnectReason.BadProtocolVersion
                                });
                                errors[errorCount++] = new RpcReceiveError
                                {
                                    connection = entities[i],
                                    error      = ErrorCodes.ProtocolMismatch
                                };
                                break;
                            }
                        }
                        else if (rpcIndex >= execute.Length)
                        {
                            errors[errorCount++] = new RpcReceiveError
                            {
                                connection = entities[i],
                                error      = ErrorCodes.InvalidRpc
                            };
                            break;
                        }
                        else
                        {
                            execute[rpcIndex].Execute.Ptr.Invoke(ref parameters);
                        }
                    }

                    dynArray.Clear();

                    var sendBuffer = rpcOutBuffer[i];
                    if (sendBuffer.Length > 0)
                    {
                        DataStreamWriter tmp = driver.BeginSend(reliablePipeline, connections[i].Value);
                        if (!tmp.IsCreated)
                        {
                            continue;
                        }
                        tmp.WriteBytes((byte *)sendBuffer.GetUnsafePtr(), sendBuffer.Length);
                        driver.EndSend(tmp);
                        sendBuffer.Clear();
                    }
                }

#if ENABLE_UNITY_COLLECTIONS_CHECKS
// TODO: we need to report the errors produced.
                if (errorCount > 0)
                {
                    throw new InvalidOperationException("RpcSystem received malformed packets or packets with the wrong version");
                }
#endif
            }