public CommandProcessor(ICommandProcessingStrategy processingStrategy, ICommandQueue commandQueue) { _processingStrategy = processingStrategy; _commandQueue = commandQueue; _cancellationTokenSource = new CancellationTokenSource(); var token = _cancellationTokenSource.Token; var task = new Task( () => { while (!token.IsCancellationRequested) { var cmd = _commandQueue.Dequeue(); while (cmd != null) { _processingStrategy.ProcessCommand(cmd.Execute); cmd = commandQueue.Dequeue(); } Thread.Sleep(100); } }, token, TaskCreationOptions.LongRunning); task.Start(); }
public void ProcessMoves() { while (_commandsQueue.Count() != 0) { var command = _commandsQueue.Dequeue(); if (command.Direction == RelativeDirection.Forward) { var newCoordinates = _position.ProcessMovement(command.Distance); if (!_terrain.WithinPerimeter(newCoordinates)) { _commandsQueue.Clear(); } else { _position.ExecuteMovement(newCoordinates); } } else { _position.ExecuteTurn(command); } } }
private void ProcessInputQueue() { var inputs = _commandQueue.Dequeue(); if (inputs.Any()) { //Store new input foreach (var input in inputs) { GameLog.Add(_world.Tick, input); foreach (var command in input.Commands) { Log.Trace(this, input.ActorId + " >> " + input.Tick + ": " + input.Commands.Count()); var inputEntity = Contexts.input.CreateEntity(); command.Execute(inputEntity); inputEntity.AddTick(input.Tick); inputEntity.AddActorId(input.ActorId); //TODO: after adding input, order the commands by timestamp => if commands intersect, the first one should win, timestamp should be added by server, RTT has to be considered //ordering by timestamp requires loopback functionality because we have to wait for server-response; at the moment commands get distributed to all clients except oneself //if a command comes back from server and it was our own command, the local command has to be overwritten instead of just adding it (like it is at the moment) } } var otherActorsInput = inputs.Where(input => input.ActorId != LocalActorId).ToList(); if (otherActorsInput.Any()) { var firstRemoteInputTick = otherActorsInput.Min(input => input.Tick); var lastRemoteInputTick = otherActorsInput.Max(input => input.Tick); Log.Trace(this, ">>>Input from " + firstRemoteInputTick + " to " + lastRemoteInputTick); //Only rollback if the mispredicted frame was in the past (the frame can be in the future e.g. due to high lag compensation) if (firstRemoteInputTick < _world.Tick) { var targetTick = _world.Tick; _world.RevertToTick(firstRemoteInputTick); //Restore last local state while (_world.Tick <= lastRemoteInputTick && _world.Tick < targetTick) { _world.Simulate(); } while (_world.Tick < targetTick) { _world.Predict(); } } } } }