using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using OutwardChatConfigs.Events;
using OutwardChatConfigs.Handlers;
using OutwardChatConfigs.Interfaces;
using OutwardChatConfigs.Managers;
using OutwardChatConfigs.Models;
using OutwardChatConfigs.Triggers;
using OutwardChatConfigs.Utility.Enums;
using OutwardChatConfigs.Utility.Helpers;
using OutwardModsCommunicator.EventBus;
using OutwardModsCommunicator.Managers;
using SideLoader;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("OutwardChatConfigs")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OutwardChatConfigs")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c5450fe0-edcf-483f-b9ea-4b1ef9d36da7")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace OutwardChatConfigs
{
[BepInPlugin("gymmed.chat_configs", "Chat Configs", "0.0.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class OCC : BaseUnityPlugin
{
public const string GUID = "gymmed.chat_configs";
public const string NAME = "Chat Configs";
public const string VERSION = "0.0.1";
public const string EVENTS_LISTENER_GUID = "gymmed.chat_configs_*";
public static string prefix = "[Chat-Configs]";
internal static ManualLogSource Log;
private Harmony _harmony;
internal void Awake()
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
LogMessage("Hello world from Chat Configs 0.0.1!");
_harmony = new Harmony("gymmed.chat_configs");
_harmony.PatchAll();
EventBusRegister.RegisterEvents();
EventBusSubscriber.AddSubscribers();
RegisterInternalEvents();
EventBusPublisher.SendCommands();
LogMessage("OutwardChatConfigs loaded!");
}
public static void LogMessage(string message)
{
Log.LogMessage((object)(prefix + " " + message));
}
public static void LogStatusMessage(string message, ChatLogStatus status = ChatLogStatus.Info)
{
LogMessage($"[{status}] {message}");
}
public static void LogSL(string message)
{
SL.Log(prefix + " " + message);
}
public static string GetProjectLocation()
{
return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
}
private void RegisterInternalEvents()
{
ScheduledEventsManager.Instance.RegisterInternalEvent("SL", "BeforePacksLoaded", delegate
{
}, "Before Packs Loaded");
ScheduledEventsManager.Instance.RegisterInternalEvent("SL", "OnPacksLoaded", delegate
{
}, "Packs Loaded");
ScheduledEventsManager.Instance.RegisterInternalEvent("SL", "OnSceneLoaded", delegate
{
}, "Scene Loaded");
ScheduledEventsManager.Instance.RegisterInternalEvent("SL", "OnGameplayResumedAfterLoading", delegate
{
}, "Gameplay Resumed");
ScheduledEventsManager.Instance.RegisterInternalEvent("SL", "OnBeforeHotReload", delegate
{
}, "Before Hot Reload");
ScheduledEventsManager.Instance.RegisterInternalEvent("gymmed", "OnFirstGameReady", delegate
{
}, "First Game Ready");
}
}
}
namespace OutwardChatConfigs.Utility.Helpers
{
public static class CharacterHelpers
{
public static Character TryToFindOtherCharacterInLobby(Character mainCharacter, string otherCharName)
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
Character val = null;
foreach (PlayerSystem item in Global.Lobby.PlayersInLobby)
{
val = item.ControlledCharacter;
if ((Object)(object)val != (Object)null && val.UID != mainCharacter.UID && string.Equals(otherCharName, val.Name))
{
return val;
}
}
return null;
}
public static Character TryToFindOtherCharacterInLobby(Character mainCharacter)
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
Character val = null;
foreach (PlayerSystem item in Global.Lobby.PlayersInLobby)
{
val = item.ControlledCharacter;
if ((Object)(object)val != (Object)null && val.UID != mainCharacter.UID)
{
return val;
}
}
return val;
}
public static bool IsCharacterInDistance(Character firstCharacter, Character secondCharacter, float minimumDistance)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = ((Component)firstCharacter).transform.position - ((Component)secondCharacter).transform.position;
float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
float num = minimumDistance * minimumDistance;
if (sqrMagnitude > num)
{
return false;
}
return true;
}
public static bool HasManualMovement(Character character)
{
CharacterControl characterControl = character.CharacterControl;
LocalCharacterControl val = (LocalCharacterControl)(object)((characterControl is LocalCharacterControl) ? characterControl : null);
if (val == null)
{
return false;
}
if (((Vector2)(ref ((CharacterControl)val).m_moveInput)).sqrMagnitude > 0.01f)
{
return true;
}
return false;
}
}
public static class ChatHelpers
{
public static void SendChatLog(ChatPanel panel, string message, ChatLogStatus status = ChatLogStatus.Info)
{
panel.ChatMessageReceived("System", ChatLogStatusHelper.GetChatLogText(message, status));
}
public static void SendChatLog(Character character, string message, ChatLogStatus status = ChatLogStatus.Info)
{
CharacterUI characterUI = character.CharacterUI;
if ((Object)(object)((characterUI != null) ? characterUI.ChatPanel : null) == (Object)null)
{
OCC.LogMessage("ChatHelpers@SendChatLog provided character with missing chatPanel!");
}
else
{
SendChatLog(character.CharacterUI.ChatPanel, message, status);
}
}
public static void SendChatOrLog(Character character, string message, ChatLogStatus status = ChatLogStatus.Info)
{
CharacterUI characterUI = character.CharacterUI;
if ((Object)(object)((characterUI != null) ? characterUI.ChatPanel : null) == (Object)null)
{
OCC.LogStatusMessage(message, status);
}
else
{
SendChatLog(character.CharacterUI.ChatPanel, message, status);
}
}
}
}
namespace OutwardChatConfigs.Utility.Enums
{
public enum ChatCommandsManagerParams
{
CommandName,
CommandParameters,
CommandAction,
IsCheatCommand,
CommandDescription,
CommandRequiresDebugMode
}
public static class ChatCommandsManagerParamsHelper
{
private static readonly Dictionary<ChatCommandsManagerParams, (string key, Type type)> _registry = new Dictionary<ChatCommandsManagerParams, (string, Type)>
{
[ChatCommandsManagerParams.CommandName] = ("command", typeof(string)),
[ChatCommandsManagerParams.CommandParameters] = ("parameters", typeof(Dictionary<string, (string, string)>)),
[ChatCommandsManagerParams.CommandAction] = ("function", typeof(Action<Character, Dictionary<string, string>>)),
[ChatCommandsManagerParams.IsCheatCommand] = ("isCheatCommand", typeof(bool)),
[ChatCommandsManagerParams.CommandDescription] = ("description", typeof(string)),
[ChatCommandsManagerParams.CommandRequiresDebugMode] = ("debugMode", typeof(bool))
};
public static (string key, Type type) Get(ChatCommandsManagerParams param)
{
return _registry[param];
}
}
public enum ChatLogStatus
{
Info,
Success,
Warning,
Error
}
public static class ChatLogStatusHelper
{
public static string GetChatLogText(string message, ChatLogStatus status = ChatLogStatus.Info)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
return status switch
{
ChatLogStatus.Success => Global.SetTextColor(message, Global.LIGHT_GREEN),
ChatLogStatus.Warning => Global.SetTextColor(message, Global.LIGHT_ORANGE),
ChatLogStatus.Error => "<color=#" + UnityEngineExtensions.ToHex(Global.LIGHT_RED) + ">" + message + "</color>",
_ => message,
};
}
}
}
namespace OutwardChatConfigs.Triggers
{
public class ExternalEventTrigger : IScheduledTrigger
{
private readonly string _eventKey;
private Action _callback;
public string EventKey => _eventKey;
public ExternalEventTrigger(string eventKey)
{
_eventKey = eventKey;
}
public void Subscribe(Action callback)
{
_callback = (Action)Delegate.Combine(_callback, callback);
}
public void Unsubscribe(Action callback)
{
_callback = (Action)Delegate.Remove(_callback, callback);
}
public void Initialize()
{
}
public void Trigger()
{
_callback?.Invoke();
}
}
public class SLEventTrigger : IScheduledTrigger
{
private readonly string _eventKey;
private readonly SLEventType _eventType;
private Action _callback;
public string EventKey => _eventKey;
public SLEventTrigger(string eventKey, SLEventType eventType)
{
_eventKey = eventKey;
_eventType = eventType;
}
public void Subscribe(Action callback)
{
_callback = (Action)Delegate.Combine(_callback, callback);
}
public void Unsubscribe(Action callback)
{
_callback = (Action)Delegate.Remove(_callback, callback);
}
public void Initialize()
{
switch (_eventType)
{
case SLEventType.BeforePacksLoaded:
SL.BeforePacksLoaded += OnSLEvent;
break;
case SLEventType.OnPacksLoaded:
SL.OnPacksLoaded += OnSLEvent;
break;
case SLEventType.OnSceneLoaded:
SL.OnSceneLoaded += OnSLEvent;
break;
case SLEventType.OnGameplayResumedAfterLoading:
SL.OnGameplayResumedAfterLoading += OnSLEvent;
break;
case SLEventType.OnBeforeHotReload:
SL.OnBeforeHotReload += OnSLEvent;
break;
}
}
private void OnSLEvent()
{
_callback?.Invoke();
}
}
public enum SLEventType
{
BeforePacksLoaded,
OnPacksLoaded,
OnSceneLoaded,
OnGameplayResumedAfterLoading,
OnBeforeHotReload
}
public static class TriggerFactory
{
private static readonly Dictionary<string, SLEventType> InternalEventMappings = new Dictionary<string, SLEventType>
{
{
"BeforePacksLoaded",
SLEventType.BeforePacksLoaded
},
{
"OnPacksLoaded",
SLEventType.OnPacksLoaded
},
{
"OnSceneLoaded",
SLEventType.OnSceneLoaded
},
{
"OnGameplayResumedAfterLoading",
SLEventType.OnGameplayResumedAfterLoading
},
{
"OnBeforeHotReload",
SLEventType.OnBeforeHotReload
}
};
public static IScheduledTrigger CreateInternalTrigger(string eventName)
{
if (InternalEventMappings.TryGetValue(eventName, out var value))
{
return new SLEventTrigger("SL." + eventName, value);
}
throw new ArgumentException("Unknown internal event: " + eventName);
}
public static IScheduledTrigger CreateExternalTrigger(string eventKey)
{
return new ExternalEventTrigger(eventKey);
}
public static bool IsInternalEvent(string eventKey)
{
return eventKey.StartsWith("SL.");
}
public static bool TryGetInternalEventName(string eventKey, out string eventName)
{
if (eventKey.StartsWith("SL."))
{
eventName = eventKey.Substring(3);
return InternalEventMappings.ContainsKey(eventName);
}
eventName = null;
return false;
}
}
}
namespace OutwardChatConfigs.Patches
{
[HarmonyPatch(typeof(ResourcesPrefabManager), "Load")]
public static class Patch_ResourcesPrefabManager_Load
{
public static void Postfix()
{
OCC.LogMessage("ResourcesPrefabManager.Load completed - pre-loading scheduled events data");
ScheduledEventsSerializer.Instance.PreLoadAllData();
}
}
}
namespace OutwardChatConfigs.Models
{
public class RegisteredEvent
{
public string Namespace { get; set; }
public string EventName { get; set; }
public string EventKey { get; set; }
public Action Callback { get; set; }
public string DisplayName { get; set; }
public bool IsInternal { get; set; }
public RegisteredEvent(string @namespace, string eventName, Action callback, string displayName = null, bool isInternal = false)
{
Namespace = @namespace;
EventName = eventName;
EventKey = @namespace + "." + eventName;
Callback = callback;
DisplayName = displayName ?? eventName;
IsInternal = isInternal;
}
}
[XmlRoot("Binding")]
public class ScheduledEventBinding
{
[XmlAttribute("key")]
public string EventKey { get; set; }
[XmlArray("Messages")]
[XmlArrayItem("Message")]
public List<ScheduledMessage> Messages { get; set; }
public ScheduledEventBinding()
{
Messages = new List<ScheduledMessage>();
}
public ScheduledEventBinding(string eventKey)
: this()
{
EventKey = eventKey;
}
}
[XmlRoot("ScheduledMessages")]
public class ScheduledEventsDataFile
{
[XmlArray("Bindings")]
[XmlArrayItem("Binding")]
public List<ScheduledEventBinding> Bindings { get; set; }
public ScheduledEventsDataFile()
{
Bindings = new List<ScheduledEventBinding>();
}
}
[XmlRoot("ScheduledMessage")]
public class ScheduledMessage
{
[XmlElement("Index")]
public int Index { get; set; }
[XmlElement("Text")]
public string Text { get; set; }
[XmlElement("CreatedAt")]
public DateTime CreatedAt { get; set; }
public ScheduledMessage()
{
}
public ScheduledMessage(int index, string text)
{
Index = index;
Text = text;
CreatedAt = DateTime.Now;
}
}
}
namespace OutwardChatConfigs.Managers
{
public static class ExecutionTracker
{
private static readonly HashSet<string> _executedMessages = new HashSet<string>();
public static void MarkAsExecuted(string eventKey, string messageText)
{
_executedMessages.Add(GetHash(eventKey, messageText));
}
public static bool IsExecuted(string eventKey, string messageText)
{
return _executedMessages.Contains(GetHash(eventKey, messageText));
}
public static void Reset()
{
_executedMessages.Clear();
}
private static string GetHash(string eventKey, string messageText)
{
string s = eventKey + "|" + messageText;
using SHA256 sHA = SHA256.Create();
return Convert.ToBase64String(sHA.ComputeHash(Encoding.UTF8.GetBytes(s)));
}
}
public class PathsManager
{
private static PathsManager _instance;
public static PathsManager Instance
{
get
{
if (_instance == null)
{
_instance = new PathsManager();
}
return _instance;
}
}
public string configPath { get; private set; }
public string xmlFilePath { get; private set; }
public string ProfilesPath { get; private set; }
private PathsManager()
{
configPath = Path.Combine(PathsManager.ConfigPath, "Chat_Configs");
xmlFilePath = Path.Combine(configPath, "MyDocument.xml");
ProfilesPath = Path.Combine(configPath, "Profiles");
}
public void EnsureDirectoriesExist()
{
if (!Directory.Exists(configPath))
{
Directory.CreateDirectory(configPath);
}
if (!Directory.Exists(ProfilesPath))
{
Directory.CreateDirectory(ProfilesPath);
}
}
}
public class ProfileManager
{
private static ProfileManager _instance;
public static ProfileManager Instance
{
get
{
if (_instance == null)
{
_instance = new ProfileManager();
}
return _instance;
}
}
private ProfileManager()
{
}
public bool ProfileExists(string name)
{
return File.Exists(GetProfilePath(name));
}
public string GetProfilePath(string name)
{
string text = SanitizeFileName(name);
return Path.Combine(PathsManager.Instance.ProfilesPath, text + ".xml");
}
public List<string> ListProfiles()
{
PathsManager.Instance.EnsureDirectoriesExist();
List<string> list = new List<string>();
string profilesPath = PathsManager.Instance.ProfilesPath;
if (!Directory.Exists(profilesPath))
{
return list;
}
string[] files = Directory.GetFiles(profilesPath, "*.xml");
for (int i = 0; i < files.Length; i++)
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(files[i]);
list.Add(fileNameWithoutExtension);
}
return list.OrderBy((string p) => p).ToList();
}
public void CreateProfile(string name, Character character)
{
PathsManager.Instance.EnsureDirectoriesExist();
string profilePath = GetProfilePath(name);
ScheduledEventsDataFile data = ScheduledEventsSerializer.Instance.Load(character);
SaveToPath(profilePath, data);
}
public void StoreProfile(string name, Character character)
{
PathsManager.Instance.EnsureDirectoriesExist();
string profilePath = GetProfilePath(name);
ScheduledEventsDataFile data = ScheduledEventsSerializer.Instance.Load(character);
SaveToPath(profilePath, data);
}
public ScheduledEventsDataFile LoadProfile(string name, Character character)
{
PathsManager.Instance.EnsureDirectoriesExist();
string profilePath = GetProfilePath(name);
ScheduledEventsDataFile scheduledEventsDataFile = LoadFromPath(profilePath);
if (scheduledEventsDataFile != null)
{
ScheduledEventsSerializer.Instance.Save(character, scheduledEventsDataFile);
ScheduledEventsSerializer.Instance.InvalidateCache();
}
return scheduledEventsDataFile;
}
public bool DeleteProfile(string name)
{
string profilePath = GetProfilePath(name);
if (File.Exists(profilePath))
{
try
{
File.Delete(profilePath);
return true;
}
catch (Exception ex)
{
OCC.LogMessage("ProfileManager: Failed to delete profile '" + name + "': " + ex.Message);
return false;
}
}
return false;
}
private void SaveToPath(string path, ScheduledEventsDataFile data)
{
try
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(ScheduledEventsDataFile));
XmlWriterSettings settings = new XmlWriterSettings
{
Indent = true,
NewLineOnAttributes = false
};
using XmlWriter xmlWriter = XmlWriter.Create(path, settings);
xmlSerializer.Serialize(xmlWriter, data);
}
catch (Exception ex)
{
OCC.LogMessage("ProfileManager@SaveToPath failed: " + ex.Message);
}
}
private ScheduledEventsDataFile LoadFromPath(string path)
{
try
{
if (!File.Exists(path))
{
OCC.LogMessage("ProfileManager: Profile file not found at: " + path);
return null;
}
XmlSerializer xmlSerializer = new XmlSerializer(typeof(ScheduledEventsDataFile));
using FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read);
return xmlSerializer.Deserialize(stream) as ScheduledEventsDataFile;
}
catch (Exception ex)
{
OCC.LogMessage("ProfileManager@LoadFromPath failed: " + ex.Message);
return null;
}
}
private string SanitizeFileName(string name)
{
char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
foreach (char oldChar in invalidFileNameChars)
{
name = name.Replace(oldChar, '_');
}
return name;
}
}
public class ScheduledEventsManager
{
private static ScheduledEventsManager _instance;
private readonly Dictionary<string, RegisteredEvent> _registeredEvents;
private readonly Dictionary<string, IScheduledTrigger> _triggers;
public static ScheduledEventsManager Instance
{
get
{
if (_instance == null)
{
_instance = new ScheduledEventsManager();
}
return _instance;
}
}
private ScheduledEventsManager()
{
_registeredEvents = new Dictionary<string, RegisteredEvent>();
_triggers = new Dictionary<string, IScheduledTrigger>();
}
public void RegisterEvent(string @namespace, string eventName, Action callback, string displayName = null)
{
string eventKey = @namespace + "." + eventName;
if (_registeredEvents.ContainsKey(eventKey))
{
OCC.LogMessage("ScheduledEventsManager: Event " + eventKey + " already registered. Overwriting.");
}
RegisteredEvent value = new RegisteredEvent(@namespace, eventName, callback, displayName);
_registeredEvents[eventKey] = value;
IScheduledTrigger scheduledTrigger = TriggerFactory.CreateExternalTrigger(eventKey);
scheduledTrigger.Subscribe(delegate
{
EventDispatcher.DispatchEvent(eventKey);
});
_triggers[eventKey] = scheduledTrigger;
OCC.LogMessage("ScheduledEventsManager: Registered event " + eventKey);
}
public void RegisterInternalEvent(string @namespace, string eventName, Action callback, string displayName = null)
{
string eventKey = @namespace + "." + eventName;
if (_registeredEvents.ContainsKey(eventKey))
{
OCC.LogMessage("ScheduledEventsManager: Internal event " + eventKey + " already registered. Overwriting.");
}
RegisteredEvent value = new RegisteredEvent(@namespace, eventName, callback, displayName, isInternal: true);
_registeredEvents[eventKey] = value;
if (@namespace == "SL")
{
try
{
IScheduledTrigger scheduledTrigger = TriggerFactory.CreateInternalTrigger(eventName);
scheduledTrigger.Initialize();
scheduledTrigger.Subscribe(delegate
{
EventDispatcher.DispatchEvent(eventKey);
});
_triggers[eventKey] = scheduledTrigger;
}
catch (Exception ex)
{
OCC.LogMessage("ScheduledEventsManager: Failed to register internal SL event " + eventKey + ": " + ex.Message);
}
}
if (@namespace == "gymmed" && eventName == "OnFirstGameReady")
{
try
{
IScheduledTrigger scheduledTrigger2 = TriggerFactory.CreateInternalTrigger("OnSceneLoaded");
scheduledTrigger2.Initialize();
scheduledTrigger2.Subscribe(delegate
{
EventDispatcher.DispatchEvent(eventKey);
});
}
catch (Exception ex2)
{
OCC.LogMessage("ScheduledEventsManager: Failed to register gymmed.OnFirstGameReady to SL.OnSceneLoaded: " + ex2.Message);
}
}
OCC.LogMessage("ScheduledEventsManager: Registered internal event " + eventKey);
}
public bool IsEventRegistered(string eventKey)
{
return _registeredEvents.ContainsKey(eventKey);
}
public RegisteredEvent GetRegisteredEvent(string eventKey)
{
_registeredEvents.TryGetValue(eventKey, out var value);
return value;
}
public IEnumerable<RegisteredEvent> GetAllRegisteredEvents()
{
return _registeredEvents.Values;
}
public IEnumerable<RegisteredEvent> GetRegisteredEventsByNamespace(string @namespace)
{
foreach (RegisteredEvent value in _registeredEvents.Values)
{
if (value.Namespace == @namespace)
{
yield return value;
}
}
}
}
public class ScheduledEventsSerializer : IMessageSerializer
{
private static ScheduledEventsSerializer _instance;
private string _configPath;
private Dictionary<string, ScheduledEventsDataFile> _cachedBindings;
private bool _isCacheLoaded;
public static ScheduledEventsSerializer Instance
{
get
{
if (_instance == null)
{
_instance = new ScheduledEventsSerializer();
}
return _instance;
}
}
private ScheduledEventsSerializer()
{
_configPath = PathsManager.Instance.configPath;
_cachedBindings = new Dictionary<string, ScheduledEventsDataFile>();
}
public void PreLoadAllData()
{
if (_isCacheLoaded)
{
OCC.LogMessage("ScheduledEventsSerializer: Cache already loaded, skipping pre-load");
return;
}
OCC.LogMessage("ScheduledEventsSerializer: Pre-loading all character event data");
_cachedBindings = LoadAllCharacters();
_isCacheLoaded = true;
OCC.LogMessage($"ScheduledEventsSerializer: Loaded {_cachedBindings.Count} character bindings into cache");
}
public void InvalidateCache()
{
_isCacheLoaded = false;
_cachedBindings.Clear();
}
public Dictionary<string, ScheduledEventsDataFile> GetCachedBindings()
{
if (!_isCacheLoaded)
{
PreLoadAllData();
}
return _cachedBindings;
}
public string GetFilePath(Character character)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
if (character != null)
{
_ = character.UID;
if (0 == 0)
{
string configPath = _configPath;
UID uID = character.UID;
return Path.Combine(configPath, ((UID)(ref uID)).Value, "ScheduledChatEvents.xml");
}
}
OCC.LogMessage("ScheduledEventsSerializer@GetCharacterXmlFilePath: Provided null character!");
return Path.Combine(_configPath, "ScheduledChatEvents.xml");
}
public ScheduledEventsDataFile Load(Character character)
{
string filePath = GetFilePath(character);
return Load(filePath);
}
public ScheduledEventsDataFile Load(string path)
{
try
{
if (!File.Exists(path))
{
OCC.LogMessage("ScheduledEventsSerializer: File not found at: " + path);
return new ScheduledEventsDataFile();
}
XmlSerializer xmlSerializer = new XmlSerializer(typeof(ScheduledEventsDataFile));
using FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read);
return (xmlSerializer.Deserialize(stream) as ScheduledEventsDataFile) ?? new ScheduledEventsDataFile();
}
catch (Exception ex)
{
OCC.LogMessage("ScheduledEventsSerializer@Load failed: " + ex.Message);
return new ScheduledEventsDataFile();
}
}
public void Save(Character character, ScheduledEventsDataFile data)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
string filePath = GetFilePath(character);
Save(filePath, data);
if (character != null)
{
_ = character.UID;
Dictionary<string, ScheduledEventsDataFile> cachedBindings = _cachedBindings;
UID uID = character.UID;
cachedBindings[((UID)(ref uID)).Value] = data;
}
}
public void Save(string path, ScheduledEventsDataFile data)
{
try
{
string directoryName = Path.GetDirectoryName(path);
if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName))
{
Directory.CreateDirectory(directoryName);
}
XmlSerializer xmlSerializer = new XmlSerializer(typeof(ScheduledEventsDataFile));
XmlWriterSettings settings = new XmlWriterSettings
{
Indent = true,
NewLineOnAttributes = false
};
using XmlWriter xmlWriter = XmlWriter.Create(path, settings);
xmlSerializer.Serialize(xmlWriter, data);
}
catch (Exception ex)
{
OCC.LogMessage("ScheduledEventsSerializer@Save failed: " + ex.Message);
}
}
public Dictionary<string, ScheduledEventsDataFile> LoadAllCharacters()
{
Dictionary<string, ScheduledEventsDataFile> dictionary = new Dictionary<string, ScheduledEventsDataFile>();
if (!Directory.Exists(_configPath))
{
return dictionary;
}
string[] directories = Directory.GetDirectories(_configPath);
foreach (string obj in directories)
{
string fileName = Path.GetFileName(obj);
string path = Path.Combine(obj, "ScheduledChatEvents.xml");
if (File.Exists(path))
{
ScheduledEventsDataFile scheduledEventsDataFile = Load(path);
if (scheduledEventsDataFile.Bindings.Count > 0)
{
dictionary[fileName] = scheduledEventsDataFile;
}
}
}
return dictionary;
}
}
}
namespace OutwardChatConfigs.Interfaces
{
public interface IMessageSerializer
{
void Save(Character character, ScheduledEventsDataFile data);
ScheduledEventsDataFile Load(Character character);
string GetFilePath(Character character);
}
public interface IScheduledTrigger
{
string EventKey { get; }
void Subscribe(Action callback);
void Unsubscribe(Action callback);
void Initialize();
}
}
namespace OutwardChatConfigs.Handlers
{
public static class ChatInputHandler
{
public static void HandleProfileCreate(Character character, Dictionary<string, string> arguments)
{
if (!arguments.TryGetValue("name", out var value) || string.IsNullOrWhiteSpace(value))
{
SendError(character, "Missing required parameter: --name");
}
else if (ProfileManager.Instance.ProfileExists(value))
{
SendWarning(character, "Profile '" + value + "' already exists. Use '/chatProfileStore --name=" + value + "' instead.");
}
else
{
ProfileManager.Instance.CreateProfile(value, character);
SendSuccess(character, "Created profile '" + value + "' with current scheduled messages.");
}
}
public static void HandleProfileStore(Character character, Dictionary<string, string> arguments)
{
if (!arguments.TryGetValue("name", out var value) || string.IsNullOrWhiteSpace(value))
{
SendError(character, "Missing required parameter: --name");
}
else if (!ProfileManager.Instance.ProfileExists(value))
{
SendError(character, "Profile '" + value + "' does not exist. Use '/chatProfileCreate --name=" + value + "' instead.");
}
else
{
ProfileManager.Instance.StoreProfile(value, character);
SendSuccess(character, "Stored current scheduled messages to profile '" + value + "'.");
}
}
public static void HandleProfileList(Character character, Dictionary<string, string> arguments)
{
List<string> list = ProfileManager.Instance.ListProfiles();
if (list.Count == 0)
{
SendInfo(character, "No profiles found.");
return;
}
SendInfo(character, $"Available profiles ({list.Count}):");
foreach (string item in list)
{
SendInfo(character, " - " + item);
}
}
public static void HandleProfileRemove(Character character, Dictionary<string, string> arguments)
{
if (!arguments.TryGetValue("name", out var value) || string.IsNullOrWhiteSpace(value))
{
SendError(character, "Missing required parameter: --name");
return;
}
if (!ProfileManager.Instance.ProfileExists(value))
{
SendError(character, "Profile '" + value + "' does not exist.");
return;
}
ProfileManager.Instance.DeleteProfile(value);
SendSuccess(character, "Deleted profile '" + value + "'.");
}
public static void HandleProfileUse(Character character, Dictionary<string, string> arguments)
{
if (!arguments.TryGetValue("name", out var value) || string.IsNullOrWhiteSpace(value))
{
SendError(character, "Missing required parameter: --name");
return;
}
if (!ProfileManager.Instance.ProfileExists(value))
{
SendError(character, "Profile '" + value + "' does not exist.");
return;
}
ScheduledEventsDataFile scheduledEventsDataFile = ProfileManager.Instance.LoadProfile(value, character);
if (scheduledEventsDataFile != null)
{
int num = scheduledEventsDataFile.Bindings.Sum((ScheduledEventBinding b) => b.Messages.Count);
SendSuccess(character, $"Loaded profile '{value}' with {num} message(s).");
}
else
{
SendError(character, "Failed to load profile '" + value + "'.");
}
}
public static void HandleBind(Character character, Dictionary<string, string> arguments)
{
if (!arguments.TryGetValue("mod", out var value) || string.IsNullOrWhiteSpace(value))
{
SendError(character, "Missing required parameter: --mod");
return;
}
if (!arguments.TryGetValue("event", out var value2) || string.IsNullOrWhiteSpace(value2))
{
SendError(character, "Missing required parameter: --event");
return;
}
if (!arguments.TryGetValue("message", out var value3) || string.IsNullOrWhiteSpace(value3))
{
SendError(character, "Missing required parameter: --message");
return;
}
string eventKey = value + "." + value2;
if (!ScheduledEventsManager.Instance.IsEventRegistered(eventKey))
{
SendError(character, "Event '" + eventKey + "' is not registered. Use /listbinds to see available events.");
return;
}
ScheduledEventsDataFile scheduledEventsDataFile = ScheduledEventsSerializer.Instance.Load(character);
ScheduledEventBinding scheduledEventBinding = scheduledEventsDataFile.Bindings.FirstOrDefault((ScheduledEventBinding b) => b.EventKey == eventKey);
if (scheduledEventBinding == null)
{
scheduledEventBinding = new ScheduledEventBinding(eventKey);
scheduledEventsDataFile.Bindings.Add(scheduledEventBinding);
}
int count = scheduledEventBinding.Messages.Count;
scheduledEventBinding.Messages.Add(new ScheduledMessage(count, value3));
ScheduledEventsSerializer.Instance.Save(character, scheduledEventsDataFile);
SendSuccess(character, $"Bound message to event '{eventKey}' with index {count}: {value3}");
}
public static void HandleUnbind(Character character, Dictionary<string, string> arguments)
{
if (!arguments.TryGetValue("mod", out var value) || string.IsNullOrWhiteSpace(value))
{
SendError(character, "Missing required parameter: --mod");
return;
}
if (!arguments.TryGetValue("event", out var value2) || string.IsNullOrWhiteSpace(value2))
{
SendError(character, "Missing required parameter: --event");
return;
}
if (!arguments.TryGetValue("index", out var value3) || !int.TryParse(value3, out var result))
{
SendError(character, "Missing required parameter: --index (must be a number)");
return;
}
string eventKey = value + "." + value2;
ScheduledEventsDataFile scheduledEventsDataFile = ScheduledEventsSerializer.Instance.Load(character);
ScheduledEventBinding scheduledEventBinding = scheduledEventsDataFile.Bindings.FirstOrDefault((ScheduledEventBinding b) => b.EventKey == eventKey);
if (scheduledEventBinding == null)
{
SendError(character, "No bindings found for event '" + eventKey + "'.");
return;
}
if (result < 0 || result >= scheduledEventBinding.Messages.Count)
{
SendError(character, $"Invalid index {result}. Valid range: 0-{scheduledEventBinding.Messages.Count - 1}");
return;
}
ScheduledMessage scheduledMessage = scheduledEventBinding.Messages[result];
scheduledEventBinding.Messages.RemoveAt(result);
for (int i = result; i < scheduledEventBinding.Messages.Count; i++)
{
scheduledEventBinding.Messages[i].Index = i;
}
ScheduledEventsSerializer.Instance.Save(character, scheduledEventsDataFile);
SendSuccess(character, $"Removed binding at index {result}: {scheduledMessage.Text}");
}
public static void HandleListBinds(Character character, Dictionary<string, string> arguments)
{
arguments.TryGetValue("mod", out var modFilter);
IEnumerable<ScheduledEventBinding> source = ScheduledEventsSerializer.Instance.Load(character).Bindings.AsEnumerable();
if (!string.IsNullOrWhiteSpace(modFilter))
{
source = source.Where((ScheduledEventBinding b) => b.EventKey.StartsWith(modFilter + "."));
}
List<ScheduledEventBinding> list = source.ToList();
if (list.Count == 0)
{
SendInfo(character, string.IsNullOrWhiteSpace(modFilter) ? "No event bindings found." : ("No event bindings found for mod '" + modFilter + "'."));
return;
}
SendInfo(character, "Event bindings" + (string.IsNullOrWhiteSpace(modFilter) ? "" : (" for mod '" + modFilter + "'")) + ":");
foreach (ScheduledEventBinding item in list)
{
SendInfo(character, " " + item.EventKey + ":");
if (item.Messages.Count == 0)
{
SendInfo(character, " (no messages bound)");
continue;
}
foreach (ScheduledMessage message in item.Messages)
{
SendInfo(character, $" [{message.Index}]: {message.Text}");
}
}
}
public static void HandleConfigEvents(Character character, Dictionary<string, string> arguments)
{
SendInfo(character, "=== Available Events ===");
SendInfo(character, "");
SendInfo(character, "Internal Events:");
SendInfo(character, " gymmed.OnFirstGameReady - First time game is ready for chat");
SendInfo(character, "");
SendInfo(character, "SL Events (SideLoader):");
SendInfo(character, " SL.BeforePacksLoaded - Before packs are loaded");
SendInfo(character, " SL.OnPacksLoaded - When packs are loaded");
SendInfo(character, " SL.OnSceneLoaded - When a scene is loaded");
SendInfo(character, " SL.OnGameplayResumedAfterLoading - When gameplay resumes after loading");
SendInfo(character, " SL.OnBeforeHotReload - Before hot reload");
SendInfo(character, "");
SendInfo(character, "External Events:");
SendInfo(character, " Any custom event key (format: ModNamespace.EventName)");
SendInfo(character, " Example: MyMod.OnPlayerLogin, MyMod.OnQuestComplete");
SendInfo(character, "");
SendInfo(character, "How to bind a message:");
SendInfo(character, " /bind --mod=\"gymmed\" --event=\"OnFirstGameReady\" --message=\"/say Hello!\"");
SendInfo(character, "");
SendInfo(character, "To listen for external events, use Mods Communicator:");
SendInfo(character, " Subscribe to 'namespace' with event name 'EventName'");
SendInfo(character, " Then publish events to trigger bound chat messages");
}
private static void SendSuccess(Character character, string message)
{
character.CharacterUI.ChatPanel.ChatMessageReceived("System", ChatLogStatusHelper.GetChatLogText(message, ChatLogStatus.Success));
}
private static void SendError(Character character, string message)
{
character.CharacterUI.ChatPanel.ChatMessageReceived("System", ChatLogStatusHelper.GetChatLogText(message, ChatLogStatus.Error));
}
private static void SendWarning(Character character, string message)
{
character.CharacterUI.ChatPanel.ChatMessageReceived("System", ChatLogStatusHelper.GetChatLogText(message, ChatLogStatus.Warning));
}
private static void SendInfo(Character character, string message)
{
character.CharacterUI.ChatPanel.ChatMessageReceived("System", ChatLogStatusHelper.GetChatLogText(message));
}
}
public static class EventDispatcher
{
private static readonly FieldInfo ChatEntryField;
static EventDispatcher()
{
ChatEntryField = typeof(ChatPanel).GetField("m_chatEntry", BindingFlags.Instance | BindingFlags.NonPublic);
}
public static void DispatchEvent(string eventKey)
{
RegisteredEvent registeredEvent = ScheduledEventsManager.Instance.GetRegisteredEvent(eventKey);
if (registeredEvent != null && registeredEvent.Callback != null)
{
try
{
registeredEvent.Callback();
}
catch (Exception ex)
{
OCC.LogMessage("EventDispatcher: Error executing callback for " + eventKey + ": " + ex.Message);
}
}
foreach (KeyValuePair<string, ScheduledEventsDataFile> cachedBinding in ScheduledEventsSerializer.Instance.GetCachedBindings())
{
Character character = CharacterManager.Instance.GetCharacter(cachedBinding.Key);
if ((Object)(object)character == (Object)null)
{
continue;
}
ScheduledEventBinding scheduledEventBinding = cachedBinding.Value.Bindings.FirstOrDefault((ScheduledEventBinding b) => b.EventKey == eventKey);
if (scheduledEventBinding == null || scheduledEventBinding.Messages.Count == 0)
{
continue;
}
CharacterUI characterUI = character.CharacterUI;
ChatPanel val = ((characterUI != null) ? characterUI.ChatPanel : null);
if ((Object)(object)val == (Object)null)
{
continue;
}
foreach (ScheduledMessage message in scheduledEventBinding.Messages)
{
bool flag = eventKey.StartsWith("gymmed.");
if (flag && ExecutionTracker.IsExecuted(eventKey, message.Text))
{
continue;
}
try
{
SendChatMessageViaReflection(val, message.Text);
if (flag)
{
ExecutionTracker.MarkAsExecuted(eventKey, message.Text);
}
}
catch (Exception ex2)
{
OCC.LogMessage("EventDispatcher: Error executing message '" + message.Text + "': " + ex2.Message);
}
}
}
}
private static void SendChatMessageViaReflection(ChatPanel panel, string messageText)
{
InputField chatEntry = panel.m_chatEntry;
if ((Object)(object)chatEntry == (Object)null)
{
OCC.LogMessage("EventDispatcher: Failed to get m_chatEntry field from ChatPanel");
return;
}
chatEntry.text = messageText;
panel.SendChatMessage();
}
}
}
namespace OutwardChatConfigs.Events
{
public static class ChatCommandsRegistrar
{
public static void RegisterCommand(string commandName, Dictionary<string, (string, string)> parameters, string description, bool requiresDebubMode, bool isCheatCommand, Action<Character, Dictionary<string, string>> function)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected O, but got Unknown
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Expected O, but got Unknown
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Expected O, but got Unknown
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Expected O, but got Unknown
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Expected O, but got Unknown
//IL_0090: Expected O, but got Unknown
EventPayload val = new EventPayload { };
string item;
((Dictionary<string, object>)val)[item] = commandName;
string item2 = ChatCommandsManagerParamsHelper.Get(ChatCommandsManagerParams.CommandParameters).key;
((Dictionary<string, object>)val)[item2] = parameters;
string item3 = ChatCommandsManagerParamsHelper.Get(ChatCommandsManagerParams.CommandAction).key;
((Dictionary<string, object>)val)[item3] = function;
string item4 = ChatCommandsManagerParamsHelper.Get(ChatCommandsManagerParams.CommandDescription).key;
((Dictionary<string, object>)val)[item4] = description;
string item5 = ChatCommandsManagerParamsHelper.Get(ChatCommandsManagerParams.CommandRequiresDebugMode).key;
((Dictionary<string, object>)val)[item5] = requiresDebubMode;
string item6 = ChatCommandsManagerParamsHelper.Get(ChatCommandsManagerParams.IsCheatCommand).key;
((Dictionary<string, object>)val)[item6] = isCheatCommand;
EventPayload val2 = val;
EventBus.Publish("gymmed.chat_commands_manager_*", "ChatCommandsManager@AddChatCommand", val2);
}
}
public static class EventBusPublisher
{
public const string Event_AddCommand = "ChatCommandsManager@AddChatCommand";
public const string Event_RemoveCommand = "ChatCommandsManager@RemoveChatCommand";
public const string ChatCommands_Listener = "gymmed.chat_commands_manager_*";
public static void SendCommands()
{
RegisterChatCommands();
}
public static void RegisterChatCommands()
{
ChatCommandsRegistrar.RegisterCommand("bind", new Dictionary<string, (string, string)>
{
{
"mod",
("Required. Mod namespace.", "")
},
{
"event",
("Required. Event name.", "")
},
{
"message",
("Required. Text to execute when event fires.", "")
}
}, "Binds a message to an event. Example: /bind --mod=\"MyMod\" --event=\"OnPlayerLogin\" --message=\"/say Hello!\"", requiresDebubMode: false, isCheatCommand: false, ChatInputHandler.HandleBind);
ChatCommandsRegistrar.RegisterCommand("unbind", new Dictionary<string, (string, string)>
{
{
"mod",
("Required. Mod namespace.", "")
},
{
"event",
("Required. Event name.", "")
},
{
"index",
("Required. Message index to remove.", "0")
}
}, "Removes a bound message from an event. Example: /unbind --mod=\"MyMod\" --event=\"OnPlayerLogin\" --index=0", requiresDebubMode: false, isCheatCommand: false, ChatInputHandler.HandleUnbind);
ChatCommandsRegistrar.RegisterCommand("listbinds", new Dictionary<string, (string, string)> {
{
"mod",
("Optional. Filter by mod namespace. Leave empty for all.", "")
} }, "Shows all bound messages. Example: /listbinds or /listbinds --mod=\"MyMod\"", requiresDebubMode: false, isCheatCommand: false, ChatInputHandler.HandleListBinds);
ChatCommandsRegistrar.RegisterCommand("configEvents", new Dictionary<string, (string, string)>(), "Shows all available events for binding. Example: /configEvents", requiresDebubMode: false, isCheatCommand: false, ChatInputHandler.HandleConfigEvents);
ChatCommandsRegistrar.RegisterCommand("chatProfileCreate", new Dictionary<string, (string, string)> {
{
"name",
("Required. Profile name.", "")
} }, "Creates a new profile with current scheduled messages. Example: /chatProfileCreate --name=myProfile", requiresDebubMode: false, isCheatCommand: false, ChatInputHandler.HandleProfileCreate);
ChatCommandsRegistrar.RegisterCommand("chatProfileStore", new Dictionary<string, (string, string)> {
{
"name",
("Required. Profile name.", "")
} }, "Stores current scheduled messages to existing profile. Example: /chatProfileStore --name=myProfile", requiresDebubMode: false, isCheatCommand: false, ChatInputHandler.HandleProfileStore);
ChatCommandsRegistrar.RegisterCommand("chatProfilesList", new Dictionary<string, (string, string)>(), "Lists all available profiles. Example: /chatProfilesList", requiresDebubMode: false, isCheatCommand: false, ChatInputHandler.HandleProfileList);
ChatCommandsRegistrar.RegisterCommand("chatProfilesRemove", new Dictionary<string, (string, string)> {
{
"name",
("Required. Profile name to remove.", "")
} }, "Removes a profile. Example: /chatProfilesRemove --name=myProfile", requiresDebubMode: false, isCheatCommand: false, ChatInputHandler.HandleProfileRemove);
ChatCommandsRegistrar.RegisterCommand("chatProfilesUse", new Dictionary<string, (string, string)> {
{
"name",
("Required. Profile name to load.", "")
} }, "Loads a profile, replacing current scheduled messages. Example: /chatProfilesUse --name=myProfile", requiresDebubMode: false, isCheatCommand: false, ChatInputHandler.HandleProfileUse);
}
}
public static class EventBusRegister
{
private static readonly (string key, Type type, string description)[] RegisterEventData = new(string, Type, string)[4]
{
("namespace", typeof(string), "Required. The namespace to prevent collision (e.g., 'MyMod')."),
("eventName", typeof(string), "Required. The event name (e.g., 'OnPlayerLogin')."),
("action", typeof(Action), "Required. The callback to execute when the event fires."),
("displayName", typeof(string), "Optional. User-facing name for the event.")
};
private static readonly (string key, Type type, string description)[] TriggerEventData = new(string, Type, string)[2]
{
("namespace", typeof(string), "Required. The namespace of the event (e.g., 'MyMod')."),
("eventName", typeof(string), "Required. The event name to trigger (e.g., 'OnPlayerLogin').")
};
public static void RegisterEvents()
{
EventBus.RegisterEvent("gymmed.chat_configs_*", "ScheduledEvents@RegisterEvent", "Registers a new event that users can bind messages to.", RegisterEventData);
EventBus.RegisterEvent("gymmed.chat_configs_*", "ScheduledEvents@TriggerEvent", "Triggers an event, executing any bound chat messages.", TriggerEventData);
}
}
public static class EventBusSubscriber
{
public const string Event_AddedChatCommand = "ChatCommandsManager@AddChatCommand_After";
public const string Event_RemovedChatCommand = "ChatCommandsManager@RemoveChatCommand_After";
public const string Event_RegisterEvent = "ScheduledEvents@RegisterEvent";
public const string Event_TriggerEvent = "ScheduledEvents@TriggerEvent";
public static void AddSubscribers()
{
EventBus.Subscribe("gymmed.chat_commands_manager_*", "ChatCommandsManager@AddChatCommand_After", (Action<EventPayload>)AddedChatCommand);
EventBus.Subscribe("gymmed.chat_commands_manager_*", "ChatCommandsManager@RemoveChatCommand_After", (Action<EventPayload>)RemovedChatCommand);
EventBus.Subscribe("gymmed.chat_configs_*", "ScheduledEvents@RegisterEvent", (Action<EventPayload>)OnRegisterEvent);
EventBus.Subscribe("gymmed.chat_configs_*", "ScheduledEvents@TriggerEvent", (Action<EventPayload>)OnTriggerEvent);
}
public static void AddedChatCommand(EventPayload payload)
{
if (payload != null)
{
(string, Type) tuple = ChatCommandsManagerParamsHelper.Get(ChatCommandsManagerParams.CommandName);
payload.Get<string>(tuple.Item1, (string)null);
OCC.LogMessage("Added command " + tuple.Item1);
}
}
public static void RemovedChatCommand(EventPayload payload)
{
if (payload != null)
{
(string, Type) tuple = ChatCommandsManagerParamsHelper.Get(ChatCommandsManagerParams.CommandName);
payload.Get<string>(tuple.Item1, (string)null);
OCC.LogMessage("Removed command " + tuple.Item1);
}
}
public static void OnRegisterEvent(EventPayload payload)
{
if (payload == null)
{
return;
}
string text = payload.Get<string>("namespace", (string)null);
if (string.IsNullOrEmpty(text))
{
OCC.LogMessage("EventBusSubscriber: namespace is required!");
return;
}
string text2 = payload.Get<string>("eventName", (string)null);
if (string.IsNullOrEmpty(text2))
{
OCC.LogMessage("EventBusSubscriber: eventName is required!");
return;
}
Action action = payload.Get<Action>("action", (Action)null);
if (action == null)
{
OCC.LogMessage("EventBusSubscriber: action callback is required!");
return;
}
string displayName = payload.Get<string>("displayName", text2);
ScheduledEventsManager.Instance.RegisterEvent(text, text2, action, displayName);
}
public static void OnTriggerEvent(EventPayload payload)
{
if (payload == null)
{
return;
}
string text = payload.Get<string>("namespace", (string)null);
if (string.IsNullOrEmpty(text))
{
OCC.LogMessage("EventBusSubscriber: namespace is required for triggering event!");
return;
}
string text2 = payload.Get<string>("eventName", (string)null);
if (string.IsNullOrEmpty(text2))
{
OCC.LogMessage("EventBusSubscriber: eventName is required for triggering event!");
return;
}
string text3 = text + "." + text2;
RegisteredEvent registeredEvent = ScheduledEventsManager.Instance.GetRegisteredEvent(text3);
if (registeredEvent != null && registeredEvent.Callback != null)
{
try
{
registeredEvent.Callback();
}
catch (Exception ex)
{
OCC.LogMessage("EventBusSubscriber: Error executing callback for " + text3 + ": " + ex.Message);
}
}
EventDispatcher.DispatchEvent(text3);
}
}
}
namespace OutwardChatConfigs.Events.Publishers
{
public static class ExamplePublisher
{
public static void SendExampleCommand()
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Expected O, but got Unknown
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Expected O, but got Unknown
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Expected O, but got Unknown
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Expected O, but got Unknown
//IL_008d: Expected O, but got Unknown
Dictionary<string, (string, string)> value = new Dictionary<string, (string, string)> {
{
"yourVar",
("Optional. Some dynamic data that user can provide in chat with --yourVar='value'.", null)
} };
Action<Character, Dictionary<string, string>> value2 = TriggerFunction;
EventPayload val = new EventPayload { };
string item;
((Dictionary<string, object>)val)[item] = "example";
string item2 = ChatCommandsManagerParamsHelper.Get(ChatCommandsManagerParams.CommandParameters).key;
((Dictionary<string, object>)val)[item2] = value;
string item3 = ChatCommandsManagerParamsHelper.Get(ChatCommandsManagerParams.CommandAction).key;
((Dictionary<string, object>)val)[item3] = value2;
string item4 = ChatCommandsManagerParamsHelper.Get(ChatCommandsManagerParams.CommandDescription).key;
((Dictionary<string, object>)val)[item4] = "Example method for user to test. This description can be seen with chat command:/help example";
EventPayload val2 = val;
EventBus.Publish("gymmed.chat_commands_manager_*", "ChatCommandsManager@AddChatCommand", val2);
}
public static void TriggerFunction(Character caller, Dictionary<string, string> arguments)
{
object obj;
if (caller == null)
{
obj = null;
}
else
{
CharacterUI characterUI = caller.CharacterUI;
obj = ((characterUI != null) ? characterUI.ChatPanel : null);
}
ChatPanel val = (ChatPanel)obj;
if ((Object)(object)val == (Object)null)
{
OCC.LogMessage("ExamplePublisher@TriggerFunction Tried to use missing chatPanel.");
return;
}
arguments.TryGetValue("yourVar", out var value);
if (string.IsNullOrWhiteSpace(value))
{
ChatHelpers.SendChatLog(val, "You didn't provide yourVar variable!", ChatLogStatus.Warning);
}
ChatHelpers.SendChatLog(val, "Finished executing trigger method!", ChatLogStatus.Success);
}
}
}