public void Execute() { NetworkConnection con; while ((con = driver.Accept()) != default(NetworkConnection)) { // New connection can never have any events, if this one does - just close it DataStreamReader reader; if (con.PopEvent(driver, out reader) != NetworkEvent.Type.Empty) { con.Disconnect(driver); continue; } // create an entity for the new connection var ent = commandBuffer.CreateEntity(); commandBuffer.AddComponent(ent, new NetworkStreamConnection { Value = con }); commandBuffer.AddComponent(ent, new NetworkSnapshotAckComponent()); commandBuffer.AddComponent(ent, new CommandTargetComponent()); commandBuffer.AddBuffer <IncomingRpcDataStreamBufferComponent>(ent); var rpcBuffer = commandBuffer.AddBuffer <OutgoingRpcDataStreamBufferComponent>(ent); commandBuffer.AddBuffer <IncomingCommandDataStreamBufferComponent>(ent); commandBuffer.AddBuffer <IncomingSnapshotDataStreamBufferComponent>(ent); RpcSystem.SendProtocolVersion(rpcBuffer, protocolVersion); // Send RPC - assign network id int nid; if (!freeNetworkIds.TryDequeue(out nid)) { // Avoid using 0 nid = numNetworkId[0] + 1; numNetworkId[0] = nid; } commandBuffer.AddComponent(ent, new NetworkIdComponent { Value = nid }); rpcQueue.Schedule(rpcBuffer, ghostFromEntity, new RpcSetNetworkId { nid = nid, netTickRate = tickRate.NetworkTickRate, simMaxSteps = tickRate.MaxSimulationStepsPerFrame, simTickRate = tickRate.SimulationTickRate }); } }
public void Execute(Entity entity, int jobIndex, [ReadOnly] ref NetworkStreamConnection con) { var rpcBuffer = commandBuffer.AddBuffer <OutgoingRpcDataStreamBufferComponent>(jobIndex, entity); RpcSystem.SendProtocolVersion(rpcBuffer, protocolVersion); }
protected override void OnUpdate() { #if UNITY_EDITOR || DEVELOPMENT_BUILD m_GhostStatsCollectionSystem.AddDiscardedPackets(m_NetStats[0]); m_NetStats[0] = 0; #endif var commandBuffer = m_Barrier.CreateCommandBuffer().AsParallelWriter(); if (!HasSingleton <NetworkProtocolVersion>()) { var entity = EntityManager.CreateEntity(); var rpcVersion = World.GetExistingSystem <RpcSystem>().CalculateVersionHash(); var componentsVersion = m_GhostCollectionSystem.CalculateComponentCollectionHash(); var gameVersion = HasSingleton <GameProtocolVersion>() ? GetSingleton <GameProtocolVersion>().Version : 0; EntityManager.AddComponentData(entity, new NetworkProtocolVersion { NetCodeVersion = NetworkProtocolVersion.k_NetCodeVersion, GameVersion = gameVersion, RpcCollectionVersion = rpcVersion, ComponentCollectionVersion = componentsVersion }); } var concurrentFreeQueue = m_FreeNetworkIds.AsParallelWriter(); Dependency = m_Driver.ScheduleUpdate(Dependency); if (m_DriverListening) { // Schedule accept job var acceptJob = new ConnectionAcceptJob(); acceptJob.driver = m_Driver; acceptJob.commandBuffer = m_Barrier.CreateCommandBuffer(); acceptJob.numNetworkId = m_NumNetworkIds; acceptJob.freeNetworkIds = m_FreeNetworkIds; acceptJob.rpcQueue = m_RpcQueue; acceptJob.ghostFromEntity = GetComponentDataFromEntity <GhostComponent>(true); acceptJob.tickRate = default(ClientServerTickRate); if (HasSingleton <ClientServerTickRate>()) { acceptJob.tickRate = GetSingleton <ClientServerTickRate>(); } acceptJob.tickRate.ResolveDefaults(); acceptJob.protocolVersion = GetSingleton <NetworkProtocolVersion>(); Dependency = acceptJob.Schedule(Dependency); } else { if (!HasSingleton <ClientServerTickRate>()) { var newEntity = World.EntityManager.CreateEntity(); var tickRate = new ClientServerTickRate(); tickRate.ResolveDefaults(); EntityManager.AddComponentData(newEntity, tickRate); } var tickRateEntity = GetSingletonEntity <ClientServerTickRate>(); Dependency = Entities .WithNone <NetworkStreamDisconnected>() .ForEach((Entity entity, int entityInQueryIndex, in ClientServerTickRateRefreshRequest req) => { var dataFromEntity = GetComponentDataFromEntity <ClientServerTickRate>(); var tickRate = dataFromEntity[tickRateEntity]; tickRate.MaxSimulationStepsPerFrame = req.MaxSimulationStepsPerFrame; tickRate.NetworkTickRate = req.NetworkTickRate; tickRate.SimulationTickRate = req.SimulationTickRate; dataFromEntity[tickRateEntity] = tickRate; commandBuffer.RemoveComponent <ClientServerTickRateRefreshRequest>(entityInQueryIndex, entity); }).Schedule(Dependency); m_FreeNetworkIds.Clear(); } var protocolVersion = GetSingleton <NetworkProtocolVersion>(); Entities.WithName("CompleteConnection").WithNone <OutgoingRpcDataStreamBufferComponent>(). ForEach((Entity entity, int nativeThreadIndex, in NetworkStreamConnection con) => { var buf = commandBuffer.AddBuffer <OutgoingRpcDataStreamBufferComponent>(nativeThreadIndex, entity); RpcSystem.SendProtocolVersion(buf, protocolVersion); }).ScheduleParallel(); Dependency = JobHandle.CombineDependencies(Dependency, LastDriverWriter); var driver = m_Driver; Entities.ForEach((Entity entity, int nativeThreadIndex, ref NetworkStreamConnection connection, in NetworkStreamRequestDisconnect disconnect) => { driver.Disconnect(connection.Value); commandBuffer.AddComponent(nativeThreadIndex, entity, new NetworkStreamDisconnected { Reason = disconnect.Reason }); commandBuffer.RemoveComponent <NetworkStreamRequestDisconnect>(nativeThreadIndex, entity); }).Schedule(); // Schedule parallel update job var concurrentDriver = m_ConcurrentDriver; var freeNetworkIds = concurrentFreeQueue; var networkId = GetComponentDataFromEntity <NetworkIdComponent>(); var rpcBuffer = GetBufferFromEntity <IncomingRpcDataStreamBufferComponent>(); var cmdBuffer = GetBufferFromEntity <IncomingCommandDataStreamBufferComponent>(); var snapshotBuffer = GetBufferFromEntity <IncomingSnapshotDataStreamBufferComponent>(); var localTime = NetworkTimeSystem.TimestampMS; #if UNITY_EDITOR || DEVELOPMENT_BUILD var netStats = m_NetStats; #endif // FIXME: because it uses buffer from entity Entities.WithNone <NetworkStreamDisconnected>().WithReadOnly(networkId). ForEach((Entity entity, int nativeThreadIndex, ref NetworkStreamConnection connection, ref NetworkSnapshotAckComponent snapshotAck) => { if (!connection.Value.IsCreated) { return; } DataStreamReader reader; NetworkEvent.Type evt; while ((evt = concurrentDriver.PopEventForConnection(connection.Value, out reader)) != NetworkEvent.Type.Empty) { switch (evt) { case NetworkEvent.Type.Connect: break; case NetworkEvent.Type.Disconnect: // Flag the connection as lost, it will be deleted in a separate system, giving user code one frame to detect and respond to lost connection commandBuffer.AddComponent(nativeThreadIndex, entity, new NetworkStreamDisconnected { Reason = NetworkStreamDisconnectReason.ConnectionClose }); rpcBuffer[entity].Clear(); cmdBuffer[entity].Clear(); connection.Value = default(NetworkConnection); if (networkId.HasComponent(entity)) { freeNetworkIds.Enqueue(networkId[entity].Value); } return; case NetworkEvent.Type.Data: // FIXME: do something with the data switch ((NetworkStreamProtocol)reader.ReadByte()) { case NetworkStreamProtocol.Command: { var buffer = cmdBuffer[entity]; #if UNITY_EDITOR || DEVELOPMENT_BUILD if (buffer.Length > 0) { netStats[0] = netStats[0] + 1; } #endif // FIXME: should be handle by a custom command stream system uint snapshot = reader.ReadUInt(); uint snapshotMask = reader.ReadUInt(); snapshotAck.UpdateReceivedByRemote(snapshot, snapshotMask); uint remoteTime = reader.ReadUInt(); uint localTimeMinusRTT = reader.ReadUInt(); uint interpolationDelay = reader.ReadUInt(); snapshotAck.UpdateRemoteTime(remoteTime, localTimeMinusRTT, localTime, interpolationDelay); buffer.Clear(); buffer.Add(ref reader); break; } case NetworkStreamProtocol.Snapshot: { uint remoteTime = reader.ReadUInt(); uint localTimeMinusRTT = reader.ReadUInt(); snapshotAck.ServerCommandAge = reader.ReadInt(); snapshotAck.UpdateRemoteTime(remoteTime, localTimeMinusRTT, localTime, 0); var buffer = snapshotBuffer[entity]; #if UNITY_EDITOR || DEVELOPMENT_BUILD if (buffer.Length > 0) { netStats[0] = netStats[0] + 1; } #endif buffer.Clear(); buffer.Add(ref reader); break; } case NetworkStreamProtocol.Rpc: { var buffer = rpcBuffer[entity]; buffer.Add(ref reader); break; } default: #if ENABLE_UNITY_COLLECTIONS_CHECKS throw new InvalidOperationException("Received unknown message type"); #else break; #endif } break; default: #if ENABLE_UNITY_COLLECTIONS_CHECKS PrintEventError(evt); throw new InvalidOperationException("Received unknown network event"); #else break; #endif } } }).Schedule(); LastDriverWriter = Dependency; m_Barrier.AddJobHandleForProducer(Dependency); }