public void UnintializedGhostOwnerThrowsException() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true); var ghostGameObject = new GameObject(); ghostGameObject.AddComponent <TestNetCodeAuthoring>().Converter = new InvalidUsageConverter(); ghostGameObject.AddComponent <GhostAuthoringComponent>().DefaultGhostMode = GhostAuthoringComponent.GhostMode.OwnerPredicted; Assert.IsTrue(testWorld.CreateGhostCollection(ghostGameObject)); testWorld.CreateWorlds(true, 1); testWorld.SpawnOnServer(ghostGameObject); float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); // Go in-game testWorld.GoInGame(); LogAssert.Expect(LogType.Error, new Regex("Trying to spawn an owner predicted ghost which does not have a valid owner set. When using owner prediction you must set GhostOwnerComponent.NetworkId when spawning the ghost. If the ghost is not owned by a player you can set NetworkId to -1.")); // Let the game run for a bit so the ghosts are spawned on the client for (int i = 0; i < 4; ++i) { testWorld.Tick(frameTime); } } }
public void Rpc_UsingConnectionEntityOnClient_Works() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true, typeof(ClientRcpSendSystem), typeof(ServerRpcReceiveSystem), typeof(NonSerializedRpcCommandRequestSystem)); testWorld.CreateWorlds(true, 1); int SendCount = 10; ClientRcpSendSystem.SendCount = SendCount; ServerRpcReceiveSystem.ReceivedCount = 0; float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); var remote = testWorld.TryGetSingletonEntity <NetworkStreamConnection>(testWorld.ClientWorlds[0]); testWorld.ClientWorlds[0].GetExistingSystem <ClientRcpSendSystem>().Remote = remote; for (int i = 0; i < 33; ++i) { testWorld.Tick(16f / 1000f); } Assert.AreEqual(SendCount, ServerRpcReceiveSystem.ReceivedCount); } }
public void Rpc_SerializedRpcFlow_Works() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true, typeof(SerializedClientRcpSendSystem), typeof(SerializedServerRpcReceiveSystem), typeof(SerializedRpcCommandRequestSystem)); testWorld.CreateWorlds(true, 1); int SendCount = 1; var SendCmd = new SerializedRpcCommand { intValue = 123456, shortValue = 32154, floatValue = 12345.67f }; SerializedClientRcpSendSystem.SendCount = SendCount; SerializedClientRcpSendSystem.Cmd = SendCmd; SerializedServerRpcReceiveSystem.ReceivedCount = 0; float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); for (int i = 0; i < 33; ++i) { testWorld.Tick(16f / 1000f); } Assert.AreEqual(SendCount, SerializedServerRpcReceiveSystem.ReceivedCount); Assert.AreEqual(SendCmd, SerializedServerRpcReceiveSystem.ReceivedCmd); } }
public void Rpc_UsingBroadcastOnClient_Works() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true, typeof(ClientRcpSendSystem), typeof(ServerRpcReceiveSystem), typeof(NonSerializedRpcCommandRequestSystem)); testWorld.CreateWorlds(true, 1); int SendCount = 10; ClientRcpSendSystem.SendCount = SendCount; ServerRpcReceiveSystem.ReceivedCount = 0; float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); for (int i = 0; i < 33; ++i) { testWorld.Tick(16f / 1000f); } Assert.AreEqual(SendCount, ServerRpcReceiveSystem.ReceivedCount); } }
public void Rpc_CanSendMoreThanOnePacketPerFrame() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true, typeof(SerializedClientLargeRcpSendSystem), typeof(SerializedServerLargeRpcReceiveSystem), typeof(SerializedLargeRpcCommandRequestSystem)); testWorld.CreateWorlds(true, 1); int SendCount = 50; var SendCmd = new SerializedLargeRpcCommand { stringValue = new FixedString512("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") }; SerializedClientLargeRcpSendSystem.SendCount = SendCount; SerializedClientLargeRcpSendSystem.Cmd = SendCmd; SerializedServerLargeRpcReceiveSystem.ReceivedCount = 0; float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); for (int i = 0; i < 33; ++i) { testWorld.Tick(16f / 1000f); } Assert.AreEqual(SendCount, SerializedServerLargeRpcReceiveSystem.ReceivedCount); Assert.AreEqual(SendCmd, SerializedServerLargeRpcReceiveSystem.ReceivedCmd); } }
public void Rpc_SendingBeforeGettingNetworkId_Throws() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true, typeof(FlawedClientRcpSendSystem), typeof(ServerRpcReceiveSystem), typeof(NonSerializedRpcCommandRequestSystem)); testWorld.CreateWorlds(true, 1); int SendCount = 1; ServerRpcReceiveSystem.ReceivedCount = 0; FlawedClientRcpSendSystem.SendCount = SendCount; float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); LogAssert.Expect(LogType.Exception, new Regex("InvalidOperationException: Cannot send RPC with no remote connection.")); for (int i = 0; i < 33; ++i) { testWorld.Tick(16f / 1000f); } Assert.AreEqual(0, ServerRpcReceiveSystem.ReceivedCount); } }
public void StaticGhostsAreNotApplied() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true); SetupBasicTest(testWorld); var clientEnt = testWorld.TryGetSingletonEntity <GhostOwnerComponent>(testWorld.ClientWorlds[0]); Assert.AreNotEqual(Entity.Null, clientEnt); var clientEntityManager = testWorld.ClientWorlds[0].EntityManager; // Write some data to a ghost field and verify that it was not touched by the ghost apply clientEntityManager.SetComponentData(clientEnt, new GhostOwnerComponent { NetworkId = 42 }); // Run a bit longer for (int i = 0; i < 16; ++i) { testWorld.Tick(frameTime); } Assert.AreEqual(42, clientEntityManager.GetComponentData <GhostOwnerComponent>(clientEnt).NetworkId); } }
public void BootstrapRespectsUpdateInWorld() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(false, typeof(ExplicitDefaultSystem), typeof(ExplicitClientSystem), typeof(ExplicitServerSystem), typeof(ExplicitClientServerSystem)); testWorld.CreateWorlds(true, 1); Assert.IsNotNull(testWorld.DefaultWorld.GetExistingSystem <ExplicitDefaultSystem>()); Assert.IsNull(testWorld.ServerWorld.GetExistingSystem <ExplicitDefaultSystem>()); Assert.IsNull(testWorld.ClientWorlds[0].GetExistingSystem <ExplicitDefaultSystem>()); Assert.IsNull(testWorld.DefaultWorld.GetExistingSystem <ExplicitClientSystem>()); Assert.IsNull(testWorld.ServerWorld.GetExistingSystem <ExplicitClientSystem>()); Assert.IsNotNull(testWorld.ClientWorlds[0].GetExistingSystem <ExplicitClientSystem>()); Assert.IsNull(testWorld.DefaultWorld.GetExistingSystem <ExplicitServerSystem>()); Assert.IsNotNull(testWorld.ServerWorld.GetExistingSystem <ExplicitServerSystem>()); Assert.IsNull(testWorld.ClientWorlds[0].GetExistingSystem <ExplicitServerSystem>()); Assert.IsNull(testWorld.DefaultWorld.GetExistingSystem <ExplicitClientServerSystem>()); Assert.IsNotNull(testWorld.ServerWorld.GetExistingSystem <ExplicitClientServerSystem>()); Assert.IsNotNull(testWorld.ClientWorlds[0].GetExistingSystem <ExplicitClientServerSystem>()); } }
public void DynamicGhostsInSameChunkAsStaticAreSent() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true, typeof(StaticOptimizationTestSystem)); StaticOptimizationTestSystem.s_ModifyNetworkId = 1; // Spawn 16 ghosts SetupBasicTest(testWorld, 16); // Set the ghost id for one of them to 1 so it is modified var serverQuery = testWorld.ServerWorld.EntityManager.CreateEntityQuery(ComponentType.ReadOnly <GhostOwnerComponent>()); using (var serverEntities = serverQuery.ToEntityArray(Allocator.TempJob)) { Assert.AreEqual(16, serverEntities.Length); testWorld.ServerWorld.EntityManager.SetComponentData(serverEntities[0], new GhostOwnerComponent { NetworkId = 1 }); } // Get the changes across to the client for (int i = 0; i < 16; ++i) { testWorld.Tick(frameTime); } var clientEntityManager = testWorld.ClientWorlds[0].EntityManager; var clientQuery = clientEntityManager.CreateEntityQuery(ComponentType.ReadOnly <GhostOwnerComponent>()); Entity clientEnt = Entity.Null; using (var clientEntities = clientQuery.ToEntityArray(Allocator.TempJob)) { Assert.AreEqual(16, clientEntities.Length); for (int i = 0; i < clientEntities.Length; ++i) { if (clientEntityManager.GetComponentData <GhostOwnerComponent>(clientEntities[i]).NetworkId == 1) { Assert.AreEqual(Entity.Null, clientEnt); clientEnt = clientEntities[i]; } } Assert.AreNotEqual(Entity.Null, clientEnt); } // Store the last tick we got for this var clientSnapshotBuffer = clientEntityManager.GetBuffer <SnapshotDataBuffer>(clientEnt); var clientSnapshot = clientEntityManager.GetComponentData <SnapshotData>(clientEnt); var lastSnapshot = clientSnapshot.GetLatestTick(clientSnapshotBuffer); // Run a bit longer for (int i = 0; i < 16; ++i) { testWorld.Tick(frameTime); } // Verify that we are getting updates for the ghost clientSnapshotBuffer = clientEntityManager.GetBuffer <SnapshotDataBuffer>(clientEnt); clientSnapshot = clientEntityManager.GetComponentData <SnapshotData>(clientEnt); Assert.AreNotEqual(lastSnapshot, clientSnapshot.GetLatestTick(clientSnapshotBuffer)); } }
public void Rpc_ClientRegisterRpcCommandWithNullFunctionPtr_Throws() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true, typeof(InvalidRpcCommandRequestSystem)); Assert.Throws <InvalidOperationException>(() => { testWorld.CreateWorlds(false, 1); }); Assert.Throws <InvalidOperationException>(() => { testWorld.CreateWorlds(true, 1); }); } }
public void StaticGhostsAreSentWhenModified() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true, typeof(StaticOptimizationTestSystem)); StaticOptimizationTestSystem.s_ModifyNetworkId = 1; SetupBasicTest(testWorld); var clientEnt = testWorld.TryGetSingletonEntity <GhostOwnerComponent>(testWorld.ClientWorlds[0]); Assert.AreNotEqual(Entity.Null, clientEnt); var clientEntityManager = testWorld.ClientWorlds[0].EntityManager; // Store the last tick we got for this var clientSnapshotBuffer = clientEntityManager.GetBuffer <SnapshotDataBuffer>(clientEnt); var clientSnapshot = clientEntityManager.GetComponentData <SnapshotData>(clientEnt); var lastSnapshot = clientSnapshot.GetLatestTick(clientSnapshotBuffer); // Run a bit longer for (int i = 0; i < 16; ++i) { testWorld.Tick(frameTime); } // Verify taht we did not get any new snapshot clientSnapshotBuffer = clientEntityManager.GetBuffer <SnapshotDataBuffer>(clientEnt); clientSnapshot = clientEntityManager.GetComponentData <SnapshotData>(clientEnt); Assert.AreEqual(lastSnapshot, clientSnapshot.GetLatestTick(clientSnapshotBuffer)); // Run one tick with modification StaticOptimizationTestSystem.s_ModifyNetworkId = 0; testWorld.Tick(frameTime); StaticOptimizationTestSystem.s_ModifyNetworkId = 1; for (int i = 0; i < 16; ++i) { testWorld.Tick(frameTime); } // Verify taht we did not get any new snapshot clientSnapshotBuffer = clientEntityManager.GetBuffer <SnapshotDataBuffer>(clientEnt); clientSnapshot = clientEntityManager.GetComponentData <SnapshotData>(clientEnt); var newLastSnapshot = clientSnapshot.GetLatestTick(clientSnapshotBuffer); Assert.AreNotEqual(lastSnapshot, newLastSnapshot); for (int i = 0; i < 16; ++i) { testWorld.Tick(frameTime); } // Verify that the snapshot stayed static at the new position clientSnapshotBuffer = clientEntityManager.GetBuffer <SnapshotDataBuffer>(clientEnt); clientSnapshot = clientEntityManager.GetComponentData <SnapshotData>(clientEnt); Assert.AreEqual(newLastSnapshot, clientSnapshot.GetLatestTick(clientSnapshotBuffer)); } }
public void ExtrapolationProduceSmoothValues() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true, typeof(MoveExtrapolated), typeof(CheckExtrapolate)); var ghostGameObject = new GameObject(); ghostGameObject.AddComponent <TestNetCodeAuthoring>().Converter = new GhostExtrapolationConverter(); ghostGameObject.AddComponent <GhostAuthoringComponent>(); Assert.IsTrue(testWorld.CreateGhostCollection(ghostGameObject)); testWorld.CreateWorlds(true, 1); var tickRate = testWorld.ServerWorld.EntityManager.CreateEntity(); // Set low net tick rate to make sure interpolation is used testWorld.ServerWorld.EntityManager.AddComponentData(tickRate, new ClientServerTickRate { NetworkTickRate = 1 }); var clientTickRate = testWorld.ClientWorlds[0].EntityManager.CreateEntity(); // Disable interpolation time to make sure extrapolation is used var tr = NetworkTimeSystem.DefaultClientTickRate; tr.InterpolationTimeNetTicks = 0; tr.MaxExtrapolationTimeSimTicks = 120; testWorld.ClientWorlds[0].EntityManager.AddComponentData(clientTickRate, tr); testWorld.SpawnOnServer(ghostGameObject); float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); // Go in-game testWorld.GoInGame(); // Let the simulation run for a bit since extrapolation requires two snapshots to be received before it does anything for (int i = 0; i < 256; ++i) { testWorld.Tick(frameTime); } // Enable the checks var clientEnt = testWorld.TryGetSingletonEntity <TestExtrapolated>(testWorld.ClientWorlds[0]); Assert.AreNotEqual(Entity.Null, clientEnt); testWorld.ClientWorlds[0].EntityManager.AddComponentData(clientEnt, new ExtrapolateBackup { Value = 0 }); // Let the game run for a bit more and verify that they are extrapolated for (int i = 0; i < 256; ++i) { testWorld.Tick(frameTime); } } }
public void DisposingDefaultWorldBeforeClientServerWorldDoesNotCauseErrors() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(false); testWorld.CreateWorlds(true, 1); testWorld.Tick(1.0f / 60.0f); testWorld.DisposeDefaultWorld(); } }
public void CanRecoverFromDeletingGhostOnClient() { using (var testWorld = new NetCodeTestWorld()) { DeleteGhostOnClientSystem.s_DeleteCount = 1; testWorld.Bootstrap(true, typeof(DeleteGhostOnClientSystem)); var ghostGameObject = new GameObject(); ghostGameObject.AddComponent <TestNetCodeAuthoring>().Converter = new InvalidUsageConverter(); Assert.IsTrue(testWorld.CreateGhostCollection(ghostGameObject)); testWorld.CreateWorlds(true, 1); testWorld.SpawnOnServer(ghostGameObject); var serverEnt = testWorld.TryGetSingletonEntity <GhostOwnerComponent>(testWorld.ServerWorld); testWorld.ServerWorld.EntityManager.SetComponentData(serverEnt, new GhostOwnerComponent { NetworkId = 42 }); float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); // Go in-game testWorld.GoInGame(); LogAssert.Expect(LogType.Error, new Regex("Found a ghost in the ghost map which does not have an entity connected to it. This can happen if you delete ghost entities on the client.")); LogAssert.Expect(LogType.Error, new Regex("Ghost ID \\d+ has already been added to the spawned ghost map")); // Let the game run for a bit so the ghosts are spawned on the client for (int i = 0; i < 64; ++i) { testWorld.Tick(frameTime); } // Validate that the ghost was deleted on the cliet Assert.AreEqual(0, DeleteGhostOnClientSystem.s_DeleteCount); // Check that the client world has the right thing and value var clientEnt = testWorld.TryGetSingletonEntity <GhostOwnerComponent>(testWorld.ClientWorlds[0]); Assert.AreNotEqual(Entity.Null, clientEnt); Assert.AreEqual(42, testWorld.ClientWorlds[0].EntityManager.GetComponentData <GhostOwnerComponent>(clientEnt).NetworkId); // Delete on server testWorld.ServerWorld.EntityManager.DestroyEntity(serverEnt); for (int i = 0; i < 4; ++i) { testWorld.Tick(frameTime); } clientEnt = testWorld.TryGetSingletonEntity <GhostOwnerComponent>(testWorld.ClientWorlds[0]); Assert.AreEqual(Entity.Null, clientEnt); } }
public void EntityMarkedAsChildIsSentAsPartOfGroup() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true); var ghostGameObject = new GameObject(); ghostGameObject.name = "ParentGhost"; ghostGameObject.AddComponent <TestNetCodeAuthoring>().Converter = new GhostGroupGhostConverter(); var childGhostGameObject = new GameObject(); childGhostGameObject.name = "ChildGhost"; childGhostGameObject.AddComponent <TestNetCodeAuthoring>().Converter = new GhostGroupGhostConverter(); Assert.IsTrue(testWorld.CreateGhostCollection(ghostGameObject, childGhostGameObject)); testWorld.CreateWorlds(true, 1); testWorld.SpawnOnServer(ghostGameObject); testWorld.SpawnOnServer(childGhostGameObject); var serverEnt = testWorld.TryGetSingletonEntity <GhostGroupRoot>(testWorld.ServerWorld); var serverChildEnt = testWorld.TryGetSingletonEntity <GhostChildEntityComponent>(testWorld.ServerWorld); testWorld.ServerWorld.EntityManager.SetComponentData(serverEnt, new GhostOwnerComponent { NetworkId = 42 }); testWorld.ServerWorld.EntityManager.SetComponentData(serverChildEnt, new GhostOwnerComponent { NetworkId = 43 }); testWorld.ServerWorld.EntityManager.GetBuffer <GhostGroup>(serverEnt).Add(new GhostGroup { Value = serverChildEnt }); float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); // Go in-game testWorld.GoInGame(); // Let the game run for a bit so the ghosts are spawned on the client for (int i = 0; i < 64; ++i) { testWorld.Tick(frameTime); } // Check that the client world has the right thing and value var clientEnt = testWorld.TryGetSingletonEntity <GhostGroupRoot>(testWorld.ClientWorlds[0]); var clientChildEnt = testWorld.TryGetSingletonEntity <GhostChildEntityComponent>(testWorld.ClientWorlds[0]); Assert.AreEqual(42, testWorld.ClientWorlds[0].EntityManager.GetComponentData <GhostOwnerComponent>(clientEnt).NetworkId); Assert.AreNotEqual(Entity.Null, clientChildEnt); Assert.AreEqual(43, testWorld.ClientWorlds[0].EntityManager.GetComponentData <GhostOwnerComponent>(clientChildEnt).NetworkId); } }
public void ChildEntityDataIsReplicated() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true); var ghostGameObject = new GameObject(); ghostGameObject.AddComponent <TestNetCodeAuthoring>().Converter = new MultiEntityGhostConverter(); var childGhost = new GameObject(); childGhost.transform.parent = ghostGameObject.transform; childGhost.AddComponent <TestNetCodeAuthoring>().Converter = new MultiEntityGhostConverter(); Assert.IsTrue(testWorld.CreateGhostCollection(ghostGameObject)); testWorld.CreateWorlds(true, 1); testWorld.SpawnOnServer(ghostGameObject); var serverEnt = testWorld.TryGetSingletonEntity <TopLevelGhostEntity>(testWorld.ServerWorld); Assert.IsTrue(testWorld.ServerWorld.EntityManager.HasComponent <LinkedEntityGroup>(serverEnt)); var serverEntityGroup = testWorld.ServerWorld.EntityManager.GetBuffer <LinkedEntityGroup>(serverEnt); Assert.AreEqual(2, serverEntityGroup.Length); testWorld.ServerWorld.EntityManager.SetComponentData(serverEntityGroup[0].Value, new GhostOwnerComponent { NetworkId = 42 }); testWorld.ServerWorld.EntityManager.SetComponentData(serverEntityGroup[1].Value, new GhostOwnerComponent { NetworkId = 42 }); float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); // Go in-game testWorld.GoInGame(); // Let the game run for a bit so the ghosts are spawned on the client for (int i = 0; i < 64; ++i) { testWorld.Tick(frameTime); } // Check that the client world has the right thing and value var clientEnt = testWorld.TryGetSingletonEntity <TopLevelGhostEntity>(testWorld.ClientWorlds[0]); Assert.IsTrue(testWorld.ClientWorlds[0].EntityManager.HasComponent <LinkedEntityGroup>(clientEnt)); var clientEntityGroup = testWorld.ClientWorlds[0].EntityManager.GetBuffer <LinkedEntityGroup>(clientEnt); Assert.AreEqual(2, clientEntityGroup.Length); Assert.AreEqual(42, testWorld.ClientWorlds[0].EntityManager.GetComponentData <GhostOwnerComponent>(clientEntityGroup[0].Value).NetworkId); Assert.AreEqual(42, testWorld.ClientWorlds[0].EntityManager.GetComponentData <GhostOwnerComponent>(clientEntityGroup[1].Value).NetworkId); } }
public void GhostsWithSameArchetypeAreDifferent() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true, typeof(GhostTypeIndex0TestGhostSpawnSystem), typeof(GhostTypeIndex0TestGhostUpdateSystem), typeof(GhostTypeIndex1TestGhostSpawnSystem), typeof(GhostTypeIndex1TestGhostUpdateSystem), typeof(GhostTypeTestGhostSendSystem), typeof(GhostTypeTestGhostReceiveSystem)); var ghostGameObject0 = new GameObject(); ghostGameObject0.AddComponent <TestNetCodeAuthoring>().Converter = new GhostTypeIndexConverter(); ghostGameObject0.name = "GhostTypeIndex0Test"; var ghostGameObject1 = new GameObject(); ghostGameObject1.AddComponent <TestNetCodeAuthoring>().Converter = new GhostTypeIndexConverter(); ghostGameObject1.name = "GhostTypeIndex1Test"; Assert.IsTrue(testWorld.CreateGhostCollection( "/../Packages/com.unity.netcode/Tests/Editor/Generated/", "GhostTypeTest", ghostGameObject0, ghostGameObject1)); testWorld.CreateWorlds(true, 1); testWorld.SpawnOnServer(ghostGameObject0); testWorld.SpawnOnServer(ghostGameObject0); testWorld.SpawnOnServer(ghostGameObject1); testWorld.SpawnOnServer(ghostGameObject1); VerifyGhostTypes(testWorld.ServerWorld); float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); // Go in-game testWorld.GoInGame(); // Let the game run for a bit so the ghosts are spawned on the client for (int i = 0; i < 64; ++i) { testWorld.Tick(frameTime); } // Assert that replicated version is correct VerifyGhostTypes(testWorld.ClientWorlds[0]); } }
public void ServerGhostCountIsVisibleOnClient() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true); var ghostGameObject = new GameObject(); ghostGameObject.AddComponent <TestNetCodeAuthoring>().Converter = new LateJoinCompletionConverter(); Assert.IsTrue(testWorld.CreateGhostCollection(ghostGameObject)); testWorld.CreateWorlds(true, 1); for (int i = 0; i < 8; ++i) { testWorld.SpawnOnServer(ghostGameObject); } float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); // Go in-game testWorld.GoInGame(); // Let the game run for a bit so the ghosts are spawned on the client for (int i = 0; i < 4; ++i) { testWorld.Tick(frameTime); } var ghostReceiveSystem = testWorld.ClientWorlds[0].GetExistingSystem <GhostReceiveSystem>(); // Validate that the ghost was deleted on the cliet Assert.AreEqual(8, ghostReceiveSystem.GhostCountOnServer); Assert.AreEqual(8, ghostReceiveSystem.GhostCountOnClient); // Spawn a few more and verify taht the count is updated for (int i = 0; i < 8; ++i) { testWorld.SpawnOnServer(ghostGameObject); } for (int i = 0; i < 4; ++i) { testWorld.Tick(frameTime); } Assert.AreEqual(16, ghostReceiveSystem.GhostCountOnServer); Assert.AreEqual(16, ghostReceiveSystem.GhostCountOnClient); } }
public void GhostCollectionGenerateSameHashOnClientAndServer() { using (var testWorld = new NetCodeTestWorld()) { var ghost1 = new GameObject(); ghost1.AddComponent <TestNetCodeAuthoring>().Converter = new TestConverter(); ghost1.AddComponent <GhostAuthoringComponent>().DefaultGhostMode = GhostAuthoringComponent.GhostMode.Predicted; var ghost2 = new GameObject(); ghost2.AddComponent <TestNetCodeAuthoring>().Converter = new TestConverter(); ghost2.AddComponent <GhostAuthoringComponent>().DefaultGhostMode = GhostAuthoringComponent.GhostMode.Interpolated; testWorld.Bootstrap(true); testWorld.CreateGhostCollection(ghost1, ghost2); testWorld.CreateWorlds(true, 1); float frameTime = 1.0f / 60.0f; var serverCollectionSystem = testWorld.ServerWorld.GetExistingSystem <GhostCollectionSystem>(); var clientCollectionSystem = testWorld.ClientWorlds[0].GetExistingSystem <GhostCollectionSystem>(); //First tick: compute on both client and server the ghost collection hash testWorld.Tick(frameTime); Assert.AreEqual(serverCollectionSystem.CalculateComponentCollectionHash(), clientCollectionSystem.CalculateComponentCollectionHash()); // compare the list of loaded prefabs var serverCollectionSingleton = testWorld.TryGetSingletonEntity <GhostCollection>(testWorld.ServerWorld); var clientCollectionSingleton = testWorld.TryGetSingletonEntity <GhostCollection>(testWorld.ClientWorlds[0]); Assert.AreNotEqual(Entity.Null, serverCollectionSingleton); Assert.AreNotEqual(Entity.Null, clientCollectionSingleton); var serverCollection = testWorld.ServerWorld.EntityManager.GetBuffer <GhostCollectionPrefab>(serverCollectionSingleton); var clientCollection = testWorld.ClientWorlds[0].EntityManager.GetBuffer <GhostCollectionPrefab>(clientCollectionSingleton); Assert.AreEqual(serverCollection.Length, clientCollection.Length); for (int i = 0; i < serverCollection.Length; ++i) { Assert.AreEqual(serverCollection[i].GhostType, clientCollection[i].GhostType); Assert.AreEqual(serverCollection[i].Hash, clientCollection[i].Hash); } //Check that and server can connect (same component hash) Assert.IsTrue(testWorld.Connect(frameTime, 4)); testWorld.GoInGame(); for (int i = 0; i < 10; ++i) { testWorld.Tick(frameTime); } Assert.IsTrue(testWorld.ClientWorlds[0].GetExistingSystem <NetworkStreamReceiveSystem>() .HasSingleton <NetworkIdComponent>()); } }
public void Rpc_LateCreationOfSystem_Throws() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true); testWorld.CreateWorlds(true, 1); float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); Assert.Throws <InvalidOperationException>(() => { testWorld.ServerWorld.GetOrCreateSystem(typeof(NonSerializedRpcCommandRequestSystem)); }); Assert.Throws <InvalidOperationException>(() => { testWorld.ClientWorlds[0].GetOrCreateSystem(typeof(NonSerializedRpcCommandRequestSystem)); }); } }
public void EntityReferenceSetAtSpawnIsResolved() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true); var ghostGameObject = new GameObject(); ghostGameObject.AddComponent <TestNetCodeAuthoring>().Converter = new GhostValueSerializerConverter(); var referencedGameObject = new GameObject(); referencedGameObject.AddComponent <GhostOwnerComponentAuthoring>(); Assert.IsTrue(testWorld.CreateGhostCollection(ghostGameObject, referencedGameObject)); testWorld.CreateWorlds(true, 1); float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); // Go in-game testWorld.GoInGame(); for (int i = 0; i < 4; ++i) { testWorld.Tick(frameTime); } var serverRefEntity = testWorld.SpawnOnServer(referencedGameObject); var serverEnt = testWorld.SpawnOnServer(ghostGameObject); testWorld.ServerWorld.EntityManager.SetComponentData(serverEnt, new GhostValueSerializer { EntityValue = serverRefEntity }); // Let the game run for a bit so the ghosts are spawned on the client for (int i = 0; i < 8; ++i) { testWorld.Tick(frameTime); var clientRefEntity = testWorld.TryGetSingletonEntity <GhostOwnerComponent>(testWorld.ClientWorlds[0]); var clientEntity = testWorld.TryGetSingletonEntity <GhostValueSerializer>(testWorld.ClientWorlds[0]); if (clientEntity != Entity.Null) { // Make sure the reference always exist if the ghost exists Assert.AreEqual(clientRefEntity, testWorld.ClientWorlds[0].EntityManager.GetComponentData <GhostValueSerializer>(clientEntity).EntityValue); } } // Verify that we did get the referenced entity at some point Assert.AreNotEqual(Entity.Null, testWorld.TryGetSingletonEntity <GhostOwnerComponent>(testWorld.ClientWorlds[0])); } }
public void MaxSmoothingDistanceIsUsed() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true, typeof(MoveExtrapolated), typeof(CheckInterpolationDistance)); var ghostGameObject = new GameObject(); ghostGameObject.AddComponent <TestNetCodeAuthoring>().Converter = new GhostExtrapolationConverter(); ghostGameObject.AddComponent <GhostAuthoringComponent>(); Assert.IsTrue(testWorld.CreateGhostCollection(ghostGameObject)); testWorld.CreateWorlds(true, 1); var tickRate = testWorld.ServerWorld.EntityManager.CreateEntity(); // Set low net tick rate to make sure interpolation is used testWorld.ServerWorld.EntityManager.AddComponentData(tickRate, new ClientServerTickRate { NetworkTickRate = 30 }); testWorld.SpawnOnServer(ghostGameObject); float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); // Go in-game testWorld.GoInGame(); for (int i = 0; i < 8; ++i) { testWorld.Tick(frameTime); } var clientEnt = testWorld.TryGetSingletonEntity <TestExtrapolated>(testWorld.ClientWorlds[0]); Assert.AreNotEqual(Entity.Null, clientEnt); Assert.Less(testWorld.ClientWorlds[0].EntityManager.GetComponentData <TestExtrapolated>(clientEnt).Value, 100); // Let the game run for a bit so the ghosts are spawned on the client for (int i = 0; i < 256; ++i) { testWorld.Tick(frameTime); } Assert.Greater(testWorld.ClientWorlds[0].EntityManager.GetComponentData <TestExtrapolated>(clientEnt).Value, 200); } }
public void StructWithLargeNumberOfFields() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true); var ghostGameObject = new GameObject(); ghostGameObject.AddComponent <TestNetCodeAuthoring>().Converter = new GhostGenBigStructConverter(); Assert.IsTrue(testWorld.CreateGhostCollection(ghostGameObject)); testWorld.CreateWorlds(true, 1); var serverEntity = testWorld.SpawnOnServer(ghostGameObject); //Use reflection.. just because if is faster var data = default(GhostGenBigStruct); unsafe { var values = (int *)UnsafeUtility.AddressOf(ref data); for (int i = 0; i < 100; ++i) { values[i] = i; } } testWorld.ServerWorld.EntityManager.SetComponentData(serverEntity, data); float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); // Go in-game testWorld.GoInGame(); // Let the game run for a bit so the ghosts are spawned on the client for (int i = 0; i < 16; ++i) { testWorld.Tick(frameTime); } var clientEntity = testWorld.TryGetSingletonEntity <GhostGenBigStruct>(testWorld.ClientWorlds[0]); var clientData = testWorld.ClientWorlds[0].EntityManager.GetComponentData <GhostGenBigStruct>(clientEntity); var serverData = testWorld.ServerWorld.EntityManager.GetComponentData <GhostGenBigStruct>(serverEntity); Assert.AreEqual(serverData, clientData); } }
public void GhostsCanBeStaticWhenChunksAreDirty() { using (var testWorld = new NetCodeTestWorld()) { // The system will get write access to translation which will dirty the chunk, but not actually write anything testWorld.Bootstrap(true, typeof(StaticOptimizationTestSystem)); StaticOptimizationTestSystem.s_ModifyNetworkId = 1; SetupBasicTest(testWorld, 16); var clientEntityManager = testWorld.ClientWorlds[0].EntityManager; var clientQuery = clientEntityManager.CreateEntityQuery(ComponentType.ReadOnly <GhostOwnerComponent>()); using (var clientEntities = clientQuery.ToEntityArray(Allocator.TempJob)) { Assert.AreEqual(16, clientEntities.Length); var lastSnapshot = new NativeArray <uint>(clientEntities.Length, Allocator.Temp); for (int i = 0; i < clientEntities.Length; ++i) { var clientEnt = clientEntities[i]; // Store the last tick we got for this var clientSnapshotBuffer = clientEntityManager.GetBuffer <SnapshotDataBuffer>(clientEnt); var clientSnapshot = clientEntityManager.GetComponentData <SnapshotData>(clientEnt); lastSnapshot[i] = clientSnapshot.GetLatestTick(clientSnapshotBuffer); } // Run a bit longer for (int i = 0; i < 16; ++i) { testWorld.Tick(frameTime); } // Verify that we did not get any new snapshot for (int i = 0; i < clientEntities.Length; ++i) { var clientEnt = clientEntities[i]; // Store the last tick we got for this var clientSnapshotBuffer = clientEntityManager.GetBuffer <SnapshotDataBuffer>(clientEnt); var clientSnapshot = clientEntityManager.GetComponentData <SnapshotData>(clientEnt); Assert.AreEqual(lastSnapshot[i], clientSnapshot.GetLatestTick(clientSnapshotBuffer)); } } } }
public void Rpc_MalformedPackets_ThrowsAndLogError() { using (var testWorld = new NetCodeTestWorld()) { testWorld.DriverRandomSeed = 0xbadc0de; testWorld.DriverFuzzOffset = 1; testWorld.DriverFuzzFactor = new int[2]; testWorld.DriverFuzzFactor[0] = 10; testWorld.Bootstrap(true, typeof(MalformedClientRcpSendSystem), typeof(ServerMultipleRpcReceiveSystem), typeof(MultipleClientSerializedRpcCommandRequestSystem)); testWorld.CreateWorlds(true, 2); int SendCount = 15; MalformedClientRcpSendSystem.SendCount[0] = SendCount; MalformedClientRcpSendSystem.SendCount[1] = SendCount; MalformedClientRcpSendSystem.Cmds[0] = new ClientIdRpcCommand { Id = 0 }; MalformedClientRcpSendSystem.Cmds[1] = new ClientIdRpcCommand { Id = 1 }; ServerMultipleRpcReceiveSystem.ReceivedCount[0] = 0; ServerMultipleRpcReceiveSystem.ReceivedCount[1] = 0; float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); LogAssert.Expect(LogType.Error, new Regex("RpcSystem received invalid rpc from connection 1")); for (int i = 0; i < 32; ++i) { testWorld.Tick(16f / 1000f); } Assert.Less(ServerMultipleRpcReceiveSystem.ReceivedCount[0], SendCount); Assert.True(ServerMultipleRpcReceiveSystem.ReceivedCount[1] == SendCount); } }
public void GhostValuesAreSerialized() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true); var ghostGameObject = new GameObject(); ghostGameObject.AddComponent <TestNetCodeAuthoring>().Converter = new GhostValueSerializerConverter(); Assert.IsTrue(testWorld.CreateGhostCollection(ghostGameObject)); testWorld.CreateWorlds(true, 1); testWorld.SpawnOnServer(ghostGameObject); SetGhostValues(testWorld, 42); float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); // Go in-game testWorld.GoInGame(); // Let the game run for a bit so the ghosts are spawned on the client for (int i = 0; i < 64; ++i) { testWorld.Tick(frameTime); } VerifyGhostValues(testWorld); SetGhostValues(testWorld, 43); for (int i = 0; i < 64; ++i) { testWorld.Tick(frameTime); } // Assert that replicated version is correct VerifyGhostValues(testWorld); } }
public void StaticGhostsAreNotSent() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true); SetupBasicTest(testWorld, 16); var clientEntityManager = testWorld.ClientWorlds[0].EntityManager; var clientQuery = clientEntityManager.CreateEntityQuery(ComponentType.ReadOnly <GhostOwnerComponent>()); using (var clientEntities = clientQuery.ToEntityArray(Allocator.TempJob)) { Assert.AreEqual(16, clientEntities.Length); var lastSnapshot = new NativeArray <uint>(clientEntities.Length, Allocator.Temp); for (int i = 0; i < clientEntities.Length; ++i) { var clientEnt = clientEntities[i]; // Store the last tick we got for this var clientSnapshotBuffer = clientEntityManager.GetBuffer <SnapshotDataBuffer>(clientEnt); var clientSnapshot = clientEntityManager.GetComponentData <SnapshotData>(clientEnt); lastSnapshot[i] = clientSnapshot.GetLatestTick(clientSnapshotBuffer); } // Run a bit longer for (int i = 0; i < 16; ++i) { testWorld.Tick(frameTime); } // Verify that we did not get any new snapshot for (int i = 0; i < clientEntities.Length; ++i) { var clientEnt = clientEntities[i]; // Store the last tick we got for this var clientSnapshotBuffer = clientEntityManager.GetBuffer <SnapshotDataBuffer>(clientEnt); var clientSnapshot = clientEntityManager.GetComponentData <SnapshotData>(clientEnt); Assert.AreEqual(lastSnapshot[i], clientSnapshot.GetLatestTick(clientSnapshotBuffer)); } } } }
public void ConnectSingleClient() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true, typeof(CheckConnectionSystem)); testWorld.CreateWorlds(true, 1); CheckConnectionSystem.IsConnected = 0; var ep = NetworkEndPoint.LoopbackIpv4; ep.Port = 7979; testWorld.ServerWorld.GetExistingSystem <NetworkStreamReceiveSystem>().Listen(ep); testWorld.ClientWorlds[0].GetExistingSystem <NetworkStreamReceiveSystem>().Connect(ep); for (int i = 0; i < 16 && CheckConnectionSystem.IsConnected != 3; ++i) { testWorld.Tick(16f / 1000f); } Assert.AreEqual(3, CheckConnectionSystem.IsConnected); } }
public void SameVersion_ConnectSuccessfully() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true); testWorld.CreateWorlds(true, 1); var serverVersion = testWorld.ServerWorld.EntityManager.CreateEntity(typeof(NetworkProtocolVersion)); testWorld.ServerWorld.EntityManager.SetComponentData(serverVersion, new NetworkProtocolVersion { NetCodeVersion = 1, GameVersion = 0, RpcCollectionVersion = 1, ComponentCollectionVersion = 1 }); var clientVersion = testWorld.ClientWorlds[0].EntityManager.CreateEntity(typeof(NetworkProtocolVersion)); testWorld.ClientWorlds[0].EntityManager.SetComponentData(clientVersion, new NetworkProtocolVersion { NetCodeVersion = 1, GameVersion = 0, RpcCollectionVersion = 1, ComponentCollectionVersion = 1 }); var ep = NetworkEndPoint.LoopbackIpv4; ep.Port = 7979; testWorld.ServerWorld.GetExistingSystem <NetworkStreamReceiveSystem>().Listen(ep); testWorld.ClientWorlds[0].GetExistingSystem <NetworkStreamReceiveSystem>().Connect(ep); for (int i = 0; i < 16; ++i) { testWorld.Tick(16f / 1000f); } var query = testWorld.ClientWorlds[0].EntityManager.CreateEntityQuery(ComponentType.ReadOnly <NetworkStreamConnection>()); Assert.AreEqual(1, query.CalculateEntityCount()); } }
public void ServerGhostCountOnlyIncludesRelevantSet() { using (var testWorld = new NetCodeTestWorld()) { testWorld.Bootstrap(true); var ghostGameObject = new GameObject(); ghostGameObject.AddComponent <TestNetCodeAuthoring>().Converter = new LateJoinCompletionConverter(); Assert.IsTrue(testWorld.CreateGhostCollection(ghostGameObject)); testWorld.CreateWorlds(true, 1); float frameTime = 1.0f / 60.0f; // Connect and make sure the connection could be established Assert.IsTrue(testWorld.Connect(frameTime, 4)); for (int i = 0; i < 8; ++i) { testWorld.SpawnOnServer(ghostGameObject); } // Go in-game testWorld.GoInGame(); testWorld.Tick(frameTime); // Setup relevancy var ghostSendSystem = testWorld.ServerWorld.GetExistingSystem <GhostSendSystem>(); ghostSendSystem.GhostRelevancyMode = GhostRelevancyMode.SetIsRelevant; var serverConnectionEnt = testWorld.TryGetSingletonEntity <NetworkIdComponent>(testWorld.ServerWorld); var serverConnectionId = testWorld.ServerWorld.EntityManager.GetComponentData <NetworkIdComponent>(serverConnectionEnt).Value; var query = testWorld.ServerWorld.EntityManager.CreateEntityQuery(ComponentType.ReadWrite <GhostComponent>()); var ghosts = query.ToComponentDataArray <GhostComponent>(Allocator.Temp); Assert.AreEqual(ghosts.Length, 8); for (int i = 0; i < 6; ++i) { ghostSendSystem.GhostRelevancySet.TryAdd(new RelevantGhostForConnection { Ghost = ghosts[i].ghostId, Connection = serverConnectionId }, 1); } // Let the game run for a bit so the ghosts are spawned on the client for (int i = 0; i < 4; ++i) { testWorld.Tick(frameTime); } var ghostReceiveSystem = testWorld.ClientWorlds[0].GetExistingSystem <GhostReceiveSystem>(); // Validate that the ghost was deleted on the cliet Assert.AreEqual(6, ghostReceiveSystem.GhostCountOnServer); Assert.AreEqual(6, ghostReceiveSystem.GhostCountOnClient); // Spawn a few more and verify taht the count is updated for (int i = 0; i < 8; ++i) { testWorld.SpawnOnServer(ghostGameObject); } for (int i = 0; i < 4; ++i) { testWorld.Tick(frameTime); } Assert.AreEqual(6, ghostReceiveSystem.GhostCountOnServer); Assert.AreEqual(6, ghostReceiveSystem.GhostCountOnClient); } }