Example #1
0
 public void RefreshState()
 {
     if (InGame)
     {
         EntityListWrapper.RefreshState();
         Area.RefreshState();
     }
 }
Example #2
0
 public GameController(Memory memory)
 {
     Memory            = memory;
     Area              = new AreaController(this);
     EntityListWrapper = new EntityListWrapper(this);
     Window            = new GameWindow(memory.Process);
     Game              = new TheGame(memory);
     Files             = new FsController(memory);
 }
Example #3
0
 public void RefreshState()
 {
     if (!InGame)
     {
         return;
     }
     Area.RefreshState();
     EntityListWrapper.RefreshState();
 }
Example #4
0
 public GameController(Memory memory)
 {
     this.Memory             = memory;
     this.Area               = new AreaController(this);
     this._entityListWrapper = new EntityListWrapper(this);
     this.Window             = new GameWindow(memory.Process);
     this.Internal           = new TheGame(memory);
     this.Files              = new FsController(memory);
 }
Example #5
0
        public GameController(Memory memory)
        {
            Instance                = this;
            Memory                  = memory;
            Game                    = new TheGame(memory);
            GameStateController     = new GameStateController(memory, Game);
            CoroutineRunner         = new Runner("Main Coroutine");
            CoroutineRunnerParallel = new Runner("Parallel Coroutine");
            Area                    = new AreaController(this);
            EntityListWrapper       = new EntityListWrapper(this);
            Window                  = new GameWindow(memory.Process);
            Cache                   = new Cache();

            Files             = new FsController(memory);
            StashController   = new StashTabController();
            InGame            = InGameReal;
            IsForeGroundCache = WinApi.IsForegroundWindow(Window.Process.MainWindowHandle);
            MainTimer         = Stopwatch.StartNew();
        }
