Decompiled source of ChaosTricks REPO TwitchIntegration v1.3.0

ChaosTricks_REPO_plugins/EventsIO.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using EventsIO.Interfaces;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("EventIO")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("BFT")]
[assembly: AssemblyProduct("EventIO")]
[assembly: AssemblyCopyright("Copyright ©  2020")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("ab7abff2-5203-43d0-88ed-aebd4b6a130c")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace EventsIO
{
	public class EventsData : IEventsData
	{
		public string Username { get; set; }

		public string Cost { get; set; }

		public string EventID { get; set; }

		public string Lang { get; set; }

		public string ExtraInfo { get; set; }

		public override string ToString()
		{
			return "EventsData: " + Username + " " + Cost + " " + EventID + " " + Lang + " " + ExtraInfo;
		}
	}
	public class EventsDataEncoder : IEventsDataEncoder, IEventsDataEncoderParams
	{
		internal static readonly string clientAppSep = "&";

		internal static readonly char clientAppSepChar = '&';

		internal static readonly string clientAppEqual = "=";

		internal static readonly char clientAppEqualChar = '=';

		protected static readonly Dictionary<string, string> symbolCodes = new Dictionary<string, string>
		{
			{ clientAppSep, "%encode_amp%" },
			{ clientAppEqual, "%encode_equal%" }
		};

		string IEventsDataEncoderParams.ClientAppSep => clientAppSep;

		char IEventsDataEncoderParams.ClientAppSepChar => clientAppSepChar;

		string IEventsDataEncoderParams.ClientAppEqual => clientAppEqual;

		char IEventsDataEncoderParams.ClientAppEqualChar => clientAppEqualChar;

		public virtual string Encode(string s)
		{
			foreach (KeyValuePair<string, string> symbolCode in symbolCodes)
			{
				s = s?.Replace(symbolCode.Key, symbolCode.Value);
			}
			return s;
		}

		public virtual string Decode(string s)
		{
			foreach (KeyValuePair<string, string> symbolCode in symbolCodes)
			{
				s = s?.Replace(symbolCode.Value, symbolCode.Key);
			}
			return s;
		}
	}
	public class EventsDataParser : IEventsDataParser
	{
		protected readonly Action<string> log;

		protected readonly IEventsDataEncoder encoder;

		protected readonly IEventsDataEncoderParams encoderParams;

		public bool isLogInfoError = true;

		public bool isLogSkipEmpty;

		public EventsDataParser(Action<string> log = null)
		{
			this.log = log;
			encoderParams = (IEventsDataEncoderParams)(encoder = new EventsDataEncoder());
		}

		protected virtual void ParserLog(string s)
		{
			log?.Invoke(s);
		}

		public virtual IEventsData ParseEvent(string data)
		{
			EventsData eventsData = new EventsData();
			string[] array = data.Split(new char[1] { encoderParams.ClientAppSepChar }, StringSplitOptions.RemoveEmptyEntries);
			if (array == null)
			{
				if (isLogInfoError)
				{
					ParserLog("get event info error. Wrong args.");
				}
				return eventsData;
			}
			string[] array2 = array;
			foreach (string text in array2)
			{
				string[] array3 = text.Split(new char[1] { encoderParams.ClientAppEqualChar }, StringSplitOptions.RemoveEmptyEntries);
				if (array3.Length != 2)
				{
					if (isLogSkipEmpty)
					{
						ParserLog("skip empty item: " + text);
					}
					continue;
				}
				string text2 = encoder.Decode(array3[0]);
				string text3 = encoder.Decode(array3[1]);
				switch (text2.ToLowerInvariant())
				{
				case "username":
					eventsData.Username = text3;
					break;
				case "eventid":
					eventsData.EventID = text3;
					break;
				case "cost":
					eventsData.Cost = text3;
					break;
				case "lang":
					eventsData.Lang = text3;
					break;
				case "extrainfo":
					eventsData.ExtraInfo = text3;
					break;
				}
			}
			return eventsData;
		}
	}
	public class EventsGenerator : IEventsGenerator
	{
		protected internal enum FieldNames
		{
			UserName,
			EventID,
			Cost,
			Lang,
			ExtraInfo
		}

		protected EventsData data;

		protected readonly IEventsDataEncoder encoder;

		protected readonly IEventsDataEncoderParams encoderParams;

		public EventsGenerator()
		{
			data = new EventsData();
			encoderParams = (IEventsDataEncoderParams)(encoder = new EventsDataEncoder());
		}

		public virtual void SetCost(string s)
		{
			data.Cost = encoder.Encode(s);
		}

		public virtual void SetEventID(string s)
		{
			data.EventID = encoder.Encode(s);
		}

		public virtual void SetLang(string s)
		{
			data.Lang = encoder.Encode(s);
		}

		public virtual void SetUsername(string s)
		{
			data.Username = encoder.Encode(s);
		}

		public virtual void SetExtraInfo(string s)
		{
			data.ExtraInfo = encoder.Encode(s);
		}

		public virtual string Generate()
		{
			Dictionary<FieldNames, string> obj = new Dictionary<FieldNames, string>
			{
				{
					FieldNames.UserName,
					data.Username
				},
				{
					FieldNames.Cost,
					data.Cost
				},
				{
					FieldNames.EventID,
					data.EventID
				},
				{
					FieldNames.Lang,
					data.Lang
				},
				{
					FieldNames.ExtraInfo,
					data.ExtraInfo
				}
			};
			StringBuilder stringBuilder = new StringBuilder(obj.Count);
			string clientAppSep = encoderParams.ClientAppSep;
			string clientAppEqual = encoderParams.ClientAppEqual;
			bool flag = true;
			foreach (KeyValuePair<FieldNames, string> item in obj)
			{
				if (flag)
				{
					stringBuilder.Append($"{item.Key}{clientAppEqual}{item.Value}");
					flag = false;
					continue;
				}
				stringBuilder.Append($"{clientAppSep}{item.Key}{clientAppEqual}{item.Value}");
			}
			data = new EventsData();
			return stringBuilder.ToString();
		}
	}
	public class EventsReaderOnKey : EventsReader, IEventsReaderOnKey, IEventsReader
	{
		protected readonly Action<IEventsData> processEvent;

		protected readonly IEventsDataParser parser;

		public EventsReaderOnKey(Action<IEventsData> processEvent, IEventsDataParser parser, Action<string> log = null, Action<string> logError = null)
			: base(log, logError)
		{
			this.processEvent = processEvent;
			this.parser = parser;
		}

		protected virtual void ProcessOnKey(string[] events)
		{
			if (events == null || events.Length == 0)
			{
				return;
			}
			foreach (IEventsData item in events.Select((string item) => parser?.ParseEvent(item)))
			{
				try
				{
					ReaderLog($"StartProcessOnKey {item}");
					processEvent?.Invoke(item);
				}
				catch (Exception arg)
				{
					ReaderLogError($"StartProcessOnKey error: {arg}");
				}
			}
		}

		public virtual void ProcessAllOnKey(string[] events)
		{
			try
			{
				ProcessOnKey(events);
			}
			catch (Exception arg)
			{
				ReaderLogError($"ProcessAllOnKey error: {arg}");
			}
		}

		public virtual void ReadAndProcessAllOnKey(string path, bool isClearFile = true)
		{
			ProcessAllOnKey(ReadAll(path, isClearFile));
		}
	}
	public class EventsReaderOnFrame : EventsReader, IEventsReaderOnFrame, IEventsReader
	{
		protected bool isFirstRun = true;

		protected readonly float delay;

		protected float delayCounter;

		protected float initDelay;

		protected float initCounter;

		protected readonly float checkPeriod;

		protected float periodCounter;

		protected readonly Action<IEventsData> processEvent;

		protected readonly IEventsDataParser parser;

		protected IEnumerator<IEventsData> eventsData;

		protected readonly string path;

		private bool isDelayEveryProcessing;

		public bool IsDelayEveryProcessing
		{
			get
			{
				return isDelayEveryProcessing;
			}
			set
			{
				isDelayEveryProcessing = value;
			}
		}

		protected virtual void StartProcessOnFrame()
		{
			while (eventsData.MoveNext())
			{
				try
				{
					ReaderLog($"StartProcessOnFrame {eventsData.Current}");
					processEvent?.Invoke(eventsData.Current);
				}
				catch (Exception arg)
				{
					ReaderLogError($"StartProcessOnFrame error: {arg}");
				}
			}
			eventsData = null;
		}

		protected virtual void StartProcessWithDelayOnFrame()
		{
			if (eventsData.MoveNext())
			{
				try
				{
					ReaderLog($"StartProcessWithDelayOnFrame {eventsData.Current}");
					processEvent?.Invoke(eventsData.Current);
					return;
				}
				catch (Exception arg)
				{
					ReaderLogError($"StartProcessWithDelayOnFrame error: {arg}");
					return;
				}
			}
			isFirstRun = false;
			eventsData = null;
			ReaderLog("StartProcessWithDelayOnFrame end");
		}

		public EventsReaderOnFrame(string path, Action<IEventsData> processEvent, IEventsDataParser parser, Action<string> log = null, Action<string> errorLog = null, float checkPeriod = 2f, float delay = 1f, float initDelay = 0.5f)
			: base(log, errorLog)
		{
			this.processEvent = processEvent;
			this.parser = parser;
			this.delay = delay;
			this.initDelay = initDelay;
			this.path = path;
			this.checkPeriod = checkPeriod;
		}

		public virtual void SetEventsToProcess(string[] events)
		{
			try
			{
				if (events == null || events.Length == 0)
				{
					eventsData = null;
					return;
				}
				ReaderLog($"SetEventsToProcess read {events.Length} events");
				eventsData = events.Select((string item) => parser?.ParseEvent(item))?.GetEnumerator();
			}
			catch (Exception arg)
			{
				ReaderLogError($"SetEventsToProcess error: {arg}");
			}
		}

		public virtual bool IsProcessEnd()
		{
			return eventsData == null;
		}

		public virtual void ProcessAllWithDelayOnFrame(float dt)
		{
			if (IsProcessEnd())
			{
				return;
			}
			try
			{
				if (isDelayEveryProcessing || isFirstRun)
				{
					if (initDelay != 0f)
					{
						initCounter += dt;
						if (initCounter >= initDelay)
						{
							initCounter = 0f;
							initDelay = 0f;
							StartProcessWithDelayOnFrame();
						}
					}
					else
					{
						delayCounter += dt;
						if (delayCounter >= delay)
						{
							delayCounter = 0f;
							StartProcessWithDelayOnFrame();
						}
					}
				}
				else
				{
					StartProcessOnFrame();
				}
			}
			catch (Exception arg)
			{
				ReaderLogError($"ProcessAllWithDelay error: {arg}");
			}
		}

		public virtual void ReadAndProcessAllWithDelayOnFrame(float dt)
		{
			if (IsProcessEnd())
			{
				periodCounter += dt;
				if (periodCounter >= checkPeriod)
				{
					periodCounter = 0f;
					string[] eventsToProcess = ReadAll(path);
					SetEventsToProcess(eventsToProcess);
				}
			}
			ProcessAllWithDelayOnFrame(dt);
		}
	}
	public class EventsReader : IEventsReader
	{
		protected readonly Action<string> log;

		protected readonly Action<string> logError;

		public EventsReader(Action<string> log = null, Action<string> logError = null)
		{
			this.log = log;
			this.logError = logError;
		}

		protected virtual void ReaderLog(string s)
		{
			log?.Invoke(s);
		}

		protected virtual void ReaderLogError(string s)
		{
			logError?.Invoke(s);
		}

		public virtual string[] ReadAllUnsafe(string path, bool isClearFile = true)
		{
			using FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
			using StreamReader streamReader = new StreamReader(fileStream, Encoding.UTF8);
			char[] separator = new char[2] { '\r', '\n' };
			string[] array = streamReader.ReadToEnd().Split(separator, StringSplitOptions.RemoveEmptyEntries);
			if (isClearFile && array != null && array.Length >= 1)
			{
				fileStream.SetLength(0L);
			}
			return array;
		}

		public virtual string[] ReadAll(string path, bool isClearFile = true)
		{
			try
			{
				return ReadAllUnsafe(path, isClearFile);
			}
			catch (FileNotFoundException)
			{
			}
			catch (DirectoryNotFoundException)
			{
			}
			catch (Exception arg)
			{
				ReaderLogError($"read event error: {arg}");
			}
			return null;
		}
	}
}
namespace EventsIO.Interfaces
{
	public interface IEventsData
	{
		string Username { get; }

		string Cost { get; }

		string EventID { get; }

		string Lang { get; }

		string ExtraInfo { get; }
	}
	public interface IEventsDataEncoderParams
	{
		string ClientAppSep { get; }

		char ClientAppSepChar { get; }

		string ClientAppEqual { get; }

		char ClientAppEqualChar { get; }
	}
	public interface IEventsDataEncoder
	{
		string Encode(string s);

		string Decode(string s);
	}
	public interface IEventsDataParser
	{
		IEventsData ParseEvent(string s);
	}
	public interface IEventsGenerator
	{
		void SetUsername(string s);

		void SetEventID(string s);

		void SetCost(string s);

		void SetLang(string s);

		void SetExtraInfo(string s);

		string Generate();
	}
	public interface IEventsReaderOnKey : IEventsReader
	{
		void ProcessAllOnKey(string[] events);

		void ReadAndProcessAllOnKey(string path, bool isClearFile = true);
	}
	public interface IEventsReaderOnFrame : IEventsReader
	{
		void SetEventsToProcess(string[] events);

		bool IsProcessEnd();

		void ProcessAllWithDelayOnFrame(float dt);

		void ReadAndProcessAllWithDelayOnFrame(float dt);
	}
	public interface IEventsReader
	{
		string[] ReadAll(string path, bool isClearFile = true);
	}
}

ChaosTricks_REPO_plugins/InteractiveMod.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using EventsIO;
using EventsIO.Interfaces;
using HarmonyLib;
using ModHelper;
using ModHelper.Interfaces;
using ModHelperUnity;
using Newtonsoft.Json;
using Photon.Pun;
using REPO_BFT_BepInEx.Commands.Interfaces;
using REPO_BFT_BepInEx.Patchers;
using REPO_BFT_BepInEx.Services;
using REPO_BFT_BepInEx.Wrappers;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using WebSocketIO;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("REPO BepInEx version")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("BFT LLC")]
[assembly: AssemblyProduct("ChaosTricksMod")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("BFT")]
[assembly: ComVisible(false)]
[assembly: Guid("482A702C-A19B-425E-8DCC-FE9C62D172B0")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.3.0.0")]
namespace REPO_BFT_BepInEx
{
	[BepInPlugin("bft.chaostricks", "Chaos Tricks", "1.3.0")]
	public class BepInExPlugin : BaseUnityPlugin
	{
		public const string GUID = "bft.chaostricks";

		public const string NAME = "Chaos Tricks";

		private GameObject hookObj;

		private bool isPatched;

		public void Awake()
		{
			try
			{
				UtilitySettings.BaseFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
				SceneManager.sceneLoaded += OnSceneLoaded;
			}
			catch (Exception arg)
			{
				((HelperLog)Utils.logger).LogError((object)string.Format("{0} v{1} error: {2}", "Chaos Tricks", "1.3.0", arg));
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			try
			{
				((HelperLog)Utils.logger).Log((object)("OnSceneLoaded triggered: " + ((Scene)(ref scene)).name));
				if (!isPatched)
				{
					((HelperLog)Utils.logger).LogInfo((object)"Background task: trying to create mod instance");
					hookObj = new GameObject();
					Object.DontDestroyOnLoad((Object)(object)hookObj);
					hookObj.AddComponent<InteractiveMod>();
					hookObj.SetActive(true);
					isPatched = true;
					SceneManager.sceneLoaded -= OnSceneLoaded;
				}
			}
			catch (Exception arg)
			{
				((HelperLog)Utils.logger).LogError((object)string.Format("{0} v{1} OnSceneLoaded error: {2}", "Chaos Tricks", "1.3.0", arg));
			}
		}
	}
	public sealed class InteractiveMod : MonoBehaviour
	{
		internal static InteractiveMod inst;

		internal const string MOD_VERSION = "1.3.0";

		private readonly ServiceProvider serviceProvider = ServiceProvider.inst;

		private readonly BufferedLogger logger = Utils.logger;

		private ScheduleManager systemScheduleManager;

		private ScheduleManager scheduleManager;

		private EventEmitter eventEmitter;

		private WebSocketEventsReader<SettingsData> eventsReader;

		private IEventsDataParser eventsParser;

		private ICommandManager commandManager;

		private CommandListArgManager commandListArgManager = new CommandListArgManager();

		private UtilityConsole console;

		private ChaosEnemySpawner enemySpawner;

		private Dictionary<string, IRepoStandaloneCommand> commands;

		private TranslationService translationService;

		private LimitedLogWrapper limitedLogger;

		private LimitedLogWrapper limitedSceneLogger;

		private bool isAppConnected;

		private bool isAppConnectedProcessed = true;

		private readonly List<IForceEnd> forceEndEvents = new List<IForceEnd>();

		private static bool msgType;

		private bool isLevelGeneratedLastCheck;

		private bool isMenuLevelLastCheck;

		public void Awake()
		{
			inst = this;
			Utils.LogClearBySize();
			limitedLogger = new LimitedLogWrapper(100, (IDebugLogger)(object)Utils.logger);
			limitedSceneLogger = new LimitedLogWrapper(50, (IDebugLogger)(object)Utils.logger);
			((HelperLog)logger).LogInfo((object)"InteractiveMod Awake");
			((HelperLog)logger).LogInfo((object)"mod version 1.3.0");
			FlushLog();
			MainPatcher.InitPatch();
		}

		public void Start()
		{
			((HelperLog)logger).LogInfo((object)"InteractiveMod Start");
			try
			{
				UtilityJson.RegisterCustomGenerator((Func<IJsonUtil>)(() => (IJsonUtil)(object)new JsonParser()));
				((HelperLog)logger).LogInfo((object)"init mod services");
				InitServices();
				((HelperLog)logger).LogInfo((object)"init mod readers");
				InitReaders();
				((HelperLog)logger).LogInfo((object)"init mod commands");
				InitCommands(needValidate: false);
				((HelperLog)logger).LogInfo((object)"mod initiation ends");
			}
			catch (Exception arg)
			{
				((HelperLog)logger).LogError((object)$"mod initiation error: {arg}");
			}
			FlushLog();
		}

		public void OnDestroy()
		{
			((HelperLog)logger).LogInfo((object)"InteractiveMod OnDestroy");
			FlushLog();
		}

		private void FlushLog()
		{
			logger.Flush(true);
		}

		private void InitServices()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			eventEmitter = new EventEmitter();
			serviceProvider.RegisterEventEmitter(eventEmitter);
			systemScheduleManager = new ScheduleManager((ILogger)(object)logger, 0);
			serviceProvider.RegisterSystemScheduleManager(systemScheduleManager);
			systemScheduleManager.NewPeriodicTask(new PeriodicTaskData
			{
				periodicAction = FlushLog,
				finishAction = FlushLog,
				periodInSec = 5f
			}, false);
			scheduleManager = new ScheduleManager((ILogger)(object)logger, 0);
			serviceProvider.RegisterScheduleManager(scheduleManager);
			translationService = new TranslationService();
			translationService.LoadData();
			commandListArgManager = new CommandListArgManager();
			serviceProvider.RegisterCommandListArgManager(commandListArgManager);
			commandListArgManager.LoadCommandsList();
			ChaosItemManager chaosItemManager = new ChaosItemManager();
			serviceProvider.RegisterItemManager(chaosItemManager);
			chaosItemManager.LoadAllObjects();
			enemySpawner = new ChaosEnemySpawner();
			serviceProvider.RegisterEnemySpawner(enemySpawner);
		}

		private void InitReaders()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			console = new UtilityConsole((IDebugLogger)(object)logger, (List<string>)null);
			eventsParser = (IEventsDataParser)new EventsDataParser((Action<string>)((HelperLog)logger).LogWarning);
			eventsReader = new WebSocketEventsReader<SettingsData>((Action<IEventsData>)ProcessEvent, eventsParser, (Action<string>)((HelperLog)logger).LogInfo, (Action<string>)((HelperLog)logger).LogInfo, 0.5f, 1f, 0.5f);
			eventsReader.InitDefaultSocket(Utils.modFolder, "chaostricks_repo", 13715, "127.0.0.1");
			eventsReader.OnOpen = delegate
			{
				isAppConnected = true;
				isAppConnectedProcessed = false;
			};
			eventsReader.OnCloseOnlyAfterConnect = delegate
			{
				isAppConnected = false;
				isAppConnectedProcessed = false;
			};
			Action<string> defaultOnConfig = eventsReader.SocketHandler.OnConfigMessage;
			eventsReader.SocketHandler.OnConfigMessage = delegate(string s)
			{
				defaultOnConfig?.Invoke(s);
				SettingsManager.QueueUpdateSettings(eventsReader.Settings);
			};
			eventsReader.OpenSocket(true);
		}

		public void InitCommands(bool needValidate)
		{
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Expected O, but got Unknown
			forceEndEvents.Clear();
			Type type = typeof(IRepoStandaloneCommand);
			IEnumerable<Type> enumerable = from p in Assembly.GetExecutingAssembly().GetTypes()
				where type.IsAssignableFrom(p) && p.IsClass && !p.IsAbstract
				select p;
			((HelperLog)logger).LogInfo((object)$"found {enumerable.Count()} commands");
			commands = new Dictionary<string, IRepoStandaloneCommand>();
			foreach (Type item2 in enumerable)
			{
				IRepoStandaloneCommand repoStandaloneCommand = Activator.CreateInstance(item2) as IRepoStandaloneCommand;
				if (repoStandaloneCommand != null)
				{
					console.RegisterCommand((IConsoleCommand)repoStandaloneCommand);
					if (commands.ContainsKey(((IConsoleCommand)repoStandaloneCommand).Id))
					{
						((HelperLog)logger).LogWarning((object)("repeated id command " + ((IConsoleCommand)repoStandaloneCommand).Id + ". The command will replace existed."));
					}
					commands[((IConsoleCommand)repoStandaloneCommand).Id] = repoStandaloneCommand;
					if (repoStandaloneCommand is IForceEnd item)
					{
						forceEndEvents.Add(item);
					}
					((HelperLog)logger).LogInfo((object)("init command '" + ((IConsoleCommand)repoStandaloneCommand).Id + "' complete"));
				}
				else
				{
					((HelperLog)logger).LogError((object)("init command '" + ((IConsoleCommand)repoStandaloneCommand).Id + "' failed"));
				}
			}
			((HelperLog)logger).LogInfo((object)$"found {commands.Count} commands and {forceEndEvents.Count} timers");
			((HelperLog)logger).LogInfo((object)"init HelperCommandManager");
			commandManager = (ICommandManager)new HelperCommandManagerFormatted((IDebugLogger)(object)logger);
			commandManager.InitFromFile(Utils.GetRelativeModFilePath("commands.data"));
			int num = commandManager.GetCommands().Length;
			((HelperLog)logger).LogInfo((object)$"found {num} events");
			if (!needValidate)
			{
				return;
			}
			((HelperLog)logger).LogInfo((object)"validate commands");
			string[] array = commandManager.GetCommands();
			foreach (string text in array)
			{
				if (!console.IsValidCommandLine(text?.Trim()))
				{
					((HelperLog)logger).LogError((object)("Command line '" + text + "' invalid"));
				}
			}
			((HelperLog)logger).LogInfo((object)"init HelperCommandManager ends");
		}

		private void ProcessEvent(IEventsData data)
		{
			string eventID = data.EventID;
			if (string.IsNullOrEmpty(eventID))
			{
				((HelperLog)logger).LogError((object)"ProcessEvent eventID is null or empty");
				return;
			}
			if (!GameUtils.IsMaster && ChaosModNetwork.NeedRunFromHost(eventID))
			{
				((HelperLog)logger).LogInfo((object)("Try to execute network event: '" + eventID + "'"));
				ChaosModNetwork.RequestClientEventRPC(GameUtils.LocalPlayer.photonView.ViewID, eventID);
				return;
			}
			((HelperLog)logger).LogInfo((object)("Try to execute event: '" + eventID + "'"));
			string text = commandManager.GetCommandData(eventID, true)?.Trim();
			try
			{
				((HelperLog)logger).LogInfo((object)("Command: " + text));
				if (console.RunCommand(text, data, (Action<string>)null))
				{
					((HelperLog)logger).LogInfo((object)("Event '" + data.EventID + "' executing is completed"));
					string trans = translationService.translation.GetTrans(data.EventID, data.Lang);
					string trans2 = translationService.translation.GetTrans("%template_msg%", data.Lang);
					string message = data.Username + " " + trans2 + " '" + trans + "'";
					GameUtils.SendTruckChatMessage(message);
					GameUtils.ShowUIMessage(message);
					msgType = !msgType;
				}
				else
				{
					((HelperDebugLog)logger).LogDebugError((object)("Event '" + data.EventID + "' executing is failed"));
				}
			}
			catch (Exception arg)
			{
				((HelperLog)logger).LogError((object)$"ProcessCommands '{data.EventID}' unexpected error: {arg}");
			}
		}

		private void OnLevelGenerated()
		{
			try
			{
				((HelperLog)Utils.logger).LogInfo((object)"OnLevelGenerated triggered");
				SemiFunc_EnemySpawnPatcher.ClearBlockEnemies();
				enemySpawner?.ClearSpawnedEnemies();
			}
			catch (Exception arg)
			{
				((HelperLog)Utils.logger).LogError((object)$"OnLevelGenerated {arg}");
			}
		}

		private void OnMenuLevel()
		{
			try
			{
				((HelperLog)Utils.logger).LogInfo((object)"OnMenuLevel triggered");
				ChaosInputManager.UnblockAll();
				ChaosInputManager.UnholdAll();
				SemiFunc_EnemySpawnPatcher.ClearBlockEnemies();
				enemySpawner?.ClearSpawnedEnemies();
				foreach (IForceEnd forceEndEvent in forceEndEvents)
				{
					try
					{
						forceEndEvent.ForceEnd();
					}
					catch (Exception arg)
					{
						((HelperLog)Utils.logger).LogError((object)$"OnMenuLevel force end for {((IConsoleCommand)forceEndEvent).Id} error: {arg}");
					}
				}
			}
			catch (Exception arg2)
			{
				((HelperLog)Utils.logger).LogError((object)$"OnMenuLevel {arg2}");
			}
		}

		private bool IsReadyForCheckEvent()
		{
			try
			{
				bool generated = LevelGenerator.Instance.Generated;
				if (generated != isLevelGeneratedLastCheck && generated)
				{
					OnLevelGenerated();
				}
				isLevelGeneratedLastCheck = generated;
				bool flag = SemiFunc.MenuLevel();
				if (flag != isMenuLevelLastCheck && flag)
				{
					OnMenuLevel();
				}
				isMenuLevelLastCheck = flag;
				if (!generated || flag)
				{
					return false;
				}
				try
				{
					if (!GameUtils.AnyPlayerAlive())
					{
						return false;
					}
				}
				catch (Exception arg)
				{
					limitedLogger.LogError($"IsReadyForCheckEvent alive check error: {arg}");
				}
				return true;
			}
			catch (Exception arg2)
			{
				limitedLogger.LogError($"IsReadyForCheckEvent error: {arg2}");
			}
			return false;
		}

		public void Update()
		{
			try
			{
				float deltaTime = Time.deltaTime;
				systemScheduleManager.OnUpdate(deltaTime);
				SettingsManager.OnUpdate();
				if (IsReadyForCheckEvent())
				{
					enemySpawner.OnUpdate(deltaTime);
					scheduleManager.OnUpdate(deltaTime);
					eventEmitter.TriggerOnUpdateEvent(this, deltaTime);
					((EventsReaderOnFrame)eventsReader).ReadAndProcessAllWithDelayOnFrame(deltaTime);
					ChaosModNetwork.ProcessNetworkEvents(commandManager, commands);
				}
			}
			catch (Exception arg)
			{
				limitedLogger.LogError($"OnUpdate error: {arg}");
			}
		}

		internal void ReinitMod()
		{
			try
			{
				((HelperLog)logger).LogInfo((object)"ReinitMod starts");
				FlushLog();
				OnMenuLevel();
				commandListArgManager.LoadCommandsList();
				InitCommands(needValidate: false);
				((HelperLog)logger).LogInfo((object)"ReinitMod ends");
			}
			catch (Exception arg)
			{
				((HelperLog)logger).LogError((object)$"ReinitMod error: {arg}");
			}
			FlushLog();
		}
	}
	internal sealed class JsonParser : IJsonUtil
	{
		public T FromFile<T>(string path) where T : class
		{
			using StreamReader streamReader = new StreamReader(path);
			return FromString<T>(streamReader.ReadToEnd());
		}

		public T FromString<T>(string s) where T : class
		{
			return JsonConvert.DeserializeObject<T>(s);
		}
	}
	internal static class CoroutineUtils
	{
		[CompilerGenerated]
		private sealed class <ActionCoroutine>d__1 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public float delayInSec;

			public Action action;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ActionCoroutine>d__1(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (delayInSec == 0f)
					{
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					<>2__current = (object)new WaitForSeconds(delayInSec);
					<>1__state = 2;
					return true;
				case 1:
					<>1__state = -1;
					break;
				case 2:
					<>1__state = -1;
					break;
				}
				try
				{
					action();
				}
				catch (Exception arg)
				{
					((HelperLog)Utils.logger).LogError((object)$"ActionCoroutine for {delayInSec} error: {arg}");
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <ActionCoroutineInFrames>d__3 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public int delayInFrames;

			public Action action;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ActionCoroutineInFrames>d__3(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (delayInFrames > 0)
				{
					int num = delayInFrames - 1;
					delayInFrames = num;
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				try
				{
					action();
				}
				catch (Exception arg)
				{
					((HelperLog)Utils.logger).LogError((object)$"ActionCoroutineInFrames for {delayInFrames} error: {arg}");
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <WhileCoroutine>d__5 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public float repeatDelayInSec;

			public Func<bool> action;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WhileCoroutine>d__5(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Expected O, but got Unknown
				int num = <>1__state;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					bool flag;
					try
					{
						flag = action();
					}
					catch (Exception arg)
					{
						((HelperLog)Utils.logger).LogError((object)$"ActionCoroutine for {repeatDelayInSec} error: {arg}");
						flag = false;
					}
					if (!flag)
					{
						return false;
					}
				}
				else
				{
					<>1__state = -1;
				}
				<>2__current = (object)new WaitForSeconds(repeatDelayInSec);
				<>1__state = 1;
				return true;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		internal static void StartCoroutine(MonoBehaviour script, float delayInSec, Action action)
		{
			if ((Object)(object)script == (Object)null)
			{
				return;
			}
			if (action == null)
			{
				((HelperLog)Utils.logger).LogError((object)"StartCoroutine got null action");
				return;
			}
			if (delayInSec < 0f)
			{
				delayInSec = 0f;
				((HelperLog)Utils.logger).LogWarning((object)$"StartCoroutine got invalid delay {delayInSec}");
			}
			script.StartCoroutine(ActionCoroutine(delayInSec, action));
		}

		[IteratorStateMachine(typeof(<ActionCoroutine>d__1))]
		private static IEnumerator ActionCoroutine(float delayInSec, Action action)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ActionCoroutine>d__1(0)
			{
				delayInSec = delayInSec,
				action = action
			};
		}

		internal static void StartCoroutineInFrames(MonoBehaviour script, int delayInFrames, Action action)
		{
			if ((Object)(object)script == (Object)null)
			{
				return;
			}
			if (action == null)
			{
				((HelperLog)Utils.logger).LogError((object)"StartCoroutineInFrames got null action");
				return;
			}
			if (delayInFrames <= 0)
			{
				((HelperLog)Utils.logger).LogWarning((object)$"StartCoroutineInFrames got invalid delay in frames {delayInFrames}. Replaced to 1.");
				delayInFrames = 1;
			}
			script.StartCoroutine(ActionCoroutineInFrames(delayInFrames, action));
		}

		[IteratorStateMachine(typeof(<ActionCoroutineInFrames>d__3))]
		private static IEnumerator ActionCoroutineInFrames(int delayInFrames, Action action)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ActionCoroutineInFrames>d__3(0)
			{
				delayInFrames = delayInFrames,
				action = action
			};
		}

		internal static void StartCoroutineWhile(MonoBehaviour script, float repeatDelayInSec, Func<bool> action)
		{
			if ((Object)(object)script == (Object)null)
			{
				return;
			}
			if (action == null)
			{
				((HelperLog)Utils.logger).LogError((object)"StartCoroutine got null action");
				return;
			}
			if (repeatDelayInSec < 0f)
			{
				repeatDelayInSec = 0f;
				((HelperLog)Utils.logger).LogWarning((object)$"StartCoroutine got invalid delay {repeatDelayInSec}");
			}
			script.StartCoroutine(WhileCoroutine(repeatDelayInSec, action));
		}

		[IteratorStateMachine(typeof(<WhileCoroutine>d__5))]
		private static IEnumerator WhileCoroutine(float repeatDelayInSec, Func<bool> action)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WhileCoroutine>d__5(0)
			{
				repeatDelayInSec = repeatDelayInSec,
				action = action
			};
		}
	}
	internal static class GameUtils
	{
		internal struct Coords
		{
			public Vector3 pos;

			public Quaternion rot;
		}

		internal static PlayerAvatar LocalPlayer
		{
			get
			{
				PlayerController instance = PlayerController.instance;
				if ((Object)(object)instance == (Object)null)
				{
					return null;
				}
				return instance.playerAvatarScript;
			}
		}

		internal static IEnumerable<PlayerAvatar> Players => from p in SemiFunc.PlayerGetAll()
			where (Object)(object)p != (Object)null
			select p;

		internal static List<PlayerAvatar> AlivePlayers => Players.Where(IsPlayerAlive).ToList();

		internal static List<PlayerAvatar> DeadPlayers => Players.Where(IsPlayerDead).ToList();

		internal static bool IsMaster
		{
			get
			{
				if (GameManager.Multiplayer())
				{
					return PhotonNetwork.IsMasterClient;
				}
				return true;
			}
		}

		internal static Vector3 GetPlayerForward(float length = 1f)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return GetPlayerForward(((Component)LocalPlayer).transform, length);
		}

		internal static Vector3 GetForwardOffset(float length = 1f, float height = 0.5f)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return GetForwardOffset(((Component)LocalPlayer).transform, length, height);
		}

		internal static Vector3 GetPlayerForward(Transform tr, float length = 1f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = tr.position;
			Vector3 forward = tr.forward;
			return position + ((Vector3)(ref forward)).normalized * length;
		}

		internal static Vector3 GetForwardOffset(Transform tr, float length = 1f, float height = 0.5f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			Vector3 forward = tr.forward;
			return ((Vector3)(ref forward)).normalized * length + new Vector3(0f, height, 0f);
		}

		internal static void SetHealthPercentage(PlayerAvatar player, float percents, bool keepAlive)
		{
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			if (percents < 0f)
			{
				percents = 0f;
				((HelperLog)Utils.logger).LogWarning((object)"SetHealth got negative percents value");
			}
			if ((Object)(object)player == (Object)null)
			{
				((HelperLog)Utils.logger).LogWarning((object)"SetHealth got null player");
				return;
			}
			if ((Object)(object)player.playerHealth == (Object)null)
			{
				((HelperLog)Utils.logger).LogWarning((object)"SetHealth playerHealth null");
				return;
			}
			if (!((Behaviour)player.playerHealth).enabled)
			{
				((HelperLog)Utils.logger).LogWarning((object)"SetHealth playerHealth disabled");
			}
			int playerMaxHealth = GetPlayerMaxHealth(player.playerHealth);
			int playerHealth = GetPlayerHealth(player.playerHealth);
			int num = (int)Math.Ceiling((float)playerMaxHealth * (percents / 100f));
			if (keepAlive && num <= 0)
			{
				num = 1;
			}
			if (playerHealth != num)
			{
				if (playerHealth < num)
				{
					int num2 = num - playerHealth;
					((HelperLog)Utils.logger).LogInfo((object)$"SetHealth calc playerHealth heal: {num2} from {playerHealth} to {num} with keep alive {keepAlive}");
					player.playerHealth.HealOther(num2, true);
				}
				else
				{
					int num3 = playerHealth - num;
					((HelperLog)Utils.logger).LogInfo((object)$"SetHealth calc playerHealth damage: {num3} from {playerHealth} to {num} with kill {keepAlive}");
					player.playerHealth.HurtOther(num3, Vector3.zero, false, -1);
				}
			}
		}

		internal static void SetHealthAmount(PlayerAvatar player, int amount, bool keepAlive)
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			if (amount < 0)
			{
				((HelperLog)Utils.logger).LogWarning((object)"SetHealthAmount got negative amount value");
				return;
			}
			if ((Object)(object)player == (Object)null)
			{
				((HelperLog)Utils.logger).LogWarning((object)"SetHealthAmount got null player");
				return;
			}
			if ((Object)(object)player.playerHealth == (Object)null)
			{
				((HelperLog)Utils.logger).LogWarning((object)"SetHealthAmount playerHealth null");
				return;
			}
			if (!((Behaviour)player.playerHealth).enabled)
			{
				((HelperLog)Utils.logger).LogWarning((object)"SetHealthAmount playerHealth disabled");
			}
			int playerHealth = GetPlayerHealth(player.playerHealth);
			if (playerHealth == amount)
			{
				return;
			}
			if (playerHealth < amount)
			{
				int num = amount - playerHealth;
				((HelperLog)Utils.logger).LogInfo((object)$"SetHealthAmount calc playerHealth heal: {num} from {playerHealth} to {amount}");
				player.playerHealth.HealOther(num, true);
				return;
			}
			int num2 = amount;
			if (keepAlive && num2 <= 0)
			{
				num2 = 1;
			}
			int num3 = playerHealth - num2;
			((HelperLog)Utils.logger).LogInfo((object)$"SetHealthAmount calc playerHealth damage: {num3} from {playerHealth} to {num2}");
			player.playerHealth.HurtOther(num3, Vector3.zero, false, -1);
		}

		internal static string GetPlayerName(PlayerAvatar player)
		{
			return Traverse.Create((object)player).Field("playerName").GetValue<string>() ?? "";
		}

		internal static int GetPlayerMaxHealth(PlayerHealth health)
		{
			return Traverse.Create((object)health).Field("maxHealth").GetValue<int>();
		}

		internal static int GetPlayerHealth(PlayerHealth health)
		{
			return Traverse.Create((object)health).Field("health").GetValue<int>();
		}

		internal static bool IsPlayerDead(PlayerAvatar p)
		{
			return Traverse.Create((object)p).Field("isDisabled").GetValue<bool>();
		}

		internal static bool IsPlayerAlive(PlayerAvatar p)
		{
			return !IsPlayerDead(p);
		}

		internal static int GetAlivePlayersCount()
		{
			return Players.Select(IsPlayerAlive).Count();
		}

		internal static bool AnyPlayerAlive()
		{
			return Players.Any(IsPlayerAlive);
		}

		internal static List<PlayerAvatar> GetAlivePlayerEventTargets(bool isMultiplayer)
		{
			if (isMultiplayer)
			{
				return AlivePlayers;
			}
			if (IsPlayerAlive(LocalPlayer))
			{
				return new List<PlayerAvatar> { LocalPlayer };
			}
			return new List<PlayerAvatar>();
		}

		internal static List<PlayerAvatar> GetDeadPlayerEventTargets(bool isMultiplayer)
		{
			if (isMultiplayer)
			{
				return DeadPlayers;
			}
			if (IsPlayerDead(LocalPlayer))
			{
				return new List<PlayerAvatar> { LocalPlayer };
			}
			return new List<PlayerAvatar>();
		}

		internal static List<PlayerAvatar> GetPlayerEventTargets(bool isMultiplayer)
		{
			if (isMultiplayer)
			{
				return Players.ToList();
			}
			return new List<PlayerAvatar> { LocalPlayer };
		}

		internal static bool IsLocalPlayer(PlayerAvatar player)
		{
			if (GameManager.Multiplayer() && !((Object)(object)player.photonView == (Object)null))
			{
				return player.photonView.IsMine;
			}
			return true;
		}

		internal static void TeleportPlayer(PlayerAvatar player, Vector3 pos, Quaternion rot)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (IsLocalPlayer(player))
			{
				PlayerController instance = PlayerController.instance;
				instance.Kinematic(0.5f);
				instance.InputDisable(0.5f);
				instance.CollisionController.ResetFalling();
				instance.VelocityRelative = Vector3.zero;
				instance.Velocity = Vector3.zero;
				Traverse.Create((object)instance).Field<bool>("VelocityIdle").Value = true;
				CoroutineUtils.StartCoroutine((MonoBehaviour)(object)instance, 0.2f, delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_000d: Unknown result type (might be due to invalid IL or missing references)
					player.Spawn(pos, rot);
				});
			}
			else
			{
				player.Spawn(pos, rot);
			}
		}

		internal static GameObject SpawnItem(string name, Vector3 spawnPos, Quaternion rot, bool needLog = true)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			ChaosItemManager.SpawnItem spawnItem = ServiceProvider.inst.itemManager.GetSpawnItem(name);
			if (SemiFunc.IsMasterClient())
			{
				if (needLog)
				{
					((HelperLog)Utils.logger).LogInfo((object)("master network spawn item '" + spawnItem.name + "'"));
				}
				if (string.IsNullOrEmpty(spawnItem.name))
				{
					((HelperLog)Utils.logger).LogError((object)"master network spawn item invalid path");
					return null;
				}
				return PhotonNetwork.InstantiateRoomObject(spawnItem.path, spawnPos, rot, (byte)0, (object[])null);
			}
			if (!SemiFunc.IsMultiplayer())
			{
				if (needLog)
				{
					((HelperLog)Utils.logger).LogInfo((object)("single mode spawn item '" + spawnItem.name + "'"));
				}
				if ((Object)(object)spawnItem.prefab == (Object)null)
				{
					((HelperLog)Utils.logger).LogError((object)"single mode spawn item invalid prefab");
					return null;
				}
				return Object.Instantiate<GameObject>(spawnItem.prefab, spawnPos, rot);
			}
			return null;
		}

		internal static void RegisterItemInGame(string assetName)
		{
			if (string.IsNullOrEmpty(assetName) || !assetName.StartsWith("Item "))
			{
				return;
			}
			StatsManager instance = StatsManager.instance;
			Dictionary<string, Item> itemDictionary = instance.itemDictionary;
			if (itemDictionary != null && itemDictionary.ContainsKey(assetName))
			{
				((HelperLog)Utils.logger).LogInfo((object)"register item");
				if (instance.itemsPurchased.TryGetValue(assetName, out var value))
				{
					instance.itemsPurchased[assetName] = value + 1;
				}
				else
				{
					instance.itemsPurchased[assetName] = 1;
				}
				if (instance.itemsPurchasedTotal.TryGetValue(assetName, out var value2))
				{
					instance.itemsPurchasedTotal[assetName] = value2 + 1;
				}
				else
				{
					instance.itemsPurchasedTotal[assetName] = 1;
				}
			}
			else
			{
				((HelperLog)Utils.logger).LogWarning((object)"registering item in game is skipped");
			}
		}

		internal static void ChargeItem(GameObject obj, float delayInSec, int amount)
		{
			if (!((Object)(object)obj == (Object)null))
			{
				ItemBattery battery = obj.GetComponentInParent<ItemBattery>();
				CoroutineUtils.StartCoroutine((MonoBehaviour)(object)battery, delayInSec, delegate
				{
					int num = amount;
					bool flag = true;
					Traverse obj2 = Traverse.Create((object)battery);
					_ = obj2.Field<PhotonView>("photonView").Value;
					obj2.Method("BatteryFullPercentChange", new object[2] { num, flag }).GetValue();
				});
			}
		}

		internal static T GetRandomLevelPoint<T>(IEnumerable<T> points, T lastUsedPoint, bool useLastUsedPointIfNoOthers = true, bool needLog = true)
		{
			HashSet<T> pointsToIgnore = new HashSet<T> { lastUsedPoint };
			T randomLevelPoint = GetRandomLevelPoint(points, pointsToIgnore, needLog);
			if (randomLevelPoint == null && useLastUsedPointIfNoOthers)
			{
				return lastUsedPoint;
			}
			return randomLevelPoint;
		}

		internal static T GetRandomLevelPoint<T>(IEnumerable<T> points, HashSet<T> pointsToIgnore, bool needLog = true)
		{
			List<T> list = points.Where((T p) => p != null && !pointsToIgnore.Contains(p)).ToList();
			if (list.Count == 0)
			{
				if (needLog)
				{
					((HelperLog)Utils.logger).LogError((object)"can't find points");
				}
				return default(T);
			}
			if (needLog)
			{
				((HelperLog)Utils.logger).LogInfo((object)$"found {list.Count()} valid points of total {points.Count()}");
			}
			if (list.Count == 1)
			{
				return list[0];
			}
			return UtilityRandom.GetRandomItemFromList<T>((IList<T>)list);
		}

		internal static GameObject GetClosestObjectByTag(Vector3 pos, string tag, Func<GameObject, bool> filter, bool needLog = true)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			if (tag == null)
			{
				return null;
			}
			GameObject[] array = GameObject.FindGameObjectsWithTag(tag);
			int num = array.Length;
			if (needLog)
			{
				((HelperLog)Utils.logger).LogInfo((object)$"GetClosestObjectByTag {tag} found {num}");
			}
			if (num == 0)
			{
				return null;
			}
			if (filter != null)
			{
				array = array.Where(filter).ToArray();
				num = array.Length;
				if (needLog)
				{
					((HelperLog)Utils.logger).LogInfo((object)$"GetClosestObjectByTag filtered size {num}");
				}
			}
			if (num == 1)
			{
				return array[0];
			}
			GameObject val = array[0];
			Vector3 val2 = pos - val.transform.position;
			float num2 = ((Vector3)(ref val2)).sqrMagnitude;
			for (int i = 1; i < num; i++)
			{
				GameObject val3 = array[i];
				val2 = pos - val3.transform.position;
				float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
				if (sqrMagnitude < num2)
				{
					val = val3;
					num2 = sqrMagnitude;
				}
			}
			return val;
		}

		internal static ValuableObject GetClosestValuableObject(Vector3 pos, Func<ValuableObject, bool> filter, bool needLog = true)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			ValuableObject[] array = Object.FindObjectsOfType<ValuableObject>();
			int num = array.Length;
			if (needLog)
			{
				((HelperLog)Utils.logger).LogInfo((object)$"GetClosestValuableObject found {num}");
			}
			if (num == 0)
			{
				return null;
			}
			if (filter != null)
			{
				array = array.Where(filter).ToArray();
				num = array.Length;
				if (needLog)
				{
					((HelperLog)Utils.logger).LogInfo((object)$"GetClosestValuableObject filtered size {num}");
				}
			}
			if (num == 1)
			{
				return array[0];
			}
			ValuableObject val = array[0];
			Vector3 val2 = pos - ((Component)val).transform.position;
			float num2 = ((Vector3)(ref val2)).sqrMagnitude;
			for (int i = 1; i < num; i++)
			{
				ValuableObject val3 = array[i];
				val2 = pos - ((Component)val3).transform.position;
				float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
				if (sqrMagnitude < num2)
				{
					val = val3;
					num2 = sqrMagnitude;
				}
			}
			return val;
		}

		internal static GameObject GetClosestCart(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return GetClosestObjectByTag(pos, "Cart", (GameObject item) => (Object)(object)item.GetComponentInParent<PhysGrabCart>() != (Object)null);
		}

		internal static GameObject[] GetObjectsByTag(string tag, Func<GameObject, bool> filter, bool needLog = true)
		{
			if (tag == null)
			{
				return (GameObject[])(object)new GameObject[0];
			}
			GameObject[] array = GameObject.FindGameObjectsWithTag(tag);
			int num = array.Length;
			if (needLog)
			{
				((HelperLog)Utils.logger).LogInfo((object)$"GetObjectsByTag found {num}");
			}
			if (num == 0)
			{
				return (GameObject[])(object)new GameObject[0];
			}
			if (filter != null)
			{
				array = array.Where(filter).ToArray();
				num = array.Length;
				if (needLog)
				{
					((HelperLog)Utils.logger).LogInfo((object)$"GetObjectsByTag filtered size {num}");
				}
			}
			return array;
		}

		internal static GameObject[] GetCarts()
		{
			return GetObjectsByTag("Cart", (GameObject item) => (Object)(object)item.GetComponentInParent<PhysGrabCart>() != (Object)null);
		}

		internal static List<CartObject> GetCartItems(GameObject cart)
		{
			PhysGrabCart componentInParent = cart.GetComponentInParent<PhysGrabCart>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				((HelperLog)Utils.logger).LogWarning((object)"can't find PhysGrabCart");
				return null;
			}
			if ((Object)(object)componentInParent.physGrabInCart == (Object)null)
			{
				((HelperLog)Utils.logger).LogWarning((object)"can't find PhysGrabCart");
				return null;
			}
			List<CartObject> value = Traverse.Create((object)componentInParent.physGrabInCart).Field<List<CartObject>>("inCartObjects").Value;
			if (value == null)
			{
				((HelperLog)Utils.logger).LogWarning((object)"inCartObjects null");
				return null;
			}
			return value;
		}

		internal static Enemy[] GetEnemies()
		{
			return Object.FindObjectsOfType<Enemy>();
		}

		internal static Enemy GetClosestEnemy(Vector3 pos)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			Enemy[] array = Object.FindObjectsOfType<Enemy>();
			int num = array.Length;
			((HelperLog)Utils.logger).LogInfo((object)$"found {num} enemies");
			switch (num)
			{
			case 0:
				return null;
			case 1:
				return array[0];
			default:
			{
				Enemy val = array[0];
				Vector3 val2 = pos - ((Component)val).transform.position;
				float num2 = ((Vector3)(ref val2)).sqrMagnitude;
				for (int i = 1; i < num; i++)
				{
					Enemy val3 = array[i];
					val2 = pos - ((Component)val3).transform.position;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (sqrMagnitude < num2)
					{
						val = val3;
						num2 = sqrMagnitude;
					}
				}
				return val;
			}
			}
		}

		internal static void ActivateTumble(PlayerTumble tumble, PlayerAvatar p, Vector3 force, float rotatePower)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			tumble.TumbleForce(force);
			tumble.TumbleTorque(((Component)tumble).transform.right * rotatePower);
			try
			{
				Traverse.Create((object)tumble).Method("BreakFree", new object[1] { p.localCameraTransform.forward }).GetValue();
			}
			catch (Exception arg)
			{
				((HelperLog)Utils.logger).LogError((object)$"BreakFree error: {arg}");
			}
			tumble.TumbleSet(true, false);
		}

		internal static ExtractionPoint GetCurrentExtractionPoint()
		{
			return Traverse.Create((object)RoundDirector.instance).Field<ExtractionPoint>("extractionPointCurrent").Value;
		}

		internal static Dictionary<RoomVolume, List<LevelPoint>> GetLevelPointsByRoom(bool excludePlayerRooms)
		{
			Dictionary<RoomVolume, List<LevelPoint>> dictionary = new Dictionary<RoomVolume, List<LevelPoint>>();
			List<LevelPoint> list = SemiFunc.LevelPointsGetAll();
			List<LevelPoint> list2 = (excludePlayerRooms ? SemiFunc.LevelPointsGetInPlayerRooms() : new List<LevelPoint>());
			if (list == null)
			{
				return dictionary;
			}
			foreach (LevelPoint item in list)
			{
				if (!((Object)(object)item == (Object)null) && (!excludePlayerRooms || !list2.Contains(item)))
				{
					if (!dictionary.TryGetValue(item.Room, out var value))
					{
						value = new List<LevelPoint>();
						dictionary[item.Room] = value;
					}
					value.Add(item);
				}
			}
			return dictionary;
		}

		internal static List<LevelPoint> GetLevelPoints(bool excludePlayerRooms)
		{
			List<LevelPoint> list = SemiFunc.LevelPointsGetAll();
			if (excludePlayerRooms)
			{
				List<LevelPoint> playerRoomPoints = SemiFunc.LevelPointsGetInPlayerRooms();
				return list.Where((LevelPoint p) => !playerRoomPoints.Contains(p)).ToList();
			}
			return list;
		}

		internal static Vector3 GetPlayerSpawnPoint()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)Object.FindFirstObjectByType<SpawnPoint>()).transform.position;
		}

		internal static Vector3[] GetPlayerSpawnPoints()
		{
			return (from p in Object.FindObjectsOfType<SpawnPoint>()
				where (Object)(object)((Component)p).transform != (Object)null
				select ((Component)p).transform.position).ToArray();
		}

		internal static Vector3 GetFreeOfPlayersFarPointFrom(Vector3 start)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			List<LevelPoint> levelPoints = GetLevelPoints(excludePlayerRooms: true);
			Vector3 result = start;
			float num = 0f;
			foreach (LevelPoint item in levelPoints)
			{
				Vector3 val = ((Component)item).transform.position - start;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (sqrMagnitude > num)
				{
					num = sqrMagnitude;
					result = ((Component)item).transform.position;
				}
			}
			return result;
		}

		public static Vector3 GetClosestSpawnPointTo(Vector3 start)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			List<LevelPoint> levelPoints = GetLevelPoints(excludePlayerRooms: true);
			Vector3 result = start;
			float num = float.MaxValue;
			foreach (LevelPoint item in levelPoints)
			{
				Vector3 val = ((Component)item).transform.position - start;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (sqrMagnitude < num)
				{
					num = sqrMagnitude;
					result = ((Component)item).transform.position;
				}
			}
			return result;
		}

		internal static void SendTruckChatMessage(string message)
		{
			TruckScreenText instance = TruckScreenText.instance;
			if ((Object)(object)instance == (Object)null)
			{
				((HelperLog)Utils.logger).LogWarning((object)"TruckScreenText null");
			}
			else
			{
				instance.MessageSendCustom("", "{arrowright}" + message + "{arrowleft}", 0);
			}
		}

		internal static void SendPlayerTTS(string message, bool crouching)
		{
			PlayerAvatar localPlayer = LocalPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				Traverse.Create((object)localPlayer).Method("ChatMessageSpeak", new object[2] { message, crouching }).GetValue();
			}
		}

		internal static void ShowUIMessage(string message)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			MissionUI instance = MissionUI.instance;
			if ((Object)(object)instance == (Object)null)
			{
				((HelperLog)Utils.logger).LogWarning((object)"MissionUI null");
			}
			else
			{
				instance.MissionText(message, Color.magenta, Color.magenta, 5f);
			}
		}
	}
	internal static class Utils
	{
		internal static readonly Random rnd = new Random(Guid.NewGuid().GetHashCode());

		internal static readonly string modFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

		private const string LOG_FNAME = "latest_log.txt";

		private static readonly string logPath = Path.Combine(modFolder, "latest_log.txt");

		internal static readonly BufferedLogger logger = new BufferedLogger(modFolder, "latest_log.txt", false, 50);

		internal static void LogClearBySize()
		{
			FileInfo fileInfo = new FileInfo(logPath);
			if (fileInfo.Exists && fileInfo.Length > 200000)
			{
				((HelperLog)logger).LogClear();
			}
		}

		internal static string GetRelativeModFilePath(string fname)
		{
			return Path.Combine(modFolder, fname);
		}

		internal static List<T> Shuffle<T>(IEnumerable<T> list)
		{
			if (list == null)
			{
				return new List<T>();
			}
			int num = list.Count();
			if (num <= 1)
			{
				return new List<T>(list);
			}
			List<T> list2 = new List<T>(list);
			for (int i = 0; i < num; i++)
			{
				T value = list2[i];
				int index = rnd.Next(num);
				list2[i] = list2[index];
				list2[index] = value;
			}
			return list2;
		}

		internal static List<T> ShuffleForceRandom<T>(IEnumerable<T> list)
		{
			if (list == null)
			{
				return new List<T>();
			}
			int num = list.Count();
			if (num <= 1)
			{
				return new List<T>(list);
			}
			T[] array = new T[num];
			T[] array2 = list.ToArray();
			List<int> list2 = new List<int>(Enumerable.Range(0, num));
			for (int i = 0; i < num; i++)
			{
				List<int> list3 = new List<int>(list2);
				list3.Remove(i);
				if (list3.Count == 0)
				{
					break;
				}
				int num2 = list3[rnd.Next(list3.Count)];
				array[i] = array2[num2];
				list2.Remove(num2);
			}
			if (list2.Count == 1)
			{
				int num3 = num - 1;
				int num4 = rnd.Next(num3);
				array[num3] = array[num4];
				array[num4] = array2[num3];
			}
			return array.ToList();
		}

		internal static float GetRandomBetween(float min, float max)
		{
			return min + (float)((double)(max - min) * rnd.NextDouble());
		}
	}
}
namespace REPO_BFT_BepInEx.Services
{
	internal class ChaosEnemySpawner
	{
		internal struct EnemyData
		{
			public GameObject prefab;

