Exemplo n.º 1
0
        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();
                        }
                    }
                }
            }
        }
Exemplo n.º 2
0
        private void Simulate(ServerFrame frame, bool isNeedGenSnap = true)
        {
            ProcessInputQueue(frame);
            _world.Simulate(isNeedGenSnap);
            var tick = _world.Tick;

            cmdBuffer.SetClientTick(tick);
            SetHashCode();
            if (isNeedGenSnap && tick % FrameBuffer.SnapshotFrameInterval == 0)
            {
                _world.CleanUselessSnapshot(System.Math.Min(cmdBuffer.nextTickToCheck - 1, _world.Tick));
            }
        }