public void Run()
        {
            Logger.Debug("Initializing GameController.");

            _configurationManager.LoadFromFile(PathHelpers.ExecutableRelativeFile("client_config.toml"));

            _resourceCache.LoadBaseResources();
            // Load resources used by splash screen and main menu.
            LoadSplashResources();
            ShowSplashScreen();

            _resourceCache.LoadLocalResources();

            //identical code for server in baseserver
            if (!AssemblyLoader.TryLoadAssembly <GameShared>(_resourceManager, $"Content.Shared"))
            {
                if (!AssemblyLoader.TryLoadAssembly <GameShared>(_resourceManager, $"Sandbox.Shared"))
                {
                    Logger.Warning($"[ENG] Could not load any Shared DLL.");
                }
            }

            if (!AssemblyLoader.TryLoadAssembly <GameClient>(_resourceManager, $"Content.Client"))
            {
                if (!AssemblyLoader.TryLoadAssembly <GameClient>(_resourceManager, $"Sandbox.Client"))
                {
                    Logger.Warning($"[ENG] Could not load any Client DLL.");
                }
            }

            IoCManager.Resolve <ILightManager>().Initialize();

            // Call Init in game assemblies.
            AssemblyLoader.BroadcastRunLevel(AssemblyLoader.RunLevel.Init);

            //Setup Cluwne first, as the rest depends on it.
            SetupCluwne();
            CleanupSplashScreen();

            //Initialization of private members
            _tileDefinitionManager.InitializeResources();

            _serializer.Initialize();
            var prototypeManager = IoCManager.Resolve <IPrototypeManager>();

            prototypeManager.LoadDirectory(@"Prototypes");
            prototypeManager.Resync();
            _networkManager.Initialize(false);
            _console.Initialize();
            _netGrapher.Initialize();
            _userInterfaceManager.Initialize();
            _mapManager.Initialize();
            _placementManager.Initialize();
            _entityManager.Initialize();

            _networkManager.RegisterNetMessage <MsgFullState>(MsgFullState.NAME, message => IoCManager.Resolve <IGameStateManager>().HandleFullStateMessage((MsgFullState)message));
            _networkManager.RegisterNetMessage <MsgStateUpdate>(MsgStateUpdate.NAME, message => IoCManager.Resolve <IGameStateManager>().HandleStateUpdateMessage((MsgStateUpdate)message));

            _client.Initialize();

            _stateManager.RequestStateChange <MainScreen>();

            #region GameLoop

            // maximum number of ticks to queue before the loop slows down.
            const int maxTicks = 5;

            _time.ResetRealTime();
            var maxTime = TimeSpan.FromTicks(_time.TickPeriod.Ticks * maxTicks);

            while (CluwneLib.IsRunning)
            {
                var accumulator = _time.RealTime - _lastTick;

                // If the game can't keep up, limit time.
                if (accumulator > maxTime)
                {
                    // limit accumulator to max time.
                    accumulator = maxTime;

                    // pull lastTick up to the current realTime
                    // This will slow down the simulation, but if we are behind from a
                    // lag spike hopefully it will be able to catch up.
                    _lastTick = _time.RealTime - maxTime;

                    // announce we are falling behind
                    if ((_time.RealTime - _lastKeepUpAnnounce).TotalSeconds >= 15.0)
                    {
                        Logger.Warning("[ENG] MainLoop: Cannot keep up!");
                        _lastKeepUpAnnounce = _time.RealTime;
                    }
                }

                _time.StartFrame();

                var realFrameEvent = new FrameEventArgs((float)_time.RealFrameTime.TotalSeconds);

                // process Net/KB/Mouse input
                Process(realFrameEvent);

                _time.InSimulation = true;
                // run the simulation for every accumulated tick
                while (accumulator >= _time.TickPeriod)
                {
                    accumulator -= _time.TickPeriod;
                    _lastTick   += _time.TickPeriod;

                    // only run the sim if unpaused, but still use up the accumulated time
                    if (!_time.Paused)
                    {
                        // update the simulation
                        var simFrameEvent = new FrameEventArgs((float)_time.FrameTime.TotalSeconds);
                        Update(simFrameEvent);
                        _time.CurTick++;
                    }
                }

                // if not paused, save how close to the next tick we are so interpolation works
                if (!_time.Paused)
                {
                    _time.TickRemainder = accumulator;
                }

                _time.InSimulation = false;

                // render the simulation
                Render(realFrameEvent);
            }

            #endregion GameLoop

            _networkManager.ClientDisconnect("Client disconnected from game.");
            CluwneLib.Terminate();
            Logger.Info("GameController terminated.");

            IoCManager.Resolve <IConfigurationManager>().SaveToFile();
        }