			public string name;

			public string path;
		}

		private const string BASE_ENEMY_PATH = "Enemies/Enemy - ";

		private readonly Dictionary<string, EnemyData> enemyPrefabs = new Dictionary<string, EnemyData>();

		private int spawnedCount;

		private readonly List<EnemyParent> spawnedEnemies = new List<EnemyParent>();

		private float spawnsCheckInSec;

		internal void RegisterSpawnedEnemyFinished(Enemy enemy)
		{
			CoroutineUtils.StartCoroutine((MonoBehaviour)(object)enemy, 0f, delegate
			{
				EnemyParent componentInParent = ((Component)enemy).GetComponentInParent<EnemyParent>();
				if ((Object)(object)componentInParent == (Object)null)
				{
					((HelperLog)Utils.logger).LogWarning((object)"EnemyParent null. Fix despawning is skipped");
				}
				else
				{
					spawnedEnemies.Add(componentInParent);
				}
			});
		}

		internal void ClearSpawnedEnemies()
		{
			spawnedEnemies.Clear();
		}

		internal void OnUpdate(float dtInSec)
		{
			spawnsCheckInSec -= dtInSec;
			if (spawnsCheckInSec > 0f)
			{
				return;
			}
			spawnsCheckInSec = 0.5f;
			foreach (EnemyParent spawnedEnemy in spawnedEnemies)
			{
				if ((Object)(object)spawnedEnemy != (Object)null && spawnedEnemy.DespawnedTimer > 0f)
				{
					spawnedEnemy.DespawnedTimer = 60f;
				}
			}
		}

