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 ChaosTricksTwitchIntegration v2.2.2
plugins/ChaosTricks/EventsIO.dll
Decompiled 2 years 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); } }
plugins/ChaosTricks/InteractiveMod.dll
Decompiled 2 years 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.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 BepInEx; using BepInEx.Logging; using EventsIO; using EventsIO.Interfaces; using HarmonyLib; using ModHelper; using ModHelper.Interfaces; using ModHelperUnity; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; using WebSocketIO; using valheim_mod.Commands; using valheim_mod.Patchers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ChaosTricks Valheim mod")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("BFT")] [assembly: AssemblyProduct("ChaosTricks Valheim mod")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("BFT")] [assembly: ComVisible(false)] [assembly: Guid("e1bf112d-820d-4486-a4e7-d44d7400fee6")] [assembly: AssemblyFileVersion("2.2.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("2.2.2.0")] namespace valheim_mod { public class DamageRanges { public float MinPhysicalDamage { get; set; } public float MaxPhysicalDamage { get; set; } public float MinElementalDamage { get; set; } public float MaxElementalDamage { get; set; } public void ReadFromArgs(IEnumerator<string> argsEnumerator) { ReadPhysicalDamageFromArgs(argsEnumerator); ReadElementalDamageFromArgs(argsEnumerator); } public void ReadPhysicalDamageFromArgs(IEnumerator<string> argsEnumerator) { float val = CommandsArgsReader.ReadFloat(argsEnumerator, 1f); float val2 = CommandsArgsReader.ReadFloat(argsEnumerator, 1f); MinPhysicalDamage = Math.Min(val, val2); MaxPhysicalDamage = Math.Max(val, val2); } public void ReadElementalDamageFromArgs(IEnumerator<string> argsEnumerator) { float val = CommandsArgsReader.ReadFloat(argsEnumerator, 0f); float val2 = CommandsArgsReader.ReadFloat(argsEnumerator, 0f); MinElementalDamage = Math.Min(val, val2); MaxElementalDamage = Math.Max(val, val2); } private static bool IsValidPair(IEnumerator<string> argsEnumerator, bool isSkippable) { if (CommandsValidator.IsValidFloat(argsEnumerator, 0f, 200f, isSkippable)) { return CommandsValidator.IsValidFloat(argsEnumerator, 0f, 200f, isSkippable); } return false; } public static bool IsValidPhysicalDamage(IEnumerator<string> argsEnumerator, bool isSkippable) { return IsValidPair(argsEnumerator, isSkippable); } public static bool IsValidElementalDamage(IEnumerator<string> argsEnumerator, bool isSkippable) { return IsValidPair(argsEnumerator, isSkippable); } public static bool IsValidDamage(IEnumerator<string> argsEnumerator, bool isSkippable) { if (IsValidPhysicalDamage(argsEnumerator, isSkippable)) { return IsValidElementalDamage(argsEnumerator, isSkippable); } return false; } } public static class CommandsArgsReader { public static int ReadInt(IEnumerator<string> args, int defaultValue) { if (args == null || !args.MoveNext()) { return defaultValue; } int result = defaultValue; try { result = int.Parse(args.Current); } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"CommandsArgsReader error: {arg}"); } return result; } public static float ReadFloat(IEnumerator<string> args, float defaultValue) { if (args == null || !args.MoveNext()) { return defaultValue; } float result = defaultValue; try { result = float.Parse(args.Current, CultureInfo.InvariantCulture.NumberFormat); } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"CommandsArgsReader error: {arg}"); } return result; } public static string ReadString(IEnumerator<string> args, string defaultValue = "") { if (args == null || !args.MoveNext()) { return defaultValue; } return args.Current; } public static bool ReadBool(IEnumerator<string> args, bool defaultValue = false) { if (args == null || !args.MoveNext()) { return defaultValue; } try { return bool.Parse(args.Current.ToLower()); } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"CommandArgsReader: {arg}"); return defaultValue; } } } public static class CommandsValidator { public static bool IsZeroArgs(IEnumerable<string> args) { int num = args?.Count() ?? 0; if (num != 0) { LoggerFactory.Logger.LogDebugError((object)$"wrong args count {num} (must be 0)"); return false; } return true; } public static bool IsZeroArgs(IEnumerator<string> args) { if (args == null || !args.MoveNext()) { return true; } LoggerFactory.Logger.LogDebugError((object)"wrong args count (more than needed)"); return false; } private static bool IsInvalidArgsCount(IEnumerator<string> args) { if (args == null || !args.MoveNext()) { return true; } return false; } public static bool IsValidInt(IEnumerator<string> args, int minValue, int maxValue, bool isSkippable = false) { if (IsInvalidArgsCount(args)) { if (isSkippable) { return true; } LoggerFactory.Logger.LogDebugError((object)"wrong args count"); return false; } try { int num = int.Parse(args.Current); if (num < minValue || num > maxValue) { string text = $"wrong integer value {num} (must be in range from {minValue} to {maxValue})"; LoggerFactory.Logger.LogDebugError((object)text); return false; } } catch (Exception) { LoggerFactory.Logger.LogDebugError((object)("can't parse integer value from '" + args.Current + "'")); return false; } return true; } public static bool IsValidFloat(IEnumerator<string> args, float minValue, float maxValue, bool isSkippable = false) { if (IsInvalidArgsCount(args)) { if (isSkippable) { return true; } LoggerFactory.Logger.LogDebugError((object)"wrong args count"); return false; } try { float num = float.Parse(args.Current, CultureInfo.InvariantCulture.NumberFormat); if (num < minValue || num > maxValue) { string text = $"wrong float value {num} (must be in range from {minValue} to {maxValue})"; LoggerFactory.Logger.LogDebugError((object)text); return false; } } catch (Exception) { LoggerFactory.Logger.LogDebugError((object)("can't parse float value from '" + args.Current + "'")); } return true; } public static bool IsValidString(IEnumerator<string> args, Func<string, bool> validator, bool isSkippable = false) { if (IsInvalidArgsCount(args)) { if (isSkippable) { return true; } LoggerFactory.Logger.LogDebugError((object)"wrong args count"); return false; } if (validator == null) { return true; } if (validator(args.Current)) { return true; } LoggerFactory.Logger.LogDebugError((object)("wrong string value " + args.Current)); return false; } public static bool IsValidBool(IEnumerator<string> args, bool isSkippable = true) { if (IsInvalidArgsCount(args)) { if (isSkippable) { return true; } LoggerFactory.Logger.LogDebugError((object)"wrong args count"); return false; } LoggerFactory.Logger.LogDebugError((object)("wrong bool value " + args.Current)); return false; } } public static class GameProxy { public static readonly string CustomNameId = "custom_name"; public static readonly string PlayerNameSpawnId = "PlayerNameSpawn"; public static readonly string CustomSpeedTriggerId = "CustomSpeedTrigger"; private static bool isNeedHudsErrorLog = true; private static ScheduleManager scheduleManager; private static bool isDebugInited; private static bool isDebug; public static Player CurrentPlayer => Player.m_localPlayer; public static Player[] TargetPlayers { get { if (!InteractiveMod.Settings.isAllPlayers) { return (Player[])(object)new Player[1] { CurrentPlayer }; } return Player.GetAllPlayers().ToArray(); } } public static ScheduleManager ScheduleManager { get { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown if (scheduleManager == null) { scheduleManager = new ScheduleManager((ILogger)(object)LoggerFactory.Logger); } return scheduleManager; } } public static void RunGameConsoleCommand(string command) { try { if (!IsCheater()) { ((ILogger)LoggerFactory.Logger).Log((object)"Standard command try to enable cheats"); StandardConsoleManager.instance.InstantlyRunCommand("devcommands"); } StandardConsoleManager.instance.AddCommandToQueue(command); } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"Standard command error: {arg}"); } } public static bool IsCheater() { try { return (Object)(object)Console.instance != (Object)null && ((Terminal)Console.instance).IsCheatsEnabled(); } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"IsCheater error: {arg}"); return false; } } private static void DebugLogReflection(string msg) { ((ILogger)LoggerFactory.Logger).Log((object)msg); } private static void VerboseDebugLogReflection(string msg, bool isVerboseDebugLog) { if (isVerboseDebugLog) { LoggerFactory.Logger.LogDebugInfo((object)msg); } } public static void UpdateEnemyHudNames(bool isVerboseDebugLog = false) { //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) EnemyHud instance = EnemyHud.instance; if ((Object)(object)instance == (Object)null) { return; } try { FieldInfo field = typeof(EnemyHud).GetField("m_huds", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null) { DebugLogReflection("UpdateEnemyHudNames info null"); return; } object value = field.GetValue(instance); if (value == null) { DebugLogReflection("UpdateEnemyHudNames dictHudData null"); return; } if (!(value is IDictionary dictionary)) { DebugLogReflection("UpdateEnemyHudNames m_huds null"); return; } VerboseDebugLogReflection($"UpdateEnemyHudNames m_huds {dictionary.Count}", isVerboseDebugLog); foreach (object key in dictionary.Keys) { object obj = dictionary[key]; if (obj == null) { VerboseDebugLogReflection("UpdateEnemyHudNames objData null", isVerboseDebugLog); continue; } Character val = (Character)((key is Character) ? key : null); if ((Object)(object)val == (Object)null || val.IsPlayer()) { VerboseDebugLogReflection($"UpdateEnemyHudNames char skipped {(Object)(object)val == (Object)null}", isVerboseDebugLog); continue; } ZDO zDO = GetZDO(val); int instanceID = ((Object)val).GetInstanceID(); uint iD = ((ZDOID)(ref zDO.m_uid)).ID; string @string = zDO.GetString(CustomNameId, ""); object[] obj2 = new object[4] { @string, instanceID, iD, null }; ZDOID zDOID = zDO.GetZDOID(CustomNameId); obj2[3] = ((ZDOID)(ref zDOID)).ID; VerboseDebugLogReflection(string.Format("UpdateEnemyHudNames: {0}, id {1}, idZDO {2}, zdoid {3}", obj2), isVerboseDebugLog); if (string.IsNullOrEmpty(@string)) { continue; } FieldInfo field2 = obj.GetType().GetField("m_name", BindingFlags.Instance | BindingFlags.Public); if (field2 == null) { DebugLogReflection("UpdateEnemyHudNames textField null"); continue; } object? value2 = field2.GetValue(obj); Text val2 = (Text)((value2 is Text) ? value2 : null); if (val2 != null) { val2.text = @string; VerboseDebugLogReflection("UpdateEnemyHudNames name is set", isVerboseDebugLog); } } } catch (Exception arg) { if (isNeedHudsErrorLog) { isNeedHudsErrorLog = false; ((ILogger)LoggerFactory.Logger).Log((object)$"UpdateEnemyHudNames error: {arg}"); } } } public static ZNetView GetZNetView(object obj) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown try { return (ZNetView)obj.GetType().GetField("m_nview", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj); } catch (Exception arg) { DebugLogReflection($"GetZNetView error: {arg}"); return null; } } public static ZDO GetZDO(Character obj) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) try { return ZDOMan.instance.GetZDO(obj.GetZDOID()); } catch (Exception arg) { DebugLogReflection($"GetZDO error: {arg}"); return null; } } public static ZDO GetZDO(GameObject obj) { try { ZNetView componentInChildren = obj.GetComponentInChildren<ZNetView>(); if ((Object)(object)componentInChildren == (Object)null) { return null; } return componentInChildren.GetZDO(); } catch (Exception arg) { DebugLogReflection($"gameObject GetZDO error: {arg}"); return null; } } public static void TriggerConsoleInputText() { try { typeof(Console).GetMethod("InputText", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(Console.instance, null); } catch (Exception arg) { DebugLogReflection($"TriggerConsoleInputText error: {arg}"); } } public static void ReinitScheduleManager() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown ScheduleManager obj = scheduleManager; if (obj != null) { obj.FinishAllImmediatly(); } scheduleManager = new ScheduleManager((ILogger)(object)LoggerFactory.Logger); } public static GameObject SpawnProjectile(Vector3 pos, string name) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)ZNetScene.instance == (Object)null) { ((ILogger)LoggerFactory.Logger).LogError((object)"SpawnProjectile ZNetScene null"); return null; } GameObject prefab = ZNetScene.instance.GetPrefab(name); if ((Object)(object)prefab == (Object)null) { ((ILogger)LoggerFactory.Logger).LogError((object)("Missing projectile prefab" + name)); return null; } return Object.Instantiate<GameObject>(prefab, pos, Quaternion.identity); } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).LogError((object)$"SpawnProjectile error: {arg}"); } return null; } public static Projectile SetupProjectilePhysics(Character owner, GameObject gameObject, Vector3 target, float velocity = 10f, float accuracy = 5f) { //IL_0045: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)gameObject == (Object)null) { ((ILogger)LoggerFactory.Logger).LogError((object)"SetupProjectile gameObject null"); return null; } Projectile component = gameObject.GetComponent<Projectile>(); if ((Object)(object)component == (Object)null) { ((ILogger)LoggerFactory.Logger).LogError((object)"SetupProjectile Projectile null error"); return null; } Vector3 val = target - ((Component)component).transform.position; Vector3 normalized = ((Vector3)(ref val)).normalized; Vector3 val2 = Vector3.Cross(normalized, Vector3.up); normalized = Quaternion.AngleAxis(Random.Range(0f - accuracy, accuracy), val2) * normalized; normalized = Quaternion.AngleAxis(Random.Range(0f - accuracy, accuracy), Vector3.up) * normalized; component.Setup(owner, normalized * velocity, -1f, (HitData)null, (ItemData)null, (ItemData)null); return component; } catch (Exception arg) { LoggerFactory.LogWithUI($"SetupProjectile error: {arg}"); } return null; } public static void DebugComponents(GameObject gameObject) { Component[] components = gameObject.GetComponents<Component>(); if (components == null) { ((ILogger)LoggerFactory.Logger).Log((object)"components not found"); return; } StringBuilder stringBuilder = new StringBuilder(); Component[] array = components; foreach (Component val in array) { if (!((Object)(object)val == (Object)null)) { stringBuilder.AppendLine(((object)val).GetType().Name); } } ((ILogger)LoggerFactory.Logger).Log((object)$"components list:\n{stringBuilder}"); } public static string[] GetTierNames() { return new string[5] { "1", "2", "3", "4", "5" }; } public static string GetCurrentTier() { float bodyArmor = ((Character)CurrentPlayer).GetBodyArmor(); if (bodyArmor < 10f) { return "1"; } if (bodyArmor < 21f) { return "2"; } if (bodyArmor < 41f) { return "3"; } if (bodyArmor < 61f) { return "4"; } return "5"; } public static bool IsPlayerCloseToOthers(Player p, ICollection<Player> others, float range) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null || others == null || others.Count == 0) { return false; } if (range <= 0f) { return true; } Vector3 position = ((Component)p).transform.position; foreach (Player other in others) { if (Vector3.Distance(((Component)other).transform.position, position) <= range) { return true; } } return false; } public static void DebugDamage(DamageTypes damage) { //IL_000a: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) ((ILogger)LoggerFactory.Logger).Log((object)$"m_damage: {damage.m_damage}"); ((ILogger)LoggerFactory.Logger).Log((object)$"m_blunt: {damage.m_blunt}"); ((ILogger)LoggerFactory.Logger).Log((object)$"m_chop: {damage.m_chop}"); ((ILogger)LoggerFactory.Logger).Log((object)$"m_fire: {damage.m_fire}"); ((ILogger)LoggerFactory.Logger).Log((object)$"m_frost: {damage.m_frost}"); ((ILogger)LoggerFactory.Logger).Log((object)$"m_lightning: {damage.m_lightning}"); ((ILogger)LoggerFactory.Logger).Log((object)$"m_pickaxe: {damage.m_pickaxe}"); ((ILogger)LoggerFactory.Logger).Log((object)$"m_pierce: {damage.m_pierce}"); ((ILogger)LoggerFactory.Logger).Log((object)$"m_poison: {damage.m_poison}"); ((ILogger)LoggerFactory.Logger).Log((object)$"m_slash: {damage.m_slash}"); ((ILogger)LoggerFactory.Logger).Log((object)$"m_spirit: {damage.m_spirit}"); } public static bool IsDebugMode() { if (isDebugInited) { return isDebug; } isDebugInited = true; isDebug = File.Exists(Path.Combine(UtilitySettings.BaseFolder, ".debug")); return isDebug; } } public static class LoggerFactory { private static IDebugLogger logger; public static IDebugLogger Logger { get { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if (logger == null) { logger = (IDebugLogger)new BufferedLogger(UtilitySettings.BaseFolder, "interactive_mod_log.txt", GameProxy.IsDebugMode(), 50); } return logger; } } public static void LogWithUI(string msg) { ((ILogger)Logger).Log((object)msg); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)1, msg, 0, (Sprite)null); } } } public class SummonController { public class PackageEnemiesData { public string name; public uint id; public long userId; } public static readonly SummonController instance = new SummonController(); private readonly List<Character> summonedEnemies = new List<Character>(); private List<PackageEnemiesData> zpackageEnemies; private const float initTimer = 1.8f; private float dotTimer = 1.8f; private const float initTimerFixCharacters = 1f; private float timerFixCharacters = 1f; private float killEnemiesTimer = 1f; private readonly string[] animalList = new string[6] { "Deer", "Neck", "Boar", "Hare", "Hen", "Lox" }; public void AddCharacter(Character enemy) { if ((Object)(object)enemy != (Object)null) { summonedEnemies.Add(enemy); } } public void AddCharacter(GameObject enemy) { if ((Object)(object)enemy != (Object)null) { AddCharacter(enemy.GetComponentInChildren<Character>()); } } public void AddPackageCharacter(PackageEnemiesData character) { if (character != null) { if (zpackageEnemies == null) { zpackageEnemies = new List<PackageEnemiesData>(); } zpackageEnemies.Add(character); } } public void ClearEnemies() { summonedEnemies.Clear(); } private static void InitCharacterHud(Character c) { try { Traverse.Create((object)EnemyHud.instance).Method("ShowHud", new object[2] { c, false }); } catch (Exception arg) { LoggerFactory.Logger.LogDebugError((object)$"InitCharacterHud {arg}"); } } private PackageEnemiesData GetPackageEnemyName(uint id, long userId) { foreach (PackageEnemiesData zpackageEnemy in zpackageEnemies) { if (zpackageEnemy.id == id && zpackageEnemy.userId == userId) { return zpackageEnemy; } } return null; } private void FixHudNames() { try { if (zpackageEnemies != null) { List<PackageEnemiesData> list = new List<PackageEnemiesData>(); foreach (Character allCharacter in Character.GetAllCharacters()) { if ((Object)(object)allCharacter == (Object)null || allCharacter.IsPlayer()) { continue; } ZDO zDO = GameProxy.GetZDO(allCharacter); if (zDO != null) { uint iD = ((ZDOID)(ref zDO.m_uid)).ID; long userID = ((ZDOID)(ref zDO.m_uid)).UserID; PackageEnemiesData packageEnemyName = GetPackageEnemyName(iD, userID); if (packageEnemyName != null) { string text = (allCharacter.m_name = packageEnemyName.name); InitCharacterHud(allCharacter); zDO.Set(GameProxy.CustomNameId, text); list.Add(packageEnemyName); } } } if (list.Count > 0) { List<PackageEnemiesData> list2 = zpackageEnemies.Except(list).ToList(); zpackageEnemies = ((list2.Count == 0) ? null : list2); } } GameProxy.UpdateEnemyHudNames(); } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"SummonController error: {arg}"); } } public void KillSpawnedEnemyOnDeath() { if (!InteractiveMod.networkIsKillSpawnsAfterPlayerDeath) { return; } Player[] targetPlayers = GameProxy.TargetPlayers; foreach (Player val in targetPlayers) { if (!(((Character)val).GetHealth() <= 0f)) { continue; } string playerName = val.GetPlayerName(); foreach (Character allCharacter in Character.GetAllCharacters()) { if (allCharacter.IsPlayer()) { continue; } ZDO zDO = GameProxy.GetZDO(allCharacter); if (zDO == null) { continue; } GameObject prefab = ZNetScene.instance.GetPrefab(zDO.GetPrefab()); string @string = zDO.GetString(GameProxy.PlayerNameSpawnId, ""); if (!string.IsNullOrEmpty(@string) && @string == playerName && !animalList.Contains(((Object)prefab).name)) { ZNetView zNetView = GameProxy.GetZNetView(allCharacter); if ((Object)(object)zNetView != (Object)null) { zNetView.Destroy(); } ((ILogger)LoggerFactory.Logger).Log((object)("EnemiesRemover " + @string)); } } } } public void KillOutRangeEnemy() { //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) if (!InteractiveMod.networkIsKillSpawnsAfterPlayerDeath) { return; } Player[] targetPlayers = GameProxy.TargetPlayers; foreach (Player val in targetPlayers) { if ((Object)(object)val == (Object)null) { ((ILogger)LoggerFactory.Logger).LogWarning((object)"KillOutRangeEnemy player is null"); continue; } foreach (Character allCharacter in Character.GetAllCharacters()) { if ((Object)(object)allCharacter == (Object)null) { ((ILogger)LoggerFactory.Logger).LogWarning((object)"KillOutRangeEnemy character is null"); } else { if (allCharacter.IsPlayer()) { continue; } ZDO zDO = GameProxy.GetZDO(allCharacter); if (zDO == null) { ((ILogger)LoggerFactory.Logger).LogWarning((object)"KillOutRangeEnemy zdo is null"); continue; } string @string = zDO.GetString(GameProxy.PlayerNameSpawnId, ""); string playerName = val.GetPlayerName(); if (string.IsNullOrEmpty(@string) || @string != playerName) { continue; } if ((Object)(object)((Component)val).transform == (Object)null || (Object)(object)((Component)allCharacter).transform == (Object)null) { ((ILogger)LoggerFactory.Logger).LogWarning((object)"KillOutRangeEnemy transform is null"); } else if (Vector3.Distance(((Component)val).transform.position, ((Component)allCharacter).transform.position) >= 80f) { ZNetView zNetView = GameProxy.GetZNetView(allCharacter); if ((Object)(object)zNetView == (Object)null) { ((ILogger)LoggerFactory.Logger).LogWarning((object)"KillOutRangeEnemy znv is null"); continue; } zNetView.Destroy(); ((ILogger)LoggerFactory.Logger).Log((object)"EnemiesRemover KillOutRangeEnemy"); } } } } } public void OnUpdate(float dt) { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown timerFixCharacters -= dt; if (timerFixCharacters <= 0f) { timerFixCharacters = 1f; FixHudNames(); } killEnemiesTimer -= dt; if (killEnemiesTimer < 0f) { killEnemiesTimer = 1f; KillOutRangeEnemy(); KillSpawnedEnemyOnDeath(); } if (!InteractiveMod.networkIsEnableSpawnDeathTimer) { return; } dotTimer -= dt; if (dotTimer > 0f) { return; } dotTimer = 1.8f; for (int num = summonedEnemies.Count - 1; num >= 0; num--) { try { Character val = summonedEnemies[num]; if ((Object)(object)val == (Object)null || val.IsDead() || (Object)(object)((Component)val).gameObject == (Object)null || !((Component)val).gameObject.activeInHierarchy) { summonedEnemies.RemoveAt(num); ((ILogger)LoggerFactory.Logger).Log((object)"SummonController enemy removed"); } else { HitData val2 = new HitData(); float val3 = val.GetMaxHealth() / (float)InteractiveMod.networkSpawnDeathTimerDuration * 1.8f; val2.m_damage.m_damage = Math.Max(val3, 0.12f); val.Damage(val2); } } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"SummonController error: {arg}"); } } } } [BepInPlugin("bft.chaostricks", "Chaos Tricks", "2.2.2")] public class BepInExPlugin : BaseUnityPlugin { private ManualLogSource loggerHook; public const string pluginGuid = "bft.chaostricks"; public const string pluginName = "Chaos Tricks"; public const string pluginVersion = "2.2.2"; public void Awake() { loggerHook = ((BaseUnityPlugin)this).Logger; try { UtilitySettings.BaseFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); ((ILogger)LoggerFactory.Logger).LogClear(); } catch (Exception ex) { ManualLogSource obj = loggerHook; if (obj != null) { obj.LogError((object)ex); } } InteractiveMod.instance = new InteractiveMod(); InteractiveMod.instance.Awake(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"plugin init finished"); } public void OnDestroy() { InteractiveMod.instance?.OnDestroy(); } public void Start() { InteractiveMod.instance?.Start(); } public void Update() { InteractiveMod.instance?.Update(); } } public class NetworkSpawnData { public int hitpointsModifier = 100; public int spawnDamageModifier = 100; public int buildingDamageModifier = 25; public bool isSpawnsHaveDrop; public bool isKillSpawnsAfterPlayerDeath = true; public bool isEnableSpawnDeathTimer = true; public int spawnDeathTimerDuration = 150; public string argName; public int argCount = 1; public int argLevel; public float argHitsPercent = 0.5f; public float argMinPhysicalDamage; public float argMaxPhysicalDamage; public float argMinElementalDamage; public float argMaxElementalDamage; public string username = "agent007"; } public class InteractiveMod { public static InteractiveMod instance; private WebSocketEventsReader<SettingsData> eventsReader; private IEventsReaderOnKey eventsReaderByKey; private IEventsDataParser eventsParser; private string keyEventsPath; private bool isNeedTriggerOnFirstConnect = true; private const int isReadyForCheckEventErrorsLimitBase = 50; private int isReadyForCheckEventErrorsLimit = 50; private ICommandManager commandManager; private ITranslation translationManager; public static RainWeather sharedMeteorRain; public static RainWeather sharedAcidRain; private bool isNeedShowConnectMessage; private bool isNeedShowDisconnectMessage; private static bool isAppConnected; public static UtilityConsole console; public static bool networkIsKillSpawnsAfterPlayerDeath = true; public static bool networkIsEnableSpawnDeathTimer = true; public static int networkSpawnDeathTimerDuration = 150; public static bool IsAppConnected => isAppConnected; public static SettingsData Settings => instance?.eventsReader?.Settings ?? new SettingsData(); public void Awake() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown ((ILogger)LoggerFactory.Logger).Log((object)"InteractiveMod Awake"); Game.isModded = true; console = new UtilityConsole(LoggerFactory.Logger, (List<string>)null); MainPatcher.InitPatch(); instance = this; } public void OnDestroy() { instance = null; ((ILogger)LoggerFactory.Logger).Log((object)"InteractiveMod destroy"); } public static void ProcessStandardCommand(string command) { ((ILogger)LoggerFactory.Logger).Log((object)("InteractiveMod add standard command '" + command + "' to queue")); GameProxy.RunGameConsoleCommand(command); } public void InitLogFlushTask() { //IL_0005: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown GameProxy.ScheduleManager.NewPeriodicTask(new PeriodicTaskData { periodicAction = delegate { IDebugLogger logger = LoggerFactory.Logger; IDebugLogger obj = ((logger is BufferedLogger) ? logger : null); if (obj != null) { ((BufferedLogger)obj).Flush(true); } }, period = 5f }, false); } public void InitOthersManagers() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown ((ILogger)LoggerFactory.Logger).Log((object)"init HelperLanguages"); translationManager = (ITranslation)new HelperLanguagesFormatted((IDebugLogger)null); translationManager.InitFromFile(Path.Combine(UtilitySettings.BaseFolder, "langs.data")); ((ILogger)LoggerFactory.Logger).Log((object)"init ScheduleManager"); GameProxy.ReinitScheduleManager(); InitLogFlushTask(); isReadyForCheckEventErrorsLimit = 50; } public void InitCommands(bool isNeedValidate) { //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Expected O, but got Unknown console.RegisterCommand((IConsoleCommand)(object)new CustomSpawner()); console.RegisterCommand((IConsoleCommand)(object)new ChangeModel()); console.RegisterCommand((IConsoleCommand)(object)new EnemiesRemover()); console.RegisterCommand((IConsoleCommand)(object)new GodMod()); console.RegisterCommand((IConsoleCommand)(object)new StandardWeather()); console.RegisterCommand((IConsoleCommand)(object)new StatusEffect()); console.RegisterCommand((IConsoleCommand)(object)new PoisonStatusEffect()); console.RegisterCommand((IConsoleCommand)(object)new BurningStatusEffect()); console.RegisterCommand((IConsoleCommand)(object)new ProjectileSpawner()); console.RegisterCommand((IConsoleCommand)(object)new MeteorSpawner()); console.RegisterCommand((IConsoleCommand)(object)new ItemsRepairer()); console.RegisterCommand((IConsoleCommand)(object)new GiveItem()); console.RegisterCommand((IConsoleCommand)(object)new RoadSpawner()); console.RegisterCommand((IConsoleCommand)(object)new DropInventory()); sharedAcidRain = new RainWeather("acid_rain", "bonemass_throw_projectile", "oozebomb_explosion", "Bonemass", null, 2f); console.RegisterCommand((IConsoleCommand)(object)sharedAcidRain); sharedMeteorRain = new RainWeather("meteor_rain", "projectile_meteor", "", "Ashrain", new MeteorSpawner.MeteorProjectileParameters { aoe = 5f, damage = new DamageRanges { MinPhysicalDamage = 10f, MaxPhysicalDamage = 12f, MinElementalDamage = 10f, MaxElementalDamage = 15f } }, 2f); console.RegisterCommand((IConsoleCommand)(object)sharedMeteorRain); console.RegisterCommand((IConsoleCommand)(object)new GiveRandomItem()); console.RegisterCommand((IConsoleCommand)(object)new RootsWeather()); console.RegisterCommand((IConsoleCommand)(object)new FxEffectSpawner()); console.RegisterCommand((IConsoleCommand)(object)new SingleFxEffectSpawner()); console.RegisterCommand((IConsoleCommand)(object)new TestDamageFxEffectSpawner()); console.RegisterCommand((IConsoleCommand)(object)new Restoring()); console.RegisterCommand((IConsoleCommand)(object)new WaterEnemiesSpawner()); console.RegisterCommand((IConsoleCommand)(object)new ClearStatus()); console.RegisterCommand((IConsoleCommand)(object)new Recall()); console.RegisterCommand((IConsoleCommand)(object)new RemoveDrops()); console.RegisterCommand((IConsoleCommand)(object)new RaiseSkill()); console.RegisterCommand((IConsoleCommand)(object)new ChangeSpeed()); console.RegisterCommand((IConsoleCommand)(object)new GiveItemInv()); console.RegisterCommand((IConsoleCommand)(object)new ItemsRain()); console.RegisterCommand((IConsoleCommand)(object)new SkipTime()); console.RegisterCommand((IConsoleCommand)(object)new CustomSpawnerAnimal()); TierCommand tierCommand = new TierCommand(); console.RegisterCommand((IConsoleCommand)(object)tierCommand); commandManager = (ICommandManager)new HelperCommandManagerFormatted(LoggerFactory.Logger); commandManager.InitFromFile(Path.Combine(UtilitySettings.BaseFolder, "commands.data")); if (!isNeedValidate) { return; } tierCommand.IsValidPostCheck((string command) => console.IsValidCommandLine(command)); ((ILogger)LoggerFactory.Logger).Log((object)"init HelperCommandManager"); string[] commands = commandManager.GetCommands(); foreach (string text in commands) { if (!console.IsValidCommandLine(text?.Trim())) { LoggerFactory.Logger.LogDebugInfo((object)("command line '" + text + "' invalid")); } } } public void Start() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown ((ILogger)LoggerFactory.Logger).Log((object)"InteractiveMod Start"); eventsParser = (IEventsDataParser)new EventsDataParser((Action<string>)((ILogger)LoggerFactory.Logger).Log); ((ILogger)LoggerFactory.Logger).Log((object)"init EventsReaderOnFrame"); if (eventsReader == null) { eventsReader = new WebSocketEventsReader<SettingsData>((Action<IEventsData>)ProcessEvent, eventsParser, (Action<string>)((ILogger)LoggerFactory.Logger).Log, (Action<string>)((ILogger)LoggerFactory.Logger).Log, 1f, 1f, 0.5f); eventsReader.InitDefaultSocket(UtilitySettings.BaseFolder, "chaostricks_valheim", 13715, "127.0.0.1"); eventsReader.OnOpen = delegate { isNeedShowConnectMessage = true; isNeedShowDisconnectMessage = false; isAppConnected = true; }; eventsReader.OnCloseOnlyAfterConnect = delegate { isNeedShowDisconnectMessage = true; isNeedShowConnectMessage = false; isAppConnected = false; }; Action<string> defaultOnConfig = eventsReader.SocketHandler.OnConfigMessage; eventsReader.SocketHandler.OnConfigMessage = delegate(string s) { defaultOnConfig?.Invoke(s); WearNTearRPC_DamagePatcher.buildingDamageModifier = Settings.buildingDamageModifier; networkIsKillSpawnsAfterPlayerDeath = Settings.isKillSpawnsAfterPlayerDeath; networkIsEnableSpawnDeathTimer = Settings.isEnableSpawnDeathTimer; networkSpawnDeathTimerDuration = Settings.spawnDeathTimerDuration; }; eventsReader.OpenSocket(true); } ((ILogger)LoggerFactory.Logger).Log((object)"init EventsReaderOnKey"); keyEventsPath = Path.Combine(UtilitySettings.BaseFolder, "events_key.txt"); eventsReaderByKey = (IEventsReaderOnKey)new EventsReaderOnKey((Action<IEventsData>)ProcessEvent, eventsParser, (Action<string>)((ILogger)LoggerFactory.Logger).Log, (Action<string>)null); InitCommands(GameProxy.IsDebugMode()); InitOthersManagers(); ((ILogger)LoggerFactory.Logger).Log((object)"InteractiveMod init ended (2.2.2)"); } private void ProcessEvent(IEventsData data) { string eventID = data.EventID; if (!string.IsNullOrEmpty(eventID)) { ((ILogger)LoggerFactory.Logger).Log((object)("try to execute event: '" + eventID + "'")); string commandLine = commandManager.GetCommandData(eventID, true)?.Trim(); ProcessCommands(commandLine, data); } } private void ProcessCommands(string commandLine, IEventsData data) { ((ILogger)LoggerFactory.Logger).Log((object)("command: " + commandLine)); if (console.RunCommand(commandLine, data, (Action<string>)ProcessStandardCommand)) { ((ILogger)LoggerFactory.Logger).Log((object)("event '" + data.EventID + "' executing is completed")); string trans = translationManager.GetTrans(data.EventID, data.Lang); trans = trans.Replace("%name%", data.Username); NotifyController.instance.AddNotifyToQueue(trans); } else { ((ILogger)LoggerFactory.Logger).Log((object)("event '" + data.EventID + "' executing is failed")); } } public bool IsReadyForCheckEvent() { //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) try { Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name != "main") { return false; } Player currentPlayer = GameProxy.CurrentPlayer; return !((Object)(object)currentPlayer == (Object)null) && !((Character)currentPlayer).IsDead() && !((Character)currentPlayer).IsTeleporting() && !((Character)currentPlayer).InCutscene() && !currentPlayer.IsSleeping() && !((Object)(object)ZNet.instance == (Object)null) && !((Object)(object)ObjectDB.instance == (Object)null) && !((Object)(object)ZNetScene.instance == (Object)null); } catch (Exception arg) { if (isReadyForCheckEventErrorsLimit > 0) { ((ILogger)LoggerFactory.Logger).Log((object)$"IsReadyForCheckEvent error: {arg}"); isReadyForCheckEventErrorsLimit--; } return false; } } public void Update() { try { if (IsReadyForCheckEvent()) { if (isNeedTriggerOnFirstConnect) { GameProxy.RunGameConsoleCommand("s Waiting until an integration will be started in the PC application Chaos Tricks"); isNeedTriggerOnFirstConnect = false; } if (isNeedShowConnectMessage) { isNeedShowConnectMessage = false; GameProxy.RunGameConsoleCommand("s Chaos Tricks connected!"); } if (isNeedShowDisconnectMessage) { isNeedShowDisconnectMessage = false; GameProxy.RunGameConsoleCommand("s Chaos Tricks disconnected!"); GameProxy.RunGameConsoleCommand("nonono"); } ((EventsReaderOnFrame)eventsReader).ReadAndProcessAllWithDelayOnFrame(Time.deltaTime); if (Input.GetKey((KeyCode)306) && Input.GetKeyDown((KeyCode)261)) { eventsReaderByKey.ReadAndProcessAllOnKey(keyEventsPath, false); } DebugHotkeysOnUpdate(); } StandardConsoleManager.instance.Update(); NotifyController.instance.Update(); SummonController.instance.OnUpdate(Time.deltaTime); GameProxy.ScheduleManager.OnUpdate(Time.deltaTime); } catch (Exception arg) { if (isReadyForCheckEventErrorsLimit > 0) { ((ILogger)LoggerFactory.Logger).Log((object)$"onUpdate error: {arg}"); isReadyForCheckEventErrorsLimit--; } } } public static void ReinitMod() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown ((ILogger)LoggerFactory.Logger).Log((object)"ReinitMod"); MeteorSpawner.RemoveMeteorOwner(); SummonController.instance?.ClearEnemies(); NotifyController.instance?.ClearQueue(); console = new UtilityConsole(LoggerFactory.Logger, (List<string>)null); if (instance != null) { instance.InitCommands(isNeedValidate: false); instance.InitOthersManagers(); } StandardConsoleManager.instance = new StandardConsoleManager(); } public void DebugHotkeysOnUpdate() { if (!GameProxy.IsDebugMode()) { return; } if (Input.GetKeyDown((KeyCode)278)) { ReinitMod(); } if (Input.GetKeyDown((KeyCode)265)) { EnemiesRemover.KillAll(); } if (Input.GetKey((KeyCode)306)) { if (Input.GetKeyDown((KeyCode)260)) { DebugInfo(); } else if (Input.GetKeyDown((KeyCode)263)) { DebugInfoItemPrefabs(); DebugInfoObjectPrefabs(); DebugInfoStatusEffects(); } else if (Input.GetKeyDown((KeyCode)264)) { DebugPosInfo(); } } } public void DebugInfo() { StringBuilder stringBuilder = new StringBuilder(); foreach (EnvSetup environment in EnvMan.instance.m_environments) { stringBuilder.Append(environment.m_name + "\n"); } ((ILogger)LoggerFactory.Logger).Log((object)$"env list:\n{stringBuilder}"); } public void DebugPosInfo() { bool flag = GameProxy.IsPlayerCloseToOthers(GameProxy.CurrentPlayer, GameProxy.TargetPlayers, 30f); ((ILogger)LoggerFactory.Logger).Log((object)$"Close to others: {flag}"); } public void DebugInfoItemPrefabs() { StringBuilder stringBuilder = new StringBuilder(); foreach (GameObject item in ObjectDB.instance.m_items) { stringBuilder.Append(((Object)item).name + "\n"); } ((ILogger)LoggerFactory.Logger).Log((object)$"\n\nprefab names list:\n{stringBuilder}"); } public void DebugInfoObjectPrefabs() { StringBuilder stringBuilder = new StringBuilder(); foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { stringBuilder.Append(((prefab != null) ? ((Object)prefab).name : null) + "\n"); } ((ILogger)LoggerFactory.Logger).Log((object)$"\n\nnet prefab names list:\n{stringBuilder}"); if (ZNetScene.instance.m_nonNetViewPrefabs == null) { return; } stringBuilder = new StringBuilder(); foreach (GameObject nonNetViewPrefab in ZNetScene.instance.m_nonNetViewPrefabs) { stringBuilder.Append(((nonNetViewPrefab != null) ? ((Object)nonNetViewPrefab).name : null) + "\n"); } ((ILogger)LoggerFactory.Logger).Log((object)$"\n\nnon net prefab names list:\n{stringBuilder}"); } public void DebugInfoStatusEffects() { StringBuilder stringBuilder = new StringBuilder(); foreach (StatusEffect statusEffect in ObjectDB.instance.m_StatusEffects) { stringBuilder.Append(((statusEffect != null) ? ((Object)statusEffect).name : null) + "\n"); } ((ILogger)LoggerFactory.Logger).Log((object)$"\n\nnet status effect names list:\n{stringBuilder}"); } } public class SettingsData { public bool isAllPlayers = true; public int hitpointsModifier = 100; public int spawnDamageModifier = 100; public int buildingDamageModifier = 25; public bool isSpawnsHaveDrop; public bool isKillSpawnsAfterPlayerDeath = true; public bool isEnableSpawnDeathTimer = true; public int spawnDeathTimerDuration = 150; public string meteorSpawnerType = "Ghost"; } public class NotifyController { public static NotifyController instance = new NotifyController(); private readonly Queue<string> notifies = new Queue<string>(); private readonly int baseDelay = 2; private float delay; public void AddNotifyToQueue(string msg) { notifies.Enqueue(msg); } public void ClearQueue() { notifies.Clear(); } public void Update() { if (delay > 0f) { delay -= Time.deltaTime; } else if (notifies.Count > 0 && !((Object)(object)MessageHud.instance == (Object)null)) { string text = notifies.Dequeue(); ((ILogger)LoggerFactory.Logger).Log((object)("Show notify " + text)); MessageHud.instance.MessageAll((MessageType)2, text); delay = baseDelay; } } } public class StandardConsoleManager { public static StandardConsoleManager instance = new StandardConsoleManager(); private readonly Queue<string> commands = new Queue<string>(); private int logChatLimit = 10; public void AddCommandToQueue(string command) { commands.Enqueue(command); } public void InstantlyRunCommand(string command) { try { ((ILogger)LoggerFactory.Logger).Log((object)"prepare chat"); ((TMP_InputField)((Terminal)Console.instance).m_input).text = command; ((ILogger)LoggerFactory.Logger).Log((object)("trigger standard command " + command)); GameProxy.TriggerConsoleInputText(); ((TMP_InputField)((Terminal)Console.instance).m_input).text = string.Empty; } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"InstantlyRunCommand error: {arg}"); } } public void Update() { try { if (commands.Count <= 0) { return; } if ((Object)(object)Console.instance == (Object)null || (Object)(object)((Terminal)Console.instance).m_input == (Object)null) { if (logChatLimit > 0) { logChatLimit--; ((ILogger)LoggerFactory.Logger).LogWarning((object)$"InstantlyRunCommand->Update error: ci or cim null ({(Object)(object)Console.instance == (Object)null})"); } } else { InstantlyRunCommand(commands.Dequeue()); } } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"StandardConsoleManager error: {arg}"); } } } } namespace valheim_mod.Patchers { [HarmonyPatch(typeof(Game))] [HarmonyPatch("OnDestroy")] public class LocalGameOnDestroyPatcher { public static void Prefix(Game __instance) { if ((Object)(object)__instance == (Object)null) { return; } try { ((ILogger)LoggerFactory.Logger).Log((object)"Game OnDestroy prefix"); InteractiveMod.ReinitMod(); } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)string.Format("{0} error: {1}", "Game OnDestroy prefix", arg)); } } } [HarmonyPatch(typeof(Player))] [HarmonyPatch("OnDestroy")] public class LocalPlayerOnDestroyPatcher { public static void Prefix(Player __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)Player.m_localPlayer != (Object)(object)__instance)) { ((ILogger)LoggerFactory.Logger).Log((object)"Player OnDestroy prefix"); } } } [HarmonyPatch(typeof(Character))] [HarmonyPatch("RPC_Damage")] public class CharacterRPC_DamagePatcher { private static readonly FieldRef<Character, ZNetView> m_nviewRef = AccessTools.FieldRefAccess<Character, ZNetView>("m_nview"); private static bool isNeedTestPatchingLog = true; public static readonly string CustomMinDamageId = "min_attack_damage"; public static readonly string CustomMaxDamageId = "max_attack_damage"; public static readonly string CustomMinElemDamageId = "min_attack_elem_damage"; public static readonly string CustomMaxElemDamageId = "max_attack_elem_damage"; public static void SetupHitData(HitData hit, float damage, float elemDamage) { if (hit.m_damage.m_damage != 0f) { hit.m_damage.m_damage = damage; } if (hit.m_damage.m_blunt != 0f) { hit.m_damage.m_blunt = damage; } if (hit.m_damage.m_chop != 0f) { hit.m_damage.m_chop = damage; } if (hit.m_damage.m_fire != 0f) { hit.m_damage.m_fire = elemDamage; } if (hit.m_damage.m_frost != 0f) { hit.m_damage.m_frost = elemDamage; } if (hit.m_damage.m_lightning != 0f) { hit.m_damage.m_lightning = elemDamage; } if (hit.m_damage.m_pickaxe != 0f) { hit.m_damage.m_pickaxe = damage; } if (hit.m_damage.m_pierce != 0f) { hit.m_damage.m_pierce = damage; } if (hit.m_damage.m_poison != 0f) { hit.m_damage.m_poison = elemDamage; } if (hit.m_damage.m_spirit != 0f) { hit.m_damage.m_spirit = elemDamage; } if (hit.m_damage.m_slash != 0f) { hit.m_damage.m_slash = damage; } } private static float ApplyAC(float ac, float damage) { if (damage == 0f) { return 0f; } if (ac <= (ac + damage) * 0.5f) { return ac + damage; } float num = Mathf.Sqrt(damage * ac * 4f); if (damage <= num) { return num; } return damage; } private static void ProcessHit(Character player, ZDO zdo, HitData hit) { float @float = zdo.GetFloat(CustomMinDamageId, -1f); if (@float == -1f) { ((ILogger)LoggerFactory.Logger).Log((object)"CharacterPatcher catch hit from default enemy"); return; } float float2 = zdo.GetFloat(CustomMaxDamageId, @float + 2f); float baseDamage = Random.Range(@float, float2); float float3 = zdo.GetFloat(CustomMinElemDamageId, 0f); float float4 = zdo.GetFloat(CustomMaxElemDamageId, 0f); float baseElemDamage = Random.Range(float3, float4); if (((DamageTypes)(ref hit.m_damage)).GetTotalElementalDamage() == 0f) { baseElemDamage = 0f; } ApplyArmor(player.GetBodyArmor(), hit, baseDamage, baseElemDamage); } private static void ApplyArmor(float ac, HitData hit, float baseDamage, float baseElemDamage) { float num = 1f; if (hit.m_damage.m_poison == 0f && (baseDamage != 0f || baseElemDamage != 0f)) { float num2 = baseElemDamage + baseDamage; num = ApplyAC(ac, num2) / num2; } else { ((ILogger)LoggerFactory.Logger).Log((object)"poison damage fixed"); } float num3 = baseDamage * num; float num4 = baseElemDamage * num; SetupHitData(hit, num3, num4); ((ILogger)LoggerFactory.Logger).Log((object)($"CharacterPatcher catch hit {num3} with armor {ac} for base {baseDamage}. " + $"Elem damage {num4} for base {baseElemDamage}")); } public static void Prefix(Character __instance, long sender, HitData hit) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || !__instance.IsPlayer() || hit == null || __instance.IsDebugFlying() || __instance.IsDead() || __instance.IsTeleporting() || __instance.InCutscene()) { return; } try { if (isNeedTestPatchingLog) { isNeedTestPatchingLog = false; ((ILogger)LoggerFactory.Logger).Log((object)"CharacterPatcher ApplyDamage Prefix debug"); } ZNetView val = m_nviewRef.Invoke(__instance); if (!((Object)(object)val == (Object)null) && val.IsValid()) { ZDO zDO = ZDOMan.instance.GetZDO(hit.m_attacker); if (zDO != null) { ProcessHit(__instance, zDO, hit); } } } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"CharacterPatcher FixedUpdate Prefix error: {arg}"); } } } [HarmonyPatch(typeof(WearNTear))] [HarmonyPatch("RPC_Damage")] public class WearNTearRPC_DamagePatcher { public static int buildingDamageModifier = 25; private static void Prefix(ref HitData hit, Piece ___m_piece) { if (hit == null) { return; } Character attacker = hit.GetAttacker(); if ((Object)(object)attacker == (Object)null) { return; } ZDO zDO = GameProxy.GetZDO(attacker); if (zDO != null) { string @string = zDO.GetString(GameProxy.PlayerNameSpawnId, ""); ((ILogger)LoggerFactory.Logger).Log((object)("EnemiesRemover PlayerName " + @string)); bool flag = (Object)(object)___m_piece != (Object)null && ___m_piece.GetCreator() == 0; if (!string.IsNullOrEmpty(@string) && !flag) { float coeff = (float)buildingDamageModifier / 100f; MultiplyDamage(hit, coeff); } } } private static void MultiplyDamage(HitData hit, float coeff) { float num = Math.Max(0f, coeff); hit.m_damage.m_damage *= num; hit.m_damage.m_blunt *= num; hit.m_damage.m_chop *= num; hit.m_damage.m_fire *= num; hit.m_damage.m_frost *= num; hit.m_damage.m_lightning *= num; hit.m_damage.m_pickaxe *= num; hit.m_damage.m_pierce *= num; hit.m_damage.m_slash *= num; hit.m_damage.m_poison *= num; hit.m_damage.m_spirit *= num; } } public class MainPatcher { public static void InitPatch() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) try { ((ILogger)LoggerFactory.Logger).Log((object)"HelperPatcher init"); new Harmony("com.Loki.patch").PatchAll(); } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"HelperPatcher error: {arg}"); } } } [HarmonyPatch(typeof(ZNet))] [HarmonyPatch("Awake")] public class ZPackagePatcher { private static void Postfix() { ZRoutedRpc.instance.Register<ZPackage>("bft_ChangeSpeed", (Action<long, ZPackage>)ChangePlayerSpeed); ZRoutedRpc.instance.Register("bft_ClearStatus", (Action<long>)ChangePlayerStatus); ZRoutedRpc.instance.Register("bft_DropInventory", (Action<long>)DropPlayerInventory); ZRoutedRpc.instance.Register<ZPackage>("bft_GodMod", (Action<long, ZPackage>)PlayerGodmod); ZRoutedRpc.instance.Register<ZPackage>("bft_RaiseSkill", (Action<long, ZPackage>)ChangePlayerSkill); ZRoutedRpc.instance.Register<ZPackage>("bft_StandardWeather", (Action<long, ZPackage>)ChangePlayerWeather); ZRoutedRpc.instance.Register<ZPackage>("bft_SingleFxEffectSpawner", (Action<long, ZPackage>)SpawnSingleFxFunc); ZRoutedRpc.instance.Register<ZPackage>("bft_GiveItemInInv", (Action<long, ZPackage>)GiveItemInPlayerInv); ZRoutedRpc.instance.Register("bft_ChangeModel", (Action<long>)ChangePlayerModel); ZRoutedRpc.instance.Register("bft_ItemsRepairer", (Action<long>)RepairAllPlayer); ZRoutedRpc.instance.Register<ZPackage>("bft_ChangeSpawnedMobNames", (Action<long, ZPackage>)ChangeSpawnedMobNames); ZRoutedRpc.instance.Register<ZPackage>("bft_ChangePlayerDebugEnv", (Action<long, ZPackage>)ChangePlayerDebugEnv); ZRoutedRpc.instance.Register("bft_RemoveDrops", (Action<long>)RemovePlayerDrops); ZRoutedRpc.instance.Register("bft_SkipTime", (Action<long>)HostSkipTime); ZRoutedRpc.instance.Register("bft_Recall", (Action<long>)HostRecall); ZRoutedRpc.instance.Register<ZPackage>("bft_CustomSpawner", (Action<long, ZPackage>)SpawnMobs); ZRoutedRpc.instance.Register<ZPackage>("bft_CustomSpawnerAnimal", (Action<long, ZPackage>)SpawnAnimalMobs); ZRoutedRpc.instance.Register<ZPackage>("bft_CustomSpawnerWater", (Action<long, ZPackage>)SpawnWaterMobs); ZRoutedRpc.instance.Register<ZPackage>("bft_FxEffectSpawner", (Action<long, ZPackage>)NetworkFxEffectSpawner); ZRoutedRpc.instance.Register<ZPackage>("bft_GiveItem", (Action<long, ZPackage>)NetworkGiveItem); ZRoutedRpc.instance.Register<ZPackage>("bft_GiveRandomItem", (Action<long, ZPackage>)NetworkGiveRandomItem); ZRoutedRpc.instance.Register<ZPackage>("bft_StatusEffect", (Action<long, ZPackage>)NetworkStatusEffect); ZRoutedRpc.instance.Register<ZPackage>("bft_RoadSpawner", (Action<long, ZPackage>)NetworkRoadSpawner); ZRoutedRpc.instance.Register("bft_BurningStatusEffect", (Action<long>)NetworkBurningStatusEffect); ZRoutedRpc.instance.Register("bft_PoisonStatusEffect", (Action<long>)NetworkPoisonStatusEffect); ZRoutedRpc.instance.Register("bft_Restoring", (Action<long>)NetworkRestoring); ZRoutedRpc.instance.Register("bft_EnemiesRemover", (Action<long>)NetworkEnemiesRemover); } private static void ChangePlayerSpeed(long id, ZPackage package) { LoggerFactory.Logger.LogDebugInfo((object)$"ChangePlayerSpeed CurrentPlayer {GameProxy.CurrentPlayer}"); double num = package.ReadDouble(); int num2 = package.ReadInt(); LoggerFactory.Logger.LogDebugInfo((object)$"speedCoeff {num} timer {num2}"); ChangeSpeed.sharedInstance?.ActivateChangeSpeedTimer((float)num, num2); } private static void ChangePlayerStatus(long id) { LoggerFactory.Logger.LogDebugInfo((object)$"ClearPlayerStatus CurrentPlayer {GameProxy.CurrentPlayer}"); ClearStatus.sharedInstance?.ClearPlayerStatus(); } private static void DropPlayerInventory(long id) { LoggerFactory.Logger.LogDebugInfo((object)$"DropPlayerInventory CurrentPlayer {GameProxy.CurrentPlayer}"); DropInventory.sharedInstance?.DropLocalPlayerInventory(); } private static void PlayerGodmod(long id, ZPackage package) { int num = package.ReadInt(); LoggerFactory.Logger.LogDebugInfo((object)$"PlayerGodmod CurrentPlayer {GameProxy.CurrentPlayer} for {num}"); GodMod.sharedInstance?.CreateGodModTimer(num); } private static void ChangePlayerSkill(long id, ZPackage package) { string text = package.ReadString(); int lvl = package.ReadInt(); LoggerFactory.Logger.LogDebugInfo((object)$"ChangePlayerSkill CurrentPlayer {GameProxy.CurrentPlayer} skill param {text} "); RaiseSkill.sharedInstance?.SwitchFunc(text, lvl); } private static void ChangePlayerWeather(long id, ZPackage package) { string text = package.ReadString(); int num = package.ReadInt(); LoggerFactory.Logger.LogDebugInfo((object)$"ChangePlayerWeather CurrentPlayer {GameProxy.CurrentPlayer} weather {text} for {num}"); StandardWeather.ChangeWeather(text, num); } private static void SpawnSingleFxFunc(long id, ZPackage package) { string text = package.ReadString(); LoggerFactory.Logger.LogDebugInfo((object)$"ChangePlayerWeather CurrentPlayer {GameProxy.CurrentPlayer} spawn fx {text}"); SingleFxEffectSpawner.SpawnFX(GameProxy.CurrentPlayer, text); } private static void GiveItemInPlayerInv(long id, ZPackage package) { string text = package.ReadString(); int num = package.ReadInt(); bool flag = package.ReadBool(); LoggerFactory.Logger.LogDebugInfo((object)$"GiveItemInPlayerInv CurrentPlayer {GameProxy.CurrentPlayer} items {text} count {num} in inv {flag}"); GiveItemInv.GiveRandomItem(GameProxy.CurrentPlayer, text, num, flag); } private static void ChangePlayerModel(long id) { LoggerFactory.Logger.LogDebugInfo((object)$"ChangePlayersModel CurrentPlayer {GameProxy.CurrentPlayer}"); ChangeModel.SwitchPlayerModel(GameProxy.CurrentPlayer); } private static void RepairAllPlayer(long id) { LoggerFactory.Logger.LogDebugInfo((object)$"RepairAllPlayer CurrentPlayer {GameProxy.CurrentPlayer}"); ItemsRepairer.RepairAll(); } private static void ChangeSpawnedMobNames(long id, ZPackage package) { uint num = package.ReadUInt(); long num2 = package.ReadLong(); string text = package.ReadString(); LoggerFactory.Logger.LogDebugInfo((object)$"ChangeSpawnedMobNames CurrentPlayer {GameProxy.CurrentPlayer}, objectId {num}, userId {num2}, name {text}"); SummonController.instance.AddPackageCharacter(new SummonController.PackageEnemiesData { id = num, userId = num2, name = text }); } private static NetworkSpawnData ReadSpawnData(ZPackage package, bool isAnimal) { int num = package.ReadInt(); int num2 = package.ReadInt(); int buildingDamageModifier = package.ReadInt(); bool flag = package.ReadBool(); bool flag2 = package.ReadBool(); bool flag3 = package.ReadBool(); int num3 = package.ReadInt(); string argName = package.ReadString(); int argCount = package.ReadInt(); int argLevel = package.ReadInt(); float argHitsPercent = package.ReadSingle(); float argMinPhysicalDamage = package.ReadSingle(); float num4 = package.ReadSingle(); float argMinElementalDamage = package.ReadSingle(); float argMaxElementalDamage = package.ReadSingle(); string text = package.ReadString(); LoggerFactory.Logger.LogDebugInfo((object)$"ReadSpawnData hpm {num}, sdm {num2}, username {text}"); SettingsData settings = InteractiveMod.Settings; if (InteractiveMod.IsAppConnected) { return new NetworkSpawnData { spawnDamageModifier = settings.spawnDamageModifier, hitpointsModifier = settings.hitpointsModifier, buildingDamageModifier = settings.buildingDamageModifier, isSpawnsHaveDrop = (isAnimal ? flag : settings.isSpawnsHaveDrop), isKillSpawnsAfterPlayerDeath = settings.isKillSpawnsAfterPlayerDeath, isEnableSpawnDeathTimer = settings.isEnableSpawnDeathTimer, spawnDeathTimerDuration = settings.spawnDeathTimerDuration, argName = argName, argCount = argCount, argLevel = argLevel, argHitsPercent = argHitsPercent, argMaxElementalDamage = argMaxElementalDamage, argMinElementalDamage = argMinElementalDamage, argMaxPhysicalDamage = num4, argMinPhysicalDamage = argMinPhysicalDamage, username = text }; } WearNTearRPC_DamagePatcher.buildingDamageModifier = buildingDamageModifier; InteractiveMod.networkIsKillSpawnsAfterPlayerDeath = flag2; InteractiveMod.networkIsEnableSpawnDeathTimer = flag3; InteractiveMod.networkSpawnDeathTimerDuration = num3; return new NetworkSpawnData { spawnDamageModifier = num2, hitpointsModifier = num, buildingDamageModifier = buildingDamageModifier, isSpawnsHaveDrop = flag, isKillSpawnsAfterPlayerDeath = flag2, isEnableSpawnDeathTimer = flag3, spawnDeathTimerDuration = num3, argName = argName, argCount = argCount, argLevel = argLevel, argHitsPercent = argHitsPercent, argMaxElementalDamage = num4, argMinPhysicalDamage = argMinPhysicalDamage, argMaxPhysicalDamage = num4, argMinElementalDamage = argMinElementalDamage, username = text }; } private static void SpawnMobs(long id, ZPackage package) { LoggerFactory.Logger.LogDebugInfo((object)$"SpawnMobs CurrentPlayer {GameProxy.CurrentPlayer}, package {id}"); CustomSpawner.RPC_SpawnObjects(ReadSpawnData(package, isAnimal: false)); } private static void SpawnAnimalMobs(long id, ZPackage package) { LoggerFactory.Logger.LogDebugInfo((object)$"SpawnAnimalMobs CurrentPlayer {GameProxy.CurrentPlayer}, package {id}"); CustomSpawnerAnimal.RPC_SpawnObjects(ReadSpawnData(package, isAnimal: true)); } private static void SpawnWaterMobs(long id, ZPackage package) { LoggerFactory.Logger.LogDebugInfo((object)$"SpawnWaterMobs CurrentPlayer {GameProxy.CurrentPlayer}, package {id}"); WaterEnemiesSpawner.RPC_SpawnObjectsInWater(ReadSpawnData(package, isAnimal: false)); } private static void ChangePlayerDebugEnv(long id, ZPackage package) { string text = package.ReadString(); LoggerFactory.Logger.LogDebugInfo((object)$"ChangePlayerDebugEnv CurrentPlayer {GameProxy.CurrentPlayer} weather {text}"); EnvMan.instance.m_debugEnv = text; } private static void RemovePlayerDrops(long id) { LoggerFactory.Logger.LogDebugInfo((object)$"RemovePlayerDrops CurrentPlayer {GameProxy.CurrentPlayer}"); RemoveDrops.sharedInstance?.RemoveAllDrops(); } private static void HostSkipTime(long id) { LoggerFactory.Logger.LogDebugInfo((object)$"HostSkipTime CurrentPlayer {GameProxy.CurrentPlayer}"); if (ZNet.instance.IsServer()) { SkipTime.sharedInstance?.SkipHalfDay(); } } private static void HostRecall(long id) { LoggerFactory.Logger.LogDebugInfo((object)$"HostRecall CurrentPlayer {GameProxy.CurrentPlayer}"); if (ZNet.instance.IsServer()) { Recall.sharedInstance?.SendRecall(); } } private static void NetworkFxEffectSpawner(long id, ZPackage package) { string text = package.ReadString(); LoggerFactory.Logger.LogDebugInfo((object)$"NetworkFxEffectSpawner CurrentPlayer {GameProxy.CurrentPlayer}, name {text}"); FxEffectSpawner.SpawnFX(GameProxy.CurrentPlayer, text); } private static void NetworkGiveItem(long id, ZPackage package) { string text = package.ReadString(); int count = package.ReadInt(); int level = package.ReadInt(); string username = package.ReadString(); LoggerFactory.Logger.LogDebugInfo((object)$"NetworkGiveItem CurrentPlayer {GameProxy.CurrentPlayer}, item {text}"); GiveItem.GiveItems(GameProxy.CurrentPlayer, text, count, level, username); } private static void NetworkGiveRandomItem(long id, ZPackage package) { string text = package.ReadString(); int count = package.ReadInt(); string username = package.ReadString(); LoggerFactory.Logger.LogDebugInfo((object)$"NetworkGiveRandomItem CurrentPlayer {GameProxy.CurrentPlayer}, group {text}"); GiveRandomItem.sharedInstance?.SpawnItem(GameProxy.CurrentPlayer, text, count, username); } private static void NetworkStatusEffect(long id, ZPackage package) { string text = package.ReadString(); LoggerFactory.Logger.LogDebugInfo((object)$"NetworkStatusEffect CurrentPlayer {GameProxy.CurrentPlayer}, name {text}"); StatusEffect.AddStatusEffect(GameProxy.CurrentPlayer, text); } private static void NetworkRoadSpawner(long id, ZPackage package) { int num = package.ReadInt(); LoggerFactory.Logger.LogDebugInfo((object)$"NetworkRoadSpawner CurrentPlayer {GameProxy.CurrentPlayer}, timer {num}"); RoadSpawner.SpawnRoad(GameProxy.CurrentPlayer, num); } private static void NetworkBurningStatusEffect(long id) { LoggerFactory.Logger.LogDebugInfo((object)$"NetworkBurningStatusEffect CurrentPlayer {GameProxy.CurrentPlayer}"); BurningStatusEffect.AddBurningEffect(GameProxy.CurrentPlayer); } private static void NetworkPoisonStatusEffect(long id) { LoggerFactory.Logger.LogDebugInfo((object)$"NetworkPoisonStatusEffect CurrentPlayer {GameProxy.CurrentPlayer}"); PoisonStatusEffect.AddPoisonEffect(GameProxy.CurrentPlayer); } private static void NetworkRestoring(long id) { LoggerFactory.Logger.LogDebugInfo((object)$"NetworkRestoring CurrentPlayer {GameProxy.CurrentPlayer}"); Restoring.SetFullHealAndStamina(GameProxy.CurrentPlayer); } private static void NetworkEnemiesRemover(long id) { LoggerFactory.Logger.LogDebugInfo((object)$"NetworkEnemiesRemover CurrentPlayer {GameProxy.CurrentPlayer}"); EnemiesRemover.KillAll(); } } } namespace valheim_mod.Commands { public class ChangeSpeed : IConsoleCommand { public float basePlayerSpeed; public bool isActive; public static ChangeSpeed sharedInstance; public virtual string Id => "change_speed"; public ChangeSpeed() { sharedInstance = this; } public virtual bool Execute(IEnumerable<string> args) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown IEnumerator<string> args2 = args?.GetEnumerator(); float num = CommandsArgsReader.ReadFloat(args2, 1f); int num2 = CommandsArgsReader.ReadInt(args2, 0); if (!isActive) { if (InteractiveMod.Settings.isAllPlayers) { ZPackage val = new ZPackage(); val.Write((double)num); val.Write(num2); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "bft_ChangeSpeed", new object[1] { val }); } else { ActivateChangeSpeedTimer(num, num2); } } return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { return true; } private void ChangePlayerSpeed(Character player, float speed) { player.m_runSpeed = speed; } public void ActivateChangeSpeedTimer(float speedCoeff, int timer) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown if (!isActive) { basePlayerSpeed = ((Character)GameProxy.CurrentPlayer).m_runSpeed; ((ILogger)LoggerFactory.Logger).Log((object)$"Base player speed {basePlayerSpeed}"); isActive = true; } Player currentPlayer = GameProxy.CurrentPlayer; float num = basePlayerSpeed * speedCoeff; ChangePlayerSpeed((Character)(object)currentPlayer, num); ((ILogger)LoggerFactory.Logger).Log((object)$"Change speed for {num}"); GameProxy.ScheduleManager.AppendTimerTask(new TimerTaskData { id = Id, duration = timer, finishAction = delegate { ChangePlayerSpeed((Character)(object)GameProxy.CurrentPlayer, basePlayerSpeed); ((ILogger)LoggerFactory.Logger).Log((object)$"Changed speed ends, default speed is set to {basePlayerSpeed}"); isActive = false; } }, false); } } public class ClearStatus : IConsoleCommand { public static ClearStatus sharedInstance; public virtual string Id => "player_clearstatus"; public ClearStatus() { sharedInstance = this; } public virtual bool Execute(IEnumerable<string> args) { if (InteractiveMod.Settings.isAllPlayers) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "bft_ClearStatus", Array.Empty<object>()); } else { ClearPlayerStatus(); } return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { return CommandsValidator.IsZeroArgs(args); } public void ClearPlayerStatus() { GameProxy.CurrentPlayer.ClearHardDeath(); ((Character)GameProxy.CurrentPlayer).GetSEMan().RemoveAllStatusEffects(false); } } public class CustomSpawnerAnimal : IConsoleCommandWithData, IConsoleCommand { public virtual string Id => "custom_spawn_animal"; public virtual bool Execute(IEnumerable<string> args) { return false; } public virtual bool Execute(IEnumerable<string> args, IEventsData data) { IEnumerator<string> enumerator = args?.GetEnumerator(); string name = CommandsArgsReader.ReadString(enumerator); int count = CommandsArgsReader.ReadInt(enumerator, 1); int level = CommandsArgsReader.ReadInt(enumerator, 0); bool flag = CommandsArgsReader.ReadBool(enumerator, defaultValue: true); float hitsPercent = CommandsArgsReader.ReadFloat(enumerator, 1f); DamageRanges damageRanges = new DamageRanges(); damageRanges.ReadFromArgs(enumerator); if (InteractiveMod.Settings.isAllPlayers) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "bft_CustomSpawnerAnimal", new object[1] { CustomSpawner.GenerateSpawnPackage(name, count, level, hitsPercent, flag, damageRanges, data) }); } else { SpawnObjects(name, count, level, hitsPercent, damageRanges, flag, data); } return true; } public static bool IsValidSpawnCommandArgs(IEnumerable<string> args) { IEnumerator<string> enumerator = args.GetEnumerator(); if (CommandsValidator.IsValidString(enumerator, (string name) => (Object)(object)ZNetScene.instance != (Object)null && Object.op_Implicit((Object)(object)ZNetScene.instance.GetPrefab(name))) && CommandsValidator.IsValidInt(enumerator, 1, 20, isSkippable: true) && CommandsValidator.IsValidInt(enumerator, 0, 3, isSkippable: true) && CommandsValidator.IsValidBool(enumerator) && CommandsValidator.IsValidFloat(enumerator, 0f, 50f, isSkippable: true)) { return DamageRanges.IsValidDamage(enumerator, isSkippable: true); } return false; } public bool IsValidCommandArgs(IEnumerable<string> args) { return IsValidSpawnCommandArgs(args); } public static void ProcessDropItems(GameObject obj, bool enableDrop) { CharacterDrop componentInChildren = obj.GetComponentInChildren<CharacterDrop>(); if ((Object)(object)componentInChildren != (Object)null) { if (enableDrop) { LoggerFactory.Logger.LogDebugInfo((object)"drop items fixed"); componentInChildren.SetDropsEnabled(true); } else { LoggerFactory.Logger.LogDebugInfo((object)"drop items fixed"); componentInChildren.SetDropsEnabled(false); componentInChildren.m_drops = new List<Drop>(); } } } public static GameObject SpawnSingleObject(GameObject prefab, Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) GameObject obj = Object.Instantiate<GameObject>(prefab, pos, Quaternion.identity); CustomSpawner.ProcessDurability(obj); CustomSpawner.ProcessQuality(obj, 1); return obj; } public static void SpawnObjects(string name, int count, int level, float hitsPercent, DamageRanges damage, bool enableDrop, IEventsData data, string fxSpawnName = "vfx_spawn_small", Func<Player, Vector3> customPos = null) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = ZNetScene.instance.GetPrefab(name); if ((Object)(object)prefab == (Object)null) { LoggerFactory.LogWithUI("Missing object " + name); return; } GameObject prefab2 = ZNetScene.instance.GetPrefab(fxSpawnName); if ((Object)(object)prefab2 == (Object)null) { ((ILogger)LoggerFactory.Logger).Log((object)("Missing fx object " + fxSpawnName)); } Player[] targetPlayers = GameProxy.TargetPlayers; foreach (Player val in targetPlayers) { Transform transform = ((Component)val).transform; for (int j = 0; j < count; j++) { try { Vector3 val2 = customPos?.Invoke(val) ?? CustomSpawner.GetPointAtHalfOfSphere(transform.position, transform.forward, 6.5f); GameObject val3 = SpawnSingleObject(prefab, val2 + Vector3.up); MathUtility.LookAt(val3.transform, ((Component)val).transform); CustomSpawner.ProcessLevel(val3, level); if ((Object)(object)prefab2 != (Object)null) { SpawnSingleObject(prefab2, val2); } ProcessDropItems(val3, enableDrop); CustomSpawner.ProcessHitPoints(val3, hitsPercent, InteractiveMod.Settings.hitpointsModifier); if (data != null && data.Username != null) { CustomSpawner.ProcessEnemyName(val3, data.Username, val); } CustomSpawner.ProcessEnemyDamage(val3, damage, InteractiveMod.Settings.spawnDamageModifier); } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"SpawnObjects spawn {name} index {count} error: {arg}"); } } } } public static void RPC_SpawnObjects(NetworkSpawnData data, string fxSpawnName = "vfx_spawn_small", Func<Player, Vector3> customPos = null) { //IL_0090: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_00a8: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) if (data == null) { ((ILogger)LoggerFactory.Logger).Log((object)"RPC_SpawnObjects NetworkSpawnData is null"); return; } GameObject prefab = ZNetScene.instance.GetPrefab(data.argName); if ((Object)(object)prefab == (Object)null) { LoggerFactory.LogWithUI("Missing object " + data.argName); return; } GameObject prefab2 = ZNetScene.instance.GetPrefab(fxSpawnName); if ((Object)(object)prefab2 == (Object)null) { ((ILogger)LoggerFactory.Logger).Log((object)("Missing fx object " + fxSpawnName)); } Player currentPlayer = GameProxy.CurrentPlayer; Transform transform = ((Component)currentPlayer).transform; for (int i = 0; i < data.argCount; i++) { try { Vector3 val = customPos?.Invoke(currentPlayer) ?? CustomSpawner.GetPointAtHalfOfSphere(transform.position, transform.forward, 6.5f); GameObject val2 = SpawnSingleObject(prefab, val + Vector3.up); MathUtility.LookAt(val2.transform, ((Component)currentPlayer).transform); CustomSpawner.ProcessLevel(val2, data.argLevel); if ((Object)(object)prefab2 != (Object)null) { SpawnSingleObject(prefab2, val); } ProcessDropItems(val2, data.isSpawnsHaveDrop); CustomSpawner.ProcessHitPoints(val2, data.argHitsPercent, data.hitpointsModifier); if (data.username != null) { CustomSpawner.ProcessEnemyName(val2, data.username, currentPlayer); } CustomSpawner.ProcessEnemyDamage(val2, new DamageRanges { MaxElementalDamage = data.argMaxElementalDamage, MaxPhysicalDamage = data.argMaxPhysicalDamage, MinElementalDamage = data.argMinElementalDamage, MinPhysicalDamage = data.argMinPhysicalDamage }, data.spawnDamageModifier); } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"SpawnObjects spawn {data.argName} index {data.argCount} error: {arg}"); } } } } public class GiveItemInv : IConsoleCommand { public virtual string Id => "give_item_inv"; public virtual bool Execute(IEnumerable<string> args) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown IEnumerator<string> args2 = args?.GetEnumerator(); string text = CommandsArgsReader.ReadString(args2); int num = CommandsArgsReader.ReadInt(args2, 0); bool flag = CommandsArgsReader.ReadBool(args2, defaultValue: true); if (InteractiveMod.Settings.isAllPlayers) { ZPackage val = new ZPackage(); val.Write(text); val.Write(num); val.Write(flag); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "bft_GiveItemInInv", new object[1] { val }); } else { GiveRandomItem(GameProxy.CurrentPlayer, text, num, flag); } return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { return true; } public static void GiveRandomItem(Player player, string items, int count, bool inv) { //IL_00c9: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ObjectDB.instance == (Object)null) { LoggerFactory.LogWithUI("GiveRandomItem ObjectDB.instance is null"); } string randomItemFromList = UtilityRandom.GetRandomItemFromList<string>((IList<string>)items.Split(new char[1] { '|' })); try { Inventory inventory = ((Humanoid)player).GetInventory(); GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(randomItemFromList); if ((Object)(object)itemPrefab == (Object)null) { LoggerFactory.LogWithUI("GiveRandomItem prefab " + randomItemFromList + " is null"); return; } bool flag = inventory.CanAddItem(itemPrefab, count); if (!flag && inv) { ItemData randomItemFromList2 = UtilityRandom.GetRandomItemFromList<ItemData>((IList<ItemData>)inventory.GetAllItems().ToArray()); ((Humanoid)player).DropItem(inventory, randomItemFromList2, randomItemFromList2.m_stack); LoggerFactory.Logger.LogDebugInfo((object)$"drop {randomItemFromList2}"); inventory.AddItem(itemPrefab, count); } else if (!flag && !inv) { Transform transform = ((Component)player).transform; Vector3 val = transform.position + transform.forward * 3f; CustomSpawner.SpawnSingleObject(itemPrefab, val + Vector3.up); } else { inventory.AddItem(itemPrefab, count); } } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"GiveItem {randomItemFromList} count {count} error: {arg}"); } } } public class ItemsRain : IConsoleCommand { private int maxRange; private float rangePeriod; private int rangeSpawnHeight; private string[] itemsArr; public virtual string Id => "items_rain"; public virtual bool Execute(IEnumerable<string> args) { IEnumerator<string> args2 = args?.GetEnumerator(); int duration = CommandsArgsReader.ReadInt(args2, 60); maxRange = CommandsArgsReader.ReadInt(args2, 30); rangePeriod = CommandsArgsReader.ReadFloat(args2, 1f); string text = CommandsArgsReader.ReadString(args2); rangeSpawnHeight = 13; itemsArr = text.Split(new char[1] { '|' }); StartRain(duration); return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { return true; } protected void SpawnItem(string itemName, Vector3 pos) { //IL_000b: 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) Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab(itemName), pos, Quaternion.identity); } public static Vector3 GetPointOfSphere(Vector3 basePos, int height, float radius) { //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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Random.onUnitSphere * radius; val.y = height; return basePos + val; } protected void SpawnRandomItem(int maxRange, int height) { //IL_0016: 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_0023: 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) try { string randomItemFromList = UtilityRandom.GetRandomItemFromList<string>((IList<string>)itemsArr); Vector3 pointOfSphere = GetPointOfSphere(((Component)GameProxy.CurrentPlayer).transform.position, height, maxRange); SpawnItem(randomItemFromList, pointOfSphere); } catch (Exception arg) { ((ILogger)LoggerFactory.Logger).Log((object)$"Spawn items rain error: {arg}"); } } protected void InitRangeTask(string id, int max, float period, int height) { //IL_002e: 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) //IL_003a: 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_0059: Expected O, but got Unknown if (!GameProxy.ScheduleManager.IsTaskExists(id)) { GameProxy.ScheduleManager.NewPeriodicTask(new PeriodicTaskData { id = id, period = period, periodicAction = delegate { SpawnRandomItem(max, height); } }, false); } } public void StartRain(int duration) { //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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown ((ILogger)LoggerFactory.Logger).Log((object)$"Start rain for {duration}"); InitRangeTask(Id, maxRange, rangePeriod, rangeSpawnHeight); GameProxy.ScheduleManager.AppendTimerTask(new TimerTaskData { id = Id, duration = duration, finishAction = delegate { GameProxy.ScheduleManager.FinishImmediatlyPeriodicTask(Id); ((ILogger)LoggerFactory.Logger).Log((object)"Rain is finished"); } }, false); } } public class RaiseSkill : IConsoleCommand { private readonly string[] skillList = new string[20] { "Swords", "Knives", "Clubs", "Polearms", "Spears", "Blocking", "Axes", "Bows", "ElementalMagic", "BloodMagic", "Unarmed", "Pickaxes", "WoodCutting", "Crossbows", "Jump", "Sneak", "Run", "Swim", "Fishing", "Ride" }; public static RaiseSkill sharedInstance; public virtual string Id => "player_addskill"; public RaiseSkill() { sharedInstance = this; } public virtual bool Execute(IEnumerable<string> args) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown IEnumerator<string> args2 = args?.GetEnumerator(); string text = CommandsArgsReader.ReadString(args2, "random"); int num = CommandsArgsReader.ReadInt(args2, 1); if (InteractiveMod.Settings.isAllPlayers) { ZPackage val = new ZPackage(); val.Write(text); val.Write(num); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "bft_RaiseSkill", new object[1] { val }); } else { SwitchFunc(text, num); } return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { return CommandsValidator.IsValidString(args?.GetEnumerator(), (string name) => skillList.Contains(name)); } public void SwitchFunc(string skillParam, int lvl) { if (!(skillParam == "random")) { if (skillParam == "all") { RaiseAllSkills(lvl); } else { RaiseCurrentSkill(skillParam, lvl); } } else { RaiseRandomSkill(lvl); } } public List<string> GetAvailableSkills() { List<Skill> list = ((Character)GameProxy.CurrentPlayer).GetSkills().GetSkillList(); List<string> list2 = new List<string>(); for (int i = 0; i < list.Count; i++) { string item = ((object)(SkillType)(ref list[i].m_info.m_skill)).ToString(); list2.Add(item); } return list2; } public void RaiseAllSkills(int lvl) { List<string> availableSkills = GetAvailableSkills(); if (availableSkills != null && availableSkills.Count > 0) { foreach (string item in availableSkills) { ((ILogger)LoggerFactory.Logger).Log((object)("RaiseAllSkills skill " + item)); ((Character)GameProxy.CurrentPlayer).GetSkills().CheatRaiseSkill(item, (float)lvl, true); } return; } ((ILogger)LoggerFactory.Logger).Log((object)"RaiseAllSkills skill list is empty raise Run"); ((Character)GameProxy.CurrentPlayer).GetSkills().CheatRaiseSkill("Run", (float)lvl, true); } public void RaiseRandomSkill(int lvl) { List<string> availableSkills = GetAvailableSkills(); if (availableSkills != null && availableSkills.Count > 0) { string randomItemFromList = UtilityRandom.GetRandomItemFromList<string>((IList<string>)availableSkills); ((ILogger)LoggerFactory.Logger).Log((object)("RaiseRandomSkill skill " + randomItemFromList)); ((Character)GameProxy.CurrentPlayer).GetSkills().CheatRaiseSkill(randomItemFromList, (float)lvl, true); } else { ((ILogger)LoggerFactory.Logger).Log((object)"RaiseRandomSkill skill list is empty raise Run"); ((Character)GameProxy.CurrentPlayer).GetSkills().CheatRaiseSkill("Run", (float)lvl, true); } } public void RaiseCurrentSkill(string skill, int lvl) { ((ILogger)LoggerFactory.Logger).Log((object)("Add 1 lvl to skill " + skill)); ((Character)GameProxy.CurrentPlayer).GetSkills().CheatRaiseSkill(skill, (float)lvl, true); } } public class Recall : IConsoleCommand { public static Recall sharedInstance; public virtual string Id => "player_recall"; public Recall() { sharedInstance = this; } public virtual bool Execute(IEnumerable<string> args) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown if (!ZNet.instance.IsServer()) { ZPackage val = new ZPackage(); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "bft_Recall", new object[1] { val }); } else { SendRecall(); } return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { return CommandsValidator.IsZeroArgs(args); } public void SendRecall() { GameProxy.RunGameConsoleCommand("recall"); } } public class RemoveDrops : IConsoleCommand { public static RemoveDrops sharedInstance; public virtual string Id => "items_removedrops"; public RemoveDrops() { sharedInstance = this; } public virtual bool Execute(IEnumerable<string> args) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown if (InteractiveMod.Settings.isAllPlayers) { ZPackage val = new ZPackage(); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "bft_RemoveDrops", new object[1] { val }); } else { RemoveAllDrops(); } return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { return CommandsValidator.IsZeroArgs(args); } public void RemoveAllDrops() { ItemDrop[] array = Object.FindObjectsOfType<ItemDrop>(); foreach (ItemDrop val in array) { Fish component = ((Component)val).gameObject.GetComponent<Fish>(); if ((Object)(object)component == (Object)null || component.IsOutOfWater()) { ZNetView component2 = ((Component)val).GetComponent<ZNetView>(); if ((Object)(object)component2 != (Object)null && component2.IsValid() && component2.IsOwner()) { component2.Destroy(); } } } } } public class SkipTime : IConsoleCommand { public static SkipTime sharedInstance; public virtual string Id => "player_skiptime"; public SkipTime() { sharedInstance = this; } public virtual bool Execute(IEnumerable<string> args) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown if (!ZNet.instance.IsServer()) { ZPackage val = new ZPackage(); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "bft_SkipTime", new object[1] { val }); } else { SkipHalfDay(); } return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { return CommandsValidator.IsZeroArgs(args); } public void SkipHalfDay() { double timeSeconds = ZNet.instance.GetTimeSeconds(); float num = 1020f; timeSeconds += (double)num; ZNet.instance.SetNetTime(timeSeconds); } } public class TestDamageFxEffectSpawner : IConsoleCommand { public virtual string Id => "spawn_damage_fx"; public virtual bool Execute(IEnumerable<string> args) { SpawnFX(CommandsArgsReader.ReadString(args?.GetEnumerator())); return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { return CommandsValidator.IsValidString(args?.GetEnumerator(), (string s) => (Object)(object)ZNetScene.instance != (Object)null && Object.op_Implicit((Object)(object)ZNetScene.instance.GetPrefab(s))); } public static void SpawnFX(string name) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) FxEffectSpawner.SpawnDamageFXAtCharacter((Character)(object)GameProxy.CurrentPlayer, name, new Vector3(0f, 1f, 0f)); } } public class SingleFxEffectSpawner : IConsoleCommand { public virtual string Id => "spawn_single_fx"; public virtual bool Execute(IEnumerable<string> args) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown string text = CommandsArgsReader.ReadString(args?.GetEnumerator()); if (InteractiveMod.Settings.isAllPlayers) { ZPackage val = new ZPackage(); val.Write(text); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "bft_SingleFxEffectSpawner", new object[1] { val }); } else { SpawnFX(GameProxy.CurrentPlayer, text); } return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { return CommandsValidator.IsValidString(args?.GetEnumerator(), (string s) => (Object)(object)ZNetScene.instance != (Object)null && Object.op_Implicit((Object)(object)ZNetScene.instance.GetPrefab(s))); } public static void SpawnFX(Player p, string name) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) FxEffectSpawner.SpawnFXAtCharacter((Character)(object)p, name, new Vector3(0f, 1f, 0f)); } } public class WaterEnemiesSpawner : IConsoleCommandWithData, IConsoleCommand { public virtual string Id => "spawn_in_water"; public virtual bool Execute(IEnumerable<string> args) { return false; } public virtual bool Execute(IEnumerable<string> args, IEventsData data) { IEnumerator<string> enumerator = args?.GetEnumerator(); string name = CommandsArgsReader.ReadString(enumerator); int count = CommandsArgsReader.ReadInt(enumerator, 1); int level = CommandsArgsReader.ReadInt(enumerator, 0); float hitsPercent = CommandsArgsReader.ReadFloat(enumerator, 1f); DamageRanges damageRanges = new DamageRanges(); damageRanges.ReadFromArgs(enumerator); bool isSpawnsHaveDrop = InteractiveMod.Settings.isSpawnsHaveDrop; if (InteractiveMod.Settings.isAllPlayers) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "bft_CustomSpawnerWater", new object[1] { CustomSpawner.GenerateSpawnPackage(name, count, level, hitsPercent, isSpawnsHaveDrop, damageRanges, data) }); } else { SpawnObjectsInWater(name, count, level, hitsPercent, damageRanges, isSpawnsHaveDrop, data); } return true; } public bool IsValidCommandArgs(IEnumerable<string> args) { return CustomSpawner.IsValidSpawnCommandArgs(args); } public static Vector3 GetPointAtWater(Vector3 basePos, Vector3 forward, int range) { //IL_0007: 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_00aa: 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_00b5: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_0036: 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_0051: Unknown result type (might be due to invalid IL or missing references) List<Vector3> list = new List<Vector3>(); for (int i = -range; i <= range; i += 2) { for (int j = -range; j <= range; j += 2) { Vector3 val = basePos + new Vector3((float)i, 0f, (float)j); if (ZoneSystem.instance.GetSolidHeight(val) < ZoneSystem.instance.m_waterLevel) { list.Add(val); } } } list.Sort((Vector3 x, Vector3 y) => (int)(Vector3.Distance(basePos, x) - Vector3.Distance(basePos, y))); if (list.Count > 0) { ((ILogger)LoggerFactory.Logger).Log((object)$"found water {list.Count} cells"); return UtilityRandom.GetRandomItemFromList<Vector3>((IList<Vector3>)list); } return CustomSpawner.GetPointAtHalfOfSphere(basePos, forward, 5f); } public static void SpawnObjectsInWater(string name, int count, int level, float hitsPercent, DamageRanges damage, bool enableDrop, IEventsData data, string fxSpawnName = "vfx_spawn_small") { //IL_0078: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to
plugins/ChaosTricks/ModHelper.dll
Decompiled 2 years agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using EventsIO; using EventsIO.Interfaces; using ModHelper.Interfaces; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ModHelper")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("BFT")] [assembly: AssemblyProduct("ModHelper")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("8d858f35-342c-4916-8e50-2b2cfd18640d")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.0.0")] namespace ModHelper { public class CommandArgsValidator { private readonly ILogger logger; public CommandArgsValidator(ILogger logger) { this.logger = logger; } public bool IsZeroArgs(IEnumerable<string> args) { int num = args?.Count() ?? 0; if (num != 0) { logger?.LogWarning($"CommandArgsValidator wrong args count {num} (must be 0)"); return false; } return true; } public bool IsZeroArgs(IEnumerator<string> args) { if (args == null || !args.MoveNext()) { return true; } logger?.LogWarning("CommandArgsValidator wrong args count (more than needed)"); return false; } private bool IsInvalidArgsCount(IEnumerator<string> args) { if (args == null || !args.MoveNext()) { return true; } return false; } 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 period; internal float periodCalculated; public int triggerTimes; public bool isInfiniteRepeates = true; public Action periodicAction; public Action finishAction; public override string ToString() { return "id=" + id + ", " + $"period={period}s, " + $"calc_period={periodCalculated}s, " + $"triggerTimes={triggerTimes}, " + $"isInfiniteRepeates={isInfiniteRepeates}"; } } public class TimerTaskData { public string id; public float duration; public Action finishAction; public override string ToString() { return $"id={id}, duration={duration}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) { Queue<string> obj = queue; if (obj == null || obj.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; Queue<string> obj = queue; if (obj != null && obj.Count > 0) { Flush(); } } } public void Dispose() { Dispose(isDisposing: true); GC.SuppressFinalize(this); } ~BufferedLogger() { Dispose(isDisposing: false); } } public static class HelperGroups { public static Dictionary<string, List<string>> GenerateNewEmptyGroupsDict() { return new Dictionary<string, List<string>>(StringComparer.InvariantCultureIgnoreCase); } private static bool SafeApplyValidator(Func<string, bool> groupItemValidator, string itemName, ILogger logger = null) { try { return groupItemValidator?.Invoke(itemName) ?? true; } catch (Exception arg) { logger?.LogError($"RandomGroup.SafeApplyValidator unexpected error: {arg}"); } return false; } public static void InitGroupsFromFiles(string dataDir, Dictionary<string, List<string>> groups, string groupsPrefix, Func<string, bool> groupItemValidator = null, IDebugLogger logger = null) { try { if (string.IsNullOrEmpty(groupsPrefix)) { logger?.LogError("RandomGroup error: wrong groupsPrefix " + groupsPrefix); return; } string[] files = Directory.GetFiles(dataDir); foreach (string path in files) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path); if (fileNameWithoutExtension.StartsWith(groupsPrefix)) { groups[fileNameWithoutExtension] = GetItemsFromFile(path, logger); } } foreach (KeyValuePair<string, List<string>> group in groups) { logger?.LogDebugInfo("RandomGroup validate list " + group.Key + ":"); List<string> list = new List<string>(); foreach (string item in group.Value) { if (!SafeApplyValidator(groupItemValidator, item, logger)) { logger?.LogWarning("invalid name " + item); list.Add(item); } } if (list.Count > 0) { foreach (string item2 in list) { group.Value.Remove(item2); } logger?.LogWarning("list " + group.Key + " is invalid"); } else { logger?.LogDebugInfo("list " + group.Key + " is valid"); } } } catch (Exception arg) { logger?.LogError($"RandomGroup.InitGroupsFromFiles unexpected error: {arg}"); } } public static Dictionary<string, List<string>> GenerateGroupsFromFiles(string dataDir, string groupsPrefix, Func<string, bool> groupItemValidator = null, IDebugLogger logger = null) { Dictionary<string, List<string>> dictionary = GenerateNewEmptyGroupsDict(); InitGroupsFromFiles(dataDir, dictionary, groupsPrefix, groupItemValidator, logger); return dictionary; } public static List<string> GetItemsFromFile(string path, IDebugLogger logger = null) { try { List<string> list = new HelperJson(logger).FromFile<List<string>>(path); if (list == null) { list = new List<string>(); } logger?.LogInfo($"Items from file {path}: found {list.Count}"); foreach (string item in list) { logger?.LogDebugInfo("value " + item); } return list; } catch (Exception arg) { logger?.LogError($"HelperGroups.GetItemsFromFile unexpected error: {arg}"); } return new List<string>(); } public static bool IsValidGroupName(Dictionary<string, List<string>> dict, string name) { return dict?.ContainsKey(name) ?? false; } public static void PrintGroups(Dictionary<string, List<string>> dict, ILogger logger, string groupsName = "default_name") { if (logger == null) { return; } if (dict == null || dict.Count == 0) { logger?.LogWarning("No groups found for " + groupsName); return; } logger?.LogInfo("---------------Groups " + groupsName + " list---------------"); foreach (KeyValuePair<string, List<string>> item in dict) { logger?.LogInfo(item.Key ?? ""); } logger?.LogInfo("---------------Groups " + groupsName + " list end---------------"); } } public class HelperJson : IJsonUtil { private class ContainerObjAndInt { public object valueObj; public int valueInt; } private class ContainerStringAndInt { public string valueString; public int valueInt; } private ILogger logger; private const char startClass = '{'; private const char endClass = '}'; private const char startArray = '['; private const char endArray = ']'; private const char isHasNextField = ','; private const char special = '\\'; private const char startString = '"'; private const char nameValueSeparator = ':'; private char[] ignoreChars = new char[9] { ' ', '\n', '\r', '\t', '\b', '\f', '\0', '{', '[' }; private string logMsgBaseError = "HelperJson error:"; private string logMsgBase = "HelperJson:"; private bool isVerboseDebugLog; private void VerboseDebugLog(string s) { if (isVerboseDebugLog) { logger?.LogInfo("[DEBUG] " + s); } } public HelperJson(IDebugLogger logger = null, bool isVerboseDebugLog = false) { this.logger = logger; this.isVerboseDebugLog = isVerboseDebugLog; } public T FromFile<T>(string path) where T : class { string s; using (StreamReader streamReader = new StreamReader(path)) { s = streamReader.ReadToEnd(); } return FromString<T>(s); } public T FromString<T>(string s) where T : class { return GetFromString(typeof(T), s, 0).valueObj as T; } private char GetSpecialChar(char c) { _ = 34; 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.GetElementType() : resultType.GetGenericArguments()[0]); return ParseIListByItemType(itemType, s, index); } private ContainerObjAndInt ParseArray(Type resultType, string s, int index) { Type elementType = resultType.GetElementType(); ContainerObjAndInt containerObjAndInt = ParseIListByItemType(elementType, s, index); Array array; if (containerObjAndInt.valueObj is IList list) { array = Array.CreateInstance(elementType, list.Count); for (int i = 0; i < array.Length; i++) { array.SetValue(list[i], i); } } else { logger?.Log(logMsgBaseError + " create empty Array"); array = Array.CreateInstance(elementType, 0); } return new ContainerObjAndInt { valueObj = array, valueInt = containerObjAndInt.valueInt }; } private ContainerObjAndInt ParseIDictionary(Type dictType, string s, int index) { Type[] genericArguments = dictType.GetGenericArguments(); if (genericArguments.Length != 2) { logger?.Log(logMsgBaseError + " can't create IDictionary, invalid args"); } if (dictType.IsGenericType) { if (!dictType.IsGenericTypeDefinition) { dictType = dictType.GetGenericTypeDefinition(); } dictType = dictType.MakeGenericType(genericArguments); } if (!(Activator.CreateInstance(dictType) is IDictionary dictionary)) { string name = dictType.GetType().Name; logger?.Log(logMsgBaseError + " can't create IDictionary " + name + " for item type " + genericArguments[0].Name + ", " + genericArguments[1].Name); return new ContainerObjAndInt { valueObj = null, valueInt = s.Length }; } Type valueType = genericArguments[0]; Type valueType2 = genericArguments[1]; do { ContainerObjAndInt nextValue = GetNextValue(valueType, s, index, isSkipSep: false); index = nextValue.valueInt; ContainerObjAndInt nextValue2 = GetNextValue(valueType2, s, index, isSkipSep: true); index = nextValue2.valueInt; dictionary.Add(nextValue.valueObj, nextValue2.valueObj); VerboseDebugLog($"{logMsgBase} dict add key {nextValue.valueObj}"); index = SkipIgnoredChars(s, index, isSkipHasNextField: true, isSkipSep: true); } while (index < s.Length && s[index] != '}' && s[index] != ']'); return new ContainerObjAndInt { valueObj = dictionary, valueInt = index + 1 }; } private bool IsTypeOf(Type targetType, Type sourceType, int argsCount) { if (sourceType.IsAssignableFrom(targetType)) { VerboseDebugLog(logMsgBase + " is " + targetType.Name); return true; } Type[] types = sourceType.Assembly.GetTypes(); foreach (Type type in types) { if (!type.IsClass) { continue; } Type[] interfaces = type.GetInterfaces(); foreach (Type type2 in interfaces) { if (type2.IsGenericType && (object)type2.GetGenericTypeDefinition() == targetType && sourceType.GetGenericArguments().Length == argsCount) { VerboseDebugLog(logMsgBase + " is " + targetType.Name + " assembly interface"); return true; } } } return false; } private ContainerObjAndInt GetFromString(Type resultType, string s, int index) { try { VerboseDebugLog(logMsgBase + " GetFromString"); if (resultType.IsArray) { VerboseDebugLog(logMsgBase + " is array"); return ParseArray(resultType, s, index); } if (resultType.IsAssignableFrom(typeof(IList)) || IsTypeOf(typeof(IList<>), resultType, 1)) { return ParseIList(resultType, s, index); } if (resultType.IsAssignableFrom(typeof(IDictionary)) || IsTypeOf(typeof(IDictionary<, >), resultType, 2)) { return ParseIDictionary(resultType, s, index); } if (resultType.IsGenericType && !resultType.IsGenericTypeDefinition) { Type[] genericArguments = resultType.GetGenericArguments(); resultType = resultType.GetGenericTypeDefinition(); resultType = resultType.MakeGenericType(genericArguments); } object obj = Activator.CreateInstance(resultType); int num = index; while (num < s.Length && s[num] != ']' && s[num] != '}') { ContainerStringAndInt nextFieldName = GetNextFieldName(s, num); string valueString = nextFieldName.valueString; if (string.IsNullOrEmpty(valueString?.Trim())) { VerboseDebugLog(logMsgBase + " IsNullOrWhiteSpace field " + valueString + ", class type " + resultType.Name); num = GetNextValue(typeof(string), s, num, isSkipSep: true).valueInt; continue; } num = nextFieldName.valueInt; FieldInfo field = resultType.GetField(valueString); VerboseDebugLog(logMsgBase + " field " + valueString + ", class type " + resultType.Name); if (isVerboseDebugLog) { FieldInfo[] fields = resultType.GetFields(); VerboseDebugLog(logMsgBase + " fields in class: "); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { VerboseDebugLog(fieldInfo.Name); } } if ((object)field == null) { logger?.LogWarning(logMsgBaseError + " can't find field " + valueString + " for type " + resultType.Name + ". Try to skip."); num = GetNextValue(typeof(string), s, num, isSkipSep: true).valueInt; } else { ContainerObjAndInt nextValue = GetNextValue(field.FieldType, s, num, isSkipSep: true); object valueObj = nextValue.valueObj; num = nextValue.valueInt; SetFieldClass(obj, valueString, valueObj); } } num = SkipIgnoredChars(s, num + 1, isSkipHasNextField: true, isSkipSep: true); return new ContainerObjAndInt { valueObj = obj, valueInt = num }; } catch (Exception arg) { logger?.LogError($"{logMsgBaseError} {arg}"); } return new ContainerObjAndInt { valueObj = null, valueInt = s.Length }; } } public class HelperDebugLog : HelperLog, IDebugLogger, ILoggerWithConsole, ILogger { protected bool isDebug; public HelperDebugLog(string folderPath = null, string logFileName = null, bool isDebug = false) : base(folderPath, logFileName) { this.isDebug = isDebug; } public virtual void LogDebugInfo(object obj) { if (isDebug) { LogInfo($"[DEBUG] {obj}"); } } public virtual void LogDebugWarning(object obj) { if (isDebug) { LogWarning($"[DEBUG] {obj}"); } } public virtual void LogDebugError(object obj) { if (isDebug) { LogError($"[DEBUG] {obj}"); } } } public class ScheduleManager { protected ILogger logger; protected Dictionary<string, TimerTaskData> timerTasks = new Dictionary<string, TimerTaskData>(); protected Dictionary<string, PeriodicTaskData> periodicTasks = new Dictionary<string, PeriodicTaskData>(); protected List<TimerTaskData> timerTasksNoId = new List<TimerTaskData>(); protected List<PeriodicTaskData> periodicTasksNoId = new List<PeriodicTaskData>(); protected int onUpdateErrorLimit = 10; public ScheduleManager(ILogger logger = null) { this.logger = logger; } 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.periodCalculated = task.period; 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.duration += timerTaskData.duration; 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 dt) { List<TimerTaskData> list2 = new List<TimerTaskData>(); foreach (TimerTaskData item in list) { item.duration -= dt; if (item.duration <= 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 dt) { List<PeriodicTaskData> list2 = new List<PeriodicTaskData>(); foreach (PeriodicTaskData item in list) { item.periodCalculated -= dt; if (!(item.periodCalculated <= 0f)) { continue; } if (item.isInfiniteRepeates || item.triggerTimes > 0) { SafeRunAction(item.periodicAction); item.periodCalculated = item.period; 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 dt) { try { foreach (TimerTaskData item in ProcessTimersList(timerTasks.Values, dt)) { timerTasks.Remove(item.id); logger?.LogInfo($"ScheduleManager OnUpdate finished timer task {item}"); } foreach (PeriodicTaskData item2 in ProcessPeriodicList(periodicTasks.Values, dt)) { periodicTasks.Remove(item2.id); logger?.LogInfo($"ScheduleManager OnUpdate finished periodic task {item2}"); } foreach (TimerTaskData item3 in ProcessTimersList(timerTasksNoId, dt)) { timerTasksNoId.Remove(item3); logger?.LogInfo($"ScheduleManager OnUpdate finished timer no id task {item3}"); } foreach (PeriodicTaskData item4 in ProcessPeriodicList(periodicTasksNoId, dt)) { 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 void FinishImmediatlyPeriodicTask(string id) { if (periodicTasks.ContainsKey(id)) { SafeRunAction(periodicTasks[id].finishAction); periodicTasks.Remove(id); logger?.LogInfo("ScheduleManager finish and remove periodic task " + id); } } public void FinishAllImmediatly(string id) { FinishImmediatlyTimerTask(id); FinishImmediatlyPeriodicTask(id); } public void FinishAllImmediatly() { foreach (TimerTaskData value in timerTasks.Values) { SafeRunAction(value.finishAction); } foreach (PeriodicTaskData value2 in periodicTasks.Values) { SafeRunAction(value2.finishAction); } foreach (TimerTaskData item in timerTasksNoId) { SafeRunAction(item.finishAction); } foreach (PeriodicTaskData item2 in periodicTasksNoId) { SafeRunAction(item2.finishAction); } RemoveAllTasks(); } protected void SafeRunAction(Action action) { if (action == null) { return; } try { action(); } catch (Exception arg) { logger?.LogError($"SafeRunAction error: {arg}"); } } } public class UtilityConsole { private readonly Dictionary<string, IConsoleCommand> consoleCommandsDict; private readonly IDebugLogger logger; private readonly List<string> ignoreValidationCommands; public bool isLogCheckCommand = true; public bool isLogCheckCommandParameters = true; public int logCheckCommandParametersMaxLength = 40; public bool isLogProcessCommand = true; public bool isLogProcessCommandParameters = true; public int logProcessCommandParametersMaxLength = 40; public UtilityConsole(IDebugLogger logger = null, List<string> ignoreValidationCommands = null) { consoleCommandsDict = new Dictionary<string, IConsoleCommand>(); this.logger = logger; this.ignoreValidationCommands = ignoreValidationCommands; } public void RegisterCommand(IConsoleCommand command) { if (string.IsNullOrEmpty(command?.Id)) { logger?.LogWarning("UtilityConsole.RegisterCommand: invalid console command"); } else { consoleCommandsDict[command.Id] = command; } } public static string[] ParseCommandLine(string commandLine) { return commandLine.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); } public static string[] ParseArgs(string command) { return command.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); } private string GetCmdName(string cmd) { string[] array = cmd.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { return ""; } return array[0]; } private void LogCommand(string funcPrefix, string cmd, bool isLog, bool isLogParams, int maxLen) { if (logger == null || !isLog) { return; } if (string.IsNullOrEmpty(cmd)) { logger.LogWarning(funcPrefix + " null or empty"); } else if (isLogParams) { if (cmd.Length > maxLen) { string text = cmd.Substring(0, maxLen); logger.Log(funcPrefix + " " + text + "..."); } else { logger.Log(funcPrefix + " " + cmd); } } else { logger.Log(funcPrefix + " " + GetCmdName(cmd)); } } public bool IsValidCommandLine(string commandLine) { try { if (string.IsNullOrEmpty(commandLine)) { logger?.LogDebugError("UtilityConsole.IsValidCommandLine: invalid command line"); return false; } string[] array = ParseCommandLine(commandLine); if (array == null || array.Length < 1) { logger?.LogDebugError("UtilityConsole.IsValidCommandLine: invalid commands count"); return false; } bool flag = true; string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string text = array2[i]?.Trim(); LogCommand("UtilityConsole.IsValidCommandLine: check command", text, isLogCheckCommand, isLogCheckCommandParameters, logCheckCommandParametersMaxLength); string[] array3 = ParseArgs(text); if (array3 == null || array3.Length < 1) { logger?.LogDebugError("UtilityConsole.IsValidCommandLine: invalid commands count"); flag = false; continue; } string text2 = array3[0]; List<string> list = ignoreValidationCommands; if (list != null && list.Contains(text2)) { logger?.LogDebugInfo("UtilityConsole.IsValidCommandLine: validation is ignored for this command"); } else if (consoleCommandsDict.ContainsKey(text2)) { bool flag2 = consoleCommandsDict[text2].IsValidCommandArgs(array3.Skip(1)); if (!flag2) { logger?.LogDebugError("UtilityConsole.IsValidCommandLine: command with id " + text2 + " is invalid"); } flag = flag && flag2; } else { logger?.LogDebugError("UtilityConsole.IsValidCommandLine: can't find custom command with id " + text2); flag = false; } } return flag; } catch (Exception arg) { logger?.LogDebugError(string.Format("{0} error: {1}", "UtilityConsole.IsValidCommandLine:", arg)); return false; } } public bool RunCommand(string commandLine, IEventsData data, Action<string> onCustomCommandNotFound = null) { try { string[] array = ParseCommandLine(commandLine); foreach (string text in array) { LogCommand("UtilityConsole.RunCommand: process command", text, isLogProcessCommand, isLogProcessCommandParameters, logProcessCommandParametersMaxLength); string[] array2 = ParseArgs(text); string key = array2[0]; if (consoleCommandsDict.ContainsKey(key)) { try { if (consoleCommandsDict[key] is IConsoleCommandWithData consoleCommandWithData) { consoleCommandWithData.Execute(array2.Skip(1), data); } else { consoleCommandsDict[key].Execute(array2.Skip(1)); } } catch (Exception arg) { logger?.LogError(string.Format("{0} execute command error {1}", "UtilityConsole.RunCommand:", arg)); } } else if (onCustomCommandNotFound != null) { onCustomCommandNotFound(text); } else { logger?.LogError("UtilityConsole.RunCommand: execute command not found error"); } } } catch (Exception arg2) { logger?.LogError(string.Format("{0} error {1}", "UtilityConsole.RunCommand:", arg2)); return false; } return true; } } public class CommandArgsReader { private readonly ILogger logger; public CommandArgsReader(ILogger logger) { this.logger = logger; } public int ReadInt(IEnumerator<string> args, int defaultValue = 0) { if (args == null || !args.MoveNext()) { return defaultValue; } try { return int.Parse(args.Current); } catch (Exception arg) { logger?.LogWarning($"CommandArgsReader: {arg}"); return defaultValue; } } public float ReadFloat(IEnumerator<string> args, float defaultValue = 0f) { if (args == null || !args.MoveNext()) { return defaultValue; } try { return float.Parse(args.Current, CultureInfo.InvariantCulture.NumberFormat); } catch (Exception arg) { logger?.LogWarning($"CommandArgsReader: {arg}"); return defaultValue; } } public string ReadString(IEnumerator<string> args, string defaultValue = "") { if (args == null || !args.MoveNext()) { return defaultValue; } return args.Current; } public bool ReadBool(IEnumerator<string> args, bool defaultValue = false) { if (args == null || !args.MoveNext()) { return defaultValue; } try { return bool.Parse(args.Current.ToLower()); } catch (Exception arg) { logger?.LogWarning($"CommandArgsReader: {arg}"); return defaultValue; } } } public static class UtilityRandom { private static readonly Random rnd = new Random(DateTime.Now.Millisecond); public static T GetRandomItemFromList<T>(IList<T> list) { if (list == null || list.Count <= 0) { return default(T); } return list[rnd.Next(list.Count)]; } } public class HelperCommandManagerFormatted : ICommandManager { private Dictionary<string, string> commandsDict; private readonly IDebugLogger logger; private readonly string errorString = string.Empty; public int logCommandMaxLength = 50; public bool isUseLogCommandLimit = true; public HelperCommandManagerFormatted(IDebugLogger logger) { this.logger = logger; } public virtual void InitFromFile(string path) { try { Dictionary<string, string> dictionary = UtilityJson.Generate(logger).FromFile<Dictionary<string, string>>(path); commandsDict = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase); CheckLoadedDict(); } catch (Exception arg) { logger?.LogError($"HelperCommandManagerFormatted InitFromFile load: {arg}"); commandsDict = null; } } public virtual void InitFromString(string data) { try { Dictionary<string, string> dictionary = UtilityJson.Generate(logger).FromString<Dictionary<string, string>>(data); commandsDict = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase); CheckLoadedDict(); } catch (Exception arg) { logger?.LogError($"HelperCommandManagerFormatted InitFromString load: {arg}"); commandsDict = null; } } protected virtual void CheckLoadedDict() { if (commandsDict == null) { logger?.LogWarning("HelperCommandManagerFormatted: commandsDict null"); return; } logger?.LogInfo($"HelperCommandManagerFormatted: found commands {commandsDict.Count}"); foreach (KeyValuePair<string, string> item in commandsDict) { logger?.LogDebugInfo("command: key=" + item.Key + ", value=" + GetSubstringCmd(item.Value)); } } protected virtual string GetSubstringCmd(string cmd) { if (!isUseLogCommandLimit || cmd == null) { return cmd; } if (cmd.Length <= logCommandMaxLength) { return cmd; } return cmd.Substring(0, logCommandMaxLength) + "..."; } public virtual string GetCommandData(string eventKey, bool isLogError = false) { if (commandsDict == null) { logger?.LogWarning("HelperCommandManagerFormatted GetCommandData: commandsDict null"); return ""; } try { eventKey = eventKey.Trim(); return commandsDict[eventKey] ?? 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(); return commandsDict[eventKey] ?? 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 eventsDict.Values; } return new List<CustomEvent>(); } public CustomEvent GetEvent(string eventID, bool isLogError = false) { try { eventID = eventID.Trim(); return eventsDict[eventID] ?? throw new NullReferenceException(); } catch (Exception arg) { if (isLogError) { logger?.LogError($"HelperCommandManager key {eventID}: {arg}"); } return null; } } } public class HelperLanguagesFormatted : ITranslation { protected Dictionary<string, Text> transDict; protected readonly IDebugLogger logger; protected readonly string errorString = "trans_error"; public bool isLogOnlyEnItems; public bool isSuppressLogItems = true; public HelperLanguagesFormatted(IDebugLogger logger) { this.logger = logger; } public virtual void InitFromFile(string path) { try { Dictionary<string, Text> dictionary = UtilityJson.Generate(logger).FromFile<Dictionary<string, Text>>(path); transDict = new Dictionary<string, Text>(dictionary, StringComparer.OrdinalIgnoreCase); CheckLoadedDict(); } catch (Exception arg) { logger?.LogError($"HelperLanguagesFormatted InitFromFile load: {arg}"); transDict = null; } } public virtual void InitFromString(string data) { try { Dictionary<string, Text> dictionary = UtilityJson.Generate(logger).FromString<Dictionary<string, Text>>(data); transDict = new Dictionary<string, Text>(dictionary, StringComparer.OrdinalIgnoreCase); CheckLoadedDict(); } catch (Exception arg) { logger?.LogError($"HelperLanguagesFormatted InitFromString load: {arg}"); transDict = null; } } protected virtual void CheckLoadedDict() { if (transDict == null) { logger?.LogWarning("HelperLanguagesFormatted: transDict null"); return; } logger?.LogInfo($"HelperLanguagesFormatted: found translates {transDict.Count}"); if (isSuppressLogItems || logger == null) { return; } foreach (KeyValuePair<string, Text> item in transDict) { if (isLogOnlyEnItems) { logger.LogDebugInfo("key=" + item.Key + ", en=" + item.Value.en); continue; } logger.LogDebugInfo("key=" + item.Key + ", ru=" + item.Value.ru + ", en=" + item.Value.en); } } public virtual string GetTrans(string key, Languages lang) { return GetTrans(key, lang.ToString()); } public virtual string GetTrans(string key, string lang) { if (transDict == null) { logger?.LogWarning("HelperLanguagesFormatted transDict is null"); return errorString; } try { key = key.Trim(); lang = lang.Trim(); return transDict[key].GetTrans(lang); } catch (Exception arg) { logger?.LogError($"HelperLanguagesFormatted key {key} lang {lang}, error: {arg}"); return errorString; } } } public class HelperLog : ILoggerWithConsole, ILogger { protected readonly string path; protected const string baseLogName = "interactive_mod_log.txt"; public bool isLogConsole = true; public bool isLogFile = true; public ConsoleColor infoColor = ConsoleColor.White; public ConsoleColor warningColor = ConsoleColor.Yellow; public ConsoleColor errorColor = ConsoleColor.Red; protected virtual string LogTime => DateTime.Now.ToString("h:mm:ss:fff"); public HelperLog(string logDir) : this(logDir, "interactive_mod_log.txt") { } public HelperLog(string logDir, string logFname) { if (logDir == "" || Directory.Exists(logDir)) { path = Path.Combine(logDir, logFname); } } protected virtual void WriteToFile(string s) { if (path != null) { using (StreamWriter streamWriter = new StreamWriter(path, append: true, Encoding.UTF8)) { streamWriter.WriteLine(s); } } } public virtual void Log(object obj) { if (isLogFile) { WriteToFile($"{LogTime} {obj}"); } } public virtual void LogConsole(string text, string prefix, ConsoleColor prefixColor) { Console.ForegroundColor = prefixColor; Console.Write(LogTime + " " + prefix + " "); Console.ResetColor(); Console.WriteLine(text); } protected virtual void LogWithConsole(object obj, string prefix, ConsoleColor color) { Log($"{prefix} {obj}"); if (isLogConsole) { LogConsole(obj.ToString(), prefix, color); } } public virtual void LogInfo(object obj) { LogWithConsole(obj, "[INFO]", infoColor); } public virtual void LogWarning(object obj) { LogWithConsole(obj, "[WARNING]", warningColor); } public virtual void LogError(object obj) { LogWithConsole(obj, "[ERROR]", errorColor); } public virtual void LogInfoConsoleOnly(object obj) { if (isLogConsole) { LogConsole(obj.ToString(), "[INFO]", infoColor); } } public virtual void LogWarningConsoleOnly(object obj) { if (isLogConsole) { LogConsole(obj.ToString(), "[WARNING]", warningColor); } } public virtual void LogErrorConsoleOnly(object obj) { if (isLogConsole) { LogConsole(obj.ToString(), "[ERROR]", errorColor); } } public virtual void LogInfoFileOnly(object obj) { Log($"[INFO] {obj}"); } public virtual void LogWarningFileOnly(object obj) { Log($"[WARNING] {obj}"); } public virtual void LogErrorFileOnly(object obj) { Log($"[ERROR] {obj}"); } public virtual void LogClear() { if (path != null) { using (new StreamWriter(path)) { } } } } public class HelperParse : IParseManager { private readonly ILogger logger; public HelperParse(ILogger logger = null) { this.logger = logger; } public Type GetEnumUnderlyingType(Type type) { if (!type.IsEnum) { return type; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (fields == null || fields.Length < 1) { return type; } return fields[0].FieldType; } public bool TryParseEnum<TEnum>(string arg, out TEnum result, TEnum defaultValue = default(TEnum)) { Type typeFromHandle = typeof(TEnum); try { Type enumUnderlyingType = GetEnumUnderlyingType(typeFromHandle); if ((object)enumUnderlyingType == typeof(int)) { if (int.TryParse(arg, out var result2) && Enum.IsDefined(typeFromHandle, result2)) { result = (TEnum)Enum.ToObject(typeFromHandle, result2); return true; } logger?.LogWarning("TryParseEnum can't parse int from " + arg + " for enum " + typeFromHandle.Name); } else if ((object)enumUnderlyingType == typeof(sbyte)) { if (sbyte.TryParse(arg, out var result3) && Enum.IsDefined(typeFromHandle, result3)) { result = (TEnum)Enum.ToObject(typeFromHandle, result3); return true; } logger?.LogWarning("TryParseEnum can't parse sbyte from " + arg + " for enum " + typeFromHandle.Name); } else { foreach (TEnum value in Enum.GetValues(typeFromHandle)) { if (Enum.GetName(typeFromHandle, value).Equals(arg, StringComparison.OrdinalIgnoreCase)) { result = value; return true; } } logger?.LogWarning("TryParseEnum can't find item by direct name " + arg + " for enum " + typeFromHandle.Name); } } catch (Exception arg2) { logger?.LogError($"TryParseEnum error happened when process {arg} for enum {typeFromHandle.Name}: {arg2}"); } result = defaultValue; return false; } public bool TryParseBool(string arg, out bool result, bool defaultValue = false) { if (bool.TryParse(arg, out result)) { return true; } if (int.TryParse(arg, out var result2)) { result = result2 != 0; return true; } logger?.LogWarning($"TryParseBool error happened when process {arg}. Will be used default {defaultValue}"); result = defaultValue; return false; } } public class UtilityJson { private static Func<IJsonUtil> customGenerator; public static IJsonUtil Generate(IDebugLogger logger) { if (customGenerator == null) { return new HelperJson(logger, File.Exists(".mod_json_debug")); } return customGenerator(); } public static void RegisterCustomGenerator(Func<IJsonUtil> generator) { customGenerator = generator; } } public class UtilitySettings { public static string CommandUpdateSettingsID => "command_update_parameters"; public static string BaseFolder { get; set; } = "ChaosTricks_InteractiveModData"; public static string SettingsFileName => "settings.txt"; public static string SettingsPath => Path.Combine(BaseFolder, SettingsFileName); public static T LoadSettings<T>(IDebugLogger logger) where T : class { string text = string.Empty; try { text = SettingsPath; T result = UtilityJson.Generate(logger).FromFile<T>(text); logger?.LogInfo("settings loaded"); return result; } catch (FileNotFoundException) { logger?.LogWarning("can't load settings. File not found at " + text + ". Using standard."); } catch (Exception arg) { logger?.LogError($"can't load settings. Using standard. \n{arg}"); } T result2 = null; try { result2 = Activator.CreateInstance<T>(); return result2; } catch (Exception arg2) { logger?.LogError($"can't create default data class. \n{arg2}"); } return result2; } } public enum Languages { ru, en } public class Text { public string ru; public string en; public Text(string ru, string en) { this.ru = ru; this.en = en; } public Text() { } public string GetTrans(Languages lang) { if (lang != Languages.en) { return ru; } return en; } public string GetTrans(string lang) { if (GetLangFromAppLang(lang) != Languages.en) { return ru; } return en; } private Languages GetLangFromAppLang(string lang) { lang = lang?.Trim()?.ToLower(); switch (lang) { case "ru": case "russian": case "rus": case "русский": case "ру": case "рус": return Languages.ru; default: return Languages.en; } } } public class HelperLanguages : ITranslation { private readonly Dictionary<string, Text> transDict; private readonly ILogger logger; private readonly string errorString = "trans_error"; public HelperLanguages(ILogger logger, string langsDir, string langsFname = "langs.data") { this.logger = logger; try { string path = Path.Combine(langsDir, langsFname); IDictManager dictManager = new HelperDictManager(logger); using (StreamReader streamReader = new StreamReader(path)) { string data = streamReader.ReadToEnd(); Dictionary<string, string> source = dictManager.ParseDict(data); transDict = GetTransDict(source); } logger?.LogInfo($"HelperLanguages: found translates {transDict.Count}"); } catch (Exception arg) { logger?.LogError($"HelperLanguages load: {arg}"); transDict = new Dictionary<string, Text>(StringComparer.OrdinalIgnoreCase); } } protected Dictionary<string, Text> GetTransDict(Dictionary<string, string> source) { Dictionary<string, Text> dictionary = new Dictionary<string, Text>(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair<string, string> item in source) { string[] array = item.Value.Split(new string[1] { "%lang%" }, StringSplitOptions.RemoveEmptyEntries); if (array == null || array.Length != 2) { logger?.LogError("HelperLanguages parse item: " + item.Key); continue; } string ru = array[0]; string en = array[1]; dictionary.Add(item.Key, new Text(ru, en)); } return dictionary; } public string GetTrans(string key, Languages lang) { return GetTrans(key, lang.ToString()); } public string GetTrans(string key, string lang) { try { key = key.Trim(); lang = lang.Trim(); return transDict[key].GetTrans(lang); } catch (Exception arg) { logger?.LogError($"HelperLanguages key {key} lang {lang}: {arg}"); return errorString; } } public virtual void InitFromFile(string path) { throw new NotImplementedException(); } public void InitFromString(string data) { throw new NotImplementedException(); } } } namespace ModHelper.Interfaces { public interface ICommandTargets { bool IsAllPlayers { get; } } public interface IConsoleCommandWithData : IConsoleCommand { bool Execute(IEnumerable<string> args, IEventsData data); } public interface IConsoleCommand { string Id { get; } bool Execute(IEnumerable<string> args); bool IsValidCommandArgs(IEnumerable<string> args); } public interface IDebugLogger : ILoggerWithConsole, ILogger { void LogDebugInfo(object obj); void LogDebugWarning(object obj); void LogDebugError(object obj); } public interface ILoggerWithConsole : ILogger { void LogInfoConsoleOnly(object obj); void LogWarningConsoleOnly(object obj); void LogErrorConsoleOnly(object obj); void LogInfoFileOnly(object obj); void LogWarningFileOnly(object obj); void LogErrorFileOnly(object obj); } public interface ICommandNotify { string ProcessMsg(string msg); } public interface ICommand { string Id { get; } } public interface IDictionaryItem<T> { string Key { get; } T Value { get; } } public interface IJsonUtil { T FromFile<T>(string path) where T : class; T FromString<T>(string s) where T : class; } public interface IDictManager { Dictionary<string, string> ParseDict(string data); } public interface ICommandManager { string GetCommandData(string eventKey, bool isLogError = false); string[] GetCommands(); void InitFromString(string data); void InitFromFile(string path); } public interface IEventManager<CustomEvent> { CustomEvent GetEvent(string eventID, bool isLogError = false); IEnumerable<CustomEvent> GetEventsCollection(); } public interface IEventWithData : IEvent { bool Execute(IEventsData data); } public interface IEvent { string Id { get; } bool Execute(); } public interface ILogger { void Log(object obj); void LogInfo(object obj); void LogWarning(object obj); void LogError(object obj); void LogClear(); } public interface ITranslation { string GetTrans(string key, Languages lang); string GetTrans(string key, string lang); void InitFromString(string data); void InitFromFile(string path); } public interface IParseManager { bool TryParseEnum<TEnum>(string arg, out TEnum result, TEnum defaultValue = default(TEnum)); bool TryParseBool(string arg, out bool result, bool defaultValue = false); } }
plugins/ChaosTricks/ModHelperUnity.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using EventsIO.Interfaces; using ModHelper; using ModHelper.Interfaces; using ModHelperUnity.Data; using ModHelperUnity.Interfaces; using ModHelperUnity.UtilityGUI; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ModHelperUnity")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ModHelperUnity")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("4afa0e1e-341b-4554-97c1-0c38ad74f246")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace ModHelperUnity { public abstract class TypedNotifyBase : MonoBehaviour, IComponentTypedNotify { private bool isDisposed; private Queue<TypedNotifyMessage> messages; private bool isInitiated; private bool isMessageProcessed; private float delayAfterNotify; private bool isShowAnimationStageFinished; private bool isShowMessageStageFinished; private bool isHideAnimationStageFinished; protected int logLimit; protected IDebugLogger logger; protected Dictionary<string, Texture2D> messageTextures = new Dictionary<string, Texture2D>(); 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).Log((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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if (messageTextures.ContainsKey(type)) { return messageTextures[type]; } return new Texture2D(2, 2); } protected void LoadFadeSettings(string settingsDir, string settingsFname = "notify_settings.data") { try { string text = Path.Combine(settingsDir, settingsFname); Settings = UtilityJson.Generate(logger).FromFile<TypedNotifySettings>(text); } catch (Exception arg) { Log($"LoadFadeSettings error: {arg}"); } if (Settings == null) { Settings = new TypedNotifySettings(); } } protected Texture2D LoadImage(string settingsDir, string imageFname) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown try { Texture2D val = UtilityUI.LoadImage(settingsDir, imageFname); Log($"LoadImage {imageFname}: width {((Texture)val).width}, height {((Texture)val).height}"); return val; } catch (Exception arg) { Log($"LoadImage {imageFname} error: {arg}"); return new Texture2D(2, 2); } } protected void LoadResources(string settingsDir) { Log("LoadResources"); LoadFadeSettings(settingsDir); ClearMessageTextures(); if (Settings.notifyParameters != null) { TypedNotifyParameters[] notifyParameters = Settings.notifyParameters; foreach (TypedNotifyParameters typedNotifyParameters in notifyParameters) { Log(typedNotifyParameters.ToString()); messageTextures[typedNotifyParameters.type] = LoadImage(settingsDir, typedNotifyParameters.imageFileName); } } } public virtual void PostInit(string settingsDir, IDebugLogger logger = null) { this.logger = logger; if (!isInitiated) { try { messages = new Queue<TypedNotifyMessage>(); CurrentMessage = null; CurrentNotifyParameters = new TypedNotifyParameters(); logLimit = 10; isInitiated = true; LoadResources(settingsDir); } catch (Exception arg) { Log($"PostInit error: {arg}"); } } Log("post init completed"); } protected virtual string ProcessCustomTemplates(string message, IEventsData eventData, ITranslation translation) { try { return Regex.Replace(message, "%template_.+?%", (Match s) => translation.GetTrans(s.Value, eventData.Lang)); } catch (Exception arg) { Log($"ProcessCustomTemplates error: {arg}"); return message; } } protected virtual string GenerateMessage(IEventsData eventData, ITranslation translation) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) TypedNotifyParameters typedNotifyParameters = GetTypedNotifyParameters(eventData); string trans = translation.GetTrans(eventData.EventID, eventData.Lang); string message = typedNotifyParameters.messageTemplate.Replace("%name%", UtilityUI.GetColoredText(eventData.Username, typedNotifyParameters.nicknameTextColor)).Replace("%message%", UtilityUI.GetColoredText(trans, typedNotifyParameters.messageTextColor)); return ProcessCustomTemplates(message, eventData, translation).ToUpperInvariant(); } protected 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]; } protected 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) { if (eventData == null) { Log("warning, eventData is null"); } if (eventData == null) { Log("warning, translation is null"); } TypedNotifyParameters typedNotifyParameters = GetTypedNotifyParameters(eventData); AddNotifyToQueue(new TypedNotifyMessage(GenerateMessage(eventData, translation), 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 static class UtilityUI { public static int StandardScreenWidth => 2560; public static int StandardScreenHeight => 1440; public static string GetColoredText(string text, Color32 color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) string text2 = ColorUtility.ToHtmlStringRGBA(Color32.op_Implicit(color)); return "<color=#" + text2 + ">" + text + "</color>"; } public static Texture2D LoadImage(string fileDirectory, string imageFname) { //IL_000f: 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_001b: Expected O, but got Unknown //IL_001d: Expected O, but got Unknown byte[] array = File.ReadAllBytes(Path.Combine(fileDirectory, imageFname)); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, array); return val; } public static float CalcScreenFactor(int baseScreenSize, int currentScreenSize) { if (baseScreenSize != currentScreenSize) { return (float)currentScreenSize / (float)baseScreenSize; } return 1f; } } public class MathUtility { public static int GetSign() { if (Random.Range(-1, 1) <= 0) { return -1; } return 1; } public static Vector3 FindRandomSpawnPointNearPosition(Vector3 pos, float minDistance, float maxDistance) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if (maxDistance < 0f) { maxDistance = 10f; } if (minDistance < 0f || minDistance > maxDistance) { minDistance = 0f; } Vector3 result = default(Vector3); float num = Random.Range(-(float)Math.PI, (float)Math.PI); float num2 = Random.Range(minDistance, maxDistance); result.x = Mathf.Floor(pos.x + num2 * Mathf.Cos(num)); result.z = Mathf.Floor(pos.z + num2 * Mathf.Sin(num)); result.y = pos.y; return result; } public static Vector3 FindRandomSpawnPointNearPositionFixY(Vector3 pos, float minDistance, float maxDistance, float yFixOffset, LayerMask mask) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) Vector3 result = FindRandomSpawnPointNearPosition(pos, minDistance, maxDistance); RaycastHit val = default(RaycastHit); if (Physics.Raycast(pos + Vector3.up * 10f, Vector3.down, ref val, 10f, LayerMask.op_Implicit(mask))) { result = ((RaycastHit)(ref val)).point; result.y += yFixOffset; } return result; } public static Vector3 GetRandomVector(Vector3 randomRangeMin, Vector3 randomRangeMax) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) float num = Random.Range(randomRangeMin.x, randomRangeMax.x); float num2 = Random.Range(randomRangeMin.y, randomRangeMax.y); float num3 = Random.Range(randomRangeMin.z, randomRangeMax.z); return new Vector3(num, num2, num3); } public static void LookAt(Transform obj, Transform target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) Vector3 val = target.position - obj.position; obj.rotation = Quaternion.LookRotation(val); } } public static class Loader { private static GameObject hookObj; private static readonly string AssemblyName; private static readonly string ClassMod; public static ILogger Logger { get; } public static GameObject HookObj { get; set; } static Loader() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown AssemblyName = "InteractiveMod"; ClassMod = AssemblyName; Logger = (ILogger)new HelperLog(UtilitySettings.BaseFolder, "loader_log.txt"); Logger.LogClear(); } public static async Task StartInitTask(Type type) { int counter = 0; do { await Task.Delay(5000); if ((Object)(object)hookObj == (Object)null) { Logger.LogInfo((object)"Background task: trying to create mod instance"); hookObj = new GameObject(); Object.DontDestroyOnLoad((Object)(object)hookObj); hookObj.AddComponent(type); hookObj.SetActive(true); } int num = counter + 1; counter = num; } while (counter <= 10 && (!((Object)(object)hookObj != (Object)null) || counter <= 2)); Logger.LogInfo((object)"Background task closed"); } public static void LoadAssembly() { Logger.LogInfo((object)"load mod assembly"); Assembly assembly = AppDomain.CurrentDomain.Load(AssemblyName); CancellationToken token = new CancellationTokenSource().Token; if (string.Equals(assembly.GetName().Name, AssemblyName, StringComparison.OrdinalIgnoreCase)) { Type[] types = assembly.GetTypes(); foreach (Type type in types) { bool num = string.Equals(type.Name, ClassMod, StringComparison.OrdinalIgnoreCase); Type typeFromHandle = typeof(MonoBehaviour); bool flag = type.IsAssignableFrom(typeFromHandle) || type.IsSubclassOf(typeFromHandle); if (!(num && flag)) { continue; } Logger.LogInfo((object)"Loader init success"); Task.Factory.StartNew((Func<Task>)async delegate { try { await StartInitTask(type); } catch (Exception arg) { Logger.LogError((object)$"LoadAssembly task error {arg}"); } }, token, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); return; } } else { Logger.LogError((object)"wrong assembly mod name"); } Logger.LogError((object)"init failed"); } public static void Init() { Logger.LogClear(); Logger.LogInfo((object)"Loader triggered"); try { LoadAssembly(); } catch (Exception arg) { Logger.LogError((object)$"ModHelperUnity.Init {arg}"); } } } public class Patcher { private readonly ILogger logger = (ILogger)new HelperLog(UtilitySettings.BaseFolder, "patcher_log.txt"); private bool isPatched; internal void ExecutePatch() { try { logger.LogClear(); logger.LogInfo((object)$"Patcher v{Assembly.GetExecutingAssembly().GetName().Version}"); SceneManager.sceneLoaded += OnSceneLoaded; } catch (Exception arg) { logger.LogError((object)$"Patcher unexpected error: {arg}"); } } private void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode) { try { logger.Log((object)("OnSceneLoaded triggered: " + ((Scene)(ref scene)).name)); if (!isPatched) { Loader.Init(); isPatched = true; SceneManager.sceneLoaded -= OnSceneLoaded; } } catch (Exception arg) { logger.LogError((object)$"Patcher unexpected error: {arg}"); } } } public class Preloader { private static string baseFolderFullPath; private static readonly ILogger logger = (ILogger)new HelperLog(UtilitySettings.BaseFolder, "preloader_log.txt"); public static string GetAssemblyModFolderFullPath() { return baseFolderFullPath; } public static void Main() { logger.LogClear(); logger.LogInfo((object)"Preloader main"); baseFolderFullPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); AppDomain.CurrentDomain.AssemblyResolve += ModAssemblyResolve; new Patcher().ExecutePatch(); } private static Assembly ModAssemblyResolve(object sender, ResolveEventArgs args) { try { string text = Path.Combine(GetAssemblyModFolderFullPath(), new AssemblyName(args.Name).Name + ".dll"); logger.LogInfo((object)text); if (File.Exists(text)) { return Assembly.LoadFrom(text); } } catch (Exception arg) { logger.LogError((object)$"Preloader {arg}"); } return null; } } } namespace ModHelperUnity.UtilityGUI { public class TypedNotifyOnGUI : TypedNotifyBase { private float currentAlpha; private float targetAlpha; protected Dictionary<string, Font> fonts; public TypedNotifyOnGUI() { 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) { IDebugLogger obj = logger; if (obj != null) { ((ILogger)obj).Log((object)$"loading font error: {arg}"); } } } } 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).Log((object)$"finding font error: {arg}"); } } return null; } protected virtual void SetupAlpha(float baseDuration) { if (!Mathf.Approximately(currentAlpha, targetAlpha)) { currentAlpha = Mathf.MoveTowards(currentAlpha, targetAlpha, Time.deltaTime / baseDuration); } } protected override void UpdateProcessShowAnimation() { SetupAlpha(base.CurrentNotifyParameters.showFadeAnimationDuration); base.UpdateProcessShowAnimation(); } protected override void UpdateProcessNoAnimationStage() { SetupAlpha(base.CurrentNotifyParameters.showMessageDuration); base.UpdateProcessNoAnimationStage(); } protected override void UpdateProcessHideAnimation() { SetupAlpha(base.CurrentNotifyParameters.hideFadeAnimationDuration); base.UpdateProcessHideAnimation(); } protected override void StartShowAnimation() { base.StartShowAnimation(); targetAlpha = 1f; } protected override void StartHideAnimation() { base.StartHideAnimation(); targetAlpha = 0f; } protected string GetFadedText(string text) { string text2 = ((int)(255f * currentAlpha)).ToString("X2"); return text.Replace("FF>", text2 + ">"); } protected override void OnGUI() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) base.OnGUI(); TypedNotifyParameters currentNotifyParameters = base.CurrentNotifyParameters; if (!base.Settings.isDisableNotify && base.CurrentMessage != null && currentNotifyParameters != null && !currentNotifyParameters.isDisable) { Matrix4x4 matrix = GUI.matrix; Color color = GUI.color; color.a = currentAlpha; GUI.color = color; Texture2D messageTexture = GetMessageTexture(base.CurrentMessage.messageType); float num = UtilityUI.CalcScreenFactor(UtilityUI.StandardScreenWidth, Screen.width); float num2 = UtilityUI.CalcScreenFactor(UtilityUI.StandardScreenHeight, Screen.height); float num3 = (float)((Texture)messageTexture).width * num; float num4 = (float)((Texture)messageTexture).height * num2; Rect val = default(Rect); ((Rect)(ref val)).x = ((float)Screen.width - num3) * (0.5f + currentNotifyParameters.notifyHorisontalOffset); ((Rect)(ref val)).y = ((float)Screen.height - num4) * (0.5f + currentNotifyParameters.notifyVerticalOffset); ((Rect)(ref val)).width = num3; ((Rect)(ref val)).height = num4; Rect val2 = val; float num5 = Math.Min(num, num2); float num6 = Math.Max(num, num2); int num7 = (int)((float)currentNotifyParameters.fontSize * num5); GUIStyle val3 = new GUIStyle(GUI.skin.label) { fontSize = num7, alignment = (TextAnchor)4, richText = true, fixedWidth = num3, fixedHeight = num4 }; Font font = GetFont(currentNotifyParameters.fontPath, num7); if ((Object)(object)font != (Object)null) { val3.font = font; } val3.padding.top = (int)((float)currentNotifyParameters.textPadding.top * num6); val3.padding.bottom = (int)((float)currentNotifyParameters.textPadding.bottom * num6); val3.padding.left = (int)((float)currentNotifyParameters.textPadding.left * num6); val3.padding.right = (int)((float)currentNotifyParameters.textPadding.right * num6); val3.normal.textColor = color; GUI.DrawTexture(val2, (Texture)(object)messageTexture); GUI.Label(val2, GetFadedText(base.CurrentMessage.message), val3); GUI.matrix = matrix; } } } public class TypedNotifySettings { public bool isDisableNotify; public TypedNotifyParameters[] notifyParameters = new TypedNotifyParameters[0]; public override string ToString() { if (notifyParameters == null) { return "TypedNotifySettings: not found notifyParameters"; } string text = $"isDisableNotify={isDisableNotify}"; TypedNotifyParameters[] array = notifyParameters; for (int i = 0; i < array.Length; i++) { _ = array[i]; text = string.Join(Environment.NewLine, text, "notifyParameters:", notifyParameters.ToString()); } return text; } } } namespace ModHelperUnity.Interfaces { public interface IComponentTypedNotify { void AddNotifyToQueue(string message, string type); void AddNotifyToQueue(IEventsData eventData, ITranslation translation); void ClearNotifyQueue(); void StopCurrentNotify(); void PostInit(string settingsDir, IDebugLogger logger = null); } public interface ISoundManager { void PlaySound(string path, int volume = 50); void StopSound(); } public interface IDictionaryItemJson<T> { string Key { get; } T Value { get; } } } namespace ModHelperUnity.Data { public class TypedNotifyParameters { public bool isDisable; public string imageFileName = string.Empty; public string type = "default"; public string messageTemplate = "%name% %message%"; public string fontPath = ""; public float showMessageDuration = 5f; public float showFadeAnimationDuration = 1f; public float hideFadeAnimationDuration = 1f; public float delayAfterNotify = 1f; public float notifyHorisontalOffset; 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}", $"notifyHorisontalOffset: {notifyHorisontalOffset}", $"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 duration; public NotifyMessage(string msg, float duration) { this.msg = (string.IsNullOrEmpty(msg?.Trim()) ? string.Empty : msg); this.duration = duration; } public string GetMessage() { return msg; } public bool IsFinished() { return duration <= 0f; } public void OnFrame(float dt) { if (!IsFinished()) { duration -= dt; } } } }
plugins/ChaosTricks/websocket-sharp.dll
Decompiled 2 years 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.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Net; using System.Net.Security; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security.Authentication; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Security.Permissions; using System.Security.Principal; using System.Text; using System.Threading; using System.Timers; using WebSocketSharp.Net; using WebSocketSharp.Net.WebSockets; using WebSocketSharp.Server; [assembly: AssemblyProduct("websocket-sharp.dll")] [assembly: CompilationRelaxations(8)] [assembly: AssemblyCompany("")] [assembly: AssemblyCopyright("sta.blockhead")] [assembly: AssemblyTrademark("")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyTitle("websocket-sharp")] [assembly: AssemblyDescription("A C# implementation of the WebSocket protocol client and server")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyVersion("1.0.2.59611")] namespace WebSocketSharp { public static class Ext { private const string _tspecials = "()<>@,;:\\\"/[]?={} \t"; private static readonly byte[] _last; private static readonly int _retry; private static byte[] compress(this byte[] data) { if (data.LongLength == 0) { return data; } using MemoryStream stream = new MemoryStream(data); return stream.compressToArray(); } private static MemoryStream compress(this Stream stream) { MemoryStream memoryStream = new MemoryStream(); if (stream.Length == 0) { return memoryStream; } stream.Position = 0L; using DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress, leaveOpen: true); CopyTo(stream, deflateStream, 1024); deflateStream.Close(); memoryStream.Write(_last, 0, 1); memoryStream.Position = 0L; return memoryStream; } private static byte[] compressToArray(this Stream stream) { using MemoryStream memoryStream = stream.compress(); memoryStream.Close(); return memoryStream.ToArray(); } private static byte[] decompress(this byte[] data) { if (data.LongLength == 0) { return data; } using MemoryStream stream = new MemoryStream(data); return stream.decompressToArray(); } private static MemoryStream decompress(this Stream stream) { MemoryStream memoryStream = new MemoryStream(); if (stream.Length == 0) { return memoryStream; } stream.Position = 0L; using DeflateStream source = new DeflateStream(stream, CompressionMode.Decompress, leaveOpen: true); CopyTo(source, memoryStream, 1024); memoryStream.Position = 0L; return memoryStream; } private static byte[] decompressToArray(this Stream stream) { using MemoryStream memoryStream = stream.decompress(); memoryStream.Close(); return memoryStream.ToArray(); } private static void times(this ulong n, Action action) { for (ulong num = 0uL; num < n; num++) { action(); } } internal static byte[] Append(this ushort code, string reason) { byte[] array = code.InternalToByteArray(ByteOrder.Big); if (reason != null && reason.Length > 0) { List<byte> list = new List<byte>(array); list.AddRange(Encoding.UTF8.GetBytes(reason)); array = list.ToArray(); } return array; } internal static string CheckIfAvailable(this ServerState state, bool ready, bool start, bool shutting) { return ((!ready && (state == ServerState.Ready || state == ServerState.Stop)) || (!start && state == ServerState.Start) || (!shutting && state == ServerState.ShuttingDown)) ? ("This operation isn't available in: " + state.ToString().ToLower()) : null; } internal static string CheckIfAvailable(this WebSocketState state, bool connecting, bool open, bool closing, bool closed) { return ((!connecting && state == WebSocketState.Connecting) || (!open && state == WebSocketState.Open) || (!closing && state == WebSocketState.Closing) || (!closed && state == WebSocketState.Closed)) ? ("This operation isn't available in: " + state.ToString().ToLower()) : null; } internal static string CheckIfValidProtocols(this string[] protocols) { return protocols.Contains((string protocol) => protocol == null || protocol.Length == 0 || !protocol.IsToken()) ? "Contains an invalid value." : (protocols.ContainsTwice() ? "Contains a value twice." : null); } internal static string CheckIfValidServicePath(this string path) { return (path == null || path.Length == 0) ? "'path' is null or empty." : ((path[0] != '/') ? "'path' isn't an absolute path." : ((path.IndexOfAny(new char[2] { '?', '#' }) > -1) ? "'path' includes either or both query and fragment components." : null)); } internal static string CheckIfValidSessionID(this string id) { return (id == null || id.Length == 0) ? "'id' is null or empty." : null; } internal static string CheckIfValidWaitTime(this TimeSpan time) { return (time <= TimeSpan.Zero) ? "A wait time is zero or less." : null; } internal static bool CheckWaitTime(this TimeSpan time, out string message) { message = null; if (time <= TimeSpan.Zero) { message = "A wait time is zero or less."; return false; } return true; } internal static void Close(this WebSocketSharp.Net.HttpListenerResponse response, WebSocketSharp.Net.HttpStatusCode code) { response.StatusCode = (int)code; response.OutputStream.Close(); } internal static void CloseWithAuthChallenge(this WebSocketSharp.Net.HttpListenerResponse response, string challenge) { response.Headers.InternalSet("WWW-Authenticate", challenge, response: true); response.Close(WebSocketSharp.Net.HttpStatusCode.Unauthorized); } internal static byte[] Compress(this byte[] data, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? data.compress() : data; } internal static Stream Compress(this Stream stream, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? stream.compress() : stream; } internal static byte[] CompressToArray(this Stream stream, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? stream.compressToArray() : stream.ToByteArray(); } internal static bool Contains<T>(this IEnumerable<T> source, Func<T, bool> condition) { foreach (T item in source) { if (condition(item)) { return true; } } return false; } internal static bool ContainsTwice(this string[] values) { int len = values.Length; Func<int, bool> contains = null; contains = delegate(int idx) { if (idx < len - 1) { for (int i = idx + 1; i < len; i++) { if (values[i] == values[idx]) { return true; } } return contains(++idx); } return false; }; return contains(0); } internal static T[] Copy<T>(this T[] source, long length) { T[] array = new T[length]; Array.Copy(source, 0L, array, 0L, length); return array; } internal static void CopyTo(this Stream source, Stream destination, int bufferLength) { byte[] buffer = new byte[bufferLength]; int num = 0; while ((num = source.Read(buffer, 0, bufferLength)) > 0) { destination.Write(buffer, 0, num); } } internal static void CopyToAsync(this Stream source, Stream destination, int bufferLength, Action completed, Action<Exception> error) { byte[] buff = new byte[bufferLength]; AsyncCallback callback = null; callback = delegate(IAsyncResult ar) { try { int num = source.EndRead(ar); if (num <= 0) { if (completed != null) { completed(); } } else { destination.Write(buff, 0, num); source.BeginRead(buff, 0, bufferLength, callback, null); } } catch (Exception obj2) { if (error != null) { error(obj2); } } }; try { source.BeginRead(buff, 0, bufferLength, callback, null); } catch (Exception obj) { if (error != null) { error(obj); } } } internal static byte[] Decompress(this byte[] data, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? data.decompress() : data; } internal static Stream Decompress(this Stream stream, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? stream.decompress() : stream; } internal static byte[] DecompressToArray(this Stream stream, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? stream.decompressToArray() : stream.ToByteArray(); } internal static bool EqualsWith(this int value, char c, Action<int> action) { action(value); return value == c; } internal static string GetAbsolutePath(this Uri uri) { if (uri.IsAbsoluteUri) { return uri.AbsolutePath; } string originalString = uri.OriginalString; if (originalString[0] != '/') { return null; } int num = originalString.IndexOfAny(new char[2] { '?', '#' }); return (num > 0) ? originalString.Substring(0, num) : originalString; } internal static string GetMessage(this CloseStatusCode code) { return code switch { CloseStatusCode.TlsHandshakeFailure => "An error has occurred during a TLS handshake.", CloseStatusCode.ServerError => "WebSocket server got an internal error.", CloseStatusCode.MandatoryExtension => "WebSocket client didn't receive expected extension(s).", CloseStatusCode.TooBig => "A too big message has been received.", CloseStatusCode.PolicyViolation => "A policy violation has occurred.", CloseStatusCode.InvalidData => "Invalid data has been received.", CloseStatusCode.Abnormal => "An exception has occurred.", CloseStatusCode.UnsupportedData => "Unsupported data has been received.", CloseStatusCode.ProtocolError => "A WebSocket protocol error has occurred.", _ => string.Empty, }; } internal static string GetName(this string nameAndValue, char separator) { int num = nameAndValue.IndexOf(separator); return (num > 0) ? nameAndValue.Substring(0, num).Trim() : null; } internal static string GetValue(this string nameAndValue, char separator) { int num = nameAndValue.IndexOf(separator); return (num > -1 && num < nameAndValue.Length - 1) ? nameAndValue.Substring(num + 1).Trim() : null; } internal static string GetValue(this string nameAndValue, char separator, bool unquote) { int num = nameAndValue.IndexOf(separator); if (num < 0 || num == nameAndValue.Length - 1) { return null; } string text = nameAndValue.Substring(num + 1).Trim(); return unquote ? text.Unquote() : text; } internal static TcpListenerWebSocketContext GetWebSocketContext(this TcpClient tcpClient, string protocol, bool secure, ServerSslConfiguration sslConfig, Logger logger) { return new TcpListenerWebSocketContext(tcpClient, protocol, secure, sslConfig, logger); } internal static byte[] InternalToByteArray(this ushort value, ByteOrder order) { byte[] bytes = BitConverter.GetBytes(value); if (!order.IsHostOrder()) { Array.Reverse((Array)bytes); } return bytes; } internal static byte[] InternalToByteArray(this ulong value, ByteOrder order) { byte[] bytes = BitConverter.GetBytes(value); if (!order.IsHostOrder()) { Array.Reverse((Array)bytes); } return bytes; } internal static bool IsCompressionExtension(this string value, CompressionMethod method) { return value.StartsWith(method.ToExtensionString()); } internal static bool IsControl(this byte opcode) { return opcode > 7 && opcode < 16; } internal static bool IsControl(this Opcode opcode) { return (int)opcode >= 8; } internal static bool IsData(this byte opcode) { return opcode == 1 || opcode == 2; } internal static bool IsData(this Opcode opcode) { return opcode == Opcode.Text || opcode == Opcode.Binary; } internal static bool IsPortNumber(this int value) { return value > 0 && value < 65536; } internal static bool IsReserved(this ushort code) { return code == 1004 || code == 1005 || code == 1006 || code == 1015; } internal static bool IsReserved(this CloseStatusCode code) { return code == CloseStatusCode.Undefined || code == CloseStatusCode.NoStatus || code == CloseStatusCode.Abnormal || code == CloseStatusCode.TlsHandshakeFailure; } internal static bool IsSupported(this byte opcode) { return Enum.IsDefined(typeof(Opcode), opcode); } internal static bool IsText(this string value) { int length = value.Length; for (int i = 0; i < length; i++) { char c = value[i]; if (c < ' ' && !Contains("\r\n\t", c)) { return false; } switch (c) { case '\u007f': return false; case '\n': if (++i < length) { c = value[i]; if (!Contains(" \t", c)) { return false; } } break; } } return true; } internal static bool IsToken(this string value) { foreach (char c in value) { if (c < ' ' || c >= '\u007f' || Contains("()<>@,;:\\\"/[]?={} \t", c)) { return false; } } return true; } internal static string Quote(this string value) { return string.Format("\"{0}\"", value.Replace("\"", "\\\"")); } internal static byte[] ReadBytes(this Stream stream, int length) { byte[] array = new byte[length]; int num = 0; try { int num2 = 0; while (length > 0) { num2 = stream.Read(array, num, length); if (num2 == 0) { break; } num += num2; length -= num2; } } catch { } return array.SubArray(0, num); } internal static byte[] ReadBytes(this Stream stream, long length, int bufferLength) { using MemoryStream memoryStream = new MemoryStream(); try { byte[] buffer = new byte[bufferLength]; int num = 0; while (length > 0) { if (length < bufferLength) { bufferLength = (int)length; } num = stream.Read(buffer, 0, bufferLength); if (num == 0) { break; } memoryStream.Write(buffer, 0, num); length -= num; } } catch { } memoryStream.Close(); return memoryStream.ToArray(); } internal static void ReadBytesAsync(this Stream stream, int length, Action<byte[]> completed, Action<Exception> error) { byte[] buff = new byte[length]; int offset = 0; int retry = 0; AsyncCallback callback = null; callback = delegate(IAsyncResult ar) { try { int num = stream.EndRead(ar); if (num == 0 && retry < _retry) { retry++; stream.BeginRead(buff, offset, length, callback, null); } else if (num == 0 || num == length) { if (completed != null) { completed(buff.SubArray(0, offset + num)); } } else { retry = 0; offset += num; length -= num; stream.BeginRead(buff, offset, length, callback, null); } } catch (Exception obj2) { if (error != null) { error(obj2); } } }; try { stream.BeginRead(buff, offset, length, callback, null); } catch (Exception obj) { if (error != null) { error(obj); } } } internal static void ReadBytesAsync(this Stream stream, long length, int bufferLength, Action<byte[]> completed, Action<Exception> error) { MemoryStream dest = new MemoryStream(); byte[] buff = new byte[bufferLength]; int retry = 0; Action<long> read = null; read = delegate(long len) { if (len < bufferLength) { bufferLength = (int)len; } stream.BeginRead(buff, 0, bufferLength, delegate(IAsyncResult ar) { try { int num = stream.EndRead(ar); if (num > 0) { dest.Write(buff, 0, num); } if (num == 0 && retry < _retry) { retry++; read(len); } else if (num == 0 || num == len) { if (completed != null) { dest.Close(); completed(dest.ToArray()); } dest.Dispose(); } else { retry = 0; read(len - num); } } catch (Exception obj2) { dest.Dispose(); if (error != null) { error(obj2); } } }, null); }; try { read(length); } catch (Exception obj) { dest.Dispose(); if (error != null) { error(obj); } } } internal static string RemovePrefix(this string value, params string[] prefixes) { int num = 0; foreach (string text in prefixes) { if (value.StartsWith(text)) { num = text.Length; break; } } return (num > 0) ? value.Substring(num) : value; } internal static T[] Reverse<T>(this T[] array) { int num = array.Length; T[] array2 = new T[num]; int num2 = num - 1; for (int i = 0; i <= num2; i++) { array2[i] = array[num2 - i]; } return array2; } internal static IEnumerable<string> SplitHeaderValue(this string value, params char[] separators) { int len = value.Length; string seps = new string(separators); StringBuilder buff = new StringBuilder(32); bool escaped = false; bool quoted = false; for (int i = 0; i < len; i++) { char c = value[i]; switch (c) { case '"': if (escaped) { escaped = !escaped; } else { quoted = !quoted; } break; case '\\': if (i < len - 1 && value[i + 1] == '"') { escaped = true; } break; default: if (Contains(seps, c) && !quoted) { yield return buff.ToString(); buff.Length = 0; continue; } break; } buff.Append(c); } if (buff.Length > 0) { yield return buff.ToString(); } } internal static byte[] ToByteArray(this Stream stream) { using MemoryStream memoryStream = new MemoryStream(); stream.Position = 0L; CopyTo(stream, memoryStream, 1024); memoryStream.Close(); return memoryStream.ToArray(); } internal static CompressionMethod ToCompressionMethod(this string value) { foreach (CompressionMethod value2 in Enum.GetValues(typeof(CompressionMethod))) { if (value2.ToExtensionString() == value) { return value2; } } return CompressionMethod.None; } internal static string ToExtensionString(this CompressionMethod method, params string[] parameters) { if (method == CompressionMethod.None) { return string.Empty; } string text = $"permessage-{method.ToString().ToLower()}"; if (parameters == null || parameters.Length == 0) { return text; } return string.Format("{0}; {1}", text, parameters.ToString("; ")); } internal static IPAddress ToIPAddress(this string hostnameOrAddress) { if (IPAddress.TryParse(hostnameOrAddress, out IPAddress address)) { return address; } try { return Dns.GetHostAddresses(hostnameOrAddress)[0]; } catch { return null; } } internal static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) { return new List<TSource>(source); } internal static ushort ToUInt16(this byte[] source, ByteOrder sourceOrder) { return BitConverter.ToUInt16(source.ToHostOrder(sourceOrder), 0); } internal static ulong ToUInt64(this byte[] source, ByteOrder sourceOrder) { return BitConverter.ToUInt64(source.ToHostOrder(sourceOrder), 0); } internal static string TrimEndSlash(this string value) { value = value.TrimEnd(new char[1] { '/' }); return (value.Length > 0) ? value : "/"; } internal static bool TryCreateWebSocketUri(this string uriString, out Uri result, out string message) { result = null; Uri uri = uriString.ToUri(); if (uri == null) { message = "An invalid URI string: " + uriString; return false; } if (!uri.IsAbsoluteUri) { message = "Not an absolute URI: " + uriString; return false; } string scheme = uri.Scheme; if (!(scheme == "ws") && !(scheme == "wss")) { message = "The scheme part isn't 'ws' or 'wss': " + uriString; return false; } if (uri.Fragment.Length > 0) { message = "Includes the fragment component: " + uriString; return false; } int port = uri.Port; if (port == 0) { message = "The port part is zero: " + uriString; return false; } result = ((port != -1) ? uri : new Uri(string.Format("{0}://{1}:{2}{3}", scheme, uri.Host, (scheme == "ws") ? 80 : 443, uri.PathAndQuery))); message = string.Empty; return true; } internal static string Unquote(this string value) { int num = value.IndexOf('"'); if (num < 0) { return value; } int num2 = value.LastIndexOf('"'); int num3 = num2 - num - 1; return (num3 < 0) ? value : ((num3 == 0) ? string.Empty : value.Substring(num + 1, num3).Replace("\\\"", "\"")); } internal static string UTF8Decode(this byte[] bytes) { try { return Encoding.UTF8.GetString(bytes); } catch { return null; } } internal static byte[] UTF8Encode(this string s) { return Encoding.UTF8.GetBytes(s); } internal static void WriteBytes(this Stream stream, byte[] bytes, int bufferLength) { using MemoryStream source = new MemoryStream(bytes); CopyTo(source, stream, bufferLength); } internal static void WriteBytesAsync(this Stream stream, byte[] bytes, int bufferLength, Action completed, Action<Exception> error) { MemoryStream input = new MemoryStream(bytes); input.CopyToAsync(stream, bufferLength, delegate { if (completed != null) { completed(); } input.Dispose(); }, delegate(Exception ex) { input.Dispose(); if (error != null) { error(ex); } }); } public static bool Contains(this string value, params char[] chars) { return chars == null || chars.Length == 0 || (value != null && value.Length != 0 && value.IndexOfAny(chars) > -1); } public static bool Contains(this NameValueCollection collection, string name) { return collection != null && collection.Count > 0 && collection[name] != null; } public static bool Contains(this NameValueCollection collection, string name, string value) { if (collection == null || collection.Count == 0) { return false; } string text = collection[name]; if (text == null) { return false; } string[] array = text.Split(new char[1] { ',' }); foreach (string text2 in array) { if (text2.Trim().Equals(value, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } public static void Emit(this EventHandler eventHandler, object sender, EventArgs e) { eventHandler?.Invoke(sender, e); } public static void Emit<TEventArgs>(this EventHandler<TEventArgs> eventHandler, object sender, TEventArgs e) where TEventArgs : EventArgs { eventHandler?.Invoke(sender, e); } public static WebSocketSharp.Net.CookieCollection GetCookies(this NameValueCollection headers, bool response) { string name = (response ? "Set-Cookie" : "Cookie"); return (headers != null && headers.Contains(name)) ? WebSocketSharp.Net.CookieCollection.Parse(headers[name], response) : new WebSocketSharp.Net.CookieCollection(); } public static string GetDescription(this WebSocketSharp.Net.HttpStatusCode code) { return ((int)code).GetStatusDescription(); } public static string GetStatusDescription(this int code) { return code switch { 100 => "Continue", 101 => "Switching Protocols", 102 => "Processing", 200 => "OK", 201 => "Created", 202 => "Accepted", 203 => "Non-Authoritative Information", 204 => "No Content", 205 => "Reset Content", 206 => "Partial Content", 207 => "Multi-Status", 300 => "Multiple Choices", 301 => "Moved Permanently", 302 => "Found", 303 => "See Other", 304 => "Not Modified", 305 => "Use Proxy", 307 => "Temporary Redirect", 400 => "Bad Request", 401 => "Unauthorized", 402 => "Payment Required", 403 => "Forbidden", 404 => "Not Found", 405 => "Method Not Allowed", 406 => "Not Acceptable", 407 => "Proxy Authentication Required", 408 => "Request Timeout", 409 => "Conflict", 410 => "Gone", 411 => "Length Required", 412 => "Precondition Failed", 413 => "Request Entity Too Large", 414 => "Request-Uri Too Long", 415 => "Unsupported Media Type", 416 => "Requested Range Not Satisfiable", 417 => "Expectation Failed", 422 => "Unprocessable Entity", 423 => "Locked", 424 => "Failed Dependency", 500 => "Internal Server Error", 501 => "Not Implemented", 502 => "Bad Gateway", 503 => "Service Unavailable", 504 => "Gateway Timeout", 505 => "Http Version Not Supported", 507 => "Insufficient Storage", _ => string.Empty, }; } public static bool IsCloseStatusCode(this ushort value) { return value > 999 && value < 5000; } public static bool IsEnclosedIn(this string value, char c) { return value != null && value.Length > 1 && value[0] == c && value[value.Length - 1] == c; } public static bool IsHostOrder(this ByteOrder order) { return !(BitConverter.IsLittleEndian ^ (order == ByteOrder.Little)); } public static bool IsLocal(this IPAddress address) { if (address == null) { return false; } if (address.Equals(IPAddress.Any)) { return true; } if (address.Equals(IPAddress.Loopback)) { return true; } if (Socket.OSSupportsIPv6) { if (address.Equals(IPAddress.IPv6Any)) { return true; } if (address.Equals(IPAddress.IPv6Loopback)) { return true; } } string hostName = Dns.GetHostName(); IPAddress[] hostAddresses = Dns.GetHostAddresses(hostName); IPAddress[] array = hostAddresses; foreach (IPAddress obj in array) { if (address.Equals(obj)) { return true; } } return false; } public static bool IsNullOrEmpty(this string value) { return value == null || value.Length == 0; } public static bool IsPredefinedScheme(this string value) { if (value == null || value.Length < 2) { return false; } char c = value[0]; if (c == 'h') { return value == "http" || value == "https"; } if (c == 'w') { return value == "ws" || value == "wss"; } if (c == 'f') { return value == "file" || value == "ftp"; } if (c == 'n') { c = value[1]; return (c != 'e') ? (value == "nntp") : (value == "news" || value == "net.pipe" || value == "net.tcp"); } return (c == 'g' && value == "gopher") || (c == 'm' && value == "mailto"); } public static bool IsUpgradeTo(this WebSocketSharp.Net.HttpListenerRequest request, string protocol) { if (request == null) { throw new ArgumentNullException("request"); } if (protocol == null) { throw new ArgumentNullException("protocol"); } if (protocol.Length == 0) { throw new ArgumentException("An empty string.", "protocol"); } return request.Headers.Contains("Upgrade", protocol) && request.Headers.Contains("Connection", "Upgrade"); } public static bool MaybeUri(this string value) { if (value == null || value.Length == 0) { return false; } int num = value.IndexOf(':'); if (num == -1) { return false; } if (num >= 10) { return false; } return value.Substring(0, num).IsPredefinedScheme(); } public static T[] SubArray<T>(this T[] array, int startIndex, int length) { int num; if (array == null || (num = array.Length) == 0) { return new T[0]; } if (startIndex < 0 || length <= 0 || startIndex + length > num) { return new T[0]; } if (startIndex == 0 && length == num) { return array; } T[] array2 = new T[length]; Array.Copy(array, startIndex, array2, 0, length); return array2; } public static T[] SubArray<T>(this T[] array, long startIndex, long length) { long longLength; if (array == null || (longLength = array.LongLength) == 0) { return new T[0]; } if (startIndex < 0 || length <= 0 || startIndex + length > longLength) { return new T[0]; } if (startIndex == 0 && length == longLength) { return array; } T[] array2 = new T[length]; Array.Copy(array, startIndex, array2, 0L, length); return array2; } public static void Times(this int n, Action action) { if (n > 0 && action != null) { ((ulong)n).times(action); } } public static void Times(this long n, Action action) { if (n > 0 && action != null) { ((ulong)n).times(action); } } public static void Times(this uint n, Action action) { if (n != 0 && action != null) { times(n, action); } } public static void Times(this ulong n, Action action) { if (n != 0 && action != null) { n.times(action); } } public static void Times(this int n, Action<int> action) { if (n > 0 && action != null) { for (int i = 0; i < n; i++) { action(i); } } } public static void Times(this long n, Action<long> action) { if (n > 0 && action != null) { for (long num = 0L; num < n; num++) { action(num); } } } public static void Times(this uint n, Action<uint> action) { if (n != 0 && action != null) { for (uint num = 0u; num < n; num++) { action(num); } } } public static void Times(this ulong n, Action<ulong> action) { if (n != 0 && action != null) { for (ulong num = 0uL; num < n; num++) { action(num); } } } public static T To<T>(this byte[] source, ByteOrder sourceOrder) where T : struct { if (source == null) { throw new ArgumentNullException("source"); } if (source.Length == 0) { return default(T); } Type typeFromHandle = typeof(T); byte[] value = source.ToHostOrder(sourceOrder); return ((object)typeFromHandle == typeof(bool)) ? ((T)(object)BitConverter.ToBoolean(value, 0)) : (((object)typeFromHandle == typeof(char)) ? ((T)(object)BitConverter.ToChar(value, 0)) : (((object)typeFromHandle == typeof(double)) ? ((T)(object)BitConverter.ToDouble(value, 0)) : (((object)typeFromHandle == typeof(short)) ? ((T)(object)BitConverter.ToInt16(value, 0)) : (((object)typeFromHandle == typeof(int)) ? ((T)(object)BitConverter.ToInt32(value, 0)) : (((object)typeFromHandle == typeof(long)) ? ((T)(object)BitConverter.ToInt64(value, 0)) : (((object)typeFromHandle == typeof(float)) ? ((T)(object)BitConverter.ToSingle(value, 0)) : (((object)typeFromHandle == typeof(ushort)) ? ((T)(object)BitConverter.ToUInt16(value, 0)) : (((object)typeFromHandle == typeof(uint)) ? ((T)(object)BitConverter.ToUInt32(value, 0)) : (((object)typeFromHandle == typeof(ulong)) ? ((T)(object)BitConverter.ToUInt64(value, 0)) : default(T)))))))))); } public static byte[] ToByteArray<T>(this T value, ByteOrder order) where T : struct { Type typeFromHandle = typeof(T); byte[] array = (((object)typeFromHandle == typeof(bool)) ? BitConverter.GetBytes((bool)(object)value) : (((object)typeFromHandle == typeof(byte)) ? new byte[1] { (byte)(object)value } : (((object)typeFromHandle == typeof(char)) ? BitConverter.GetBytes((char)(object)value) : (((object)typeFromHandle == typeof(double)) ? BitConverter.GetBytes((double)(object)value) : (((object)typeFromHandle == typeof(short)) ? BitConverter.GetBytes((short)(object)value) : (((object)typeFromHandle == typeof(int)) ? BitConverter.GetBytes((int)(object)value) : (((object)typeFromHandle == typeof(long)) ? BitConverter.GetBytes((long)(object)value) : (((object)typeFromHandle == typeof(float)) ? BitConverter.GetBytes((float)(object)value) : (((object)typeFromHandle == typeof(ushort)) ? BitConverter.GetBytes((ushort)(object)value) : (((object)typeFromHandle == typeof(uint)) ? BitConverter.GetBytes((uint)(object)value) : (((object)typeFromHandle == typeof(ulong)) ? BitConverter.GetBytes((ulong)(object)value) : WebSocket.EmptyBytes))))))))))); if (array.Length > 1 && !order.IsHostOrder()) { Array.Reverse((Array)array); } return array; } public static byte[] ToHostOrder(this byte[] source, ByteOrder sourceOrder) { if (source == null) { throw new ArgumentNullException("source"); } return (source.Length > 1 && !sourceOrder.IsHostOrder()) ? source.Reverse() : source; } public static string ToString<T>(this T[] array, string separator) { if (array == null) { throw new ArgumentNullException("array"); } int num = array.Length; if (num == 0) { return string.Empty; } if (separator == null) { separator = string.Empty; } StringBuilder buff = new StringBuilder(64); (num - 1).Times(delegate(int i) { buff.AppendFormat("{0}{1}", array[i].ToString(), separator); }); buff.Append(array[num - 1].ToString()); return buff.ToString(); } public static Uri ToUri(this string uriString) { Uri.TryCreate(uriString, uriString.MaybeUri() ? UriKind.Absolute : UriKind.Relative, out Uri result); return result; } public static string UrlDecode(this string value) { return (value != null && value.Length > 0) ? HttpUtility.UrlDecode(value) : value; } public static string UrlEncode(this string value) { return (value != null && value.Length > 0) ? HttpUtility.UrlEncode(value) : value; } public static void WriteContent(this WebSocketSharp.Net.HttpListenerResponse response, byte[] content) { if (response == null) { throw new ArgumentNullException("response"); } if (content == null) { throw new ArgumentNullException("content"); } long longLength = content.LongLength; if (longLength == 0) { response.Close(); return; } response.ContentLength64 = longLength; Stream outputStream = response.OutputStream; if (longLength <= int.MaxValue) { outputStream.Write(content, 0, (int)longLength); } else { outputStream.WriteBytes(content, 1024); } outputStream.Close(); } static Ext() { byte[] last = new byte[1]; _last = last; _retry = 5; } } public class MessageEventArgs : EventArgs { private string _data; private bool _dataSet; private Opcode _opcode; private byte[] _rawData; public string Data { get { if (!_dataSet) { _data = ((_opcode != Opcode.Binary) ? _rawData.UTF8Decode() : BitConverter.ToString(_rawData)); _dataSet = true; } return _data; } } public bool IsBinary => _opcode == Opcode.Binary; public bool IsPing => _opcode == Opcode.Ping; public bool IsText => _opcode == Opcode.Text; public byte[] RawData => _rawData; [Obsolete("This property will be removed. Use any of the Is properties instead.")] public Opcode Type => _opcode; internal MessageEventArgs(WebSocketFrame frame) { _opcode = frame.Opcode; _rawData = frame.PayloadData.ApplicationData; } internal MessageEventArgs(Opcode opcode, byte[] rawData) { if ((ulong)rawData.LongLength > PayloadData.MaxLength) { throw new WebSocketException(CloseStatusCode.TooBig); } _opcode = opcode; _rawData = rawData; } } public class CloseEventArgs : EventArgs { private bool _clean; private ushort _code; private PayloadData _payloadData; private string _reason; internal PayloadData PayloadData => _payloadData ?? (_payloadData = new PayloadData(_code.Append(_reason))); public ushort Code => _code; public string Reason => _reason ?? string.Empty; public bool WasClean { get { return _clean; } internal set { _clean = value; } } internal CloseEventArgs() { _code = 1005; _payloadData = PayloadData.Empty; } internal CloseEventArgs(ushort code) { _code = code; } internal CloseEventArgs(CloseStatusCode code) : this((ushort)code) { } internal CloseEventArgs(PayloadData payloadData) { _payloadData = payloadData; byte[] applicationData = payloadData.ApplicationData; int num = applicationData.Length; _code = (ushort)((num > 1) ? applicationData.SubArray(0, 2).ToUInt16(ByteOrder.Big) : 1005); _reason = ((num > 2) ? applicationData.SubArray(2, num - 2).UTF8Decode() : string.Empty); } internal CloseEventArgs(ushort code, string reason) { _code = code; _reason = reason; } internal CloseEventArgs(CloseStatusCode code, string reason) : this((ushort)code, reason) { } } public enum ByteOrder { Little, Big } public class ErrorEventArgs : EventArgs { private Exception _exception; private string _message; public Exception Exception => _exception; public string Message => _message; internal ErrorEventArgs(string message) : this(message, null) { } internal ErrorEventArgs(string message, Exception exception) { _message = message; _exception = exception; } } public class WebSocket : IDisposable { private const string _guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; private const string _version = "13"; private AuthenticationChallenge _authChallenge; private string _base64Key; private bool _client; private Action _closeContext; private CompressionMethod _compression; private WebSocketContext _context; private WebSocketSharp.Net.CookieCollection _cookies; private WebSocketSharp.Net.NetworkCredential _credentials; private bool _emitOnPing; private bool _enableRedirection; private AutoResetEvent _exitReceiving; private string _extensions; private bool _extensionsRequested; private object _forConn; private object _forMessageEventQueue; private object _forSend; private MemoryStream _fragmentsBuffer; private bool _fragmentsCompressed; private Opcode _fragmentsOpcode; private Func<WebSocketContext, string> _handshakeRequestChecker; private bool _ignoreExtensions; private bool _inContinuation; private volatile bool _inMessage; private volatile Logger _logger; private Action<MessageEventArgs> _message; private Queue<MessageEventArgs> _messageEventQueue; private uint _nonceCount; private string _origin; private bool _preAuth; private string _protocol; private string[] _protocols; private bool _protocolsRequested; private WebSocketSharp.Net.NetworkCredential _proxyCredentials; private Uri _proxyUri; private volatile WebSocketState _readyState; private AutoResetEvent _receivePong; private bool _secure; private ClientSslConfiguration _sslConfig; private Stream _stream; private TcpClient _tcpClient; private Uri _uri; private TimeSpan _waitTime; internal static readonly byte[] EmptyBytes; internal static readonly int FragmentLength; internal static readonly RandomNumberGenerator RandomNumber; internal WebSocketSharp.Net.CookieCollection CookieCollection => _cookies; internal Func<WebSocketContext, string> CustomHandshakeRequestChecker { get { return _handshakeRequestChecker; } set { _handshakeRequestChecker = value; } } internal bool HasMessage { get { lock (_forMessageEventQueue) { return _messageEventQueue.Count > 0; } } } internal bool IgnoreExtensions { get { return _ignoreExtensions; } set { _ignoreExtensions = value; } } internal bool IsConnected => _readyState == WebSocketState.Open || _readyState == WebSocketState.Closing; public CompressionMethod Compression { get { return _compression; } set { lock (_forConn) { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in setting the compression.", null); } else { _compression = value; } } } } public IEnumerable<WebSocketSharp.Net.Cookie> Cookies { get { object syncRoot; object obj = (syncRoot = _cookies.SyncRoot); Monitor.Enter(syncRoot); try { foreach (WebSocketSharp.Net.Cookie cookie in _cookies) { yield return cookie; } } finally { Monitor.Exit(obj); } } } public WebSocketSharp.Net.NetworkCredential Credentials => _credentials; public bool EmitOnPing { get { return _emitOnPing; } set { _emitOnPing = value; } } public bool EnableRedirection { get { return _enableRedirection; } set { lock (_forConn) { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in setting the enable redirection.", null); } else { _enableRedirection = value; } } } } public string Extensions => _extensions ?? string.Empty; public bool IsAlive => Ping(); public bool IsSecure => _secure; public Logger Log { get { return _logger; } internal set { _logger = value; } } public string Origin { get { return _origin; } set { lock (_forConn) { Uri result; if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in setting the origin.", null); } else if (value.IsNullOrEmpty()) { _origin = value; } else if (!Uri.TryCreate(value, UriKind.Absolute, out result) || result.Segments.Length > 1) { _logger.Error("The syntax of an origin must be '<scheme>://<host>[:<port>]'."); error("An error has occurred in setting the origin.", null); } else { _origin = value.TrimEnd(new char[1] { '/' }); } } } } public string Protocol { get { return _protocol ?? string.Empty; } internal set { _protocol = value; } } public WebSocketState ReadyState => _readyState; public ClientSslConfiguration SslConfiguration { get { return _client ? (_sslConfig ?? (_sslConfig = new ClientSslConfiguration(_uri.DnsSafeHost))) : null; } set { lock (_forConn) { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in setting the ssl configuration.", null); } else { _sslConfig = value; } } } } public Uri Url => _client ? _uri : _context.RequestUri; public TimeSpan WaitTime { get { return _waitTime; } set { lock (_forConn) { if (!checkIfAvailable(client: true, server: true, connecting: true, open: false, closing: false, closed: true, out var text) || !value.CheckWaitTime(out text)) { _logger.Error(text); error("An error has occurred in setting the wait time.", null); } else { _waitTime = value; } } } } public event EventHandler<CloseEventArgs> OnClose; public event EventHandler<ErrorEventArgs> OnError; public event EventHandler<MessageEventArgs> OnMessage; public event EventHandler OnOpen; static WebSocket() { EmptyBytes = new byte[0]; FragmentLength = 1016; RandomNumber = new RNGCryptoServiceProvider(); } internal WebSocket(HttpListenerWebSocketContext context, string protocol) { _context = context; _protocol = protocol; _closeContext = context.Close; _logger = context.Log; _message = messages; _secure = context.IsSecureConnection; _stream = context.Stream; _waitTime = TimeSpan.FromSeconds(1.0); init(); } internal WebSocket(TcpListenerWebSocketContext context, string protocol) { _context = context; _protocol = protocol; _closeContext = context.Close; _logger = context.Log; _message = messages; _secure = context.IsSecureConnection; _stream = context.Stream; _waitTime = TimeSpan.FromSeconds(1.0); init(); } public WebSocket(string url, params string[] protocols) { if (url == null) { throw new ArgumentNullException("url"); } if (url.Length == 0) { throw new ArgumentException("An empty string.", "url"); } if (!url.TryCreateWebSocketUri(out _uri, out var text)) { throw new ArgumentException(text, "url"); } if (protocols != null && protocols.Length > 0) { text = protocols.CheckIfValidProtocols(); if (text != null) { throw new ArgumentException(text, "protocols"); } _protocols = protocols; } _base64Key = CreateBase64Key(); _client = true; _logger = new Logger(); _message = messagec; _secure = _uri.Scheme == "wss"; _waitTime = TimeSpan.FromSeconds(5.0); init(); } private bool accept() { lock (_forConn) { if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in accepting.", null); return false; } try { if (!acceptHandshake()) { return false; } _readyState = WebSocketState.Open; } catch (Exception ex) { _logger.Fatal(ex.ToString()); fatal("An exception has occurred while accepting.", ex); return false; } return true; } } private bool acceptHandshake() { _logger.Debug($"A request from {_context.UserEndPoint}:\n{_context}"); if (!checkHandshakeRequest(_context, out var text)) { sendHttpResponse(createHandshakeFailureResponse(WebSocketSharp.Net.HttpStatusCode.BadRequest)); _logger.Fatal(text); fatal("An error has occurred while accepting.", CloseStatusCode.ProtocolError); return false; } if (!customCheckHandshakeRequest(_context, out text)) { sendHttpResponse(createHandshakeFailureResponse(WebSocketSharp.Net.HttpStatusCode.BadRequest)); _logger.Fatal(text); fatal("An error has occurred while accepting.", CloseStatusCode.PolicyViolation); return false; } _base64Key = _context.Headers["Sec-WebSocket-Key"]; if (_protocol != null) { processSecWebSocketProtocolHeader(_context.SecWebSocketProtocols); } if (!_ignoreExtensions) { processSecWebSocketExtensionsClientHeader(_context.Headers["Sec-WebSocket-Extensions"]); } return sendHttpResponse(createHandshakeResponse()); } private bool checkHandshakeRequest(WebSocketContext context, out string message) { message = null; if (context.RequestUri == null) { message = "Specifies an invalid Request-URI."; return false; } if (!context.IsWebSocketRequest) { message = "Not a WebSocket handshake request."; return false; } NameValueCollection headers = context.Headers; if (!validateSecWebSocketKeyHeader(headers["Sec-WebSocket-Key"])) { message = "Includes no Sec-WebSocket-Key header, or it has an invalid value."; return false; } if (!validateSecWebSocketVersionClientHeader(headers["Sec-WebSocket-Version"])) { message = "Includes no Sec-WebSocket-Version header, or it has an invalid value."; return false; } if (!validateSecWebSocketProtocolClientHeader(headers["Sec-WebSocket-Protocol"])) { message = "Includes an invalid Sec-WebSocket-Protocol header."; return false; } if (!_ignoreExtensions && !validateSecWebSocketExtensionsClientHeader(headers["Sec-WebSocket-Extensions"])) { message = "Includes an invalid Sec-WebSocket-Extensions header."; return false; } return true; } private bool checkHandshakeResponse(HttpResponse response, out string message) { message = null; if (response.IsRedirect) { message = "Indicates the redirection."; return false; } if (response.IsUnauthorized) { message = "Requires the authentication."; return false; } if (!response.IsWebSocketResponse) { message = "Not a WebSocket handshake response."; return false; } NameValueCollection headers = response.Headers; if (!validateSecWebSocketAcceptHeader(headers["Sec-WebSocket-Accept"])) { message = "Includes no Sec-WebSocket-Accept header, or it has an invalid value."; return false; } if (!validateSecWebSocketProtocolServerHeader(headers["Sec-WebSocket-Protocol"])) { message = "Includes no Sec-WebSocket-Protocol header, or it has an invalid value."; return false; } if (!validateSecWebSocketExtensionsServerHeader(headers["Sec-WebSocket-Extensions"])) { message = "Includes an invalid Sec-WebSocket-Extensions header."; return false; } if (!validateSecWebSocketVersionServerHeader(headers["Sec-WebSocket-Version"])) { message = "Includes an invalid Sec-WebSocket-Version header."; return false; } return true; } private bool checkIfAvailable(bool connecting, bool open, bool closing, bool closed, out string message) { message = null; if (!connecting && _readyState == WebSocketState.Connecting) { message = "This operation isn't available in: connecting"; return false; } if (!open && _readyState == WebSocketState.Open) { message = "This operation isn't available in: open"; return false; } if (!closing && _readyState == WebSocketState.Closing) { message = "This operation isn't available in: closing"; return false; } if (!closed && _readyState == WebSocketState.Closed) { message = "This operation isn't available in: closed"; return false; } return true; } private bool checkIfAvailable(bool client, bool server, bool connecting, bool open, bool closing, bool closed, out string message) { message = null; if (!client && _client) { message = "This operation isn't available in: client"; return false; } if (!server && !_client) { message = "This operation isn't available in: server"; return false; } return checkIfAvailable(connecting, open, closing, closed, out message); } private bool checkReceivedFrame(WebSocketFrame frame, out string message) { message = null; bool isMasked = frame.IsMasked; if (_client && isMasked) { message = "A frame from the server is masked."; return false; } if (!_client && !isMasked) { message = "A frame from a client isn't masked."; return false; } if (_inContinuation && frame.IsData) { message = "A data frame has been received while receiving continuation frames."; return false; } if (frame.IsCompressed && _compression == CompressionMethod.None) { message = "A compressed frame has been received without any agreement for it."; return false; } if (frame.Rsv2 == Rsv.On) { message = "The RSV2 of a frame is non-zero without any negotiation for it."; return false; } if (frame.Rsv3 == Rsv.On) { message = "The RSV3 of a frame is non-zero without any negotiation for it."; return false; } return true; } private void close(CloseEventArgs e, bool send, bool receive, bool received) { lock (_forConn) { if (_readyState == WebSocketState.Closing) { _logger.Info("The closing is already in progress."); return; } if (_readyState == WebSocketState.Closed) { _logger.Info("The connection has been closed."); return; } send = send && _readyState == WebSocketState.Open; receive = receive && send; _readyState = WebSocketState.Closing; } _logger.Trace("Begin closing the connection."); byte[] frameAsBytes = (send ? WebSocketFrame.CreateCloseFrame(e.PayloadData, _client).ToArray() : null); e.WasClean = closeHandshake(frameAsBytes, receive, received); releaseResources(); _logger.Trace("End closing the connection."); _readyState = WebSocketState.Closed; try { this.OnClose.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.ToString()); error("An exception has occurred during the OnClose event.", ex); } } private void closeAsync(CloseEventArgs e, bool send, bool receive, bool received) { Action<CloseEventArgs, bool, bool, bool> closer = close; closer.BeginInvoke(e, send, receive, received, delegate(IAsyncResult ar) { closer.EndInvoke(ar); }, null); } private bool closeHandshake(byte[] frameAsBytes, bool receive, bool received) { bool flag = frameAsBytes != null && sendBytes(frameAsBytes); received = received || (receive && flag && _exitReceiving != null && _exitReceiving.WaitOne(_waitTime)); bool flag2 = flag && received; _logger.Debug($"Was clean?: {flag2}\n sent: {flag}\n received: {received}"); return flag2; } private bool connect() { lock (_forConn) { if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in connecting.", null); return false; } try { _readyState = WebSocketState.Connecting; if (!doHandshake()) { return false; } _readyState = WebSocketState.Open; } catch (Exception ex) { _logger.Fatal(ex.ToString()); fatal("An exception has occurred while connecting.", ex); return false; } return true; } } private string createExtensions() { StringBuilder stringBuilder = new StringBuilder(80); if (_compression != 0) { string arg = _compression.ToExtensionString("server_no_context_takeover", "client_no_context_takeover"); stringBuilder.AppendFormat("{0}, ", arg); } int length = stringBuilder.Length; if (length > 2) { stringBuilder.Length = length - 2; return stringBuilder.ToString(); } return null; } private HttpResponse createHandshakeFailureResponse(WebSocketSharp.Net.HttpStatusCode code) { HttpResponse httpResponse = HttpResponse.CreateCloseResponse(code); httpResponse.Headers["Sec-WebSocket-Version"] = "13"; return httpResponse; } private HttpRequest createHandshakeRequest() { HttpRequest httpRequest = HttpRequest.CreateWebSocketRequest(_uri); NameValueCollection headers = httpRequest.Headers; if (!_origin.IsNullOrEmpty()) { headers["Origin"] = _origin; } headers["Sec-WebSocket-Key"] = _base64Key; _protocolsRequested = _protocols != null; if (_protocolsRequested) { headers["Sec-WebSocket-Protocol"] = _protocols.ToString(", "); } _extensionsRequested = _compression != CompressionMethod.None; if (_extensionsRequested) { headers["Sec-WebSocket-Extensions"] = createExtensions(); } headers["Sec-WebSocket-Version"] = "13"; AuthenticationResponse authenticationResponse = null; if (_authChallenge != null && _credentials != null) { authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount); _nonceCount = authenticationResponse.NonceCount; } else if (_preAuth) { authenticationResponse = new AuthenticationResponse(_credentials); } if (authenticationResponse != null) { headers["Authorization"] = authenticationResponse.ToString(); } if (_cookies.Count > 0) { httpRequest.SetCookies(_cookies); } return httpRequest; } private HttpResponse createHandshakeResponse() { HttpResponse httpResponse = HttpResponse.CreateWebSocketResponse(); NameValueCollection headers = httpResponse.Headers; headers["Sec-WebSocket-Accept"] = CreateResponseKey(_base64Key); if (_protocol != null) { headers["Sec-WebSocket-Protocol"] = _protocol; } if (_extensions != null) { headers["Sec-WebSocket-Extensions"] = _extensions; } if (_cookies.Count > 0) { httpResponse.SetCookies(_cookies); } return httpResponse; } private bool customCheckHandshakeRequest(WebSocketContext context, out string message) { message = null; return _handshakeRequestChecker == null || (message = _handshakeRequestChecker(context)) == null; } private MessageEventArgs dequeueFromMessageEventQueue() { lock (_forMessageEventQueue) { return (_messageEventQueue.Count > 0) ? _messageEventQueue.Dequeue() : null; } } private bool doHandshake() { setClientStream(); HttpResponse httpResponse = sendHandshakeRequest(); if (!checkHandshakeResponse(httpResponse, out var text)) { _logger.Fatal(text); fatal("An error has occurred while connecting.", CloseStatusCode.ProtocolError); return false; } if (_protocolsRequested) { _protocol = httpResponse.Headers["Sec-WebSocket-Protocol"]; } if (_extensionsRequested) { processSecWebSocketExtensionsServerHeader(httpResponse.Headers["Sec-WebSocket-Extensions"]); } processCookies(httpResponse.Cookies); return true; } private void enqueueToMessageEventQueue(MessageEventArgs e) { lock (_forMessageEventQueue) { _messageEventQueue.Enqueue(e); } } private void error(string message, Exception exception) { try { this.OnError.Emit(this, new ErrorEventArgs(message, exception)); } catch (Exception ex) { _logger.Error(ex.ToString()); } } private void fatal(string message, Exception exception) { CloseStatusCode code = ((exception is WebSocketException) ? ((WebSocketException)exception).Code : CloseStatusCode.Abnormal); fatal(message, code); } private void fatal(string message, CloseStatusCode code) { close(new CloseEventArgs(code, message), !code.IsReserved(), receive: false, received: false); } private void init() { _compression = CompressionMethod.None; _cookies = new WebSocketSharp.Net.CookieCollection(); _forConn = new object(); _forSend = new object(); _messageEventQueue = new Queue<MessageEventArgs>(); _forMessageEventQueue = ((ICollection)_messageEventQueue).SyncRoot; _readyState = WebSocketState.Connecting; } private void message() { MessageEventArgs obj = null; lock (_forMessageEventQueue) { if (_inMessage || _messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { return; } _inMessage = true; obj = _messageEventQueue.Dequeue(); } _message(obj); } private void messagec(MessageEventArgs e) { while (true) { try { this.OnMessage.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.ToString()); error("An exception has occurred during an OnMessage event.", ex); } lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { _inMessage = false; break; } e = _messageEventQueue.Dequeue(); } bool flag = true; } } private void messages(MessageEventArgs e) { try { this.OnMessage.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.ToString()); error("An exception has occurred during an OnMessage event.", ex); } lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { _inMessage = false; return; } e = _messageEventQueue.Dequeue(); } ThreadPool.QueueUserWorkItem(delegate { messages(e); }); } private void open() { _inMessage = true; startReceiving(); try { this.OnOpen.Emit(this, EventArgs.Empty); } catch (Exception ex) { _logger.Error(ex.ToString()); error("An exception has occurred during the OnOpen event.", ex); } MessageEventArgs obj = null; lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { _inMessage = false; return; } obj = _messageEventQueue.Dequeue(); } _message.BeginInvoke(obj, delegate(IAsyncResult ar) { _message.EndInvoke(ar); }, null); } private bool processCloseFrame(WebSocketFrame frame) { PayloadData payloadData = frame.PayloadData; close(new CloseEventArgs(payloadData), !payloadData.IncludesReservedCloseStatusCode, receive: false, received: true); return false; } private void processCookies(WebSocketSharp.Net.CookieCollection cookies) { if (cookies.Count != 0) { _cookies.SetOrRemove(cookies); } } private bool processDataFrame(WebSocketFrame frame) { enqueueToMessageEventQueue(frame.IsCompressed ? new MessageEventArgs(frame.Opcode, frame.PayloadData.ApplicationData.Decompress(_compression)) : new MessageEventArgs(frame)); return true; } private bool processFragmentFrame(WebSocketFrame frame) { if (!_inContinuation) { if (frame.IsContinuation) { return true; } _fragmentsOpcode = frame.Opcode; _fragmentsCompressed = frame.IsCompressed; _fragmentsBuffer = new MemoryStream(); _inContinuation = true; } _fragmentsBuffer.WriteBytes(frame.PayloadData.ApplicationData, 1024); if (frame.IsFinal) { using (_fragmentsBuffer) { byte[] rawData = (_fragmentsCompressed ? _fragmentsBuffer.DecompressToArray(_compression) : _fragmentsBuffer.ToArray()); enqueueToMessageEventQueue(new MessageEventArgs(_fragmentsOpcode, rawData)); } _fragmentsBuffer = null; _inContinuation = false; } return true; } private bool processPingFrame(WebSocketFrame frame) { if (send(new WebSocketFrame(Opcode.Pong, frame.PayloadData, _client).ToArray())) { _logger.Trace("Returned a pong."); } if (_emitOnPing) { enqueueToMessageEventQueue(new MessageEventArgs(frame)); } return true; } private bool processPongFrame(WebSocketFrame frame) { _receivePong.Set(); _logger.Trace("Received a pong."); return true; } private bool processReceivedFrame(WebSocketFrame frame) { if (!checkReceivedFrame(frame, out var text)) { throw new WebSocketException(CloseStatusCode.ProtocolError, text); } frame.Unmask(); return frame.IsFragment ? processFragmentFrame(frame) : (frame.IsData ? processDataFrame(frame) : (frame.IsPing ? processPingFrame(frame) : (frame.IsPong ? processPongFrame(frame) : (frame.IsClose ? processCloseFrame(frame) : processUnsupportedFrame(frame))))); } private void processSecWebSocketExtensionsClientHeader(string value) { if (value == null) { return; } StringBuilder stringBuilder = new StringBuilder(80); bool flag = false; foreach (string item in value.SplitHeaderValue(',')) { string value2 = item.Trim(); if (!flag && value2.IsCompressionExtension(CompressionMethod.Deflate)) { _compression = CompressionMethod.Deflate; stringBuilder.AppendFormat("{0}, ", _compression.ToExtensionString("client_no_context_takeover", "server_no_context_takeover")); flag = true; } } int length = stringBuilder.Length; if (length > 2) { stringBuilder.Length = length - 2; _extensions = stringBuilder.ToString(); } } private void processSecWebSocketExtensionsServerHeader(string value) { if (value == null) { _compression = CompressionMethod.None; } else { _extensions = value; } } private void processSecWebSocketProtocolHeader(IEnumerable<string> values) { if (!values.Contains((string p) => p == _protocol)) { _protocol = null; } } private bool processUnsupportedFrame(WebSocketFrame frame) { _logger.Fatal("An unsupported frame:" + frame.PrintToString(dumped: false)); fatal("There is no way to handle it.", CloseStatusCode.PolicyViolation); return false; } private void releaseClientResources() { if (_stream != null) { _stream.Dispose(); _stream = null; } if (_tcpClient != null) { _tcpClient.Close(); _tcpClient = null; } } private void releaseCommonResources() { if (_fragmentsBuffer != null) { _fragmentsBuffer.Dispose(); _fragmentsBuffer = null; _inContinuation = false; } if (_receivePong != null) { _receivePong.Close(); _receivePong = null; } if (_exitReceiving != null) { _exitReceiving.Close(); _exitReceiving = null; } } private void releaseResources() { if (_client) { releaseClientResources(); } else { releaseServerResources(); } releaseCommonResources(); } private void releaseServerResources() { if (_closeContext != null) { _closeContext(); _closeContext = null; _stream = null; _context = null; } } private bool send(byte[] frameAsBytes) { lock (_forConn) { if (_readyState != WebSocketState.Open) { _logger.Error("The sending has been interrupted."); return false; } return sendBytes(frameAsBytes); } } private bool send(Opcode opcode, Stream stream) { lock (_forSend) { Stream stream2 = stream; bool flag = false; bool flag2 = false; try { if (_compression != 0) { stream = stream.Compress(_compression); flag = true; } flag2 = send(opcode, stream, flag); if (!flag2) { error("The sending has been interrupted.", null); } } catch (Exception ex) { _logger.Error(ex.ToString()); error("An exception has occurred while sending data.", ex); } finally { if (flag) { stream.Dispose(); } stream2.Dispose(); } return flag2; } } private bool send(Opcode opcode, Stream stream, bool compressed) { long length = stream.Length; if (length == 0) { return send(Fin.Final, opcode, EmptyBytes, compressed); } long num = length / FragmentLength; int num2 = (int)(length % FragmentLength); byte[] array = null; if (num == 0) { array = new byte[num2]; return stream.Read(array, 0, num2) == num2 && send(Fin.Final, opcode, array, compressed); } array = new byte[FragmentLength]; if (num == 1 && num2 == 0) { return stream.Read(array, 0, FragmentLength) == FragmentLength && send(Fin.Final, opcode, array, compressed); } if (stream.Read(array, 0, FragmentLength) != FragmentLength || !send(Fin.More, opcode, array, compressed)) { return false; } long num3 = ((num2 == 0) ? (num - 2) : (num - 1)); for (long num4 = 0L; num4 < num3; num4++) { if (stream.Read(array, 0, FragmentLength) != FragmentLength || !send(Fin.More, Opcode.Cont, array, compressed)) { return false; } } if (num2 == 0) { num2 = FragmentLength; } else { array = new byte[num2]; } return stream.Read(array, 0, num2) == num2 && send(Fin.Final, Opcode.Cont, array, compressed); } private bool send(Fin fin, Opcode opcode, byte[] data, bool compressed) { lock (_forConn) { if (_readyState != WebSocketState.Open) { _logger.Error("The sending has been interrupted."); return false; } return sendBytes(new WebSocketFrame(fin, opcode, data, compressed, _client).ToArray()); } } private void sendAsync(Opcode opcode, Stream stream, Action<bool> completed) { Func<Opcode, Stream, bool> sender = send; sender.BeginInvoke(opcode, stream, delegate(IAsyncResult ar) { try { bool obj = sender.EndInvoke(ar); if (completed != null) { completed(obj); } } catch (Exception ex) { _logger.Error(ex.ToString()); error("An exception has occurred during a send callback.", ex); } }, null); } private bool sendBytes(byte[] bytes) { try { _stream.Write(bytes, 0, bytes.Length); return true; } catch (Exception ex) { _logger.Error(ex.ToString()); return false; } } private HttpResponse sendHandshakeRequest() { HttpRequest httpRequest = createHandshakeRequest(); HttpResponse httpResponse = sendHttpRequest(httpRequest, 90000); if (httpResponse.IsUnauthorized) { string text = httpResponse.Headers["WWW-Authenticate"]; _logger.Warn($"Received an authentication requirement for '{text}'."); if (text.IsNullOrEmpty()) { _logger.Error("No authentication challenge is specified."); return httpResponse; } _authChallenge = AuthenticationChallenge.Parse(text); if (_authChallenge == null) { _logger.Error("An invalid authentication challenge is specified."); return httpResponse; } if (_credentials != null && (!_preAuth || _authChallenge.Scheme == WebSocketSharp.Net.AuthenticationSchemes.Digest)) { if (httpResponse.HasConnectionClose) { releaseClientResources(); setClientStream(); } AuthenticationResponse authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount); _nonceCount = authenticationResponse.NonceCount; httpRequest.Headers["Authorization"] = authenticationResponse.ToString(); httpResponse = sendHttpRequest(httpRequest, 15000); } } if (httpResponse.IsRedirect) { string text2 = httpResponse.Headers["Location"]; _logger.Warn($"Received a redirection to '{text2}'."); if (_enableRedirection) { if (text2.IsNullOrEmpty()) { _logger.Error("No url to redirect is located."); return httpResponse; } if (!text2.TryCreateWebSocketUri(out var result, out var text3)) { _logger.Error("An invalid url to redirect is located: " + text3); return httpResponse; } releaseClientResources(); _uri = result; _secure = result.Scheme == "wss"; setClientStream(); return sendHandshakeRequest(); } } return httpResponse; } private HttpResponse sendHttpRequest(HttpRequest request, int millisecondsTimeout) { _logger.Debug("A request to the server:\n" + request.ToString()); HttpResponse response = request.GetResponse(_stream, millisecondsTimeout); _logger.Debug("A response to this request:\n" + response.ToString()); return response; } private bool sendHttpResponse(HttpResponse response) { _logger.Debug("A response to this request:\n" + response.ToString()); return sendBytes(response.ToByteArray()); } private void sendProxyConnectRequest() { HttpRequest httpRequest = HttpRequest.CreateConnectRequest(_uri); HttpResponse httpResponse = sendHttpRequest(httpRequest, 90000); if (httpResponse.IsProxyAuthenticationRequired) { string text = httpResponse.Headers["Proxy-Authenticate"]; _logger.Warn($"Received a proxy authentication requirement for '{text}'."); if (text.IsNullOrEmpty()) { throw new WebSocketException("No proxy authentication challenge is specified."); } AuthenticationChallenge authenticationChallenge = AuthenticationChallenge.Parse(text); if (authenticationChallenge == null) { throw new WebSocketException("An invalid proxy authentication challenge is specified."); } if (_proxyCredentials != null) { if (httpResponse.HasConnectionClose) { releaseClientResources(); _tcpClient = new TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port); _stream = _tcpClient.GetStream(); } AuthenticationResponse authenticationResponse = new AuthenticationResponse(authenticationChallenge, _proxyCredentials, 0u); httpRequest.Headers["Proxy-Authorization"] = authenticationResponse.ToString(); httpResponse = sendHttpRequest(httpRequest, 15000); } if (httpResponse.IsProxyAuthenticationRequired) { throw new WebSocketException("A proxy authentication is required."); } } if (httpResponse.StatusCode[0] != '2') { throw new WebSocketException("The proxy has failed a connection to the requested host and port."); } } private void setClientStream() { if (_proxyUri != null) { _tcpClient = new TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port); _stream = _tcpClient.GetStream(); sendProxyConnectRequest(); } else { _tcpClient = new TcpClient(_uri.DnsSafeHost, _uri.Port); _stream = _tcpClient.GetStream(); } if (_secure) { ClientSslConfiguration sslConfiguration = SslConfiguration; string targetHost = sslConfiguration.TargetHost; if (targetHost != _uri.DnsSafeHost) { throw new WebSocketException(CloseStatusCode.TlsHandshakeFailure, "An invalid host name is specified."); } try { SslStream sslStream = new SslStream(_stream, leaveInnerStreamOpen: false, sslConfiguration.ServerCertificateValidationCallback, sslConfiguration.ClientCertificateSelectionCallback); sslStream.AuthenticateAsClient(targetHost, sslConfiguration.ClientCertificates, sslConfiguration.EnabledSslProtocols, sslConfiguration.CheckCertificateRevocation); _stream = sslStream; } catch (Exception innerException) { throw new WebSocketException(CloseStatusCode.TlsHandshakeFailure, innerException); } } } private void startReceiving() { if (_messageEventQueue.Count > 0) { _messageEventQueue.Clear(); } _exitReceiving = new AutoResetEvent(initialState: false); _receivePong = new AutoResetEvent(initialState: false); Action receive = null; receive = delegate { WebSocketFrame.ReadFrameAsync(_stream, unmask: false, delegate(WebSocketFrame frame) { if (!processReceivedFrame(frame) || _readyState == WebSocketState.Closed) { _exitReceiving?.Set(); } else { receive(); if (!_inMessage && HasMessage && _readyState == WebSocketState.Open) { message(); } } }, delegate(Exception ex) { _logger.Fatal(ex.ToString()); fatal("An exception has occurred while receiving.", ex); }); }; receive(); } private bool validateSecWebSocketAcceptHeader(string value) { return value != null && value == CreateResponseKey(_base64Key); } private bool validateSecWebSocketExtensionsClientHeader(string value) { return value == null || value.Length > 0; } private bool validateSecWebSocketExtensionsServerHeader(string value) { if (value == null) { return true; } if (value.Length == 0) { return false; } if (!_extensionsRequested) { return false; } bool flag = _compression != CompressionMethod.None; foreach (string item in value.SplitHeaderValue(',')) { string text = item.Trim(); if (flag && text.IsCompressionExtension(_compression)) { if (!text.Contains("server_no_context_takeover")) { _logger.Error("The server hasn't sent back 'server_no_context_takeover'."); return false; } if (!text.Contains("client_no_context_takeover")) { _logger.Warn("The server hasn't sent back 'client_no_context_takeover'."); } string method = _compression.ToExtensionString(); if (text.SplitHeaderValue(';').Contains(delegate(string t) { t = t.Trim(); return t != method && t != "server_no_context_takeover" && t != "client_no_context_takeover"; })) { return false; } continue; } return false; } return true; } private bool validateSecWebSocketKeyHeader(string value) { return value != null && value.Length > 0; } private bool validateSecWebSocketProtocolClientHeader(string value) { return value == null || value.Length > 0; } private bool validateSecWebSocketProtocolServerHeader(string value) { if (value == null) { return !_protocolsRequested; } if (value.Length == 0) { return false; } return _protocolsRequested && _protocols.Contains((string p) => p == value); } private bool validateSecWebSocketVersionClientHeader(string value) { return value != null && value == "13"; } private bool validateSecWebSocketVersionServerHeader(string value) { return value == null || value == "13"; } internal static string CheckCloseParameters(ushort code, string reason, bool client) { return (!code.IsCloseStatusCode()) ? "An invalid close status code." : ((code != 1005) ? ((code == 1010 && !client) ? "MandatoryExtension cannot be used by a server." : ((code == 1011 && client) ? "ServerError cannot be used by a client." : ((!reason.IsNullOrEmpty() && reason.UTF8Encode().Length > 123) ? "A reason has greater than the allowable max size." : null))) : ((!reason.IsNullOrEmpty()) ? "NoStatus cannot have a reason." : null)); } internal static string CheckCloseParameters(CloseStatusCode code, string reason, bool client) { return (code != CloseStatusCode.NoStatus) ? ((code == CloseStatusCode.MandatoryExtension && !client) ? "MandatoryExtension cannot be used by a server." : ((code == CloseStatusCode.ServerError && client) ? "ServerError cannot be used by a client." : ((!reason.IsNullOrEmpty() && reason.UTF8Encode().Length > 123) ? "A reason has greater than the allowable max size." : null))) : ((!reason.IsNullOrEmpty()) ? "NoStatus cannot have a reason." : null); } internal static string CheckPingParameter(string message, out byte[] bytes) { bytes = message.UTF8Encode(); return (bytes.Length > 125) ? "A message has greater than the allowable max size." : null; } internal static string CheckSendParameter(byte[] data) { return (data == null) ? "'data' is null." : null; } internal static string CheckSendParameter(FileInfo file) { return (file == null) ? "'file' is null." : null; } internal static string CheckSendParameter(string data) { return (data == null) ? "'data' is null." : null; } internal static string CheckSendParameters(Stream stream, int length) { return (stream == null) ? "'stream' is null." : ((!stream.CanRead) ? "'stream' cannot be read." : ((length < 1) ? "'length' is less than 1." : null)); } internal void Close(HttpResponse response) { _readyState = WebSocketState.Closing; sendHttpResponse(response); releaseServerResources(); _readyState = WebSocketState.Closed; } internal void Close(WebSocketSharp.Net.HttpStatusCode code) { Close(createHandshakeFailureResponse(code)); } internal void Close(CloseEventArgs e, byte[] frameAsBytes, bool receive) { lock (_forConn) { if (_readyState == WebSocketState.Closing) { _logger.Info("The closing is already in progress."); return; } if (_readyState == WebSocketState.Closed) { _logger.Info("The connection has been closed."); return; } _readyState = WebSocketState.Closing; } e.WasClean = closeHandshake(frameAsBytes, receive, received: false); releaseServerResources(); releaseCommonResources(); _readyState = WebSocketState.Closed; try { this.OnClose.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.ToString()); } } internal static string CreateBase64Key() { byte[] array = new byte[16]; RandomNumber.GetBytes(array); return Convert.ToBase64String(array); } internal static string CreateResponseKey(string base64Key) { StringBuilder stringBuilder = new StringBuilder(base64Key, 64); stringBuilder.Append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); SHA1 sHA = new SHA1CryptoServiceProvider(); byte[] inArray = sHA.ComputeHash(stringBuilder.ToString().UTF8Encode()); return Convert.ToBase64String(inArray); } internal void InternalAccept() { try { if (!acceptHandshake()) { return; } _readyState = WebSocketState.Open; } catch (Exception ex) { _logger.Fatal(ex.ToString()); fatal("An exception has occurred while accepting.", ex); return; } open(); } internal bool Ping(byte[] frameAsBytes, TimeSpan timeout) { if (_readyState != WebSocketState.Open) { return false; } if (!send(frameAsBytes)) { return false; } return _receivePong?.WaitOne(timeout) ?? false; } internal void Send(Opcode opcode, byte[] data, Dictionary<CompressionMethod, byte[]> cache) { lock (_forSend) { lock (_forConn) { if (_readyState != WebSocketState.Open) { _logger.Error("The sending has been interrupted."); return; } try { if (!cache.TryGetValue(_compression, out var value)) { value = new WebSocketFrame(Fin.Final, opcode, data.Compress(_compression), _compression != CompressionMethod.None, mask: false).ToArray(); cache.Add(_compression, value); } sendBytes(value); } catch (Exception ex) { _logger.Error(ex.ToString()); } } } } internal void Send(Opcode opcode, Stream stream, Dictionary<CompressionMethod, Stream> cache) { lock (_forSend) { try { if (!cache.TryGetValue(_compression, out var value)) { value = stream.Compress(_compression); cache.Add(_compression, value); } else { value.Position = 0L; } send(opcode, value, _compression != CompressionMethod.None); } catch (Exception ex) { _logger.Error(ex.ToString()); } } } public void Accept() { if (!checkIfAvailable(client: false, server: true, connecting: true, open: false, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in accepting.", null); } else if (accept()) { open(); } } public void AcceptAsync() { if (!checkIfAvailable(client: false, server: true, connecting: true, open: false, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in accepting.", null); return; } Func<bool> acceptor = accept; acceptor.BeginInvoke(delegate(IAsyncResult ar) { if (acceptor.EndInvoke(ar)) { open(); } }, null); } public void Close() { if (!checkIfAvailable(connecting: true, open: true, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else { close(new CloseEventArgs(), send: true, receive: true, received: false); } } public void Close(ushort code) { string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, null, _client); if (text != null) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (code == 1005) { close(new CloseEventArgs(), send: true, receive: true, received: false); } else { bool receive = !code.IsReserved(); close(new CloseEventArgs(code), receive, receive, received: false); } } public void Close(CloseStatusCode code) { string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, null, _client); if (text != null) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (code == CloseStatusCode.NoStatus) { close(new CloseEventArgs(), send: true, receive: true, received: false); } else { bool receive = !code.IsReserved(); close(new CloseEventArgs(code), receive, receive, received: false); } } public void Close(ushort code, string reason) { string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, reason, _client); if (text != null) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (code == 1005) { close(new CloseEventArgs(), send: true, receive: true, received: false); } else { bool receive = !code.IsReserved(); close(new CloseEventArgs(code, reason), receive, receive, received: false); } } public void Close(CloseStatusCode code, string reason) { string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, reason, _client); if (text != null) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (code == CloseStatusCode.NoStatus) { close(new CloseEventArgs(), send: true, receive: true, received: false); } else { bool receive = !code.IsReserved(); close(new CloseEventArgs(code, reason), receive, receive, received: false); } } public void CloseAsync() { if (!checkIfAvailable(connecting: true, open: true, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else { closeAsync(new CloseEventArgs(), send: true, receive: true, received: false); } } public void CloseAsync(ushort code) { string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, null, _client); if (text != null) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (code == 1005) { closeAsync(new CloseEventArgs(), send: true, receive: true, received: false); } else { bool receive = !code.IsReserved(); closeAsync(new CloseEventArgs(code), receive, receive, received: false); } } public void CloseAsync(CloseStatusCode code) { string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, null, _client); if (text != null) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (code == CloseStatusCode.NoStatus) { closeAsync(new CloseEventArgs(), send: true, receive: true, received: false); } else { bool receive = !code.IsReserved(); closeAsync(new CloseEventArgs(code), receive, receive, received: false); } } public void CloseAsync(ushort code, string reason) { string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, reason, _client); if (text != null) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (code == 1005) { closeAsync(new CloseEventArgs(), send: true, receive: true, received: false); } else { bool receive = !code.IsReserved(); closeAsync(new CloseEventArgs(code, reason), receive, receive, received: false); } } public void CloseAsync(CloseStatusCode code, string reason) { string text = _readyState.CheckIfAvailable(connecting: true, open: true, closing: false, closed: false) ?? CheckCloseParameters(code, reason, _client); if (text != null) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (code == CloseStatusCode.NoStatus) { closeAsync(new CloseEventArgs(), send: true, receive: true, received: false); } else { bool receive = !code.IsReserved(); closeAsync(new CloseEventArgs(code, reason), receive, receive, received: false); } } public void Connect() { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in connecting.", null); } else if (connect()) { open(); } } public void ConnectAsync() { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in connecting.", null); return; } Func<bool> connector = connect; connector.BeginInvoke(delegate(IAsyncResult ar) { if (connector.EndInvoke(ar)) { open(); } }, null); } public bool Ping() { byte[] frameAsBytes = (_client ? WebSocketFrame.CreatePingFrame(mask: true).ToArray() : WebSocketFrame.EmptyPingBytes); return Ping(frameAsBytes, _waitTime); } public bool Ping(string message) { if (message == null || message.Length == 0) { return Ping(); } byte[] bytes; string text = CheckPingParameter(message, out bytes); if (text != null) { _logger.Error(text); error("An error has occurred in sending a ping.", null); return false; } return Ping(WebSocketFrame.CreatePingFrame(bytes, _client).ToArray(), _waitTime); } public void Send(byte[] data) { string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(data); if (text != null) { _logger.Error(text); error("An error has occurred in sending data.", null); } else { send(Opcode.Binary, new MemoryStream(data)); } } public void Send(FileInfo file) { string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(file); if (text != null) { _logger.Error(text); error("An error has occurred in sending data.", null); } else { send(Opcode.Binary, file.OpenRead()); } } public void Send(string data) { string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(data); if (text != null) { _logger.Error(text); error("An error has occurred in sending data.", null); } else { send(Opcode.Text, new MemoryStream(data.UTF8Encode())); } } public void SendAsync(byte[] data, Action<bool> completed) { string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(data); if (text != null) { _logger.Error(text); error("An error has occurred in sending data.", null); } else { sendAsync(Opcode.Binary, new MemoryStream(data), completed); } } public void SendAsync(FileInfo file, Action<bool> completed) { string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(file); if (text != null) { _logger.Error(text); error("An error has occurred in sending data.", null); } else { sendAsync(Opcode.Binary, file.OpenRead(), completed); } } public void SendAsync(string data, Action<bool> completed) { string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(data); if (text != null) { _logger.Error(text); error("An error has occurred in sending data.", null); } else { sendAsync(Opcode.Text, new MemoryStream(data.UTF8Encode()), completed); } } public void SendAsync(Stream stream, int length, Action<bool> completed) { string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameters(stream, length); if (text != null) { _logger.Error(text); error("An error has occurred in sending data.", null); return; } stream.ReadBytesAsync(length, delegate(byte[] data) { int num = data.Length; if (num == 0) { _logger.Error("The data cannot be read from 'stream'."); error("An error has occurred in sending data.", null); } else { if (num < length) { _logger.Warn($"The length of the data is less than 'length':\n expected: {length}\n actual: {num}"); } bool obj = send(Opcode.Binary, new MemoryStream(data)); if (completed != null) { completed(obj); } } }, delegate(Exception ex) { _logger.Error(ex.ToString()); error("An exception has occurred while sending data.", ex); }); } public void SetCookie(WebSocketSharp.Net.Cookie cookie) { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in setting a cookie.", null); return; } lock (_forConn) { if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: true, out text)) { _logger.Error(text); error("An error has occurred in setting a cookie.", null); return; } if (cookie == null) { _logger.Error("'cookie' is null."); error("An error has occurred in setting a cookie.", null); return; } lock (_cookies.SyncRoot) { _cookies.SetOrRemove(cookie); } } } public void SetCredentials(string username, string password, bool preAuth) { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in setting the credentials.", null); return; } lock (_forConn) { if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: true, out text)) { _logger.Error(text); error("An error has occurred in setting the credentials.", null); } else if (username.IsNullOrEmpty()) { _logger.Warn("The credentials are set back to the default."); _credentials = null; _preAuth = false; } else if (Ext.Contains(username, ':') || !username.IsText()) { _logger.Error("'username' contains an invalid character."); error("An error has occurred in setting the credentials.", null); } else if (!password.IsNullOrEmpty() && !password.IsText()) { _logger.Error("'password' contains an invalid character."); error("An error has occurred in setting the credentials.", null); } else { _credentials = new WebSocketSharp.Net.NetworkCredential(username, password, _uri.PathAndQuery); _preAuth = preAuth; } } } public void SetProxy(string url, string username, string password) { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in setting the proxy.", null); return; } lock (_forConn) { Uri result; if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: true, out text)) { _logger.Error(text); error("An error has occurred in setting the proxy.", null); } else if (url.IsNullOrEmpty()) { _logger.Warn("The proxy url and credentials are set back to the default."); _proxyUri = null; _proxyCredentials = null; } else if (!Uri.TryCreate(url, UriKind.Absolute, out result) || result.Scheme != "http" || result.Segments.Length > 1) { _logger.Error("The syntax of a proxy url must be 'http://<host>[:<port>]'."); error("An error has occurred in setting the proxy.", null); } else if (username.IsNullOrEmpty()) { _logger.Warn("The proxy credentials are set back to the default."); _proxyUri = result; _proxyCredentials = null; } else if (Ext.Contains(username, ':') || !username.IsText()) { _logger.Error("'username' contains an invalid character."); error("An error has occurred in setting the proxy.", null); } else if (!password.IsNullOrEmpty() && !password.IsText()) { _logger.Error("'password' contains an invalid character."); error("An error has occurred in setting the proxy.", null); } else { _proxyUri = result; _proxyCredentials = new WebSocketSharp.Net.NetworkCredential(username, password, $"{_uri.DnsSafeHost}:{_uri.Port}"); } } } void IDisposable.Dispose() { close(new CloseEventArgs(CloseStatusCode.Away), send: true, receive: true, received: false); } } } namespace WebSocketSharp.Server { public class WebSocketServer { private IPAddress _address; private WebSocketSharp.Net.AuthenticationSchemes _authSchemes; private static readonly string _defaultRealm; private bool _dnsStyle; private string _hostname; private TcpListener _listener; private Logger _logger; private int _port; private string _realm; private Thread _receiveThread; private bool _reuseAddress; private bool _secure; private WebSocketServiceManager _services; private ServerSslConfiguration _sslConfig; private volatile ServerState _state; private object _sync; private Func<IIdentity, WebSocketSharp.Net.NetworkCredential> _userCredFinder; public IPAddress Address => _address; public WebSocketSharp.Net.AuthenticationSchemes AuthenticationSchemes { get { return _authSchemes; } set { string text = _state.CheckIfAvailable(ready: true, start: false, shutting: false); if (text != null) { _logger.Error(text); } else { _authSchemes = value; } } } public bool IsListening => _state == ServerState.Start; public bool IsSecure => _secure; public bool KeepClean { get { return _services.KeepClean; } set { string text = _state.CheckIfAvailable(ready: true, start: false, shutting: false); if (text != null) { _logger.Error(text); } else { _services.KeepClean = value; } } } public Logger Log => _logger; public int Port => _port; public string Realm { get { return _realm; } set { string text = _state.CheckIfAvailable(ready: true, start: false, shutting: false); if (text != null) { _logger.Error(text); } else { _realm = value; } } } public bool ReuseAddress { get { return _reuseAddress; } set { string text = _state.CheckIfAvailable(ready: true, start: false, shutting: false); if (text != null) { _logger.Error(text); } else { _reuseAddress = value; } } } public ServerSslConfiguration SslConfiguration { get { return _sslConfig ?? (_sslConfig = new ServerSslConfiguration(null)); } set { string text = _state.CheckIfAvailable(ready: true, start: false, shutting: false); if (text != null) { _logger.Error(text); } else { _sslConfig = value; } } } public Func<IIdentity, WebSocketSharp.Net.NetworkCredential> UserCredentialsFinder { get { return _userCredFinder; } set { string text = _state.CheckIfAvailable(ready: true, start: false, shutting: false); if (text != null) { _logger.Error(text); } else { _userCredFinder = value; } } } public TimeSpan WaitTime { get { return _services.WaitTime; } set { string text = _state.CheckIfAvailable(ready: true, start: false, shutting: false) ?? value.CheckIfValidWaitTime(); if (text != null) { _logger.Error(text); } else { _services.WaitTime = value; } } } public WebSocketServiceManager WebSocketServices => _services; static WebSocketServer() { _defaultRealm = "SECRET AREA"; } public WebSocketServer() { init(null, IPAddress.Any, 80, secure: false); } public WebSocketServer(int port) : this(port, port == 443) { } public WebSocketServer(string url) { if (url == null) { throw new ArgumentNullException("url"); } if (url.Length == 0) { throw new ArgumentException("An empty string.", "url"); } if (!tryCreateUri(url, out var result, out var message)) { throw new ArgumentException(message, "url"); } string dnsSafeHost = result.DnsSafeHost; IPAddress address = dnsSafeHost.ToIPAddress(); if (!address.IsLocal()) { throw new ArgumentException("The host part isn't a local host name: " + url, "url"); } init(dnsSafeHost, address, result.Port, result.Scheme == "wss"); } public WebSocketServer(int port, bool secure) { if (!port.IsPortNumber()) { throw new ArgumentOutOfRangeException("port", "Not between 1 and 65535 inclusive: " + port); } init(null, IPAddress.Any, port, secure); } public WebSocketServer(IPAddress address, int port) : this(address, port, port == 443) { } public WebSocketServer(IPAddress address, int port, bool secure) { if (address == null) { throw new ArgumentNullException("address"); } if (!address.IsLocal()) { throw new ArgumentException("Not a local IP address: " + address, "address"); } if (!port.IsPortNumber()) { throw new ArgumentOutOfRangeException("port", "Not between 1 and 65535 inclusive: " + port); } init(null, address, port, secure); } private void abort() { lock (_sync) { if (!IsListening) { return; } _state = ServerState.ShuttingDown; } _listener.Stop(); _services.Stop(new CloseEventArgs(CloseStatusCode.ServerError), send: true, receive: false); _state = ServerState.Stop; } private string checkIfCertificateExists() { return (_secure && (_sslConfig == null || _sslConfig.ServerCertificate == null)) ? "The secure connection requires a server certificate." : null; } private string getRealm() { string realm = _realm; return (realm != null && realm.Length > 0) ? realm : _defaultRealm; } private void init(string hostname, IPAddress address, int port, bool secure) { _hostname = hostname ?? address.ToString(); _address = address; _port = port; _secure = se
plugins/ChaosTricks/WebSocketIO.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using EventsIO; using EventsIO.Interfaces; using ModHelper; using ModHelper.Interfaces; using WebSocketIO.Data; using WebSocketSharp; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("WebSocketIO")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("BFT")] [assembly: AssemblyProduct("WebSocketIO")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("27b98c5b-ac6a-4518-ae12-3c9957b291e4")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.0.0")] namespace WebSocketIO { public class ChaosWebSocketHandler { public const string TypeEventMessage = "event"; public const string TypeConfigMessage = "config"; public bool isEnableDebugLog = true; public bool isEnableDebugLogOnClose; public bool isEnableDebugLogOnOpen; public bool isEnableDebugLogOnCloseValidConnect = true; protected bool isNeedLogOnCloseValidConnect; protected ILogger logger; public Action<string, string> OnCustomMessage { get; set; } public Action<string> OnEventMessage { get; set; } public Action<string> OnConfigMessage { get; set; } public Action OnWebSocketOpen { get; set; } public Action<CloseEventArgs> OnWebSocketClose { get; set; } public Action<ErrorEventArgs> OnWebSocketError { get; set; } public ChaosWebSocketHandler(ILogger logger = null) { this.logger = logger; } protected void DebugWebSocketLog(string s) { if (isEnableDebugLog && logger != null) { logger.LogInfo((object)("[DEBUG] ChaosTricks WebSocketHandler: " + s)); } } protected void DebugWebSocketLogError(string s) { if (isEnableDebugLog && logger != null) { logger.LogError((object)("[DEBUG] ChaosTricks WebSocketHandler: " + s)); } } public void OnOpen() { if (isEnableDebugLogOnOpen) { DebugWebSocketLog("OnOpen"); } try { if (isEnableDebugLogOnCloseValidConnect) { isNeedLogOnCloseValidConnect = true; } OnWebSocketOpen?.Invoke(); } catch (Exception arg) { if (isEnableDebugLogOnOpen) { DebugWebSocketLogError($"OnOpen {arg}"); } } } public void OnClose(CloseEventArgs e) { if (isEnableDebugLogOnClose) { DebugWebSocketLog("OnClose " + e.Reason); } try { OnWebSocketClose?.Invoke(e); } catch (Exception arg) { if (isEnableDebugLogOnClose) { DebugWebSocketLogError($"OnClose {arg}"); } else if (isEnableDebugLogOnCloseValidConnect && isNeedLogOnCloseValidConnect) { isNeedLogOnCloseValidConnect = false; DebugWebSocketLogError($"OnClose {arg}"); } } } public void OnError(ErrorEventArgs e) { DebugWebSocketLogError("Error " + e.Message); try { OnWebSocketError?.Invoke(e); } catch (Exception arg) { DebugWebSocketLogError($"OnError inner error {arg}"); } } public WebSocketMessage ParseWebSocketMessage(string data) { try { return UtilityJson.Generate((IDebugLogger)null).FromString<WebSocketMessage>(data) ?? new WebSocketMessage(); } catch (Exception arg) { DebugWebSocketLogError($"ParseWebSocketMessage {arg}"); return new WebSocketMessage(); } } public void OnMessage(MessageEventArgs e) { if (!e.IsText) { return; } try { WebSocketMessage webSocketMessage = ParseWebSocketMessage(e.Data); string type = webSocketMessage.type; string data = webSocketMessage.data; if (!(type == "config")) { if (type == "event") { DebugWebSocketLog("OnMessage - event"); OnEventMessage?.Invoke(data); } else { DebugWebSocketLog("OnMessage - custom msg"); OnCustomMessage?.Invoke(type, data); } } else { DebugWebSocketLog("OnMessage - config"); OnConfigMessage?.Invoke(data); } } catch (Exception arg) { DebugWebSocketLogError($"OnMessage {arg}"); } } } public class WebSocketEventsReader<T> : EventsReaderOnFrame, IDisposable where T : class { protected object locker = new object(); protected List<string> eventListFromSocket = new List<string>(); protected bool isDisposed; protected bool isSocketMessageProcessing; public bool isAutoRequestSettingsOnOpen = true; public bool isAutoConnectOnRead = true; public const int DEFAULT_PORT = 13715; public float autoConnectOnReadPeriod = 8f; protected float autoConnectOnReadPeriodTicks; protected bool isNeedLogOnClose; public virtual ChaosWebSocketHandler SocketHandler { get; set; } public virtual WebSocket Socket { get; set; } public virtual T Settings { get; protected set; } public Action<MessageEventArgs> OnMessage { get; set; } public Action OnOpen { get; set; } public Action<CloseEventArgs> OnCloseOnlyAfterConnect { get; set; } public Action<ErrorEventArgs> OnErrorOnlyAfterConnect { get; set; } public Action<CloseEventArgs> OnClose { get; set; } public Action<ErrorEventArgs> OnError { get; set; } public WebSocketEventsReader(Action<IEventsData> processEvent, IEventsDataParser parser, Action<string> log = null, Action<string> errorLog = null, float checkPeriod = 2f, float delay = 1f, float initDelay = 0.5f) : base("", processEvent, parser, log, errorLog, checkPeriod, delay, initDelay) { } public virtual int GetPortFromSettingsOrDefault(string settingsDir) { try { string path = Path.Combine(settingsDir, "ChaosWebSocketConfig.txt"); if (File.Exists(path)) { return int.Parse(File.ReadAllLines(path)[0]); } } catch (Exception arg) { ((EventsReader)this).ReaderLogError($"GetPortFromSettingsOrDefault error: {arg}. (will be used {13715})"); } return 13715; } public virtual T ParseSettings(string data) { try { T result = UtilityJson.Generate((IDebugLogger)null).FromString<T>(data); ((EventsReader)this).ReaderLog("settings parsing completed: " + data); return result; } catch (Exception arg) { ((EventsReader)this).ReaderLogError($"error: {arg}.\nCan't parse settings. Using standard."); } T result2 = null; try { result2 = Activator.CreateInstance<T>(); return result2; } catch (Exception arg2) { ((EventsReader)this).ReaderLogError($"error: {arg2}.\nCan't create default data class."); return result2; } } public virtual void OpenSocket(bool isLogOnError = true) { try { WebSocket socket = Socket; if (socket != null && !socket.IsAlive) { ((EventsReader)this).ReaderLog("try to open socket connection"); socket.ConnectAsync(); } } catch (Exception arg) { if (isLogOnError) { ((EventsReader)this).ReaderLogError($"OpenSocket error: {arg}"); } } } public virtual void CloseSocket() { try { WebSocket socket = Socket; if (socket != null) { socket.Close(); } } catch (Exception arg) { ((EventsReader)this).ReaderLogError($"CloseSocket error: {arg}"); } } public virtual void RequestSettings() { try { WebSocket socket = Socket; if (socket != null) { socket.Send(new WebSocketMessage("config", "").ToString()); } } catch (Exception arg) { ((EventsReader)this).ReaderLogError($"RequestSettings error: {arg}"); } } public virtual void InitDefaultSocket(string settingsDir, string room, int port, string ip = "127.0.0.1") { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown WebSocket val = new WebSocket($"ws://{ip}:{port}/{room}", new string[0]); ChaosWebSocketHandler socketHandler = new ChaosWebSocketHandler { OnEventMessage = delegate(string data) { isSocketMessageProcessing = true; lock (locker) { eventListFromSocket.Add(data); } isSocketMessageProcessing = false; }, OnConfigMessage = delegate(string data) { Settings = ParseSettings(data); }, OnWebSocketOpen = delegate { isNeedLogOnClose = true; ((EventsReader)this).ReaderLog("ChaosTricks connected"); if (isAutoRequestSettingsOnOpen) { RequestSettings(); } try { OnOpen?.Invoke(); } catch (Exception arg6) { ((EventsReader)this).ReaderLogError($"ChaosTricks custom OnOpen error: {arg6}"); } }, OnWebSocketClose = delegate(CloseEventArgs e) { if (isNeedLogOnClose) { isNeedLogOnClose = false; ((EventsReader)this).ReaderLog($"ChaosTricks disconnected {e.Reason} {e.Code}"); try { OnCloseOnlyAfterConnect?.Invoke(e); } catch (Exception arg4) { ((EventsReader)this).ReaderLogError($"ChaosTricks custom OnClose after success connection error: {arg4}"); } } try { OnClose?.Invoke(e); } catch (Exception arg5) { ((EventsReader)this).ReaderLogError($"ChaosTricks custom OnClose error: {arg5}"); } }, OnWebSocketError = delegate(ErrorEventArgs e) { if (isNeedLogOnClose) { ((EventsReader)this).ReaderLog($"ChaosTricks ws error {e.Message} {e.Exception}"); try { OnErrorOnlyAfterConnect?.Invoke(e); } catch (Exception arg2) { ((EventsReader)this).ReaderLogError($"ChaosTricks custom OnError after success connection error: {arg2}"); } } try { OnError?.Invoke(e); } catch (Exception arg3) { ((EventsReader)this).ReaderLogError($"ChaosTricks custom OnError error: {arg3}"); } } }; val.OnMessage += delegate(object sender, MessageEventArgs e) { socketHandler.OnMessage(e); try { OnMessage?.Invoke(e); } catch (Exception arg) { ((EventsReader)this).ReaderLogError($"ChaosTricks custom OnMessage error: {arg}"); } }; val.OnOpen += delegate { socketHandler.OnOpen(); }; val.OnClose += delegate(object sender, CloseEventArgs e) { socketHandler.OnClose(e); }; val.OnError += delegate(object sender, ErrorEventArgs e) { socketHandler.OnError(e); }; if (!File.Exists(Path.Combine(settingsDir ?? "", ".debug_websocket"))) { val.Log.Level = (LogLevel)10; } SocketHandler = socketHandler; Socket = val; } public override string[] ReadAll(string path, bool isClearFile = true) { string[] result = null; if (!isSocketMessageProcessing) { lock (locker) { if (eventListFromSocket.Count > 0) { result = eventListFromSocket.ToArray(); eventListFromSocket.Clear(); } } } return result; } public override void ReadAndProcessAllWithDelayOnFrame(float dt) { if (isAutoConnectOnRead) { autoConnectOnReadPeriodTicks += dt; if (autoConnectOnReadPeriodTicks > autoConnectOnReadPeriod) { autoConnectOnReadPeriodTicks = 0f; OpenSocket(isLogOnError: false); } } ((EventsReaderOnFrame)this).ReadAndProcessAllWithDelayOnFrame(dt); } protected virtual void Dispose(bool disposing) { if (!isDisposed) { isDisposed = true; if (disposing) { ((IDisposable)Socket)?.Dispose(); } } } ~WebSocketEventsReader() { try { Dispose(disposing: false); } finally { ((object)this).Finalize(); } } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } } } namespace WebSocketIO.Interfaces { public interface IChaosWebSocket { void Start(); void Stop(); } } namespace WebSocketIO.Data { public class WebSocketMessage { public string type = ""; public string data = ""; public WebSocketMessage() { } public WebSocketMessage(string type, string data) { this.type = type; this.data = data; } public override string ToString() { string text = data.Replace("\"", "\\\""); return "{\"type\":\"" + type + "\", \"data\":\"" + text + "\"}"; } } }