using RimWorld; using rjw.Modules.Shared.Logs; using System; using System.Collections.Generic; using System.Text; using Verse; namespace rjwquirks.Modules.Shared.Events { public static class RjwEventManager { private static readonly Dictionary> _handlers = BuildHandlerDictionary(); private static readonly ILog _logger = LogManager.GetLogger("RjwEventManager"); /// /// Routes RJW events to the relevant event handlers based on the def subscriptions /// public static void NotifyEvent(RjwEvent ev) { //implement own settings later if (Prefs.DevMode) { _logger.Message($"RJW Event {ev.def}{SignalArgsToString(ev.args)}"); } if (!_handlers.TryGetValue(ev.def, out List eventHandlers)) { return; } if (Prefs.DevMode) { // Since event args are filled in C#, no reason to waste time checking them outside of the actual mod developement CheckObligatoryArgs(ev); } foreach (RjwEventHandler handler in eventHandlers) { try { handler.HandleEvent(ev); } catch (Exception e) { // suppress exceptions so one bad mod wouldn't break everything _logger.Error($"Handler exception when handling {ev.def}", e); } } } private static Dictionary> BuildHandlerDictionary() { Dictionary> handlers = new Dictionary>(); foreach (RjwEventHandlerDef handlerDef in DefDatabase.AllDefsListForReading) { foreach (RjwEventDef eventDef in handlerDef.handlesEvents) { if (handlers.ContainsKey(eventDef)) { handlers[eventDef].Add(handlerDef.Worker); } else { handlers[eventDef] = new List { handlerDef.Worker }; } } } return handlers; } private static void CheckObligatoryArgs(RjwEvent ev) { foreach (string argName in ev.def.obligatoryArgs) { if (!ev.args.TryGetArg(argName, out _)) { _logger.Error($"Got a {ev.def} event without the obligatory argument '{argName}'"); } } } private static string SignalArgsToString(SignalArgs args) { StringBuilder message = new StringBuilder(); foreach (var arg in args.Args) { message.Append(", "); message.Append(arg); } return message.ToString(); } } }