Example #2
0
        /// <summary>
        ///     Start running the loop. This function will block for as long as the loop is Running.
        ///     Set Running to false to exit the loop and return from this function.
        /// </summary>
        public void Run()
        {
            if (_timing.TickRate <= 0)
            {
                throw new InvalidOperationException("TickRate must be greater than 0.");
            }

            Running = true;

            FrameEventArgs realFrameEvent;
            FrameEventArgs simFrameEvent;

            _timing.ResetRealTime();

            while (Running)
            {
                // maximum number of ticks to queue before the loop slows down.
                var maxTime = TimeSpan.FromTicks(_timing.TickPeriod.Ticks * MaxQueuedTicks);

                var accumulator = _timing.RealTime - _lastTick;

                // If the game can't keep up, limit time.
                if (accumulator > maxTime)
                {
                    // limit accumulator to max time.
                    accumulator = maxTime;

                    // pull lastTick up to the current realTime
                    // This will slow down the simulation, but if we are behind from a
                    // lag spike hopefully it will be able to catch up.
                    _lastTick = _timing.RealTime - maxTime;

                    // announce we are falling behind
                    if ((_timing.RealTime - _lastKeepUp).TotalSeconds >= 15.0)
                    {
                        Logger.WarningS("eng", "MainLoop: Cannot keep up!");
                        _lastKeepUp = _timing.RealTime;
                    }
                }

                _timing.StartFrame();
                realFrameEvent = new FrameEventArgs((float)_timing.RealFrameTime.TotalSeconds);
#if EXCEPTION_TOLERANCE
                try
#endif
                {
                    // process Net/KB/Mouse input
                    Input?.Invoke(this, realFrameEvent);
                }
#if EXCEPTION_TOLERANCE
                catch (Exception exp)
                {
                    _runtimeLog.LogException(exp, "GameLoop Input");
                }
#endif
                _timing.InSimulation = true;
                var tickPeriod = CalcTickPeriod();


                // run the simulation for every accumulated tick
                while (accumulator >= tickPeriod)
                {
                    accumulator -= tickPeriod;
                    _lastTick   += tickPeriod;

                    // only run the simulation if unpaused, but still use up the accumulated time
                    if (_timing.Paused)
                    {
                        continue;
                    }

                    // update the simulation
                    simFrameEvent = new FrameEventArgs((float)_timing.FrameTime.TotalSeconds);
#if EXCEPTION_TOLERANCE
                    var threw = false;
                    try
                    {
#endif
                    if (EnableMetrics)
                    {
                        using (_frameTimeHistogram.NewTimer())
                        {
                            Tick?.Invoke(this, simFrameEvent);
                        }
                    }
                    else
                    {
                        Tick?.Invoke(this, simFrameEvent);
                    }
#if EXCEPTION_TOLERANCE
                }
                catch (Exception exp)
                {
                    threw = true;
                    _runtimeLog.LogException(exp, "GameLoop Tick");
                    _tickExceptions += 1;

                    if (_tickExceptions > MaxSoftLockExceptions && DetectSoftLock)
                    {
                        Logger.FatalS("eng",
                                      "MainLoop: 10 consecutive exceptions inside GameLoop Tick, shutting down!");
                        Running = false;
                    }
                }

                if (!threw)
                {
                    _tickExceptions = 0;
                }
#endif
                    _timing.CurTick = new GameTick(_timing.CurTick.Value + 1);
                    tickPeriod      = CalcTickPeriod();

                    if (SingleStep)
                    {
                        _timing.Paused = true;
                    }
                }

                // if not paused, save how close to the next tick we are so interpolation works
                if (!_timing.Paused)
                {
                    _timing.TickRemainder = accumulator;
                }

                _timing.InSimulation = false;

                // update out of the simulation

#if EXCEPTION_TOLERANCE
                try
#endif
                {
                    Update?.Invoke(this, realFrameEvent);
                }
#if EXCEPTION_TOLERANCE
                catch (Exception exp)
                {
                    _runtimeLog.LogException(exp, "GameLoop Update");
                }
#endif

                // render the simulation
#if EXCEPTION_TOLERANCE
                try
#endif
                {
                    Render?.Invoke(this, realFrameEvent);
                }
#if EXCEPTION_TOLERANCE
                catch (Exception exp)
                {
                    _runtimeLog.LogException(exp, "GameLoop Render");
                }
#endif

                // Set sleep to 1 if you want to be nice and give the rest of the timeslice up to the os scheduler.
                // Set sleep to 0 if you want to use 100% cpu, but still cooperate with the scheduler.
                // do not call sleep if you want to be 'that thread' and hog 100% cpu.
                if (SleepMode != SleepMode.None)
                {
                    Thread.Sleep((int)SleepMode);
                }
            }
        }
