public void RequestControlUpdate(RailEntityClient entity, RailStateDelta delta) { // Can't infer anything if the delta is an empty frozen update if (delta.IsFrozen) { return; } if (delta.IsRemoving) { if (entity.Controller != null) { localPeer.RevokeControlInternal(entity); } } else if (delta.HasControllerData) { if (entity.Controller == null) { localPeer.GrantControlInternal(entity); } } else { if (entity.Controller != null) { localPeer.RevokeControlInternal(entity); } } }
public static RailCommandUpdate Create( IRailCommandConstruction commandCreator, RailEntityClient entity, IEnumerable <RailCommand> commands) { RailCommandUpdate update = commandCreator.CreateCommandUpdate(); update.Initialize(entity.Id, commands); update.Entity = entity; return(update); }
/// <summary> /// Updates the room a number of ticks. If we have entities waiting to be /// added, this function will check them and add them if applicable. /// </summary> public void ClientUpdate(Tick localTick, Tick estimatedServerTick) { Tick = estimatedServerTick; UpdatePendingEntities(estimatedServerTick); OnPreRoomUpdate(Tick); // Collect the entities in the priority order and // separate them out for either update or removal foreach (RailEntityBase railEntityBase in Entities) { RailEntityClient entity = (RailEntityClient)railEntityBase; if (entity.ShouldRemove) { ToRemove.Add(entity); } else { ToUpdate.Add(entity); } } // Wave 0: Remove all sunsetted entities ToRemove.ForEach(RemoveEntity); // Wave 1: Start/initialize all entities ToUpdate.ForEach(e => e.PreUpdate()); // Wave 2: Update all entities ToUpdate.ForEach(e => e.ClientUpdate(localTick)); // Wave 3: Post-update all entities ToUpdate.ForEach(e => e.PostUpdate()); ToRemove.Clear(); ToUpdate.Clear(); OnPostRoomUpdate(Tick); }
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); }