using System;
using HarmonyLib;
using UnityEngine;
namespace NecromancerTome
{
///
/// Грифельная доска (necroChalkboard, 09.10.2026): надписи мелом - как на табличках (TEFeatureSignable), но
/// «игрок этого делать не будет, а нам для сюжета пригодится». Поэтому команда «написать» у доски есть
/// только в редакторе префабов, в творческом режиме и в режиме отладки (так мы и подписываем её - текст
/// сохраняется в префабе локации, IFeatureSavedInPrefab). В обычной игре доску только читают: без команды
/// нет и подсказки «E - использовать».
///
public static class Chalkboard
{
/// Сюжетная доска (чертоги, локации): пишет мод или автор префаба.
public const string BlockName = "necroChalkboard";
/// Доска игрока (10.10): крафтится, пишется в обычной игре - записи свои у каждой доски.
public const string PlayerBlockName = "necroChalkboardPlayer";
static string NameOf(TEFeatureSignable _sign)
{
return _sign?.Parent?.TeData?.Block?.GetBlockName();
}
/// Любая из досок - для материала надписи.
public static bool Is(TEFeatureSignable _sign)
{
string n = NameOf(_sign);
return n == BlockName || n == PlayerBlockName;
}
/// Сюжетная доска - писать только в редакторе, творческом режиме, отладке.
public static bool IsLocked(TEFeatureSignable _sign)
{
return NameOf(_sign) == BlockName && !CanWrite();
}
/// Кто может писать: редактор префабов, творческий режим, отладка.
public static bool CanWrite()
{
return GameManager.Instance != null && GameManager.Instance.IsEditMode() ||
GameStats.GetBool(EnumGameStats.IsCreativeMenuEnabled) ||
GamePrefs.GetBool(EnumGamePrefs.DebugMenuEnabled);
}
/// Материал надписи - из бандла, свой шейдер NecroTome/ChalkText с ZTest LEqual (тест 09.10: надпись
/// просвечивала сквозь стены - встроенный GUI/Text Shader берёт ZTest из глобального unity_GUIZTestMode, который
/// интерфейс держит «Always», и переопределение в материале не помогло). Шрифт динамический: его текстура
/// растёт и пересоздаётся при новых буквах - держим её в материале надписи (один материал на все доски).
static Material _mat;
static Font _font;
static bool _hooked;
public static void BindText(TextMesh _tm, MeshRenderer _r)
{
_mat = _r.sharedMaterial;
_font = _tm.font;
if (_mat == null || _font == null)
{
return;
}
_mat.mainTexture = _font.material.mainTexture;
if (!_hooked)
{
_hooked = true;
Font.textureRebuilt += _f =>
{
if (_mat != null && _f == _font)
{
_mat.mainTexture = _f.material.mainTexture;
}
};
}
}
}
[HarmonyPatch(typeof(TEFeatureSignable), nameof(TEFeatureSignable.SetBlockEntityData))]
public static class Patch_TEFeatureSignable_SetBlockEntityData_Chalkboard
{
public static void Postfix(TEFeatureSignable __instance, BlockEntityData _blockEntityData)
{
if (_blockEntityData == null || !_blockEntityData.bHasTransform || !Chalkboard.Is(__instance))
{
return;
}
foreach (TextMesh tm in _blockEntityData.transform.GetComponentsInChildren())
{
MeshRenderer r = tm.GetComponent();
if (r != null && tm.font != null)
{
Chalkboard.BindText(tm, r);
}
}
}
}
[HarmonyPatch(typeof(TEFeatureSignable), nameof(TEFeatureSignable.AllowBlockActivationCommand))]
public static class Patch_TEFeatureSignable_AllowBlockActivationCommand_Chalkboard
{
public static void Postfix(TEFeatureSignable __instance, ITileEntityFeature _module, ReadOnlySpan _commandName, ref bool __result)
{
if (__result && __instance.Equals(_module) && _commandName.SequenceEqual("edit".AsSpan()) &&
Chalkboard.IsLocked(__instance))
{
__result = false;
}
}
}
[HarmonyPatch(typeof(TEFeatureSignable), nameof(TEFeatureSignable.GetActivationText))]
public static class Patch_TEFeatureSignable_GetActivationText_Chalkboard
{
public static void Postfix(TEFeatureSignable __instance, ref string __result)
{
if (Chalkboard.IsLocked(__instance))
{
__result = null;
}
}
}
}