Files
MVP1/Assets/Scripts/Modules/Core/EventBus.cs
T
AlexanderandClaude Opus 5.5 964cb23d9d Модульная система: игровое ядро + 6 модулей, документы Docs/Modules
- Ядро (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>
2026-10-19 18:39:28 +02:00

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();
}
}