diff --git a/com.unity.netcode.gameobjects/Runtime/Components/Helpers/NetworkObjectBridge.cs b/com.unity.netcode.gameobjects/Runtime/Components/Helpers/NetworkObjectBridge.cs index c0f3ceb295..3d857b4c67 100644 --- a/com.unity.netcode.gameobjects/Runtime/Components/Helpers/NetworkObjectBridge.cs +++ b/com.unity.netcode.gameobjects/Runtime/Components/Helpers/NetworkObjectBridge.cs @@ -7,15 +7,17 @@ namespace Unity.Netcode { /// - /// TODO-UNIFIED: Would need to be reviewed for alternate ways of handling this. + /// TODO-UNIFIED: Needs further peer review and exploring alternate ways of handling this. /// /// /// If used, we most likely would make this internal /// public partial class NetworkObjectBridge : GhostBehaviour { - public Action NetworkObjectIdChanged; - + /// + /// This is used to link data to + /// N4E-spawned hybrid prefab instances. + /// internal GhostField NetworkObjectId = new GhostField(); public void SetNetworkObjectId(ulong value) @@ -41,7 +43,7 @@ public override bool Initialize(string defaultWorldName) { var networkManager = NetworkManager.Singleton; Instance = this; - AutoConnectPort = 0; + AutoConnectPort = Port; if (base.Initialize(defaultWorldName)) { UnityEngine.Debug.LogError($"[{nameof(UnifiedBootStrap)}] Auto-bootstrap is enabled!!! This will break the POC!"); @@ -80,21 +82,10 @@ public override bool Initialize(string defaultWorldName) return true; } - - public static void StopClient() - { - ClientWorld.Dispose(); - ClientWorlds.Remove(ClientWorld); - } - - public static void StopServer() - { - ServerWorld.Dispose(); - ServerWorlds.Remove(ServerWorld); - } ~UnifiedBootStrap() { + World = null; Instance = null; } } diff --git a/com.unity.netcode.gameobjects/Runtime/Components/Helpers/UnifiedUpdateConnections.cs b/com.unity.netcode.gameobjects/Runtime/Components/Helpers/UnifiedUpdateConnections.cs index efece3bc56..faa1b12d67 100644 --- a/com.unity.netcode.gameobjects/Runtime/Components/Helpers/UnifiedUpdateConnections.cs +++ b/com.unity.netcode.gameobjects/Runtime/Components/Helpers/UnifiedUpdateConnections.cs @@ -13,9 +13,6 @@ public struct NetcodeConnection internal Entity Entity; public int NetworkId; - internal float ConnectedTime; - internal bool IsSynced; - public bool IsServer => World.IsServer(); public void GoInGame() { @@ -34,20 +31,13 @@ internal partial class UnifiedUpdateConnections : SystemBase private List m_TempConnections = new List(); private Dictionary m_NewConnections = new Dictionary(); - - public void MarkSync(int NetworkId) - { - if (m_NewConnections.TryGetValue(NetworkId, out var connection)) - { - connection.IsSynced = true; - m_NewConnections[NetworkId] = connection; - } - } protected override void OnUpdate() { var isServer = World.IsServer(); var commandBuffer = new EntityCommandBuffer(Allocator.Temp); + var networkManager = NetworkManager.Singleton; + foreach (var (networkId, connectionState, entity) in SystemAPI.Query().WithNone().WithEntityAccess()) { commandBuffer.RemoveComponent(entity); @@ -60,16 +50,12 @@ protected override void OnUpdate() m_TempConnections.Clear(); - + // TODO: We should figure out how to associate the N4E NetworkId with the NGO ClientId foreach (var (networkId, entity) in SystemAPI.Query().WithAll().WithNone().WithEntityAccess()) { - // TODO-Unified: For new connections, we have a delay before the N4E in-game state for the client to provide time for the NGO side of the client to synchronize. - // Note: Once both are using the same transport we should be able to get the transport id and determine the NGO assigned client-id and at that point once the - // client has signaled that it has synchronized (or has been sent the synchronization data) we finalize the in-game connection state (or something along those lines). if (!m_NewConnections.ContainsKey(networkId.Value)) { - var delayTime = 0.0f;// isServer ? 0.2f : 0.1f; - var newConnection = new NetcodeConnection { World = World, Entity = entity, NetworkId = networkId.Value, ConnectedTime = UnityEngine.Time.realtimeSinceStartup + delayTime, IsSynced = isServer}; + var newConnection = new NetcodeConnection { World = World, Entity = entity, NetworkId = networkId.Value }; m_NewConnections.Add(networkId.Value, newConnection); } } @@ -79,8 +65,9 @@ protected override void OnUpdate() { foreach (var entry in m_NewConnections) { - // Check if the delay time has passed. - if (entry.Value.IsSynced && entry.Value.ConnectedTime < UnityEngine.Time.realtimeSinceStartup) + // Server: always connect + // Client: wait until we have synchronized before announcing we are ready to receive snapshots + if (networkManager.IsServer || (!networkManager.IsServer && networkManager.IsConnectedClient)) { // Set the connection in-game commandBuffer.AddComponent(entry.Value.Entity); @@ -97,21 +84,29 @@ protected override void OnUpdate() } m_TempConnections.Clear(); + // If the local NetworkManager is shutting down or no longer connected, then + // make sure we have disconnected all known connections. + if (networkManager.ShutdownInProgress || !networkManager.IsListening) + { + foreach (var (networkId, entity) in SystemAPI.Query().WithEntityAccess()) + { + commandBuffer.RemoveComponent(entity); + NetworkManager.OnNetCodeDisconnect?.Invoke(new NetcodeConnection { World = World, Entity = entity, NetworkId = networkId.Value }); + } + } commandBuffer.Playback(EntityManager); } + /// + /// Always disconnect all known connections when being destroyed. + /// protected override void OnDestroy() { var commandBuffer = new EntityCommandBuffer(Allocator.Temp); foreach (var (networkId, entity) in SystemAPI.Query().WithEntityAccess()) { commandBuffer.RemoveComponent(entity); - // TODO: maybe disconnect reason? - m_TempConnections.Add(new NetcodeConnection { World = World, Entity = entity, NetworkId = networkId.Value }); - } - foreach (var con in m_TempConnections) - { - NetworkManager.OnNetCodeDisconnect?.Invoke(con); + NetworkManager.OnNetCodeDisconnect?.Invoke(new NetcodeConnection { World = World, Entity = entity, NetworkId = networkId.Value }); } commandBuffer.Playback(EntityManager); base.OnDestroy(); diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs index 22f6527caf..b8c29a67e4 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs @@ -8,7 +8,9 @@ #endif using Unity.Netcode.Components; using Unity.Netcode.Runtime; +#if UNIFIED_NETCODE using Unity.Netcode.Unified; +#endif using UnityEngine; #if UNITY_EDITOR using UnityEditor; @@ -1204,11 +1206,11 @@ internal void Initialize(bool server) // UnityTransport dependencies are then initialized RealTimeProvider = ComponentFactory.Create(this); - + #if UNIFIED_NETCODE NetworkConfig.NetworkTransport = gameObject.AddComponent(); #endif - + MetricsManager.Initialize(this); { @@ -1320,18 +1322,27 @@ private System.Collections.IEnumerator WaitForHybridPrefabRegistration(StartType { NetworkLog.LogInfo($"[{nameof(WaitForHybridPrefabRegistration)}] Netcode is not active but has an instance at this point."); } + + /// !! Important !! + /// Clear out any pre-existing configuration in the event this applicatioin instance has already been connected to a session. + NetCode.Netcode.Reset(); + + /// !! Initialize worlds here !! + /// Worlds are created here: DefaultWorldInitialization.Initialize("Default World", false); - var waitTime = new WaitForSeconds(0.016f); - // This should not be needed at this point, but here in the event something changes. - while (NetworkConfig.Prefabs.HasPendingGhostPrefabs) + + // This should not be needed at this point, but this is here in the event something changes. + if (NetworkConfig.Prefabs.HasPendingGhostPrefabs) { - if (LogLevel <= LogLevel.Developer) + NetworkLog.LogWarning($"[{nameof(WaitForHybridPrefabRegistration)}] !!!!! (Ghosts are still pending registration) !!!!!"); + var waitTime = new WaitForSeconds(0.016f); + while (NetworkConfig.Prefabs.HasPendingGhostPrefabs) { - NetworkLog.LogInfo($"[{nameof(WaitForHybridPrefabRegistration)}] Ghosts are still pending registration!"); + NetworkConfig.Prefabs.RegisterGhostPrefabs(this); + yield return waitTime; } - NetworkConfig.Prefabs.RegisterGhostPrefabs(this); - yield return waitTime; } + if (LogLevel <= LogLevel.Developer) { NetworkLog.LogInfo($"[{nameof(WaitForHybridPrefabRegistration)}] All hybrid prefabs have been registered!"); diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs index 92bbffa48a..e5c96dbc17 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs @@ -257,10 +257,6 @@ private static void CheckPrefabStage(PrefabStage prefabStage) /// internal void OnValidate() { -#if UNIFIED_NETCODE - UnifiedValidation(); -#endif - // Always exit early if we are in prefab edit mode and this instance is the // prefab instance within the InContext or InIsolation edit scene. if (s_PrefabInstance == this) @@ -280,6 +276,10 @@ internal void OnValidate() return; } +#if UNIFIED_NETCODE + UnifiedValidation(); +#endif + // Get a global object identifier for this network prefab. var globalId = GlobalObjectId.GetGlobalObjectIdSlow(this); @@ -1732,10 +1732,19 @@ private void OnDestroy() return; } + var spawnManager = NetworkManager.SpawnManager; + // Always attempt to remove from scene changed updates - networkManager.SpawnManager?.RemoveNetworkObjectFromSceneChangedUpdates(this); + spawnManager?.RemoveNetworkObjectFromSceneChangedUpdates(this); +#if UNIFIED_NETCODE + spawnManager?.GhostsPendingSpawn.Remove(NetworkObjectId); + spawnManager?.GhostsPendingSynchronization.Remove(NetworkObjectId); + // N4E controls this on the client, allow this if there is a ghost + if (IsSpawned && !HasGhost && !networkManager.ShutdownInProgress) +#else if (IsSpawned && !networkManager.ShutdownInProgress) +#endif { // An authorized destroy is when done by the authority instance or done due to a scene event and the NetworkObject // was marked as destroy pending scene event (which means the destroy with scene property was set). @@ -1763,11 +1772,11 @@ private void OnDestroy() } } - if (networkManager.SpawnManager != null && networkManager.SpawnManager.SpawnedObjects.TryGetValue(NetworkObjectId, out var networkObject)) + if (spawnManager != null && spawnManager.SpawnedObjects.TryGetValue(NetworkObjectId, out var networkObject)) { if (this == networkObject) { - networkManager.SpawnManager.OnDespawnObject(networkObject, false); + spawnManager.OnDespawnObject(networkObject, false); } } } @@ -3846,7 +3855,6 @@ private void InitGhost() { Debug.Log($"[{nameof(NetworkObject)}] GhostBridge {name} detected and instantiated."); } - NetworkObjectBridge.NetworkObjectIdChanged += OnNetworkObjectIdChanged; if (NetworkObjectBridge.NetworkObjectId.Value != 0) { RegisterGhostBridge(); @@ -3866,11 +3874,6 @@ internal void RegisterGhostBridge() NetworkManager.SpawnManager.RegisterGhostPendingSpawn(this, NetworkObjectBridge.NetworkObjectId.Value); } } - - private void OnNetworkObjectIdChanged(ulong networkObjectId) - { - RegisterGhostBridge(); - } #endif /// diff --git a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/SceneEventMessage.cs b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/SceneEventMessage.cs index 320dc2ba1a..c0452146b4 100644 --- a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/SceneEventMessage.cs +++ b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/SceneEventMessage.cs @@ -1,7 +1,3 @@ - -using Unity.Netcode.Components; -using Unity.Netcode.Unified; - namespace Unity.Netcode { // Todo: Would be lovely to get this one nicely formatted with all the data it sends in the struct @@ -30,11 +26,6 @@ public void Handle(ref NetworkContext context) { var networkManager = (NetworkManager)context.SystemOwner; networkManager.SceneManager.HandleSceneEvent(context.SenderId, m_ReceivedData); - -#if UNIFIED_NETCODE - var unifiedConnectionSystem = NetCode.Netcode.GetWorld(false).GetExistingSystemManaged(); - unifiedConnectionSystem.MarkSync((int)context.SenderId); -#endif } } } diff --git a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs index 0e75f0c92f..d4930c6026 100644 --- a/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs @@ -2740,8 +2740,14 @@ internal void PopulateScenePlacedObjects(Scene sceneToFilterBy, bool clearSceneP var globalObjectIdHash = networkObjectInstance.GlobalObjectIdHash; var sceneHandle = networkObjectInstance.gameObject.scene.handle; // We check to make sure the NetworkManager instance is the same one to be "NetcodeIntegrationTestHelpers" compatible and filter the list on a per scene basis (for additive scenes) +#if UNIFIED_NETCODE + if (!networkObjectInstance.HasGhost && networkObjectInstance.IsSceneObject != false && (networkObjectInstance.NetworkManager == NetworkManager || + networkObjectInstance.NetworkManagerOwner == null) && sceneHandle == sceneToFilterBy.handle) +#else if (networkObjectInstance.IsSceneObject != false && (networkObjectInstance.NetworkManager == NetworkManager || networkObjectInstance.NetworkManagerOwner == null) && sceneHandle == sceneToFilterBy.handle) + +#endif { if (!ScenePlacedObjects.ContainsKey(globalObjectIdHash)) { diff --git a/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs b/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs index 9168761037..4f9b0fff14 100644 --- a/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs @@ -43,19 +43,39 @@ internal void RegisterGhostPendingSpawn(NetworkObject networkObject, ulong netwo if (GhostsPendingSpawn.TryAdd(networkObjectId, networkObject)) { // TODO-UNIFIED: We need a better way to preserve any hybrid instances pending NGO spawn. - // For now, move any pending object into the DDOL. - UnityEngine.Object.DontDestroyOnLoad(networkObject.gameObject); + // Edge-Case scenario: During initial client synchronization (i.e. !NetworkManager.IsConnectedClient). + // + // Description: A client can receive snapshots before finishing the NGO synchronization process. + // This is when an edge case scenario can happen where the initial NGO synchronization information + // can include new scenes to load. If one of those scenes is configured to load in SingleMode, then + // any instantiated ghosts pending synchronization would be instantiated in whatever the currently + // active scene was when the client was processing the synchronization data. If the ghosts pending + // synchrpnization are in the currently active scene when the new scene is loaded in SingleMode, then + // they would be destroyed. + // + // Current Fix: + // If the client is not yet synchronized, then any ghost pending spawn get migrated into the DDOL. + // + // Further review: + // We need to make sure that we are migrating NetworkObjects into their assigned scene (if scene + // management is enabled). Currently, we assume all instances were in the DDOL and just migrate + // them into the currently active scene upon spawn. + if (!NetworkManager.IsConnectedClient && !GhostsPendingSynchronization.ContainsKey(networkObjectId)) + { + UnityEngine.Object.DontDestroyOnLoad(networkObject.gameObject); + } + else // There is matching spawn data for this pending Ghost, process the pending spawn for this hybrid instance. + { + NetworkManager.DeferredMessageManager.ProcessTriggers(IDeferredNetworkMessageManager.TriggerType.OnGhostSpawned, networkObjectId); + if (GhostsPendingSynchronization.ContainsKey(networkObjectId)) + { + ProcessGhostPendingSynchronization(networkObjectId); + } + } } - - NetworkManager.DeferredMessageManager.ProcessTriggers(IDeferredNetworkMessageManager.TriggerType.OnGhostSpawned, networkObjectId); - if (GhostsArePendingSynchronization && GhostsPendingSynchronization.ContainsKey(networkObjectId)) + else { - // TODO-UNIFIED: We need a better way to preserve any hybrid instances pending NGO spawn. - // NOTE: We might be able to use the NetworkSceneHandle to get the associated local scene handle to which we can use to get the targeted scene. - UnityEngine.SceneManagement.SceneManager.MoveGameObjectToScene(networkObject.gameObject, UnityEngine.SceneManagement.SceneManager.GetActiveScene()); - - // When the object is spawned, it will invoke GetGhostNetworkObjectForSpawn below which removes the entry from GhostsPendingSpawn - ProcessGhostPendingSynchronization(networkObjectId); + Debug.LogError($"[{networkObject.name}-{networkObjectId}] Has already been registered as a pending ghost!"); } } @@ -67,10 +87,14 @@ internal NetworkObject GetGhostNetworkObjectForSpawn(ulong networkObjectId) return null; } var networkObject = GhostsPendingSpawn[networkObjectId]; + GhostsPendingSpawn.Remove(networkObjectId); - // TODO-UNIFIED: We need a better way to preserve any hybrid instances pending NGO spawn. - // NOTE: We might be able to use the NetworkSceneHandle to get the associated local scene handle to which we can use to get the targeted scene. - UnityEngine.SceneManagement.SceneManager.MoveGameObjectToScene(networkObject.gameObject, UnityEngine.SceneManagement.SceneManager.GetActiveScene()); + if (networkObject != null) + { + // TODO-UNIFIED: We need a better way to preserve any hybrid instances pending NGO spawn. + // NOTE: We might be able to use the NetworkSceneHandle to get the associated local scene handle to which we can use to get the targeted scene. + UnityEngine.SceneManagement.SceneManager.MoveGameObjectToScene(networkObject.gameObject, UnityEngine.SceneManagement.SceneManager.GetActiveScene()); + } return networkObject; } @@ -109,6 +133,7 @@ internal void ProcessGhostPendingSynchronization(ulong networkObjectId, bool rem //} if (removeUponSpawn) { + GhostsPendingSynchronization.Remove(networkObjectId); GhostsArePendingSynchronization = GhostsPendingSynchronization.Count > 0; ghostPendingSynch.Buffer.Dispose(); } diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/Unified/UnifiedNetcodeTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/Unified/UnifiedNetcodeTransport.cs index d35c554ae2..0c728b1c79 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/Unified/UnifiedNetcodeTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/Unified/UnifiedNetcodeTransport.cs @@ -1,19 +1,16 @@ #if UNIFIED_NETCODE using System; using System.Collections.Generic; -using System.Text; using Unity.Burst; using Unity.Burst.Intrinsics; using Unity.Collections; -using Unity.Collections.LowLevel.Unsafe; using Unity.Entities; using Unity.NetCode; using Unity.Netcode.Transports.UTP; -using Unity.Networking.Transport; -using UnityEngine; namespace Unity.Netcode.Unified { + [BurstCompile] internal struct TransportRpc : IOutOfBandRpcCommand, IRpcCommandSerializer { public FixedList4096Bytes Buffer; @@ -31,8 +28,10 @@ public unsafe void Deserialize(ref DataStreamReader reader, in RpcDeserializerSt { data.Order = reader.ReadULong(); var length = reader.ReadInt(); - data.Buffer = new FixedList4096Bytes(); - data.Buffer.Length = length; + data.Buffer = new FixedList4096Bytes() + { + Length = length + }; var span = new Span(data.Buffer.GetUnsafePtr(), length); reader.ReadBytes(span); } @@ -43,29 +42,29 @@ private static void InvokeExecute(ref RpcExecutor.Parameters parameters) RpcExecutor.ExecuteCreateRequestComponent(ref parameters); } - static readonly PortableFunctionPointer InvokeExecuteFunctionPointer = new PortableFunctionPointer(InvokeExecute); + private static readonly PortableFunctionPointer k_InvokeExecuteFunctionPointer = new PortableFunctionPointer(InvokeExecute); public PortableFunctionPointer CompileExecute() { - return InvokeExecuteFunctionPointer; + return k_InvokeExecuteFunctionPointer; } } [UpdateInGroup(typeof(RpcCommandRequestSystemGroup))] [CreateAfter(typeof(RpcSystem))] [BurstCompile] - partial struct TransportRpcCommandRequestSystem : ISystem + internal partial struct TransportRpcCommandRequestSystem : ISystem { private RpcCommandRequest m_Request; [BurstCompile] - struct SendRpc : IJobChunk + internal struct SendRpc : IJobChunk { - public RpcCommandRequest.SendRpcData data; + public RpcCommandRequest.SendRpcData Data; public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask) { - data.Execute(chunk, unfilteredChunkIndex); + Data.Execute(chunk, unfilteredChunkIndex); } } @@ -77,7 +76,7 @@ public void OnCreate(ref SystemState state) [BurstCompile] public void OnUpdate(ref SystemState state) { - var sendJob = new SendRpc { data = m_Request.InitJobData(ref state) }; + var sendJob = new SendRpc { Data = m_Request.InitJobData(ref state) }; state.Dependency = sendJob.Schedule(m_Request.Query, state.Dependency); } } @@ -125,13 +124,11 @@ protected override void OnUpdate() internal class UnifiedNetcodeTransport : NetworkTransport { + private const int k_MaxPacketSize = 1300; + private int m_ServerClientId = -1; public override ulong ServerClientId => (ulong)m_ServerClientId; - private bool m_IsClient; - private bool m_IsServer; - private bool m_StartedServerWorld = false; - private bool m_StartedClientWorld = false; private NetworkManager m_NetworkManager; private IRealTimeProvider m_RealTimeProvider; @@ -210,9 +207,10 @@ public override unsafe void Send(ulong clientId, ArraySegment payload, Net { Buffer = new FixedList4096Bytes(), }; - var writer = new DataStreamWriter(rpc.Buffer.GetUnsafePtr(), 1024); + + var writer = new DataStreamWriter(rpc.Buffer.GetUnsafePtr(), k_MaxPacketSize); - var amount = connectionInfo.SendQueue.FillWriterWithBytes(ref writer, 1024); + var amount = connectionInfo.SendQueue.FillWriterWithBytes(ref writer, k_MaxPacketSize); rpc.Buffer.Length = amount; rpc.Order = ++connectionInfo.LastSent; @@ -265,44 +263,24 @@ private void OnServerClientDisconnected(Connection connection, NetCodeConnection public override bool StartClient() { - if (!UnifiedBootStrap.HasClientWorlds) - { - UnifiedBootStrap.CreateClientWorld("ClientWorld"); - m_StartedClientWorld = true; - } - NetCode.Netcode.Client.OnConnect = OnClientConnectedToServer; NetCode.Netcode.Client.OnDisconnect = OnClientDisconnectFromServer; var updateSystem = NetCode.Netcode.GetWorld(false).GetExistingSystemManaged(); updateSystem.Transport = this; - using var drvQuery = updateSystem.EntityManager.CreateEntityQuery(ComponentType.ReadWrite()); - var driver = drvQuery.GetSingletonRW(); - driver.ValueRW.Connect(updateSystem.EntityManager, NetworkEndpoint.Parse("127.0.0.1", 7979)); return true; } public override bool StartServer() { - if (!UnifiedBootStrap.HasServerWorld) - { - UnifiedBootStrap.CreateServerWorld("ServerWorld"); - m_StartedClientWorld = true; - } - else + foreach (var connection in NetCode.Netcode.Server.Connections) { - foreach (var connection in NetCode.Netcode.Server.Connections) - { - OnServerNewClientConnection(connection, default); - } + OnServerNewClientConnection(connection, default); } NetCode.Netcode.Server.OnConnect = OnServerNewClientConnection; NetCode.Netcode.Server.OnDisconnect = OnServerClientDisconnected; var updateSystem = NetCode.Netcode.GetWorld(true).GetExistingSystemManaged(); updateSystem.Transport = this; - using var drvQuery = updateSystem.EntityManager.CreateEntityQuery(ComponentType.ReadWrite()); - var driver = drvQuery.GetSingletonRW(); - driver.ValueRW.Listen(NetworkEndpoint.Parse("127.0.0.1", 7979)); return true; } @@ -326,24 +304,17 @@ public override ulong GetCurrentRtt(ulong clientId) return (ulong)m_Connections[(int)transportId].Connection.RTT; } - public override void Shutdown() - { - if (m_StartedClientWorld) - { - UnifiedBootStrap.StopClient(); - } - if (m_StartedServerWorld) - { - UnifiedBootStrap.StopServer(); - } - } - public override void Initialize(NetworkManager networkManager = null) { m_Connections = new Dictionary(); m_RealTimeProvider = networkManager.RealTimeProvider; m_NetworkManager = networkManager; } + + public override void Shutdown() + { + + } } } -#endif \ No newline at end of file +#endif