private static void InvokeExecute(ref RpcExecutor.Parameters parameters) { var rpcData = default(RpcSetNetworkId); rpcData.Deserialize(ref parameters.Reader); parameters.CommandBuffer.AddComponent(parameters.JobIndex, parameters.Connection, new NetworkIdComponent { Value = rpcData.nid }); var ent = parameters.CommandBuffer.CreateEntity(parameters.JobIndex); parameters.CommandBuffer.AddComponent(parameters.JobIndex, ent, new ClientServerTickRate { MaxSimulationStepsPerFrame = rpcData.simMaxSteps, NetworkTickRate = rpcData.netTickRate, SimulationTickRate = rpcData.simTickRate }); }
private static void InvokeExecute(ref RpcExecutor.Parameters parameters) { RpcExecutor.ExecuteCreateRequestComponent <HeartbeatComponent>(ref parameters); }
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); 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(); } } }
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 }