Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ChaosTricks REPO TwitchIntegration v1.6.0
ChaosTricks_REPO_plugins/EventsIO.dll
Decompiled 6 months 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 6 months 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.Utilities; 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.6.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.6.0.0")] namespace REPO_BFT_BepInEx { [BepInPlugin("bft.chaostricks", "Chaos Tricks", "1.6.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 { SettingsUtils.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.6.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.6.0", arg)); } } } public sealed class InteractiveMod : MonoBehaviour { internal static InteractiveMod inst; internal const string MOD_VERSION = "1.6.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 CommandConsole 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 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.6.0"); FlushLog(); MainPatcher.InitPatch(); } public void Start() { ((HelperLog)logger).LogInfo((object)"InteractiveMod Start"); try { JsonUtils.RegisterCustomGenerator((Func<IJsonUtils>)(() => (IJsonUtils)(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 CommandConsole((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, true); 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, data.Lang, data.Username); NotifyEvent(data.EventID, data.Lang, data.Username, ignoreTruck: false); ChaosModNetwork.RequestNotifyOtherRPC(data.EventID, data.Lang, data.Username); 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")); NotifyEvent(data.EventID, data.Lang, data.Username, ignoreTruck: false); ChaosModNetwork.RequestNotifyOtherRPC(data.EventID, data.Lang, data.Username); } else { ((HelperDebugLog)logger).LogDebugError((object)("Event '" + data.EventID + "' executing is failed")); } } catch (Exception arg) { ((HelperLog)logger).LogError((object)$"ProcessCommands '{data.EventID}' unexpected error: {arg}"); } } public void NotifyEvent(string eventID, string lang, string username, bool ignoreTruck) { string trans = translationService.translation.GetTrans(eventID, lang); string trans2 = translationService.translation.GetTrans("%template_msg%", lang); string message = (username ?? "viewer") + " " + trans2 + " '" + trans + "'"; if (!ignoreTruck) { GameUtils.SendTruckChatMessage(message); } GameUtils.ShowUIMessage(message); } private void OnLevelGenerated() { try { ((HelperLog)Utils.logger).LogInfo((object)"OnLevelGenerated triggered"); SemiFunc_EnemySpawnPatcher.ClearBlockEnemies(); EnemyParentPatcher.ClearEnemies(); 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(); EnemyParentPatcher.ClearEnemies(); 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 : IJsonUtils { 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_001d: 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_003e: 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) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) PhysGrabber physGrabber = player.physGrabber; if ((Object)(object)physGrabber != (Object)null) { physGrabber.ReleaseObject(-1, 0.2f); } player.Spawn(pos, rot); Traverse.Create((object)player.tumble).Field<PhysGrabObject>("physGrabObject").Value.Teleport(pos, rot); ((Component)player).transform.position = pos; ((Component)player).transform.rotation = rot; ((Component)player.playerAvatarVisuals).transform.position = pos; Traverse.Create((object)player.playerAvatarVisuals).Field<Vector3>("visualPosition").Value = pos; if (IsLocalPlayer(player)) { PlayerController instance = PlayerController.instance; instance.CollisionController.ResetFalling(); instance.VelocityRelative = Vector3.zero; instance.Velocity = Vector3.zero; Rigidbody value = Traverse.Create((object)instance).Field<Rigidbody>("rb").Value; value.velocity = Vector3.zero; value.position = pos; value.rotation = rot; Traverse.Create((object)instance).Field<Vector3>("clientPosition").Value = pos; Traverse.Create((object)instance).Field<Vector3>("clientPositionCurrent").Value = pos; Traverse.Create((object)instance).Field<Quaternion>("clientRotation").Value = rot; Traverse.Create((object)instance).Field<Quaternion>("clientRotationCurrent").Value = rot; Traverse.Create((object)instance).Field<Vector3>("spawnPosition").Value = pos; Traverse.Create((object)instance).Field<Quaternion>("spawnRotation").Value = rot; Traverse.Create((object)instance).Field<Vector3>("rbVelocityRaw").Value = Vector3.zero; Traverse.Create((object)instance).Field<float>("MoveForceAmount").Value = 0f; Traverse.Create((object)instance).Field<Vector3>("VelocityImpulse").Value = Vector3.zero; } } 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 = -1) { if (!((Object)(object)obj == (Object)null)) { ItemBattery battery = obj.GetComponentInParent<ItemBattery>(); CoroutineUtils.StartCoroutine((MonoBehaviour)(object)battery, delayInSec, delegate { int num = ((amount < 0) ? battery.batteryBars : 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 RandomUtils.GetRandomItemFromList<T>((IList<T>)list); } internal static GameObject GetClosestObjectByTag(Vector3 pos, string tag, Func<GameObject, bool> filter, bool needLog = true) { //IL_0075: 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_0086: 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_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) //IL_00ad: 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}"); } } switch (num) { case 0: return null; case 1: return array[0]; default: { 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_006e: 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_007f: 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_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) //IL_00a6: 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}"); } } switch (num) { case 0: return null; case 1: return array[0]; default: { 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_003c: 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] { ((Component)p.localCamera).transform.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); } } public static ItemEquippable GetGrabbedItem(PhysGrabber grabber) { if ((Object)(object)grabber == (Object)null) { return null; } try { PhysGrabObject value = Traverse.Create((object)grabber).Field<PhysGrabObject>("grabbedPhysGrabObject").Value; if ((Object)(object)value == (Object)null) { return null; } return ((Component)value).GetComponent<ItemEquippable>(); } catch (Exception arg) { ((HelperLog)Utils.logger).LogWarning((object)$"grabber {arg}"); return null; } } } 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).ClearLog((Action<string>)null); } } 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_009d: 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; } if ((Object)(object)RunManager.instance == (Object)null) { ((HelperLog)Utils.logger).LogError((object)"error: SpawnEnemy RunManager.instance is null"); 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); EnemyParentPatcher.AddEnemy(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_007a: 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)); if ((Object)(object)val == (Object)null) { ((HelperLog)Utils.logger).LogError((object)"LevelGeneratorEnemySpawn spawned enemy is null"); return null; } 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); } } public class ChaosModNetwork : MonoBehaviour { public struct DataSource { public int playerID; public string eventID; public string username; public string lang; } private static ChaosModNetwork inst; private PhotonView photonView; private static Queue<DataSource> commandQueue; private static bool logNetworkInitIssue = true; private static readonly HashSet<string> shouldBeRunFromHost = new HashSet<string> { "solo_buff_resurrect", "all_buff_resurrect_rand", "all_buff_resurrect_all", "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", "item_duck_bucket", "item_melee_prodzap", "item_gun_boltzap", "item_gun_pulse", "loot_rand_beta_small", "loot_rand_beta_med", "loot_mug_deluxe", "loot_baby_head", "loot_gem_burger", "loot_ac_gumball", "loot_ac_boombox", "loot_milk", "loot_golden_swirl", "loot_ac_blender", "loot_horse", "loot_ac_trafic_light", "solo_upgrade_wings", "solo_upgrade_rest", "item_book_wings", "item_book_rest", "item_cart_cannon", "item_cart_laser", "item_bridge", "item_photon_blaster", "spawn_dogo", "spawn_tick", "spawn_birthday_boy", "spawn_gambit", "spawn_headgrab", "spawn_heart_hugger", "spawn_cleanup_crew", "spawn_bella", "spawn_oogly", "spawn_loom", "item_book_battery", "item_book_climb", "loot_rand_huge", "loot_star_wand", "loot_lev_potion", "loot_jackhammer", "loot_coffin", "loot_tray", "loot_dragon_skull" }; 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, string lang, string username) { ((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, lang = lang, username = username }); } public 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}"); } } public static void RequestClientEventRPC(int userID, string eventID, string lang, string username) { ((HelperLog)Utils.logger).LogInfo((object)$"ChaosModNetwork->RequestClientEventRPC triggered for {userID} {eventID}"); try { inst.photonView.RPC("ActivateClientEventRPC", (RpcTarget)2, new object[4] { userID, eventID, lang, username }); } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"ChaosModNetwork->RequestClientEventRPC error: {arg}"); } } public static bool NeedRunFromHost(string eventID) { return shouldBeRunFromHost.Contains(eventID); } public static void ProcessNetworkEvents(ICommandManager cm, Dictionary<string, IRepoStandaloneCommand> commands) { if (commandQueue == null || cm == null || commands == null) { if (logNetworkInitIssue) { logNetworkInitIssue = false; ((HelperLog)Utils.logger).LogWarning((object)$"ProcessNetworkEvents unexpected issue cq {commandQueue == null}, cm {cm == null}, c {commands == null}"); } return; } while (commandQueue.Count > 0) { try { logNetworkInitIssue = true; 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(CommandConsole.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 = CommandConsole.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}"); } } } public static void RequestNotifyOtherRPC(string eventID, string lang, string username) { if (eventID.StartsWith("all_") || eventID.StartsWith("spawn_")) { try { inst.photonView.RPC("NotifyOtherRPC", (RpcTarget)1, new object[3] { eventID, lang, username }); } catch (Exception arg) { ((HelperLog)Utils.logger).LogError((object)$"ChaosModNetwork->RequestActivateNotifyRPC error: {arg}"); } ((HelperLog)Utils.logger).LogInfo((object)("ChaosModNetwork->RequestActivateNotifyRPC triggered for " + eventID)); } } [PunRPC] private void NotifyOtherRPC(string eventID, string lang, string username) { ((HelperLog)Utils.logger).LogInfo((object)("ChaosModNetwork->ActivateNotifyRPC triggered for " + eventID)); InteractiveMod.inst.NotifyEvent(eventID, lang, username, ignoreTruck: true); } } 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 = JsonUtils.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 = JsonUtils.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 RandomUtils.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) => CommandArgsReader.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 CommandArgsReader.ParseItemPath(RandomUtils.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 : CommandArgsReader { public CommandArgsReaderWrapper(IEnumerable<string> args) : base(args, (ILogger)(object)Utils.logger) { } } 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 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; } public void ClearLog(Action<string> onError) { ((ILogger)logger).ClearLog(onError); } public void ClearLogBySize(int fileSizeInBytes, Action<string> onError) { ((ILogger)logger).ClearLogBySize(fileSizeInBytes, onError); } } } 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 '" + ((Object)enemy).name + "' patcher")); ServiceProvider.inst.enemySpawner.RegisterSpawnedEnemyFinished(enemy); enemiesToBlockInGameSpawn.Remove(enemy); __result = true; return false; } return true; } } [HarmonyPatch(typeof(EnemyParent))] public static class EnemyParentPatcher { private static readonly HashSet<Enemy> enemies = new HashSet<Enemy>(); public static void AddEnemy(Enemy enemy) { if (!((Object)(object)enemy == (Object)null)) { enemies.Add(enemy); } } public static void ClearEnemies() { enemies.Clear(); } [HarmonyPatch("Despawn")] [HarmonyPrefix] private static bool Despawn_Prefix(Enemy ___Enemy, float ___SpawnedTimeMax, ref float ___SpawnedTimer) { if (enemies.Contains(___Enemy)) { ((HelperLog)Utils.logger).LogInfo((object)("despawn '" + ((Object)___Enemy).name + "' patcher")); enemies.Remove(___Enemy); ___SpawnedTimer = ___SpawnedTimeMax; 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 = ((CommandArgsReader)new CommandArgsReaderWrapper(args)).ReadInt(0); 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 = ((CommandArgsReader)commandArgsReaderWrapper).ReadFloat(0f); float num2 = ((CommandArgsReader)commandArgsReaderWrapper).ReadFloat(0f); float num3 = ((CommandArgsReader)commandArgsReaderWrapper).ReadFloat(0f); 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 = ((CommandArgsReader)commandArgsReaderWrapper).ReadFloat(0f); float num2 = ((CommandArgsReader)commandArgsReaderWrapper).ReadFloat(0f); float num3 = ((CommandArgsReader)commandArgsReaderWrapper).ReadFloat(0f); float rotatePower = ((CommandArgsReader)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 = ((CommandArgsReader)commandArgsReaderWrapper).ReadFloat(0f); float num2 = ((CommandArgsReader)commandArgsReaderWrapper).ReadFloat(0f); 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 = ((CommandArgsReader)new CommandArgsReaderWrapper(args)).ReadFloat(0f); 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 = ((CommandArgsReader)commandArgsReaderWrapper).ReadFloat(0f); ChaosInputManager.mouseSpeedCoeffX = ((CommandArgsReader)commandArgsReaderWrapper).ReadFloat(0f); 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 = ((CommandArgsReader)commandArgsReaderWrapper).ReadFloat(0f); ChaosInputManager.mouseSpeedCoeffY = ((CommandArgsReader)commandArgsReaderWrapper).ReadFloat(0f); 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 = ((CommandArgsReader)new CommandArgsReaderWrapper(args)).ReadFloat(0f); 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((KeyValuePa
ChaosTricks_REPO_plugins/ModHelper.dll
Decompiled 6 months 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.Runtime.Versioning; 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: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [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 : IJsonUtils { 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 && 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 (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 CommandConsole { 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 CommandConsole(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("CommandConsole.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("CommandConsole.IsValidCommandLine: invalid command line"); return false; } string[] array = ParseCommandLine(commandLine); if (array == null || array.Length < 1) { logger?.LogDebugError("CommandConsole.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("CommandConsole.IsValidCommandLine: check command", text, isLogCheckCommand, isLogCheckCommandParameters, logCheckCommandParametersMaxLength); string[] array3 = ParseArgs(text); if (array3 == null || array3.Length < 1) { logger?.LogDebugError("CommandConsole.IsValidCommandLine: invalid commands count"); flag = false; continue; } string text2 = array3[0]; List<string> list = ignoreValidationCommands; if (list != null && list.Contains(text2)) { logger?.LogDebugInfo("CommandConsole.IsValidCommandLine: validation is ignored for this command"); } else if (consoleCommandsDict.ContainsKey(text2)) { bool flag2 = consoleCommandsDict[text2].IsValidCommandArgs(array3.Skip(1)); if (!flag2) { logger?.LogDebugError("CommandConsole.IsValidCommandLine: command with id " + text2 + " is invalid"); } flag = flag && flag2; } else { logger?.LogDebugError("CommandConsole.IsValidCommandLine: can't find custom command with id " + text2); flag = false; } } return flag; } catch (Exception arg) { logger?.LogDebugError(string.Format("{0} error: {1}", "CommandConsole.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("CommandConsole.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}", "CommandConsole.RunCommand:", arg)); } } else if (onCustomCommandNotFound != null) { onCustomCommandNotFound(text); } else { logger?.LogError("CommandConsole.RunCommand: execute command not found error"); } } } catch (Exception arg2) { logger?.LogError(string.Format("{0} error {1}", "CommandConsole.RunCommand:", arg2)); return false; } return true; } } public class CommandArgsReader { private readonly ILogger logger; private readonly IEnumerator<string> args; public CommandArgsReader(IEnumerable<string> argsSource, ILogger logger) { args = argsSource.GetEnumerator(); this.logger = logger; } public int ReadInt(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(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(string defaultValue = "") { if (args != null && args.MoveNext()) { return args.Current; } return defaultValue; } public bool ReadBool(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 string ReadSpacedString(string defaultValue = "") { return ParseItemPath(ReadString(defaultValue)); } public string ReadAllAsSingleString(string separator = " ", string defaultValue = "") { if (args == null) { return defaultValue; } StringBuilder stringBuilder = new StringBuilder(); bool flag = true; while (args.MoveNext()) { if (!flag && !string.IsNullOrEmpty(separator)) { stringBuilder.Append(separator); } flag = false; stringBuilder.Append(args.Current); } string text = stringBuilder.ToString(); if (!string.IsNullOrEmpty(text)) { return text; } return defaultValue; } public string[] ParseList(string s, string separator = "|") { if (string.IsNullOrEmpty(s)) { return null; } return (from item in s.Split(new string[1] { separator }, StringSplitOptions.None) select item.Trim() into item where !string.IsNullOrWhiteSpace(item) select item).ToArray(); } public static string ParseItemPath(string path) { return path?.Replace("_", " "); } } public static class RandomUtils { 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 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; } public 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(); } } 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 = JsonUtils.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 = JsonUtils.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 = JsonUtils.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 = JsonUtils.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 ClearLog(Action<string> onError) { if (path == null) { return; } try { using (new StreamWriter(path)) { } } catch (Exception arg) { onError?.Invoke($"ClearLog error: {arg}"); } } public virtual void ClearLogBySize(int fileSizeInBytes, Action<string> onError) { try { FileInfo fileInfo = new FileInfo(path); if (fileInfo.Exists && fileInfo.Length > fileSizeInBytes) { ClearLog(onError); } } catch (Exception arg) { onError?.Invoke($"ClearLogBySize error: {arg}"); } } } 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 (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 (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 JsonUtils { private static Func<IJsonUtils> customGenerator; public static IJsonUtils Generate(IDebugLogger logger) { if (customGenerator == null) { return new HelperJson(logger, File.Exists(".mod_json_debug")); } return customGenerator(); } public static void RegisterCustomGenerator(Func<IJsonUtils> generator) { customGenerator = generator; } } public class SettingsUtils { 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 = JsonUtils.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.Wrappers { public class LimitedLogWrapper : IDebugLogger, ILoggerWithConsole, ILogger { private readonly IDebugLogger logger; private int messagesLimit; public LimitedLogWrapper(int messagesLimit, IDebugLogger logger) { this.logger = logger; this.messagesLimit = messagesLimit; } public void Log(object obj) { if (messagesLimit > 0) { messagesLimit--; logger.Log(obj); } } 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--; logger.LogInfo(obj); } } public void LogInfoConsoleOnly(object obj) { if (messagesLimit > 0) { messagesLimit--; logger.LogInfoConsoleOnly(obj); } } public void LogInfoFileOnly(object obj) { if (messagesLimit > 0) { messagesLimit--; logger.LogInfoFileOnly(obj); } } public void LogWarning(object obj) { if (messagesLimit > 0) { messagesLimit--; logger.LogWarning(obj); } } public void LogWarningConsoleOnly(object obj) { if (messagesLimit > 0) { messagesLimit--; logger.LogWarningConsoleOnly(obj); } } public void LogWarningFileOnly(object obj) { if (messagesLimit > 0) { messagesLimit--; logger.LogWarningFileOnly(obj); } } public void LogError(object obj) { if (messagesLimit > 0) { messagesLimit--; logger.LogError(obj); } } public void LogErrorConsoleOnly(object obj) { if (messagesLimit > 0) { messagesLimit--; logger.LogErrorConsoleOnly(obj); } } public void LogErrorFileOnly(object obj) { if (messagesLimit > 0) { messagesLimit--; logger.LogErrorFileOnly(obj); } } public void UpdateLimit(int limit) { messagesLimit = limit; } public void ClearLog(Action<string> onError) { logger.ClearLog(onError); } public void ClearLogBySize(int fileSizeInBytes, Action<string> onError) { logger.ClearLogBySize(fileSizeInBytes, onError); } } } 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 IJsonUtils { 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 ClearLog(Action<string> onError); void ClearLogBySize(int fileSizeInBytes, Action<string> onError); } 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 6 months agousing 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 System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using EventsIO.Interfaces; using ModHelper; using ModHelper.Interfaces; using ModHelperUnity.Data; using ModHelperUnity.Interfaces; using ModHelperUnity.Utilities; using UnityEngine; [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.Utilities { public 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; public Action<string> log; 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) { log?.Invoke($"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; public Action<string> log; 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) { log?.Invoke($"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; public Action<string> log; 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) { log?.Invoke($"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(); } } public static void StartCoroutine(MonoBehaviour script, float delayInSec, Action action, Action<string> log = null) { if ((Object)(object)script == (Object)null) { return; } if (action == null) { log?.Invoke("StartCoroutine got null action"); return; } if (delayInSec < 0f) { delayInSec = 0f; log?.Invoke($"StartCoroutine got invalid delay {delayInSec}"); } script.StartCoroutine(ActionCoroutine(delayInSec, action)); } [IteratorStateMachine(typeof(<ActionCoroutine>d__1))] private static IEnumerator ActionCoroutine(float delayInSec, Action action, Action<string> log = null) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ActionCoroutine>d__1(0) { delayInSec = delayInSec, action = action, log = log }; } public static void StartCoroutineInFrames(MonoBehaviour script, int delayInFrames, Action action, Action<string> log = null) { if ((Object)(object)script == (Object)null) { return; } if (action == null) { log?.Invoke("StartCoroutineInFrames got null action"); return; } if (delayInFrames <= 0) { log?.Invoke($"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, Action<string> log = null) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ActionCoroutineInFrames>d__3(0) { delayInFrames = delayInFrames, action = action, log = log }; } public static void StartCoroutineWhile(MonoBehaviour script, float repeatDelayInSec, Func<bool> action, Action<string> log = null) { if ((Object)(object)script == (Object)null) { return; } if (action == null) { log?.Invoke("StartCoroutine got null action"); return; } if (repeatDelayInSec < 0f) { repeatDelayInSec = 0f; log?.Invoke($"StartCoroutine got invalid delay {repeatDelayInSec}"); } script.StartCoroutine(WhileCoroutine(repeatDelayInSec, action)); } [IteratorStateMachine(typeof(<WhileCoroutine>d__5))] private static IEnumerator WhileCoroutine(float repeatDelayInSec, Func<bool> action, Action<string> log = null) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WhileCoroutine>d__5(0) { repeatDelayInSec = repeatDelayInSec, action = action, log = log }; } } public static class GameObjectUtils { public static T GetClosestObject<T>(Vector3 pos, Func<T, bool> filter, Action<string> log) where T : MonoBehaviour { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) T[] array = Object.FindObjectsOfType<T>(); int num = array.Length; log?.Invoke($"GetClosestObject found {num}"); if (num == 0) { return default(T); } if (filter != null) { array = array.Where(filter).ToArray(); num = array.Length; log?.Invoke($"GetClosestObject filtered size {num}"); } switch (num) { case 0: return default(T); case 1: return array[0]; default: { T val = array[0]; Vector3 val2 = pos - ((Component)(object)val).transform.position; float num2 = ((Vector3)(ref val2)).sqrMagnitude; for (int i = 1; i < num; i++) { T val3 = array[i]; val2 = pos - ((Component)(object)val3).transform.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num2) { val = val3; num2 = sqrMagnitude; } } return val; } } } public static void DebugFindAndPrintAllObjects<T>(Action<string> log) where T : MonoBehaviour { T[] array = Resources.FindObjectsOfTypeAll<T>(); StringBuilder stringBuilder = new StringBuilder("--- Found object list (names) ---\n"); T[] array2 = array; foreach (T val in array2) { stringBuilder.AppendLine(((Object)(object)val).name ?? ""); } log?.Invoke(stringBuilder.ToString()); } public static void DebugLoadAndPrintAllObjects<T>(string resourcePath, bool replaceSpaces, Action<string> log) where T : MonoBehaviour { T[] array = Resources.LoadAll<T>(resourcePath); StringBuilder stringBuilder = new StringBuilder("\n--- Loaded object list (path) ---\n"); T[] array2 = array; foreach (T val in array2) { string value = (replaceSpaces ? ((Object)(object)val).name.Replace(" ", "_") : ((Object)(object)val).name); stringBuilder.AppendLine(value); } log?.Invoke(stringBuilder.ToString()); } } public static class HelperUI { 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 UnityMathUtils { public static bool GetRandomBool() { return Random.value > 0.5f; } public static int GetRandomSign() { if (!GetRandomBool()) { 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); } } } 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.TypedNotify { 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 = JsonUtils.Generate(logger).FromFile<TypedNotifySettings>(settingsFilePath); } else { byte[] bytes = customFileReader(settingsFilePath); string @string = Encoding.UTF8.GetString(bytes); Settings = JsonUtils.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 = HelperUI.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%", HelperUI.GetColoredText(eventData.Username, typedNotifyParameters.nicknameTextColor)).Replace("%message%", HelperUI.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 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 = HelperUI.CalcScreenFactor(HelperUI.StandardScreenWidth, Screen.width); float num2 = HelperUI.CalcScreenFactor(HelperUI.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.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 6 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; 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: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [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 JsonUtils.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; protected bool logOnConnectionError; 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, bool logOnConnectionError = false) : base("", processEvent, parser, log, errorLog, checkPeriod, delay, initDelay) { this.logOnConnectionError = logOnConnectionError; } 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 = JsonUtils.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) { WebSocket socket = Socket; try { 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}"); } try { socket.Close(); } catch (Exception) { } } } 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown WebSocket val = new WebSocket($"ws://{ip}:{port}/{room}", Array.Empty<string>()); 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; SetSocketForConnectLimit(val, int.MaxValue); } public void SetSocketForConnectLimit(WebSocket ws, int max) { FieldInfo field = ((object)ws).GetType().GetField("_maxRetryCountForConnect", BindingFlags.Static | BindingFlags.NonPublic); if (field == null) { ((EventsReader)this).ReaderLogError("FixSocketLimit error, maxRetryField is null"); } else { field.SetValue(ws, max); } } 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(logOnConnectionError); } } ((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 + "\"}"; } } }