Files
necromants-tome-7d2d-3-2/HarmonySrc/GameVersionGuard.cs
T
AlexCubeandClaude Opus 5.5 e8e21d5a58 Сборка под игру 3.3: хранилище, Пирамида, проверка версии
- Пирамида: StreamModeWrite/Read теперь глобальные перечисления (в 3.2 были внутри TileEntity).
- Хранилище: Bag поверх ItemStackGrid (конструктор с местом хранения, Resize, ItemGrid),
  запись и чтение через PooledBinaryWriter/Reader. Формат хранилища 2; формат 1 из сейвов 3.2
  читается. Незнакомый номер формата больше не считается «хранилища нет» - байты сохраняются.
- Сфера на браслете: ModificationCount/GetModification/SetModification.
- Непустой сундук: TEFeatureStorage.IsEmpty (ITileEntityLootable в 3.3 нет).
- Поиск ножа в инвентаре через ItemGrid.
- GameVersionGuard пускает только 3.3.

Проверено в игре на V 3.3.0 b14: хранилище из сейва 3.2 (24 стопки) прочиталось, сохранилось
и перечиталось; Пирамида включается; «Жертва», обыск трупа и мешки работают.

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

152 lines
6.6 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 System;
using System.IO;
using HarmonyLib;
using UnityEngine;
namespace NecromancerTome
{
/// <summary>
/// ПРОВЕРКА ВЕРСИИ ИГРЫ, 1.4.2 (2026-09-24). Повод: 1.4.1 на игре 3.3.0 experimental молча
/// потеряла содержимое Пространственного хранилища - разбор в BACKLOG.md, «Игра 3.3.0
/// experimental». Решение пользователя: при несовместимой версии мод показывает в главном меню
/// окно «мод несовместим, обновите» с ЕДИНСТВЕННОЙ кнопкой «Выйти из игры» - без «играть всё
/// равно».
///
/// ПОЧЕМУ ЧИТАЕТСЯ cVersionInformation, А НЕ cVersionMinor. cVersionMinor - const, компилятор
/// вписывает её значение (20) прямо в нашу DLL, и на 3.3 она всё равно «видела» бы 20.
/// cVersionInformation - static readonly, её значение берётся из игры при запуске.
///
/// ПОЧЕМУ Minor / 10. Игра хранит версию двузначным числом: 3.2.0 = 20, 3.2.1 = 21, 3.3.0 = 30
/// (VersionInformation печатает его как {Minor/10}.{Minor%10}). Проверка по десяткам пропускает
/// любые хотфиксы 3.3.x и не пропускает ни 3.2, ни 3.4 и всё, что будет после.
///
/// ВСЁ, ЧЕМ ПОЛЬЗУЕТСЯ ЭТОТ ФАЙЛ, СВЕРЕНО С ДЕКОМПИЛЯЦИЕЙ 3.3.0 (build 25485021): Constants,
/// VersionInformation, XUiC_MainMenu.OnOpen, XUiC_MessageBoxWindowGroup (класс совпадает целиком),
/// Mod.VersionString. Иначе сборка под 3.2 упала бы на 3.3 раньше, чем показала окно.
///
/// ОТЛАДКА НА 3.2: если в папке мода лежит файл FORCE_VERSION_GUARD, мод ведёт себя так, будто
/// версия несовместима. В релизный архив он не попадает - состав архива задан явным списком.
/// </summary>
public static class GameVersionGuard
{
/// <summary>Под какую версию собран мод: Major и десяток Minor (3.3.x = 3 и 3; сборка 1.4.x была под 3.2).</summary>
public const int SupportedMajor = 3;
public const int SupportedMinorTens = 3;
public const string SupportedText = "3.3";
private static bool? supported;
public static bool IsSupported
{
get
{
if (supported == null)
{
supported = Check();
}
return supported.Value;
}
}
public static string GameVersionText
{
get
{
VersionInformation v = Constants.cVersionInformation;
return v != null ? v.LongStringNoBuild : "?";
}
}
private static bool Check()
{
if (ForcedByFile())
{
Debug.LogWarning("[NecromancerTome] GameVersionGuard: FORCE_VERSION_GUARD file present - acting as if the game version were unsupported");
return false;
}
VersionInformation v = Constants.cVersionInformation;
bool ok = v != null && v.Major == SupportedMajor && v.Minor / 10 == SupportedMinorTens;
Debug.Log("[NecromancerTome] GameVersionGuard: game " + GameVersionText + " (Major " + (v != null ? v.Major : -1) +
", Minor " + (v != null ? v.Minor : -1) + "), mod built for " + SupportedText + " -> " +
(ok ? "supported" : "NOT SUPPORTED"));
return ok;
}
private static bool ForcedByFile()
{
return DebugFileExists("FORCE_VERSION_GUARD");
}
/// <summary>Отладка сохранения хранилища байт в байт на 3.2: при файле FORCE_VAULT_UNREAD
/// в папке мода хранилище из сейва не разбирается, а проходит всю цепочку сохранения
/// нетронутым - ровно как на несовместимой версии, но без окна с выходом, так что в мир
/// можно зайти и сохраниться.</summary>
public static bool ForceVaultUnread
{
get { return DebugFileExists("FORCE_VAULT_UNREAD"); }
}
private static bool DebugFileExists(string _name)
{
try
{
string folder = ModEntry.Instance != null ? ModEntry.Instance.Path : null;
return folder != null && File.Exists(Path.Combine(folder, _name));
}
catch (Exception)
{
return false;
}
}
public static void ShowIncompatibleWindow(XUi _xui)
{
string modVersion = ModEntry.Instance != null ? ModEntry.Instance.VersionString : "?";
string text = string.Format(Localization.Get("necroVersionGuardText"), modVersion, SupportedText, GameVersionText);
XUiC_MessageBoxWindowGroup.ShowCustom(_xui,
Localization.Get("necroVersionGuardTitle"),
text,
"",
delegate(XUiC_MessageBoxWindowGroup _box)
{
_box.buttons[0].DefaultConfirm("necroVersionGuardQuit", delegate
{
Debug.Log("[NecromancerTome] GameVersionGuard: player pressed Quit");
Application.Quit();
});
},
_openMainMenuOnClose: false,
_modal: true,
_buttonOnOutsideClick: -1,
// Проверено в игре 2026-09-25: Esc модальное окно не закрывает - оно остаётся на
// экране, и уйти можно только кнопкой. Это и нужно. _buttonOnExternalClose: 0 - на
// случай, если игра всё же закроет окно извне: тогда это тоже выход.
_buttonOnExternalClose: 0);
Debug.LogWarning("[NecromancerTome] GameVersionGuard: incompatible game version, quit window shown");
}
}
/// <summary>Главное меню: здесь показывается окно, и здесь же сбрасываются непрочитанные байты
/// хранилища - возврат в меню значит, что прежний мир закрыт, и его данные не должны перейти к
/// персонажу следующего.</summary>
[HarmonyPatch(typeof(XUiC_MainMenu), "OnOpen")]
public static class Patch_XUiC_MainMenu_OnOpen_VersionGuard
{
public static void Postfix(XUiC_MainMenu __instance)
{
try
{
SpatialVaultPersistence.UnreadableByEntity.Clear();
if (!GameVersionGuard.IsSupported)
{
GameVersionGuard.ShowIncompatibleWindow(__instance.xui);
}
}
catch (Exception e)
{
Debug.LogError("[NecromancerTome] GameVersionGuard: main menu postfix failed: " + e);
}
}
}
}