		internal Enemy SpawnEnemy(string enemyName, Vector3 spawnPoint)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(enemyName))
			{
				((HelperLog)Utils.logger).LogError((object)"SpawnEnemy invalid name");
				return null;
			}
			EnemyData enemyPrefab = GetEnemyPrefab(enemyName);
			GameObject prefab = enemyPrefab.prefab;
			if ((Object)(object)prefab == (Object)null)
			{
				((HelperLog)Utils.logger).LogError((object)("SpawnEnemy can't find enemy prefab: path '" + enemyPrefab.path + "', name '" + enemyName + "'"));
				return null;
			}
			RunManager.instance.EnemiesSpawnedRemoveStart();
			Enemy val = LevelGeneratorEnemySpawn(prefab, enemyPrefab.path, spawnPoint);
			if ((Object)(object)val == (Object)null)
			{
				((HelperLog)Utils.logger).LogWarning((object)"ChaosEnemySpawner->SpawnEnemy Enemy component is null");
			}
			else
			{
				((Object)val).name = $"Chaos Tricks custom mob [{enemyName}] [{spawnedCount++}]";
				foreach (PlayerAvatar player in GameUtils.Players)
				{
					val.PlayerAdded(player.photonView.ViewID);
				}
			}
			SemiFunc_EnemySpawnPatcher.AddEnemyToBlockInGameSpawn(val);
			RunManager.instance.EnemiesSpawnedRemoveEnd();
			return val;
		}

		private Enemy LevelGeneratorEnemySpawn(GameObject prefab, string path, Vector3 position)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = ((GameManager.instance.gameMode != 0) ? PhotonNetwork.InstantiateRoomObject(path, position, Quaternion.identity, (byte)0, (object[])null) : Object.Instantiate<GameObject>(prefab, position, Quaternion.identity));
			EnemyParent component = val.GetComponent<EnemyParent>();
			if (Object.op_Implicit((Object)(object)component))
			{
				Traverse.Create((object)component).Field<bool>("SetupDone").Value = true;
				Enemy componentInChildren = val.GetComponentInChildren<Enemy>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.EnemyTeleported(position);
					Traverse<int> obj = Traverse.Create((object)LevelGenerator.Instance).Field<int>("EnemiesSpawnTarget");
					int value = obj.Value;
					obj.Value = value + 1;
					EnemyDirector.instance.FirstSpawnPointAdd(component);
				}
				return componentInChildren;
			}
			((HelperLog)Utils.logger).LogWarning((object)("LevelGeneratorEnemySpawn can't find EnemyParent component for '" + path + "'"));
			return null;
		}

		private EnemyData GetEnemyPrefab(string name)
		{
			if (enemyPrefabs.TryGetValue(name, out var value) && (Object)(object)value.prefab != (Object)null)
			{
				return value;
			}
			string enemyPath = GetEnemyPath(name);
			EnemyData enemyData = default(EnemyData);
			enemyData.name = name;
			enemyData.path = enemyPath;
			enemyData.prefab = Resources.Load<GameObject>(enemyPath);
			EnemyData enemyData2 = enemyData;
			enemyPrefabs[name] = enemyData2;
			return enemyData2;
		}

		private string GetEnemyPath(string name)
		{
			return "Enemies/Enemy - " + name;
		}
	}
	internal class ChaosItemManager
	{
		internal struct SpawnItem
		{
			public GameObject prefab;

			public string name;

			public string path;
		}

		private readonly Dictionary<string, SpawnItem> prefabs;

		internal static readonly string itemsBasePath = "Items/";

		internal static readonly string removedItemsBasePath = "Items/Removed Items/";

		internal static readonly string valuablesBasePath = "Valuables/";

		internal static readonly string[] valuableCategories = new string[7] { "01 Tiny", "02 Small", "03 Medium", "04 Big", "05 Wide", "06 Tall", "07 Very Tall" };

		internal ChaosItemManager()
		{
			prefabs = new Dictionary<string, SpawnItem>();
		}

		internal SpawnItem GetSpawnItem(string name)
		{
			if (prefabs.TryGetValue(name, out var value))
			{
				if ((Object)(object)value.prefab != (Object)null)
				{
					return value;
				}
				value.prefab = Resources.Load<GameObject>(value.path);
				prefabs[value.name] = value;
				return value;
			}
			SpawnItem result = TryToFindObject(name);
			if ((Object)(object)result.prefab == (Object)null)
			{
				((HelperLog)Utils.logger).LogError((object)("can't load prefab for '" + name + "'"));
			}
			return result;
		}

		private void LoadObjects(string basePath)
		{
			GameObject[] array = Resources.LoadAll<GameObject>(basePath);
			foreach (GameObject val in array)
			{
				string path = basePath + ((Object)val).name;
				prefabs[((Object)val).name] = new SpawnItem
				{
					prefab = val,
					name = ((Object)val).name,
					path = path
				};
			}
		}

		internal void LoadAllObjects()
		{
			try
			{
				LoadObjects(removedItemsBasePath);
				LoadObjects(itemsBasePath);
				LoadObjects(valuablesBasePath);
				string[] array = valuableCategories;
				foreach (string text in array)
				{
					LoadObjects(valuablesBasePath + text + "/");
				}
			}
			catch (Exception arg)
			{
				((HelperLog)Utils.logger).LogError((object)$"ChaosItemManager->LoadAllObjects {arg}");
			}
		}

		private SpawnItem LoadObjectWithFilter(string basePath, string targetName)
		{
			GameObject[] array = Resources.LoadAll<GameObject>(basePath);
			foreach (GameObject val in array)
			{
				if (targetName == ((Object)val).name)
				{
					string path = basePath + ((Object)val).name;
					SpawnItem spawnItem = default(SpawnItem);
					spawnItem.prefab = val;
					spawnItem.name = ((Object)val).name;
					spawnItem.path = path;
					SpawnItem spawnItem2 = spawnItem;
					prefabs[((Object)val).name] = spawnItem2;
					return spawnItem2;
				}
			}
			return default(SpawnItem);
		}

		private SpawnItem TryToFindObject(string targetName)
		{
			string[] array = valuableCategories;
			foreach (string text in array)
			{
				SpawnItem result = LoadObjectWithFilter(valuablesBasePath + text + "/", targetName);
				if ((Object)(object)result.prefab != (Object)null)
				{
					return result;
				}
			}
			SpawnItem result2 = LoadObjectWithFilter(valuablesBasePath, targetName);
			if ((Object)(object)result2.prefab != (Object)null)
			{
				return result2;
			}
			result2 = LoadObjectWithFilter(itemsBasePath, targetName);
			if ((Object)(object)result2.prefab != (Object)null)
			{
				return result2;
			}
			return LoadObjectWithFilter(removedItemsBasePath, targetName);
		}
	}
	internal class ChaosModNetwork : MonoBehaviour
	{
		internal struct DataSource
		{
			public int playerID;

			public string eventID;
		}

		private static ChaosModNetwork inst;

		private PhotonView photonView;

		private static Queue<DataSource> commandQueue;

		private static readonly HashSet<string> shouldBeRunFromHost = new HashSet<string>
		{
			"all_buff_hp_average", "all_goal_dec", "all_goal_inc", "solo_debuff_item_boom", "all_debuff_kill_rand", "all_cart_spread", "active_nade_stun", "active_nade_shock", "active_nade_expl", "active_nade_duck",
			"spawn_duck", "spawn_spewer", "spawn_upscream", "spawn_alien", "spawn_animal", "spawn_baby", "spawn_thinman", "spawn_hidden", "spawn_frog", "spawn_bowtie",
			"spawn_huntsman", "spawn_head", "spawn_trudge", "spawn_clown", "spawn_robe", "spawn_reaper", "item_health_small", "item_health_med", "item_health_big", "item_crystal",
			"item_nade_stun", "item_nade_shock", "item_nade_expl", "item_nade_f1", "item_nade_duck_f1", "item_mine_stun", "item_mine_shock", "item_mine_expl", "item_rubber_duck", "item_book_roll",
			"item_book_speed", "item_book_energy", "item_book_health", "item_book_range", "item_book_strength", "item_book_jump", "item_drone_roll", "item_drone_gravity", "item_drone_feather", "item_drone_energy",
			"item_drone_shield", "item_sphere_gravity", "item_frying_pan", "item_inflatable_hammer", "item_sword", "item_baseball_bat", "item_sledge_hammer", "item_valuable_tracker", "item_extraction_tracker", "item_cart_small",
			"item_cart_medium", "item_tranq", "item_handgun", "item_shotgun", "loot_rand_small", "loot_rand_med", "loot_rand_big", "loot_money_rain", "loot_frog", "loot_bottle",
			"loot_love_potion", "loot_gramophone", "loot_power_crystal", "loot_fan", "loot_clown", "loot_guitar", "loot_propane_tank", "loot_music_box", "loot_television", "loot_flamethrower",
			"loot_saw", "loot_time_glass", "loot_doll", "loot_barrel", "loot_sword", "loot_staff", "loot_animal_crate", "loot_creature_leg", "loot_ice_block", "loot_broom",
			"loot_painting", "loot_harp", "loot_grandfather_clock", "loot_golden_statue", "loot_science_station", "loot_server_rack", "loot_dinosaur", "loot_griffin_statue", "loot_piano", "solo_frogs_around",
			"solo_poop_diamonds", "solo_poop_mines", "solo_poop_nades", "loot_rand_enemy", "all_stun_enemies", "all_cart_teleport_rand", "all_cart_teleport_start", "all_teleport_rand", "solo_teleport_start", "all_teleport_start",
			"all_teleport_shuffle", "solo_upgrade_roll", "solo_upgrade_speed", "solo_upgrade_energy", "solo_upgrade_health", "solo_upgrade_range", "solo_upgrade_strength", "solo_upgrade_jump"
		};

		private void Awake()
		{
			inst = this;
			photonView = ((Component)this).GetComponent<PhotonView>();
			commandQueue = new Queue<DataSource>();
		}

		[PunRPC]
		private void ActivateEventOtherRPC(string eventID)
		{
			((HelperLog)Utils.logger).LogInfo((object)("ChaosModNetwork->ActivateEventOtherRPC triggered for " + eventID));
		}

		[PunRPC]
		private void ActivateClientEventRPC(int playerID, string eventID)
		{
			((HelperLog)Utils.logger).LogInfo((object)$"ChaosModNetwork->ActivateClientEventRPC triggered for {playerID} {eventID}");
			if (commandQueue == null)
			{
				((HelperLog)Utils.logger).LogError((object)"ChaosModNetwork->ActivateClientEventRPC an attempt to store events before initiating");
				return;
			}
			commandQueue.Enqueue(new DataSource
			{
				eventID = eventID,
				playerID = playerID
			});
		}

		internal static void RequestEventOther(string eventID)
		{
			((HelperLog)Utils.logger).LogInfo((object)("ChaosModNetwork->RequestEventOther triggered for " + eventID));
			try
			{
				inst.photonView.RPC("ActivateEventOtherRPC", (RpcTarget)1, new object[1] { eventID });
			}
			catch (Exception arg)
			{
				((HelperLog)Utils.logger).LogError((object)$"ChaosModNetwork->RequestEventOther error: {arg}");
			}
		}

		internal static void RequestClientEventRPC(int userID, string eventID)
		{
			((HelperLog)Utils.logger).LogInfo((object)$"ChaosModNetwork->RequestClientEventRPC triggered for {userID} {eventID}");
			try
			{
				inst.photonView.RPC("ActivateClientEventRPC", (RpcTarget)2, new object[2] { userID, eventID });
			}
			catch (Exception arg)
			{
				((HelperLog)Utils.logger).LogError((object)$"ChaosModNetwork->RequestClientEventRPC error: {arg}");
			}
		}

		internal static bool NeedRunFromHost(string eventID)
		{
			return shouldBeRunFromHost.Contains(eventID);
		}

		internal static void ProcessNetworkEvents(ICommandManager cm, Dictionary<string, IRepoStandaloneCommand> commands)
		{
			while (commandQueue.Count > 0)
			{
				try
				{
					DataSource dataSource = commandQueue.Dequeue();
					((HelperLog)Utils.logger).LogInfo((object)$"ChaosModNetwork->ProcessEvents event id {dataSource.eventID} for {dataSource.playerID}");
					PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonID(dataSource.playerID);
					if ((Object)(object)val == (Object)null)
					{
						((HelperLog)Utils.logger).LogWarning((object)"ChaosModNetwork->ProcessEvents can't find player. Skip event");
						continue;
					}
					string text = cm.GetCommandData(dataSource.eventID, true)?.Trim();
					if (string.IsNullOrEmpty(text))
					{
						((HelperLog)Utils.logger).LogWarning((object)"ChaosModNetwork->ProcessEvents can't find commands");
					}
					else
					{
						ProcessCommandLines(UtilityConsole.ParseCommandLine(text), val, commands);
					}
				}
				catch (Exception arg)
				{
					((HelperLog)Utils.logger).LogError((object)$"ChaosModNetwork->ProcessEvents: {arg}");
				}
			}
		}

		private static void ProcessCommandLines(string[] lines, PlayerAvatar player, Dictionary<string, IRepoStandaloneCommand> commands)
		{
			for (int i = 0; i < lines.Length; i++)
			{
				string[] array = UtilityConsole.ParseArgs(lines[i]);
				string key = array[0];
				try
				{
					IRepoStandaloneCommand repoStandaloneCommand = commands[key];
					if (repoStandaloneCommand is INetworkCommand networkCommand)
					{
						networkCommand.Execute(array.Skip(1), player);
					}
					else
					{
						((IConsoleCommand)repoStandaloneCommand).Execute(array.Skip(1));
					}
				}
				catch (Exception arg)
				{
					((HelperLog)Utils.logger).LogError((object)$"ChaosModNetwork->ProcessEvents: {arg}");
				}
			}
		}
	}
	internal class CommandListArgManager
	{
		internal class Group
		{
			[JsonProperty("drop_variants")]
			public DropVariant[] dropVariants;
		}

		internal class DropVariant
		{
			public string[] items;
		}

		private Dictionary<string, Group> groups;

		private Dictionary<string, string[]> simpleGroups;

		internal CommandListArgManager()
		{
		}

		internal void LoadCommandsList()
		{
			try
			{
				string relativeModFilePath = Utils.GetRelativeModFilePath("drop_groups.data");
				groups = UtilityJson.Generate((IDebugLogger)(object)Utils.logger).FromFile<Dictionary<string, Group>>(relativeModFilePath);
			}
			catch (Exception arg)
			{
				((HelperLog)Utils.logger).LogError((object)$"CommandListArgManager groups init error: {arg}");
			}
			try
			{
				string relativeModFilePath2 = Utils.GetRelativeModFilePath("drop_simple_groups.data");
				simpleGroups = UtilityJson.Generate((IDebugLogger)(object)Utils.logger).FromFile<Dictionary<string, string[]>>(relativeModFilePath2);
			}
			catch (Exception arg2)
			{
				((HelperLog)Utils.logger).LogError((object)$"CommandListArgManager simple groups init error: {arg2}");
			}
		}

		internal DropVariant GetRandomDropVariant(string groupName)
		{
			if (groups == null)
			{
				((HelperLog)Utils.logger).LogWarning((object)"CommandListArgManager groups null");
				return null;
			}
			if (!groups.TryGetValue(groupName, out var value))
			{
				((HelperLog)Utils.logger).LogWarning((object)("CommandListArgManager can't find group " + groupName));
				return null;
			}
			if (value == null || value.dropVariants == null || value.dropVariants.Length == 0)
			{
				((HelperLog)Utils.logger).LogWarning((object)("CommandListArgManager drop variants empty for " + groupName));
				return null;
			}
			return UtilityRandom.GetRandomItemFromList<DropVariant>((IList<DropVariant>)value.dropVariants);
		}

		internal string[] GetRandomDropVariantPaths(string groupName)
		{
			DropVariant randomDropVariant = GetRandomDropVariant(groupName);
			if (randomDropVariant == null || randomDropVariant.items == null)
			{
				return new string[0];
			}
			return randomDropVariant.items.Select((string s) => CommandArgsReaderWrapper.ParseItemPath(s)).ToArray();
		}

		internal string GetRandomDropFromSimpleGroup(string groupName)
		{
			if (simpleGroups == null)
			{
				((HelperLog)Utils.logger).LogWarning((object)"CommandListArgManager simpleGroups null");
				return null;
			}
			if (!simpleGroups.TryGetValue(groupName, out var value))
			{
				((HelperLog)Utils.logger).LogWarning((object)("CommandListArgManager can't find simple group " + groupName));
				return null;
			}
			return CommandArgsReaderWrapper.ParseItemPath(UtilityRandom.GetRandomItemFromList<string>((IList<string>)value));
		}

		internal bool IsSimpeGroup(string name)
		{
			if (simpleGroups != null)
			{
				return simpleGroups.ContainsKey(name);
			}
			return false;
		}
	}
	internal sealed class EventEmitter
	{
		private enum Event
		{
			OnUpdate,
			OnConfigChangedThreadSafe
		}

		private class EmitterAction
		{
			public string id;

			public Action<object, object> action;
		}

		private readonly ILogger logger = (ILogger)(object)new LimitedLogWrapper(100, (IDebugLogger)(object)Utils.logger);

		private readonly Dictionary<Event, List<EmitterAction>> eventHandlers;

		internal EventEmitter()
		{
			eventHandlers = new Dictionary<Event, List<EmitterAction>>();
			foreach (Event item in Enum.GetValues(typeof(Event)).OfType<Event>())
			{
				eventHandlers[item] = new List<EmitterAction>();
			}
		}

		private void ReplaceOrAddHandler(Event key, string id, Action<object, object> handler)
		{
			if (id != null)
			{
				eventHandlers[key].RemoveAll((EmitterAction action) => action.id == id);
			}
			eventHandlers[key].Add(new EmitterAction
			{
				action = handler,
				id = id
			});
		}

		private void TriggerEvent(Event key, object sender, object data)
		{
			try
			{
				if (!eventHandlers.TryGetValue(key, out var value))
				{
					return;
				}
				foreach (EmitterAction item in value)
				{
					try
					{
						item.action(sender, data);
					}
					catch (Exception arg)
					{
						logger.LogError((object)$"EventEmitter->TriggerEvent inner {key} error: {arg}");
					}
				}
			}
			catch (Exception arg2)
			{
				logger.LogError((object)$"EventEmitter->TriggerEvent {key} error: {arg2}");
			}
		}

		internal void ReplaceOrAddOnUpdateHandler(string id, Action<object, float> handler)
		{
			ReplaceOrAddHandler(Event.OnUpdate, id, delegate(object sender, object data)
			{
				handler(sender, (float)data);
			});
		}

		internal void TriggerOnUpdateEvent(object sender, float dtInSec)
		{
			TriggerEvent(Event.OnUpdate, sender, dtInSec);
		}

		internal void ReplaceOrAddOnConfigChanged_ThreadSafeHandler(string id, Action<object, SettingsData> handler)
		{
			ReplaceOrAddHandler(Event.OnConfigChangedThreadSafe, id, delegate(object sender, object settings)
			{
				handler(sender, (SettingsData)settings);
			});
		}

		internal void TriggerOnConfigChangedEvent_ThreadSafe(object sender, SettingsData settings)
		{
			TriggerEvent(Event.OnConfigChangedThreadSafe, sender, settings);
		}
	}
	internal static class ExplodeManager
	{
		private static GameObject explodePrefab;

		private static void CheckPrefab()
		{
			if ((Object)(object)explodePrefab == (Object)null)
			{
				explodePrefab = Resources.Load<GameObject>("Effects/Part Prefab Explosion");
			}
		}

		private static void InternalExplode(Vector3 pos, float expSize, int expDamage, float forceMult)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			CheckPrefab();
			ParticlePrefabExplosion component = Object.Instantiate<GameObject>(explodePrefab, pos, Quaternion.identity).GetComponent<ParticlePrefabExplosion>();
			component.forceMultiplier = forceMult;
			Traverse obj = Traverse.Create((object)component);
			obj.Field<float>("explosionSize").Value = expSize;
			obj.Field<int>("explosionDamage").Value = expDamage;
		}

		internal static void CreateExplodeNearPlayer(PlayerAvatar player, float offset, float expSize, int expDamage, float forceMult)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			InternalExplode(GameUtils.GetPlayerForward(((Component)player).transform, offset), expSize, expDamage, forceMult);
		}

		internal static GameObject ExplodeGrabItem(PlayerAvatar player, float expSize, int expDamage, float forceMult)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			PhysGrabber physGrabber = player.physGrabber;
			if (!physGrabber.grabbed)
			{
				((HelperLog)Utils.logger).LogInfo((object)"ExplodeGrabItem no item in hands");
				return null;
			}
			InternalExplode(physGrabber.grabbedObjectTransform.position, expSize, expDamage, forceMult);
			return ((Component)physGrabber.grabbedObjectTransform).gameObject;
		}

		internal static ValuableObject ExplodeClosestItem(PlayerAvatar player, float expSize, int expDamage, float forceMult)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			ValuableObject closestValuableObject = GameUtils.GetClosestValuableObject(((Component)player).transform.position, null);
			if ((Object)(object)closestValuableObject == (Object)null)
			{
				((HelperLog)Utils.logger).LogInfo((object)"ExplodeGrabItem no item found");
				return null;
			}
			InternalExplode(((Component)closestValuableObject).transform.position, expSize, expDamage, forceMult);
			return closestValuableObject;
		}
	}
	internal sealed class ServiceProvider
	{
		internal static readonly ServiceProvider inst = new ServiceProvider();

		internal ScheduleManager systemScheduleManager;

		internal ScheduleManager scheduleManager;

		internal EventEmitter eventEmitter;

		internal ChaosItemManager itemManager;

		internal CommandListArgManager commandListArgManager;

		internal ChaosEnemySpawner enemySpawner;

		internal void RegisterSystemScheduleManager(ScheduleManager systemScheduleManager)
		{
			this.systemScheduleManager = systemScheduleManager;
		}

		internal void RegisterScheduleManager(ScheduleManager scheduleManager)
		{
			this.scheduleManager = scheduleManager;
		}

		internal void RegisterEventEmitter(EventEmitter eventEmitter)
		{
			this.eventEmitter = eventEmitter;
		}

		internal void RegisterItemManager(ChaosItemManager itemManager)
		{
			this.itemManager = itemManager;
		}

		internal void RegisterCommandListArgManager(CommandListArgManager commandListArgManager)
		{
			this.commandListArgManager = commandListArgManager;
		}

		internal void RegisterEnemySpawner(ChaosEnemySpawner enemySpawner)
		{
			this.enemySpawner = enemySpawner;
		}
	}
	internal sealed class SettingsData
	{
		internal bool ApplySpawnEventsForAll { get; set; } = true;


		internal bool ApplyEffectEventsForAll { get; set; } = true;

	}
	internal static class SettingsManager
	{
		private static SettingsData newData;

		internal static SettingsData Data { get; private set; } = new SettingsData();


		internal static void QueueUpdateSettings(SettingsData data)
		{
			newData = data;
		}

		internal static void OnUpdate()
		{
			if (newData != null)
			{
				Data = newData;
				ServiceProvider.inst.eventEmitter.TriggerOnConfigChangedEvent_ThreadSafe(null, newData);
				newData = null;
			}
		}
	}
	internal class TranslationService
	{
		public readonly ITranslation translation;

		internal TranslationService()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			translation = (ITranslation)new HelperLanguagesFormatted((IDebugLogger)(object)Utils.logger);
		}

		public void LoadData()
		{
			translation.InitFromFile(Utils.GetRelativeModFilePath("langs.data"));
		}
	}
}
namespace REPO_BFT_BepInEx.Wrappers
{
	internal class CommandArgsReaderWrapper
	{
		private readonly IEnumerator<string> args;

