diff --git a/HarmonySrc/CVarBindingLeakPatch.cs b/HarmonySrc/CVarBindingLeakPatch.cs new file mode 100644 index 0000000..133b754 --- /dev/null +++ b/HarmonySrc/CVarBindingLeakPatch.cs @@ -0,0 +1,42 @@ +using HarmonyLib; + +namespace NecromancerTome +{ + /// + /// Утечка в самой игре, на которую наступала шкала некромантии в поясе (1.3.0+, + /// fill="{% cvar('necroNecromancyProgressCVar') / 20 }" в Config/XUi_InGame/windows.xml). + /// + /// Найдено 28.09 замером (NecroProfiler): FPS 60 -> 30 за 10-15 минут в любом мире, в теле; + /// группа окон toolbelt росла 2 -> 23 мс/кадр при неизменных 573 элементах; в режиме змеи пояс + /// скрыт - и тормозов нет; перезаход в мир сбрасывает. + /// + /// Механика (декомпиляция 3.3): BindingNcalcFunctions.cvar при каждом вычислении выражения + /// регистрирует НОВЫЙ VariableStateCVar, а BindingInfoNcalc.RegisterVariable добавляет его в + /// список без проверки. Новая переменная начинает с 0; если шкала не пуста, её RefreshValue в + /// следующем кадре видит «изменилось» -> выражение пересчитывается -> cvar() добавляет ещё одну. + /// Плюс одна переменная за кадр, пока CVar не 0, и каждый кадр обходится весь список. + /// + /// Лечение: одну и ту же CVar в одной привязке регистрируем один раз. Значение cvar() берёт + /// прямо у игрока, так что отслеживающая переменная нужна только одна - для «изменилось». + /// + [HarmonyPatch(typeof(BindingInfoNcalc), nameof(BindingInfoNcalc.RegisterVariable))] + public static class Patch_BindingInfoNcalc_RegisterVariable_CVarLeak + { + public static bool Prefix(BindingInfoNcalc __instance, BindingInfoNcalc.VariableStateAbs _var, ref bool __result) + { + if (!(_var is BindingInfoNcalc.VariableStateCVar added)) + { + return true; + } + foreach (BindingInfoNcalc.VariableStateAbs existing in __instance.variables) + { + if (existing is BindingInfoNcalc.VariableStateCVar known && known.cVarName == added.cVarName) + { + __result = true; + return false; + } + } + return true; + } + } +} diff --git a/HarmonySrc/CustomBlockPaintPatch.cs b/HarmonySrc/CustomBlockPaintPatch.cs index bd5d84b..5ec8cf6 100644 --- a/HarmonySrc/CustomBlockPaintPatch.cs +++ b/HarmonySrc/CustomBlockPaintPatch.cs @@ -269,7 +269,15 @@ namespace NecromancerTome return -1; } - if (ours.width != src.width || ours.height != src.height) + // Качество текстур ниже Full уменьшает атлас игры вдвое/вчетверо (Half: 256 вместо 512). + // Раньше тут был пропуск - и пирамида оставалась без текстуры (28.09, игра на Half). + // Наши уменьшенные копии уже лежат в мипах: при Half берём с мипа 1, при Quarter - с 2. + int mipOffset = 0; + while (mipOffset < ours.mipmapCount && (ours.width >> mipOffset) > src.width) + { + mipOffset++; + } + if ((ours.width >> mipOffset) != src.width || (ours.height >> mipOffset) != src.height) { Debug.LogWarning("[NecromancerTome] CustomBlockPaint: " + label + " size mismatch, " + "atlas is " + src.width + "x" + src.height + " but ours is " + @@ -283,11 +291,11 @@ namespace NecromancerTome " - skipped"); return -1; } - if (ours.mipmapCount != src.mipmapCount) + if (ours.mipmapCount - mipOffset < src.mipmapCount) { Debug.LogWarning("[NecromancerTome] CustomBlockPaint: " + label + " mip mismatch, " + "atlas has " + src.mipmapCount + " but ours has " + ours.mipmapCount + - " - skipped"); + " (from mip " + mipOffset + ") - skipped"); return -1; } @@ -303,11 +311,14 @@ namespace NecromancerTome // GPU-side copy: the game's arrays are non-readable, so nothing can be pulled back // to the CPU. CopyTexture moves whole slices with their mip chains. for (int i = 0; i < slice; i++) Graphics.CopyTexture(src, i, grown, i); - Graphics.CopyTexture(ours, 0, grown, slice); + for (int mip = 0; mip < src.mipmapCount; mip++) + { + Graphics.CopyTexture(ours, 0, mip + mipOffset, grown, slice, mip); + } target = grown; Debug.Log("[NecromancerTome] CustomBlockPaint: " + label + " grown from " + slice + - " to " + (slice + 1) + " slices"); + " to " + (slice + 1) + " slices" + (mipOffset > 0 ? ", ours taken from mip " + mipOffset : "")); return slice; } diff --git a/NecromancerHarmony.dll b/NecromancerHarmony.dll index bf722c2..5670138 100644 Binary files a/NecromancerHarmony.dll and b/NecromancerHarmony.dll differ diff --git a/NecromancerHarmony.pdb b/NecromancerHarmony.pdb index e6c9c68..059e7a3 100644 Binary files a/NecromancerHarmony.pdb and b/NecromancerHarmony.pdb differ diff --git a/Resources/necroatlas b/Resources/necroatlas index 57cfcfc..bbe308e 100644 Binary files a/Resources/necroatlas and b/Resources/necroatlas differ