Decompiled source of ChaosTricks REPO TwitchIntegration v1.3.0
ChaosTricks_REPO_plugins/EventsIO.dll
Decompiled 3 weeks agousing 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.Text; using EventsIO.Interfaces; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("EventIO")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("BFT")] [assembly: AssemblyProduct("EventIO")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("ab7abff2-5203-43d0-88ed-aebd4b6a130c")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.0.0")] namespace EventsIO { public class EventsData : IEventsData { public string Username { get; set; } public string Cost { get; set; } public string EventID { get; set; } public string Lang { get; set; } public string ExtraInfo { get; set; } public override string ToString() { return "EventsData: " + Username + " " + Cost + " " + EventID + " " + Lang + " " + ExtraInfo; } } public class EventsDataEncoder : IEventsDataEncoder, IEventsDataEncoderParams { internal static readonly string clientAppSep = "&"; internal static readonly char clientAppSepChar = '&'; internal static readonly string clientAppEqual = "="; internal static readonly char clientAppEqualChar = '='; protected static readonly Dictionary<string, string> symbolCodes = new Dictionary<string, string> { { clientAppSep, "%encode_amp%" }, { clientAppEqual, "%encode_equal%" } }; string IEventsDataEncoderParams.ClientAppSep => clientAppSep; char IEventsDataEncoderParams.ClientAppSepChar => clientAppSepChar; string IEventsDataEncoderParams.ClientAppEqual => clientAppEqual; char IEventsDataEncoderParams.ClientAppEqualChar => clientAppEqualChar; public virtual string Encode(string s) { foreach (KeyValuePair<string, string> symbolCode in symbolCodes) { s = s?.Replace(symbolCode.Key, symbolCode.Value); } return s; } public virtual string Decode(string s) { foreach (KeyValuePair<string, string> symbolCode in symbolCodes) { s = s?.Replace(symbolCode.Value, symbolCode.Key); } return s; } } public class EventsDataParser : IEventsDataParser { protected readonly Action<string> log; protected readonly IEventsDataEncoder encoder; protected readonly IEventsDataEncoderParams encoderParams; public bool isLogInfoError = true; public bool isLogSkipEmpty; public EventsDataParser(Action<string> log = null) { this.log = log; encoderParams = (IEventsDataEncoderParams)(encoder = new EventsDataEncoder()); } protected virtual void ParserLog(string s) { log?.Invoke(s); } public virtual IEventsData ParseEvent(string data) { EventsData eventsData = new EventsData(); string[] array = data.Split(new char[1] { encoderParams.ClientAppSepChar }, StringSplitOptions.RemoveEmptyEntries); if (array == null) { if (isLogInfoError) { ParserLog("get event info error. Wrong args."); } return eventsData; } string[] array2 = array; foreach (string text in array2) { string[] array3 = text.Split(new char[1] { encoderParams.ClientAppEqualChar }, StringSplitOptions.RemoveEmptyEntries); if (array3.Length != 2) { if (isLogSkipEmpty) { ParserLog("skip empty item: " + text); } continue; } string text2 = encoder.Decode(array3[0]); string text3 = encoder.Decode(array3[1]); switch (text2.ToLowerInvariant()) { case "username": eventsData.Username = text3; break; case "eventid": eventsData.EventID = text3; break; case "cost": eventsData.Cost = text3; break; case "lang": eventsData.Lang = text3; break; case "extrainfo": eventsData.ExtraInfo = text3; break; } } return eventsData; } } public class EventsGenerator : IEventsGenerator { protected internal enum FieldNames { UserName, EventID, Cost, Lang, ExtraInfo } protected EventsData data; protected readonly IEventsDataEncoder encoder; protected readonly IEventsDataEncoderParams encoderParams; public EventsGenerator() { data = new EventsData(); encoderParams = (IEventsDataEncoderParams)(encoder = new EventsDataEncoder()); } public virtual void SetCost(string s) { data.Cost = encoder.Encode(s); } public virtual void SetEventID(string s) { data.EventID = encoder.Encode(s); } public virtual void SetLang(string s) { data.Lang = encoder.Encode(s); } public virtual void SetUsername(string s) { data.Username = encoder.Encode(s); } public virtual void SetExtraInfo(string s) { data.ExtraInfo = encoder.Encode(s); } public virtual string Generate() { Dictionary<FieldNames, string> obj = new Dictionary<FieldNames, string> { { FieldNames.UserName, data.Username }, { FieldNames.Cost, data.Cost }, { FieldNames.EventID, data.EventID }, { FieldNames.Lang, data.Lang }, { FieldNames.ExtraInfo, data.ExtraInfo } }; StringBuilder stringBuilder = new StringBuilder(obj.Count); string clientAppSep = encoderParams.ClientAppSep; string clientAppEqual = encoderParams.ClientAppEqual; bool flag = true; foreach (KeyValuePair<FieldNames, string> item in obj) { if (flag) { stringBuilder.Append($"{item.Key}{clientAppEqual}{item.Value}"); flag = false; continue; } stringBuilder.Append($"{clientAppSep}{item.Key}{clientAppEqual}{item.Value}"); } data = new EventsData(); return stringBuilder.ToString(); } } public class EventsReaderOnKey : EventsReader, IEventsReaderOnKey, IEventsReader { protected readonly Action<IEventsData> processEvent; protected readonly IEventsDataParser parser; public EventsReaderOnKey(Action<IEventsData> processEvent, IEventsDataParser parser, Action<string> log = null, Action<string> logError = null) : base(log, logError) { this.processEvent = processEvent; this.parser = parser; } protected virtual void ProcessOnKey(string[] events) { if (events == null || events.Length == 0) { return; } foreach (IEventsData item in events.Select((string item) => parser?.ParseEvent(item))) { try { ReaderLog($"StartProcessOnKey {item}"); processEvent?.Invoke(item); } catch (Exception arg) { ReaderLogError($"StartProcessOnKey error: {arg}"); } } } public virtual void ProcessAllOnKey(string[] events) { try { ProcessOnKey(events); } catch (Exception arg) { ReaderLogError($"ProcessAllOnKey error: {arg}"); } } public virtual void ReadAndProcessAllOnKey(string path, bool isClearFile = true) { ProcessAllOnKey(ReadAll(path, isClearFile)); } } public class EventsReaderOnFrame : EventsReader, IEventsReaderOnFrame, IEventsReader { protected bool isFirstRun = true; protected readonly float delay; protected float delayCounter; protected float initDelay; protected float initCounter; protected readonly float checkPeriod; protected float periodCounter; protected readonly Action<IEventsData> processEvent; protected readonly IEventsDataParser parser; protected IEnumerator<IEventsData> eventsData; protected readonly string path; private bool isDelayEveryProcessing; public bool IsDelayEveryProcessing { get { return isDelayEveryProcessing; } set { isDelayEveryProcessing = value; } } protected virtual void StartProcessOnFrame() { while (eventsData.MoveNext()) { try { ReaderLog($"StartProcessOnFrame {eventsData.Current}"); processEvent?.Invoke(eventsData.Current); } catch (Exception arg) { ReaderLogError($"StartProcessOnFrame error: {arg}"); } } eventsData = null; } protected virtual void StartProcessWithDelayOnFrame() { if (eventsData.MoveNext()) { try { ReaderLog($"StartProcessWithDelayOnFrame {eventsData.Current}"); processEvent?.Invoke(eventsData.Current); return; } catch (Exception arg) { ReaderLogError($"StartProcessWithDelayOnFrame error: {arg}"); return; } } isFirstRun = false; eventsData = null; ReaderLog("StartProcessWithDelayOnFrame end"); } public EventsReaderOnFrame(string path, Action<IEventsData> processEvent, IEventsDataParser parser, Action<string> log = null, Action<string> errorLog = null, float checkPeriod = 2f, float delay = 1f, float initDelay = 0.5f) : base(log, errorLog) { this.processEvent = processEvent; this.parser = parser; this.delay = delay; this.initDelay = initDelay; this.path = path; this.checkPeriod = checkPeriod; } public virtual void SetEventsToProcess(string[] events) { try { if (events == null || events.Length == 0) { eventsData = null; return; } ReaderLog($"SetEventsToProcess read {events.Length} events"); eventsData = events.Select((string item) => parser?.ParseEvent(item))?.GetEnumerator(); } catch (Exception arg) { ReaderLogError($"SetEventsToProcess error: {arg}"); } } public virtual bool IsProcessEnd() { return eventsData == null; } public virtual void ProcessAllWithDelayOnFrame(float dt) { if (IsProcessEnd()) { return; } try { if (isDelayEveryProcessing || isFirstRun) { if (initDelay != 0f) { initCounter += dt; if (initCounter >= initDelay) { initCounter = 0f; initDelay = 0f; StartProcessWithDelayOnFrame(); } } else { delayCounter += dt; if (delayCounter >= delay) { delayCounter = 0f; StartProcessWithDelayOnFrame(); } } } else { StartProcessOnFrame(); } } catch (Exception arg) { ReaderLogError($"ProcessAllWithDelay error: {arg}"); } } public virtual void ReadAndProcessAllWithDelayOnFrame(float dt) { if (IsProcessEnd()) { periodCounter += dt; if (periodCounter >= checkPeriod) { periodCounter = 0f; string[] eventsToProcess = ReadAll(path); SetEventsToProcess(eventsToProcess); } } ProcessAllWithDelayOnFrame(dt); } } public class EventsReader : IEventsReader { protected readonly Action<string> log; protected readonly Action<string> logError; public EventsReader(Action<string> log = null, Action<string> logError = null) { this.log = log; this.logError = logError; } protected virtual void ReaderLog(string s) { log?.Invoke(s); } protected virtual void ReaderLogError(string s) { logError?.Invoke(s); } public virtual string[] ReadAllUnsafe(string path, bool isClearFile = true) { using FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); using StreamReader streamReader = new StreamReader(fileStream, Encoding.UTF8); char[] separator = new char[2] { '\r', '\n' }; string[] array = streamReader.ReadToEnd().Split(separator, StringSplitOptions.RemoveEmptyEntries); if (isClearFile && array != null && array.Length >= 1) { fileStream.SetLength(0L); } return array; } public virtual string[] ReadAll(string path, bool isClearFile = true) { try { return ReadAllUnsafe(path, isClearFile); } catch (FileNotFoundException) { } catch (DirectoryNotFoundException) { } catch (Exception arg) { ReaderLogError($"read event error: {arg}"); } return null; } } } namespace EventsIO.Interfaces { public interface IEventsData { string Username { get; } string Cost { get; } string EventID { get; } string Lang { get; } string ExtraInfo { get; } } public interface IEventsDataEncoderParams { string ClientAppSep { get; } char ClientAppSepChar { get; } string ClientAppEqual { get; } char ClientAppEqualChar { get; } } public interface IEventsDataEncoder { string Encode(string s); string Decode(string s); } public interface IEventsDataParser { IEventsData ParseEvent(string s); } public interface IEventsGenerator { void SetUsername(string s); void SetEventID(string s); void SetCost(string s); void SetLang(string s); void SetExtraInfo(string s); string Generate(); } public interface IEventsReaderOnKey : IEventsReader { void ProcessAllOnKey(string[] events); void ReadAndProcessAllOnKey(string path, bool isClearFile = true); } public interface IEventsReaderOnFrame : IEventsReader { void SetEventsToProcess(string[] events); bool IsProcessEnd(); void ProcessAllWithDelayOnFrame(float dt); void ReadAndProcessAllWithDelayOnFrame(float dt); } public interface IEventsReader { string[] ReadAll(string path, bool isClearFile = true); } }
ChaosTricks_REPO_plugins/InteractiveMod.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; 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 BepInEx; using EventsIO; using EventsIO.Interfaces; using HarmonyLib; using ModHelper; using ModHelper.Interfaces; using ModHelperUnity; using Newtonsoft.Json; using Photon.Pun; using REPO_BFT_BepInEx.Commands.Interfaces; using REPO_BFT_BepInEx.Patchers; using REPO_BFT_BepInEx.Services; using REPO_BFT_BepInEx.Wrappers; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; using WebSocketIO; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("REPO BepInEx version")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("BFT LLC")] [assembly: AssemblyProduct("ChaosTricksMod")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("BFT")] [assembly: ComVisible(false)] [assembly: Guid("482A702C-A19B-425E-8DCC-FE9C62D172B0")] [assembly: AssemblyFileVersion("1.3.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.3.0.0")] namespace REPO_BFT_BepInEx { [BepInPlugin("bft.chaostricks", "Chaos Tricks", "1.3.0")] public class BepInExPlugin : BaseUnityPlugin { public const string GUID = "bft.chaostricks"; public const string NAME = "Chaos Tricks"; private GameObject hookObj; private bool isPatched; public void Awake() { try { UtilitySettings.BaseFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); SceneManager.sceneLoaded += OnSceneLoaded; } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)string.Format("{0} v{1} error: {2}", "Chaos Tricks", "1.3.0", arg)); } } private void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown try { ((HelperLog)Utils.logger).Log((object)("OnSceneLoaded triggered: " + ((Scene)(ref scene)).name)); if (!isPatched) { ((HelperLog)Utils.logger).LogInfo((object)"Background task: trying to create mod instance"); hookObj = new GameObject(); Object.DontDestroyOnLoad((Object)(object)hookObj); hookObj.AddComponent<InteractiveMod>(); hookObj.SetActive(true); isPatched = true; SceneManager.sceneLoaded -= OnSceneLoaded; } } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)string.Format("{0} v{1} OnSceneLoaded error: {2}", "Chaos Tricks", "1.3.0", arg)); } } } public sealed class InteractiveMod : MonoBehaviour { internal static InteractiveMod inst; internal const string MOD_VERSION = "1.3.0"; private readonly ServiceProvider serviceProvider = ServiceProvider.inst; private readonly BufferedLogger logger = Utils.logger; private ScheduleManager systemScheduleManager; private ScheduleManager scheduleManager; private EventEmitter eventEmitter; private WebSocketEventsReader<SettingsData> eventsReader; private IEventsDataParser eventsParser; private ICommandManager commandManager; private CommandListArgManager commandListArgManager = new CommandListArgManager(); private UtilityConsole console; private ChaosEnemySpawner enemySpawner; private Dictionary<string, IRepoStandaloneCommand> commands; private TranslationService translationService; private LimitedLogWrapper limitedLogger; private LimitedLogWrapper limitedSceneLogger; private bool isAppConnected; private bool isAppConnectedProcessed = true; private readonly List<IForceEnd> forceEndEvents = new List<IForceEnd>(); private static bool msgType; private bool isLevelGeneratedLastCheck; private bool isMenuLevelLastCheck; public void Awake() { inst = this; Utils.LogClearBySize(); limitedLogger = new LimitedLogWrapper(100, (IDebugLogger)(object)Utils.logger); limitedSceneLogger = new LimitedLogWrapper(50, (IDebugLogger)(object)Utils.logger); ((HelperLog)logger).LogInfo((object)"InteractiveMod Awake"); ((HelperLog)logger).LogInfo((object)"mod version 1.3.0"); FlushLog(); MainPatcher.InitPatch(); } public void Start() { ((HelperLog)logger).LogInfo((object)"InteractiveMod Start"); try { UtilityJson.RegisterCustomGenerator((Func<IJsonUtil>)(() => (IJsonUtil)(object)new JsonParser())); ((HelperLog)logger).LogInfo((object)"init mod services"); InitServices(); ((HelperLog)logger).LogInfo((object)"init mod readers"); InitReaders(); ((HelperLog)logger).LogInfo((object)"init mod commands"); InitCommands(needValidate: false); ((HelperLog)logger).LogInfo((object)"mod initiation ends"); } catch (Exception arg) { ((HelperLog)logger).LogError((object)$"mod initiation error: {arg}"); } FlushLog(); } public void OnDestroy() { ((HelperLog)logger).LogInfo((object)"InteractiveMod OnDestroy"); FlushLog(); } private void FlushLog() { logger.Flush(true); } private void InitServices() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown eventEmitter = new EventEmitter(); serviceProvider.RegisterEventEmitter(eventEmitter); systemScheduleManager = new ScheduleManager((ILogger)(object)logger, 0); serviceProvider.RegisterSystemScheduleManager(systemScheduleManager); systemScheduleManager.NewPeriodicTask(new PeriodicTaskData { periodicAction = FlushLog, finishAction = FlushLog, periodInSec = 5f }, false); scheduleManager = new ScheduleManager((ILogger)(object)logger, 0); serviceProvider.RegisterScheduleManager(scheduleManager); translationService = new TranslationService(); translationService.LoadData(); commandListArgManager = new CommandListArgManager(); serviceProvider.RegisterCommandListArgManager(commandListArgManager); commandListArgManager.LoadCommandsList(); ChaosItemManager chaosItemManager = new ChaosItemManager(); serviceProvider.RegisterItemManager(chaosItemManager); chaosItemManager.LoadAllObjects(); enemySpawner = new ChaosEnemySpawner(); serviceProvider.RegisterEnemySpawner(enemySpawner); } private void InitReaders() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown console = new UtilityConsole((IDebugLogger)(object)logger, (List<string>)null); eventsParser = (IEventsDataParser)new EventsDataParser((Action<string>)((HelperLog)logger).LogWarning); eventsReader = new WebSocketEventsReader<SettingsData>((Action<IEventsData>)ProcessEvent, eventsParser, (Action<string>)((HelperLog)logger).LogInfo, (Action<string>)((HelperLog)logger).LogInfo, 0.5f, 1f, 0.5f); eventsReader.InitDefaultSocket(Utils.modFolder, "chaostricks_repo", 13715, "127.0.0.1"); eventsReader.OnOpen = delegate { isAppConnected = true; isAppConnectedProcessed = false; }; eventsReader.OnCloseOnlyAfterConnect = delegate { isAppConnected = false; isAppConnectedProcessed = false; }; Action<string> defaultOnConfig = eventsReader.SocketHandler.OnConfigMessage; eventsReader.SocketHandler.OnConfigMessage = delegate(string s) { defaultOnConfig?.Invoke(s); SettingsManager.QueueUpdateSettings(eventsReader.Settings); }; eventsReader.OpenSocket(true); } public void InitCommands(bool needValidate) { //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Expected O, but got Unknown forceEndEvents.Clear(); Type type = typeof(IRepoStandaloneCommand); IEnumerable<Type> enumerable = from p in Assembly.GetExecutingAssembly().GetTypes() where type.IsAssignableFrom(p) && p.IsClass && !p.IsAbstract select p; ((HelperLog)logger).LogInfo((object)$"found {enumerable.Count()} commands"); commands = new Dictionary<string, IRepoStandaloneCommand>(); foreach (Type item2 in enumerable) { IRepoStandaloneCommand repoStandaloneCommand = Activator.CreateInstance(item2) as IRepoStandaloneCommand; if (repoStandaloneCommand != null) { console.RegisterCommand((IConsoleCommand)repoStandaloneCommand); if (commands.ContainsKey(((IConsoleCommand)repoStandaloneCommand).Id)) { ((HelperLog)logger).LogWarning((object)("repeated id command " + ((IConsoleCommand)repoStandaloneCommand).Id + ". The command will replace existed.")); } commands[((IConsoleCommand)repoStandaloneCommand).Id] = repoStandaloneCommand; if (repoStandaloneCommand is IForceEnd item) { forceEndEvents.Add(item); } ((HelperLog)logger).LogInfo((object)("init command '" + ((IConsoleCommand)repoStandaloneCommand).Id + "' complete")); } else { ((HelperLog)logger).LogError((object)("init command '" + ((IConsoleCommand)repoStandaloneCommand).Id + "' failed")); } } ((HelperLog)logger).LogInfo((object)$"found {commands.Count} commands and {forceEndEvents.Count} timers"); ((HelperLog)logger).LogInfo((object)"init HelperCommandManager"); commandManager = (ICommandManager)new HelperCommandManagerFormatted((IDebugLogger)(object)logger); commandManager.InitFromFile(Utils.GetRelativeModFilePath("commands.data")); int num = commandManager.GetCommands().Length; ((HelperLog)logger).LogInfo((object)$"found {num} events"); if (!needValidate) { return; } ((HelperLog)logger).LogInfo((object)"validate commands"); string[] array = commandManager.GetCommands(); foreach (string text in array) { if (!console.IsValidCommandLine(text?.Trim())) { ((HelperLog)logger).LogError((object)("Command line '" + text + "' invalid")); } } ((HelperLog)logger).LogInfo((object)"init HelperCommandManager ends"); } private void ProcessEvent(IEventsData data) { string eventID = data.EventID; if (string.IsNullOrEmpty(eventID)) { ((HelperLog)logger).LogError((object)"ProcessEvent eventID is null or empty"); return; } if (!GameUtils.IsMaster && ChaosModNetwork.NeedRunFromHost(eventID)) { ((HelperLog)logger).LogInfo((object)("Try to execute network event: '" + eventID + "'")); ChaosModNetwork.RequestClientEventRPC(GameUtils.LocalPlayer.photonView.ViewID, eventID); return; } ((HelperLog)logger).LogInfo((object)("Try to execute event: '" + eventID + "'")); string text = commandManager.GetCommandData(eventID, true)?.Trim(); try { ((HelperLog)logger).LogInfo((object)("Command: " + text)); if (console.RunCommand(text, data, (Action<string>)null)) { ((HelperLog)logger).LogInfo((object)("Event '" + data.EventID + "' executing is completed")); string trans = translationService.translation.GetTrans(data.EventID, data.Lang); string trans2 = translationService.translation.GetTrans("%template_msg%", data.Lang); string message = data.Username + " " + trans2 + " '" + trans + "'"; GameUtils.SendTruckChatMessage(message); GameUtils.ShowUIMessage(message); msgType = !msgType; } else { ((HelperDebugLog)logger).LogDebugError((object)("Event '" + data.EventID + "' executing is failed")); } } catch (Exception arg) { ((HelperLog)logger).LogError((object)$"ProcessCommands '{data.EventID}' unexpected error: {arg}"); } } private void OnLevelGenerated() { try { ((HelperLog)Utils.logger).LogInfo((object)"OnLevelGenerated triggered"); SemiFunc_EnemySpawnPatcher.ClearBlockEnemies(); enemySpawner?.ClearSpawnedEnemies(); } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"OnLevelGenerated {arg}"); } } private void OnMenuLevel() { try { ((HelperLog)Utils.logger).LogInfo((object)"OnMenuLevel triggered"); ChaosInputManager.UnblockAll(); ChaosInputManager.UnholdAll(); SemiFunc_EnemySpawnPatcher.ClearBlockEnemies(); enemySpawner?.ClearSpawnedEnemies(); foreach (IForceEnd forceEndEvent in forceEndEvents) { try { forceEndEvent.ForceEnd(); } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"OnMenuLevel force end for {((IConsoleCommand)forceEndEvent).Id} error: {arg}"); } } } catch (Exception arg2) { ((HelperLog)Utils.logger).LogError((object)$"OnMenuLevel {arg2}"); } } private bool IsReadyForCheckEvent() { try { bool generated = LevelGenerator.Instance.Generated; if (generated != isLevelGeneratedLastCheck && generated) { OnLevelGenerated(); } isLevelGeneratedLastCheck = generated; bool flag = SemiFunc.MenuLevel(); if (flag != isMenuLevelLastCheck && flag) { OnMenuLevel(); } isMenuLevelLastCheck = flag; if (!generated || flag) { return false; } try { if (!GameUtils.AnyPlayerAlive()) { return false; } } catch (Exception arg) { limitedLogger.LogError($"IsReadyForCheckEvent alive check error: {arg}"); } return true; } catch (Exception arg2) { limitedLogger.LogError($"IsReadyForCheckEvent error: {arg2}"); } return false; } public void Update() { try { float deltaTime = Time.deltaTime; systemScheduleManager.OnUpdate(deltaTime); SettingsManager.OnUpdate(); if (IsReadyForCheckEvent()) { enemySpawner.OnUpdate(deltaTime); scheduleManager.OnUpdate(deltaTime); eventEmitter.TriggerOnUpdateEvent(this, deltaTime); ((EventsReaderOnFrame)eventsReader).ReadAndProcessAllWithDelayOnFrame(deltaTime); ChaosModNetwork.ProcessNetworkEvents(commandManager, commands); } } catch (Exception arg) { limitedLogger.LogError($"OnUpdate error: {arg}"); } } internal void ReinitMod() { try { ((HelperLog)logger).LogInfo((object)"ReinitMod starts"); FlushLog(); OnMenuLevel(); commandListArgManager.LoadCommandsList(); InitCommands(needValidate: false); ((HelperLog)logger).LogInfo((object)"ReinitMod ends"); } catch (Exception arg) { ((HelperLog)logger).LogError((object)$"ReinitMod error: {arg}"); } FlushLog(); } } internal sealed class JsonParser : IJsonUtil { public T FromFile<T>(string path) where T : class { using StreamReader streamReader = new StreamReader(path); return FromString<T>(streamReader.ReadToEnd()); } public T FromString<T>(string s) where T : class { return JsonConvert.DeserializeObject<T>(s); } } internal static class CoroutineUtils { [CompilerGenerated] private sealed class <ActionCoroutine>d__1 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float delayInSec; public Action action; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ActionCoroutine>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (delayInSec == 0f) { <>2__current = null; <>1__state = 1; return true; } <>2__current = (object)new WaitForSeconds(delayInSec); <>1__state = 2; return true; case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; } try { action(); } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"ActionCoroutine for {delayInSec} error: {arg}"); } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ActionCoroutineInFrames>d__3 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public int delayInFrames; public Action action; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ActionCoroutineInFrames>d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (delayInFrames > 0) { int num = delayInFrames - 1; delayInFrames = num; <>2__current = null; <>1__state = 1; return true; } try { action(); } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"ActionCoroutineInFrames for {delayInFrames} error: {arg}"); } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <WhileCoroutine>d__5 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float repeatDelayInSec; public Func<bool> action; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WhileCoroutine>d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; bool flag; try { flag = action(); } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"ActionCoroutine for {repeatDelayInSec} error: {arg}"); flag = false; } if (!flag) { return false; } } else { <>1__state = -1; } <>2__current = (object)new WaitForSeconds(repeatDelayInSec); <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal static void StartCoroutine(MonoBehaviour script, float delayInSec, Action action) { if ((Object)(object)script == (Object)null) { return; } if (action == null) { ((HelperLog)Utils.logger).LogError((object)"StartCoroutine got null action"); return; } if (delayInSec < 0f) { delayInSec = 0f; ((HelperLog)Utils.logger).LogWarning((object)$"StartCoroutine got invalid delay {delayInSec}"); } script.StartCoroutine(ActionCoroutine(delayInSec, action)); } [IteratorStateMachine(typeof(<ActionCoroutine>d__1))] private static IEnumerator ActionCoroutine(float delayInSec, Action action) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ActionCoroutine>d__1(0) { delayInSec = delayInSec, action = action }; } internal static void StartCoroutineInFrames(MonoBehaviour script, int delayInFrames, Action action) { if ((Object)(object)script == (Object)null) { return; } if (action == null) { ((HelperLog)Utils.logger).LogError((object)"StartCoroutineInFrames got null action"); return; } if (delayInFrames <= 0) { ((HelperLog)Utils.logger).LogWarning((object)$"StartCoroutineInFrames got invalid delay in frames {delayInFrames}. Replaced to 1."); delayInFrames = 1; } script.StartCoroutine(ActionCoroutineInFrames(delayInFrames, action)); } [IteratorStateMachine(typeof(<ActionCoroutineInFrames>d__3))] private static IEnumerator ActionCoroutineInFrames(int delayInFrames, Action action) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ActionCoroutineInFrames>d__3(0) { delayInFrames = delayInFrames, action = action }; } internal static void StartCoroutineWhile(MonoBehaviour script, float repeatDelayInSec, Func<bool> action) { if ((Object)(object)script == (Object)null) { return; } if (action == null) { ((HelperLog)Utils.logger).LogError((object)"StartCoroutine got null action"); return; } if (repeatDelayInSec < 0f) { repeatDelayInSec = 0f; ((HelperLog)Utils.logger).LogWarning((object)$"StartCoroutine got invalid delay {repeatDelayInSec}"); } script.StartCoroutine(WhileCoroutine(repeatDelayInSec, action)); } [IteratorStateMachine(typeof(<WhileCoroutine>d__5))] private static IEnumerator WhileCoroutine(float repeatDelayInSec, Func<bool> action) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WhileCoroutine>d__5(0) { repeatDelayInSec = repeatDelayInSec, action = action }; } } internal static class GameUtils { internal struct Coords { public Vector3 pos; public Quaternion rot; } internal static PlayerAvatar LocalPlayer { get { PlayerController instance = PlayerController.instance; if ((Object)(object)instance == (Object)null) { return null; } return instance.playerAvatarScript; } } internal static IEnumerable<PlayerAvatar> Players => from p in SemiFunc.PlayerGetAll() where (Object)(object)p != (Object)null select p; internal static List<PlayerAvatar> AlivePlayers => Players.Where(IsPlayerAlive).ToList(); internal static List<PlayerAvatar> DeadPlayers => Players.Where(IsPlayerDead).ToList(); internal static bool IsMaster { get { if (GameManager.Multiplayer()) { return PhotonNetwork.IsMasterClient; } return true; } } internal static Vector3 GetPlayerForward(float length = 1f) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return GetPlayerForward(((Component)LocalPlayer).transform, length); } internal static Vector3 GetForwardOffset(float length = 1f, float height = 0.5f) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) return GetForwardOffset(((Component)LocalPlayer).transform, length, height); } internal static Vector3 GetPlayerForward(Transform tr, float length = 1f) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) Vector3 position = tr.position; Vector3 forward = tr.forward; return position + ((Vector3)(ref forward)).normalized * length; } internal static Vector3 GetForwardOffset(Transform tr, float length = 1f, float height = 0.5f) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) Vector3 forward = tr.forward; return ((Vector3)(ref forward)).normalized * length + new Vector3(0f, height, 0f); } internal static void SetHealthPercentage(PlayerAvatar player, float percents, bool keepAlive) { //IL_0144: Unknown result type (might be due to invalid IL or missing references) if (percents < 0f) { percents = 0f; ((HelperLog)Utils.logger).LogWarning((object)"SetHealth got negative percents value"); } if ((Object)(object)player == (Object)null) { ((HelperLog)Utils.logger).LogWarning((object)"SetHealth got null player"); return; } if ((Object)(object)player.playerHealth == (Object)null) { ((HelperLog)Utils.logger).LogWarning((object)"SetHealth playerHealth null"); return; } if (!((Behaviour)player.playerHealth).enabled) { ((HelperLog)Utils.logger).LogWarning((object)"SetHealth playerHealth disabled"); } int playerMaxHealth = GetPlayerMaxHealth(player.playerHealth); int playerHealth = GetPlayerHealth(player.playerHealth); int num = (int)Math.Ceiling((float)playerMaxHealth * (percents / 100f)); if (keepAlive && num <= 0) { num = 1; } if (playerHealth != num) { if (playerHealth < num) { int num2 = num - playerHealth; ((HelperLog)Utils.logger).LogInfo((object)$"SetHealth calc playerHealth heal: {num2} from {playerHealth} to {num} with keep alive {keepAlive}"); player.playerHealth.HealOther(num2, true); } else { int num3 = playerHealth - num; ((HelperLog)Utils.logger).LogInfo((object)$"SetHealth calc playerHealth damage: {num3} from {playerHealth} to {num} with kill {keepAlive}"); player.playerHealth.HurtOther(num3, Vector3.zero, false, -1); } } } internal static void SetHealthAmount(PlayerAvatar player, int amount, bool keepAlive) { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) if (amount < 0) { ((HelperLog)Utils.logger).LogWarning((object)"SetHealthAmount got negative amount value"); return; } if ((Object)(object)player == (Object)null) { ((HelperLog)Utils.logger).LogWarning((object)"SetHealthAmount got null player"); return; } if ((Object)(object)player.playerHealth == (Object)null) { ((HelperLog)Utils.logger).LogWarning((object)"SetHealthAmount playerHealth null"); return; } if (!((Behaviour)player.playerHealth).enabled) { ((HelperLog)Utils.logger).LogWarning((object)"SetHealthAmount playerHealth disabled"); } int playerHealth = GetPlayerHealth(player.playerHealth); if (playerHealth == amount) { return; } if (playerHealth < amount) { int num = amount - playerHealth; ((HelperLog)Utils.logger).LogInfo((object)$"SetHealthAmount calc playerHealth heal: {num} from {playerHealth} to {amount}"); player.playerHealth.HealOther(num, true); return; } int num2 = amount; if (keepAlive && num2 <= 0) { num2 = 1; } int num3 = playerHealth - num2; ((HelperLog)Utils.logger).LogInfo((object)$"SetHealthAmount calc playerHealth damage: {num3} from {playerHealth} to {num2}"); player.playerHealth.HurtOther(num3, Vector3.zero, false, -1); } internal static string GetPlayerName(PlayerAvatar player) { return Traverse.Create((object)player).Field("playerName").GetValue<string>() ?? ""; } internal static int GetPlayerMaxHealth(PlayerHealth health) { return Traverse.Create((object)health).Field("maxHealth").GetValue<int>(); } internal static int GetPlayerHealth(PlayerHealth health) { return Traverse.Create((object)health).Field("health").GetValue<int>(); } internal static bool IsPlayerDead(PlayerAvatar p) { return Traverse.Create((object)p).Field("isDisabled").GetValue<bool>(); } internal static bool IsPlayerAlive(PlayerAvatar p) { return !IsPlayerDead(p); } internal static int GetAlivePlayersCount() { return Players.Select(IsPlayerAlive).Count(); } internal static bool AnyPlayerAlive() { return Players.Any(IsPlayerAlive); } internal static List<PlayerAvatar> GetAlivePlayerEventTargets(bool isMultiplayer) { if (isMultiplayer) { return AlivePlayers; } if (IsPlayerAlive(LocalPlayer)) { return new List<PlayerAvatar> { LocalPlayer }; } return new List<PlayerAvatar>(); } internal static List<PlayerAvatar> GetDeadPlayerEventTargets(bool isMultiplayer) { if (isMultiplayer) { return DeadPlayers; } if (IsPlayerDead(LocalPlayer)) { return new List<PlayerAvatar> { LocalPlayer }; } return new List<PlayerAvatar>(); } internal static List<PlayerAvatar> GetPlayerEventTargets(bool isMultiplayer) { if (isMultiplayer) { return Players.ToList(); } return new List<PlayerAvatar> { LocalPlayer }; } internal static bool IsLocalPlayer(PlayerAvatar player) { if (GameManager.Multiplayer() && !((Object)(object)player.photonView == (Object)null)) { return player.photonView.IsMine; } return true; } internal static void TeleportPlayer(PlayerAvatar player, Vector3 pos, Quaternion rot) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (IsLocalPlayer(player)) { PlayerController instance = PlayerController.instance; instance.Kinematic(0.5f); instance.InputDisable(0.5f); instance.CollisionController.ResetFalling(); instance.VelocityRelative = Vector3.zero; instance.Velocity = Vector3.zero; Traverse.Create((object)instance).Field<bool>("VelocityIdle").Value = true; CoroutineUtils.StartCoroutine((MonoBehaviour)(object)instance, 0.2f, delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) player.Spawn(pos, rot); }); } else { player.Spawn(pos, rot); } } internal static GameObject SpawnItem(string name, Vector3 spawnPos, Quaternion rot, bool needLog = true) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) ChaosItemManager.SpawnItem spawnItem = ServiceProvider.inst.itemManager.GetSpawnItem(name); if (SemiFunc.IsMasterClient()) { if (needLog) { ((HelperLog)Utils.logger).LogInfo((object)("master network spawn item '" + spawnItem.name + "'")); } if (string.IsNullOrEmpty(spawnItem.name)) { ((HelperLog)Utils.logger).LogError((object)"master network spawn item invalid path"); return null; } return PhotonNetwork.InstantiateRoomObject(spawnItem.path, spawnPos, rot, (byte)0, (object[])null); } if (!SemiFunc.IsMultiplayer()) { if (needLog) { ((HelperLog)Utils.logger).LogInfo((object)("single mode spawn item '" + spawnItem.name + "'")); } if ((Object)(object)spawnItem.prefab == (Object)null) { ((HelperLog)Utils.logger).LogError((object)"single mode spawn item invalid prefab"); return null; } return Object.Instantiate<GameObject>(spawnItem.prefab, spawnPos, rot); } return null; } internal static void RegisterItemInGame(string assetName) { if (string.IsNullOrEmpty(assetName) || !assetName.StartsWith("Item ")) { return; } StatsManager instance = StatsManager.instance; Dictionary<string, Item> itemDictionary = instance.itemDictionary; if (itemDictionary != null && itemDictionary.ContainsKey(assetName)) { ((HelperLog)Utils.logger).LogInfo((object)"register item"); if (instance.itemsPurchased.TryGetValue(assetName, out var value)) { instance.itemsPurchased[assetName] = value + 1; } else { instance.itemsPurchased[assetName] = 1; } if (instance.itemsPurchasedTotal.TryGetValue(assetName, out var value2)) { instance.itemsPurchasedTotal[assetName] = value2 + 1; } else { instance.itemsPurchasedTotal[assetName] = 1; } } else { ((HelperLog)Utils.logger).LogWarning((object)"registering item in game is skipped"); } } internal static void ChargeItem(GameObject obj, float delayInSec, int amount) { if (!((Object)(object)obj == (Object)null)) { ItemBattery battery = obj.GetComponentInParent<ItemBattery>(); CoroutineUtils.StartCoroutine((MonoBehaviour)(object)battery, delayInSec, delegate { int num = amount; bool flag = true; Traverse obj2 = Traverse.Create((object)battery); _ = obj2.Field<PhotonView>("photonView").Value; obj2.Method("BatteryFullPercentChange", new object[2] { num, flag }).GetValue(); }); } } internal static T GetRandomLevelPoint<T>(IEnumerable<T> points, T lastUsedPoint, bool useLastUsedPointIfNoOthers = true, bool needLog = true) { HashSet<T> pointsToIgnore = new HashSet<T> { lastUsedPoint }; T randomLevelPoint = GetRandomLevelPoint(points, pointsToIgnore, needLog); if (randomLevelPoint == null && useLastUsedPointIfNoOthers) { return lastUsedPoint; } return randomLevelPoint; } internal static T GetRandomLevelPoint<T>(IEnumerable<T> points, HashSet<T> pointsToIgnore, bool needLog = true) { List<T> list = points.Where((T p) => p != null && !pointsToIgnore.Contains(p)).ToList(); if (list.Count == 0) { if (needLog) { ((HelperLog)Utils.logger).LogError((object)"can't find points"); } return default(T); } if (needLog) { ((HelperLog)Utils.logger).LogInfo((object)$"found {list.Count()} valid points of total {points.Count()}"); } if (list.Count == 1) { return list[0]; } return UtilityRandom.GetRandomItemFromList<T>((IList<T>)list); } internal static GameObject GetClosestObjectByTag(Vector3 pos, string tag, Func<GameObject, bool> filter, bool needLog = true) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if (tag == null) { return null; } GameObject[] array = GameObject.FindGameObjectsWithTag(tag); int num = array.Length; if (needLog) { ((HelperLog)Utils.logger).LogInfo((object)$"GetClosestObjectByTag {tag} found {num}"); } if (num == 0) { return null; } if (filter != null) { array = array.Where(filter).ToArray(); num = array.Length; if (needLog) { ((HelperLog)Utils.logger).LogInfo((object)$"GetClosestObjectByTag filtered size {num}"); } } if (num == 1) { return array[0]; } GameObject val = array[0]; Vector3 val2 = pos - val.transform.position; float num2 = ((Vector3)(ref val2)).sqrMagnitude; for (int i = 1; i < num; i++) { GameObject val3 = array[i]; val2 = pos - val3.transform.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num2) { val = val3; num2 = sqrMagnitude; } } return val; } internal static ValuableObject GetClosestValuableObject(Vector3 pos, Func<ValuableObject, bool> filter, bool needLog = true) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) ValuableObject[] array = Object.FindObjectsOfType<ValuableObject>(); int num = array.Length; if (needLog) { ((HelperLog)Utils.logger).LogInfo((object)$"GetClosestValuableObject found {num}"); } if (num == 0) { return null; } if (filter != null) { array = array.Where(filter).ToArray(); num = array.Length; if (needLog) { ((HelperLog)Utils.logger).LogInfo((object)$"GetClosestValuableObject filtered size {num}"); } } if (num == 1) { return array[0]; } ValuableObject val = array[0]; Vector3 val2 = pos - ((Component)val).transform.position; float num2 = ((Vector3)(ref val2)).sqrMagnitude; for (int i = 1; i < num; i++) { ValuableObject val3 = array[i]; val2 = pos - ((Component)val3).transform.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num2) { val = val3; num2 = sqrMagnitude; } } return val; } internal static GameObject GetClosestCart(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return GetClosestObjectByTag(pos, "Cart", (GameObject item) => (Object)(object)item.GetComponentInParent<PhysGrabCart>() != (Object)null); } internal static GameObject[] GetObjectsByTag(string tag, Func<GameObject, bool> filter, bool needLog = true) { if (tag == null) { return (GameObject[])(object)new GameObject[0]; } GameObject[] array = GameObject.FindGameObjectsWithTag(tag); int num = array.Length; if (needLog) { ((HelperLog)Utils.logger).LogInfo((object)$"GetObjectsByTag found {num}"); } if (num == 0) { return (GameObject[])(object)new GameObject[0]; } if (filter != null) { array = array.Where(filter).ToArray(); num = array.Length; if (needLog) { ((HelperLog)Utils.logger).LogInfo((object)$"GetObjectsByTag filtered size {num}"); } } return array; } internal static GameObject[] GetCarts() { return GetObjectsByTag("Cart", (GameObject item) => (Object)(object)item.GetComponentInParent<PhysGrabCart>() != (Object)null); } internal static List<CartObject> GetCartItems(GameObject cart) { PhysGrabCart componentInParent = cart.GetComponentInParent<PhysGrabCart>(); if ((Object)(object)componentInParent == (Object)null) { ((HelperLog)Utils.logger).LogWarning((object)"can't find PhysGrabCart"); return null; } if ((Object)(object)componentInParent.physGrabInCart == (Object)null) { ((HelperLog)Utils.logger).LogWarning((object)"can't find PhysGrabCart"); return null; } List<CartObject> value = Traverse.Create((object)componentInParent.physGrabInCart).Field<List<CartObject>>("inCartObjects").Value; if (value == null) { ((HelperLog)Utils.logger).LogWarning((object)"inCartObjects null"); return null; } return value; } internal static Enemy[] GetEnemies() { return Object.FindObjectsOfType<Enemy>(); } internal static Enemy GetClosestEnemy(Vector3 pos) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) Enemy[] array = Object.FindObjectsOfType<Enemy>(); int num = array.Length; ((HelperLog)Utils.logger).LogInfo((object)$"found {num} enemies"); switch (num) { case 0: return null; case 1: return array[0]; default: { Enemy val = array[0]; Vector3 val2 = pos - ((Component)val).transform.position; float num2 = ((Vector3)(ref val2)).sqrMagnitude; for (int i = 1; i < num; i++) { Enemy val3 = array[i]; val2 = pos - ((Component)val3).transform.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num2) { val = val3; num2 = sqrMagnitude; } } return val; } } } internal static void ActivateTumble(PlayerTumble tumble, PlayerAvatar p, Vector3 force, float rotatePower) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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) tumble.TumbleForce(force); tumble.TumbleTorque(((Component)tumble).transform.right * rotatePower); try { Traverse.Create((object)tumble).Method("BreakFree", new object[1] { p.localCameraTransform.forward }).GetValue(); } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"BreakFree error: {arg}"); } tumble.TumbleSet(true, false); } internal static ExtractionPoint GetCurrentExtractionPoint() { return Traverse.Create((object)RoundDirector.instance).Field<ExtractionPoint>("extractionPointCurrent").Value; } internal static Dictionary<RoomVolume, List<LevelPoint>> GetLevelPointsByRoom(bool excludePlayerRooms) { Dictionary<RoomVolume, List<LevelPoint>> dictionary = new Dictionary<RoomVolume, List<LevelPoint>>(); List<LevelPoint> list = SemiFunc.LevelPointsGetAll(); List<LevelPoint> list2 = (excludePlayerRooms ? SemiFunc.LevelPointsGetInPlayerRooms() : new List<LevelPoint>()); if (list == null) { return dictionary; } foreach (LevelPoint item in list) { if (!((Object)(object)item == (Object)null) && (!excludePlayerRooms || !list2.Contains(item))) { if (!dictionary.TryGetValue(item.Room, out var value)) { value = new List<LevelPoint>(); dictionary[item.Room] = value; } value.Add(item); } } return dictionary; } internal static List<LevelPoint> GetLevelPoints(bool excludePlayerRooms) { List<LevelPoint> list = SemiFunc.LevelPointsGetAll(); if (excludePlayerRooms) { List<LevelPoint> playerRoomPoints = SemiFunc.LevelPointsGetInPlayerRooms(); return list.Where((LevelPoint p) => !playerRoomPoints.Contains(p)).ToList(); } return list; } internal static Vector3 GetPlayerSpawnPoint() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) return ((Component)Object.FindFirstObjectByType<SpawnPoint>()).transform.position; } internal static Vector3[] GetPlayerSpawnPoints() { return (from p in Object.FindObjectsOfType<SpawnPoint>() where (Object)(object)((Component)p).transform != (Object)null select ((Component)p).transform.position).ToArray(); } internal static Vector3 GetFreeOfPlayersFarPointFrom(Vector3 start) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) List<LevelPoint> levelPoints = GetLevelPoints(excludePlayerRooms: true); Vector3 result = start; float num = 0f; foreach (LevelPoint item in levelPoints) { Vector3 val = ((Component)item).transform.position - start; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude > num) { num = sqrMagnitude; result = ((Component)item).transform.position; } } return result; } public static Vector3 GetClosestSpawnPointTo(Vector3 start) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) List<LevelPoint> levelPoints = GetLevelPoints(excludePlayerRooms: true); Vector3 result = start; float num = float.MaxValue; foreach (LevelPoint item in levelPoints) { Vector3 val = ((Component)item).transform.position - start; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = ((Component)item).transform.position; } } return result; } internal static void SendTruckChatMessage(string message) { TruckScreenText instance = TruckScreenText.instance; if ((Object)(object)instance == (Object)null) { ((HelperLog)Utils.logger).LogWarning((object)"TruckScreenText null"); } else { instance.MessageSendCustom("", "{arrowright}" + message + "{arrowleft}", 0); } } internal static void SendPlayerTTS(string message, bool crouching) { PlayerAvatar localPlayer = LocalPlayer; if (!((Object)(object)localPlayer == (Object)null)) { Traverse.Create((object)localPlayer).Method("ChatMessageSpeak", new object[2] { message, crouching }).GetValue(); } } internal static void ShowUIMessage(string message) { //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) MissionUI instance = MissionUI.instance; if ((Object)(object)instance == (Object)null) { ((HelperLog)Utils.logger).LogWarning((object)"MissionUI null"); } else { instance.MissionText(message, Color.magenta, Color.magenta, 5f); } } } internal static class Utils { internal static readonly Random rnd = new Random(Guid.NewGuid().GetHashCode()); internal static readonly string modFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); private const string LOG_FNAME = "latest_log.txt"; private static readonly string logPath = Path.Combine(modFolder, "latest_log.txt"); internal static readonly BufferedLogger logger = new BufferedLogger(modFolder, "latest_log.txt", false, 50); internal static void LogClearBySize() { FileInfo fileInfo = new FileInfo(logPath); if (fileInfo.Exists && fileInfo.Length > 200000) { ((HelperLog)logger).LogClear(); } } internal static string GetRelativeModFilePath(string fname) { return Path.Combine(modFolder, fname); } internal static List<T> Shuffle<T>(IEnumerable<T> list) { if (list == null) { return new List<T>(); } int num = list.Count(); if (num <= 1) { return new List<T>(list); } List<T> list2 = new List<T>(list); for (int i = 0; i < num; i++) { T value = list2[i]; int index = rnd.Next(num); list2[i] = list2[index]; list2[index] = value; } return list2; } internal static List<T> ShuffleForceRandom<T>(IEnumerable<T> list) { if (list == null) { return new List<T>(); } int num = list.Count(); if (num <= 1) { return new List<T>(list); } T[] array = new T[num]; T[] array2 = list.ToArray(); List<int> list2 = new List<int>(Enumerable.Range(0, num)); for (int i = 0; i < num; i++) { List<int> list3 = new List<int>(list2); list3.Remove(i); if (list3.Count == 0) { break; } int num2 = list3[rnd.Next(list3.Count)]; array[i] = array2[num2]; list2.Remove(num2); } if (list2.Count == 1) { int num3 = num - 1; int num4 = rnd.Next(num3); array[num3] = array[num4]; array[num4] = array2[num3]; } return array.ToList(); } internal static float GetRandomBetween(float min, float max) { return min + (float)((double)(max - min) * rnd.NextDouble()); } } } namespace REPO_BFT_BepInEx.Services { internal class ChaosEnemySpawner { internal struct EnemyData { public GameObject prefab; public string name; public string path; } private const string BASE_ENEMY_PATH = "Enemies/Enemy - "; private readonly Dictionary<string, EnemyData> enemyPrefabs = new Dictionary<string, EnemyData>(); private int spawnedCount; private readonly List<EnemyParent> spawnedEnemies = new List<EnemyParent>(); private float spawnsCheckInSec; internal void RegisterSpawnedEnemyFinished(Enemy enemy) { CoroutineUtils.StartCoroutine((MonoBehaviour)(object)enemy, 0f, delegate { EnemyParent componentInParent = ((Component)enemy).GetComponentInParent<EnemyParent>(); if ((Object)(object)componentInParent == (Object)null) { ((HelperLog)Utils.logger).LogWarning((object)"EnemyParent null. Fix despawning is skipped"); } else { spawnedEnemies.Add(componentInParent); } }); } internal void ClearSpawnedEnemies() { spawnedEnemies.Clear(); } internal void OnUpdate(float dtInSec) { spawnsCheckInSec -= dtInSec; if (spawnsCheckInSec > 0f) { return; } spawnsCheckInSec = 0.5f; foreach (EnemyParent spawnedEnemy in spawnedEnemies) { if ((Object)(object)spawnedEnemy != (Object)null && spawnedEnemy.DespawnedTimer > 0f) { spawnedEnemy.DespawnedTimer = 60f; } } } internal Enemy SpawnEnemy(string enemyName, Vector3 spawnPoint) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(enemyName)) { ((HelperLog)Utils.logger).LogError((object)"SpawnEnemy invalid name"); return null; } EnemyData enemyPrefab = GetEnemyPrefab(enemyName); GameObject prefab = enemyPrefab.prefab; if ((Object)(object)prefab == (Object)null) { ((HelperLog)Utils.logger).LogError((object)("SpawnEnemy can't find enemy prefab: path '" + enemyPrefab.path + "', name '" + enemyName + "'")); return null; } RunManager.instance.EnemiesSpawnedRemoveStart(); Enemy val = LevelGeneratorEnemySpawn(prefab, enemyPrefab.path, spawnPoint); if ((Object)(object)val == (Object)null) { ((HelperLog)Utils.logger).LogWarning((object)"ChaosEnemySpawner->SpawnEnemy Enemy component is null"); } else { ((Object)val).name = $"Chaos Tricks custom mob [{enemyName}] [{spawnedCount++}]"; foreach (PlayerAvatar player in GameUtils.Players) { val.PlayerAdded(player.photonView.ViewID); } } SemiFunc_EnemySpawnPatcher.AddEnemyToBlockInGameSpawn(val); RunManager.instance.EnemiesSpawnedRemoveEnd(); return val; } private Enemy LevelGeneratorEnemySpawn(GameObject prefab, string path, Vector3 position) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) GameObject val = ((GameManager.instance.gameMode != 0) ? PhotonNetwork.InstantiateRoomObject(path, position, Quaternion.identity, (byte)0, (object[])null) : Object.Instantiate<GameObject>(prefab, position, Quaternion.identity)); EnemyParent component = val.GetComponent<EnemyParent>(); if (Object.op_Implicit((Object)(object)component)) { Traverse.Create((object)component).Field<bool>("SetupDone").Value = true; Enemy componentInChildren = val.GetComponentInChildren<Enemy>(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.EnemyTeleported(position); Traverse<int> obj = Traverse.Create((object)LevelGenerator.Instance).Field<int>("EnemiesSpawnTarget"); int value = obj.Value; obj.Value = value + 1; EnemyDirector.instance.FirstSpawnPointAdd(component); } return componentInChildren; } ((HelperLog)Utils.logger).LogWarning((object)("LevelGeneratorEnemySpawn can't find EnemyParent component for '" + path + "'")); return null; } private EnemyData GetEnemyPrefab(string name) { if (enemyPrefabs.TryGetValue(name, out var value) && (Object)(object)value.prefab != (Object)null) { return value; } string enemyPath = GetEnemyPath(name); EnemyData enemyData = default(EnemyData); enemyData.name = name; enemyData.path = enemyPath; enemyData.prefab = Resources.Load<GameObject>(enemyPath); EnemyData enemyData2 = enemyData; enemyPrefabs[name] = enemyData2; return enemyData2; } private string GetEnemyPath(string name) { return "Enemies/Enemy - " + name; } } internal class ChaosItemManager { internal struct SpawnItem { public GameObject prefab; public string name; public string path; } private readonly Dictionary<string, SpawnItem> prefabs; internal static readonly string itemsBasePath = "Items/"; internal static readonly string removedItemsBasePath = "Items/Removed Items/"; internal static readonly string valuablesBasePath = "Valuables/"; internal static readonly string[] valuableCategories = new string[7] { "01 Tiny", "02 Small", "03 Medium", "04 Big", "05 Wide", "06 Tall", "07 Very Tall" }; internal ChaosItemManager() { prefabs = new Dictionary<string, SpawnItem>(); } internal SpawnItem GetSpawnItem(string name) { if (prefabs.TryGetValue(name, out var value)) { if ((Object)(object)value.prefab != (Object)null) { return value; } value.prefab = Resources.Load<GameObject>(value.path); prefabs[value.name] = value; return value; } SpawnItem result = TryToFindObject(name); if ((Object)(object)result.prefab == (Object)null) { ((HelperLog)Utils.logger).LogError((object)("can't load prefab for '" + name + "'")); } return result; } private void LoadObjects(string basePath) { GameObject[] array = Resources.LoadAll<GameObject>(basePath); foreach (GameObject val in array) { string path = basePath + ((Object)val).name; prefabs[((Object)val).name] = new SpawnItem { prefab = val, name = ((Object)val).name, path = path }; } } internal void LoadAllObjects() { try { LoadObjects(removedItemsBasePath); LoadObjects(itemsBasePath); LoadObjects(valuablesBasePath); string[] array = valuableCategories; foreach (string text in array) { LoadObjects(valuablesBasePath + text + "/"); } } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"ChaosItemManager->LoadAllObjects {arg}"); } } private SpawnItem LoadObjectWithFilter(string basePath, string targetName) { GameObject[] array = Resources.LoadAll<GameObject>(basePath); foreach (GameObject val in array) { if (targetName == ((Object)val).name) { string path = basePath + ((Object)val).name; SpawnItem spawnItem = default(SpawnItem); spawnItem.prefab = val; spawnItem.name = ((Object)val).name; spawnItem.path = path; SpawnItem spawnItem2 = spawnItem; prefabs[((Object)val).name] = spawnItem2; return spawnItem2; } } return default(SpawnItem); } private SpawnItem TryToFindObject(string targetName) { string[] array = valuableCategories; foreach (string text in array) { SpawnItem result = LoadObjectWithFilter(valuablesBasePath + text + "/", targetName); if ((Object)(object)result.prefab != (Object)null) { return result; } } SpawnItem result2 = LoadObjectWithFilter(valuablesBasePath, targetName); if ((Object)(object)result2.prefab != (Object)null) { return result2; } result2 = LoadObjectWithFilter(itemsBasePath, targetName); if ((Object)(object)result2.prefab != (Object)null) { return result2; } return LoadObjectWithFilter(removedItemsBasePath, targetName); } } internal class ChaosModNetwork : MonoBehaviour { internal struct DataSource { public int playerID; public string eventID; } private static ChaosModNetwork inst; private PhotonView photonView; private static Queue<DataSource> commandQueue; private static readonly HashSet<string> shouldBeRunFromHost = new HashSet<string> { "all_buff_hp_average", "all_goal_dec", "all_goal_inc", "solo_debuff_item_boom", "all_debuff_kill_rand", "all_cart_spread", "active_nade_stun", "active_nade_shock", "active_nade_expl", "active_nade_duck", "spawn_duck", "spawn_spewer", "spawn_upscream", "spawn_alien", "spawn_animal", "spawn_baby", "spawn_thinman", "spawn_hidden", "spawn_frog", "spawn_bowtie", "spawn_huntsman", "spawn_head", "spawn_trudge", "spawn_clown", "spawn_robe", "spawn_reaper", "item_health_small", "item_health_med", "item_health_big", "item_crystal", "item_nade_stun", "item_nade_shock", "item_nade_expl", "item_nade_f1", "item_nade_duck_f1", "item_mine_stun", "item_mine_shock", "item_mine_expl", "item_rubber_duck", "item_book_roll", "item_book_speed", "item_book_energy", "item_book_health", "item_book_range", "item_book_strength", "item_book_jump", "item_drone_roll", "item_drone_gravity", "item_drone_feather", "item_drone_energy", "item_drone_shield", "item_sphere_gravity", "item_frying_pan", "item_inflatable_hammer", "item_sword", "item_baseball_bat", "item_sledge_hammer", "item_valuable_tracker", "item_extraction_tracker", "item_cart_small", "item_cart_medium", "item_tranq", "item_handgun", "item_shotgun", "loot_rand_small", "loot_rand_med", "loot_rand_big", "loot_money_rain", "loot_frog", "loot_bottle", "loot_love_potion", "loot_gramophone", "loot_power_crystal", "loot_fan", "loot_clown", "loot_guitar", "loot_propane_tank", "loot_music_box", "loot_television", "loot_flamethrower", "loot_saw", "loot_time_glass", "loot_doll", "loot_barrel", "loot_sword", "loot_staff", "loot_animal_crate", "loot_creature_leg", "loot_ice_block", "loot_broom", "loot_painting", "loot_harp", "loot_grandfather_clock", "loot_golden_statue", "loot_science_station", "loot_server_rack", "loot_dinosaur", "loot_griffin_statue", "loot_piano", "solo_frogs_around", "solo_poop_diamonds", "solo_poop_mines", "solo_poop_nades", "loot_rand_enemy", "all_stun_enemies", "all_cart_teleport_rand", "all_cart_teleport_start", "all_teleport_rand", "solo_teleport_start", "all_teleport_start", "all_teleport_shuffle", "solo_upgrade_roll", "solo_upgrade_speed", "solo_upgrade_energy", "solo_upgrade_health", "solo_upgrade_range", "solo_upgrade_strength", "solo_upgrade_jump" }; private void Awake() { inst = this; photonView = ((Component)this).GetComponent<PhotonView>(); commandQueue = new Queue<DataSource>(); } [PunRPC] private void ActivateEventOtherRPC(string eventID) { ((HelperLog)Utils.logger).LogInfo((object)("ChaosModNetwork->ActivateEventOtherRPC triggered for " + eventID)); } [PunRPC] private void ActivateClientEventRPC(int playerID, string eventID) { ((HelperLog)Utils.logger).LogInfo((object)$"ChaosModNetwork->ActivateClientEventRPC triggered for {playerID} {eventID}"); if (commandQueue == null) { ((HelperLog)Utils.logger).LogError((object)"ChaosModNetwork->ActivateClientEventRPC an attempt to store events before initiating"); return; } commandQueue.Enqueue(new DataSource { eventID = eventID, playerID = playerID }); } internal static void RequestEventOther(string eventID) { ((HelperLog)Utils.logger).LogInfo((object)("ChaosModNetwork->RequestEventOther triggered for " + eventID)); try { inst.photonView.RPC("ActivateEventOtherRPC", (RpcTarget)1, new object[1] { eventID }); } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"ChaosModNetwork->RequestEventOther error: {arg}"); } } internal static void RequestClientEventRPC(int userID, string eventID) { ((HelperLog)Utils.logger).LogInfo((object)$"ChaosModNetwork->RequestClientEventRPC triggered for {userID} {eventID}"); try { inst.photonView.RPC("ActivateClientEventRPC", (RpcTarget)2, new object[2] { userID, eventID }); } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"ChaosModNetwork->RequestClientEventRPC error: {arg}"); } } internal static bool NeedRunFromHost(string eventID) { return shouldBeRunFromHost.Contains(eventID); } internal static void ProcessNetworkEvents(ICommandManager cm, Dictionary<string, IRepoStandaloneCommand> commands) { while (commandQueue.Count > 0) { try { DataSource dataSource = commandQueue.Dequeue(); ((HelperLog)Utils.logger).LogInfo((object)$"ChaosModNetwork->ProcessEvents event id {dataSource.eventID} for {dataSource.playerID}"); PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonID(dataSource.playerID); if ((Object)(object)val == (Object)null) { ((HelperLog)Utils.logger).LogWarning((object)"ChaosModNetwork->ProcessEvents can't find player. Skip event"); continue; } string text = cm.GetCommandData(dataSource.eventID, true)?.Trim(); if (string.IsNullOrEmpty(text)) { ((HelperLog)Utils.logger).LogWarning((object)"ChaosModNetwork->ProcessEvents can't find commands"); } else { ProcessCommandLines(UtilityConsole.ParseCommandLine(text), val, commands); } } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"ChaosModNetwork->ProcessEvents: {arg}"); } } } private static void ProcessCommandLines(string[] lines, PlayerAvatar player, Dictionary<string, IRepoStandaloneCommand> commands) { for (int i = 0; i < lines.Length; i++) { string[] array = UtilityConsole.ParseArgs(lines[i]); string key = array[0]; try { IRepoStandaloneCommand repoStandaloneCommand = commands[key]; if (repoStandaloneCommand is INetworkCommand networkCommand) { networkCommand.Execute(array.Skip(1), player); } else { ((IConsoleCommand)repoStandaloneCommand).Execute(array.Skip(1)); } } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"ChaosModNetwork->ProcessEvents: {arg}"); } } } } internal class CommandListArgManager { internal class Group { [JsonProperty("drop_variants")] public DropVariant[] dropVariants; } internal class DropVariant { public string[] items; } private Dictionary<string, Group> groups; private Dictionary<string, string[]> simpleGroups; internal CommandListArgManager() { } internal void LoadCommandsList() { try { string relativeModFilePath = Utils.GetRelativeModFilePath("drop_groups.data"); groups = UtilityJson.Generate((IDebugLogger)(object)Utils.logger).FromFile<Dictionary<string, Group>>(relativeModFilePath); } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"CommandListArgManager groups init error: {arg}"); } try { string relativeModFilePath2 = Utils.GetRelativeModFilePath("drop_simple_groups.data"); simpleGroups = UtilityJson.Generate((IDebugLogger)(object)Utils.logger).FromFile<Dictionary<string, string[]>>(relativeModFilePath2); } catch (Exception arg2) { ((HelperLog)Utils.logger).LogError((object)$"CommandListArgManager simple groups init error: {arg2}"); } } internal DropVariant GetRandomDropVariant(string groupName) { if (groups == null) { ((HelperLog)Utils.logger).LogWarning((object)"CommandListArgManager groups null"); return null; } if (!groups.TryGetValue(groupName, out var value)) { ((HelperLog)Utils.logger).LogWarning((object)("CommandListArgManager can't find group " + groupName)); return null; } if (value == null || value.dropVariants == null || value.dropVariants.Length == 0) { ((HelperLog)Utils.logger).LogWarning((object)("CommandListArgManager drop variants empty for " + groupName)); return null; } return UtilityRandom.GetRandomItemFromList<DropVariant>((IList<DropVariant>)value.dropVariants); } internal string[] GetRandomDropVariantPaths(string groupName) { DropVariant randomDropVariant = GetRandomDropVariant(groupName); if (randomDropVariant == null || randomDropVariant.items == null) { return new string[0]; } return randomDropVariant.items.Select((string s) => CommandArgsReaderWrapper.ParseItemPath(s)).ToArray(); } internal string GetRandomDropFromSimpleGroup(string groupName) { if (simpleGroups == null) { ((HelperLog)Utils.logger).LogWarning((object)"CommandListArgManager simpleGroups null"); return null; } if (!simpleGroups.TryGetValue(groupName, out var value)) { ((HelperLog)Utils.logger).LogWarning((object)("CommandListArgManager can't find simple group " + groupName)); return null; } return CommandArgsReaderWrapper.ParseItemPath(UtilityRandom.GetRandomItemFromList<string>((IList<string>)value)); } internal bool IsSimpeGroup(string name) { if (simpleGroups != null) { return simpleGroups.ContainsKey(name); } return false; } } internal sealed class EventEmitter { private enum Event { OnUpdate, OnConfigChangedThreadSafe } private class EmitterAction { public string id; public Action<object, object> action; } private readonly ILogger logger = (ILogger)(object)new LimitedLogWrapper(100, (IDebugLogger)(object)Utils.logger); private readonly Dictionary<Event, List<EmitterAction>> eventHandlers; internal EventEmitter() { eventHandlers = new Dictionary<Event, List<EmitterAction>>(); foreach (Event item in Enum.GetValues(typeof(Event)).OfType<Event>()) { eventHandlers[item] = new List<EmitterAction>(); } } private void ReplaceOrAddHandler(Event key, string id, Action<object, object> handler) { if (id != null) { eventHandlers[key].RemoveAll((EmitterAction action) => action.id == id); } eventHandlers[key].Add(new EmitterAction { action = handler, id = id }); } private void TriggerEvent(Event key, object sender, object data) { try { if (!eventHandlers.TryGetValue(key, out var value)) { return; } foreach (EmitterAction item in value) { try { item.action(sender, data); } catch (Exception arg) { logger.LogError((object)$"EventEmitter->TriggerEvent inner {key} error: {arg}"); } } } catch (Exception arg2) { logger.LogError((object)$"EventEmitter->TriggerEvent {key} error: {arg2}"); } } internal void ReplaceOrAddOnUpdateHandler(string id, Action<object, float> handler) { ReplaceOrAddHandler(Event.OnUpdate, id, delegate(object sender, object data) { handler(sender, (float)data); }); } internal void TriggerOnUpdateEvent(object sender, float dtInSec) { TriggerEvent(Event.OnUpdate, sender, dtInSec); } internal void ReplaceOrAddOnConfigChanged_ThreadSafeHandler(string id, Action<object, SettingsData> handler) { ReplaceOrAddHandler(Event.OnConfigChangedThreadSafe, id, delegate(object sender, object settings) { handler(sender, (SettingsData)settings); }); } internal void TriggerOnConfigChangedEvent_ThreadSafe(object sender, SettingsData settings) { TriggerEvent(Event.OnConfigChangedThreadSafe, sender, settings); } } internal static class ExplodeManager { private static GameObject explodePrefab; private static void CheckPrefab() { if ((Object)(object)explodePrefab == (Object)null) { explodePrefab = Resources.Load<GameObject>("Effects/Part Prefab Explosion"); } } private static void InternalExplode(Vector3 pos, float expSize, int expDamage, float forceMult) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) CheckPrefab(); ParticlePrefabExplosion component = Object.Instantiate<GameObject>(explodePrefab, pos, Quaternion.identity).GetComponent<ParticlePrefabExplosion>(); component.forceMultiplier = forceMult; Traverse obj = Traverse.Create((object)component); obj.Field<float>("explosionSize").Value = expSize; obj.Field<int>("explosionDamage").Value = expDamage; } internal static void CreateExplodeNearPlayer(PlayerAvatar player, float offset, float expSize, int expDamage, float forceMult) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) InternalExplode(GameUtils.GetPlayerForward(((Component)player).transform, offset), expSize, expDamage, forceMult); } internal static GameObject ExplodeGrabItem(PlayerAvatar player, float expSize, int expDamage, float forceMult) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) PhysGrabber physGrabber = player.physGrabber; if (!physGrabber.grabbed) { ((HelperLog)Utils.logger).LogInfo((object)"ExplodeGrabItem no item in hands"); return null; } InternalExplode(physGrabber.grabbedObjectTransform.position, expSize, expDamage, forceMult); return ((Component)physGrabber.grabbedObjectTransform).gameObject; } internal static ValuableObject ExplodeClosestItem(PlayerAvatar player, float expSize, int expDamage, float forceMult) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) ValuableObject closestValuableObject = GameUtils.GetClosestValuableObject(((Component)player).transform.position, null); if ((Object)(object)closestValuableObject == (Object)null) { ((HelperLog)Utils.logger).LogInfo((object)"ExplodeGrabItem no item found"); return null; } InternalExplode(((Component)closestValuableObject).transform.position, expSize, expDamage, forceMult); return closestValuableObject; } } internal sealed class ServiceProvider { internal static readonly ServiceProvider inst = new ServiceProvider(); internal ScheduleManager systemScheduleManager; internal ScheduleManager scheduleManager; internal EventEmitter eventEmitter; internal ChaosItemManager itemManager; internal CommandListArgManager commandListArgManager; internal ChaosEnemySpawner enemySpawner; internal void RegisterSystemScheduleManager(ScheduleManager systemScheduleManager) { this.systemScheduleManager = systemScheduleManager; } internal void RegisterScheduleManager(ScheduleManager scheduleManager) { this.scheduleManager = scheduleManager; } internal void RegisterEventEmitter(EventEmitter eventEmitter) { this.eventEmitter = eventEmitter; } internal void RegisterItemManager(ChaosItemManager itemManager) { this.itemManager = itemManager; } internal void RegisterCommandListArgManager(CommandListArgManager commandListArgManager) { this.commandListArgManager = commandListArgManager; } internal void RegisterEnemySpawner(ChaosEnemySpawner enemySpawner) { this.enemySpawner = enemySpawner; } } internal sealed class SettingsData { internal bool ApplySpawnEventsForAll { get; set; } = true; internal bool ApplyEffectEventsForAll { get; set; } = true; } internal static class SettingsManager { private static SettingsData newData; internal static SettingsData Data { get; private set; } = new SettingsData(); internal static void QueueUpdateSettings(SettingsData data) { newData = data; } internal static void OnUpdate() { if (newData != null) { Data = newData; ServiceProvider.inst.eventEmitter.TriggerOnConfigChangedEvent_ThreadSafe(null, newData); newData = null; } } } internal class TranslationService { public readonly ITranslation translation; internal TranslationService() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown translation = (ITranslation)new HelperLanguagesFormatted((IDebugLogger)(object)Utils.logger); } public void LoadData() { translation.InitFromFile(Utils.GetRelativeModFilePath("langs.data")); } } } namespace REPO_BFT_BepInEx.Wrappers { internal class CommandArgsReaderWrapper { private readonly IEnumerator<string> args; private readonly CommandArgsReader reader; public CommandArgsReaderWrapper(IEnumerable<string> args) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown this.args = args?.GetEnumerator(); reader = new CommandArgsReader((ILogger)(object)Utils.logger); } public int ReadInt(int defaultValue = 0) { return reader.ReadInt(args, defaultValue); } public float ReadFloat(float defaultValue = 0f) { return reader.ReadFloat(args, defaultValue); } public string ReadString(string defaultValue = "") { return reader.ReadString(args, defaultValue); } public string ReadSpacedString(string defaultValue = "") { return ParseItemPath(reader.ReadString(args, defaultValue)); } public static string ParseItemPath(string path) { return path?.Replace("_", " "); } public bool ReadBool(bool defaultValue = false) { return reader.ReadBool(args, defaultValue); } } internal class LimitedLogWrapper : IDebugLogger, ILoggerWithConsole, ILogger { private readonly IDebugLogger logger; private int messagesLimit; internal LimitedLogWrapper(int messagesLimit, IDebugLogger logger) { this.logger = logger; this.messagesLimit = messagesLimit; } public void Log(object obj) { if (messagesLimit > 0) { messagesLimit--; ((ILogger)logger).Log(obj); } } public void LogClear() { ((ILogger)logger).LogClear(); } public void LogDebugInfo(object obj) { if (messagesLimit > 0) { messagesLimit--; logger.LogDebugInfo(obj); } } public void LogDebugWarning(object obj) { if (messagesLimit > 0) { messagesLimit--; logger.LogDebugWarning(obj); } } public void LogDebugError(object obj) { if (messagesLimit > 0) { messagesLimit--; logger.LogDebugError(obj); } } public void LogInfo(object obj) { if (messagesLimit > 0) { messagesLimit--; ((ILogger)logger).LogInfo(obj); } } public void LogInfoConsoleOnly(object obj) { if (messagesLimit > 0) { messagesLimit--; ((ILoggerWithConsole)logger).LogInfoConsoleOnly(obj); } } public void LogInfoFileOnly(object obj) { if (messagesLimit > 0) { messagesLimit--; ((ILoggerWithConsole)logger).LogInfoFileOnly(obj); } } public void LogWarning(object obj) { if (messagesLimit > 0) { messagesLimit--; ((ILogger)logger).LogWarning(obj); } } public void LogWarningConsoleOnly(object obj) { if (messagesLimit > 0) { messagesLimit--; ((ILoggerWithConsole)logger).LogWarningConsoleOnly(obj); } } public void LogWarningFileOnly(object obj) { if (messagesLimit > 0) { messagesLimit--; ((ILoggerWithConsole)logger).LogWarningFileOnly(obj); } } public void LogError(object obj) { if (messagesLimit > 0) { messagesLimit--; ((ILogger)logger).LogError(obj); } } public void LogErrorConsoleOnly(object obj) { if (messagesLimit > 0) { messagesLimit--; ((ILoggerWithConsole)logger).LogErrorConsoleOnly(obj); } } public void LogErrorFileOnly(object obj) { if (messagesLimit > 0) { messagesLimit--; ((ILoggerWithConsole)logger).LogErrorFileOnly(obj); } } public void UpdateLimit(int limit) { messagesLimit = limit; } } } namespace REPO_BFT_BepInEx.Patchers { internal static class ChaosInputManager { private static readonly Dictionary<InputKey, bool> blockedKeys = new Dictionary<InputKey, bool>(); private static readonly Dictionary<InputKey, bool> holdKeys = new Dictionary<InputKey, bool>(); internal static float mouseSpeedCoeffX = 1f; internal static float mouseSpeedCoeffY = 1f; internal static void BlockKey(InputKey key) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) blockedKeys[key] = true; } internal static void UnblockKey(InputKey key) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) blockedKeys[key] = false; } internal static void UnblockAll() { blockedKeys.Clear(); } internal static bool IsKeyBlocked(InputKey key) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (blockedKeys.TryGetValue(key, out var value)) { return value; } return false; } internal static void HoldKey(InputKey key) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) holdKeys[key] = true; } internal static void UnholdKey(InputKey key) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) holdKeys[key] = false; } internal static void UnholdAll() { holdKeys.Clear(); } internal static bool IsKeyHold(InputKey key) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (holdKeys.TryGetValue(key, out var value)) { return value; } return false; } } [HarmonyPatch(typeof(InputManager), "KeyDown")] internal class InputManager_KeyDownPatcher { private static bool Prefix(ref bool __result, InputKey key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (ChaosInputManager.IsKeyBlocked(key)) { __result = false; return false; } return true; } } [HarmonyPatch(typeof(InputManager), "KeyHold")] internal class InputManager_KeyHoldPatcher { internal static bool Prefix(ref bool __result, InputKey key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (ChaosInputManager.IsKeyBlocked(key)) { __result = false; return false; } if (ChaosInputManager.IsKeyHold(key)) { __result = true; return false; } return true; } } [HarmonyPatch(typeof(InputManager), "GetMouseX")] internal class InputManager_MouseX_Patcher { internal static void Postfix(ref float __result) { __result *= ChaosInputManager.mouseSpeedCoeffX; } } [HarmonyPatch(typeof(InputManager), "GetMouseY")] internal class InputManager_MouseY_Patcher { internal static void Postfix(ref float __result) { __result *= ChaosInputManager.mouseSpeedCoeffY; } } internal static class MainPatcher { private static bool isPatched; internal static void InitPatch() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (isPatched) { return; } isPatched = true; try { ((HelperLog)Utils.logger).Log((object)"MainPatcher init"); new Harmony("com.Loki.patch").PatchAll(Assembly.GetExecutingAssembly()); } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"MainPatcher error: {arg}"); } } } [HarmonyPatch(typeof(PlayerAvatar), "Awake")] internal class PlayerAvatarPatcher { internal static void Postfix(PlayerAvatar __instance) { if ((Object)(object)((Component)__instance).GetComponent<ChaosModNetwork>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<ChaosModNetwork>(); } } } [HarmonyPatch(typeof(SemiFunc), "EnemySpawn")] internal class SemiFunc_EnemySpawnPatcher { private static readonly HashSet<Enemy> enemiesToBlockInGameSpawn = new HashSet<Enemy>(); internal static void AddEnemyToBlockInGameSpawn(Enemy enemy) { if (!((Object)(object)enemy == (Object)null)) { enemiesToBlockInGameSpawn.Add(enemy); } } internal static void ClearBlockEnemies() { enemiesToBlockInGameSpawn.Clear(); } private static bool Prefix(ref bool __result, Enemy enemy) { if (enemiesToBlockInGameSpawn.Contains(enemy)) { ((HelperLog)Utils.logger).LogInfo((object)("semi spawn for enemy '" + ((Object)enemy).name + "' is blocked")); enemiesToBlockInGameSpawn.Remove(enemy); ServiceProvider.inst.enemySpawner.RegisterSpawnedEnemyFinished(enemy); __result = false; return false; } return true; } } } namespace REPO_BFT_BepInEx.Commands { internal class AddExtractGoal : IRepoStandaloneCommand, IConsoleCommand, INetworkCommand { public string Id => "add_extract_goal"; public bool Execute(IEnumerable<string> args) { int num = new CommandArgsReaderWrapper(args).ReadInt(); Traverse obj = Traverse.Create((object)RoundDirector.instance); int value = obj.Field<int>("extractionHaulGoal").Value; Traverse.Create((object)obj.Field<ExtractionPoint>("extractionPointCurrent").Value).Method("HaulGoalSet", new object[1] { Mathf.Max(1, value + num) }).GetValue(); return true; } public bool Execute(IEnumerable<string> args, PlayerAvatar targetPlayer) { return Execute(args); } public bool IsValidCommandArgs(IEnumerable<string> args) { throw new NotImplementedException(); } } internal class ApplyForceMoveImpulse : IRepoStandaloneCommand, IConsoleCommand { public string Id => "force_move"; public bool Execute(IEnumerable<string> args) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) CommandArgsReaderWrapper commandArgsReaderWrapper = new CommandArgsReaderWrapper(args); float num = commandArgsReaderWrapper.ReadFloat(); float num2 = commandArgsReaderWrapper.ReadFloat(); float num3 = commandArgsReaderWrapper.ReadFloat(); GameUtils.LocalPlayer.ForceImpulse(new Vector3(num, num2, num3)); return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { throw new NotImplementedException(); } } internal class ApplyForceRigitBody : IRepoStandaloneCommand, IConsoleCommand { public string Id => "force_rb"; public bool Execute(IEnumerable<string> args) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) CommandArgsReaderWrapper commandArgsReaderWrapper = new CommandArgsReaderWrapper(args); float num = commandArgsReaderWrapper.ReadFloat(); float num2 = commandArgsReaderWrapper.ReadFloat(); float num3 = commandArgsReaderWrapper.ReadFloat(); float rotatePower = commandArgsReaderWrapper.ReadFloat(10f); PlayerAvatar localPlayer = GameUtils.LocalPlayer; GameUtils.ActivateTumble(localPlayer.tumble, localPlayer, new Vector3(num, num2, num3), rotatePower); return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { throw new NotImplementedException(); } } internal class ApplyRelForceMoveImpulse : IRepoStandaloneCommand, IConsoleCommand { public string Id => "rel_force_move"; public bool Execute(IEnumerable<string> args) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) CommandArgsReaderWrapper commandArgsReaderWrapper = new CommandArgsReaderWrapper(args); float num = commandArgsReaderWrapper.ReadFloat(); float num2 = commandArgsReaderWrapper.ReadFloat(); Transform transform = ((Component)GameUtils.LocalPlayer).transform; Vector3 val = transform.forward; Vector3 val2 = ((Vector3)(ref val)).normalized * num; val = transform.right; Vector3 val3 = ((Vector3)(ref val)).normalized * (0f - num2); PlayerAvatar localPlayer = GameUtils.LocalPlayer; Traverse val4 = Traverse.Create((object)localPlayer); Vector3 val5 = val2 + val3; localPlayer.ForceImpulse(val5); if (val4.Field<bool>("isCrouching").Value || val4.Field<bool>("isCrawling").Value) { ((HelperLog)Utils.logger).LogInfo((object)"add push v2"); GameUtils.ActivateTumble(localPlayer.tumble, localPlayer, val5, 10f); return true; } return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { throw new NotImplementedException(); } } internal class AveragePlayersHealth : IRepoStandaloneCommand, IConsoleCommand, INetworkCommand { public string Id => "avg_players_hp"; public bool Execute(IEnumerable<string> args) { List<PlayerAvatar> alivePlayers = GameUtils.AlivePlayers; int amount = alivePlayers.Select((PlayerAvatar p) => GameUtils.GetPlayerHealth(p.playerHealth)).Sum() / alivePlayers.Count; foreach (PlayerAvatar item in alivePlayers) { GameUtils.SetHealthAmount(item, amount, keepAlive: true); } return true; } public bool Execute(IEnumerable<string> args, PlayerAvatar targetPlayer) { return Execute(args); } public bool IsValidCommandArgs(IEnumerable<string> args) { throw new NotImplementedException(); } } internal class ChangeExtractGoalPercents : IRepoStandaloneCommand, IConsoleCommand, INetworkCommand { public string Id => "change_extract_goal_percents"; public bool Execute(IEnumerable<string> args) { float num = new CommandArgsReaderWrapper(args).ReadFloat(); Traverse obj = Traverse.Create((object)RoundDirector.instance); int value = obj.Field<int>("extractionHaulGoal").Value; Traverse.Create((object)obj.Field<ExtractionPoint>("extractionPointCurrent").Value).Method("HaulGoalSet", new object[1] { Mathf.Max(1, (int)((float)value * num)) }).GetValue(); return true; } public bool Execute(IEnumerable<string> args, PlayerAvatar targetPlayer) { return Execute(args); } public bool IsValidCommandArgs(IEnumerable<string> args) { throw new NotImplementedException(); } } internal class ChangeHeight : IRepoStandaloneCommand, IConsoleCommand { private Vector3 basePlayerScale; private int sizeTriggerCount; public string Id => "change_height"; public bool IsActive { get; private set; } public bool Execute(IEnumerable<string> args) { return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { throw new NotImplementedException(); } } internal class ChangeMouseSpeedX : IRepoStandaloneCommand, IConsoleCommand, IForceEnd { public string Id => "change_mouse_speed_x"; public bool IsActive { get; private set; } public bool Execute(IEnumerable<string> args) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown CommandArgsReaderWrapper commandArgsReaderWrapper = new CommandArgsReaderWrapper(args); float durationInSec = commandArgsReaderWrapper.ReadFloat(); ChaosInputManager.mouseSpeedCoeffX = commandArgsReaderWrapper.ReadFloat(); ServiceProvider.inst.scheduleManager.AppendTimerTask(new TimerTaskData { id = Id, durationInSec = durationInSec, finishAction = delegate { IsActive = false; ChaosInputManager.mouseSpeedCoeffX = 1f; } }, true); return true; } public void ForceEnd() { ServiceProvider.inst.scheduleManager.FinishImmediatlyTimerTask(Id); } public bool IsValidCommandArgs(IEnumerable<string> args) { throw new NotImplementedException(); } } internal class ChangeMouseSpeedY : IRepoStandaloneCommand, IConsoleCommand, IForceEnd { public string Id => "change_mouse_speed_y"; public bool IsActive { get; private set; } public bool Execute(IEnumerable<string> args) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown CommandArgsReaderWrapper commandArgsReaderWrapper = new CommandArgsReaderWrapper(args); float durationInSec = commandArgsReaderWrapper.ReadFloat(); ChaosInputManager.mouseSpeedCoeffY = commandArgsReaderWrapper.ReadFloat(); ServiceProvider.inst.scheduleManager.AppendTimerTask(new TimerTaskData { id = Id, durationInSec = durationInSec, finishAction = delegate { IsActive = false; ChaosInputManager.mouseSpeedCoeffY = 1f; } }, true); return true; } public void ForceEnd() { ServiceProvider.inst.scheduleManager.FinishImmediatlyTimerTask(Id); } public bool IsValidCommandArgs(IEnumerable<string> args) { throw new NotImplementedException(); } } internal class DisablePlayerAiming : IRepoStandaloneCommand, IConsoleCommand, IForceEnd { public string Id => "disable_player_aiming"; public bool IsActive { get; private set; } public bool Execute(IEnumerable<string> args) { float num = new CommandArgsReaderWrapper(args).ReadFloat(); Traverse<float> aimingTimerField = GetAimingTimerField(); if (aimingTimerField == null) { ((HelperLog)Utils.logger).LogError((object)(Id + " target field null")); return false; } aimingTimerField.Value = num + Mathf.Max(0f, aimingTimerField.Value); return true; } private Traverse<float> GetAimingTimerField() { InputManager instance = InputManager.instance; if ((Object)(object)instance == (Object)null) { ((HelperLog)Utils.logger).LogError((object)(Id + " InputManager null")); return null; } return Traverse.Create((object)instance).Field<float>("disableAimingTimer"); } public void ForceEnd() { Traverse<float> aimingTimerField = GetAimingTimerField(); if (aimingTimerField != null) { aimingTimerField.Value = 0f; } else { ((HelperLog)Utils.logger).LogWarning((object)(Id + " field null when ForceEnd")); } } public bool IsValidCommandArgs(IEnumerable<string> args) { throw new NotImplementedException(); } } internal class DisableCrouch : IRepoStandaloneCommand, IConsoleCommand, IForceEnd { private readonly Dictionary<InputKey, bool> isActive = new Dictionary<InputKey, bool>(); public string Id => "disable_input"; public bool IsActive => isActive.Any((KeyValuePair<InputKey, bool> item) => item.Value); public bool Execute(IEnumerable<string> args) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown CommandArgsReaderWrapper commandArgsReaderWrapper = new CommandArgsReaderWrapper(args); float durationInSec = commandArgsReaderWrapper.ReadFloat(); string text = commandArgsReaderWrapper.ReadString(); if (!Enum.TryParse<InputKey>(text, ignoreCase: true, out InputKey key)) { ((HelperLog)Utils.logger).LogError((object)(Id + " can't find key for name " + text)); return false; } isActive[key] = true; ChaosInputManager.BlockKey(key); ServiceProvider.inst.scheduleManager.AppendTimerTask(new TimerTaskData { id = GetTimerKey(key), durationInSec = durationInSec, finishAction = delegate { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) isActive[key] = false; ChaosInputManager.UnblockKey(key); ((HelperLog)Utils.logger).LogInfo((object)(Id + " ends")); } }, false); return true; } private string GetTimerKey(InputKey key) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return $"{Id}_{key}"; } public void ForceEnd() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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) foreach (InputKey key in isActive.Keys) { ServiceProvider.inst.scheduleManager.FinishImmediatlyTimerTask(GetTimerKey(key)); } } public bool IsValidCommandArgs(IEnumerable<string> args) { throw new NotImplementedException(); } } internal class DisablePlayerMovement : IRepoStandaloneCommand, IConsoleCommand, IForceEnd { public string Id => "disable_player_movement"; public bool IsActive { get; private set; } public bool Execute(IEnumerable<string> args) { float num = new CommandArgsReaderWrapper(args).ReadFloat(); Traverse<float> movementTimerField = GetMovementTimerField(); if (movementTimerField == null) { ((HelperLog)Utils.logger).LogError((object)(Id + " target field null")); return false; } movementTimerField.Value = num + Mathf.Max(0f, movementTimerField.Value); return true; } private Traverse<float> GetMovementTimerField() { InputManager instance = InputManager.instance; if ((Object)(object)instance == (Object)null) { ((HelperLog)Utils.logger).LogError((object)(Id + " InputManager null")); return null; } return Traverse.Create((object)instance).Field<float>("disableMovementTimer"); } public void ForceEnd() { Traverse<float> movementTimerField = GetMovementTimerField(); if (movementTimerField != null) { movementTimerField.Value = 0f; } else { ((HelperLog)Utils.logger).LogWarning((object)(Id + " field null when ForceEnd")); } } public bool IsValidCommandArgs(IEnumerable<string> args) { throw new NotImplementedException(); } } internal class DrainStamina : IRepoStandaloneCommand, IConsoleCommand, IForceEnd { private float power; public string Id => "drain_player_stamina"; public bool IsActive { get; private set; } public bool Execute(IEnumerable<string> args) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown CommandArgsReaderWrapper commandArgsReaderWrapper = new CommandArgsReaderWrapper(args); float durationInSec = commandArgsReaderWrapper.ReadFloat(); power = commandArgsReaderWrapper.ReadFloat(); ServiceProvider.inst.eventEmitter.ReplaceOrAddOnUpdateHandler(Id, OnUpdate); ServiceProvider.inst.scheduleManager.AppendTimerTask(new TimerTaskData { id = Id, durationInSec = durationInSec, finishAction = delegate { IsActive = false; ((HelperLog)Utils.logger).LogInfo((object)(Id + " ends")); } }, false); IsActive = true; return true; } private void OnUpdate(object sender, float dtInSec) { if (IsActive) { float energyCurrent = PlayerController.instance.EnergyCurrent; PlayerController.instance.EnergyCurrent = Mathf.Max(0f, energyCurrent - power * dtInSec); } } public void ForceEnd() { ServiceProvider.inst.scheduleManager.FinishImmediatlyTimerTask(Id); } public bool IsValidCommandArgs(IEnumerable<string> args) { throw new NotImplementedException(); } } internal class DropInventory : IRepoStandaloneCommand, IConsoleCommand { public string Id => "drop_inventory"; public bool Execute(IEnumerable<string> args) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar localPlayer = GameUtils.LocalPlayer; if (GameUtils.IsPlayerDead(GameUtils.LocalPlayer)) { ((HelperLog)Utils.logger).LogInfo((object)(Id + " player is dead")); return true; } Inventory instance = Inventory.instance; if ((Object)(object)instance == (Object)null) { ((HelperLog)Utils.logger).LogInfo((object)(Id + " player inventory is not found")); return false; } PhysGrabber grabber = GameUtils.LocalPlayer.physGrabber; _ = ((Component)localPlayer).transform.position + GameUtils.GetForwardOffset(); List<ItemEquippable> l
ChaosTricks_REPO_plugins/ModHelper.dll
Decompiled 3 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using EventsIO; using EventsIO.Interfaces; using ModHelper.Interfaces; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ModHelper")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("BFT")] [assembly: AssemblyProduct("ModHelper")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("8d858f35-342c-4916-8e50-2b2cfd18640d")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.0.0")] namespace ModHelper { public class CommandArgsValidator { private readonly ILogger logger; public CommandArgsValidator(ILogger logger) { this.logger = logger; } public bool IsZeroArgs(IEnumerable<string> args) { int num = args?.Count() ?? 0; if (num != 0) { logger?.LogWarning($"CommandArgsValidator wrong args count {num} (must be 0)"); return false; } return true; } public bool IsZeroArgs(IEnumerator<string> args) { if (args == null || !args.MoveNext()) { return true; } logger?.LogWarning("CommandArgsValidator wrong args count (more than needed)"); return false; } private bool IsInvalidArgsCount(IEnumerator<string> args) { if (args != null) { return !args.MoveNext(); } return true; } public bool IsValidInt(IEnumerator<string> args, int minValue, int maxValue, bool isSkippable = false) { if (IsInvalidArgsCount(args)) { if (isSkippable) { return true; } logger?.LogWarning("CommandArgsValidator wrong args count"); return false; } try { int num = int.Parse(args.Current); if (num < minValue || num > maxValue) { string obj = $"CommandArgsValidator wrong integer value {num} (must be in range from {minValue} to {maxValue})"; logger?.LogWarning(obj); return false; } } catch (Exception arg) { logger?.LogWarning($"CommandArgsValidator can't parse integer value from '{args.Current}', {arg}"); return false; } return true; } public bool IsValidFloat(IEnumerator<string> args, float minValue, float maxValue, bool isSkippable = false) { if (IsInvalidArgsCount(args)) { if (isSkippable) { return true; } logger?.LogWarning("CommandArgsValidator wrong args count"); return false; } try { float num = float.Parse(args.Current, CultureInfo.InvariantCulture.NumberFormat); if (num < minValue || num > maxValue) { string obj = $"CommandArgsValidator wrong float value {num} (must be in range from {minValue} to {maxValue})"; logger?.LogWarning(obj); return false; } } catch (Exception arg) { logger?.LogWarning($"CommandArgsValidator can't parse float value from '{args.Current}', {arg}"); } return true; } public bool IsValidString(IEnumerator<string> args, Func<string, bool> validator, bool isSkippable = false) { if (IsInvalidArgsCount(args)) { if (isSkippable) { return true; } logger?.LogWarning("CommandArgsValidator wrong args count"); return false; } if (validator == null || validator(args.Current)) { return true; } logger?.LogWarning("CommandArgsValidator wrong string value " + args.Current); return false; } public bool IsValidBool(IEnumerator<string> args, bool isSkippable = false) { if (IsInvalidArgsCount(args)) { if (isSkippable) { return true; } logger?.LogWarning("CommandArgsValidator wrong args count"); return false; } try { bool.Parse(args.Current.ToLower()); } catch (Exception arg) { logger?.LogWarning($"CommandArgsValidator can't parse bool value from '{args.Current}', {arg}"); return false; } return true; } } public class PeriodicTaskData { public string id; public float periodInSec; internal float periodCalculatedInSec; public int triggerTimes; public bool isInfiniteRepeates = true; public Action periodicAction; public Action finishAction; public override string ToString() { return "id=" + id + ", " + $"period={periodInSec}s, " + $"calc_period={periodCalculatedInSec}s, " + $"triggerTimes={triggerTimes}, " + $"isInfiniteRepeates={isInfiniteRepeates}"; } } public class TimerTaskData { public string id; public float durationInSec; public Action finishAction; public override string ToString() { return $"id={id}, duration={durationInSec}s"; } } public class BufferedLogger : HelperDebugLog, IDisposable { protected readonly Queue<string> queue; protected readonly int bufferRecordsCount; private bool isDisposed; public BufferedLogger(string folderPath = null, string logFileName = null, bool isDebug = false, int bufferRecordsCount = 10) : base(folderPath, logFileName, isDebug) { this.bufferRecordsCount = bufferRecordsCount; queue = new Queue<string>(); } public virtual void Flush(bool isNeedClearQueue = false) { if (queue.Count != 0) { WriteToFile(string.Join("\n", queue.ToArray())); if (isNeedClearQueue) { queue.Clear(); } } } public override void Log(object obj) { if (obj != null && isLogFile) { queue.Enqueue($"{LogTime} {obj}"); if (queue.Count >= bufferRecordsCount) { Flush(isNeedClearQueue: true); } } } protected virtual void Dispose(bool isDisposing) { if (!isDisposed) { isDisposed = true; if (queue.Count > 0) { Flush(); } } } public void Dispose() { Dispose(isDisposing: true); GC.SuppressFinalize(this); } ~BufferedLogger() { Dispose(isDisposing: false); } } public static class HelperGroups { public static Dictionary<string, List<string>> GenerateNewEmptyGroupsDict() { return new Dictionary<string, List<string>>(StringComparer.InvariantCultureIgnoreCase); } private static bool SafeApplyValidator(Func<string, bool> groupItemValidator, string itemName, ILogger logger = null) { try { return groupItemValidator?.Invoke(itemName) ?? true; } catch (Exception arg) { logger?.LogError($"RandomGroup.SafeApplyValidator unexpected error: {arg}"); } return false; } public static void InitGroupsFromFiles(string dataDir, Dictionary<string, List<string>> groups, string groupsPrefix, Func<string, bool> groupItemValidator = null, IDebugLogger logger = null) { try { if (string.IsNullOrEmpty(groupsPrefix)) { logger?.LogError("RandomGroup error: wrong groupsPrefix " + groupsPrefix); return; } string[] files = Directory.GetFiles(dataDir); foreach (string path in files) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path); if (fileNameWithoutExtension.StartsWith(groupsPrefix)) { groups[fileNameWithoutExtension] = GetItemsFromFile(path, logger); } } foreach (KeyValuePair<string, List<string>> group in groups) { logger?.LogDebugInfo("RandomGroup validate list " + group.Key + ":"); List<string> list = new List<string>(); foreach (string item in group.Value) { if (!SafeApplyValidator(groupItemValidator, item, logger)) { logger?.LogWarning("invalid name " + item); list.Add(item); } } if (list.Count > 0) { foreach (string item2 in list) { group.Value.Remove(item2); } logger?.LogWarning("list " + group.Key + " is invalid"); } else { logger?.LogDebugInfo("list " + group.Key + " is valid"); } } } catch (Exception arg) { logger?.LogError($"RandomGroup.InitGroupsFromFiles unexpected error: {arg}"); } } public static Dictionary<string, List<string>> GenerateGroupsFromFiles(string dataDir, string groupsPrefix, Func<string, bool> groupItemValidator = null, IDebugLogger logger = null) { Dictionary<string, List<string>> dictionary = GenerateNewEmptyGroupsDict(); InitGroupsFromFiles(dataDir, dictionary, groupsPrefix, groupItemValidator, logger); return dictionary; } public static List<string> GetItemsFromFile(string path, IDebugLogger logger = null) { try { List<string> list = new HelperJson(logger).FromFile<List<string>>(path); if (list == null) { list = new List<string>(); } logger?.LogInfo($"Items from file {path}: found {list.Count}"); foreach (string item in list) { logger?.LogDebugInfo("value " + item); } return list; } catch (Exception arg) { logger?.LogError($"HelperGroups.GetItemsFromFile unexpected error: {arg}"); } return new List<string>(); } public static bool IsValidGroupName(Dictionary<string, List<string>> dict, string name) { return dict?.ContainsKey(name) ?? false; } public static void PrintGroups(Dictionary<string, List<string>> dict, ILogger logger, string groupsName = "default_name") { if (logger == null) { return; } if (dict == null || dict.Count == 0) { logger?.LogWarning("No groups found for " + groupsName); return; } logger?.LogInfo("---------------Groups " + groupsName + " list---------------"); foreach (KeyValuePair<string, List<string>> item in dict) { logger?.LogInfo(item.Key ?? ""); } logger?.LogInfo("---------------Groups " + groupsName + " list end---------------"); } } public class HelperJson : IJsonUtil { private class ContainerObjAndInt { public object valueObj; public int valueInt; } private class ContainerStringAndInt { public string valueString; public int valueInt; } private ILogger logger; private const char startClass = '{'; private const char endClass = '}'; private const char startArray = '['; private const char endArray = ']'; private const char isHasNextField = ','; private const char special = '\\'; private const char startString = '"'; private const char nameValueSeparator = ':'; private char[] ignoreChars = new char[9] { ' ', '\n', '\r', '\t', '\b', '\f', '\0', '{', '[' }; private string logMsgBaseError = "HelperJson error:"; private string logMsgBase = "HelperJson:"; private bool isVerboseDebugLog; private void VerboseDebugLog(string s) { if (isVerboseDebugLog) { logger?.LogInfo("[DEBUG] " + s); } } public HelperJson(IDebugLogger logger = null, bool isVerboseDebugLog = false) { this.logger = logger; this.isVerboseDebugLog = isVerboseDebugLog; } public T FromFile<T>(string path) where T : class { string s; using (StreamReader streamReader = new StreamReader(path)) { s = streamReader.ReadToEnd(); } return FromString<T>(s); } public T FromString<T>(string s) where T : class { return GetFromString(typeof(T), s, 0).valueObj as T; } private char GetSpecialChar(char c) { if (c != '"') { return c; } return c; } private void SetFieldClass<T, R>(T instance, string fieldName, R fieldValue) where T : class where R : class { Type type = instance.GetType(); VerboseDebugLog("type=" + type.Name + ", field=" + fieldName); type.GetField(fieldName).SetValue(instance, fieldValue); } private ContainerStringAndInt ParseNextStringValue(string s, int index, bool isSkipSep = true) { StringBuilder stringBuilder = new StringBuilder(); bool flag = false; int i; for (i = index; i < s.Length; i++) { char c = s[i]; VerboseDebugLog($"{logMsgBase} ParseNextStringValue for process {c}"); if (!flag) { i = SkipIgnoredChars(s, i, isSkipHasNextField: false, isSkipSep); if (i >= s.Length) { logger?.Log(logMsgBaseError + " class field value parsing internal issue. Set default value."); break; } c = s[i]; if (c == '"') { flag = true; VerboseDebugLog(logMsgBase + " ParseNextStringValue is startString case"); continue; } if (c == ']' || c == '}') { break; } if (c == ',' || c == ':') { i = SkipIgnoredChars(s, i, isSkipHasNextField: true, isSkipSep); break; } } else if (c == '\\') { VerboseDebugLog(logMsgBase + " ParseNextStringValue is special case"); i++; if (i >= s.Length) { logger?.Log(logMsgBaseError + " class field value parsing internal issue with special symbols. Set default value."); break; } c = GetSpecialChar(s[i]); if (c != '"') { stringBuilder.Append('\\'); } } else if (c == '"') { VerboseDebugLog(logMsgBase + " ParseNextStringValue is startString end case"); i = SkipIgnoredChars(s, ++i, isSkipHasNextField: true, isSkipSep); break; } VerboseDebugLog($"{logMsgBase} ParseNextStringValue append {c}"); stringBuilder.Append(c); } string text = stringBuilder.ToString(); VerboseDebugLog($"{logMsgBase} ParseNextStringValue {text}, end at index {i}"); return new ContainerStringAndInt { valueString = text, valueInt = i }; } private ContainerStringAndInt GetNextFieldName(string s, int index) { VerboseDebugLog(logMsgBase + " GetNextFieldName"); return ParseNextStringValue(s, index, isSkipSep: false); } private ContainerObjAndInt GetNextValue(Type valueType, string s, int index, bool isSkipSep) { VerboseDebugLog(logMsgBase + " GetNextValue"); int num = SkipIgnoredChars(s, index, isSkipHasNextField: true, isSkipSep); if (num >= s.Length) { logger?.LogError(logMsgBaseError + " class parsing internal issue at value type " + valueType.Name + ". Set default value."); } if (valueType.IsPrimitive) { ContainerStringAndInt containerStringAndInt = ParseNextStringValue(s, num, isSkipSep); try { TypeCode typeCode = Type.GetTypeCode(valueType); object valueObj; if ((uint)(typeCode - 5) <= 10u) { if (double.TryParse(containerStringAndInt.valueString, NumberStyles.Any, CultureInfo.InvariantCulture, out var result)) { valueObj = Convert.ChangeType(result, valueType); } else { valueObj = Activator.CreateInstance(valueType); logger?.Log(logMsgBaseError + " incorrect convert, use default."); logger?.Log("Read value: " + containerStringAndInt.valueString + ", type: " + valueType.Name); } } else { valueObj = Convert.ChangeType(containerStringAndInt.valueString, valueType); } return new ContainerObjAndInt { valueObj = valueObj, valueInt = containerStringAndInt.valueInt }; } catch (Exception arg) { logger?.Log($"{logMsgBaseError} incorrect format, use default. Msg: {arg}"); logger?.Log("read value: " + containerStringAndInt.valueString + ", type: " + valueType.Name); return new ContainerObjAndInt { valueObj = Activator.CreateInstance(valueType), valueInt = containerStringAndInt.valueInt }; } } if (valueType.IsAssignableFrom(typeof(string))) { ContainerStringAndInt containerStringAndInt2 = ParseNextStringValue(s, num, isSkipSep); return new ContainerObjAndInt { valueObj = containerStringAndInt2.valueString, valueInt = containerStringAndInt2.valueInt }; } ContainerObjAndInt fromString = GetFromString(valueType, s, num); return new ContainerObjAndInt { valueObj = fromString.valueObj, valueInt = fromString.valueInt }; } private int SkipIgnoredChars(string s, int index, bool isSkipHasNextField = false, bool isSkipSep = false) { for (int i = index; i < s.Length; i++) { if (ignoreChars.Contains(s[i])) { VerboseDebugLog($"skip char '{s[i]}'"); continue; } if (isSkipHasNextField && s[i] == ',') { VerboseDebugLog($"skip char '{s[i]}'"); continue; } if (isSkipSep && s[i] == ':') { VerboseDebugLog($"skip char '{s[i]}'"); continue; } return i; } return s.Length; } private ContainerObjAndInt ParseIListByItemType(Type itemType, string s, int index) { if (!(Activator.CreateInstance(typeof(List<>).MakeGenericType(itemType)) is IList list)) { logger?.LogError(logMsgBaseError + " can't create IList for item type " + itemType.Name); return new ContainerObjAndInt { valueObj = null, valueInt = s.Length }; } do { ContainerObjAndInt nextValue = GetNextValue(itemType, s, index, isSkipSep: true); object valueObj = nextValue.valueObj; index = nextValue.valueInt; list.Add(valueObj); index = SkipIgnoredChars(s, index, isSkipHasNextField: true, isSkipSep: true); } while (index < s.Length && s[index] != ']' && s[index] != '}'); return new ContainerObjAndInt { valueObj = list, valueInt = index + 1 }; } private ContainerObjAndInt ParseIList(Type resultType, string s, int index) { Type itemType = (resultType.IsGenericType ? resultType.GetGenericArguments()[0] : resultType.GetElementType()); return ParseIListByItemType(itemType, s, index); } private ContainerObjAndInt ParseArray(Type resultType, string s, int index) { Type elementType = resultType.GetElementType(); ContainerObjAndInt containerObjAndInt = ParseIListByItemType(elementType, s, index); Array array; if (containerObjAndInt.valueObj is IList list) { array = Array.CreateInstance(elementType, list.Count); for (int i = 0; i < array.Length; i++) { array.SetValue(list[i], i); } } else { logger?.Log(logMsgBaseError + " create empty Array"); array = Array.CreateInstance(elementType, 0); } return new ContainerObjAndInt { valueObj = array, valueInt = containerObjAndInt.valueInt }; } private ContainerObjAndInt ParseIDictionary(Type dictType, string s, int index) { Type[] genericArguments = dictType.GetGenericArguments(); if (genericArguments.Length != 2) { logger?.Log(logMsgBaseError + " can't create IDictionary, invalid args"); } if (dictType.IsGenericType) { if (!dictType.IsGenericTypeDefinition) { dictType = dictType.GetGenericTypeDefinition(); } dictType = dictType.MakeGenericType(genericArguments); } if (!(Activator.CreateInstance(dictType) is IDictionary dictionary)) { string name = dictType.GetType().Name; logger?.Log(logMsgBaseError + " can't create IDictionary " + name + " for item type " + genericArguments[0].Name + ", " + genericArguments[1].Name); return new ContainerObjAndInt { valueObj = null, valueInt = s.Length }; } Type valueType = genericArguments[0]; Type valueType2 = genericArguments[1]; do { ContainerObjAndInt nextValue = GetNextValue(valueType, s, index, isSkipSep: false); index = nextValue.valueInt; ContainerObjAndInt nextValue2 = GetNextValue(valueType2, s, index, isSkipSep: true); index = nextValue2.valueInt; dictionary.Add(nextValue.valueObj, nextValue2.valueObj); VerboseDebugLog($"{logMsgBase} dict add key {nextValue.valueObj}"); index = SkipIgnoredChars(s, index, isSkipHasNextField: true, isSkipSep: true); } while (index < s.Length && s[index] != '}' && s[index] != ']'); return new ContainerObjAndInt { valueObj = dictionary, valueInt = index + 1 }; } private bool IsTypeOf(Type targetType, Type sourceType, int argsCount) { if (sourceType.IsAssignableFrom(targetType)) { VerboseDebugLog(logMsgBase + " is " + targetType.Name); return true; } Type[] types = sourceType.Assembly.GetTypes(); foreach (Type type in types) { if (!type.IsClass) { continue; } Type[] interfaces = type.GetInterfaces(); foreach (Type type2 in interfaces) { if (type2.IsGenericType && (object)type2.GetGenericTypeDefinition() == targetType && sourceType.GetGenericArguments().Length == argsCount) { VerboseDebugLog(logMsgBase + " is " + targetType.Name + " assembly interface"); return true; } } } return false; } private ContainerObjAndInt GetFromString(Type resultType, string s, int index) { try { VerboseDebugLog(logMsgBase + " GetFromString"); if (resultType.IsArray) { VerboseDebugLog(logMsgBase + " is array"); return ParseArray(resultType, s, index); } if (resultType.IsAssignableFrom(typeof(IList)) || IsTypeOf(typeof(IList<>), resultType, 1)) { return ParseIList(resultType, s, index); } if (resultType.IsAssignableFrom(typeof(IDictionary)) || IsTypeOf(typeof(IDictionary<, >), resultType, 2)) { return ParseIDictionary(resultType, s, index); } if (resultType.IsGenericType && !resultType.IsGenericTypeDefinition) { Type[] genericArguments = resultType.GetGenericArguments(); resultType = resultType.GetGenericTypeDefinition(); resultType = resultType.MakeGenericType(genericArguments); } object obj = Activator.CreateInstance(resultType); int num = index; while (num < s.Length && s[num] != ']' && s[num] != '}') { ContainerStringAndInt nextFieldName = GetNextFieldName(s, num); string valueString = nextFieldName.valueString; if (string.IsNullOrEmpty(valueString?.Trim())) { VerboseDebugLog(logMsgBase + " IsNullOrWhiteSpace field " + valueString + ", class type " + resultType.Name); num = GetNextValue(typeof(string), s, num, isSkipSep: true).valueInt; continue; } num = nextFieldName.valueInt; FieldInfo field = resultType.GetField(valueString); VerboseDebugLog(logMsgBase + " field " + valueString + ", class type " + resultType.Name); if (isVerboseDebugLog) { FieldInfo[] fields = resultType.GetFields(); VerboseDebugLog(logMsgBase + " fields in class: "); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { VerboseDebugLog(fieldInfo.Name); } } if ((object)field == null) { logger?.LogWarning(logMsgBaseError + " can't find field " + valueString + " for type " + resultType.Name + ". Try to skip."); num = GetNextValue(typeof(string), s, num, isSkipSep: true).valueInt; } else { ContainerObjAndInt nextValue = GetNextValue(field.FieldType, s, num, isSkipSep: true); object valueObj = nextValue.valueObj; num = nextValue.valueInt; SetFieldClass(obj, valueString, valueObj); } } num = SkipIgnoredChars(s, num + 1, isSkipHasNextField: true, isSkipSep: true); return new ContainerObjAndInt { valueObj = obj, valueInt = num }; } catch (Exception arg) { logger?.LogError($"{logMsgBaseError} {arg}"); } return new ContainerObjAndInt { valueObj = null, valueInt = s.Length }; } } public class HelperDebugLog : HelperLog, IDebugLogger, ILoggerWithConsole, ILogger { protected bool isDebug; public HelperDebugLog(string folderPath = null, string logFileName = null, bool isDebug = false) : base(folderPath, logFileName) { this.isDebug = isDebug; } public virtual void LogDebugInfo(object obj) { if (isDebug) { LogInfo($"[DEBUG] {obj}"); } } public virtual void LogDebugWarning(object obj) { if (isDebug) { LogWarning($"[DEBUG] {obj}"); } } public virtual void LogDebugError(object obj) { if (isDebug) { LogError($"[DEBUG] {obj}"); } } } public class ScheduleManager { protected ILogger logger; protected Dictionary<string, TimerTaskData> timerTasks = new Dictionary<string, TimerTaskData>(); protected Dictionary<string, PeriodicTaskData> periodicTasks = new Dictionary<string, PeriodicTaskData>(); protected List<TimerTaskData> timerTasksNoId = new List<TimerTaskData>(); protected List<PeriodicTaskData> periodicTasksNoId = new List<PeriodicTaskData>(); protected int onUpdateErrorLimit = 10; public ScheduleManager(ILogger logger = null, int onUpdateErrorLimit = 0) { this.logger = logger; this.onUpdateErrorLimit = onUpdateErrorLimit; } public void NewTimerTask(TimerTaskData task, bool triggerFinishIfExists = false) { if (task == null) { logger?.LogInfo($"ScheduleManager new timer task null error. Details info: {task}"); return; } if (task.id == null) { NewTimerTaskWithOutId(task); return; } if (triggerFinishIfExists && timerTasks.ContainsKey(task.id)) { SafeRunAction(timerTasks[task.id].finishAction); } timerTasks[task.id] = task; logger?.LogInfo($"ScheduleManager new timer task {task}"); } public void NewPeriodicTask(PeriodicTaskData task, bool triggerFinishIfExists = false) { if (task == null) { logger?.LogInfo($"ScheduleManager new periodic task null error. Details info: {task}"); return; } task.periodCalculatedInSec = task.periodInSec; if (task.id == null) { NewPeriodicTaskWithOutId(task); return; } if (triggerFinishIfExists && periodicTasks.ContainsKey(task.id)) { SafeRunAction(periodicTasks[task.id].finishAction); } periodicTasks[task.id] = task; logger?.LogInfo($"ScheduleManager new periodic task {task}"); } public void AppendPeriodicTask(PeriodicTaskData task, bool isReplaceAction = false) { if (task.id == null || !periodicTasks.ContainsKey(task.id)) { NewPeriodicTask(task); return; } logger?.LogInfo($"ScheduleManager append periodic task {task}"); PeriodicTaskData periodicTaskData = periodicTasks[task.id]; periodicTaskData.triggerTimes += task.triggerTimes; if (isReplaceAction) { periodicTaskData.finishAction = task.finishAction; } } protected void NewTimerTaskWithOutId(TimerTaskData task) { if (task == null) { logger?.LogWarning($"ScheduleManager new timer no id task null error. Details info: {task}"); return; } timerTasksNoId.Add(task); logger?.LogInfo($"ScheduleManager new timer no id task {task}"); } protected void NewPeriodicTaskWithOutId(PeriodicTaskData task) { if (task == null) { logger?.LogWarning($"ScheduleManager new periodic no id task null error. Details info: {task}"); return; } periodicTasksNoId.Add(task); logger?.LogInfo($"ScheduleManager new periodic no id task {task}"); } public void AppendTimerTask(TimerTaskData task, bool isReplaceAction = true) { if (!timerTasks.ContainsKey(task.id)) { NewTimerTask(task); return; } logger?.LogInfo($"ScheduleManager append timer task {task}"); TimerTaskData timerTaskData = timerTasks[task.id]; timerTasks[task.id] = task; task.durationInSec += timerTaskData.durationInSec; if (!isReplaceAction) { task.finishAction = timerTaskData.finishAction; } } public bool IsTaskExists(string id) { if (!periodicTasks.ContainsKey(id)) { return timerTasks.ContainsKey(id); } return true; } public void RemoveTimerTask(string id) { if (timerTasks.Remove(id)) { logger?.LogInfo("ScheduleManager remove timer task " + id); } } public void RemovePeriodicTask(string id) { if (periodicTasks.Remove(id)) { logger?.LogInfo("ScheduleManager remove periodic task " + id); } } public void RemoveAllTasks(string id) { logger?.LogInfo("ScheduleManager RemoveAllTasks with id " + id); RemoveTimerTask(id); RemovePeriodicTask(id); } public void RemoveAllTasks(bool isSuppressLog = false) { timerTasks.Clear(); periodicTasks.Clear(); timerTasksNoId.Clear(); periodicTasksNoId.Clear(); if (!isSuppressLog && logger != null) { logger.LogInfo("ScheduleManager RemoveAllTasks"); } } protected List<TimerTaskData> ProcessTimersList(ICollection<TimerTaskData> list, float dtInSec) { List<TimerTaskData> list2 = new List<TimerTaskData>(); foreach (TimerTaskData item in list) { item.durationInSec -= dtInSec; if (item.durationInSec <= 0f) { SafeRunAction(item.finishAction); list2.Add(item); logger?.LogInfo("ScheduleManager triggered finish action timer task " + item.id); } } return list2; } protected List<PeriodicTaskData> ProcessPeriodicList(ICollection<PeriodicTaskData> list, float dtInSec) { List<PeriodicTaskData> list2 = new List<PeriodicTaskData>(); foreach (PeriodicTaskData item in list) { item.periodCalculatedInSec -= dtInSec; if (!(item.periodCalculatedInSec <= 0f)) { continue; } if (item.isInfiniteRepeates || item.triggerTimes > 0) { SafeRunAction(item.periodicAction); item.periodCalculatedInSec = item.periodInSec; if (item.triggerTimes == 1) { logger?.LogInfo("ScheduleManager triggered action periodic task " + item.id); } } if (!item.isInfiniteRepeates) { item.triggerTimes--; if (item.triggerTimes <= 0) { SafeRunAction(item.finishAction); list2.Add(item); logger?.LogInfo("ScheduleManager triggered finish action periodic task " + item.id); } } } return list2; } public void OnUpdate(float dtInSec) { try { foreach (TimerTaskData item in ProcessTimersList(timerTasks.Values, dtInSec)) { timerTasks.Remove(item.id); logger?.LogInfo($"ScheduleManager OnUpdate finished timer task {item}"); } foreach (PeriodicTaskData item2 in ProcessPeriodicList(periodicTasks.Values, dtInSec)) { periodicTasks.Remove(item2.id); logger?.LogInfo($"ScheduleManager OnUpdate finished periodic task {item2}"); } foreach (TimerTaskData item3 in ProcessTimersList(timerTasksNoId, dtInSec)) { timerTasksNoId.Remove(item3); logger?.LogInfo($"ScheduleManager OnUpdate finished timer no id task {item3}"); } foreach (PeriodicTaskData item4 in ProcessPeriodicList(periodicTasksNoId, dtInSec)) { periodicTasksNoId.Remove(item4); logger?.LogInfo($"ScheduleManager OnUpdate finished periodic no id task {item4}"); } } catch (Exception arg) { if (onUpdateErrorLimit > 0) { logger?.LogError($"ScheduleManager unexpected onUpdate error: {arg}"); onUpdateErrorLimit--; } } } public void FinishImmediatlyTimerTask(string id) { if (timerTasks.ContainsKey(id)) { SafeRunAction(timerTasks[id].finishAction); timerTasks.Remove(id); logger?.LogInfo("ScheduleManager finish and remove timer task " + id); } } public float GetTimerTaskDurationInSec(string id) { if (!timerTasks.ContainsKey(id)) { return -1f; } return timerTasks[id].durationInSec; } public void FinishImmediatlyPeriodicTask(string id) { if (periodicTasks.ContainsKey(id)) { SafeRunAction(periodicTasks[id].finishAction); periodicTasks.Remove(id); logger?.LogInfo("ScheduleManager finish and remove periodic task " + id); } } public void FinishAllImmediatly(string id) { FinishImmediatlyTimerTask(id); FinishImmediatlyPeriodicTask(id); } public void FinishAllImmediatly() { foreach (TimerTaskData value in timerTasks.Values) { SafeRunAction(value.finishAction); } foreach (PeriodicTaskData value2 in periodicTasks.Values) { SafeRunAction(value2.finishAction); } foreach (TimerTaskData item in timerTasksNoId) { SafeRunAction(item.finishAction); } foreach (PeriodicTaskData item2 in periodicTasksNoId) { SafeRunAction(item2.finishAction); } RemoveAllTasks(); } protected void SafeRunAction(Action action) { if (action == null) { return; } try { action(); } catch (Exception arg) { logger?.LogError($"SafeRunAction error: {arg}"); } } } public class UtilityConsole { private readonly Dictionary<string, IConsoleCommand> consoleCommandsDict; private readonly IDebugLogger logger; private readonly List<string> ignoreValidationCommands; public bool isLogCheckCommand = true; public bool isLogCheckCommandParameters = true; public int logCheckCommandParametersMaxLength = 40; public bool isLogProcessCommand = true; public bool isLogProcessCommandParameters = true; public int logProcessCommandParametersMaxLength = 40; public UtilityConsole(IDebugLogger logger = null, List<string> ignoreValidationCommands = null) { consoleCommandsDict = new Dictionary<string, IConsoleCommand>(); this.logger = logger; this.ignoreValidationCommands = ignoreValidationCommands; } public void RegisterCommand(IConsoleCommand command) { if (string.IsNullOrEmpty(command?.Id)) { logger?.LogWarning("UtilityConsole.RegisterCommand: invalid console command"); } else { consoleCommandsDict[command.Id] = command; } } public static string[] ParseCommandLine(string commandLine) { return commandLine.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); } public static string[] ParseArgs(string command) { return command.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); } private string GetCmdName(string cmd) { string[] array = cmd.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length != 0) { return array[0]; } return ""; } private void LogCommand(string funcPrefix, string cmd, bool isLog, bool isLogParams, int maxLen) { if (logger == null || !isLog) { return; } if (string.IsNullOrEmpty(cmd)) { logger.LogWarning(funcPrefix + " null or empty"); } else if (isLogParams) { if (cmd.Length > maxLen) { string text = cmd.Substring(0, maxLen); logger.Log(funcPrefix + " " + text + "..."); } else { logger.Log(funcPrefix + " " + cmd); } } else { logger.Log(funcPrefix + " " + GetCmdName(cmd)); } } public bool IsValidCommandLine(string commandLine) { try { if (string.IsNullOrEmpty(commandLine)) { logger?.LogDebugError("UtilityConsole.IsValidCommandLine: invalid command line"); return false; } string[] array = ParseCommandLine(commandLine); if (array == null || array.Length < 1) { logger?.LogDebugError("UtilityConsole.IsValidCommandLine: invalid commands count"); return false; } bool flag = true; string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string text = array2[i]?.Trim(); LogCommand("UtilityConsole.IsValidCommandLine: check command", text, isLogCheckCommand, isLogCheckCommandParameters, logCheckCommandParametersMaxLength); string[] array3 = ParseArgs(text); if (array3 == null || array3.Length < 1) { logger?.LogDebugError("UtilityConsole.IsValidCommandLine: invalid commands count"); flag = false; continue; } string text2 = array3[0]; List<string> list = ignoreValidationCommands; if (list != null && list.Contains(text2)) { logger?.LogDebugInfo("UtilityConsole.IsValidCommandLine: validation is ignored for this command"); } else if (consoleCommandsDict.ContainsKey(text2)) { bool flag2 = consoleCommandsDict[text2].IsValidCommandArgs(array3.Skip(1)); if (!flag2) { logger?.LogDebugError("UtilityConsole.IsValidCommandLine: command with id " + text2 + " is invalid"); } flag = flag && flag2; } else { logger?.LogDebugError("UtilityConsole.IsValidCommandLine: can't find custom command with id " + text2); flag = false; } } return flag; } catch (Exception arg) { logger?.LogDebugError(string.Format("{0} error: {1}", "UtilityConsole.IsValidCommandLine:", arg)); return false; } } public bool RunCommand(string commandLine, IEventsData data, Action<string> onCustomCommandNotFound = null) { try { string[] array = ParseCommandLine(commandLine); foreach (string text in array) { LogCommand("UtilityConsole.RunCommand: process command", text, isLogProcessCommand, isLogProcessCommandParameters, logProcessCommandParametersMaxLength); string[] array2 = ParseArgs(text); string key = array2[0]; if (consoleCommandsDict.ContainsKey(key)) { try { if (consoleCommandsDict[key] is IConsoleCommandWithData consoleCommandWithData) { consoleCommandWithData.Execute(array2.Skip(1), data); } else { consoleCommandsDict[key].Execute(array2.Skip(1)); } } catch (Exception arg) { logger?.LogError(string.Format("{0} execute command error {1}", "UtilityConsole.RunCommand:", arg)); } } else if (onCustomCommandNotFound != null) { onCustomCommandNotFound(text); } else { logger?.LogError("UtilityConsole.RunCommand: execute command not found error"); } } } catch (Exception arg2) { logger?.LogError(string.Format("{0} error {1}", "UtilityConsole.RunCommand:", arg2)); return false; } return true; } } public class CommandArgsReader { private readonly ILogger logger; public CommandArgsReader(ILogger logger) { this.logger = logger; } public int ReadInt(IEnumerator<string> args, int defaultValue = 0) { if (args == null || !args.MoveNext()) { return defaultValue; } try { return int.Parse(args.Current); } catch (Exception arg) { logger?.LogWarning($"CommandArgsReader: {arg}"); return defaultValue; } } public float ReadFloat(IEnumerator<string> args, float defaultValue = 0f) { if (args == null || !args.MoveNext()) { return defaultValue; } try { return float.Parse(args.Current, CultureInfo.InvariantCulture.NumberFormat); } catch (Exception arg) { logger?.LogWarning($"CommandArgsReader: {arg}"); return defaultValue; } } public string ReadString(IEnumerator<string> args, string defaultValue = "") { if (args != null && args.MoveNext()) { return args.Current; } return defaultValue; } public bool ReadBool(IEnumerator<string> args, bool defaultValue = false) { if (args == null || !args.MoveNext()) { return defaultValue; } try { return bool.Parse(args.Current.ToLower()); } catch (Exception arg) { logger?.LogWarning($"CommandArgsReader: {arg}"); return defaultValue; } } } public static class UtilityRandom { private static readonly Random rnd = new Random(Guid.NewGuid().GetHashCode()); public static T GetRandomItemFromList<T>(IList<T> list) { if (list != null && list.Count > 0) { return list[rnd.Next(list.Count)]; } return default(T); } } public class HelperCommandManagerFormatted : ICommandManager { private Dictionary<string, string> commandsDict; private readonly IDebugLogger logger; private readonly string errorString = string.Empty; public int logCommandMaxLength = 50; public bool isUseLogCommandLimit = true; public HelperCommandManagerFormatted(IDebugLogger logger) { this.logger = logger; } public virtual void InitFromFile(string path) { try { Dictionary<string, string> dictionary = UtilityJson.Generate(logger).FromFile<Dictionary<string, string>>(path); commandsDict = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase); CheckLoadedDict(); } catch (Exception arg) { logger?.LogError($"HelperCommandManagerFormatted InitFromFile load: {arg}"); commandsDict = null; } } public virtual void InitFromString(string data) { try { Dictionary<string, string> dictionary = UtilityJson.Generate(logger).FromString<Dictionary<string, string>>(data); commandsDict = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase); CheckLoadedDict(); } catch (Exception arg) { logger?.LogError($"HelperCommandManagerFormatted InitFromString load: {arg}"); commandsDict = null; } } protected virtual void CheckLoadedDict() { if (commandsDict == null) { logger?.LogWarning("HelperCommandManagerFormatted: commandsDict null"); return; } logger?.LogInfo($"HelperCommandManagerFormatted: found commands {commandsDict.Count}"); foreach (KeyValuePair<string, string> item in commandsDict) { logger?.LogDebugInfo("command: key=" + item.Key + ", value=" + GetSubstringCmd(item.Value)); } } protected virtual string GetSubstringCmd(string cmd) { if (isUseLogCommandLimit && cmd != null) { if (cmd.Length > logCommandMaxLength) { return cmd.Substring(0, logCommandMaxLength) + "..."; } return cmd; } return cmd; } public virtual string GetCommandData(string eventKey, bool isLogError = false) { if (commandsDict == null) { logger?.LogWarning("HelperCommandManagerFormatted GetCommandData: commandsDict null"); return ""; } try { eventKey = eventKey.Trim(); string text = commandsDict[eventKey]; if (text != null) { return text; } throw new NullReferenceException(); } catch (Exception arg) { if (isLogError) { logger?.LogError($"HelperCommandManagerFormatted key {eventKey}, error: {arg}"); } return errorString; } } public virtual string[] GetCommands() { if (commandsDict == null) { logger?.LogWarning("HelperCommandManagerFormatted GetCommands: commandsDict null"); return new string[0]; } List<string> list = new List<string>(); foreach (KeyValuePair<string, string> item in commandsDict) { list.Add(item.Value); } return list.ToArray(); } } public class HelperDictManager : IDictManager { private readonly ILogger logger; private readonly IEventsDataEncoder encoder; private readonly IEventsDataEncoderParams encoderParams; public HelperDictManager(ILogger logger = null) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown this.logger = logger; encoderParams = (IEventsDataEncoderParams)(object)(encoder = (IEventsDataEncoder)new EventsDataEncoder()); } public Dictionary<string, string> ParseDict(string data) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); try { string[] array = data.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); if (array == null) { logger?.LogError("HelperDictManager error, wrong args. Source: " + data); return dictionary; } string[] array2 = array; foreach (string text in array2) { string[] array3 = text.Split(new char[1] { encoderParams.ClientAppSepChar }, StringSplitOptions.RemoveEmptyEntries); if (array3.Length != 2) { logger?.LogWarning("HelperDictManager, invalid item: " + text); continue; } string text2 = array3[0]; string text3 = array3[1]; if (text3 == null || text2 == null) { logger?.LogWarning("HelperDictManager, invalid key/val: " + text2 + "/" + text3); continue; } string key = encoder.Decode(text2).Trim(); string value = encoder.Decode(text3).Trim(); dictionary.Add(key, value); } } catch (Exception arg) { logger?.LogError($"HelperDictManager error: {arg}"); } return dictionary; } } public class HelperCommandManager : ICommandManager { private readonly Dictionary<string, string> commandsDict; private readonly IDebugLogger logger; private readonly string errorString = string.Empty; public HelperCommandManager(IDebugLogger logger, string commandsDir, string commandsFname = "commands.data") { this.logger = logger; try { string path = Path.Combine(commandsDir, commandsFname); IDictManager dictManager = new HelperDictManager(); using StreamReader streamReader = new StreamReader(path); string data = streamReader.ReadToEnd(); Dictionary<string, string> dictionary = dictManager.ParseDict(data); commandsDict = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase); logger?.LogInfo($"HelperCommandManager: found commands {commandsDict.Count}"); foreach (KeyValuePair<string, string> item in commandsDict) { logger?.LogDebugInfo("command: key=" + item.Key + ", value=" + item.Value); } } catch (Exception arg) { logger?.LogError($"HelperCommandManager load: {arg}"); commandsDict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); } } public string GetCommandData(string eventKey, bool isLogError = false) { try { eventKey = eventKey.Trim(); string text = commandsDict[eventKey]; if (text != null) { return text; } throw new NullReferenceException(); } catch (Exception arg) { if (isLogError) { logger?.LogError($"HelperCommandManager key {eventKey}: {arg}"); } return errorString; } } public string[] GetCommands() { List<string> list = new List<string>(); foreach (KeyValuePair<string, string> item in commandsDict) { list.Add(item.Value); } return list.ToArray(); } public virtual void InitFromFile(string path) { throw new NotImplementedException(); } public virtual void InitFromString(string data) { throw new NotImplementedException(); } } public class HelperEventManager<CustomEvent> : IEventManager<CustomEvent> where CustomEvent : class, IEvent { private readonly Dictionary<string, CustomEvent> eventsDict; private readonly IDebugLogger logger; public HelperEventManager(IDebugLogger logger) { this.logger = logger; eventsDict = new Dictionary<string, CustomEvent>(StringComparer.OrdinalIgnoreCase); try { Type type = typeof(CustomEvent); IEnumerable<Type> enumerable = from p in AppDomain.CurrentDomain.GetAssemblies().SelectMany(delegate(Assembly s) { try { return s.GetTypes(); } catch (Exception) { return new Type[0]; } }) where p.IsClass && !p.IsAbstract && !p.IsInterface && type.IsAssignableFrom(p) select p; logger?.LogInfo($"HelperEventManager: found {enumerable.Count()} events"); foreach (Type item in enumerable) { CustomEvent val = Activator.CreateInstance(item) as CustomEvent; if (val != null) { eventsDict.Add(val.Id, val); logger?.LogDebugInfo("init event '" + val.Id + "' complete"); } else { logger?.LogWarning("init event '" + val.Id + "' failed"); } } } catch (Exception arg) { logger?.LogError($"HelperEventManager error: {arg}"); } } public HelperEventManager(IDebugLogger logger, IEventManager<IEvent> manager) { this.logger = logger; eventsDict = new Dictionary<string, CustomEvent>(StringComparer.OrdinalIgnoreCase); string name = typeof(CustomEvent).Name; try { foreach (IEvent item in manager.GetEventsCollection()) { if (item is CustomEvent val) { eventsDict.Add(val.Id, val); logger?.LogDebugInfo("init event '" + val.Id + "' as '" + name + "' complete"); } } } catch (Exception arg) { logger?.LogError($"HelperEventManager: {arg}"); } } public IEnumerable<CustomEvent> GetEventsCollection() { if (eventsDict == null) { return new List<CustomEvent>(); } return eventsDict.Values; } public CustomEvent GetEvent(string eventID, bool isLogError = false) { try { eventID = eventID.Trim(); CustomEvent val = eventsDict[eventID]; if (val != null) { return val; } throw new NullReferenceException(); } catch (Exception arg) { if (isLogError) { logger?.LogError($"HelperCommandManager key {eventID}: {arg}"); } return null; } } } public class HelperLanguagesFormatted : ITranslation { protected Dictionary<string, Text> transDict; protected readonly IDebugLogger logger; protected readonly string errorString = "trans_error"; public bool isLogOnlyEnItems; public bool isSuppressLogItems = true; public HelperLanguagesFormatted(IDebugLogger logger) { this.logger = logger; } public virtual void InitFromFile(string path) { try { Dictionary<string, Text> dictionary = UtilityJson.Generate(logger).FromFile<Dictionary<string, Text>>(path); transDict = new Dictionary<string, Text>(dictionary, StringComparer.OrdinalIgnoreCase); CheckLoadedDict(); } catch (Exception arg) { logger?.LogError($"HelperLanguagesFormatted InitFromFile load: {arg}"); transDict = null; } } public virtual void InitFromString(string data) { try { Dictionary<string, Text> dictionary = UtilityJson.Generate(logger).FromString<Dictionary<string, Text>>(data); transDict = new Dictionary<string, Text>(dictionary, StringComparer.OrdinalIgnoreCase); CheckLoadedDict(); } catch (Exception arg) { logger?.LogError($"HelperLanguagesFormatted InitFromString load: {arg}"); transDict = null; } } protected virtual void CheckLoadedDict() { if (transDict == null) { logger?.LogWarning("HelperLanguagesFormatted: transDict null"); return; } logger?.LogInfo($"HelperLanguagesFormatted: found translates {transDict.Count}"); if (isSuppressLogItems || logger == null) { return; } foreach (KeyValuePair<string, Text> item in transDict) { if (isLogOnlyEnItems) { logger.LogDebugInfo("key=" + item.Key + ", en=" + item.Value.en); continue; } logger.LogDebugInfo("key=" + item.Key + ", ru=" + item.Value.ru + ", en=" + item.Value.en); } } public virtual string GetTrans(string key, Languages lang) { return GetTrans(key, lang.ToString()); } public virtual string GetTrans(string key, string lang) { if (transDict == null) { logger?.LogWarning("HelperLanguagesFormatted transDict is null"); return errorString; } try { key = key.Trim(); lang = lang.Trim(); return transDict[key].GetTrans(lang); } catch (Exception arg) { logger?.LogError($"HelperLanguagesFormatted key {key} lang {lang}, error: {arg}"); return errorString; } } } public class HelperLog : ILoggerWithConsole, ILogger { protected readonly string path; protected const string baseLogName = "interactive_mod_log.txt"; public bool isLogConsole = true; public bool isLogFile = true; public ConsoleColor infoColor = ConsoleColor.White; public ConsoleColor warningColor = ConsoleColor.Yellow; public ConsoleColor errorColor = ConsoleColor.Red; protected virtual string LogTime => DateTime.Now.ToString("h:mm:ss:fff"); public HelperLog(string logDir) : this(logDir, "interactive_mod_log.txt") { } public HelperLog(string logDir, string logFname) { if (logDir == "" || Directory.Exists(logDir)) { path = Path.Combine(logDir, logFname); } } protected virtual void WriteToFile(string s) { if (path != null) { using (StreamWriter streamWriter = new StreamWriter(path, append: true, Encoding.UTF8)) { streamWriter.WriteLine(s); } } } public virtual void Log(object obj) { if (isLogFile) { WriteToFile($"{LogTime} {obj}"); } } public virtual void LogConsole(string text, string prefix, ConsoleColor prefixColor) { Console.ForegroundColor = prefixColor; Console.Write(LogTime + " " + prefix + " "); Console.ResetColor(); Console.WriteLine(text); } protected virtual void LogWithConsole(object obj, string prefix, ConsoleColor color) { Log($"{prefix} {obj}"); if (isLogConsole) { LogConsole(obj.ToString(), prefix, color); } } public virtual void LogInfo(object obj) { LogWithConsole(obj, "[INFO]", infoColor); } public virtual void LogWarning(object obj) { LogWithConsole(obj, "[WARNING]", warningColor); } public virtual void LogError(object obj) { LogWithConsole(obj, "[ERROR]", errorColor); } public virtual void LogInfoConsoleOnly(object obj) { if (isLogConsole) { LogConsole(obj.ToString(), "[INFO]", infoColor); } } public virtual void LogWarningConsoleOnly(object obj) { if (isLogConsole) { LogConsole(obj.ToString(), "[WARNING]", warningColor); } } public virtual void LogErrorConsoleOnly(object obj) { if (isLogConsole) { LogConsole(obj.ToString(), "[ERROR]", errorColor); } } public virtual void LogInfoFileOnly(object obj) { Log($"[INFO] {obj}"); } public virtual void LogWarningFileOnly(object obj) { Log($"[WARNING] {obj}"); } public virtual void LogErrorFileOnly(object obj) { Log($"[ERROR] {obj}"); } public virtual void LogClear() { if (path != null) { using (new StreamWriter(path)) { } } } } public class HelperParse : IParseManager { private readonly ILogger logger; public HelperParse(ILogger logger = null) { this.logger = logger; } public Type GetEnumUnderlyingType(Type type) { if (!type.IsEnum) { return type; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (fields != null && fields.Length >= 1) { return fields[0].FieldType; } return type; } public bool TryParseEnum<TEnum>(string arg, out TEnum result, TEnum defaultValue = default(TEnum)) { Type typeFromHandle = typeof(TEnum); try { Type enumUnderlyingType = GetEnumUnderlyingType(typeFromHandle); if ((object)enumUnderlyingType == typeof(int)) { if (int.TryParse(arg, out var result2) && Enum.IsDefined(typeFromHandle, result2)) { result = (TEnum)Enum.ToObject(typeFromHandle, result2); return true; } logger?.LogWarning("TryParseEnum can't parse int from " + arg + " for enum " + typeFromHandle.Name); } else if ((object)enumUnderlyingType == typeof(sbyte)) { if (sbyte.TryParse(arg, out var result3) && Enum.IsDefined(typeFromHandle, result3)) { result = (TEnum)Enum.ToObject(typeFromHandle, result3); return true; } logger?.LogWarning("TryParseEnum can't parse sbyte from " + arg + " for enum " + typeFromHandle.Name); } else { foreach (TEnum value in Enum.GetValues(typeFromHandle)) { if (Enum.GetName(typeFromHandle, value).Equals(arg, StringComparison.OrdinalIgnoreCase)) { result = value; return true; } } logger?.LogWarning("TryParseEnum can't find item by direct name " + arg + " for enum " + typeFromHandle.Name); } } catch (Exception arg2) { logger?.LogError($"TryParseEnum error happened when process {arg} for enum {typeFromHandle.Name}: {arg2}"); } result = defaultValue; return false; } public bool TryParseBool(string arg, out bool result, bool defaultValue = false) { if (bool.TryParse(arg, out result)) { return true; } if (int.TryParse(arg, out var result2)) { result = result2 != 0; return true; } logger?.LogWarning($"TryParseBool error happened when process {arg}. Will be used default {defaultValue}"); result = defaultValue; return false; } } public class UtilityJson { private static Func<IJsonUtil> customGenerator; public static IJsonUtil Generate(IDebugLogger logger) { if (customGenerator == null) { return new HelperJson(logger, File.Exists(".mod_json_debug")); } return customGenerator(); } public static void RegisterCustomGenerator(Func<IJsonUtil> generator) { customGenerator = generator; } } public class UtilitySettings { public static string CommandUpdateSettingsID => "command_update_parameters"; public static string BaseFolder { get; set; } = "ChaosTricks_InteractiveModData"; public static string SettingsFileName => "settings.txt"; public static string SettingsPath => Path.Combine(BaseFolder, SettingsFileName); public static T LoadSettings<T>(IDebugLogger logger) where T : class { string text = string.Empty; try { text = SettingsPath; T result = UtilityJson.Generate(logger).FromFile<T>(text); logger?.LogInfo("settings loaded"); return result; } catch (FileNotFoundException) { logger?.LogWarning("can't load settings. File not found at " + text + ". Using standard."); } catch (Exception arg) { logger?.LogError($"can't load settings. Using standard. \n{arg}"); } T result2 = null; try { result2 = Activator.CreateInstance<T>(); return result2; } catch (Exception arg2) { logger?.LogError($"can't create default data class. \n{arg2}"); } return result2; } } public enum Languages { ru, en } public class Text { public string ru; public string en; public Text(string ru, string en) { this.ru = ru; this.en = en; } public Text() { } public string GetTrans(Languages lang) { if (lang != Languages.en) { return ru; } return en; } public string GetTrans(string lang) { if (GetLangFromAppLang(lang) != Languages.en) { return ru; } return en; } private Languages GetLangFromAppLang(string lang) { lang = lang?.Trim()?.ToLower(); switch (lang) { default: return Languages.en; case "ru": case "russian": case "rus": case "русский": case "ру": case "рус": return Languages.ru; } } } public class HelperLanguages : ITranslation { private readonly Dictionary<string, Text> transDict; private readonly ILogger logger; private readonly string errorString = "trans_error"; public HelperLanguages(ILogger logger, string langsDir, string langsFname = "langs.data") { this.logger = logger; try { string path = Path.Combine(langsDir, langsFname); IDictManager dictManager = new HelperDictManager(logger); using (StreamReader streamReader = new StreamReader(path)) { string data = streamReader.ReadToEnd(); Dictionary<string, string> source = dictManager.ParseDict(data); transDict = GetTransDict(source); } logger?.LogInfo($"HelperLanguages: found translates {transDict.Count}"); } catch (Exception arg) { logger?.LogError($"HelperLanguages load: {arg}"); transDict = new Dictionary<string, Text>(StringComparer.OrdinalIgnoreCase); } } protected Dictionary<string, Text> GetTransDict(Dictionary<string, string> source) { Dictionary<string, Text> dictionary = new Dictionary<string, Text>(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair<string, string> item in source) { string[] array = item.Value.Split(new string[1] { "%lang%" }, StringSplitOptions.RemoveEmptyEntries); if (array == null || array.Length != 2) { logger?.LogError("HelperLanguages parse item: " + item.Key); continue; } string ru = array[0]; string en = array[1]; dictionary.Add(item.Key, new Text(ru, en)); } return dictionary; } public string GetTrans(string key, Languages lang) { return GetTrans(key, lang.ToString()); } public string GetTrans(string key, string lang) { try { key = key.Trim(); lang = lang.Trim(); return transDict[key].GetTrans(lang); } catch (Exception arg) { logger?.LogError($"HelperLanguages key {key} lang {lang}: {arg}"); return errorString; } } public virtual void InitFromFile(string path) { throw new NotImplementedException(); } public void InitFromString(string data) { throw new NotImplementedException(); } } } namespace ModHelper.Interfaces { public interface ICommandTargets { bool IsAllPlayers { get; } } public interface IConsoleCommandWithData : IConsoleCommand { bool Execute(IEnumerable<string> args, IEventsData data); } public interface IConsoleCommand { string Id { get; } bool Execute(IEnumerable<string> args); bool IsValidCommandArgs(IEnumerable<string> args); } public interface IDebugLogger : ILoggerWithConsole, ILogger { void LogDebugInfo(object obj); void LogDebugWarning(object obj); void LogDebugError(object obj); } public interface ILoggerWithConsole : ILogger { void LogInfoConsoleOnly(object obj); void LogWarningConsoleOnly(object obj); void LogErrorConsoleOnly(object obj); void LogInfoFileOnly(object obj); void LogWarningFileOnly(object obj); void LogErrorFileOnly(object obj); } public interface ICommandNotify { string ProcessMsg(string msg); } public interface ICommand { string Id { get; } } public interface IDictionaryItem<T> { string Key { get; } T Value { get; } } public interface IJsonUtil { T FromFile<T>(string path) where T : class; T FromString<T>(string s) where T : class; } public interface IDictManager { Dictionary<string, string> ParseDict(string data); } public interface ICommandManager { string GetCommandData(string eventKey, bool isLogError = false); string[] GetCommands(); void InitFromString(string data); void InitFromFile(string path); } public interface IEventManager<CustomEvent> { CustomEvent GetEvent(string eventID, bool isLogError = false); IEnumerable<CustomEvent> GetEventsCollection(); } public interface IEventWithData : IEvent { bool Execute(IEventsData data); } public interface IEvent { string Id { get; } bool Execute(); } public interface ILogger { void Log(object obj); void LogInfo(object obj); void LogWarning(object obj); void LogError(object obj); void LogClear(); } public interface ITranslation { string GetTrans(string key, Languages lang); string GetTrans(string key, string lang); void InitFromString(string data); void InitFromFile(string path); } public interface IParseManager { bool TryParseEnum<TEnum>(string arg, out TEnum result, TEnum defaultValue = default(TEnum)); bool TryParseBool(string arg, out bool result, bool defaultValue = false); } }
ChaosTricks_REPO_plugins/ModHelperUnity.dll
Decompiled 3 weeks agousing 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.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using EventsIO.Interfaces; using ModHelper; using ModHelper.Interfaces; using ModHelperUnity.Data; using ModHelperUnity.Interfaces; using ModHelperUnity.UtilityGUI; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ModHelperUnity")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("BFT")] [assembly: AssemblyProduct("ModHelperUnity")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("4afa0e1e-341b-4554-97c1-0c38ad74f246")] [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 ModHelperUnity { public abstract class TypedNotifyBase : MonoBehaviour, IComponentTypedNotify { private bool isDisposed; private Queue<TypedNotifyMessage> messages; private bool isInitiated; private bool isMessageProcessed; private float delayAfterNotify; private bool isShowAnimationStageFinished; private bool isShowMessageStageFinished; private bool isHideAnimationStageFinished; protected int logLimit; protected IDebugLogger logger; protected Dictionary<string, Texture2D> messageTextures = new Dictionary<string, Texture2D>(); protected readonly Dictionary<string, IPostProcessText> postProcessEvents = new Dictionary<string, IPostProcessText>(); public TypedNotifySettings Settings { get; protected set; } protected TypedNotifyMessage CurrentMessage { get; private set; } protected TypedNotifyParameters CurrentNotifyParameters { get; private set; } protected virtual void Log(object obj) { IDebugLogger obj2 = logger; if (obj2 != null) { ((ILogger)obj2).LogInfo((object)$"TypedNotifyBase: {obj}"); } } protected virtual void LimitedLogError(object obj) { if (logLimit > 0 && logger != null) { ((ILogger)logger).LogError((object)$"TypedNotifyBase: {obj}"); logLimit--; } } protected virtual Texture2D GetMessageTexture(string type) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown if (!messageTextures.ContainsKey(type)) { return new Texture2D(2, 2); } return messageTextures[type]; } protected void LoadFadeSettings(string settingsFilePath, Func<string, byte[]> customFileReader = null) { try { if (customFileReader == null) { Settings = UtilityJson.Generate(logger).FromFile<TypedNotifySettings>(settingsFilePath); } else { byte[] bytes = customFileReader(settingsFilePath); string @string = Encoding.UTF8.GetString(bytes); Settings = UtilityJson.Generate(logger).FromString<TypedNotifySettings>(@string); } } catch (Exception arg) { Log($"LoadFadeSettings error: {arg}"); } if (Settings == null) { Settings = new TypedNotifySettings(); } } protected Texture2D LoadImage(string imageFilePath, Func<string, byte[]> customFileReader = null) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown try { Texture2D val = UtilityUI.LoadImage(imageFilePath, customFileReader); Log($"LoadImage {imageFilePath}: width {((Texture)val).width}, height {((Texture)val).height}"); return val; } catch (Exception arg) { Log($"LoadImage {imageFilePath} error: {arg}"); return new Texture2D(2, 2, (TextureFormat)4, false); } } protected void LoadResources(string folderPath, Func<string, byte[]> customFileReader = null) { Log("LoadResources"); string text = "notify_settings.data"; string settingsFilePath = ((folderPath == null) ? text : Path.Combine(folderPath, text)); LoadFadeSettings(settingsFilePath, customFileReader); ClearMessageTextures(); if (Settings.notifyParameters != null) { TypedNotifyParameters[] notifyParameters = Settings.notifyParameters; foreach (TypedNotifyParameters typedNotifyParameters in notifyParameters) { Log(typedNotifyParameters.ToString()); string imageFilePath = ((folderPath == null) ? typedNotifyParameters.imageFileName : Path.Combine(folderPath, typedNotifyParameters.imageFileName)); Texture2D val = LoadImage(imageFilePath, customFileReader); messageTextures[typedNotifyParameters.type] = val; ((Texture)val).filterMode = (FilterMode)2; ((Texture)val).anisoLevel = 16; } } } public virtual void PostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null) { if (!isInitiated) { ForcePostInit(folderPath, logger, customFileReader); } Log("post init completed"); } public virtual void ForcePostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null) { this.logger = logger; try { messages = new Queue<TypedNotifyMessage>(); CurrentMessage = null; CurrentNotifyParameters = new TypedNotifyParameters(); logLimit = 10; isInitiated = true; LoadResources(folderPath, customFileReader); } catch (Exception arg) { Log($"ForcePostInit error: {arg}"); } Log("force init"); } protected virtual string ProcessCustomTemplates(string message, IEventsData eventData, ITranslation translation) { try { return Regex.Replace(message, "%template_.+?%", (Match s) => translation.GetTrans(s.Value, eventData.Lang)); } catch (Exception arg) { Log($"ProcessCustomTemplates error: {arg}"); return message; } } protected virtual string GenerateMessage(IEventsData eventData, ITranslation translation) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) TypedNotifyParameters typedNotifyParameters = GetTypedNotifyParameters(eventData); string trans = translation.GetTrans(eventData.EventID, eventData.Lang); string message = typedNotifyParameters.messageTemplate.Replace("%name%", UtilityUI.GetColoredText(eventData.Username, typedNotifyParameters.nicknameTextColor)).Replace("%message%", UtilityUI.GetColoredText(trans, typedNotifyParameters.messageTextColor)); return ProcessCustomTemplates(message, eventData, translation); } public virtual TypedNotifyParameters GetTypedNotifyParameters(string type) { TypedNotifyParameters[] notifyParameters = Settings.notifyParameters; if (notifyParameters == null || notifyParameters.Length == 0) { Log("warning, notify types empty (use default)"); return new TypedNotifyParameters(); } TypedNotifyParameters[] array = notifyParameters; foreach (TypedNotifyParameters typedNotifyParameters in array) { if (typedNotifyParameters.type == type) { return typedNotifyParameters; } } return notifyParameters[0]; } public virtual TypedNotifyParameters GetTypedNotifyParameters(IEventsData eventData) { TypedNotifyParameters[] notifyParameters = Settings.notifyParameters; if (notifyParameters == null || notifyParameters.Length == 0) { Log("warning, notify types empty (use default)"); return new TypedNotifyParameters(); } TypedNotifyParameters[] array = notifyParameters; foreach (TypedNotifyParameters typedNotifyParameters in array) { string[] events = typedNotifyParameters.events; if (events != null && events.Contains(eventData.EventID)) { return typedNotifyParameters; } } return notifyParameters[0]; } public virtual void AddNotifyToQueue(IEventsData eventData, ITranslation translation, Func<string, string> converter = null, bool applyUpperCase = true) { if (eventData == null) { Log("warning, eventData is null"); } if (translation == null) { Log("warning, translation is null"); } TypedNotifyParameters typedNotifyParameters = GetTypedNotifyParameters(eventData); string text = GenerateMessage(eventData, translation); if (converter != null) { text = converter(text); } text = PostProcessEvent(text, eventData.EventID, eventData.Lang); AddNotifyToQueue(new TypedNotifyMessage(applyUpperCase ? text.ToUpperInvariant() : text, typedNotifyParameters.type, typedNotifyParameters.showMessageDuration, typedNotifyParameters.showFadeAnimationDuration, typedNotifyParameters.hideFadeAnimationDuration)); } public virtual void AddNotifyToQueue(string message, string type) { TypedNotifyParameters typedNotifyParameters = GetTypedNotifyParameters(type); AddNotifyToQueue(new TypedNotifyMessage(message, type, typedNotifyParameters.showMessageDuration, typedNotifyParameters.showFadeAnimationDuration, typedNotifyParameters.hideFadeAnimationDuration)); } public virtual void AddNotifyToQueue(TypedNotifyMessage notifyMessage) { if (!isInitiated) { Log("error, attempt to use the manager before init completed"); return; } if (notifyMessage == null) { Log("error, message is null"); return; } messages.Enqueue(notifyMessage); Log("add new notify message: " + notifyMessage.message); } public virtual void ClearNotifyQueue() { if (isInitiated) { messages.Clear(); } } public virtual void StopCurrentNotify() { CurrentMessage = null; isShowAnimationStageFinished = true; isShowMessageStageFinished = true; isHideAnimationStageFinished = true; isMessageProcessed = false; } protected virtual void Update() { try { if (!isInitiated) { return; } if (CurrentMessage == null) { if (delayAfterNotify > 0f) { delayAfterNotify -= Time.deltaTime; } else if (messages.Count > 0) { CurrentMessage = messages.Peek(); CurrentNotifyParameters = GetTypedNotifyParameters(CurrentMessage.messageType); delayAfterNotify = CurrentNotifyParameters.delayAfterNotify; StartShowAnimation(); } return; } if (!isShowAnimationStageFinished) { UpdateProcessShowAnimation(); } else if (!isShowMessageStageFinished) { UpdateProcessNoAnimationStage(); } else if (!isHideAnimationStageFinished) { UpdateProcessHideAnimation(); } if (isMessageProcessed) { messages.Dequeue(); CurrentMessage = null; isMessageProcessed = false; } } catch (Exception obj) { LimitedLogError(obj); } } protected virtual void UpdateProcessShowAnimation() { if (CurrentMessage.showFadeAnimationDuration > 0f) { CurrentMessage.showFadeAnimationDuration -= Time.deltaTime; } else { FinishShowAnimation(); } } protected virtual void UpdateProcessNoAnimationStage() { if (CurrentMessage.showMessageDuration > 0f) { CurrentMessage.showMessageDuration -= Time.deltaTime; } else { StartHideAnimation(); } } protected virtual void UpdateProcessHideAnimation() { if (CurrentMessage.hideFadeAnimationDuration > 0f) { CurrentMessage.hideFadeAnimationDuration -= Time.deltaTime; } else { FinishHideAnimation(); } } protected virtual void Start() { } protected virtual void Awake() { } protected virtual void OnGUI() { } protected virtual void StartShowAnimation() { isShowAnimationStageFinished = false; Log("start show animation"); } protected virtual void FinishShowAnimation() { isShowAnimationStageFinished = true; isShowMessageStageFinished = false; Log("finish show animation"); } protected virtual void StartHideAnimation() { isHideAnimationStageFinished = false; isShowMessageStageFinished = true; Log("start hide animation"); } protected virtual void FinishHideAnimation() { isHideAnimationStageFinished = true; isMessageProcessed = true; Log("finish hide animation"); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void ClearMessageTextures() { if (messageTextures == null) { return; } foreach (Texture2D value in messageTextures.Values) { ((Object)value).hideFlags = (HideFlags)61; Object.Destroy((Object)(object)value); } } protected virtual void Dispose(bool disposing) { if (!isDisposed) { ClearMessageTextures(); messageTextures = null; isDisposed = true; } } ~TypedNotifyBase() { try { Dispose(disposing: false); } finally { ((object)this).Finalize(); } } public void RegisterPostProcessEvent(string key, IPostProcessText e) { if (string.IsNullOrEmpty(key) || e == null) { IDebugLogger obj = logger; if (obj != null) { ((ILogger)obj).LogError((object)("TypedNotifyOnGUI RegisterPostProcessEvent invalid arg error for key '" + key + "'")); } } else { postProcessEvents[key] = e; } } protected string PostProcessEvent(string text, string eventKey, string langKey) { if (string.IsNullOrEmpty(eventKey) || text == null) { IDebugLogger obj = logger; if (obj != null) { ((ILogger)obj).LogWarning((object)("TypedNotifyOnGUI PostProcessEvent invalid arg error for key '" + eventKey + "', text " + text)); } return text; } if (!postProcessEvents.TryGetValue(eventKey, out var value)) { return text; } return value.PostProcessText(text, langKey); } } public static class UtilityUI { public static int StandardScreenWidth => 2560; public static int StandardScreenHeight => 1440; public static string GetColoredText(string text, Color32 color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) string text2 = ColorUtility.ToHtmlStringRGBA(Color32.op_Implicit(color)); return "<color=#" + text2 + ">" + text + "</color>"; } public static Texture2D LoadImage(string imageFilePath, Func<string, byte[]> customFileReader = null) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0025: Expected O, but got Unknown byte[] array = ((customFileReader == null) ? File.ReadAllBytes(imageFilePath) : customFileReader(imageFilePath)); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ImageConversion.LoadImage(val, array); return val; } public static float CalcScreenFactor(int baseScreenSize, int currentScreenSize) { if (baseScreenSize != currentScreenSize) { return (float)currentScreenSize / (float)baseScreenSize; } return 1f; } } public class MathUtility { public static bool RandomBool() { return Random.value > 0.5f; } public static int GetRandomSign() { if (!RandomBool()) { return 1; } return -1; } public static Vector3 GetRandomPointOnCircle(float radius = 1f) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) Vector2 insideUnitCircle = Random.insideUnitCircle; return Vector2.op_Implicit(((Vector2)(ref insideUnitCircle)).normalized * radius); } public static Vector3 GetRandomPointOnCircleInForward(Vector3 forward, float radiusMin, float radiusMax, float minAngleInDeg = -90f, float maxAngleInDeg = 90f) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) Vector3 val = forward; val.y = 0f; val = ((Vector3)(ref val)).normalized; if (minAngleInDeg > maxAngleInDeg) { float num = minAngleInDeg; minAngleInDeg = maxAngleInDeg; maxAngleInDeg = num; } float num2 = Random.Range(minAngleInDeg, maxAngleInDeg); if (radiusMin < 0f) { radiusMin = 0f; } if (radiusMax < 0f) { radiusMax = 1f; } if (radiusMin > radiusMax) { float num3 = radiusMin; radiusMin = radiusMax; radiusMax = num3; } float num4 = Random.Range(radiusMin, radiusMax); Vector3 result = default(Vector3); float num5 = (float)Math.PI / 180f * num2; float num6 = Mathf.Atan2(val.z, val.x); num5 += num6; result.x = num4 * Mathf.Cos(num5); result.z = num4 * Mathf.Sin(num5); return result; } public static Vector3 FindRandomSpawnPointNearPosition(Vector3 pos, float minDistance, float maxDistance) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if (maxDistance < 0f) { maxDistance = 10f; } if (minDistance < 0f || minDistance > maxDistance) { minDistance = 0f; } Vector3 result = default(Vector3); float num = Random.Range(-(float)Math.PI, (float)Math.PI); float num2 = Random.Range(minDistance, maxDistance); result.x = Mathf.Floor(pos.x + num2 * Mathf.Cos(num)); result.z = Mathf.Floor(pos.z + num2 * Mathf.Sin(num)); result.y = pos.y; return result; } public static Vector3 FindRandomSpawnPointNearPositionFixY(Vector3 pos, float minDistance, float maxDistance, float yFixOffset, LayerMask mask) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_003f: Unknown result type (might be due to invalid IL or missing references) Vector3 result = FindRandomSpawnPointNearPosition(pos, minDistance, maxDistance); RaycastHit val = default(RaycastHit); if (Physics.Raycast(pos + Vector3.up * 10f, Vector3.down, ref val, 10f, LayerMask.op_Implicit(mask))) { result = ((RaycastHit)(ref val)).point; result.y += yFixOffset; } return result; } public static Vector3 GetRandomVector(Vector3 randomRangeMin, Vector3 randomRangeMax) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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) float num = Random.Range(randomRangeMin.x, randomRangeMax.x); float num2 = Random.Range(randomRangeMin.y, randomRangeMax.y); float num3 = Random.Range(randomRangeMin.z, randomRangeMax.z); return new Vector3(num, num2, num3); } public static void LookAt(Transform obj, Transform target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) Vector3 val = target.position - obj.position; obj.rotation = Quaternion.LookRotation(val); } } public static class Loader { private static ILogger logger; private static GameObject hookObj; private const string ASSEMBLY_NAME = "InteractiveMod"; private const string CLASS_MOD = "InteractiveMod"; public static GameObject HookObj { get; set; } static Loader() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown logger = (ILogger)new HelperLog(UtilitySettings.BaseFolder, "loader_log.txt"); logger.LogClear(); } public static async Task StartInitTask(Type type) { int counter = 0; do { await Task.Delay(5000); if ((Object)(object)hookObj == (Object)null) { logger.LogInfo((object)"Background task: trying to create mod instance"); hookObj = new GameObject(); Object.DontDestroyOnLoad((Object)(object)hookObj); hookObj.AddComponent(type); hookObj.SetActive(true); } int num = counter + 1; counter = num; } while (counter <= 10 && (!((Object)(object)hookObj != (Object)null) || counter <= 2)); logger.LogInfo((object)"Background task closed"); } public static void LoadAssembly() { logger.LogInfo((object)"load mod assembly"); Assembly assembly = AppDomain.CurrentDomain.Load("InteractiveMod"); CancellationToken token = new CancellationTokenSource().Token; if (!string.Equals(assembly.GetName().Name, "InteractiveMod", StringComparison.OrdinalIgnoreCase)) { logger.LogError((object)"wrong assembly mod name"); return; } Type[] types = assembly.GetTypes(); foreach (Type type in types) { bool num = string.Equals(type.Name, "InteractiveMod", StringComparison.OrdinalIgnoreCase); Type typeFromHandle = typeof(MonoBehaviour); if (!num || (!type.IsAssignableFrom(typeFromHandle) && !type.IsSubclassOf(typeFromHandle))) { continue; } logger.LogInfo((object)"Found valid type in Loader class"); Task.Factory.StartNew((Func<Task>)async delegate { try { await StartInitTask(type); } catch (Exception arg) { logger.LogError((object)$"LoadAssembly task error {arg}"); } }, token, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); return; } logger.LogError((object)"init failed"); } public static void Init() { logger.LogInfo((object)"Loader triggered"); try { LoadAssembly(); } catch (Exception arg) { logger.LogError((object)$"ModHelperUnity.Init {arg}"); } } } public class Patcher { private readonly ILogger logger = (ILogger)new HelperLog(UtilitySettings.BaseFolder, "patcher_log.txt"); private bool isPatched; internal void ExecutePatch() { try { logger.LogClear(); logger.LogInfo((object)$"Patcher v{Assembly.GetExecutingAssembly().GetName().Version}"); SceneManager.sceneLoaded += OnSceneLoaded; } catch (Exception arg) { logger.LogError((object)$"Patcher unexpected error: {arg}"); } } private void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode) { try { logger.Log((object)("OnSceneLoaded triggered: " + ((Scene)(ref scene)).name)); if (!isPatched) { Loader.Init(); isPatched = true; SceneManager.sceneLoaded -= OnSceneLoaded; } } catch (Exception arg) { logger.LogError((object)$"Patcher unexpected error: {arg}"); } } } public static class Preloader { private static string baseFolderFullPath; private static readonly ILogger logger = (ILogger)new HelperLog(UtilitySettings.BaseFolder, "preloader_log.txt"); public static string GetAssemblyModFolderFullPath() { return baseFolderFullPath; } public static void Main() { logger.LogClear(); logger.LogInfo((object)"Preloader main"); baseFolderFullPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); AppDomain.CurrentDomain.AssemblyResolve += ModAssemblyResolve; new Patcher().ExecutePatch(); } private static Assembly ModAssemblyResolve(object sender, ResolveEventArgs args) { try { string text = Path.Combine(GetAssemblyModFolderFullPath(), new AssemblyName(args.Name).Name + ".dll"); logger.LogInfo((object)text); if (File.Exists(text)) { return Assembly.LoadFrom(text); } } catch (Exception arg) { logger.LogError((object)$"error: {arg}"); } return null; } } } namespace ModHelperUnity.UtilityGUI { public class TypedNotifyOnGUI : TypedNotifyBase { private float currentAlpha; private float targetAlpha; protected Dictionary<string, Font> fonts; public override void ForcePostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null) { base.ForcePostInit(folderPath, logger, customFileReader); try { fonts = new Dictionary<string, Font>(); TypedNotifyParameters[] notifyParameters = base.Settings.notifyParameters; foreach (TypedNotifyParameters typedNotifyParameters in notifyParameters) { try { string fontPath = typedNotifyParameters.fontPath; if (!fonts.ContainsKey(fontPath)) { Font val = Resources.Load<Font>(fontPath); if ((Object)(object)val != (Object)null) { fonts.Add(fontPath, val); } } } catch (Exception arg) { if (logger != null) { ((ILogger)logger).LogError((object)$"TypedNotifyOnGUI loading font: {arg}"); } } } } catch (Exception arg2) { if (logger != null) { ((ILogger)logger).LogError((object)$"TypedNotifyOnGUI PostInit: {arg2}"); } } } protected Font GetFont(string path, int size) { try { if (fonts.ContainsKey(path)) { return fonts[path]; } string key = $"{path}_{size}"; if (fonts.ContainsKey(key)) { return fonts[key]; } Font val = Font.CreateDynamicFontFromOSFont(path, size); if ((Object)(object)val != (Object)null) { fonts.Add(key, val); } return val; } catch (Exception arg) { IDebugLogger obj = logger; if (obj != null) { ((ILogger)obj).LogError((object)$"TypedNotifyOnGUI finding font: {arg}"); } } return null; } protected virtual void SetupAlpha(float baseDuration) { if (!Mathf.Approximately(currentAlpha, targetAlpha)) { currentAlpha = Mathf.MoveTowards(currentAlpha, targetAlpha, Time.deltaTime / baseDuration); } } protected override void UpdateProcessShowAnimation() { SetupAlpha(base.CurrentNotifyParameters.showFadeAnimationDuration); base.UpdateProcessShowAnimation(); } protected override void UpdateProcessNoAnimationStage() { SetupAlpha(base.CurrentNotifyParameters.showMessageDuration); base.UpdateProcessNoAnimationStage(); } protected override void UpdateProcessHideAnimation() { SetupAlpha(base.CurrentNotifyParameters.hideFadeAnimationDuration); base.UpdateProcessHideAnimation(); } protected override void StartShowAnimation() { base.StartShowAnimation(); targetAlpha = 1f; } protected override void StartHideAnimation() { base.StartHideAnimation(); targetAlpha = 0f; } protected string GetFadedText(string text) { string text2 = ((int)(255f * currentAlpha)).ToString("X2"); return text.Replace("FF>", text2 + ">"); } protected override void OnGUI() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) base.OnGUI(); TypedNotifyParameters currentNotifyParameters = base.CurrentNotifyParameters; if (!base.Settings.isDisableNotify && base.CurrentMessage != null && currentNotifyParameters != null && !currentNotifyParameters.isDisable) { Matrix4x4 matrix = GUI.matrix; Color color = GUI.color; color.a = currentAlpha; GUI.color = color; Texture2D messageTexture = GetMessageTexture(base.CurrentMessage.messageType); float num = UtilityUI.CalcScreenFactor(UtilityUI.StandardScreenWidth, Screen.width); float num2 = UtilityUI.CalcScreenFactor(UtilityUI.StandardScreenHeight, Screen.height); float num3 = (float)((Texture)messageTexture).width * num; float num4 = (float)((Texture)messageTexture).height * num2; Rect val = default(Rect); ((Rect)(ref val)).x = ((float)Screen.width - num3) * (0.5f + currentNotifyParameters.notifyHorizontalOffset); ((Rect)(ref val)).y = ((float)Screen.height - num4) * (0.5f + currentNotifyParameters.notifyVerticalOffset); ((Rect)(ref val)).width = num3; ((Rect)(ref val)).height = num4; Rect val2 = val; float num5 = Math.Min(num, num2); float num6 = Math.Max(num, num2); int num7 = (int)((float)currentNotifyParameters.fontSize * num5); GUIStyle val3 = new GUIStyle(GUI.skin.label) { fontSize = num7, alignment = (TextAnchor)4, richText = true, fixedWidth = num3, fixedHeight = num4 }; Font font = GetFont(currentNotifyParameters.fontPath, num7); if ((Object)(object)font != (Object)null) { val3.font = font; } val3.padding.top = (int)((float)currentNotifyParameters.textPadding.top * num6); val3.padding.bottom = (int)((float)currentNotifyParameters.textPadding.bottom * num6); val3.padding.left = (int)((float)currentNotifyParameters.textPadding.left * num6); val3.padding.right = (int)((float)currentNotifyParameters.textPadding.right * num6); val3.normal.textColor = color; GUI.DrawTexture(val2, (Texture)(object)messageTexture); GUI.Label(val2, GetFadedText(base.CurrentMessage.message), val3); GUI.matrix = matrix; } } } public class TypedNotifySettings { public bool isDisableNotify; public TypedNotifyParameters[] notifyParameters = new TypedNotifyParameters[0]; public override string ToString() { if (notifyParameters == null) { return "TypedNotifySettings: not found notifyParameters"; } string text = $"isDisableNotify={isDisableNotify}"; TypedNotifyParameters[] array = notifyParameters; for (int i = 0; i < array.Length; i++) { _ = array[i]; text = string.Join(Environment.NewLine, text, "notifyParameters:", notifyParameters.ToString()); } return text; } } } namespace ModHelperUnity.Interfaces { public interface IComponentTypedNotify { void AddNotifyToQueue(string message, string type); void AddNotifyToQueue(IEventsData eventData, ITranslation translation, Func<string, string> converter = null, bool applyUpperCase = true); void ClearNotifyQueue(); void StopCurrentNotify(); void PostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null); void ForcePostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null); void RegisterPostProcessEvent(string key, IPostProcessText e); } public interface IPostProcessText { string PostProcessText(string text, string langKey); } public interface ISoundManager { void PlaySound(string path, int volume = 50); void StopSound(); } public interface IDictionaryItemJson<T> { string Key { get; } T Value { get; } } } namespace ModHelperUnity.Data { public class TypedNotifyParameters { public bool isDisable; public string imageFileName = string.Empty; public string type = "default"; public string messageTemplate = "%name% %message%"; public string fontPath = ""; public float showMessageDuration = 5f; public float showFadeAnimationDuration = 1f; public float hideFadeAnimationDuration = 1f; public float delayAfterNotify = 1f; public float notifyHorizontalOffset; public float notifyVerticalOffset = -0.45f; public int fontSize = 19; public Padding textPadding = new Padding { bottom = 20, top = 20, left = 24, right = 24 }; public Color32 nicknameTextColor = new Color32((byte)65, (byte)160, (byte)94, byte.MaxValue); public Color32 messageTextColor = new Color32((byte)65, (byte)160, (byte)94, byte.MaxValue); public string[] events = new string[0]; public override string ToString() { //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) return string.Join(Environment.NewLine, "imageFileName: " + imageFileName, "type: " + type, $"showMessageDuration: {showMessageDuration}", $"showFadeAnimationDuration: {showFadeAnimationDuration}", $"hideFadeAnimationDuration: {hideFadeAnimationDuration}", $"delayAfterNotify: {delayAfterNotify}", $"notifyHorizontalOffset: {notifyHorizontalOffset}", $"notifyVerticalOffset: {notifyVerticalOffset}", $"textPadding: {textPadding}", $"fontSize: {fontSize}", $"isDisable: {isDisable}", $"nicknameTextColor: {nicknameTextColor}", $"messageTextColor: {messageTextColor}", "events: " + string.Join(Environment.NewLine, events), "fontPath: " + fontPath); } } public class Padding { public int left; public int right; public int top; public int bottom; public Padding() { } public Padding(int left, int right, int top, int bottom) { this.left = left; this.right = right; this.top = top; this.bottom = bottom; } public RectOffset GetRect() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown return new RectOffset(left, right, top, bottom); } public override string ToString() { return $"left: {left}, right: {right}, top: {top}, bottom: {bottom}"; } } public class TypedNotifyMessage { public readonly string message; public readonly string messageType; public float showMessageDuration; public float showFadeAnimationDuration; public float hideFadeAnimationDuration; public TypedNotifyMessage(string message, string messageType, float showMessageDuration, float showFadeAnimationDuration, float hideFadeAnimationDuration) { this.message = (string.IsNullOrEmpty(message?.Trim()) ? string.Empty : message); this.messageType = messageType; this.showMessageDuration = showMessageDuration; this.showFadeAnimationDuration = showFadeAnimationDuration; this.hideFadeAnimationDuration = hideFadeAnimationDuration; } } public class NotifyMessage { private readonly string msg; private float durationInSec; public NotifyMessage(string msg, float durationInSec) { this.msg = (string.IsNullOrEmpty(msg?.Trim()) ? string.Empty : msg); this.durationInSec = durationInSec; } public string GetMessage() { return msg; } public bool IsFinished() { return durationInSec <= 0f; } public void OnFrame(float dtInSec) { if (!IsFinished()) { durationInSec -= dtInSec; } } } }
ChaosTricks_REPO_plugins/WebSocketIO.dll
Decompiled 3 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using EventsIO; using EventsIO.Interfaces; using ModHelper; using ModHelper.Interfaces; using WebSocketIO.Data; using WebSocketSharp; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("WebSocketIO")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("BFT")] [assembly: AssemblyProduct("WebSocketIO")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("27b98c5b-ac6a-4518-ae12-3c9957b291e4")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.0.0")] namespace WebSocketIO { public class ChaosWebSocketHandler { public const string TypeEventMessage = "event"; public const string TypeConfigMessage = "config"; public bool isEnableDebugLog = true; public bool isEnableDebugLogOnClose; public bool isEnableDebugLogOnOpen; public bool isEnableDebugLogOnCloseValidConnect = true; protected bool isNeedLogOnCloseValidConnect; protected ILogger logger; public Action<string, string> OnCustomMessage { get; set; } public Action<string> OnEventMessage { get; set; } public Action<string> OnConfigMessage { get; set; } public Action OnWebSocketOpen { get; set; } public Action<CloseEventArgs> OnWebSocketClose { get; set; } public Action<ErrorEventArgs> OnWebSocketError { get; set; } public ChaosWebSocketHandler(ILogger logger = null) { this.logger = logger; } protected void DebugWebSocketLog(string s) { if (isEnableDebugLog && logger != null) { logger.LogInfo((object)("[DEBUG] ChaosTricks WebSocketHandler: " + s)); } } protected void DebugWebSocketLogError(string s) { if (isEnableDebugLog && logger != null) { logger.LogError((object)("[DEBUG] ChaosTricks WebSocketHandler: " + s)); } } public void OnOpen() { if (isEnableDebugLogOnOpen) { DebugWebSocketLog("OnOpen"); } try { if (isEnableDebugLogOnCloseValidConnect) { isNeedLogOnCloseValidConnect = true; } OnWebSocketOpen?.Invoke(); } catch (Exception arg) { if (isEnableDebugLogOnOpen) { DebugWebSocketLogError($"OnOpen {arg}"); } } } public void OnClose(CloseEventArgs e) { if (isEnableDebugLogOnClose) { DebugWebSocketLog("OnClose " + e.Reason); } try { OnWebSocketClose?.Invoke(e); } catch (Exception arg) { if (isEnableDebugLogOnClose) { DebugWebSocketLogError($"OnClose {arg}"); } else if (isEnableDebugLogOnCloseValidConnect && isNeedLogOnCloseValidConnect) { isNeedLogOnCloseValidConnect = false; DebugWebSocketLogError($"OnClose {arg}"); } } } public void OnError(ErrorEventArgs e) { DebugWebSocketLogError("Error " + e.Message); try { OnWebSocketError?.Invoke(e); } catch (Exception arg) { DebugWebSocketLogError($"OnError inner error {arg}"); } } public WebSocketMessage ParseWebSocketMessage(string data) { try { return UtilityJson.Generate((IDebugLogger)null).FromString<WebSocketMessage>(data) ?? new WebSocketMessage(); } catch (Exception arg) { DebugWebSocketLogError($"ParseWebSocketMessage {arg}"); return new WebSocketMessage(); } } public void OnMessage(MessageEventArgs e) { if (!e.IsText) { return; } try { WebSocketMessage webSocketMessage = ParseWebSocketMessage(e.Data); string type = webSocketMessage.type; string data = webSocketMessage.data; if (!(type == "config")) { if (type == "event") { DebugWebSocketLog("OnMessage - event"); OnEventMessage?.Invoke(data); } else { DebugWebSocketLog("OnMessage - custom msg"); OnCustomMessage?.Invoke(type, data); } } else { DebugWebSocketLog("OnMessage - config"); OnConfigMessage?.Invoke(data); } } catch (Exception arg) { DebugWebSocketLogError($"OnMessage {arg}"); } } } public class WebSocketEventsReader<T> : EventsReaderOnFrame, IDisposable where T : class { protected object locker = new object(); protected List<string> eventListFromSocket = new List<string>(); protected bool isDisposed; protected bool isSocketMessageProcessing; public bool isAutoRequestSettingsOnOpen = true; public bool isAutoConnectOnRead = true; public const int DEFAULT_PORT = 13715; public float autoConnectOnReadPeriod = 8f; protected float autoConnectOnReadPeriodTicks; protected bool isNeedLogOnClose; public virtual ChaosWebSocketHandler SocketHandler { get; set; } public virtual WebSocket Socket { get; set; } public virtual T Settings { get; protected set; } public Action<MessageEventArgs> OnMessage { get; set; } public Action OnOpen { get; set; } public Action<CloseEventArgs> OnCloseOnlyAfterConnect { get; set; } public Action<ErrorEventArgs> OnErrorOnlyAfterConnect { get; set; } public Action<CloseEventArgs> OnClose { get; set; } public Action<ErrorEventArgs> OnError { get; set; } public WebSocketEventsReader(Action<IEventsData> processEvent, IEventsDataParser parser, Action<string> log = null, Action<string> errorLog = null, float checkPeriod = 2f, float delay = 1f, float initDelay = 0.5f) : base("", processEvent, parser, log, errorLog, checkPeriod, delay, initDelay) { } public virtual int GetPortFromSettingsOrDefault(string settingsDir) { try { string path = Path.Combine(settingsDir, "ChaosWebSocketConfig.txt"); if (File.Exists(path)) { return int.Parse(File.ReadAllLines(path)[0]); } } catch (Exception arg) { ((EventsReader)this).ReaderLogError($"GetPortFromSettingsOrDefault error: {arg}. (will be used {13715})"); } return 13715; } public virtual T ParseSettings(string data) { try { T result = UtilityJson.Generate((IDebugLogger)null).FromString<T>(data); ((EventsReader)this).ReaderLog("settings parsing completed: " + data); return result; } catch (Exception arg) { ((EventsReader)this).ReaderLogError($"error: {arg}.\nCan't parse settings. Using standard."); } T result2 = null; try { result2 = Activator.CreateInstance<T>(); return result2; } catch (Exception arg2) { ((EventsReader)this).ReaderLogError($"error: {arg2}.\nCan't create default data class."); return result2; } } public virtual void OpenSocket(bool isLogOnError = true) { try { WebSocket socket = Socket; if (socket != null && !socket.IsAlive) { ((EventsReader)this).ReaderLog("try to open socket connection"); socket.ConnectAsync(); } } catch (Exception arg) { if (isLogOnError) { ((EventsReader)this).ReaderLogError($"OpenSocket error: {arg}"); } } } public virtual void CloseSocket() { try { WebSocket socket = Socket; if (socket != null) { socket.Close(); } } catch (Exception arg) { ((EventsReader)this).ReaderLogError($"CloseSocket error: {arg}"); } } public virtual void RequestSettings() { try { WebSocket socket = Socket; if (socket != null) { socket.Send(new WebSocketMessage("config", "").ToString()); } } catch (Exception arg) { ((EventsReader)this).ReaderLogError($"RequestSettings error: {arg}"); } } public virtual void InitDefaultSocket(string settingsDir, string room, int port, string ip = "127.0.0.1") { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown WebSocket val = new WebSocket($"ws://{ip}:{port}/{room}", new string[0]); ChaosWebSocketHandler socketHandler = new ChaosWebSocketHandler { OnEventMessage = delegate(string data) { isSocketMessageProcessing = true; lock (locker) { eventListFromSocket.Add(data); } isSocketMessageProcessing = false; }, OnConfigMessage = delegate(string data) { Settings = ParseSettings(data); }, OnWebSocketOpen = delegate { isNeedLogOnClose = true; ((EventsReader)this).ReaderLog("ChaosTricks connected"); if (isAutoRequestSettingsOnOpen) { RequestSettings(); } try { OnOpen?.Invoke(); } catch (Exception arg6) { ((EventsReader)this).ReaderLogError($"ChaosTricks custom OnOpen error: {arg6}"); } }, OnWebSocketClose = delegate(CloseEventArgs e) { if (isNeedLogOnClose) { isNeedLogOnClose = false; ((EventsReader)this).ReaderLog($"ChaosTricks disconnected {e.Reason} {e.Code}"); try { OnCloseOnlyAfterConnect?.Invoke(e); } catch (Exception arg4) { ((EventsReader)this).ReaderLogError($"ChaosTricks custom OnClose after success connection error: {arg4}"); } } try { OnClose?.Invoke(e); } catch (Exception arg5) { ((EventsReader)this).ReaderLogError($"ChaosTricks custom OnClose error: {arg5}"); } }, OnWebSocketError = delegate(ErrorEventArgs e) { if (isNeedLogOnClose) { ((EventsReader)this).ReaderLog($"ChaosTricks ws error {e.Message} {e.Exception}"); try { OnErrorOnlyAfterConnect?.Invoke(e); } catch (Exception arg2) { ((EventsReader)this).ReaderLogError($"ChaosTricks custom OnError after success connection error: {arg2}"); } } try { OnError?.Invoke(e); } catch (Exception arg3) { ((EventsReader)this).ReaderLogError($"ChaosTricks custom OnError error: {arg3}"); } } }; val.OnMessage += delegate(object sender, MessageEventArgs e) { socketHandler.OnMessage(e); try { OnMessage?.Invoke(e); } catch (Exception arg) { ((EventsReader)this).ReaderLogError($"ChaosTricks custom OnMessage error: {arg}"); } }; val.OnOpen += delegate { socketHandler.OnOpen(); }; val.OnClose += delegate(object sender, CloseEventArgs e) { socketHandler.OnClose(e); }; val.OnError += delegate(object sender, ErrorEventArgs e) { socketHandler.OnError(e); }; if (!File.Exists(Path.Combine(settingsDir ?? "", ".debug_websocket"))) { val.Log.Level = (LogLevel)10; } SocketHandler = socketHandler; Socket = val; } public override string[] ReadAll(string path, bool isClearFile = true) { string[] result = null; if (!isSocketMessageProcessing) { lock (locker) { if (eventListFromSocket.Count > 0) { result = eventListFromSocket.ToArray(); eventListFromSocket.Clear(); } } } return result; } public override void ReadAndProcessAllWithDelayOnFrame(float dt) { if (isAutoConnectOnRead) { autoConnectOnReadPeriodTicks += dt; if (autoConnectOnReadPeriodTicks > autoConnectOnReadPeriod) { autoConnectOnReadPeriodTicks = 0f; OpenSocket(isLogOnError: false); } } ((EventsReaderOnFrame)this).ReadAndProcessAllWithDelayOnFrame(dt); } protected virtual void Dispose(bool disposing) { if (!isDisposed) { isDisposed = true; if (disposing) { ((IDisposable)Socket)?.Dispose(); } } } ~WebSocketEventsReader() { try { Dispose(disposing: false); } finally { ((object)this).Finalize(); } } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } } } namespace WebSocketIO.Interfaces { public interface IChaosWebSocket { void Start(); void Stop(); } } namespace WebSocketIO.Data { public class WebSocketMessage { public string type = ""; public string data = ""; public WebSocketMessage() { } public WebSocketMessage(string type, string data) { this.type = type; this.data = data; } public override string ToString() { string text = data.Replace("\"", "\\\""); return "{\"type\":\"" + type + "\", \"data\":\"" + text + "\"}"; } } }