		private readonly CommandArgsReader reader;

		public CommandArgsReaderWrapper(IEnumerable<string> args)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			this.args = args?.GetEnumerator();
			reader = new CommandArgsReader((ILogger)(object)Utils.logger);
		}

		public int ReadInt(int defaultValue = 0)
		{
			return reader.ReadInt(args, defaultValue);
		}

		public float ReadFloat(float defaultValue = 0f)
		{
			return reader.ReadFloat(args, defaultValue);
		}

		public string ReadString(string defaultValue = "")
		{
			return reader.ReadString(args, defaultValue);
		}

		public string ReadSpacedString(string defaultValue = "")
		{
			return ParseItemPath(reader.ReadString(args, defaultValue));
		}

		public static string ParseItemPath(string path)
		{
			return path?.Replace("_", " ");
		}

		public bool ReadBool(bool defaultValue = false)
		{
			return reader.ReadBool(args, defaultValue);
		}
	}
	internal class LimitedLogWrapper : IDebugLogger, ILoggerWithConsole, ILogger
	{
		private readonly IDebugLogger logger;

		private int messagesLimit;

		internal LimitedLogWrapper(int messagesLimit, IDebugLogger logger)
		{
			this.logger = logger;
			this.messagesLimit = messagesLimit;
		}

		public void Log(object obj)
		{
			if (messagesLimit > 0)
			{
				messagesLimit--;
				((ILogger)logger).Log(obj);
			}
		}

		public void LogClear()
		{
			((ILogger)logger).LogClear();
		}

		public void LogDebugInfo(object obj)
		{
			if (messagesLimit > 0)
			{
				messagesLimit--;
				logger.LogDebugInfo(obj);
			}
		}

		public void LogDebugWarning(object obj)
		{
			if (messagesLimit > 0)
			{
				messagesLimit--;
				logger.LogDebugWarning(obj);
			}
		}

		public void LogDebugError(object obj)
		{
			if (messagesLimit > 0)
			{
				messagesLimit--;
				logger.LogDebugError(obj);
			}
		}

		public void LogInfo(object obj)
		{
			if (messagesLimit > 0)
			{
				messagesLimit--;
				((ILogger)logger).LogInfo(obj);
			}
		}

		public void LogInfoConsoleOnly(object obj)
		{
			if (messagesLimit > 0)
			{
				messagesLimit--;
				((ILoggerWithConsole)logger).LogInfoConsoleOnly(obj);
			}
		}

		public void LogInfoFileOnly(object obj)
		{
			if (messagesLimit > 0)
			{
				messagesLimit--;
				((ILoggerWithConsole)logger).LogInfoFileOnly(obj);
			}
		}

		public void LogWarning(object obj)
		{
			if (messagesLimit > 0)
			{
				messagesLimit--;
				((ILogger)logger).LogWarning(obj);
			}
		}

		public void LogWarningConsoleOnly(object obj)
		{
			if (messagesLimit > 0)
			{
				messagesLimit--;
				((ILoggerWithConsole)logger).LogWarningConsoleOnly(obj);
			}
		}

		public void LogWarningFileOnly(object obj)
		{
			if (messagesLimit > 0)
			{
				messagesLimit--;
				((ILoggerWithConsole)logger).LogWarningFileOnly(obj);
			}
		}

		public void LogError(object obj)
		{
			if (messagesLimit > 0)
			{
				messagesLimit--;
				((ILogger)logger).LogError(obj);
			}
		}

		public void LogErrorConsoleOnly(object obj)
		{
			if (messagesLimit > 0)
			{
				messagesLimit--;
				((ILoggerWithConsole)logger).LogErrorConsoleOnly(obj);
			}
		}

		public void LogErrorFileOnly(object obj)
		{
			if (messagesLimit > 0)
			{
				messagesLimit--;
				((ILoggerWithConsole)logger).LogErrorFileOnly(obj);
			}
		}

		public void UpdateLimit(int limit)
		{
			messagesLimit = limit;
		}
	}
}
namespace REPO_BFT_BepInEx.Patchers
{
	internal static class ChaosInputManager
	{
		private static readonly Dictionary<InputKey, bool> blockedKeys = new Dictionary<InputKey, bool>();

		private static readonly Dictionary<InputKey, bool> holdKeys = new Dictionary<InputKey, bool>();

		internal static float mouseSpeedCoeffX = 1f;

		internal static float mouseSpeedCoeffY = 1f;

		internal static void BlockKey(InputKey key)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			blockedKeys[key] = true;
		}

