- Ядро (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.1 KiB
C#
55 lines
2.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
// Шина событий: модуль сообщает "что случилось", не зная, кто это слушает.
|
|
//
|
|
// EventBus.Publish(new MarchReturnedEvent { ... }); // модуль Мира
|
|
// EventBus.Subscribe<MarchReturnedEvent>(OnMarchReturned); // задания, статистика, UI
|
|
//
|
|
// Подписчик обязан отписаться (OnDestroy / OnDisable), иначе получит событие уже уничтоженным.
|
|
public static class EventBus
|
|
{
|
|
private static readonly Dictionary<Type, Delegate> handlers = new Dictionary<Type, Delegate>();
|
|
|
|
// Ошибка в одном подписчике не должна ломать остальных. Ядро не знает про Unity,
|
|
// поэтому куда писать ошибку, задаёт Core.Unity (там это Debug.LogException).
|
|
public static Action<Exception> OnHandlerError;
|
|
|
|
public static void Subscribe<T>(Action<T> handler)
|
|
{
|
|
handlers.TryGetValue(typeof(T), out Delegate existing);
|
|
handlers[typeof(T)] = Delegate.Combine(existing, handler);
|
|
}
|
|
|
|
public static void Unsubscribe<T>(Action<T> handler)
|
|
{
|
|
if (!handlers.TryGetValue(typeof(T), out Delegate existing)) return;
|
|
Delegate remaining = Delegate.Remove(existing, handler);
|
|
if (remaining == null) handlers.Remove(typeof(T));
|
|
else handlers[typeof(T)] = remaining;
|
|
}
|
|
|
|
public static void Publish<T>(T gameEvent)
|
|
{
|
|
if (!handlers.TryGetValue(typeof(T), out Delegate existing)) return;
|
|
|
|
// Копия списка: подписчик может отписаться прямо во время рассылки
|
|
foreach (Delegate d in existing.GetInvocationList())
|
|
{
|
|
try
|
|
{
|
|
((Action<T>)d)(gameEvent);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
OnHandlerError?.Invoke(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void Clear()
|
|
{
|
|
handlers.Clear();
|
|
}
|
|
}
|