- Ядро (Bogatyri.Core): контракты модулей, EventBus, GameServices, SaveRegistry - Модули: Экономика, Поселение, Армия, Глобальный мир, Боевая система, Сохранения (каждый — отдельный asmdef, видит только ядро) - App/GameModules: регистрация модулей и связь с GameProgress/Казармами - Сохранения v2 по секциям модулей, перенос старого save.json и походов из progress.json - Сброс сохранений: ISaveSystem.ResetAll, ResetState у модулей, меню Tools - EditMode-тесты модулей, документы по каждому модулю с журналом изменений Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
55 lines
2.3 KiB
C#
55 lines
2.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
// Реестр модулей: модуль регистрирует свой контракт, остальные получают его отсюда.
|
|
// Так модули не ссылаются на классы друг друга: Армия знает про IEconomy, но не про ResourceManager.
|
|
//
|
|
// GameServices.Register<IEconomy>(this); // в модуле Экономики
|
|
// GameServices.Get<IEconomy>().TrySpend(ResourceType.Food, 15); // в любом другом модуле
|
|
public static class GameServices
|
|
{
|
|
private static readonly Dictionary<Type, object> services = new Dictionary<Type, object>();
|
|
|
|
public static void Register<T>(T service) where T : class
|
|
{
|
|
services[typeof(T)] = service ?? throw new ArgumentNullException(nameof(service));
|
|
}
|
|
|
|
// Снимает регистрацию, только если зарегистрирован именно этот экземпляр
|
|
// (дубликат синглтона, уничтожаясь, не должен снять настоящий)
|
|
public static void Unregister<T>(T service) where T : class
|
|
{
|
|
if (services.TryGetValue(typeof(T), out object current) && ReferenceEquals(current, service))
|
|
services.Remove(typeof(T));
|
|
}
|
|
|
|
public static T Get<T>() where T : class
|
|
{
|
|
if (services.TryGetValue(typeof(T), out object service)) return (T)service;
|
|
throw new InvalidOperationException(
|
|
$"Модуль {typeof(T).Name} не зарегистрирован. Проверь, что он есть на сцене или в App/GameModules.");
|
|
}
|
|
|
|
public static bool TryGet<T>(out T service) where T : class
|
|
{
|
|
if (services.TryGetValue(typeof(T), out object found))
|
|
{
|
|
service = (T)found;
|
|
return true;
|
|
}
|
|
service = null;
|
|
return false;
|
|
}
|
|
|
|
public static bool Has<T>() where T : class
|
|
{
|
|
return services.ContainsKey(typeof(T));
|
|
}
|
|
|
|
// Полная очистка -- при старте игры (в редакторе статика может пережить прошлый запуск)
|
|
public static void Clear()
|
|
{
|
|
services.Clear();
|
|
}
|
|
}
|