Example #6
0
        public void WhileLoop()
        {
            Task.Run(ParallelCoroutineRunner);
            DebugInformation["FpsLoop"]             = 0;
            DebugInformation["FpsRender"]           = 0;
            DebugInformation["FpsCoroutine"]        = 0;
            DebugInformation["ElapsedMilliseconds"] = 0;
            var   sw                = Stopwatch.StartNew();
            float nextRenderTick    = sw.ElapsedMilliseconds;
            var   tickEverySecond   = sw.ElapsedMilliseconds;
            var   skipTicksRender   = 0f;
            int   fpsLoop           = 0;
            int   fpsRender         = 0;
            int   fpsCoroutine      = 0;
            float updateRate        = 1f / 60f;
            float loopLimit         = 1;
            int   updateAreaLimit   = 100;
            int   updateEntityLimit = 50;
            int   updateStashTabs   = 500;
            int   updateIngameState = 100;
            int   deltaError        = 500;

            //Pause?resumt coroutines in plugins
            foreach (var setting in pluginsSettings)
            {
                setting.Value.Enable.OnValueChanged += () =>
                {
                    var coroutines = CoroutineRunner.Coroutines.Where(x => x.Owner == setting.Key).Concat(CoroutineRunnerParallel.Coroutines.Where(x => x.Owner == setting.Key)).ToList();
                    foreach (var coroutine in coroutines)
                    {
                        if (setting.Value.Enable)
                        {
                            if (coroutine.AutoResume)
                            {
                                coroutine.Resume();
                            }
                        }
                        else
                        {
                            coroutine.Pause();
                        }
                    }
                };
            }
            void MainCoroutineAction()
            {
                var coroutines = CoroutineRunner.Coroutines.Concat(CoroutineRunnerParallel.Coroutines).ToList();

                if (!InGame || !IsForeGroundCache || IsLoading)
                {
                    Clear.SafeInvoke();
                    foreach (var cor in coroutines)
                    {
                        cor.Pause();
                    }
                    AutoResume = true;
                }
                else
                {
                    if (AutoResume)
                    {
                        foreach (var coroutine in coroutines)
                        {
                            if (pluginsSettings.TryGetValue(coroutine.Owner, out var result))
                            {
                                if (result.Enable && coroutine.AutoResume)
                                {
                                    coroutine.Resume();
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            if (coroutine.AutoResume)
                            {
                                coroutine.Resume();
                            }
                        }
                        AutoResume = false;
                    }
                    foreach (var coroutine in coroutines)
                    {
                        if (pluginsSettings.TryGetValue(coroutine.Owner, out var result) && !result.Enable)
                        {
                            coroutine.Pause();
                        }
                    }
                }
            }

            //Main work for coroutines logic when you not in game
            var updateCoroutine = new Coroutine(MainCoroutineAction, 250, nameof(GameController), "$#Main#$")
            {
                Priority = CoroutinePriority.Critical
            };
            //Coroutine for update area
            var updateArea = (new Coroutine(() => { Area.RefreshState(); }, updateAreaLimit, nameof(GameController), "Update area")
            {
                Priority = CoroutinePriority.High
            });
            //Coroutine for update entity list
            var updateEntity = (new Coroutine(() => { EntityListWrapper.RefreshState(); }, updateEntityLimit, nameof(GameController), "Update Entity")
            {
                Priority = CoroutinePriority.High
            });

            var checkTabs = (new Coroutine(() => { StashController.CheckStashTabsLoop(); }, updateStashTabs, nameof(StashTabController), "Stash Tab Controller")
            {
                Priority = CoroutinePriority.Normal
            });

            //
            //Control cache for game status
            var updateGameState = (new Coroutine(() => {
                InGame = InGameReal;
                IsForeGroundCache = Performance.AlwaysForeground || WinApi.IsForegroundWindow(Window.Process.MainWindowHandle);
                Cache.ForceUpdateWindowCache();
                IsLoading = Game.IsGameLoading;
            }, updateIngameState, nameof(GameController), "Update Game State")
            {
                Priority = CoroutinePriority.Critical
            }).Run();

            //Update coroutine setting when change settings in menu
            if (Performance != null)
            {
                loopLimit         = Performance.LoopLimit;
                skipTicksRender   = 1000f / Performance.RenderLimit;
                Cache.Enable      = Performance.Cache;
                updateAreaLimit   = Performance.UpdateAreaLimit;
                updateEntityLimit = Performance.UpdateEntityDataLimit;
                updateIngameState = Performance.UpdateIngemeStateLimit;
                Performance.UpdateEntityDataLimit.OnValueChanged += () =>
                {
                    CoroutineRunner.Coroutines.Concat(CoroutineRunnerParallel.Coroutines).FirstOrDefault(x => x.Name == "Update Entity")
                    ?.UpdateCondtion(new WaitTime(1000 / Performance.UpdateEntityDataLimit.Value));
                };
                Performance.RenderLimit.OnValueChanged     += () => { skipTicksRender = 1000f / Performance.RenderLimit; };
                Performance.LoopLimit.OnValueChanged       += () => { loopLimit = 300 + Performance.LoopLimit; };
                Performance.UpdateAreaLimit.OnValueChanged += () => { CoroutineRunner.Coroutines.Concat(CoroutineRunnerParallel.Coroutines).FirstOrDefault(x => x.Name == "Update Entity")
                                                                      ?.UpdateCondtion(new WaitTime(Performance.UpdateAreaLimit)); };
                Performance.UpdateIngemeStateLimit.OnValueChanged += () => { CoroutineRunner.Coroutines.Concat(CoroutineRunnerParallel.Coroutines).FirstOrDefault(x => x.Name == "Update Entity")
                                                                             ?.UpdateCondtion(new WaitTime(Performance.UpdateIngemeStateLimit)); };
                Performance.Cache.OnValueChanged         += () => { Cache.Enable = Performance.Cache; };
                Performance.DpsUpdateTime.OnValueChanged += () =>
                {
                    CoroutineRunner.Coroutines.Concat(CoroutineRunnerParallel.Coroutines).FirstOrDefault(x => x.Name == "Calculate DPS")?.UpdateCondtion(new WaitTime(Performance.DpsUpdateTime));
                };
            }
            updateArea.AutoRestart(CoroutineRunner).Run();
            //Update entity list in another thread give more smoothness for ui but need more nullable check
            if (Performance?.ParallelEntityUpdate)
            {
                //Sometimes parallel maybe unstable need testing
                updateEntity.AutoRestart(CoroutineRunnerParallel).RunParallel();
            }
            else
            {
                updateEntity.AutoRestart(CoroutineRunner).Run();
            }
            sw.Restart();
            updateCoroutine.Run();
            checkTabs.Run();
            while (true)
            {
                if (!InGame)
                {
                    Thread.Sleep(50);
                }

                var startFrameTime = sw.Elapsed.TotalMilliseconds;

                for (int j = 0; j < CoroutineRunner.RunPerLoopIter; j++)
                {
                    if (CoroutineRunner.IsRunning)
                    {
                        fpsCoroutine++;
                        try
                        {
                            CoroutineRunner.Update();
                        }
                        catch (Exception e) { DebugPlugin.LogMsg($"Coroutine error: {e.Message}", 1); }
                    }
                }

                if (IsForeGroundLast != IsForeGroundCache)
                {
                    IsForeGroundLast = IsForeGroundCache;
                    eIsForegroundChanged(IsForeGroundCache);
                }
                if (sw.Elapsed.TotalMilliseconds >= nextRenderTick && InGame && IsForeGroundCache && !IsLoading)
                {
                    Render.SafeInvoke();
                    nextRenderTick += skipTicksRender;
                    fpsRender++;
                    RenderCount++;
                    DebugInformation["DeltaRender"] = (float)(sw.Elapsed.TotalMilliseconds - startFrameTime);
                }


                if (sw.ElapsedMilliseconds >= tickEverySecond)
                {
                    DebugInformation["FpsLoop"]        = fpsLoop;
                    DebugInformation["FpsRender"]      = fpsRender;
                    DebugInformation["FpsCoroutine"]   = fpsCoroutine;
                    DebugInformation["Looplimit"]      = loopLimit;
                    DebugInformation["ElapsedSeconds"] = sw.Elapsed.Seconds;
                    DebugInformation["FpsRenderCount"] = RenderCount;
                    fpsLoop          = 0;
                    fpsRender        = 0;
                    fpsCoroutine     = 0;
                    tickEverySecond += 1000;
                    if (nextRenderTick - sw.ElapsedMilliseconds > deltaError || nextRenderTick - sw.ElapsedMilliseconds < deltaError)
                    {
                        nextRenderTick = sw.ElapsedMilliseconds;
                    }
                    //Autorestart coroutines in main thread
                    foreach (var autorestartCoroutine in CoroutineRunner.AutorestartCoroutines)
                    {
                        if (!CoroutineRunner.HasName(autorestartCoroutine.Name))
                        {
                            autorestartCoroutine.GetCopy().Run();
                        }
                    }
                    //Autorestart coroutines in another thread
                    foreach (var autorestartCoroutine in CoroutineRunnerParallel.AutorestartCoroutines)
                    {
                        if (!CoroutineRunnerParallel.HasName(autorestartCoroutine.Name))
                        {
                            autorestartCoroutine.GetCopy().RunParallel();
                        }
                    }
                    Game.RefreshTheGameState();
                }
                fpsLoop++;
                DebugInformation["ElapsedMilliseconds"] = sw.ElapsedMilliseconds;
                DebugInformation["DeltaTimeMs"]         = (float)(sw.Elapsed.TotalMilliseconds - startFrameTime);


                if (fpsLoop >= loopLimit)
                {
                    Thread.Sleep(1);
                }
            }
        }