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(); } } }
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);
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(); } } } } }
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 }