Files
necromants-tome-7d2d-3-2/HarmonySrc/CVarBindingLeakPatch.cs
T
AlexCubeandClaude Opus 5.5 888cf1ee7e FPS: утечка привязки cvar() в шкале некромантии; пирамида при качестве текстур ниже Full
FPS сползал 60 -> 15-30 за 10-15 минут в любом мире; перезаход сбрасывал, в режиме
змеи (пояс скрыт) тормозов не было. Замер показал: группа окон toolbelt 2 -> 23 мс/кадр
при неизменном числе элементов. Причина - ошибка игры: BindingNcalcFunctions.cvar при
каждом вычислении регистрирует новый VariableStateCVar, RegisterVariable добавляет без
проверки, новая переменная стартует с 0 и в следующем кадре снова вызывает пересчёт.
Шкала fill="{% cvar('necroNecromancyProgressCVar') / 20 }" (с 1.3.0) набирала по одной
переменной за кадр. CVarBindingLeakPatch: одна CVar регистрируется в привязке один раз.
Проверено: 15 мин, 25 убийств - FPS 55-58 ровно, toolbelt ~1 мс/кадр.

Пирамида: на Texture Quality ниже Full атлас блоков игры меньше нашей текстуры 512, и
CustomBlockPaint её пропускал. Теперь берётся мип под размер атласа; бандл necroatlas
пересобран с ignoreMipmapLimit (иначе CopyTexture отказывает и пирамида чёрная).
Проверено на Half.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 00:11:59 +03:00

43 lines
2.3 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using HarmonyLib;
namespace NecromancerTome
{
/// <summary>
/// Утечка в самой игре, на которую наступала шкала некромантии в поясе (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() берёт
/// прямо у игрока, так что отслеживающая переменная нужна только одна - для «изменилось».
/// </summary>
[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;
}
}
}