		internal static void UnblockKey(InputKey key)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			blockedKeys[key] = false;
		}

		internal static void UnblockAll()
		{
			blockedKeys.Clear();
		}

		internal static bool IsKeyBlocked(InputKey key)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (blockedKeys.TryGetValue(key, out var value))
			{
				return value;
			}
			return false;
		}

		internal static void HoldKey(InputKey key)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			holdKeys[key] = true;
		}

		internal static void UnholdKey(InputKey key)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			holdKeys[key] = false;
		}

		internal static void UnholdAll()
		{
			holdKeys.Clear();
		}

		internal static bool IsKeyHold(InputKey key)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (holdKeys.TryGetValue(key, out var value))
			{
				return value;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(InputManager), "KeyDown")]
	internal class InputManager_KeyDownPatcher
	{
		private static bool Prefix(ref bool __result, InputKey key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (ChaosInputManager.IsKeyBlocked(key))
			{
				__result = false;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(InputManager), "KeyHold")]
	internal class InputManager_KeyHoldPatcher
	{
		internal static bool Prefix(ref bool __result, InputKey key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (ChaosInputManager.IsKeyBlocked(key))
			{
				__result = false;
				return false;
			}
			if (ChaosInputManager.IsKeyHold(key))
			{
				__result = true;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(InputManager), "GetMouseX")]
	internal class InputManager_MouseX_Patcher
	{
		internal static void Postfix(ref float __result)
		{
			__result *= ChaosInputManager.mouseSpeedCoeffX;
		}
	}
	[HarmonyPatch(typeof(InputManager), "GetMouseY")]
	internal class InputManager_MouseY_Patcher
	{
		internal static void Postfix(ref float __result)
		{
			__result *= ChaosInputManager.mouseSpeedCoeffY;
		}
	}
	internal static class MainPatcher
	{
		private static bool isPatched;

		internal static void InitPatch()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (isPatched)
			{
				return;
			}
			isPatched = true;
			try
			{
				((HelperLog)Utils.logger).Log((object)"MainPatcher init");
				new Harmony("com.Loki.patch").PatchAll(Assembly.GetExecutingAssembly());
			}
			catch (Exception arg)
			{
				((HelperLog)Utils.logger).LogError((object)$"MainPatcher error: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "Awake")]
	internal class PlayerAvatarPatcher
	{
		internal static void Postfix(PlayerAvatar __instance)
		{
			if ((Object)(object)((Component)__instance).GetComponent<ChaosModNetwork>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<ChaosModNetwork>();
			}
		}
	}
	[HarmonyPatch(typeof(SemiFunc), "EnemySpawn")]
	internal class SemiFunc_EnemySpawnPatcher
	{
		private static readonly HashSet<Enemy> enemiesToBlockInGameSpawn = new HashSet<Enemy>();

		internal static void AddEnemyToBlockInGameSpawn(Enemy enemy)
		{
			if (!((Object)(object)enemy == (Object)null))
			{
				enemiesToBlockInGameSpawn.Add(enemy);
			}
		}

		internal static void ClearBlockEnemies()
		{
			enemiesToBlockInGameSpawn.Clear();
		}

		private static bool Prefix(ref bool __result, Enemy enemy)
		{
			if (enemiesToBlockInGameSpawn.Contains(enemy))
			{
				((HelperLog)Utils.logger).LogInfo((object)("semi spawn for enemy '" + ((Object)enemy).name + "' is blocked"));
				enemiesToBlockInGameSpawn.Remove(enemy);
				ServiceProvider.inst.enemySpawner.RegisterSpawnedEnemyFinished(enemy);
				__result = false;
				return false;
			}
			return true;
		}
	}
}
namespace REPO_BFT_BepInEx.Commands
{
	internal class AddExtractGoal : IRepoStandaloneCommand, IConsoleCommand, INetworkCommand
	{
		public string Id => "add_extract_goal";

		public bool Execute(IEnumerable<string> args)
		{
			int num = new CommandArgsReaderWrapper(args).ReadInt();
			Traverse obj = Traverse.Create((object)RoundDirector.instance);
			int value = obj.Field<int>("extractionHaulGoal").Value;
			Traverse.Create((object)obj.Field<ExtractionPoint>("extractionPointCurrent").Value).Method("HaulGoalSet", new object[1] { Mathf.Max(1, value + num) }).GetValue();
			return true;
		}

		public bool Execute(IEnumerable<string> args, PlayerAvatar targetPlayer)
		{
			return Execute(args);
		}

		public bool IsValidCommandArgs(IEnumerable<string> args)
		{
			throw new NotImplementedException();
		}
	}
	internal class ApplyForceMoveImpulse : IRepoStandaloneCommand, IConsoleCommand
	{
		public string Id => "force_move";

		public bool Execute(IEnumerable<string> args)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			CommandArgsReaderWrapper commandArgsReaderWrapper = new CommandArgsReaderWrapper(args);
			float num = commandArgsReaderWrapper.ReadFloat();
			float num2 = commandArgsReaderWrapper.ReadFloat();
			float num3 = commandArgsReaderWrapper.ReadFloat();
			GameUtils.LocalPlayer.ForceImpulse(new Vector3(num, num2, num3));
			return true;
		}

		public bool IsValidCommandArgs(IEnumerable<string> args)
		{
			throw new NotImplementedException();
		}
	}
	internal class ApplyForceRigitBody : IRepoStandaloneCommand, IConsoleCommand
	{
		public string Id => "force_rb";

		public bool Execute(IEnumerable<string> args)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			CommandArgsReaderWrapper commandArgsReaderWrapper = new CommandArgsReaderWrapper(args);
			float num = commandArgsReaderWrapper.ReadFloat();
			float num2 = commandArgsReaderWrapper.ReadFloat();
			float num3 = commandArgsReaderWrapper.ReadFloat();
			float rotatePower = commandArgsReaderWrapper.ReadFloat(10f);
			PlayerAvatar localPlayer = GameUtils.LocalPlayer;
			GameUtils.ActivateTumble(localPlayer.tumble, localPlayer, new Vector3(num, num2, num3), rotatePower);
			return true;
		}

		public bool IsValidCommandArgs(IEnumerable<string> args)
		{
			throw new NotImplementedException();
		}
	}
	internal class ApplyRelForceMoveImpulse : IRepoStandaloneCommand, IConsoleCommand
	{
		public string Id => "rel_force_move";

		public bool Execute(IEnumerable<string> args)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			CommandArgsReaderWrapper commandArgsReaderWrapper = new CommandArgsReaderWrapper(args);
			float num = commandArgsReaderWrapper.ReadFloat();
			float num2 = commandArgsReaderWrapper.ReadFloat();
			Transform transform = ((Component)GameUtils.LocalPlayer).transform;
			Vector3 val = transform.forward;
			Vector3 val2 = ((Vector3)(ref val)).normalized * num;
			val = transform.right;
			Vector3 val3 = ((Vector3)(ref val)).normalized * (0f - num2);
			PlayerAvatar localPlayer = GameUtils.LocalPlayer;
			Traverse val4 = Traverse.Create((object)localPlayer);
			Vector3 val5 = val2 + val3;
			localPlayer.ForceImpulse(val5);
			if (val4.Field<bool>("isCrouching").Value || val4.Field<bool>("isCrawling").Value)
			{
				((HelperLog)Utils.logger).LogInfo((object)"add push v2");
				GameUtils.ActivateTumble(localPlayer.tumble, localPlayer, val5, 10f);
				return true;
			}
			return true;
		}

		public bool IsValidCommandArgs(IEnumerable<string> args)
		{
			throw new NotImplementedException();
		}
	}
	internal class AveragePlayersHealth : IRepoStandaloneCommand, IConsoleCommand, INetworkCommand
	{
		public string Id => "avg_players_hp";

		public bool Execute(IEnumerable<string> args)
		{
			List<PlayerAvatar> alivePlayers = GameUtils.AlivePlayers;
			int amount = alivePlayers.Select((PlayerAvatar p) => GameUtils.GetPlayerHealth(p.playerHealth)).Sum() / alivePlayers.Count;
			foreach (PlayerAvatar item in alivePlayers)
			{
				GameUtils.SetHealthAmount(item, amount, keepAlive: true);
			}
			return true;
		}

		public bool Execute(IEnumerable<string> args, PlayerAvatar targetPlayer)
		{
			return Execute(args);
		}

		public bool IsValidCommandArgs(IEnumerable<string> args)
		{
			throw new NotImplementedException();
		}
	}
	internal class ChangeExtractGoalPercents : IRepoStandaloneCommand, IConsoleCommand, INetworkCommand
	{
		public string Id => "change_extract_goal_percents";

		public bool Execute(IEnumerable<string> args)
		{
			float num = new CommandArgsReaderWrapper(args).ReadFloat();
			Traverse obj = Traverse.Create((object)RoundDirector.instance);
			int value = obj.Field<int>("extractionHaulGoal").Value;
			Traverse.Create((object)obj.Field<ExtractionPoint>("extractionPointCurrent").Value).Method("HaulGoalSet", new object[1] { Mathf.Max(1, (int)((float)value * num)) }).GetValue();
			return true;
		}

		public bool Execute(IEnumerable<string> args, PlayerAvatar targetPlayer)
		{
			return Execute(args);
		}

		public bool IsValidCommandArgs(IEnumerable<string> args)
		{
			throw new NotImplementedException();
		}
	}
	internal class ChangeHeight : IRepoStandaloneCommand, IConsoleCommand
	{
		private Vector3 basePlayerScale;

		private int sizeTriggerCount;

		public string Id => "change_height";

		public bool IsActive { get; private set; }

		public bool Execute(IEnumerable<string> args)
		{
			return true;
		}

		public bool IsValidCommandArgs(IEnumerable<string> args)
		{
			throw new NotImplementedException();
		}
	}
	internal class ChangeMouseSpeedX : IRepoStandaloneCommand, IConsoleCommand, IForceEnd
	{
		public string Id => "change_mouse_speed_x";

		public bool IsActive { get; private set; }

		public bool Execute(IEnumerable<string> args)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			CommandArgsReaderWrapper commandArgsReaderWrapper = new CommandArgsReaderWrapper(args);
			float durationInSec = commandArgsReaderWrapper.ReadFloat();
			ChaosInputManager.mouseSpeedCoeffX = commandArgsReaderWrapper.ReadFloat();
			ServiceProvider.inst.scheduleManager.AppendTimerTask(new TimerTaskData
			{
				id = Id,
				durationInSec = durationInSec,
				finishAction = delegate
				{
					IsActive = false;
					ChaosInputManager.mouseSpeedCoeffX = 1f;
				}
			}, true);
			return true;
		}

		public void ForceEnd()
		{
			ServiceProvider.inst.scheduleManager.FinishImmediatlyTimerTask(Id);
		}

		public bool IsValidCommandArgs(IEnumerable<string> args)
		{
			throw new NotImplementedException();
		}
	}
	internal class ChangeMouseSpeedY : IRepoStandaloneCommand, IConsoleCommand, IForceEnd
	{
		public string Id => "change_mouse_speed_y";

		public bool IsActive { get; private set; }

		public bool Execute(IEnumerable<string> args)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			CommandArgsReaderWrapper commandArgsReaderWrapper = new CommandArgsReaderWrapper(args);
			float durationInSec = commandArgsReaderWrapper.ReadFloat();
			ChaosInputManager.mouseSpeedCoeffY = commandArgsReaderWrapper.ReadFloat();
			ServiceProvider.inst.scheduleManager.AppendTimerTask(new TimerTaskData
			{
				id = Id,
				durationInSec = durationInSec,
				finishAction = delegate
				{
					IsActive = false;
					ChaosInputManager.mouseSpeedCoeffY = 1f;
				}
			}, true);
			return true;
		}

		public void ForceEnd()
		{
			ServiceProvider.inst.scheduleManager.FinishImmediatlyTimerTask(Id);
		}

		public bool IsValidCommandArgs(IEnumerable<string> args)
		{
			throw new NotImplementedException();
		}
	}
	internal class DisablePlayerAiming : IRepoStandaloneCommand, IConsoleCommand, IForceEnd
	{
		public string Id => "disable_player_aiming";

		public bool IsActive { get; private set; }

		public bool Execute(IEnumerable<string> args)
		{
			float num = new CommandArgsReaderWrapper(args).ReadFloat();
			Traverse<float> aimingTimerField = GetAimingTimerField();
			if (aimingTimerField == null)
			{
				((HelperLog)Utils.logger).LogError((object)(Id + " target field null"));
				return false;
			}
			aimingTimerField.Value = num + Mathf.Max(0f, aimingTimerField.Value);
			return true;
		}

		private Traverse<float> GetAimingTimerField()
		{
			InputManager instance = InputManager.instance;
			if ((Object)(object)instance == (Object)null)
			{
				((HelperLog)Utils.logger).LogError((object)(Id + " InputManager null"));
				return null;
			}
			return Traverse.Create((object)instance).Field<float>("disableAimingTimer");
		}

		public void ForceEnd()
		{
			Traverse<float> aimingTimerField = GetAimingTimerField();
			if (aimingTimerField != null)
			{
				aimingTimerField.Value = 0f;
			}
			else
			{
				((HelperLog)Utils.logger).LogWarning((object)(Id + " field null when ForceEnd"));
			}
		}

		public bool IsValidCommandArgs(IEnumerable<string> args)
		{
			throw new NotImplementedException();
		}
	}
	internal class DisableCrouch : IRepoStandaloneCommand, IConsoleCommand, IForceEnd
	{
		private readonly Dictionary<InputKey, bool> isActive = new Dictionary<InputKey, bool>();

		public string Id => "disable_input";

		public bool IsActive => isActive.Any((KeyValuePair<InputKey, bool> item) => item.Value);

		public bool Execute(IEnumerable<string> args)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			CommandArgsReaderWrapper commandArgsReaderWrapper = new CommandArgsReaderWrapper(args);
			float durationInSec = commandArgsReaderWrapper.ReadFloat();
			string text = commandArgsReaderWrapper.ReadString();
			if (!Enum.TryParse<InputKey>(text, ignoreCase: true, out InputKey key))
			{
				((HelperLog)Utils.logger).LogError((object)(Id + " can't find key for name " + text));
				return false;
			}
			isActive[key] = true;
			ChaosInputManager.BlockKey(key);
			ServiceProvider.inst.scheduleManager.AppendTimerTask(new TimerTaskData
			{
				id = GetTimerKey(key),
				durationInSec = durationInSec,
				finishAction = delegate
				{
					//IL_000c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0018: Unknown result type (might be due to invalid IL or missing references)
					isActive[key] = false;
					ChaosInputManager.UnblockKey(key);
					((HelperLog)Utils.logger).LogInfo((object)(Id + " ends"));
				}
			}, false);
			return true;
		}

		private string GetTimerKey(InputKey key)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return $"{Id}_{key}";
		}

		public void ForceEnd()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			foreach (InputKey key in isActive.Keys)
			{
				ServiceProvider.inst.scheduleManager.FinishImmediatlyTimerTask(GetTimerKey(key));
			}
		}

		public bool IsValidCommandArgs(IEnumerable<string> args)
		{
			throw new NotImplementedException();
		}
	}
	internal class DisablePlayerMovement : IRepoStandaloneCommand, IConsoleCommand, IForceEnd
	{
		public string Id => "disable_player_movement";

		public bool IsActive { get; private set; }

		public bool Execute(IEnumerable<string> args)
		{
			float num = new CommandArgsReaderWrapper(args).ReadFloat();
			Traverse<float> movementTimerField = GetMovementTimerField();
			if (movementTimerField == null)
			{
				((HelperLog)Utils.logger).LogError((object)(Id + " target field null"));
				return false;
			}
			movementTimerField.Value = num + Mathf.Max(0f, movementTimerField.Value);
			return true;
		}

		private Traverse<float> GetMovementTimerField()
		{
			InputManager instance = InputManager.instance;
			if ((Object)(object)instance == (Object)null)
			{
				((HelperLog)Utils.logger).LogError((object)(Id + " InputManager null"));
				return null;
			}
			return Traverse.Create((object)instance).Field<float>("disableMovementTimer");
		}

		public void ForceEnd()
		{
			Traverse<float> movementTimerField = GetMovementTimerField();
			if (movementTimerField != null)
			{
				movementTimerField.Value = 0f;
			}
			else
			{
				((HelperLog)Utils.logger).LogWarning((object)(Id + " field null when ForceEnd"));
			}
		}

		public bool IsValidCommandArgs(IEnumerable<string> args)
		{
			throw new NotImplementedException();
		}
	}
	internal class DrainStamina : IRepoStandaloneCommand, IConsoleCommand, IForceEnd
	{
		private float power;

		public string Id => "drain_player_stamina";

		public bool IsActive { get; private set; }

		public bool Execute(IEnumerable<string> args)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			CommandArgsReaderWrapper commandArgsReaderWrapper = new CommandArgsReaderWrapper(args);
			float durationInSec = commandArgsReaderWrapper.ReadFloat();
			power = commandArgsReaderWrapper.ReadFloat();
			ServiceProvider.inst.eventEmitter.ReplaceOrAddOnUpdateHandler(Id, OnUpdate);
			ServiceProvider.inst.scheduleManager.AppendTimerTask(new TimerTaskData
			{
				id = Id,
				durationInSec = durationInSec,
				finishAction = delegate
				{
					IsActive = false;
					((HelperLog)Utils.logger).LogInfo((object)(Id + " ends"));
				}
			}, false);
			IsActive = true;
			return true;
		}

		private void OnUpdate(object sender, float dtInSec)
		{
			if (IsActive)
			{
				float energyCurrent = PlayerController.instance.EnergyCurrent;
				PlayerController.instance.EnergyCurrent = Mathf.Max(0f, energyCurrent - power * dtInSec);
			}
		}

		public void ForceEnd()
		{
			ServiceProvider.inst.scheduleManager.FinishImmediatlyTimerTask(Id);
		}

		public bool IsValidCommandArgs(IEnumerable<string> args)
		{
			throw new NotImplementedException();
		}
	}
	internal class DropInventory : IRepoStandaloneCommand, IConsoleCommand
	{
		public string Id => "drop_inventory";

		public bool Execute(IEnumerable<string> args)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar localPlayer = GameUtils.LocalPlayer;
			if (GameUtils.IsPlayerDead(GameUtils.LocalPlayer))
			{
				((HelperLog)Utils.logger).LogInfo((object)(Id + " player is dead"));
				return true;
			}
			Inventory instance = Inventory.instance;
			if ((Object)(object)instance == (Object)null)
			{
				((HelperLog)Utils.logger).LogInfo((object)(Id + " player inventory is not found"));
				return false;
			}
			PhysGrabber grabber = GameUtils.LocalPlayer.physGrabber;
			_ = ((Component)localPlayer).transform.position + GameUtils.GetForwardOffset();
			List<ItemEquippable> l

ChaosTricks_REPO_plugins/ModHelper.dll

Decompiled 3 weeks ago
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.Text;
using EventsIO;
using EventsIO.Interfaces;
using ModHelper.Interfaces;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ModHelper")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("BFT")]
[assembly: AssemblyProduct("ModHelper")]
[assembly: AssemblyCopyright("Copyright ©  2020")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8d858f35-342c-4916-8e50-2b2cfd18640d")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ModHelper
{
	public class CommandArgsValidator
	{
		private readonly ILogger logger;

		public CommandArgsValidator(ILogger logger)
		{
			this.logger = logger;
		}

		public bool IsZeroArgs(IEnumerable<string> args)
		{
			int num = args?.Count() ?? 0;
			if (num != 0)
			{
				logger?.LogWarning($"CommandArgsValidator wrong args count {num} (must be 0)");
				return false;
			}
			return true;
		}

		public bool IsZeroArgs(IEnumerator<string> args)
		{
			if (args == null || !args.MoveNext())
			{
				return true;
			}
			logger?.LogWarning("CommandArgsValidator wrong args count (more than needed)");
			return false;
		}

		private bool IsInvalidArgsCount(IEnumerator<string> args)
		{
			if (args != null)
			{
				return !args.MoveNext();
			}
			return true;
		}

		public bool IsValidInt(IEnumerator<string> args, int minValue, int maxValue, bool isSkippable = false)
		{
			if (IsInvalidArgsCount(args))
			{
				if (isSkippable)
				{
					return true;
				}
				logger?.LogWarning("CommandArgsValidator wrong args count");
				return false;
			}
			try
			{
				int num = int.Parse(args.Current);
				if (num < minValue || num > maxValue)
				{
					string obj = $"CommandArgsValidator wrong integer value {num} (must be in range from {minValue} to {maxValue})";
					logger?.LogWarning(obj);
					return false;
				}
			}
			catch (Exception arg)
			{
				logger?.LogWarning($"CommandArgsValidator can't parse integer value from '{args.Current}', {arg}");
				return false;
			}
			return true;
		}

		public bool IsValidFloat(IEnumerator<string> args, float minValue, float maxValue, bool isSkippable = false)
		{
			if (IsInvalidArgsCount(args))
			{
				if (isSkippable)
				{
					return true;
				}
				logger?.LogWarning("CommandArgsValidator wrong args count");
				return false;
			}
			try
			{
				float num = float.Parse(args.Current, CultureInfo.InvariantCulture.NumberFormat);
				if (num < minValue || num > maxValue)
				{
					string obj = $"CommandArgsValidator wrong float value {num} (must be in range from {minValue} to {maxValue})";
					logger?.LogWarning(obj);
					return false;
				}
			}
			catch (Exception arg)
			{
				logger?.LogWarning($"CommandArgsValidator can't parse float value from '{args.Current}', {arg}");
			}
			return true;
		}

		public bool IsValidString(IEnumerator<string> args, Func<string, bool> validator, bool isSkippable = false)
		{
			if (IsInvalidArgsCount(args))
			{
				if (isSkippable)
				{
					return true;
				}
				logger?.LogWarning("CommandArgsValidator wrong args count");
				return false;
			}
			if (validator == null || validator(args.Current))
			{
				return true;
			}
			logger?.LogWarning("CommandArgsValidator wrong string value " + args.Current);
			return false;
		}

		public bool IsValidBool(IEnumerator<string> args, bool isSkippable = false)
		{
			if (IsInvalidArgsCount(args))
			{
				if (isSkippable)
				{
					return true;
				}
				logger?.LogWarning("CommandArgsValidator wrong args count");
				return false;
			}
			try
			{
				bool.Parse(args.Current.ToLower());
			}
			catch (Exception arg)
			{
				logger?.LogWarning($"CommandArgsValidator can't parse bool value from '{args.Current}', {arg}");
				return false;
			}
			return true;
		}
	}
	public class PeriodicTaskData
	{
		public string id;

		public float periodInSec;

		internal float periodCalculatedInSec;

		public int triggerTimes;

		public bool isInfiniteRepeates = true;

		public Action periodicAction;

		public Action finishAction;

		public override string ToString()
		{
			return "id=" + id + ", " + $"period={periodInSec}s, " + $"calc_period={periodCalculatedInSec}s, " + $"triggerTimes={triggerTimes}, " + $"isInfiniteRepeates={isInfiniteRepeates}";
		}
	}
	public class TimerTaskData
	{
		public string id;

		public float durationInSec;

		public Action finishAction;

		public override string ToString()
		{
			return $"id={id}, duration={durationInSec}s";
		}
	}
	public class BufferedLogger : HelperDebugLog, IDisposable
	{
		protected readonly Queue<string> queue;

		protected readonly int bufferRecordsCount;

		private bool isDisposed;

		public BufferedLogger(string folderPath = null, string logFileName = null, bool isDebug = false, int bufferRecordsCount = 10)
			: base(folderPath, logFileName, isDebug)
		{
			this.bufferRecordsCount = bufferRecordsCount;
			queue = new Queue<string>();
		}

		public virtual void Flush(bool isNeedClearQueue = false)
		{
			if (queue.Count != 0)
			{
				WriteToFile(string.Join("\n", queue.ToArray()));
				if (isNeedClearQueue)
				{
					queue.Clear();
				}
			}
		}

		public override void Log(object obj)
		{
			if (obj != null && isLogFile)
			{
				queue.Enqueue($"{LogTime} {obj}");
				if (queue.Count >= bufferRecordsCount)
				{
					Flush(isNeedClearQueue: true);
				}
			}
		}

		protected virtual void Dispose(bool isDisposing)
		{
			if (!isDisposed)
			{
				isDisposed = true;
				if (queue.Count > 0)
				{
					Flush();
				}
			}
		}

		public void Dispose()
		{
			Dispose(isDisposing: true);
			GC.SuppressFinalize(this);
		}

		~BufferedLogger()
		{
			Dispose(isDisposing: false);
		}
	}
	public static class HelperGroups
	{
		public static Dictionary<string, List<string>> GenerateNewEmptyGroupsDict()
		{
			return new Dictionary<string, List<string>>(StringComparer.InvariantCultureIgnoreCase);
		}

		private static bool SafeApplyValidator(Func<string, bool> groupItemValidator, string itemName, ILogger logger = null)
		{
			try
			{
				return groupItemValidator?.Invoke(itemName) ?? true;
			}
			catch (Exception arg)
			{
				logger?.LogError($"RandomGroup.SafeApplyValidator unexpected error: {arg}");
			}
			return false;
		}

		public static void InitGroupsFromFiles(string dataDir, Dictionary<string, List<string>> groups, string groupsPrefix, Func<string, bool> groupItemValidator = null, IDebugLogger logger = null)
		{
			try
			{
				if (string.IsNullOrEmpty(groupsPrefix))
				{
					logger?.LogError("RandomGroup error: wrong groupsPrefix " + groupsPrefix);
					return;
				}
				string[] files = Directory.GetFiles(dataDir);
				foreach (string path in files)
				{
					string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
					if (fileNameWithoutExtension.StartsWith(groupsPrefix))
					{
						groups[fileNameWithoutExtension] = GetItemsFromFile(path, logger);
					}
				}
				foreach (KeyValuePair<string, List<string>> group in groups)
				{
					logger?.LogDebugInfo("RandomGroup validate list " + group.Key + ":");
					List<string> list = new List<string>();
					foreach (string item in group.Value)
					{
						if (!SafeApplyValidator(groupItemValidator, item, logger))
						{
							logger?.LogWarning("invalid name " + item);
							list.Add(item);
						}
					}
					if (list.Count > 0)
					{
						foreach (string item2 in list)
						{
							group.Value.Remove(item2);
						}
						logger?.LogWarning("list " + group.Key + " is invalid");
					}
					else
					{
						logger?.LogDebugInfo("list " + group.Key + " is valid");
					}
				}
			}
			catch (Exception arg)
			{
				logger?.LogError($"RandomGroup.InitGroupsFromFiles unexpected error: {arg}");
			}
		}

		public static Dictionary<string, List<string>> GenerateGroupsFromFiles(string dataDir, string groupsPrefix, Func<string, bool> groupItemValidator = null, IDebugLogger logger = null)
		{
			Dictionary<string, List<string>> dictionary = GenerateNewEmptyGroupsDict();
			InitGroupsFromFiles(dataDir, dictionary, groupsPrefix, groupItemValidator, logger);
			return dictionary;
		}

		public static List<string> GetItemsFromFile(string path, IDebugLogger logger = null)
		{
			try
			{
				List<string> list = new HelperJson(logger).FromFile<List<string>>(path);
				if (list == null)
				{
					list = new List<string>();
				}
				logger?.LogInfo($"Items from file {path}: found {list.Count}");
				foreach (string item in list)
				{
					logger?.LogDebugInfo("value " + item);
				}
				return list;
			}
			catch (Exception arg)
			{
				logger?.LogError($"HelperGroups.GetItemsFromFile unexpected error: {arg}");
			}
			return new List<string>();
		}

		public static bool IsValidGroupName(Dictionary<string, List<string>> dict, string name)
		{
			return dict?.ContainsKey(name) ?? false;
		}

		public static void PrintGroups(Dictionary<string, List<string>> dict, ILogger logger, string groupsName = "default_name")
		{
			if (logger == null)
			{
				return;
			}
			if (dict == null || dict.Count == 0)
			{
				logger?.LogWarning("No groups found for " + groupsName);
				return;
			}
			logger?.LogInfo("---------------Groups " + groupsName + " list---------------");
			foreach (KeyValuePair<string, List<string>> item in dict)
			{
				logger?.LogInfo(item.Key ?? "");
			}
			logger?.LogInfo("---------------Groups " + groupsName + " list end---------------");
		}
	}
	public class HelperJson : IJsonUtil
	{
		private class ContainerObjAndInt
		{
			public object valueObj;

			public int valueInt;
		}

		private class ContainerStringAndInt
		{
			public string valueString;

			public int valueInt;
		}

		private ILogger logger;

		private const char startClass = '{';

		private const char endClass = '}';

		private const char startArray = '[';

		private const char endArray = ']';

		private const char isHasNextField = ',';

		private const char special = '\\';

		private const char startString = '"';

		private const char nameValueSeparator = ':';

		private char[] ignoreChars = new char[9] { ' ', '\n', '\r', '\t', '\b', '\f', '\0', '{', '[' };

		private string logMsgBaseError = "HelperJson error:";

		private string logMsgBase = "HelperJson:";

		private bool isVerboseDebugLog;

		private void VerboseDebugLog(string s)
		{
			if (isVerboseDebugLog)
			{
				logger?.LogInfo("[DEBUG] " + s);
			}
		}

		public HelperJson(IDebugLogger logger = null, bool isVerboseDebugLog = false)
		{
			this.logger = logger;
			this.isVerboseDebugLog = isVerboseDebugLog;
		}

		public T FromFile<T>(string path) where T : class
		{
			string s;
			using (StreamReader streamReader = new StreamReader(path))
			{
				s = streamReader.ReadToEnd();
			}
			return FromString<T>(s);
		}

		public T FromString<T>(string s) where T : class
		{
			return GetFromString(typeof(T), s, 0).valueObj as T;
		}

		private char GetSpecialChar(char c)
		{
			if (c != '"')
			{
				return c;
			}
			return c;
		}

		private void SetFieldClass<T, R>(T instance, string fieldName, R fieldValue) where T : class where R : class
		{
			Type type = instance.GetType();
			VerboseDebugLog("type=" + type.Name + ", field=" + fieldName);
			type.GetField(fieldName).SetValue(instance, fieldValue);
		}

		private ContainerStringAndInt ParseNextStringValue(string s, int index, bool isSkipSep = true)
		{
			StringBuilder stringBuilder = new StringBuilder();
			bool flag = false;
			int i;
			for (i = index; i < s.Length; i++)
			{
				char c = s[i];
				VerboseDebugLog($"{logMsgBase} ParseNextStringValue for process {c}");
				if (!flag)
				{
					i = SkipIgnoredChars(s, i, isSkipHasNextField: false, isSkipSep);
					if (i >= s.Length)
					{
						logger?.Log(logMsgBaseError + " class field value parsing internal issue. Set default value.");
						break;
					}
					c = s[i];
					if (c == '"')
					{
						flag = true;
						VerboseDebugLog(logMsgBase + " ParseNextStringValue is startString case");
						continue;
					}
					if (c == ']' || c == '}')
					{
						break;
					}
					if (c == ',' || c == ':')
					{
						i = SkipIgnoredChars(s, i, isSkipHasNextField: true, isSkipSep);
						break;
					}
				}
				else if (c == '\\')
				{
					VerboseDebugLog(logMsgBase + " ParseNextStringValue is special case");
					i++;
					if (i >= s.Length)
					{
						logger?.Log(logMsgBaseError + " class field value parsing internal issue with special symbols. Set default value.");
						break;
					}
					c = GetSpecialChar(s[i]);
					if (c != '"')
					{
						stringBuilder.Append('\\');
					}
				}
				else if (c == '"')
				{
					VerboseDebugLog(logMsgBase + " ParseNextStringValue is startString end case");
					i = SkipIgnoredChars(s, ++i, isSkipHasNextField: true, isSkipSep);
					break;
				}
				VerboseDebugLog($"{logMsgBase} ParseNextStringValue append {c}");
				stringBuilder.Append(c);
			}
			string text = stringBuilder.ToString();
			VerboseDebugLog($"{logMsgBase} ParseNextStringValue {text}, end at index {i}");
			return new ContainerStringAndInt
			{
				valueString = text,
				valueInt = i
			};
		}

		private ContainerStringAndInt GetNextFieldName(string s, int index)
		{
			VerboseDebugLog(logMsgBase + " GetNextFieldName");
			return ParseNextStringValue(s, index, isSkipSep: false);
		}

		private ContainerObjAndInt GetNextValue(Type valueType, string s, int index, bool isSkipSep)
		{
			VerboseDebugLog(logMsgBase + " GetNextValue");
			int num = SkipIgnoredChars(s, index, isSkipHasNextField: true, isSkipSep);
			if (num >= s.Length)
			{
				logger?.LogError(logMsgBaseError + " class parsing internal issue at value type " + valueType.Name + ". Set default value.");
			}
			if (valueType.IsPrimitive)
			{
				ContainerStringAndInt containerStringAndInt = ParseNextStringValue(s, num, isSkipSep);
				try
				{
					TypeCode typeCode = Type.GetTypeCode(valueType);
					object valueObj;
					if ((uint)(typeCode - 5) <= 10u)
					{
						if (double.TryParse(containerStringAndInt.valueString, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
						{
							valueObj = Convert.ChangeType(result, valueType);
						}
						else
						{
							valueObj = Activator.CreateInstance(valueType);
							logger?.Log(logMsgBaseError + " incorrect convert, use default.");
							logger?.Log("Read value: " + containerStringAndInt.valueString + ", type: " + valueType.Name);
						}
					}
					else
					{
						valueObj = Convert.ChangeType(containerStringAndInt.valueString, valueType);
					}
					return new ContainerObjAndInt
					{
						valueObj = valueObj,
						valueInt = containerStringAndInt.valueInt
					};
				}
				catch (Exception arg)
				{
					logger?.Log($"{logMsgBaseError} incorrect format, use default. Msg: {arg}");
					logger?.Log("read value: " + containerStringAndInt.valueString + ", type: " + valueType.Name);
					return new ContainerObjAndInt
					{
						valueObj = Activator.CreateInstance(valueType),
						valueInt = containerStringAndInt.valueInt
					};
				}
			}
			if (valueType.IsAssignableFrom(typeof(string)))
			{
				ContainerStringAndInt containerStringAndInt2 = ParseNextStringValue(s, num, isSkipSep);
				return new ContainerObjAndInt
				{
					valueObj = containerStringAndInt2.valueString,
					valueInt = containerStringAndInt2.valueInt
				};
			}
			ContainerObjAndInt fromString = GetFromString(valueType, s, num);
			return new ContainerObjAndInt
			{
				valueObj = fromString.valueObj,
				valueInt = fromString.valueInt
			};
		}

		private int SkipIgnoredChars(string s, int index, bool isSkipHasNextField = false, bool isSkipSep = false)
		{
			for (int i = index; i < s.Length; i++)
			{
				if (ignoreChars.Contains(s[i]))
				{
					VerboseDebugLog($"skip char '{s[i]}'");
					continue;
				}
				if (isSkipHasNextField && s[i] == ',')
				{
					VerboseDebugLog($"skip char '{s[i]}'");
					continue;
				}
				if (isSkipSep && s[i] == ':')
				{
					VerboseDebugLog($"skip char '{s[i]}'");
					continue;
				}
				return i;
			}
			return s.Length;
		}

		private ContainerObjAndInt ParseIListByItemType(Type itemType, string s, int index)
		{
			if (!(Activator.CreateInstance(typeof(List<>).MakeGenericType(itemType)) is IList list))
			{
				logger?.LogError(logMsgBaseError + " can't create IList for item type " + itemType.Name);
				return new ContainerObjAndInt
				{
					valueObj = null,
					valueInt = s.Length
				};
			}
			do
			{
				ContainerObjAndInt nextValue = GetNextValue(itemType, s, index, isSkipSep: true);
				object valueObj = nextValue.valueObj;
				index = nextValue.valueInt;
				list.Add(valueObj);
				index = SkipIgnoredChars(s, index, isSkipHasNextField: true, isSkipSep: true);
			}
			while (index < s.Length && s[index] != ']' && s[index] != '}');
			return new ContainerObjAndInt
			{
				valueObj = list,
				valueInt = index + 1
			};
		}

		private ContainerObjAndInt ParseIList(Type resultType, string s, int index)
		{
			Type itemType = (resultType.IsGenericType ? resultType.GetGenericArguments()[0] : resultType.GetElementType());
			return ParseIListByItemType(itemType, s, index);
		}

		private ContainerObjAndInt ParseArray(Type resultType, string s, int index)
		{
			Type elementType = resultType.GetElementType();
			ContainerObjAndInt containerObjAndInt = ParseIListByItemType(elementType, s, index);
			Array array;
			if (containerObjAndInt.valueObj is IList list)
			{
				array = Array.CreateInstance(elementType, list.Count);
				for (int i = 0; i < array.Length; i++)
				{
					array.SetValue(list[i], i);
				}
			}
			else
			{
				logger?.Log(logMsgBaseError + " create empty Array");
				array = Array.CreateInstance(elementType, 0);
			}
			return new ContainerObjAndInt
			{
				valueObj = array,
				valueInt = containerObjAndInt.valueInt
			};
		}

		private ContainerObjAndInt ParseIDictionary(Type dictType, string s, int index)
		{
			Type[] genericArguments = dictType.GetGenericArguments();
			if (genericArguments.Length != 2)
			{
				logger?.Log(logMsgBaseError + " can't create IDictionary, invalid args");
			}
			if (dictType.IsGenericType)
			{
				if (!dictType.IsGenericTypeDefinition)
				{
					dictType = dictType.GetGenericTypeDefinition();
				}
				dictType = dictType.MakeGenericType(genericArguments);
			}
			if (!(Activator.CreateInstance(dictType) is IDictionary dictionary))
			{
				string name = dictType.GetType().Name;
				logger?.Log(logMsgBaseError + " can't create IDictionary " + name + " for item type " + genericArguments[0].Name + ", " + genericArguments[1].Name);
				return new ContainerObjAndInt
				{
					valueObj = null,
					valueInt = s.Length
				};
			}
			Type valueType = genericArguments[0];
			Type valueType2 = genericArguments[1];
			do
			{
				ContainerObjAndInt nextValue = GetNextValue(valueType, s, index, isSkipSep: false);
				index = nextValue.valueInt;
				ContainerObjAndInt nextValue2 = GetNextValue(valueType2, s, index, isSkipSep: true);
				index = nextValue2.valueInt;
				dictionary.Add(nextValue.valueObj, nextValue2.valueObj);
				VerboseDebugLog($"{logMsgBase} dict add key {nextValue.valueObj}");
				index = SkipIgnoredChars(s, index, isSkipHasNextField: true, isSkipSep: true);
			}
			while (index < s.Length && s[index] != '}' && s[index] != ']');
			return new ContainerObjAndInt
			{
				valueObj = dictionary,
				valueInt = index + 1
			};
		}

		private bool IsTypeOf(Type targetType, Type sourceType, int argsCount)
		{
			if (sourceType.IsAssignableFrom(targetType))
			{
				VerboseDebugLog(logMsgBase + " is " + targetType.Name);
				return true;
			}
			Type[] types = sourceType.Assembly.GetTypes();
			foreach (Type type in types)
			{
				if (!type.IsClass)
				{
					continue;
				}
				Type[] interfaces = type.GetInterfaces();
				foreach (Type type2 in interfaces)
				{
					if (type2.IsGenericType && (object)type2.GetGenericTypeDefinition() == targetType && sourceType.GetGenericArguments().Length == argsCount)
					{
						VerboseDebugLog(logMsgBase + " is " + targetType.Name + " assembly interface");
						return true;
					}
				}
			}
			return false;
		}

		private ContainerObjAndInt GetFromString(Type resultType, string s, int index)
		{
			try
			{
				VerboseDebugLog(logMsgBase + " GetFromString");
				if (resultType.IsArray)
				{
					VerboseDebugLog(logMsgBase + " is array");
					return ParseArray(resultType, s, index);
				}
				if (resultType.IsAssignableFrom(typeof(IList)) || IsTypeOf(typeof(IList<>), resultType, 1))
				{
					return ParseIList(resultType, s, index);
				}
				if (resultType.IsAssignableFrom(typeof(IDictionary)) || IsTypeOf(typeof(IDictionary<, >), resultType, 2))
				{
					return ParseIDictionary(resultType, s, index);
				}
				if (resultType.IsGenericType && !resultType.IsGenericTypeDefinition)
				{
					Type[] genericArguments = resultType.GetGenericArguments();
					resultType = resultType.GetGenericTypeDefinition();
					resultType = resultType.MakeGenericType(genericArguments);
				}
				object obj = Activator.CreateInstance(resultType);
				int num = index;
				while (num < s.Length && s[num] != ']' && s[num] != '}')
				{
					ContainerStringAndInt nextFieldName = GetNextFieldName(s, num);
					string valueString = nextFieldName.valueString;
					if (string.IsNullOrEmpty(valueString?.Trim()))
					{
						VerboseDebugLog(logMsgBase + " IsNullOrWhiteSpace field " + valueString + ", class type " + resultType.Name);
						num = GetNextValue(typeof(string), s, num, isSkipSep: true).valueInt;
						continue;
					}
					num = nextFieldName.valueInt;
					FieldInfo field = resultType.GetField(valueString);
					VerboseDebugLog(logMsgBase + " field " + valueString + ", class type " + resultType.Name);
					if (isVerboseDebugLog)
					{
						FieldInfo[] fields = resultType.GetFields();
						VerboseDebugLog(logMsgBase + " fields in class: ");
						FieldInfo[] array = fields;
						foreach (FieldInfo fieldInfo in array)
						{
							VerboseDebugLog(fieldInfo.Name);
						}
					}
					if ((object)field == null)
					{
						logger?.LogWarning(logMsgBaseError + " can't find field " + valueString + " for type " + resultType.Name + ". Try to skip.");
						num = GetNextValue(typeof(string), s, num, isSkipSep: true).valueInt;
					}
					else
					{
						ContainerObjAndInt nextValue = GetNextValue(field.FieldType, s, num, isSkipSep: true);
						object valueObj = nextValue.valueObj;
						num = nextValue.valueInt;
						SetFieldClass(obj, valueString, valueObj);
					}
				}
				num = SkipIgnoredChars(s, num + 1, isSkipHasNextField: true, isSkipSep: true);
				return new ContainerObjAndInt
				{
					valueObj = obj,
					valueInt = num
				};
			}
			catch (Exception arg)
			{
				logger?.LogError($"{logMsgBaseError} {arg}");
			}
			return new ContainerObjAndInt
			{
				valueObj = null,
				valueInt = s.Length
			};
		}
	}
	public class HelperDebugLog : HelperLog, IDebugLogger, ILoggerWithConsole, ILogger
	{
		protected bool isDebug;

		public HelperDebugLog(string folderPath = null, string logFileName = null, bool isDebug = false)
			: base(folderPath, logFileName)
		{
			this.isDebug = isDebug;
		}

		public virtual void LogDebugInfo(object obj)
		{
			if (isDebug)
			{
				LogInfo($"[DEBUG] {obj}");
			}
		}

		public virtual void LogDebugWarning(object obj)
		{
			if (isDebug)
			{
				LogWarning($"[DEBUG] {obj}");
			}
		}

		public virtual void LogDebugError(object obj)
		{
			if (isDebug)
			{
				LogError($"[DEBUG] {obj}");
			}
		}
	}
	public class ScheduleManager
	{
		protected ILogger logger;

		protected Dictionary<string, TimerTaskData> timerTasks = new Dictionary<string, TimerTaskData>();

		protected Dictionary<string, PeriodicTaskData> periodicTasks = new Dictionary<string, PeriodicTaskData>();

		protected List<TimerTaskData> timerTasksNoId = new List<TimerTaskData>();

		protected List<PeriodicTaskData> periodicTasksNoId = new List<PeriodicTaskData>();

		protected int onUpdateErrorLimit = 10;

		public ScheduleManager(ILogger logger = null, int onUpdateErrorLimit = 0)
		{
			this.logger = logger;
			this.onUpdateErrorLimit = onUpdateErrorLimit;
		}

		public void NewTimerTask(TimerTaskData task, bool triggerFinishIfExists = false)
		{
			if (task == null)
			{
				logger?.LogInfo($"ScheduleManager new timer task null error. Details info: {task}");
				return;
			}
			if (task.id == null)
			{
				NewTimerTaskWithOutId(task);
				return;
			}
			if (triggerFinishIfExists && timerTasks.ContainsKey(task.id))
			{
				SafeRunAction(timerTasks[task.id].finishAction);
			}
			timerTasks[task.id] = task;
			logger?.LogInfo($"ScheduleManager new timer task {task}");
		}

		public void NewPeriodicTask(PeriodicTaskData task, bool triggerFinishIfExists = false)
		{
			if (task == null)
			{
				logger?.LogInfo($"ScheduleManager new periodic task null error. Details info: {task}");
				return;
			}
			task.periodCalculatedInSec = task.periodInSec;
			if (task.id == null)
			{
				NewPeriodicTaskWithOutId(task);
				return;
			}
			if (triggerFinishIfExists && periodicTasks.ContainsKey(task.id))
			{
				SafeRunAction(periodicTasks[task.id].finishAction);
			}
			periodicTasks[task.id] = task;
			logger?.LogInfo($"ScheduleManager new periodic task {task}");
		}

		public void AppendPeriodicTask(PeriodicTaskData task, bool isReplaceAction = false)
		{
			if (task.id == null || !periodicTasks.ContainsKey(task.id))
			{
				NewPeriodicTask(task);
				return;
			}
			logger?.LogInfo($"ScheduleManager append periodic task {task}");
			PeriodicTaskData periodicTaskData = periodicTasks[task.id];
			periodicTaskData.triggerTimes += task.triggerTimes;
			if (isReplaceAction)
			{
				periodicTaskData.finishAction = task.finishAction;
			}
		}

		protected void NewTimerTaskWithOutId(TimerTaskData task)
		{
			if (task == null)
			{
				logger?.LogWarning($"ScheduleManager new timer no id task null error. Details info: {task}");
				return;
			}
			timerTasksNoId.Add(task);
			logger?.LogInfo($"ScheduleManager new timer no id task {task}");
		}

		protected void NewPeriodicTaskWithOutId(PeriodicTaskData task)
		{
			if (task == null)
			{
				logger?.LogWarning($"ScheduleManager new periodic no id task null error. Details info: {task}");
				return;
			}
			periodicTasksNoId.Add(task);
			logger?.LogInfo($"ScheduleManager new periodic no id task {task}");
		}

		public void AppendTimerTask(TimerTaskData task, bool isReplaceAction = true)
		{
			if (!timerTasks.ContainsKey(task.id))
			{
				NewTimerTask(task);
				return;
			}
			logger?.LogInfo($"ScheduleManager append timer task {task}");
			TimerTaskData timerTaskData = timerTasks[task.id];
			timerTasks[task.id] = task;
			task.durationInSec += timerTaskData.durationInSec;
			if (!isReplaceAction)
			{
				task.finishAction = timerTaskData.finishAction;
			}
		}

		public bool IsTaskExists(string id)
		{
			if (!periodicTasks.ContainsKey(id))
			{
				return timerTasks.ContainsKey(id);
			}
			return true;
		}

		public void RemoveTimerTask(string id)
		{
			if (timerTasks.Remove(id))
			{
				logger?.LogInfo("ScheduleManager remove timer task " + id);
			}
		}

		public void RemovePeriodicTask(string id)
		{
			if (periodicTasks.Remove(id))
			{
				logger?.LogInfo("ScheduleManager remove periodic task " + id);
			}
		}

		public void RemoveAllTasks(string id)
		{
			logger?.LogInfo("ScheduleManager RemoveAllTasks with id " + id);
			RemoveTimerTask(id);
			RemovePeriodicTask(id);
		}

		public void RemoveAllTasks(bool isSuppressLog = false)
		{
			timerTasks.Clear();
			periodicTasks.Clear();
			timerTasksNoId.Clear();
			periodicTasksNoId.Clear();
			if (!isSuppressLog && logger != null)
			{
				logger.LogInfo("ScheduleManager RemoveAllTasks");
			}
		}

		protected List<TimerTaskData> ProcessTimersList(ICollection<TimerTaskData> list, float dtInSec)
		{
			List<TimerTaskData> list2 = new List<TimerTaskData>();
			foreach (TimerTaskData item in list)
			{
				item.durationInSec -= dtInSec;
				if (item.durationInSec <= 0f)
				{
					SafeRunAction(item.finishAction);
					list2.Add(item);
					logger?.LogInfo("ScheduleManager triggered finish action timer task " + item.id);
				}
			}
			return list2;
		}

		protected List<PeriodicTaskData> ProcessPeriodicList(ICollection<PeriodicTaskData> list, float dtInSec)
		{
			List<PeriodicTaskData> list2 = new List<PeriodicTaskData>();
			foreach (PeriodicTaskData item in list)
			{
				item.periodCalculatedInSec -= dtInSec;
				if (!(item.periodCalculatedInSec <= 0f))
				{
					continue;
				}
				if (item.isInfiniteRepeates || item.triggerTimes > 0)
				{
					SafeRunAction(item.periodicAction);
					item.periodCalculatedInSec = item.periodInSec;
					if (item.triggerTimes == 1)
					{
						logger?.LogInfo("ScheduleManager triggered action periodic task " + item.id);
					}
				}
				if (!item.isInfiniteRepeates)
				{
					item.triggerTimes--;
					if (item.triggerTimes <= 0)
					{
						SafeRunAction(item.finishAction);
						list2.Add(item);
						logger?.LogInfo("ScheduleManager triggered finish action periodic task " + item.id);
					}
				}
			}
			return list2;
		}

		public void OnUpdate(float dtInSec)
		{
			try
			{
				foreach (TimerTaskData item in ProcessTimersList(timerTasks.Values, dtInSec))
				{
					timerTasks.Remove(item.id);
					logger?.LogInfo($"ScheduleManager OnUpdate finished timer task {item}");
				}
				foreach (PeriodicTaskData item2 in ProcessPeriodicList(periodicTasks.Values, dtInSec))
				{
					periodicTasks.Remove(item2.id);
					logger?.LogInfo($"ScheduleManager OnUpdate finished periodic task {item2}");
				}
				foreach (TimerTaskData item3 in ProcessTimersList(timerTasksNoId, dtInSec))
				{
					timerTasksNoId.Remove(item3);
					logger?.LogInfo($"ScheduleManager OnUpdate finished timer no id task {item3}");
				}
				foreach (PeriodicTaskData item4 in ProcessPeriodicList(periodicTasksNoId, dtInSec))
				{
					periodicTasksNoId.Remove(item4);
					logger?.LogInfo($"ScheduleManager OnUpdate finished periodic no id task {item4}");
				}
			}
			catch (Exception arg)
			{
				if (onUpdateErrorLimit > 0)
				{
					logger?.LogError($"ScheduleManager unexpected onUpdate error: {arg}");
					onUpdateErrorLimit--;
				}
			}
		}

		public void FinishImmediatlyTimerTask(string id)
		{
			if (timerTasks.ContainsKey(id))
			{
				SafeRunAction(timerTasks[id].finishAction);
				timerTasks.Remove(id);
				logger?.LogInfo("ScheduleManager finish and remove timer task " + id);
			}
		}

		public float GetTimerTaskDurationInSec(string id)
		{
			if (!timerTasks.ContainsKey(id))
			{
				return -1f;
			}
			return timerTasks[id].durationInSec;
		}

		public void FinishImmediatlyPeriodicTask(string id)
		{
			if (periodicTasks.ContainsKey(id))
			{
				SafeRunAction(periodicTasks[id].finishAction);
				periodicTasks.Remove(id);
				logger?.LogInfo("ScheduleManager finish and remove periodic task " + id);
			}
		}

		public void FinishAllImmediatly(string id)
		{
			FinishImmediatlyTimerTask(id);
			FinishImmediatlyPeriodicTask(id);
		}

		public void FinishAllImmediatly()
		{
			foreach (TimerTaskData value in timerTasks.Values)
			{
				SafeRunAction(value.finishAction);
			}
			foreach (PeriodicTaskData value2 in periodicTasks.Values)
			{
				SafeRunAction(value2.finishAction);
			}
			foreach (TimerTaskData item in timerTasksNoId)
			{
				SafeRunAction(item.finishAction);
			}
			foreach (PeriodicTaskData item2 in periodicTasksNoId)
			{
				SafeRunAction(item2.finishAction);
			}
			RemoveAllTasks();
		}

		protected void SafeRunAction(Action action)
		{
			if (action == null)
			{
				return;
			}
			try
			{
				action();
			}
			catch (Exception arg)
			{
				logger?.LogError($"SafeRunAction error: {arg}");
			}
		}
	}
	public class UtilityConsole
	{
		private readonly Dictionary<string, IConsoleCommand> consoleCommandsDict;

		private readonly IDebugLogger logger;

		private readonly List<string> ignoreValidationCommands;

		public bool isLogCheckCommand = true;

		public bool isLogCheckCommandParameters = true;

		public int logCheckCommandParametersMaxLength = 40;

		public bool isLogProcessCommand = true;

		public bool isLogProcessCommandParameters = true;

		public int logProcessCommandParametersMaxLength = 40;

		public UtilityConsole(IDebugLogger logger = null, List<string> ignoreValidationCommands = null)
		{
			consoleCommandsDict = new Dictionary<string, IConsoleCommand>();
			this.logger = logger;
			this.ignoreValidationCommands = ignoreValidationCommands;
		}

		public void RegisterCommand(IConsoleCommand command)
		{
			if (string.IsNullOrEmpty(command?.Id))
			{
				logger?.LogWarning("UtilityConsole.RegisterCommand: invalid console command");
			}
			else
			{
				consoleCommandsDict[command.Id] = command;
			}
		}

		public static string[] ParseCommandLine(string commandLine)
		{
			return commandLine.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
		}

		public static string[] ParseArgs(string command)
		{
			return command.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
		}

		private string GetCmdName(string cmd)
		{
			string[] array = cmd.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length != 0)
			{
				return array[0];
			}
			return "";
		}

		private void LogCommand(string funcPrefix, string cmd, bool isLog, bool isLogParams, int maxLen)
		{
			if (logger == null || !isLog)
			{
				return;
			}
			if (string.IsNullOrEmpty(cmd))
			{
				logger.LogWarning(funcPrefix + " null or empty");
			}
			else if (isLogParams)
			{
				if (cmd.Length > maxLen)
				{
					string text = cmd.Substring(0, maxLen);
					logger.Log(funcPrefix + " " + text + "...");
				}
				else
				{
					logger.Log(funcPrefix + " " + cmd);
				}
			}
			else
			{
				logger.Log(funcPrefix + " " + GetCmdName(cmd));
			}
		}

		public bool IsValidCommandLine(string commandLine)
		{
			try
			{
				if (string.IsNullOrEmpty(commandLine))
				{
					logger?.LogDebugError("UtilityConsole.IsValidCommandLine: invalid command line");
					return false;
				}
				string[] array = ParseCommandLine(commandLine);
				if (array == null || array.Length < 1)
				{
					logger?.LogDebugError("UtilityConsole.IsValidCommandLine: invalid commands count");
					return false;
				}
				bool flag = true;
				string[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					string text = array2[i]?.Trim();
					LogCommand("UtilityConsole.IsValidCommandLine: check command", text, isLogCheckCommand, isLogCheckCommandParameters, logCheckCommandParametersMaxLength);
					string[] array3 = ParseArgs(text);
					if (array3 == null || array3.Length < 1)
					{
						logger?.LogDebugError("UtilityConsole.IsValidCommandLine: invalid commands count");
						flag = false;
						continue;
					}
					string text2 = array3[0];
					List<string> list = ignoreValidationCommands;
					if (list != null && list.Contains(text2))
					{
						logger?.LogDebugInfo("UtilityConsole.IsValidCommandLine: validation is ignored for this command");
					}
					else if (consoleCommandsDict.ContainsKey(text2))
					{
						bool flag2 = consoleCommandsDict[text2].IsValidCommandArgs(array3.Skip(1));
						if (!flag2)
						{
							logger?.LogDebugError("UtilityConsole.IsValidCommandLine: command with id " + text2 + " is invalid");
						}
						flag = flag && flag2;
					}
					else
					{
						logger?.LogDebugError("UtilityConsole.IsValidCommandLine: can't find custom command with id " + text2);
						flag = false;
					}
				}
				return flag;
			}
			catch (Exception arg)
			{
				logger?.LogDebugError(string.Format("{0} error: {1}", "UtilityConsole.IsValidCommandLine:", arg));
				return false;
			}
		}

		public bool RunCommand(string commandLine, IEventsData data, Action<string> onCustomCommandNotFound = null)
		{
			try
			{
				string[] array = ParseCommandLine(commandLine);
				foreach (string text in array)
				{
					LogCommand("UtilityConsole.RunCommand: process command", text, isLogProcessCommand, isLogProcessCommandParameters, logProcessCommandParametersMaxLength);
					string[] array2 = ParseArgs(text);
					string key = array2[0];
					if (consoleCommandsDict.ContainsKey(key))
					{
						try
						{
							if (consoleCommandsDict[key] is IConsoleCommandWithData consoleCommandWithData)
							{
								consoleCommandWithData.Execute(array2.Skip(1), data);
							}
							else
							{
								consoleCommandsDict[key].Execute(array2.Skip(1));
							}
						}
						catch (Exception arg)
						{
							logger?.LogError(string.Format("{0} execute command error {1}", "UtilityConsole.RunCommand:", arg));
						}
					}
					else if (onCustomCommandNotFound != null)
					{
						onCustomCommandNotFound(text);
					}
					else
					{
						logger?.LogError("UtilityConsole.RunCommand: execute command not found error");
					}
				}
			}
			catch (Exception arg2)
			{
				logger?.LogError(string.Format("{0} error {1}", "UtilityConsole.RunCommand:", arg2));
				return false;
			}
			return true;
		}
	}
	public class CommandArgsReader
	{
		private readonly ILogger logger;

		public CommandArgsReader(ILogger logger)
		{
			this.logger = logger;
		}

		public int ReadInt(IEnumerator<string> args, int defaultValue = 0)
		{
			if (args == null || !args.MoveNext())
			{
				return defaultValue;
			}
			try
			{
				return int.Parse(args.Current);
			}
			catch (Exception arg)
			{
				logger?.LogWarning($"CommandArgsReader: {arg}");
				return defaultValue;
			}
		}

		public float ReadFloat(IEnumerator<string> args, float defaultValue = 0f)
		{
			if (args == null || !args.MoveNext())
			{
				return defaultValue;
			}
			try
			{
				return float.Parse(args.Current, CultureInfo.InvariantCulture.NumberFormat);
			}
			catch (Exception arg)
			{
				logger?.LogWarning($"CommandArgsReader: {arg}");
				return defaultValue;
			}
		}

		public string ReadString(IEnumerator<string> args, string defaultValue = "")
		{
			if (args != null && args.MoveNext())
			{
				return args.Current;
			}
			return defaultValue;
		}

		public bool ReadBool(IEnumerator<string> args, bool defaultValue = false)
		{
			if (args == null || !args.MoveNext())
			{
				return defaultValue;
			}
			try
			{
				return bool.Parse(args.Current.ToLower());
			}
			catch (Exception arg)
			{
				logger?.LogWarning($"CommandArgsReader: {arg}");
				return defaultValue;
			}
		}
	}
	public static class UtilityRandom
	{
		private static readonly Random rnd = new Random(Guid.NewGuid().GetHashCode());

		public static T GetRandomItemFromList<T>(IList<T> list)
		{
			if (list != null && list.Count > 0)
			{
				return list[rnd.Next(list.Count)];
			}
			return default(T);
		}
	}
	public class HelperCommandManagerFormatted : ICommandManager
	{
		private Dictionary<string, string> commandsDict;

		private readonly IDebugLogger logger;

		private readonly string errorString = string.Empty;

		public int logCommandMaxLength = 50;

		public bool isUseLogCommandLimit = true;

		public HelperCommandManagerFormatted(IDebugLogger logger)
		{
			this.logger = logger;
		}

		public virtual void InitFromFile(string path)
		{
			try
			{
				Dictionary<string, string> dictionary = UtilityJson.Generate(logger).FromFile<Dictionary<string, string>>(path);
				commandsDict = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase);
				CheckLoadedDict();
			}
			catch (Exception arg)
			{
				logger?.LogError($"HelperCommandManagerFormatted InitFromFile load: {arg}");
				commandsDict = null;
			}
		}

		public virtual void InitFromString(string data)
		{
			try
			{
				Dictionary<string, string> dictionary = UtilityJson.Generate(logger).FromString<Dictionary<string, string>>(data);
				commandsDict = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase);
				CheckLoadedDict();
			}
			catch (Exception arg)
			{
				logger?.LogError($"HelperCommandManagerFormatted InitFromString load: {arg}");
				commandsDict = null;
			}
		}

		protected virtual void CheckLoadedDict()
		{
			if (commandsDict == null)
			{
				logger?.LogWarning("HelperCommandManagerFormatted: commandsDict null");
				return;
			}
			logger?.LogInfo($"HelperCommandManagerFormatted: found commands {commandsDict.Count}");
			foreach (KeyValuePair<string, string> item in commandsDict)
			{
				logger?.LogDebugInfo("command: key=" + item.Key + ", value=" + GetSubstringCmd(item.Value));
			}
		}

		protected virtual string GetSubstringCmd(string cmd)
		{
			if (isUseLogCommandLimit && cmd != null)
			{
				if (cmd.Length > logCommandMaxLength)
				{
					return cmd.Substring(0, logCommandMaxLength) + "...";
				}
				return cmd;
			}
			return cmd;
		}

		public virtual string GetCommandData(string eventKey, bool isLogError = false)
		{
			if (commandsDict == null)
			{
				logger?.LogWarning("HelperCommandManagerFormatted GetCommandData: commandsDict null");
				return "";
			}
			try
			{
				eventKey = eventKey.Trim();
				string text = commandsDict[eventKey];
				if (text != null)
				{
					return text;
				}
				throw new NullReferenceException();
			}
			catch (Exception arg)
			{
				if (isLogError)
				{
					logger?.LogError($"HelperCommandManagerFormatted key {eventKey}, error: {arg}");
				}
				return errorString;
			}
		}

		public virtual string[] GetCommands()
		{
			if (commandsDict == null)
			{
				logger?.LogWarning("HelperCommandManagerFormatted GetCommands: commandsDict null");
				return new string[0];
			}
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, string> item in commandsDict)
			{
				list.Add(item.Value);
			}
			return list.ToArray();
		}
	}
	public class HelperDictManager : IDictManager
	{
		private readonly ILogger logger;

		private readonly IEventsDataEncoder encoder;

		private readonly IEventsDataEncoderParams encoderParams;

		public HelperDictManager(ILogger logger = null)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			this.logger = logger;
			encoderParams = (IEventsDataEncoderParams)(object)(encoder = (IEventsDataEncoder)new EventsDataEncoder());
		}

		public Dictionary<string, string> ParseDict(string data)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			try
			{
				string[] array = data.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
				if (array == null)
				{
					logger?.LogError("HelperDictManager error, wrong args. Source: " + data);
					return dictionary;
				}
				string[] array2 = array;
				foreach (string text in array2)
				{
					string[] array3 = text.Split(new char[1] { encoderParams.ClientAppSepChar }, StringSplitOptions.RemoveEmptyEntries);
					if (array3.Length != 2)
					{
						logger?.LogWarning("HelperDictManager, invalid item: " + text);
						continue;
					}
					string text2 = array3[0];
					string text3 = array3[1];
					if (text3 == null || text2 == null)
					{
						logger?.LogWarning("HelperDictManager, invalid key/val: " + text2 + "/" + text3);
						continue;
					}
					string key = encoder.Decode(text2).Trim();
					string value = encoder.Decode(text3).Trim();
					dictionary.Add(key, value);
				}
			}
			catch (Exception arg)
			{
				logger?.LogError($"HelperDictManager error: {arg}");
			}
			return dictionary;
		}
	}
	public class HelperCommandManager : ICommandManager
	{
		private readonly Dictionary<string, string> commandsDict;

		private readonly IDebugLogger logger;

		private readonly string errorString = string.Empty;

		public HelperCommandManager(IDebugLogger logger, string commandsDir, string commandsFname = "commands.data")
		{
			this.logger = logger;
			try
			{
				string path = Path.Combine(commandsDir, commandsFname);
				IDictManager dictManager = new HelperDictManager();
				using StreamReader streamReader = new StreamReader(path);
				string data = streamReader.ReadToEnd();
				Dictionary<string, string> dictionary = dictManager.ParseDict(data);
				commandsDict = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase);
				logger?.LogInfo($"HelperCommandManager: found commands {commandsDict.Count}");
				foreach (KeyValuePair<string, string> item in commandsDict)
				{
					logger?.LogDebugInfo("command: key=" + item.Key + ", value=" + item.Value);
				}
			}
			catch (Exception arg)
			{
				logger?.LogError($"HelperCommandManager load: {arg}");
				commandsDict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			}
		}

		public string GetCommandData(string eventKey, bool isLogError = false)
		{
			try
			{
				eventKey = eventKey.Trim();
				string text = commandsDict[eventKey];
				if (text != null)
				{
					return text;
				}
				throw new NullReferenceException();
			}
			catch (Exception arg)
			{
				if (isLogError)
				{
					logger?.LogError($"HelperCommandManager key {eventKey}: {arg}");
				}
				return errorString;
			}
		}

		public string[] GetCommands()
		{
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, string> item in commandsDict)
			{
				list.Add(item.Value);
			}
			return list.ToArray();
		}

		public virtual void InitFromFile(string path)
		{
			throw new NotImplementedException();
		}

		public virtual void InitFromString(string data)
		{
			throw new NotImplementedException();
		}
	}
	public class HelperEventManager<CustomEvent> : IEventManager<CustomEvent> where CustomEvent : class, IEvent
	{
		private readonly Dictionary<string, CustomEvent> eventsDict;

		private readonly IDebugLogger logger;

		public HelperEventManager(IDebugLogger logger)
		{
			this.logger = logger;
			eventsDict = new Dictionary<string, CustomEvent>(StringComparer.OrdinalIgnoreCase);
			try
			{
				Type type = typeof(CustomEvent);
				IEnumerable<Type> enumerable = from p in AppDomain.CurrentDomain.GetAssemblies().SelectMany(delegate(Assembly s)
					{
						try
						{
							return s.GetTypes();
						}
						catch (Exception)
						{
							return new Type[0];
						}
					})
					where p.IsClass && !p.IsAbstract && !p.IsInterface && type.IsAssignableFrom(p)
					select p;
				logger?.LogInfo($"HelperEventManager: found {enumerable.Count()} events");
				foreach (Type item in enumerable)
				{
					CustomEvent val = Activator.CreateInstance(item) as CustomEvent;
					if (val != null)
					{
						eventsDict.Add(val.Id, val);
						logger?.LogDebugInfo("init event '" + val.Id + "' complete");
					}
					else
					{
						logger?.LogWarning("init event '" + val.Id + "' failed");
					}
				}
			}
			catch (Exception arg)
			{
				logger?.LogError($"HelperEventManager error: {arg}");
			}
		}

		public HelperEventManager(IDebugLogger logger, IEventManager<IEvent> manager)
		{
			this.logger = logger;
			eventsDict = new Dictionary<string, CustomEvent>(StringComparer.OrdinalIgnoreCase);
			string name = typeof(CustomEvent).Name;
			try
			{
				foreach (IEvent item in manager.GetEventsCollection())
				{
					if (item is CustomEvent val)
					{
						eventsDict.Add(val.Id, val);
						logger?.LogDebugInfo("init event '" + val.Id + "' as '" + name + "' complete");
					}
				}
			}
			catch (Exception arg)
			{
				logger?.LogError($"HelperEventManager: {arg}");
			}
		}

		public IEnumerable<CustomEvent> GetEventsCollection()
		{
			if (eventsDict == null)
			{
				return new List<CustomEvent>();
			}
			return eventsDict.Values;
		}

		public CustomEvent GetEvent(string eventID, bool isLogError = false)
		{
			try
			{
				eventID = eventID.Trim();
				CustomEvent val = eventsDict[eventID];
				if (val != null)
				{
					return val;
				}
				throw new NullReferenceException();
			}
			catch (Exception arg)
			{
				if (isLogError)
				{
					logger?.LogError($"HelperCommandManager key {eventID}: {arg}");
				}
				return null;
			}
		}
	}
	public class HelperLanguagesFormatted : ITranslation
	{
		protected Dictionary<string, Text> transDict;

		protected readonly IDebugLogger logger;

		protected readonly string errorString = "trans_error";

		public bool isLogOnlyEnItems;

		public bool isSuppressLogItems = true;

		public HelperLanguagesFormatted(IDebugLogger logger)
		{
			this.logger = logger;
		}

		public virtual void InitFromFile(string path)
		{
			try
			{
				Dictionary<string, Text> dictionary = UtilityJson.Generate(logger).FromFile<Dictionary<string, Text>>(path);
				transDict = new Dictionary<string, Text>(dictionary, StringComparer.OrdinalIgnoreCase);
				CheckLoadedDict();
			}
			catch (Exception arg)
			{
				logger?.LogError($"HelperLanguagesFormatted InitFromFile load: {arg}");
				transDict = null;
			}
		}

		public virtual void InitFromString(string data)
		{
			try
			{
				Dictionary<string, Text> dictionary = UtilityJson.Generate(logger).FromString<Dictionary<string, Text>>(data);
				transDict = new Dictionary<string, Text>(dictionary, StringComparer.OrdinalIgnoreCase);
				CheckLoadedDict();
			}
			catch (Exception arg)
			{
				logger?.LogError($"HelperLanguagesFormatted InitFromString load: {arg}");
				transDict = null;
			}
		}

		protected virtual void CheckLoadedDict()
		{
			if (transDict == null)
			{
				logger?.LogWarning("HelperLanguagesFormatted: transDict null");
				return;
			}
			logger?.LogInfo($"HelperLanguagesFormatted: found translates {transDict.Count}");
			if (isSuppressLogItems || logger == null)
			{
				return;
			}
			foreach (KeyValuePair<string, Text> item in transDict)
			{
				if (isLogOnlyEnItems)
				{
					logger.LogDebugInfo("key=" + item.Key + ", en=" + item.Value.en);
					continue;
				}
				logger.LogDebugInfo("key=" + item.Key + ", ru=" + item.Value.ru + ", en=" + item.Value.en);
			}
		}

		public virtual string GetTrans(string key, Languages lang)
		{
			return GetTrans(key, lang.ToString());
		}

		public virtual string GetTrans(string key, string lang)
		{
			if (transDict == null)
			{
				logger?.LogWarning("HelperLanguagesFormatted transDict is null");
				return errorString;
			}
			try
			{
				key = key.Trim();
				lang = lang.Trim();
				return transDict[key].GetTrans(lang);
			}
			catch (Exception arg)
			{
				logger?.LogError($"HelperLanguagesFormatted key {key} lang {lang}, error: {arg}");
				return errorString;
			}
		}
	}
	public class HelperLog : ILoggerWithConsole, ILogger
	{
		protected readonly string path;

		protected const string baseLogName = "interactive_mod_log.txt";

		public bool isLogConsole = true;

		public bool isLogFile = true;

		public ConsoleColor infoColor = ConsoleColor.White;

		public ConsoleColor warningColor = ConsoleColor.Yellow;

		public ConsoleColor errorColor = ConsoleColor.Red;

		protected virtual string LogTime => DateTime.Now.ToString("h:mm:ss:fff");

		public HelperLog(string logDir)
			: this(logDir, "interactive_mod_log.txt")
		{
		}

		public HelperLog(string logDir, string logFname)
		{
			if (logDir == "" || Directory.Exists(logDir))
			{
				path = Path.Combine(logDir, logFname);
			}
		}

		protected virtual void WriteToFile(string s)
		{
			if (path != null)
			{
				using (StreamWriter streamWriter = new StreamWriter(path, append: true, Encoding.UTF8))
				{
					streamWriter.WriteLine(s);
				}
			}
		}

		public virtual void Log(object obj)
		{
			if (isLogFile)
			{
				WriteToFile($"{LogTime} {obj}");
			}
		}

		public virtual void LogConsole(string text, string prefix, ConsoleColor prefixColor)
		{
			Console.ForegroundColor = prefixColor;
			Console.Write(LogTime + " " + prefix + " ");
			Console.ResetColor();
			Console.WriteLine(text);
		}

		protected virtual void LogWithConsole(object obj, string prefix, ConsoleColor color)
		{
			Log($"{prefix} {obj}");
			if (isLogConsole)
			{
				LogConsole(obj.ToString(), prefix, color);
			}
		}

		public virtual void LogInfo(object obj)
		{
			LogWithConsole(obj, "[INFO]", infoColor);
		}

		public virtual void LogWarning(object obj)
		{
			LogWithConsole(obj, "[WARNING]", warningColor);
		}

		public virtual void LogError(object obj)
		{
			LogWithConsole(obj, "[ERROR]", errorColor);
		}

		public virtual void LogInfoConsoleOnly(object obj)
		{
			if (isLogConsole)
			{
				LogConsole(obj.ToString(), "[INFO]", infoColor);
			}
		}

		public virtual void LogWarningConsoleOnly(object obj)
		{
			if (isLogConsole)
			{
				LogConsole(obj.ToString(), "[WARNING]", warningColor);
			}
		}

		public virtual void LogErrorConsoleOnly(object obj)
		{
			if (isLogConsole)
			{
				LogConsole(obj.ToString(), "[ERROR]", errorColor);
			}
		}

		public virtual void LogInfoFileOnly(object obj)
		{
			Log($"[INFO] {obj}");
		}

		public virtual void LogWarningFileOnly(object obj)
		{
			Log($"[WARNING] {obj}");
		}

		public virtual void LogErrorFileOnly(object obj)
		{
			Log($"[ERROR] {obj}");
		}

		public virtual void LogClear()
		{
			if (path != null)
			{
				using (new StreamWriter(path))
				{
				}
			}
		}
	}
	public class HelperParse : IParseManager
	{
		private readonly ILogger logger;

		public HelperParse(ILogger logger = null)
		{
			this.logger = logger;
		}

		public Type GetEnumUnderlyingType(Type type)
		{
			if (!type.IsEnum)
			{
				return type;
			}
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (fields != null && fields.Length >= 1)
			{
				return fields[0].FieldType;
			}
			return type;
		}

		public bool TryParseEnum<TEnum>(string arg, out TEnum result, TEnum defaultValue = default(TEnum))
		{
			Type typeFromHandle = typeof(TEnum);
			try
			{
				Type enumUnderlyingType = GetEnumUnderlyingType(typeFromHandle);
				if ((object)enumUnderlyingType == typeof(int))
				{
					if (int.TryParse(arg, out var result2) && Enum.IsDefined(typeFromHandle, result2))
					{
						result = (TEnum)Enum.ToObject(typeFromHandle, result2);
						return true;
					}
					logger?.LogWarning("TryParseEnum can't parse int from " + arg + " for enum " + typeFromHandle.Name);
				}
				else if ((object)enumUnderlyingType == typeof(sbyte))
				{
					if (sbyte.TryParse(arg, out var result3) && Enum.IsDefined(typeFromHandle, result3))
					{
						result = (TEnum)Enum.ToObject(typeFromHandle, result3);
						return true;
					}
					logger?.LogWarning("TryParseEnum can't parse sbyte from " + arg + " for enum " + typeFromHandle.Name);
				}
				else
				{
					foreach (TEnum value in Enum.GetValues(typeFromHandle))
					{
						if (Enum.GetName(typeFromHandle, value).Equals(arg, StringComparison.OrdinalIgnoreCase))
						{
							result = value;
							return true;
						}
					}
					logger?.LogWarning("TryParseEnum can't find item by direct name " + arg + " for enum " + typeFromHandle.Name);
				}
			}
			catch (Exception arg2)
			{
				logger?.LogError($"TryParseEnum error happened when process {arg} for enum {typeFromHandle.Name}: {arg2}");
			}
			result = defaultValue;
			return false;
		}

		public bool TryParseBool(string arg, out bool result, bool defaultValue = false)
		{
			if (bool.TryParse(arg, out result))
			{
				return true;
			}
			if (int.TryParse(arg, out var result2))
			{
				result = result2 != 0;
				return true;
			}
			logger?.LogWarning($"TryParseBool error happened when process {arg}. Will be used default {defaultValue}");
			result = defaultValue;
			return false;
		}
	}
	public class UtilityJson
	{
		private static Func<IJsonUtil> customGenerator;

		public static IJsonUtil Generate(IDebugLogger logger)
		{
			if (customGenerator == null)
			{
				return new HelperJson(logger, File.Exists(".mod_json_debug"));
			}
			return customGenerator();
		}

		public static void RegisterCustomGenerator(Func<IJsonUtil> generator)
		{
			customGenerator = generator;
		}
	}
	public class UtilitySettings
	{
		public static string CommandUpdateSettingsID => "command_update_parameters";

		public static string BaseFolder { get; set; } = "ChaosTricks_InteractiveModData";


		public static string SettingsFileName => "settings.txt";

		public static string SettingsPath => Path.Combine(BaseFolder, SettingsFileName);

		public static T LoadSettings<T>(IDebugLogger logger) where T : class
		{
			string text = string.Empty;
			try
			{
				text = SettingsPath;
				T result = UtilityJson.Generate(logger).FromFile<T>(text);
				logger?.LogInfo("settings loaded");
				return result;
			}
			catch (FileNotFoundException)
			{
				logger?.LogWarning("can't load settings. File not found at " + text + ". Using standard.");
			}
			catch (Exception arg)
			{
				logger?.LogError($"can't load settings. Using standard. \n{arg}");
			}
			T result2 = null;
			try
			{
				result2 = Activator.CreateInstance<T>();
				return result2;
			}
			catch (Exception arg2)
			{
				logger?.LogError($"can't create default data class. \n{arg2}");
			}
			return result2;
		}
	}
	public enum Languages
	{
		ru,
		en
	}
	public class Text
	{
		public string ru;

		public string en;

		public Text(string ru, string en)
		{
			this.ru = ru;
			this.en = en;
		}

		public Text()
		{
		}

		public string GetTrans(Languages lang)
		{
			if (lang != Languages.en)
			{
				return ru;
			}
			return en;
		}

		public string GetTrans(string lang)
		{
			if (GetLangFromAppLang(lang) != Languages.en)
			{
				return ru;
			}
			return en;
		}

		private Languages GetLangFromAppLang(string lang)
		{
			lang = lang?.Trim()?.ToLower();
			switch (lang)
			{
			default:
				return Languages.en;
			case "ru":
			case "russian":
			case "rus":
			case "русский":
			case "ру":
			case "рус":
				return Languages.ru;
			}
		}
	}
	public class HelperLanguages : ITranslation
	{
		private readonly Dictionary<string, Text> transDict;

		private readonly ILogger logger;

		private readonly string errorString = "trans_error";

		public HelperLanguages(ILogger logger, string langsDir, string langsFname = "langs.data")
		{
			this.logger = logger;
			try
			{
				string path = Path.Combine(langsDir, langsFname);
				IDictManager dictManager = new HelperDictManager(logger);
				using (StreamReader streamReader = new StreamReader(path))
				{
					string data = streamReader.ReadToEnd();
					Dictionary<string, string> source = dictManager.ParseDict(data);
					transDict = GetTransDict(source);
				}
				logger?.LogInfo($"HelperLanguages: found translates {transDict.Count}");
			}
			catch (Exception arg)
			{
				logger?.LogError($"HelperLanguages load: {arg}");
				transDict = new Dictionary<string, Text>(StringComparer.OrdinalIgnoreCase);
			}
		}

		protected Dictionary<string, Text> GetTransDict(Dictionary<string, string> source)
		{
			Dictionary<string, Text> dictionary = new Dictionary<string, Text>(StringComparer.OrdinalIgnoreCase);
			foreach (KeyValuePair<string, string> item in source)
			{
				string[] array = item.Value.Split(new string[1] { "%lang%" }, StringSplitOptions.RemoveEmptyEntries);
				if (array == null || array.Length != 2)
				{
					logger?.LogError("HelperLanguages parse item: " + item.Key);
					continue;
				}
				string ru = array[0];
				string en = array[1];
				dictionary.Add(item.Key, new Text(ru, en));
			}
			return dictionary;
		}

		public string GetTrans(string key, Languages lang)
		{
			return GetTrans(key, lang.ToString());
		}

		public string GetTrans(string key, string lang)
		{
			try
			{
				key = key.Trim();
				lang = lang.Trim();
				return transDict[key].GetTrans(lang);
			}
			catch (Exception arg)
			{
				logger?.LogError($"HelperLanguages key {key} lang {lang}: {arg}");
				return errorString;
			}
		}

		public virtual void InitFromFile(string path)
		{
			throw new NotImplementedException();
		}

		public void InitFromString(string data)
		{
			throw new NotImplementedException();
		}
	}
}
namespace ModHelper.Interfaces
{
	public interface ICommandTargets
	{
		bool IsAllPlayers { get; }
	}
	public interface IConsoleCommandWithData : IConsoleCommand
	{
		bool Execute(IEnumerable<string> args, IEventsData data);
	}
	public interface IConsoleCommand
	{
		string Id { get; }

