public void Update(TimeSpan frameTime) { List <object> toRemove = new List <object>(); foreach (KeyValuePair <ISyncable, Dictionary <object, BufferedData> > fieldBuffer in FieldWatcher.BufferedChanges) { ISyncable syncable = fieldBuffer.Key; foreach (KeyValuePair <object, BufferedData> instanceBuffer in fieldBuffer.Value) { object instance = instanceBuffer.Key; if (CheckShouldRemove(syncable, instance, instanceBuffer.Value)) { toRemove.Add(instanceBuffer.Key); } else if (!instanceBuffer.Value.Sent) { ISyncable field = fieldBuffer.Key; field.GetSyncHandler(instance)?.Invoke(instanceBuffer.Value.ToSend); field.GetSyncHandler(SyncableInstance.Any) ?.Invoke(instanceBuffer.Value.ToSend); instanceBuffer.Value.Sent = true; } } toRemove.ForEach(o => fieldBuffer.Value.Remove(o)); toRemove.Clear(); } m_RailClient.Update(); }
public void Update(TimeSpan frameTime) { List <object> toRemove = new List <object>(); foreach (KeyValuePair <ValueAccess, Dictionary <object, ValueChangeRequest> > buffer in FieldChangeBuffer.BufferedChanges) { ValueAccess access = buffer.Key; foreach (KeyValuePair <object, ValueChangeRequest> instanceBuffer in buffer.Value) { object instance = instanceBuffer.Key; if (CheckShouldRemove(access, instance, instanceBuffer.Value)) { toRemove.Add(instanceBuffer.Key); } else if (!instanceBuffer.Value.RequestProcessed) { access.GetHandler(instance)?.Invoke(instanceBuffer.Value.RequestedValue); instanceBuffer.Value.RequestProcessed = true; } } toRemove.ForEach(o => buffer.Value.Remove(o)); toRemove.Clear(); } m_RailClient.Update(); }
private void ClientServerCommunication() { // Initialization CampaignTimeControlMode expectedTimeControl = CampaignTimeControlMode.StoppablePlay; RailClientRoom clientRoom = m_Client.StartRoom(); RailServerRoom serverRoom = m_Server.StartRoom(); RailEntityServer <SomeState> entityServerSide = serverRoom.AddNewEntity <RailEntityServer <SomeState> >(); entityServerSide.State.Mode = expectedTimeControl; m_Server.AddClient(m_PeerServerSide.Object, ""); m_Client.SetPeer(m_PeerClientSide.Object); Assert.Empty(clientRoom.Entities); Assert.Single(serverRoom.Entities); // Sync entity from server to client for (int i = 0; i < RailConfig.SERVER_SEND_RATE + RailConfig.CLIENT_SEND_RATE + 1; ++i) { m_ConClientSide.ExecuteSends(); m_Server.Update(); m_ConServerSide.ExecuteSends(); m_Client.Update(); } // The client has received the entity. Assert.Single(clientRoom.Entities); Assert.Single(serverRoom.Entities); // Clients representation of the entity is identical to the server RailEntityBase entityProxy = clientRoom.Entities.First(); Assert.IsType <RailEntityClient <SomeState> >(entityProxy); RailEntityClient <SomeState> entityClientSide = entityProxy as RailEntityClient <SomeState>; Assert.NotNull(entityClientSide); Assert.Equal(entityServerSide.Id, entityProxy.Id); Assert.Equal(expectedTimeControl, entityServerSide.State.Mode); Assert.Equal(expectedTimeControl, entityClientSide.State.Mode); // Change the entity on server side and sync to the client expectedTimeControl = CampaignTimeControlMode.Stop; entityServerSide.State.Mode = expectedTimeControl; // Let the server detect the change and send the packet bool bWasSendTick = false; while (!bWasSendTick) { m_Server.Update(); bWasSendTick = serverRoom.Tick.IsSendTick(RailConfig.SERVER_SEND_RATE); } // Let the client receive & process the packet. We need to bring the client up to the same tick as the server to see the result. while (clientRoom.Tick < serverRoom.Tick) { m_ConServerSide.ExecuteSends(); m_Client.Update(); } Assert.Equal(expectedTimeControl, entityServerSide.State.Mode); Assert.Equal(expectedTimeControl, entityClientSide.State.Mode); }
private void EntitiesAreSynchronized() { // Initialization RailClientRoom clientRoom = client.StartRoom(); RailServerRoom serverRoom = server.StartRoom(); EntityServer entityServerSide = serverRoom.AddNewEntity <EntityServer>(); server.AddClient(peerServerSide.Object, ""); client.SetPeer(peerClientSide.Object); // Nothing has been sent or received yet peerClientSide.Verify( c => c.SendPayload(It.IsAny <ArraySegment <byte> >()), Times.Never()); peerServerSide.Verify( c => c.SendPayload(It.IsAny <ArraySegment <byte> >()), Times.Never()); Assert.Empty(clientRoom.Entities); Assert.Single(serverRoom.Entities); // Let the server send its update to the client for (int i = 0; i < RailConfig.SERVER_SEND_RATE + RailConfig.CLIENT_SEND_RATE + 1; ++i) { peerServerSide.Object.PollEvents(); server.Update(); peerClientSide.Object.PollEvents(); client.Update(); } // The client has received the server entity. Assert.Single(clientRoom.Entities); Assert.Single(serverRoom.Entities); // Clients representation of the entity is identical to the server RailEntityBase entityProxy = clientRoom.Entities.First(); Assert.IsType <EntityClient>(entityProxy); EntityClient entityClientSide = entityProxy as EntityClient; Assert.NotNull(entityClientSide); Assert.Equal(entityServerSide.Id, entityProxy.Id); Assert.Equal(entityClientSide.State.PosX, entityServerSide.State.PosX); Assert.Equal(entityClientSide.State.PosY, entityServerSide.State.PosY); // Change the entity on the server side and sync it to the client float fExpectedPosX = 42; float fExpectedPosY = 106; entityServerSide.State.PosX = fExpectedPosX; entityServerSide.State.PosY = fExpectedPosY; // Let the server detect the change and send the packet server.Update(); bool bWasSendTick = serverRoom.Tick.IsSendTick(RailConfig.SERVER_SEND_RATE); while (!bWasSendTick) { server.Update(); bWasSendTick = serverRoom.Tick.IsSendTick(RailConfig.SERVER_SEND_RATE); } // Let the client receive & process the packet. We need to bring the client up to the same tick as the server to see the result. while (clientRoom.Tick < serverRoom.Tick) { peerClientSide.Object.PollEvents(); client.Update(); } Assert.Equal(fExpectedPosX, entityClientSide.State.PosX); Assert.Equal(fExpectedPosY, entityClientSide.State.PosY); Assert.Equal(fExpectedPosX, entityServerSide.State.PosX); Assert.Equal(fExpectedPosY, entityServerSide.State.PosY); }