Exemplo n.º 1
0
        public GameStep?GetNextStep()
        {
            lock (_gameHistory) {
                GameStep nextStep = new GameStep();

                // If new Game Step is found
                if (_gameHistory.TryGet(_unityGameStepNum, out nextStep))
                {
                    if (_unityGameStepNum != nextStep.StepNumber)
                    {
                        Log("Exception!");
                        throw new InvalidProgramException("Next step should be last step + 1!");
                    }
                    _unityGameStepNum++;
                    return(nextStep);
                }
                // If no game step is found
                else
                {
                    var lag = _highestGameStepNum - _unityGameStepNum;
                    return(null);
                }
            }
        }
Exemplo n.º 2
0
        private void SendPlayerUpdates()
        {
            Console.WriteLine("Starting Broadcasts");
            _lastStepBroadcast = DateTime.UtcNow;

            DateTime start           = DateTime.UtcNow;
            int      sleepIntervalMs = GameStepIntervalMs;

            try {
                while (true)
                {
                    if (sleepIntervalMs > 0)
                    {
                        Thread.Sleep(sleepIntervalMs);
                    }

                    start = DateTime.UtcNow;

                    GameStep gameStep;
                    lock (_gameLock) {
                        byte ellapsed = (byte)Math.Min((DateTime.UtcNow - _lastStepBroadcast).TotalMilliseconds, byte.MaxValue);

                        // Create new GameStep to broadcast
                        gameStep = new GameStep(_stepNumber, ellapsed);

                        GameStep lastGameStep;
                        // If previous GameSteps exit
                        if (_gameHistory.Count > 0 && _gameHistory.TryGet((UInt16)(_stepNumber - 1), out lastGameStep))
                        {
                            foreach (var currentInput in _curPlayerInputs)
                            {
                                // If Player input exists from last game update, take XOR of last player input and current player input
                                PlayerInputs lastInput;
                                if (lastGameStep.PlayerInputs.TryGetValue(currentInput.Key, out lastInput))
                                {
                                    var changed = currentInput.Value.Inputs
                                                  .Where(i => !lastInput.Inputs.ContainsKey(i.Key) || lastInput.Inputs[i.Key] != i.Value)
                                                  .ToDictionary(k => k.Key, k => k.Value);

                                    PlayerInputs pi = new PlayerInputs()
                                    {
                                        PlayerId = currentInput.Key,
                                        Inputs   = changed
                                    };

                                    gameStep.PlayerInputs.Add(pi.PlayerId, pi);
                                }
                                // If no last game update for this player, just send current inputs
                                else
                                {
                                    gameStep.PlayerInputs.Add(currentInput.Key, currentInput.Value);
                                }
                            }

                            _curPlayerInputs.Clear();
                        }
                        // If no previous GameSteps exist
                        else
                        {
                            gameStep.PlayerInputs = _curPlayerInputs;
                        }

                        _gameHistory.Add(gameStep);
                    }

                    GameStepCollection gsc = new GameStepCollection(3);
                    gsc.GameSteps.Add(gameStep);

                    // Send Redundant Step #1
                    if (_stepNumber >= 1)
                    {
                        UInt16   idx = (UInt16)Math.Max(_stepNumber - 2, 0);
                        GameStep redundant;
                        if (_gameHistory.TryGet(idx, out redundant))
                        {
                            gsc.GameSteps.Add(redundant);
                        }
                    }

                    // Send Redundant Step #2
                    if (_stepNumber >= 3)
                    {
                        UInt16   idx = (UInt16)Math.Max(_stepNumber - 8, 0);
                        GameStep redundant;
                        if (_gameHistory.TryGet(idx, out redundant))
                        {
                            gsc.GameSteps.Add(redundant);
                        }
                    }

                    BroadcastGameStepCollection(gsc);

                    // Calculate next Sleep Interval
                    _lastStepBroadcast = DateTime.UtcNow;
                    _stepNumber++;
                    TimeSpan broadcastDuration = (_lastStepBroadcast - start);
                    sleepIntervalMs = Math.Max(GameStepIntervalMs - (int)broadcastDuration.TotalMilliseconds, 0);
                }
            }
            catch (Exception e) {
                Console.Write(e);
            }
        }