Example #3
0
        /// <summary>
        ///     Start running the loop. This function will block for as long as the loop is Running.
        ///     Set Running to false to exit the loop and return from this function.
        /// </summary>
        public void Run()
        {
            if (_timing.TickRate <= 0)
            {
                throw new InvalidOperationException("TickRate must be greater than 0.");
            }

            Running = true;

            // maximum number of ticks to queue before the loop slows down.
            var maxTime = TimeSpan.FromTicks(_timing.TickPeriod.Ticks * MaxQueuedTicks);

            var realFrameEvent = new MutableFrameEventArgs(0);
            var simFrameEvent  = new MutableFrameEventArgs(0);

            _timing.ResetRealTime();

            while (Running)
            {
                var accumulator = _timing.RealTime - _lastTick;

                // If the game can't keep up, limit time.
                if (accumulator > maxTime)
                {
                    // limit accumulator to max time.
                    accumulator = maxTime;

                    // pull lastTick up to the current realTime
                    // This will slow down the simulation, but if we are behind from a
                    // lag spike hopefully it will be able to catch up.
                    _lastTick = _timing.RealTime - maxTime;

                    // announce we are falling behind
                    if ((_timing.RealTime - _lastKeepUp).TotalSeconds >= 15.0)
                    {
                        Logger.Warning("[ENG] MainLoop: Cannot keep up!");
                        _lastKeepUp = _timing.RealTime;
                    }
                }
                _timing.StartFrame();

                realFrameEvent.SetDeltaSeconds((float)_timing.RealFrameTime.TotalSeconds);

                try
                {
                    // process Net/KB/Mouse input
                    Input?.Invoke(this, realFrameEvent);
                }
                catch (Exception exp)
                {
                    _runtimeLog.LogException(exp, "GameLoop Input");
                }
                _timing.InSimulation = true;

                // run the simulation for every accumulated tick
                while (accumulator >= _timing.TickPeriod)
                {
                    accumulator -= _timing.TickPeriod;
                    _lastTick   += _timing.TickPeriod;

                    // only run the simulation if unpaused, but still use up the accumulated time
                    if (_timing.Paused)
                    {
                        continue;
                    }

                    // update the simulation
                    simFrameEvent.SetDeltaSeconds((float)_timing.FrameTime.TotalSeconds);
                    try
                    {
                        Tick?.Invoke(this, simFrameEvent);
                    }
                    catch (Exception exp)
                    {
                        _runtimeLog.LogException(exp, "GameLoop Tick");
                    }
                    _timing.CurTick++;

                    if (SingleStep)
                    {
                        _timing.Paused = true;
                    }
                }

                // if not paused, save how close to the next tick we are so interpolation works
                if (!_timing.Paused)
                {
                    _timing.TickRemainder = accumulator;
                }

                _timing.InSimulation = false;

                // update out of the simulation
                simFrameEvent.SetDeltaSeconds((float)_timing.FrameTime.TotalSeconds);
                try
                {
                    Update?.Invoke(this, simFrameEvent);
                }
                catch (Exception exp)
                {
                    _runtimeLog.LogException(exp, "GameLoop Update");
                }

                // render the simulation
                try
                {
                    Render?.Invoke(this, realFrameEvent);
                }
                catch (Exception exp)
                {
                    _runtimeLog.LogException(exp, "GameLoop Render");
                }
                // Set sleep to 1 if you want to be nice and give the rest of the timeslice up to the os scheduler.
                // Set sleep to 0 if you want to use 100% cpu, but still cooperate with the scheduler.
                // do not call sleep if you want to be 'that thread' and hog 100% cpu.
                if (SleepMode != SleepMode.None)
                {
                    Thread.Sleep((int)SleepMode);
                }
            }
        }