Decompiled source of ChaosTricksTwitchIntegration v2.2.2
plugins/ChaosTricks/EventsIO.dll
Decompiled 6 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using EventsIO.Interfaces; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("EventIO")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("BFT")] [assembly: AssemblyProduct("EventIO")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("ab7abff2-5203-43d0-88ed-aebd4b6a130c")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.0.0")] namespace EventsIO { public class EventsData : IEventsData { public string Username { get; set; } public string Cost { get; set; } public string EventID { get; set; } public string Lang { get; set; } public string ExtraInfo { get; set; } public override string ToString() { return "EventsData: " + Username + " " + Cost + " " + EventID + " " + Lang + " " + ExtraInfo; } } public class EventsDataEncoder : IEventsDataEncoder, IEventsDataEncoderParams { internal static readonly string clientAppSep = "&"; internal static readonly char clientAppSepChar = '&'; internal static readonly string clientAppEqual = "="; internal static readonly char clientAppEqualChar = '='; protected static readonly Dictionary<string, string> symbolCodes = new Dictionary<string, string> { { clientAppSep, "%encode_amp%" }, { clientAppEqual, "%encode_equal%" } }; string IEventsDataEncoderParams.ClientAppSep => clientAppSep; char IEventsDataEncoderParams.ClientAppSepChar => clientAppSepChar; string IEventsDataEncoderParams.ClientAppEqual => clientAppEqual; char IEventsDataEncoderParams.ClientAppEqualChar => clientAppEqualChar; public virtual string Encode(string s) { foreach (KeyValuePair<string, string> symbolCode in symbolCodes) { s = s?.Replace(symbolCode.Key, symbolCode.Value); } return s; } public virtual string Decode(string s) { foreach (KeyValuePair<string, string> symbolCode in symbolCodes) { s = s?.Replace(symbolCode.Value, symbolCode.Key); } return s; } } public class EventsDataParser : IEventsDataParser { protected readonly Action<string> log; protected readonly IEventsDataEncoder encoder; protected readonly IEventsDataEncoderParams encoderParams; public bool isLogInfoError = true; public bool isLogSkipEmpty; public EventsDataParser(Action<string> log = null) { this.log = log; encoderParams = (IEventsDataEncoderParams)(encoder = new EventsDataEncoder()); } protected virtual void ParserLog(string s) { log?.Invoke(s); } public virtual IEventsData ParseEvent(string data) { EventsData eventsData = new EventsData(); string[] array = data.Split(new char[1] { encoderParams.ClientAppSepChar }, StringSplitOptions.RemoveEmptyEntries); if (array == null) { if (isLogInfoError) { ParserLog("get event info error. Wrong args."); } return eventsData; } string[] array2 = array; foreach (string text in array2) { string[] array3 = text.Split(new char[1] { encoderParams.ClientAppEqualChar }, StringSplitOptions.RemoveEmptyEntries); if (array3.Length != 2) { if (isLogSkipEmpty) { ParserLog("skip empty item: " + text); } continue; } string text2 = encoder.Decode(array3[0]); string text3 = encoder.Decode(array3[1]); switch (text2.ToLowerInvariant()) { case "username": eventsData.Username = text3; break; case "eventid": eventsData.EventID = text3; break; case "cost": eventsData.Cost = text3; break; case "lang": eventsData.Lang = text3; break; case "extrainfo": eventsData.ExtraInfo = text3; break; } } return eventsData; } } public class EventsGenerator : IEventsGenerator { protected internal enum FieldNames { UserName, EventID, Cost, Lang, ExtraInfo } protected EventsData data; protected readonly IEventsDataEncoder encoder; protected readonly IEventsDataEncoderParams encoderParams; public EventsGenerator() { data = new EventsData(); encoderParams = (IEventsDataEncoderParams)(encoder = new EventsDataEncoder()); } public virtual void SetCost(string s) { data.Cost = encoder.Encode(s); } public virtual void SetEventID(string s) { data.EventID = encoder.Encode(s); } public virtual void SetLang(string s) { data.Lang = encoder.Encode(s); } public virtual void SetUsername(string s) { data.Username = encoder.Encode(s); } public virtual void SetExtraInfo(string s) { data.ExtraInfo = encoder.Encode(s); } public virtual string Generate() { Dictionary<FieldNames, string> obj = new Dictionary<FieldNames, string> { { FieldNames.UserName, data.Username }, { FieldNames.Cost, data.Cost }, { FieldNames.EventID, data.EventID }, { FieldNames.Lang, data.Lang }, { FieldNames.ExtraInfo, data.ExtraInfo } }; StringBuilder stringBuilder = new StringBuilder(obj.Count); string clientAppSep = encoderParams.ClientAppSep; string clientAppEqual = encoderParams.ClientAppEqual; bool flag = true; foreach (KeyValuePair<FieldNames, string> item in obj) { if (flag) { stringBuilder.Append($"{item.Key}{clientAppEqual}{item.Value}"); flag = false; continue; } stringBuilder.Append($"{clientAppSep}{item.Key}{clientAppEqual}{item.Value}"); } data = new EventsData(); return stringBuilder.ToString(); } } public class EventsReaderOnKey : EventsReader, IEventsReaderOnKey, IEventsReader { protected readonly Action<IEventsData> processEvent; protected readonly IEventsDataParser parser; public EventsReaderOnKey(Action<IEventsData> processEvent, IEventsDataParser parser, Action<string> log = null, Action<string> logError = null) : base(log, logError) { this.processEvent = processEvent; this.parser = parser; } protected virtual void ProcessOnKey(string[] events) { if (events == null || events.Length == 0) { return; } foreach (IEventsData item in events.Select((string item) => parser?.ParseEvent(item))) { try { ReaderLog($"StartProcessOnKey {item}"); processEvent?.Invoke(item); } catch (Exception arg) { ReaderLogError($"StartProcessOnKey error: {arg}"); } } } public virtual void ProcessAllOnKey(string[] events) { try { ProcessOnKey(events); } catch (Exception arg) { ReaderLogError($"ProcessAllOnKey error: {arg}"); } } public virtual void ReadAndProcessAllOnKey(string path, bool isClearFile = true) { ProcessAllOnKey(ReadAll(path, isClearFile)); } } public class EventsReaderOnFrame : EventsReader, IEventsReaderOnFrame, IEventsReader { protected bool isFirstRun = true; protected readonly float delay; protected float delayCounter; protected float initDelay; protected float initCounter; protected readonly float checkPeriod; protected float periodCounter; protected readonly Action<IEventsData> processEvent; protected readonly IEventsDataParser parser; protected IEnumerator<IEventsData> eventsData; protected readonly string path; private bool isDelayEveryProcessing; public bool IsDelayEveryProcessing { get { return isDelayEveryProcessing; } set { isDelayEveryProcessing = value; } } protected virtual void StartProcessOnFrame() { while (eventsData.MoveNext()) { try { ReaderLog($"StartProcessOnFrame {eventsData.Current}"); processEvent?.Invoke(eventsData.Current); } catch (Exception arg) { ReaderLogError($"StartProcessOnFrame error: {arg}"); } } eventsData = null; } protected virtual void StartProcessWithDelayOnFrame() { if (eventsData.MoveNext()) { try { ReaderLog($"StartProcessWithDelayOnFrame {eventsData.Current}"); processEvent?.Invoke(eventsData.Current); return; } catch (Exception arg) { ReaderLogError($"StartProcessWithDelayOnFrame error: {arg}"); return; } } isFirstRun = false; eventsData = null; ReaderLog("StartProcessWithDelayOnFrame end"); } public EventsReaderOnFrame(string path, Action<IEventsData> processEvent, IEventsDataParser parser, Action<string> log = null, Action<string> errorLog = null, float checkPeriod = 2f, float delay = 1f, float initDelay = 0.5f) : base(log, errorLog) { this.processEvent = processEvent; this.parser = parser; this.delay = delay; this.initDelay = initDelay; this.path = path; this.checkPeriod = checkPeriod; } public virtual void SetEventsToProcess(string[] events) { try { if (events == null || events.Length == 0) { eventsData = null; return; } ReaderLog($"SetEventsToProcess read {events.Length} events"); eventsData = events.Select((string item) => parser?.ParseEvent(item))?.GetEnumerator(); } catch (Exception arg) { ReaderLogError($"SetEventsToProcess error: {arg}"); } } public virtual bool IsProcessEnd() { return eventsData == null; } public virtual void ProcessAllWithDelayOnFrame(float dt) { if (IsProcessEnd()) { return; } try { if (isDelayEveryProcessing || isFirstRun) { if (initDelay != 0f) { initCounter += dt; if (initCounter >= initDelay) { initCounter = 0f; initDelay = 0f; StartProcessWithDelayOnFrame(); } } else { delayCounter += dt; if (delayCounter >= delay) { delayCounter = 0f; StartProcessWithDelayOnFrame(); } } } else { StartProcessOnFrame(); } } catch (Exception arg) { ReaderLogError($"ProcessAllWithDelay error: {arg}"); } } public virtual void ReadAndProcessAllWithDelayOnFrame(float dt) { if (IsProcessEnd()) { periodCounter += dt; if (periodCounter >= checkPeriod) { periodCounter = 0f; string[] eventsToProcess = ReadAll(path); SetEventsToProcess(eventsToProcess); } } ProcessAllWithDelayOnFrame(dt); } } public class EventsReader : IEventsReader { protected readonly Action<string> log; protected readonly Action<string> logError; public EventsReader(Action<string> log = null, Action<string> logError = null) { this.log = log; this.logError = logError; } protected virtual void ReaderLog(string s) { log?.Invoke(s); } protected virtual void ReaderLogError(string s) { logError?.Invoke(s); } public virtual string[] ReadAllUnsafe(string path, bool isClearFile = true) { using FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); using StreamReader streamReader = new StreamReader(fileStream, Encoding.UTF8); char[] separator = new char[2] { '\r', '\n' }; string[] array = streamReader.ReadToEnd().Split(separator, StringSplitOptions.RemoveEmptyEntries); if (isClearFile && array != null && array.Length >= 1) { fileStream.SetLength(0L); } return array; } public virtual string[] ReadAll(string path, bool isClearFile = true) { try { return ReadAllUnsafe(path, isClearFile); } catch (FileNotFoundException) { } catch (DirectoryNotFoundException) { } catch (Exception arg) { ReaderLogError($"read event error: {arg}"); } return null; } } } namespace EventsIO.Interfaces { public interface IEventsData { string Username { get; } string Cost { get; } string EventID { get; } string Lang { get; } string ExtraInfo { get; } } public interface IEventsDataEncoderParams { string ClientAppSep { get; } char ClientAppSepChar { get; } string ClientAppEqual { get; } char ClientAppEqualChar { get; } } public interface IEventsDataEncoder { string Encode(string s); string Decode(string s); } public interface IEventsDataParser { IEventsData ParseEvent(string s); } public interface IEventsGenerator { void SetUsername(string s); void SetEventID(string s); void SetCost(string s); void SetLang(string s); void SetExtraInfo(string s); string Generate(); } public interface IEventsReaderOnKey : IEventsReader { void ProcessAllOnKey(string[] events); void ReadAndProcessAllOnKey(string path, bool isClearFile = true); } public interface IEventsReaderOnFrame : IEventsReader { void SetEventsToProcess(string[] events); bool IsProcessEnd(); void ProcessAllWithDelayOnFrame(float dt); void ReadAndProcessAllWithDelayOnFrame(float dt); } public interface IEventsReader { string[] ReadAll(string path, bool isClearFile = true); } }
plugins/ChaosTricks/InteractiveMod.dll
Decompiled 6 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.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 6 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.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 6 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.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 6 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.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 6 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using 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 + "\"}"; } } }