		bool Execute(IEnumerable<string> args);

		bool IsValidCommandArgs(IEnumerable<string> args);
	}
	public interface IDebugLogger : ILoggerWithConsole, ILogger
	{
		void LogDebugInfo(object obj);

		void LogDebugWarning(object obj);

		void LogDebugError(object obj);
	}
	public interface ILoggerWithConsole : ILogger
	{
		void LogInfoConsoleOnly(object obj);

		void LogWarningConsoleOnly(object obj);

		void LogErrorConsoleOnly(object obj);

		void LogInfoFileOnly(object obj);

		void LogWarningFileOnly(object obj);

		void LogErrorFileOnly(object obj);
	}
	public interface ICommandNotify
	{
		string ProcessMsg(string msg);
	}
	public interface ICommand
	{
		string Id { get; }
	}
	public interface IDictionaryItem<T>
	{
		string Key { get; }

		T Value { get; }
	}
	public interface IJsonUtil
	{
		T FromFile<T>(string path) where T : class;

		T FromString<T>(string s) where T : class;
	}
	public interface IDictManager
	{
		Dictionary<string, string> ParseDict(string data);
	}
	public interface ICommandManager
	{
		string GetCommandData(string eventKey, bool isLogError = false);

		string[] GetCommands();

		void InitFromString(string data);

