diff --git a/HarmonySrc/FreezeProbe.cs b/HarmonySrc/FreezeProbe.cs new file mode 100644 index 0000000..adf60d5 --- /dev/null +++ b/HarmonySrc/FreezeProbe.cs @@ -0,0 +1,46 @@ +using UnityEngine; + +namespace NecromancerTome +{ + /// + /// Замер фризов (жалоба 10.10: «в чертогах лагает... это были фризы»). Средний FPS из строк игры «Time: ... FPS» + /// их не показывает - он за минуту. Здесь каждый кадр дольше Threshold пишется в лог: длительность, сколько + /// сборок мусора прошло за этот кадр (GC поколения 0 - если растёт, фриз от сборки мусора: мод или игра много + /// выделяют), режим мода (чертоги/змея/одержимость) и сколько областей мира загружено. + /// Строки: «[NecromancerTome] FreezeProbe: ...». Ничего не хранит, кроме пары чисел. + /// + public static class FreezeProbe + { + public const float Threshold = 0.1f; + static int _gc = -1; + static float _skipUntil; + + public static void Init() + { + ModEvents.UnityUpdate.RegisterHandler(OnUnityUpdate); + } + + static void OnUnityUpdate(ref ModEvents.SUnityUpdateData _data) + { + int gc = System.GC.CollectionCount(0); + World world = GameManager.Instance?.World; + if (world == null || world.GetPrimaryPlayer() == null) + { + _gc = gc; + _skipUntil = Time.unscaledTime + 20f; // загрузка мира - фризы ожидаемы + return; + } + float dt = Time.unscaledDeltaTime; + int dgc = _gc < 0 ? 0 : gc - _gc; + _gc = gc; + if (dt < Threshold || Time.unscaledTime < _skipUntil || GameManager.Instance.IsPaused()) + { + return; + } + string mode = MindPalace.Active ? "чертоги" : SnakeMode.Active ? "змея" : Possession.Active ? "одержимость" : "тело"; + int obs = GameManager.Instance.World?.m_ChunkManager?.m_ObservedEntities?.Count ?? -1; + Debug.Log("[NecromancerTome] FreezeProbe: кадр " + Mathf.RoundToInt(dt * 1000f) + " мс, сборок мусора +" + dgc + + ", режим " + mode + ", наблюдателей областей " + obs + ", куча " + (System.GC.GetTotalMemory(false) >> 20) + " МБ"); + } + } +} diff --git a/HarmonySrc/MindPalace.cs b/HarmonySrc/MindPalace.cs index de13834..67adca8 100644 --- a/HarmonySrc/MindPalace.cs +++ b/HarmonySrc/MindPalace.cs @@ -829,6 +829,7 @@ namespace NecromancerTome // Дальность как у змеи: при радиусе 2 игра не строила коллизии участка (тест 03.10: // «чертоги не построились вовремя» - ждали коллизий 30 с). _observer = GameManager.Instance.AddChunkObserver(center, true, GameUtils.GetViewDistance(), -1); + ShrinkBody(_player); _stage = Stage.Loading; _deadline = Time.time + 30f; Active = true; @@ -868,6 +869,27 @@ namespace NecromancerTome GameManager.Instance.RemoveChunkObserver(_observer); } _observer = null; + EntityPlayerLocal p = GameManager.Instance?.World?.GetPrimaryPlayer(); + if (_bodyViewDim > 0 && p?.ChunkObserver != null) + { + p.ChunkObserver.viewDim = _bodyViewDim; + } + _bodyViewDim = -1; + } + + /// Область мира у тела до входа (-1 - не сжата). Фризы в чертогах (жалоба 10.10): игра держала две + /// полные области - у чертогов на краю карты и у лежащего тела; подгрузка и пересборка участков - мусор + /// и паузы его сборки. Тело сжимаем до Possession.BodyViewDim, как у змеи и одержимого. + static int _bodyViewDim = -1; + + static void ShrinkBody(EntityPlayerLocal _player) + { + ChunkManager.ChunkObserver body = _player?.ChunkObserver; + if (body != null && _bodyViewDim < 0 && body.viewDim > Possession.BodyViewDim) + { + _bodyViewDim = body.viewDim; + body.viewDim = Possession.BodyViewDim; + } } static void OnUnityUpdate(ref ModEvents.SUnityUpdateData _data) @@ -880,6 +902,7 @@ namespace NecromancerTome _observer = null; MindControl.End(null); _slotsFor = null; + _bodyViewDim = -1; return; } EntityPlayerLocal player = world.GetPrimaryPlayer(); diff --git a/HarmonySrc/ModEntry.cs b/HarmonySrc/ModEntry.cs index 5da1a66..71c898d 100644 --- a/HarmonySrc/ModEntry.cs +++ b/HarmonySrc/ModEntry.cs @@ -66,6 +66,7 @@ namespace NecromancerTome NecroMailbox.Init(); Possession.Init(); BloodTide.Init(); + FreezeProbe.Init(); // PyramidWardPatch.cs's TEFeaturePyramidWard needs no Init() call - it's discovered // automatically by the engine's own TileEntityCompositeData reflection scan (see that // file's class doc comment), not registered here like PetFollowPatch's UnityUpdate hook. diff --git a/NecromancerHarmony.dll b/NecromancerHarmony.dll index 4d19333..1df9fd4 100644 Binary files a/NecromancerHarmony.dll and b/NecromancerHarmony.dll differ diff --git a/NecromancerHarmony.pdb b/NecromancerHarmony.pdb index a438cb1..8f8d700 100644 Binary files a/NecromancerHarmony.pdb and b/NecromancerHarmony.pdb differ