		void InitFromFile(string path);
	}
	public interface IEventManager<CustomEvent>
	{
		CustomEvent GetEvent(string eventID, bool isLogError = false);

		IEnumerable<CustomEvent> GetEventsCollection();
	}
	public interface IEventWithData : IEvent
	{
		bool Execute(IEventsData data);
	}
	public interface IEvent
	{
		string Id { get; }

		bool Execute();
	}
	public interface ILogger
	{
		void Log(object obj);

		void LogInfo(object obj);

		void LogWarning(object obj);

		void LogError(object obj);

		void LogClear();
	}
	public interface ITranslation
	{
		string GetTrans(string key, Languages lang);

		string GetTrans(string key, string lang);

		void InitFromString(string data);

		void InitFromFile(string path);
	}
	public interface IParseManager
	{
		bool TryParseEnum<TEnum>(string arg, out TEnum result, TEnum defaultValue = default(TEnum));

		bool TryParseBool(string arg, out bool result, bool defaultValue = false);
	}
}

ChaosTricks_REPO_plugins/ModHelperUnity.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using EventsIO.Interfaces;
using ModHelper;
using ModHelper.Interfaces;
using ModHelperUnity.Data;
using ModHelperUnity.Interfaces;
using ModHelperUnity.UtilityGUI;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ModHelperUnity")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("BFT")]
[assembly: AssemblyProduct("ModHelperUnity")]
[assembly: AssemblyCopyright("Copyright ©  2020")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4afa0e1e-341b-4554-97c1-0c38ad74f246")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace ModHelperUnity
{
	public abstract class TypedNotifyBase : MonoBehaviour, IComponentTypedNotify
	{
		private bool isDisposed;

		private Queue<TypedNotifyMessage> messages;

		private bool isInitiated;

		private bool isMessageProcessed;

		private float delayAfterNotify;

		private bool isShowAnimationStageFinished;

		private bool isShowMessageStageFinished;

		private bool isHideAnimationStageFinished;

		protected int logLimit;

		protected IDebugLogger logger;

		protected Dictionary<string, Texture2D> messageTextures = new Dictionary<string, Texture2D>();

		protected readonly Dictionary<string, IPostProcessText> postProcessEvents = new Dictionary<string, IPostProcessText>();

		public TypedNotifySettings Settings { get; protected set; }

		protected TypedNotifyMessage CurrentMessage { get; private set; }

		protected TypedNotifyParameters CurrentNotifyParameters { get; private set; }

		protected virtual void Log(object obj)
		{
			IDebugLogger obj2 = logger;
			if (obj2 != null)
			{
				((ILogger)obj2).LogInfo((object)$"TypedNotifyBase: {obj}");
			}
		}

		protected virtual void LimitedLogError(object obj)
		{
			if (logLimit > 0 && logger != null)
			{
				((ILogger)logger).LogError((object)$"TypedNotifyBase: {obj}");
				logLimit--;
			}
		}

		protected virtual Texture2D GetMessageTexture(string type)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			if (!messageTextures.ContainsKey(type))
			{
				return new Texture2D(2, 2);
			}
			return messageTextures[type];
		}

		protected void LoadFadeSettings(string settingsFilePath, Func<string, byte[]> customFileReader = null)
		{
			try
			{
				if (customFileReader == null)
				{
					Settings = UtilityJson.Generate(logger).FromFile<TypedNotifySettings>(settingsFilePath);
				}
				else
				{
					byte[] bytes = customFileReader(settingsFilePath);
					string @string = Encoding.UTF8.GetString(bytes);
					Settings = UtilityJson.Generate(logger).FromString<TypedNotifySettings>(@string);
				}
			}
			catch (Exception arg)
			{
				Log($"LoadFadeSettings error: {arg}");
			}
			if (Settings == null)
			{
				Settings = new TypedNotifySettings();
			}
		}

		protected Texture2D LoadImage(string imageFilePath, Func<string, byte[]> customFileReader = null)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			try
			{
				Texture2D val = UtilityUI.LoadImage(imageFilePath, customFileReader);
				Log($"LoadImage {imageFilePath}: width {((Texture)val).width}, height {((Texture)val).height}");
				return val;
			}
			catch (Exception arg)
			{
				Log($"LoadImage {imageFilePath} error: {arg}");
				return new Texture2D(2, 2, (TextureFormat)4, false);
			}
		}

		protected void LoadResources(string folderPath, Func<string, byte[]> customFileReader = null)
		{
			Log("LoadResources");
			string text = "notify_settings.data";
			string settingsFilePath = ((folderPath == null) ? text : Path.Combine(folderPath, text));
			LoadFadeSettings(settingsFilePath, customFileReader);
			ClearMessageTextures();
			if (Settings.notifyParameters != null)
			{
				TypedNotifyParameters[] notifyParameters = Settings.notifyParameters;
				foreach (TypedNotifyParameters typedNotifyParameters in notifyParameters)
				{
					Log(typedNotifyParameters.ToString());
					string imageFilePath = ((folderPath == null) ? typedNotifyParameters.imageFileName : Path.Combine(folderPath, typedNotifyParameters.imageFileName));
					Texture2D val = LoadImage(imageFilePath, customFileReader);
					messageTextures[typedNotifyParameters.type] = val;
					((Texture)val).filterMode = (FilterMode)2;
					((Texture)val).anisoLevel = 16;
				}
			}
		}

		public virtual void PostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null)
		{
			if (!isInitiated)
			{
				ForcePostInit(folderPath, logger, customFileReader);
			}
			Log("post init completed");
		}

		public virtual void ForcePostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null)
		{
			this.logger = logger;
			try
			{
				messages = new Queue<TypedNotifyMessage>();
				CurrentMessage = null;
				CurrentNotifyParameters = new TypedNotifyParameters();
				logLimit = 10;
				isInitiated = true;
				LoadResources(folderPath, customFileReader);
			}
			catch (Exception arg)
			{
				Log($"ForcePostInit error: {arg}");
			}
			Log("force init");
		}

		protected virtual string ProcessCustomTemplates(string message, IEventsData eventData, ITranslation translation)
		{
			try
			{
				return Regex.Replace(message, "%template_.+?%", (Match s) => translation.GetTrans(s.Value, eventData.Lang));
			}
			catch (Exception arg)
			{
				Log($"ProcessCustomTemplates error: {arg}");
				return message;
			}
		}

		protected virtual string GenerateMessage(IEventsData eventData, ITranslation translation)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			TypedNotifyParameters typedNotifyParameters = GetTypedNotifyParameters(eventData);
			string trans = translation.GetTrans(eventData.EventID, eventData.Lang);
			string message = typedNotifyParameters.messageTemplate.Replace("%name%", UtilityUI.GetColoredText(eventData.Username, typedNotifyParameters.nicknameTextColor)).Replace("%message%", UtilityUI.GetColoredText(trans, typedNotifyParameters.messageTextColor));
			return ProcessCustomTemplates(message, eventData, translation);
		}

		public virtual TypedNotifyParameters GetTypedNotifyParameters(string type)
		{
			TypedNotifyParameters[] notifyParameters = Settings.notifyParameters;
			if (notifyParameters == null || notifyParameters.Length == 0)
			{
				Log("warning, notify types empty (use default)");
				return new TypedNotifyParameters();
			}
			TypedNotifyParameters[] array = notifyParameters;
			foreach (TypedNotifyParameters typedNotifyParameters in array)
			{
				if (typedNotifyParameters.type == type)
				{
					return typedNotifyParameters;
				}
			}
			return notifyParameters[0];
		}

		public virtual TypedNotifyParameters GetTypedNotifyParameters(IEventsData eventData)
		{
			TypedNotifyParameters[] notifyParameters = Settings.notifyParameters;
			if (notifyParameters == null || notifyParameters.Length == 0)
			{
				Log("warning, notify types empty (use default)");
				return new TypedNotifyParameters();
			}
			TypedNotifyParameters[] array = notifyParameters;
			foreach (TypedNotifyParameters typedNotifyParameters in array)
			{
				string[] events = typedNotifyParameters.events;
				if (events != null && events.Contains(eventData.EventID))
				{
					return typedNotifyParameters;
				}
			}
			return notifyParameters[0];
		}

		public virtual void AddNotifyToQueue(IEventsData eventData, ITranslation translation, Func<string, string> converter = null, bool applyUpperCase = true)
		{
			if (eventData == null)
			{
				Log("warning, eventData is null");
			}
			if (translation == null)
			{
				Log("warning, translation is null");
			}
			TypedNotifyParameters typedNotifyParameters = GetTypedNotifyParameters(eventData);
			string text = GenerateMessage(eventData, translation);
			if (converter != null)
			{
				text = converter(text);
			}
			text = PostProcessEvent(text, eventData.EventID, eventData.Lang);
			AddNotifyToQueue(new TypedNotifyMessage(applyUpperCase ? text.ToUpperInvariant() : text, typedNotifyParameters.type, typedNotifyParameters.showMessageDuration, typedNotifyParameters.showFadeAnimationDuration, typedNotifyParameters.hideFadeAnimationDuration));
		}

		public virtual void AddNotifyToQueue(string message, string type)
		{
			TypedNotifyParameters typedNotifyParameters = GetTypedNotifyParameters(type);
			AddNotifyToQueue(new TypedNotifyMessage(message, type, typedNotifyParameters.showMessageDuration, typedNotifyParameters.showFadeAnimationDuration, typedNotifyParameters.hideFadeAnimationDuration));
		}

		public virtual void AddNotifyToQueue(TypedNotifyMessage notifyMessage)
		{
			if (!isInitiated)
			{
				Log("error, attempt to use the manager before init completed");
				return;
			}
			if (notifyMessage == null)
			{
				Log("error, message is null");
				return;
			}
			messages.Enqueue(notifyMessage);
			Log("add new notify message: " + notifyMessage.message);
		}

		public virtual void ClearNotifyQueue()
		{
			if (isInitiated)
			{
				messages.Clear();
			}
		}

		public virtual void StopCurrentNotify()
		{
			CurrentMessage = null;
			isShowAnimationStageFinished = true;
			isShowMessageStageFinished = true;
			isHideAnimationStageFinished = true;
			isMessageProcessed = false;
		}

		protected virtual void Update()
		{
			try
			{
				if (!isInitiated)
				{
					return;
				}
				if (CurrentMessage == null)
				{
					if (delayAfterNotify > 0f)
					{
						delayAfterNotify -= Time.deltaTime;
					}
					else if (messages.Count > 0)
					{
						CurrentMessage = messages.Peek();
						CurrentNotifyParameters = GetTypedNotifyParameters(CurrentMessage.messageType);
						delayAfterNotify = CurrentNotifyParameters.delayAfterNotify;
						StartShowAnimation();
					}
					return;
				}
				if (!isShowAnimationStageFinished)
				{
					UpdateProcessShowAnimation();
				}
				else if (!isShowMessageStageFinished)
				{
					UpdateProcessNoAnimationStage();
				}
				else if (!isHideAnimationStageFinished)
				{
					UpdateProcessHideAnimation();
				}
				if (isMessageProcessed)
				{
					messages.Dequeue();
					CurrentMessage = null;
					isMessageProcessed = false;
				}
			}
			catch (Exception obj)
			{
				LimitedLogError(obj);
			}
		}

		protected virtual void UpdateProcessShowAnimation()
		{
			if (CurrentMessage.showFadeAnimationDuration > 0f)
			{
				CurrentMessage.showFadeAnimationDuration -= Time.deltaTime;
			}
			else
			{
				FinishShowAnimation();
			}
		}

		protected virtual void UpdateProcessNoAnimationStage()
		{
			if (CurrentMessage.showMessageDuration > 0f)
			{
				CurrentMessage.showMessageDuration -= Time.deltaTime;
			}
			else
			{
				StartHideAnimation();
			}
		}

		protected virtual void UpdateProcessHideAnimation()
		{
			if (CurrentMessage.hideFadeAnimationDuration > 0f)
			{
				CurrentMessage.hideFadeAnimationDuration -= Time.deltaTime;
			}
			else
			{
				FinishHideAnimation();
			}
		}

		protected virtual void Start()
		{
		}

		protected virtual void Awake()
		{
		}

		protected virtual void OnGUI()
		{
		}

		protected virtual void StartShowAnimation()
		{
			isShowAnimationStageFinished = false;
			Log("start show animation");
		}

		protected virtual void FinishShowAnimation()
		{
			isShowAnimationStageFinished = true;
			isShowMessageStageFinished = false;
			Log("finish show animation");
		}

		protected virtual void StartHideAnimation()
		{
			isHideAnimationStageFinished = false;
			isShowMessageStageFinished = true;
			Log("start hide animation");
		}

		protected virtual void FinishHideAnimation()
		{
			isHideAnimationStageFinished = true;
			isMessageProcessed = true;
			Log("finish hide animation");
		}

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}

		protected virtual void ClearMessageTextures()
		{
			if (messageTextures == null)
			{
				return;
			}
			foreach (Texture2D value in messageTextures.Values)
			{
				((Object)value).hideFlags = (HideFlags)61;
				Object.Destroy((Object)(object)value);
			}
		}

		protected virtual void Dispose(bool disposing)
		{
			if (!isDisposed)
			{
				ClearMessageTextures();
				messageTextures = null;
				isDisposed = true;
			}
		}

		~TypedNotifyBase()
		{
			try
			{
				Dispose(disposing: false);
			}
			finally
			{
				((object)this).Finalize();
			}
		}

		public void RegisterPostProcessEvent(string key, IPostProcessText e)
		{
			if (string.IsNullOrEmpty(key) || e == null)
			{
				IDebugLogger obj = logger;
				if (obj != null)
				{
					((ILogger)obj).LogError((object)("TypedNotifyOnGUI RegisterPostProcessEvent invalid arg error for key '" + key + "'"));
				}
			}
			else
			{
				postProcessEvents[key] = e;
			}
		}

		protected string PostProcessEvent(string text, string eventKey, string langKey)
		{
			if (string.IsNullOrEmpty(eventKey) || text == null)
			{
				IDebugLogger obj = logger;
				if (obj != null)
				{
					((ILogger)obj).LogWarning((object)("TypedNotifyOnGUI PostProcessEvent invalid arg error for key '" + eventKey + "', text " + text));
				}
				return text;
			}
			if (!postProcessEvents.TryGetValue(eventKey, out var value))
			{
				return text;
			}
			return value.PostProcessText(text, langKey);
		}
	}
	public static class UtilityUI
	{
		public static int StandardScreenWidth => 2560;

		public static int StandardScreenHeight => 1440;

		public static string GetColoredText(string text, Color32 color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			string text2 = ColorUtility.ToHtmlStringRGBA(Color32.op_Implicit(color));
			return "<color=#" + text2 + ">" + text + "</color>";
		}

		public static Texture2D LoadImage(string imageFilePath, Func<string, byte[]> customFileReader = null)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_0025: Expected O, but got Unknown
			byte[] array = ((customFileReader == null) ? File.ReadAllBytes(imageFilePath) : customFileReader(imageFilePath));
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			ImageConversion.LoadImage(val, array);
			return val;
		}

		public static float CalcScreenFactor(int baseScreenSize, int currentScreenSize)
		{
			if (baseScreenSize != currentScreenSize)
			{
				return (float)currentScreenSize / (float)baseScreenSize;
			}
			return 1f;
		}
	}
	public class MathUtility
	{
		public static bool RandomBool()
		{
			return Random.value > 0.5f;
		}

		public static int GetRandomSign()
		{
			if (!RandomBool())
			{
				return 1;
			}
			return -1;
		}

		public static Vector3 GetRandomPointOnCircle(float radius = 1f)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			Vector2 insideUnitCircle = Random.insideUnitCircle;
			return Vector2.op_Implicit(((Vector2)(ref insideUnitCircle)).normalized * radius);
		}

		public static Vector3 GetRandomPointOnCircleInForward(Vector3 forward, float radiusMin, float radiusMax, float minAngleInDeg = -90f, float maxAngleInDeg = 90f)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = forward;
			val.y = 0f;
			val = ((Vector3)(ref val)).normalized;
			if (minAngleInDeg > maxAngleInDeg)
			{
				float num = minAngleInDeg;
				minAngleInDeg = maxAngleInDeg;
				maxAngleInDeg = num;
			}
			float num2 = Random.Range(minAngleInDeg, maxAngleInDeg);
			if (radiusMin < 0f)
			{
				radiusMin = 0f;
			}
			if (radiusMax < 0f)
			{
				radiusMax = 1f;
			}
			if (radiusMin > radiusMax)
			{
				float num3 = radiusMin;
				radiusMin = radiusMax;
				radiusMax = num3;
			}
			float num4 = Random.Range(radiusMin, radiusMax);
			Vector3 result = default(Vector3);
			float num5 = (float)Math.PI / 180f * num2;
			float num6 = Mathf.Atan2(val.z, val.x);
			num5 += num6;
			result.x = num4 * Mathf.Cos(num5);
			result.z = num4 * Mathf.Sin(num5);
			return result;
		}

		public static Vector3 FindRandomSpawnPointNearPosition(Vector3 pos, float minDistance, float maxDistance)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if (maxDistance < 0f)
			{
				maxDistance = 10f;
			}
			if (minDistance < 0f || minDistance > maxDistance)
			{
				minDistance = 0f;
			}
			Vector3 result = default(Vector3);
			float num = Random.Range(-(float)Math.PI, (float)Math.PI);
			float num2 = Random.Range(minDistance, maxDistance);
			result.x = Mathf.Floor(pos.x + num2 * Mathf.Cos(num));
			result.z = Mathf.Floor(pos.z + num2 * Mathf.Sin(num));
			result.y = pos.y;
			return result;
		}

		public static Vector3 FindRandomSpawnPointNearPositionFixY(Vector3 pos, float minDistance, float maxDistance, float yFixOffset, LayerMask mask)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 result = FindRandomSpawnPointNearPosition(pos, minDistance, maxDistance);
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(pos + Vector3.up * 10f, Vector3.down, ref val, 10f, LayerMask.op_Implicit(mask)))
			{
				result = ((RaycastHit)(ref val)).point;
				result.y += yFixOffset;
			}
			return result;
		}

		public static Vector3 GetRandomVector(Vector3 randomRangeMin, Vector3 randomRangeMax)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			float num = Random.Range(randomRangeMin.x, randomRangeMax.x);
			float num2 = Random.Range(randomRangeMin.y, randomRangeMax.y);
			float num3 = Random.Range(randomRangeMin.z, randomRangeMax.z);
			return new Vector3(num, num2, num3);
		}

		public static void LookAt(Transform obj, Transform target)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = target.position - obj.position;
			obj.rotation = Quaternion.LookRotation(val);
		}
	}
	public static class Loader
	{
		private static ILogger logger;

		private static GameObject hookObj;

		private const string ASSEMBLY_NAME = "InteractiveMod";

		private const string CLASS_MOD = "InteractiveMod";

		public static GameObject HookObj { get; set; }

		static Loader()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			logger = (ILogger)new HelperLog(UtilitySettings.BaseFolder, "loader_log.txt");
			logger.LogClear();
		}

		public static async Task StartInitTask(Type type)
		{
			int counter = 0;
			do
			{
				await Task.Delay(5000);
				if ((Object)(object)hookObj == (Object)null)
				{
					logger.LogInfo((object)"Background task: trying to create mod instance");
					hookObj = new GameObject();
					Object.DontDestroyOnLoad((Object)(object)hookObj);
					hookObj.AddComponent(type);
					hookObj.SetActive(true);
				}
				int num = counter + 1;
				counter = num;
			}
			while (counter <= 10 && (!((Object)(object)hookObj != (Object)null) || counter <= 2));
			logger.LogInfo((object)"Background task closed");
		}

		public static void LoadAssembly()
		{
			logger.LogInfo((object)"load mod assembly");
			Assembly assembly = AppDomain.CurrentDomain.Load("InteractiveMod");
			CancellationToken token = new CancellationTokenSource().Token;
			if (!string.Equals(assembly.GetName().Name, "InteractiveMod", StringComparison.OrdinalIgnoreCase))
			{
				logger.LogError((object)"wrong assembly mod name");
				return;
			}
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				bool num = string.Equals(type.Name, "InteractiveMod", StringComparison.OrdinalIgnoreCase);
				Type typeFromHandle = typeof(MonoBehaviour);
				if (!num || (!type.IsAssignableFrom(typeFromHandle) && !type.IsSubclassOf(typeFromHandle)))
				{
					continue;
				}
				logger.LogInfo((object)"Found valid type in Loader class");
				Task.Factory.StartNew((Func<Task>)async delegate
				{
					try
					{
						await StartInitTask(type);
					}
					catch (Exception arg)
					{
						logger.LogError((object)$"LoadAssembly task error {arg}");
					}
				}, token, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
				return;
			}
			logger.LogError((object)"init failed");
		}

		public static void Init()
		{
			logger.LogInfo((object)"Loader triggered");
			try
			{
				LoadAssembly();
			}
			catch (Exception arg)
			{
				logger.LogError((object)$"ModHelperUnity.Init {arg}");
			}
		}
	}
	public class Patcher
	{
		private readonly ILogger logger = (ILogger)new HelperLog(UtilitySettings.BaseFolder, "patcher_log.txt");

		private bool isPatched;

		internal void ExecutePatch()
		{
			try
			{
				logger.LogClear();
				logger.LogInfo((object)$"Patcher v{Assembly.GetExecutingAssembly().GetName().Version}");
				SceneManager.sceneLoaded += OnSceneLoaded;
			}
			catch (Exception arg)
			{
				logger.LogError((object)$"Patcher unexpected error: {arg}");
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode)
		{
			try
			{
				logger.Log((object)("OnSceneLoaded triggered: " + ((Scene)(ref scene)).name));
				if (!isPatched)
				{
					Loader.Init();
					isPatched = true;
					SceneManager.sceneLoaded -= OnSceneLoaded;
				}
			}
			catch (Exception arg)
			{
				logger.LogError((object)$"Patcher unexpected error: {arg}");
			}
		}
	}
	public static class Preloader
	{
		private static string baseFolderFullPath;

		private static readonly ILogger logger = (ILogger)new HelperLog(UtilitySettings.BaseFolder, "preloader_log.txt");

		public static string GetAssemblyModFolderFullPath()
		{
			return baseFolderFullPath;
		}

		public static void Main()
		{
			logger.LogClear();
			logger.LogInfo((object)"Preloader main");
			baseFolderFullPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			AppDomain.CurrentDomain.AssemblyResolve += ModAssemblyResolve;
			new Patcher().ExecutePatch();
		}

		private static Assembly ModAssemblyResolve(object sender, ResolveEventArgs args)
		{
			try
			{
				string text = Path.Combine(GetAssemblyModFolderFullPath(), new AssemblyName(args.Name).Name + ".dll");
				logger.LogInfo((object)text);
				if (File.Exists(text))
				{
					return Assembly.LoadFrom(text);
				}
			}
			catch (Exception arg)
			{
				logger.LogError((object)$"error: {arg}");
			}
			return null;
		}
	}
}
namespace ModHelperUnity.UtilityGUI
{
	public class TypedNotifyOnGUI : TypedNotifyBase
	{
		private float currentAlpha;

		private float targetAlpha;

		protected Dictionary<string, Font> fonts;

		public override void ForcePostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null)
		{
			base.ForcePostInit(folderPath, logger, customFileReader);
			try
			{
				fonts = new Dictionary<string, Font>();
				TypedNotifyParameters[] notifyParameters = base.Settings.notifyParameters;
				foreach (TypedNotifyParameters typedNotifyParameters in notifyParameters)
				{
					try
					{
						string fontPath = typedNotifyParameters.fontPath;
						if (!fonts.ContainsKey(fontPath))
						{
							Font val = Resources.Load<Font>(fontPath);
							if ((Object)(object)val != (Object)null)
							{
								fonts.Add(fontPath, val);
							}
						}
					}
					catch (Exception arg)
					{
						if (logger != null)
						{
							((ILogger)logger).LogError((object)$"TypedNotifyOnGUI loading font: {arg}");
						}
					}
				}
			}
			catch (Exception arg2)
			{
				if (logger != null)
				{
					((ILogger)logger).LogError((object)$"TypedNotifyOnGUI PostInit: {arg2}");
				}
			}
		}

		protected Font GetFont(string path, int size)
		{
			try
			{
				if (fonts.ContainsKey(path))
				{
					return fonts[path];
				}
				string key = $"{path}_{size}";
				if (fonts.ContainsKey(key))
				{
					return fonts[key];
				}
				Font val = Font.CreateDynamicFontFromOSFont(path, size);
				if ((Object)(object)val != (Object)null)
				{
					fonts.Add(key, val);
				}
				return val;
			}
			catch (Exception arg)
			{
				IDebugLogger obj = logger;
				if (obj != null)
				{
					((ILogger)obj).LogError((object)$"TypedNotifyOnGUI finding font: {arg}");
				}
			}
			return null;
		}

		protected virtual void SetupAlpha(float baseDuration)
		{
			if (!Mathf.Approximately(currentAlpha, targetAlpha))
			{
				currentAlpha = Mathf.MoveTowards(currentAlpha, targetAlpha, Time.deltaTime / baseDuration);
			}
		}

		protected override void UpdateProcessShowAnimation()
		{
			SetupAlpha(base.CurrentNotifyParameters.showFadeAnimationDuration);
			base.UpdateProcessShowAnimation();
		}

		protected override void UpdateProcessNoAnimationStage()
		{
			SetupAlpha(base.CurrentNotifyParameters.showMessageDuration);
			base.UpdateProcessNoAnimationStage();
		}

		protected override void UpdateProcessHideAnimation()
		{
			SetupAlpha(base.CurrentNotifyParameters.hideFadeAnimationDuration);
			base.UpdateProcessHideAnimation();
		}

		protected override void StartShowAnimation()
		{
			base.StartShowAnimation();
			targetAlpha = 1f;
		}

		protected override void StartHideAnimation()
		{
			base.StartHideAnimation();
			targetAlpha = 0f;
		}

		protected string GetFadedText(string text)
		{
			string text2 = ((int)(255f * currentAlpha)).ToString("X2");
			return text.Replace("FF>", text2 + ">");
		}

		protected override void OnGUI()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Expected O, but got Unknown
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			base.OnGUI();
			TypedNotifyParameters currentNotifyParameters = base.CurrentNotifyParameters;
			if (!base.Settings.isDisableNotify && base.CurrentMessage != null && currentNotifyParameters != null && !currentNotifyParameters.isDisable)
			{
				Matrix4x4 matrix = GUI.matrix;
				Color color = GUI.color;
				color.a = currentAlpha;
				GUI.color = color;
				Texture2D messageTexture = GetMessageTexture(base.CurrentMessage.messageType);
				float num = UtilityUI.CalcScreenFactor(UtilityUI.StandardScreenWidth, Screen.width);
				float num2 = UtilityUI.CalcScreenFactor(UtilityUI.StandardScreenHeight, Screen.height);
				float num3 = (float)((Texture)messageTexture).width * num;
				float num4 = (float)((Texture)messageTexture).height * num2;
				Rect val = default(Rect);
				((Rect)(ref val)).x = ((float)Screen.width - num3) * (0.5f + currentNotifyParameters.notifyHorizontalOffset);
				((Rect)(ref val)).y = ((float)Screen.height - num4) * (0.5f + currentNotifyParameters.notifyVerticalOffset);
				((Rect)(ref val)).width = num3;
				((Rect)(ref val)).height = num4;
				Rect val2 = val;
				float num5 = Math.Min(num, num2);
				float num6 = Math.Max(num, num2);
				int num7 = (int)((float)currentNotifyParameters.fontSize * num5);
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					fontSize = num7,
					alignment = (TextAnchor)4,
					richText = true,
					fixedWidth = num3,
					fixedHeight = num4
				};
				Font font = GetFont(currentNotifyParameters.fontPath, num7);
				if ((Object)(object)font != (Object)null)
				{
					val3.font = font;
				}
				val3.padding.top = (int)((float)currentNotifyParameters.textPadding.top * num6);
				val3.padding.bottom = (int)((float)currentNotifyParameters.textPadding.bottom * num6);
				val3.padding.left = (int)((float)currentNotifyParameters.textPadding.left * num6);
				val3.padding.right = (int)((float)currentNotifyParameters.textPadding.right * num6);
				val3.normal.textColor = color;
				GUI.DrawTexture(val2, (Texture)(object)messageTexture);
				GUI.Label(val2, GetFadedText(base.CurrentMessage.message), val3);
				GUI.matrix = matrix;
			}
		}
	}
	public class TypedNotifySettings
	{
		public bool isDisableNotify;

		public TypedNotifyParameters[] notifyParameters = new TypedNotifyParameters[0];

		public override string ToString()
		{
			if (notifyParameters == null)
			{
				return "TypedNotifySettings: not found notifyParameters";
			}
			string text = $"isDisableNotify={isDisableNotify}";
			TypedNotifyParameters[] array = notifyParameters;
			for (int i = 0; i < array.Length; i++)
			{
				_ = array[i];
				text = string.Join(Environment.NewLine, text, "notifyParameters:", notifyParameters.ToString());
			}
			return text;
		}
	}
}
namespace ModHelperUnity.Interfaces
{
	public interface IComponentTypedNotify
	{
		void AddNotifyToQueue(string message, string type);

		void AddNotifyToQueue(IEventsData eventData, ITranslation translation, Func<string, string> converter = null, bool applyUpperCase = true);

		void ClearNotifyQueue();

		void StopCurrentNotify();

		void PostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null);

		void ForcePostInit(string folderPath, IDebugLogger logger = null, Func<string, byte[]> customFileReader = null);

		void RegisterPostProcessEvent(string key, IPostProcessText e);
	}
	public interface IPostProcessText
	{
		string PostProcessText(string text, string langKey);
	}
	public interface ISoundManager
	{
		void PlaySound(string path, int volume = 50);

		void StopSound();
	}
	public interface IDictionaryItemJson<T>
	{
		string Key { get; }

		T Value { get; }
	}
}
namespace ModHelperUnity.Data
{
	public class TypedNotifyParameters
	{
		public bool isDisable;

		public string imageFileName = string.Empty;

		public string type = "default";

		public string messageTemplate = "%name% %message%";

		public string fontPath = "";

		public float showMessageDuration = 5f;

		public float showFadeAnimationDuration = 1f;

		public float hideFadeAnimationDuration = 1f;

		public float delayAfterNotify = 1f;

		public float notifyHorizontalOffset;

		public float notifyVerticalOffset = -0.45f;

		public int fontSize = 19;

		public Padding textPadding = new Padding
		{
			bottom = 20,
			top = 20,
			left = 24,
			right = 24
		};

		public Color32 nicknameTextColor = new Color32((byte)65, (byte)160, (byte)94, byte.MaxValue);

		public Color32 messageTextColor = new Color32((byte)65, (byte)160, (byte)94, byte.MaxValue);

		public string[] events = new string[0];

		public override string ToString()
		{
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			return string.Join(Environment.NewLine, "imageFileName: " + imageFileName, "type: " + type, $"showMessageDuration: {showMessageDuration}", $"showFadeAnimationDuration: {showFadeAnimationDuration}", $"hideFadeAnimationDuration: {hideFadeAnimationDuration}", $"delayAfterNotify: {delayAfterNotify}", $"notifyHorizontalOffset: {notifyHorizontalOffset}", $"notifyVerticalOffset: {notifyVerticalOffset}", $"textPadding: {textPadding}", $"fontSize: {fontSize}", $"isDisable: {isDisable}", $"nicknameTextColor: {nicknameTextColor}", $"messageTextColor: {messageTextColor}", "events: " + string.Join(Environment.NewLine, events), "fontPath: " + fontPath);
		}
	}
	public class Padding
	{
		public int left;

		public int right;

		public int top;

		public int bottom;

		public Padding()
		{
		}

		public Padding(int left, int right, int top, int bottom)
		{
			this.left = left;
			this.right = right;
			this.top = top;
			this.bottom = bottom;
		}

		public RectOffset GetRect()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			return new RectOffset(left, right, top, bottom);
		}

		public override string ToString()
		{
			return $"left: {left}, right: {right}, top: {top}, bottom: {bottom}";
		}
	}
	public class TypedNotifyMessage
	{
		public readonly string message;

		public readonly string messageType;

		public float showMessageDuration;

		public float showFadeAnimationDuration;

		public float hideFadeAnimationDuration;

		public TypedNotifyMessage(string message, string messageType, float showMessageDuration, float showFadeAnimationDuration, float hideFadeAnimationDuration)
		{
			this.message = (string.IsNullOrEmpty(message?.Trim()) ? string.Empty : message);
			this.messageType = messageType;
			this.showMessageDuration = showMessageDuration;
			this.showFadeAnimationDuration = showFadeAnimationDuration;
			this.hideFadeAnimationDuration = hideFadeAnimationDuration;
		}
	}
	public class NotifyMessage
	{
		private readonly string msg;

		private float durationInSec;

		public NotifyMessage(string msg, float durationInSec)
		{
			this.msg = (string.IsNullOrEmpty(msg?.Trim()) ? string.Empty : msg);
			this.durationInSec = durationInSec;
		}

		public string GetMessage()
		{
			return msg;
		}

		public bool IsFinished()
		{
			return durationInSec <= 0f;
		}

		public void OnFrame(float dtInSec)
		{
			if (!IsFinished())
			{
				durationInSec -= dtInSec;
			}
		}
	}
}

ChaosTricks_REPO_plugins/WebSocketIO.dll

Decompiled 3 weeks ago
using 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 + "\"}";
		}
	}
}