Decompiled source of ChaosTricks Twitch Integration for SOTF v1.1.7

plugins/ChaosTricks/ChaosTricksPlugin.dll

Decompiled a month ago
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Il2CppInterop.Runtime.Injection;
using UnityEngine;
using bft_mod;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BFT")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ChaosTricksPlugin")]
[assembly: AssemblyTitle("ChaosTricksPlugin")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ChaosTricksPlugin;

public static class PluginInfo
{
	public const string PLUGIN_GUID = "36601542-7EB9-44B2-8036-57FC97579AA0";

	public const string PLUGIN_NAME = "ChaosTricks";

	public const string PLUGIN_VERSION = "1.0.0";
}
[BepInPlugin("36601542-7EB9-44B2-8036-57FC97579AA0", "ChaosTricks", "1.0.0")]
public class ChaosTricksPlugin : BasePlugin
{
	public override void Load()
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Expected O, but got Unknown
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		ManualLogSource log = ((BasePlugin)this).Log;
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(33, 1, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("BFT ChaosTricks plugin ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("36601542-7EB9-44B2-8036-57FC97579AA0");
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is loaded");
		}
		log.LogInfo(val);
		ClassInjector.RegisterTypeInIl2Cpp<InteractiveMod>();
		GameObject val2 = new GameObject
		{
			hideFlags = (HideFlags)61
		};
		Object.DontDestroyOnLoad((Object)val2);
		val2.AddComponent<InteractiveMod>();
		val2.SetActive(true);
		((BasePlugin)this).Log.LogInfo((object)"BFT mod init finished");
	}
}

plugins/ChaosTricks/EventsIO.dll

Decompiled a month 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.Versioning;
using System.Text;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BFT")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EventsIO")]
[assembly: AssemblyTitle("EventsIO")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace EventsIO;

public class EventsData
{
	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
{
	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%" }
	};

	public string ClientAppSep => clientAppSep;

	public char ClientAppSepChar => clientAppSepChar;

	public string ClientAppEqual => clientAppEqual;

	public char 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
{
	protected readonly Action<string> log;

	protected readonly EventsDataEncoder encoder;

	protected readonly EventsDataEncoder encoderParams;

	public bool isLogInfoError = true;

	public bool isLogSkipEmpty;

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

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

	public virtual EventsData 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
{
	protected internal enum FieldNames
	{
		UserName,
		EventID,
		Cost,
		Lang,
		ExtraInfo
	}

	protected EventsData data;

	protected readonly EventsDataEncoder encoder;

	protected readonly EventsDataEncoder encoderParams;

	public EventsGenerator()
	{
		data = new EventsData();
		encoderParams = (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 stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder3 = stringBuilder2;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(0, 3, stringBuilder2);
				handler.AppendFormatted(item.Key);
				handler.AppendFormatted(clientAppEqual);
				handler.AppendFormatted(item.Value);
				stringBuilder3.Append(ref handler);
				flag = false;
			}
			else
			{
				StringBuilder stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder4 = stringBuilder2;
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(0, 4, stringBuilder2);
				handler.AppendFormatted(clientAppSep);
				handler.AppendFormatted(item.Key);
				handler.AppendFormatted(clientAppEqual);
				handler.AppendFormatted(item.Value);
				stringBuilder4.Append(ref handler);
			}
		}
		data = new EventsData();
		return stringBuilder.ToString();
	}
}
public class EventsReader
{
	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 value)
		{
			ReaderLogError($"read event error: {value}");
		}
		return null;
	}
}
public class EventsReaderOnFrame : EventsReader
{
	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<EventsData> processEvent;

	protected readonly EventsDataParser parser;

	protected IEnumerator<EventsData> 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 value)
			{
				ReaderLogError($"StartProcessOnFrame error: {value}");
			}
		}
		eventsData = null;
	}

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

	public EventsReaderOnFrame(string path, Action<EventsData> processEvent, EventsDataParser 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 EventsReaderOnFrame(string path, Action<string, string, string, string, string> processEvent, EventsDataParser parser, Action<string> log = null, Action<string> errorLog = null, float checkPeriod = 2f, float delay = 1f, float initDelay = 0.5f)
		: base(log, errorLog)
	{
		this.processEvent = delegate(EventsData e)
		{
			processEvent?.Invoke(e.Username, e.Cost, e.EventID, e.Lang, e.ExtraInfo);
		};
		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 value)
		{
			ReaderLogError($"SetEventsToProcess error: {value}");
		}
	}

	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 value)
		{
			ReaderLogError($"ProcessAllWithDelay error: {value}");
		}
	}

	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 EventsReaderOnKey : EventsReader
{
	protected readonly Action<EventsData> processEvent;

	protected readonly EventsDataParser parser;

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

	public EventsReaderOnKey(Action<string, string, string, string, string> processEvent, EventsDataParser parser, Action<string> log = null, Action<string> logError = null)
		: base(log, logError)
	{
		this.processEvent = delegate(EventsData e)
		{
			processEvent?.Invoke(e.Username, e.Cost, e.EventID, e.Lang, e.ExtraInfo);
		};
		this.parser = parser;
	}

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

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

	public virtual void ReadAndProcessAllOnKey(string path, bool isClearFile = true)
	{
		ProcessAllOnKey(ReadAll(path, isClearFile));
	}
}

plugins/ChaosTricks/InteractiveMod.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using EventsIO;
using Il2CppSystem;
using Microsoft.CodeAnalysis;
using ModHelper;
using ModHelper.Data;
using ModHelperUnity;
using ModHelperUnity.UtilityGUI;
using ModUnityTools;
using Sons.Loading;
using TheForest;
using TheForest.Utils;
using UnityEngine;
using bft_mod.Command;
using bft_mod.HelperBFT;
using bft_mod.Service;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BFT")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Sons of The Forest mod")]
[assembly: AssemblyTitle("InteractiveMod")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace bft_mod
{
	public class InteractiveMod : MonoBehaviour
	{
		private HelperCommandManagerFormatted commandManager;

		private EventsDataParser eventsParser;

		private EventsReaderOnFrame eventsReader;

		private EventsReaderOnKey eventsReaderByKey;

		private TypedNotifyOnGUI notifyManager;

		private const int UPDATE_ERRORS_LIMIT = 50;

		private int updateErrorsLimit = 50;

		private bool isQuiting;

		private string keyEventsPath;

		private bool isInitiated;

		private bool isNeedTriggerOnFirstConnect = true;

		private bool isNeedShowConnectMessage;

		private bool isNeedShowDisconnectMessage;

		public UtilityConsole console;

		public void Awake()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			try
			{
				UtilitySettings.BaseFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
				Console.WriteLine(UtilitySettings.BaseFolder);
				((HelperLog)LoggerFactory.Logger).LogClear();
			}
			catch (Exception value)
			{
				((HelperLog)LoggerFactory.Logger).Log((object)$"Awake {value}");
			}
			if (isInitiated)
			{
				((HelperLog)LoggerFactory.Logger).Log((object)"InteractiveMod is already initiated");
				return;
			}
			((HelperLog)LoggerFactory.Logger).Log((object)"InteractiveMod Awake");
			isInitiated = true;
			((HelperLog)LoggerFactory.Logger).Log((object)"init console");
			console = new UtilityConsole(LoggerFactory.Logger, (List<string>)null);
			try
			{
				((HelperLog)LoggerFactory.Logger).Log((object)"init data parser");
				eventsParser = new EventsDataParser((Action<string>)((HelperLog)LoggerFactory.Logger).Log);
				((HelperLog)LoggerFactory.Logger).Log((object)"init reader");
				eventsReader = new EventsReaderOnFrame(CreateEventsFile(), (Action<string, string, string, string, string>)ProcessEvent, eventsParser, (Action<string>)((HelperLog)LoggerFactory.Logger).Log, (Action<string>)((HelperLog)LoggerFactory.Logger).Log, 1f, 0.1f, 0.5f)
				{
					IsDelayEveryProcessing = true
				};
				keyEventsPath = Path.Combine(UtilitySettings.BaseFolder, "events_key.txt");
				eventsReaderByKey = new EventsReaderOnKey((Action<string, string, string, string, string>)ProcessEvent, eventsParser, (Action<string>)((HelperLog)LoggerFactory.Logger).Log, (Action<string>)((HelperLog)LoggerFactory.Logger).Log);
				InitOthersManagers();
				InitCommands(isNeedValidate: true);
			}
			catch (Exception value2)
			{
				((HelperLog)LoggerFactory.Logger).Log((object)$"init error: {value2}");
			}
			((HelperLog)LoggerFactory.Logger).Log((object)"InteractiveMod init end");
		}

		private string CreateEventsFile()
		{
			try
			{
				string text = Path.Combine(Path.GetTempPath(), "chaos_tricks");
				if (!Directory.Exists(text))
				{
					Directory.CreateDirectory(text);
				}
				text = Path.Combine(text, "sons_of_the_forest.txt");
				File.CreateText(text).Close();
				return text;
			}
			catch (Exception value)
			{
				((HelperLog)LoggerFactory.Logger).Log((object)$"InteractiveMod create events source error: {value}");
				return Path.Combine(Path.GetTempPath(), "chaos_tricks", "sons_of_the_forest.txt");
			}
		}

		public void OnDestroy()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			((HelperLog)LoggerFactory.Logger).Log((object)"InteractiveMod OnDestroy");
			if (!isQuiting)
			{
				((HelperLog)LoggerFactory.Logger).Log((object)"InteractiveMod reinit mod script");
				GameObject val = new GameObject();
				val.AddComponent<InteractiveMod>();
				val.SetActive(true);
			}
		}

		public void OnApplicationQuit()
		{
			((HelperLog)LoggerFactory.Logger).Log((object)"InteractiveMod OnApplicationQuit");
			isQuiting = true;
		}

		public void InitLogFlushTask()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			ScheduleFactory.Instance.NewPeriodicTask(new PeriodicTaskData
			{
				periodicAction = delegate
				{
					HelperDebugLog logger = LoggerFactory.Logger;
					HelperDebugLog obj = ((logger is BufferedLogger) ? logger : null);
					if (obj != null)
					{
						((BufferedLogger)obj).Flush(true);
					}
				},
				period = 5f
			}, false);
		}

		public void InitOthersManagers()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			((HelperLog)LoggerFactory.Logger).Log((object)"init HelperLanguages");
			TranslationFactory.Reinit();
			TranslationFactory.Instance.InitFromFile(Path.Combine(UtilitySettings.BaseFolder, "langs.data"));
			((HelperLog)LoggerFactory.Logger).Log((object)"init ScheduleManager");
			ScheduleFactory.Reinit();
			InitLogFlushTask();
			updateErrorsLimit = 50;
			if (notifyManager == null)
			{
				notifyManager = new TypedNotifyOnGUI();
			}
			TypedNotifyOnGUI obj = notifyManager;
			if (obj != null)
			{
				((TypedNotifyBase)obj).ForcePostInit(UtilitySettings.BaseFolder, (HelperLog)(object)LoggerFactory.Logger, (Func<string, byte[]>)null);
			}
		}

		public void InitCommands(bool isNeedValidate)
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			console.RegisterCommand((ConsoleCommand)(object)new GameConsoleCommand());
			console.RegisterCommand((ConsoleCommand)(object)new Immortality());
			console.RegisterCommand((ConsoleCommand)(object)new InfiniteAmmo());
			console.RegisterCommand((ConsoleCommand)(object)new InfiniteEnergy());
			console.RegisterCommand((ConsoleCommand)(object)new SpeedyRun());
			console.RegisterCommand((ConsoleCommand)(object)new SuperJump());
			console.RegisterCommand((ConsoleCommand)(object)new InvertLook());
			console.RegisterCommand((ConsoleCommand)(object)new AnimSpeedAI());
			console.RegisterCommand((ConsoleCommand)(object)new Gravity());
			console.RegisterCommand((ConsoleCommand)(object)new TimeScale());
			console.RegisterCommand((ConsoleCommand)(object)new StopCommandTimer());
			console.RegisterCommand((ConsoleCommand)(object)new MouseSensitivity());
			commandManager = new HelperCommandManagerFormatted((HelperLog)(object)LoggerFactory.Logger);
			commandManager.InitFromFile(Path.Combine(UtilitySettings.BaseFolder, "commands.data"));
			if (!isNeedValidate)
			{
				return;
			}
			((HelperLog)LoggerFactory.Logger).Log((object)"init HelperCommandManager");
			string[] commands = commandManager.GetCommands();
			foreach (string text in commands)
			{
				if (!console.IsValidCommandLine(text?.Trim()))
				{
					((HelperLog)LoggerFactory.Logger).Log((object)("command line '" + text + "' invalid"));
				}
			}
		}

		private int GetRndNumberFromArgGroup(string group)
		{
			if (string.IsNullOrEmpty(group))
			{
				return 1;
			}
			string[] array = group.Split(new char[2] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
			if (array != null && array.Length >= 2)
			{
				int.TryParse(array[0], out var result);
				int.TryParse(array[1], out var result2);
				int num = Random.Range(result, result2);
				((HelperLog)LoggerFactory.Logger).Log((object)$"GetRndNumberFromArgGroup get value: {num}");
				return num;
			}
			((HelperLog)LoggerFactory.Logger).Log((object)"GetRndNumberFromArgGroup wrong group size");
			return 1;
		}

		private string ProcessCommandCustomArgs(string cmd)
		{
			string pattern = "(rnd\\()(.+?)(\\))";
			return Regex.Replace(cmd, pattern, delegate(Match groups)
			{
				string value = groups.Groups[2].Value;
				return GetRndNumberFromArgGroup(value).ToString();
			});
		}

		private void ProcessEvent(string username, string cost, string eventID, string lang, string extraInfo)
		{
			if (string.IsNullOrEmpty(eventID))
			{
				return;
			}
			((HelperLog)LoggerFactory.Logger).Log((object)("try to execute event: '" + eventID + "'"));
			try
			{
				string cmd = commandManager.GetCommandData(eventID, true)?.Trim();
				string commandLine = ProcessCommandCustomArgs(cmd);
				ProcessCommands(commandLine, username, cost, eventID, lang, extraInfo);
			}
			catch (Exception value)
			{
				((HelperLog)LoggerFactory.Logger).Log((object)$"execute event unexpected error: {value}");
			}
		}

		private void ProcessCommands(string commandLine, string username, string cost, string eventID, string lang, string extraInfo)
		{
			//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_000c: 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_001b: 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_002c: Expected O, but got Unknown
			EventsData val = new EventsData
			{
				Username = username,
				Cost = cost,
				EventID = eventID,
				Lang = lang,
				ExtraInfo = extraInfo
			};
			try
			{
				((HelperLog)LoggerFactory.Logger).Log((object)("command: " + commandLine));
				if (console.RunCommand(commandLine, val, (Action<string>)null))
				{
					((HelperLog)LoggerFactory.Logger).Log((object)("event '" + val.EventID + "' executing is completed"));
					TypedNotifyOnGUI obj = notifyManager;
					if (obj != null)
					{
						((TypedNotifyBase)obj).AddNotifyToQueue(val, TranslationFactory.Instance);
					}
				}
				else
				{
					LoggerFactory.Logger.LogDebugError((object)("event '" + val.EventID + "' executing is failed"));
				}
			}
			catch (Exception value)
			{
				((HelperLog)LoggerFactory.Logger).Log((object)$"ProcessCommands '{val.EventID}' unexpected error: {value}");
			}
		}

		public void Update()
		{
			try
			{
				float deltaTime = Time.deltaTime;
				DebugHotkeysOnUpdate(deltaTime);
				if (GameStateServiceFactory.Instance.IsReadyForCheckEvent(deltaTime, OnCheckEventsDisabled))
				{
					if (isNeedTriggerOnFirstConnect)
					{
						isNeedTriggerOnFirstConnect = false;
					}
					if (isNeedShowConnectMessage)
					{
						isNeedShowConnectMessage = false;
					}
					else if (isNeedShowDisconnectMessage)
					{
						isNeedShowDisconnectMessage = false;
					}
					eventsReader.ReadAndProcessAllWithDelayOnFrame(deltaTime);
				}
				ScheduleFactory.Instance.OnUpdate(deltaTime);
				TypedNotifyOnGUI obj = notifyManager;
				if (obj != null)
				{
					((TypedNotifyBase)obj).Update();
				}
			}
			catch (Exception value)
			{
				if (updateErrorsLimit > 0)
				{
					updateErrorsLimit--;
					((HelperLog)LoggerFactory.Logger).Log((object)$"OnUpdate error: {value}");
				}
			}
		}

		public void OnGUI()
		{
			TypedNotifyOnGUI obj = notifyManager;
			if (obj != null)
			{
				((TypedNotifyBase)obj).OnGUI();
			}
		}

		public void DebugHotkeysOnUpdate(float dt)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			try
			{
				if (!UnityHelper.IsDebugMode())
				{
					return;
				}
				if (Input.GetKeyDown((KeyCode)281))
				{
					((HelperLog)LoggerFactory.Logger).Log((object)"DebugHotkeysOnUpdate reinit mod");
					ScheduleFactory.Instance.FinishAllImmediatly();
					if (notifyManager != null)
					{
						((TypedNotifyBase)notifyManager).ClearNotifyQueue();
						((TypedNotifyBase)notifyManager).StopCurrentNotify();
					}
					console = new UtilityConsole(LoggerFactory.Logger, (List<string>)null);
					InitOthersManagers();
					InitCommands(isNeedValidate: true);
				}
				if (GameStateServiceFactory.Instance.IsReadyForCheckEvent(dt, OnCheckEventsDisabled) && Input.GetKeyDown((KeyCode)104))
				{
					((HelperLog)LoggerFactory.Logger).Log((object)"read events by key");
					eventsReaderByKey.ReadAndProcessAllOnKey(keyEventsPath, false);
				}
			}
			catch
			{
			}
		}

		private void OnCheckEventsDisabled()
		{
			((HelperLog)LoggerFactory.Logger).Log((object)"OnCheckEventsDisabled");
			ScheduleFactory.Instance.FinishAllImmediatly();
			if (notifyManager != null)
			{
				((TypedNotifyBase)notifyManager).ClearNotifyQueue();
				((TypedNotifyBase)notifyManager).StopCurrentNotify();
			}
		}
	}
}
namespace bft_mod.Service
{
	public class GameStateService : Object
	{
		private const int CHECK_EVENT_ERRORS_LIMIT = 50;

		private int checkEventErrorsLimit = 50;

		private const int CHECK_READY_FOR_EVENT_PERIOD = 2;

		private float checkReadyForEventTimer;

		private bool lastIsReady;

		public bool IsReadyForCheckEvent(float dt, Action onEventIsNotReady)
		{
			if (checkReadyForEventTimer >= 0f)
			{
				checkReadyForEventTimer -= dt;
			}
			else
			{
				checkReadyForEventTimer = 2f;
			}
			try
			{
				bool flag = (Object)(object)LocalPlayer._instance != (Object)null && ((Behaviour)LocalPlayer._instance).isActiveAndEnabled && !SonsSceneManager.UsedLoadingScreen;
				if (lastIsReady && !flag)
				{
					try
					{
						onEventIsNotReady?.Invoke();
					}
					catch (Exception value)
					{
						((HelperLog)LoggerFactory.Logger).Log((object)$"onEventIsNotReady error: {value}");
					}
				}
				lastIsReady = flag;
				return flag;
			}
			catch (Exception value2)
			{
				if (checkEventErrorsLimit > 0)
				{
					checkEventErrorsLimit--;
					((HelperLog)LoggerFactory.Logger).Log((object)$"checkEventErrorsLimit error: {value2}");
				}
				return false;
			}
		}
	}
}
namespace bft_mod.HelperBFT
{
	public class CommandArgsReaderFactory
	{
		private static readonly Lazy<CommandArgsReader> instance = new Lazy<CommandArgsReader>((Func<CommandArgsReader>)(() => new CommandArgsReader((HelperLog)(object)LoggerFactory.Logger)));

		public static CommandArgsReader Reader => instance.Value;
	}
	public class CommandArgsValidatorFactory
	{
		private static readonly Lazy<CommandArgsValidator> instance = new Lazy<CommandArgsValidator>((Func<CommandArgsValidator>)(() => new CommandArgsValidator((HelperLog)(object)LoggerFactory.Logger)));

		public static CommandArgsValidator Validator => instance.Value;
	}
	public static class Game
	{
		private static float fallDamage;

		public static void RunConsoleCommand(string command)
		{
			try
			{
				if ((Object)(object)DebugConsole.Instance != (Object)null)
				{
					DebugConsole.Instance.SendCommand(command);
					((HelperLog)LoggerFactory.Logger).Log((object)("RunConsoleCommand " + command + " ends"));
				}
				else
				{
					((HelperLog)LoggerFactory.Logger).Log((object)"Warning: GameConsole is null, the event activation will be skipped");
				}
			}
			catch (Exception value)
			{
				((HelperLog)LoggerFactory.Logger).Log((object)$"RunConsoleCommand error: {value}");
			}
		}

		public static void EnableFallDamage(bool isEnable)
		{
			try
			{
				if (isEnable && fallDamage == 0f)
				{
					fallDamage = LocalPlayer._instance._fpc._baseFallDamage;
				}
				LocalPlayer._instance._fpc._baseFallDamage = (isEnable ? 0f : fallDamage);
			}
			catch (Exception value)
			{
				((HelperLog)LoggerFactory.Logger).Log((object)$"setting up fall damage error: {value}");
			}
		}

		public static string GetOnOff(bool isActivate)
		{
			if (!isActivate)
			{
				return "off";
			}
			return "on";
		}

		public static string GetCommandWithOnOff(string cmd, bool isActivate)
		{
			return cmd + " " + GetOnOff(isActivate);
		}

		public static string GetOneZero(bool isActivate)
		{
			if (!isActivate)
			{
				return "0";
			}
			return "1";
		}

		public static string GetCommandWithOneZero(string cmd, bool isActivate)
		{
			return cmd + " " + GetOneZero(isActivate);
		}
	}
	public static class GameStateServiceFactory
	{
		private static readonly Lazy<GameStateService> instance = new Lazy<GameStateService>();

		public static GameStateService Instance => instance.Value;
	}
	public static class LoggerFactory
	{
		private static readonly Lazy<HelperDebugLog> instance = new Lazy<HelperDebugLog>((Func<HelperDebugLog>)(() => new HelperDebugLog("interactive_mod_log.txt", true)));

		public static HelperDebugLog Logger => instance.Value;
	}
	public static class ScheduleFactory
	{
		private static Lazy<ScheduleManager> instance = GenerateLazyObject();

		public static ScheduleManager Instance => instance.Value;

		private static Lazy<ScheduleManager> GenerateLazyObject()
		{
			return new Lazy<ScheduleManager>((Func<ScheduleManager>)(() => new ScheduleManager((HelperLog)(object)LoggerFactory.Logger)));
		}

		public static void Reinit()
		{
			if (instance.IsValueCreated)
			{
				Instance.FinishAllImmediatly();
				instance = GenerateLazyObject();
			}
		}
	}
	public static class TranslationFactory
	{
		private static Lazy<HelperLanguagesFormatted> instance = GenerateLazyObject();

		public static HelperLanguagesFormatted Instance => instance.Value;

		private static Lazy<HelperLanguagesFormatted> GenerateLazyObject()
		{
			return new Lazy<HelperLanguagesFormatted>((Func<HelperLanguagesFormatted>)(() => new HelperLanguagesFormatted((HelperLog)(object)LoggerFactory.Logger)));
		}

		public static void Reinit(bool isForceCreate = true)
		{
			if (instance.IsValueCreated)
			{
				instance = GenerateLazyObject();
			}
			if (isForceCreate)
			{
				ForceCreate();
			}
		}

		public static void ForceCreate()
		{
			_ = Instance;
		}
	}
	public static class UnityHelper
	{
		private static Dictionary<string, float> storedNames;

		private static bool isDebugInited;

		private static bool isDebug;

		public static float GetCustomSize(string objectName)
		{
			if (objectName == null)
			{
				((HelperLog)LoggerFactory.Logger).Log((object)"GetCustomSize warning: invalid value");
				return 1f;
			}
			if (storedNames == null || IsDebugMode())
			{
				try
				{
					string text = Path.Combine(UtilitySettings.BaseFolder, "custom_sizes.data");
					storedNames = UtilityJson.Generate((HelperLog)(object)LoggerFactory.Logger).FromFile<Dictionary<string, float>>(text);
				}
				catch (Exception value)
				{
					((HelperLog)LoggerFactory.Logger).Log((object)$"GetCustomSize error: {value}");
				}
				if (storedNames == null)
				{
					storedNames = new Dictionary<string, float>();
				}
			}
			if (storedNames.ContainsKey(objectName))
			{
				return storedNames[objectName];
			}
			((HelperLog)LoggerFactory.Logger).Log((object)("GetCustomSize warning: missed value " + objectName));
			return 1f;
		}

		public static bool IsDebugMode()
		{
			if (isDebugInited)
			{
				return isDebug;
			}
			isDebugInited = true;
			isDebug = File.Exists(Path.Combine(UtilitySettings.BaseFolder, ".debug"));
			return isDebug;
		}
	}
}
namespace bft_mod.Command
{
	public class AnimSpeedAI : BaseTimerCommandDefaultParam
	{
		public override string Id => "aianimspeed";

		public AnimSpeedAI()
		{
			commands = new string[1] { "aianimspeed" };
		}
	}
	public class BaseTimerCommand : ConsoleCommand
	{
		public override string Id => "base_timer_command";

		public override bool Execute(IEnumerable<string> args)
		{
			IEnumerator<string> enumerator = args?.GetEnumerator();
			int timer = CommandArgsReaderFactory.Reader.ReadInt(enumerator, 30);
			ActivateTimer(timer);
			return true;
		}

		public override bool IsValidCommandArgs(IEnumerable<string> args)
		{
			return CommandArgsValidatorFactory.Validator.IsValidInt(args?.GetEnumerator(), 0, 500, false);
		}

		public virtual void SetEffectState(bool isActivate)
		{
		}

		public virtual void ActivateTimer(int timer)
		{
			//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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			SetEffectState(isActivate: true);
			ScheduleFactory.Instance.AppendTimerTask(new TimerTaskData
			{
				id = ((ConsoleCommand)this).Id,
				duration = timer,
				finishAction = delegate
				{
					SetEffectState(isActivate: false);
				}
			}, false);
		}
	}
	public class BaseTimerCommandDefaultParam : BaseTimerCommand
	{
		protected float newValue;

		protected float oldValue;

		protected string[] commands;

		public override string Id => "base_timer_command_with_default";

		public override bool Execute(IEnumerable<string> args)
		{
			IEnumerator<string> enumerator = args?.GetEnumerator();
			CommandArgsReader reader = CommandArgsReaderFactory.Reader;
			int timer = reader.ReadInt(enumerator, 30);
			newValue = reader.ReadFloat(enumerator, 1f);
			oldValue = reader.ReadFloat(enumerator, 1f);
			ActivateTimer(timer);
			return true;
		}

		public override bool IsValidCommandArgs(IEnumerable<string> args)
		{
			IEnumerator<string> enumerator = args?.GetEnumerator();
			if (CommandArgsValidatorFactory.Validator.IsValidInt(enumerator, 0, 500, false) && CommandArgsValidatorFactory.Validator.IsValidFloat(enumerator, 0f, 500f, false))
			{
				return CommandArgsValidatorFactory.Validator.IsValidFloat(enumerator, 0f, 500f, false);
			}
			return false;
		}

		public override void SetEffectState(bool isActivate)
		{
			if (commands != null)
			{
				float value = (isActivate ? newValue : oldValue);
				string[] array = commands;
				foreach (string value2 in array)
				{
					Game.RunConsoleCommand($"{value2} {value}");
				}
			}
		}
	}
	public class GameConsoleCommand : ConsoleCommand
	{
		public override string Id => "console_command";

		public override bool Execute(IEnumerable<string> args)
		{
			Game.RunConsoleCommand(string.Join(" ", args));
			return true;
		}

		public override bool IsValidCommandArgs(IEnumerable<string> args)
		{
			return true;
		}
	}
	public class Gravity : BaseTimerCommandDefaultParam
	{
		public override string Id => "gravity";

		public Gravity()
		{
			commands = new string[1] { "gravity" };
		}
	}
	public class Immortality : BaseTimerCommand
	{
		public override string Id => "god_mode";

		public override void SetEffectState(bool isActivate)
		{
			Game.RunConsoleCommand(Game.GetCommandWithOnOff("godmode", isActivate));
		}
	}
	public class InfiniteAmmo : BaseTimerCommand
	{
		public override string Id => "infinite_ammo";

		public override void SetEffectState(bool isActivate)
		{
			Game.RunConsoleCommand(Game.GetCommandWithOnOff("ammohack", isActivate));
		}
	}
	public class InfiniteEnergy : BaseTimerCommand
	{
		public override string Id => "infinite_energy";

		public override void SetEffectState(bool isActivate)
		{
			Game.RunConsoleCommand(Game.GetCommandWithOnOff("energyhack", isActivate));
		}
	}
	public class InvertLook : BaseTimerCommand
	{
		public override string Id => "invert_look";

		public override void SetEffectState(bool isActivate)
		{
			Game.RunConsoleCommand(Game.GetCommandWithOneZero("invertlook", isActivate));
		}
	}
	public class MouseSensitivity : BaseTimerCommandDefaultParam
	{
		public override string Id => "mouse_sensitivity";

		public MouseSensitivity()
		{
			commands = new string[2] { "mousexsensitivity", "mouseysensitivity" };
		}
	}
	public class SpeedyRun : BaseTimerCommand
	{
		public override string Id => "speedy_run";

		public override void SetEffectState(bool isActivate)
		{
			Game.RunConsoleCommand(Game.GetCommandWithOnOff("speedyrun", isActivate));
			Game.EnableFallDamage(isActivate);
		}
	}
	public class StopCommandTimer : ConsoleCommand
	{
		public override string Id => "stop_command";

		public override bool Execute(IEnumerable<string> args)
		{
			foreach (string arg in args)
			{
				if (arg != null)
				{
					ScheduleFactory.Instance.RemoveTimerTask(arg);
				}
			}
			return true;
		}

		public override bool IsValidCommandArgs(IEnumerable<string> args)
		{
			return true;
		}
	}
	public class SuperJump : BaseTimerCommand
	{
		public override string Id => "super_jump";

		public override void SetEffectState(bool isActivate)
		{
			Game.RunConsoleCommand(Game.GetCommandWithOnOff("superjump", isActivate));
			Game.EnableFallDamage(isActivate);
		}
	}
	public class TimeScale : BaseTimerCommandDefaultParam
	{
		public override string Id => "timescale";

		public TimeScale()
		{
			commands = new string[1] { "timescale" };
		}
	}
}

plugins/ChaosTricks/ModHelper.dll

Decompiled a month 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.Versioning;
using System.Text;
using EventsIO;
using ModHelper;
using ModHelper.Data;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BFT")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ModHelper")]
[assembly: AssemblyTitle("ModHelper")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ModUnityTools
{
	public class ScheduleManager
	{
		protected HelperLog 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(HelperLog logger = null)
		{
			this.logger = logger;
		}

		public void NewTimerTask(TimerTaskData task, bool triggerFinishIfExists = false)
		{
			if (task == null)
			{
				logger?.Log($"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?.Log($"ScheduleManager new timer task {task}");
		}

		public void NewPeriodicTask(PeriodicTaskData task, bool triggerFinishIfExists = false)
		{
			if (task == null)
			{
				logger?.Log($"ScheduleManager new periodic task null error. Details info: {task}");
				return;
			}
			task.periodCalculated = task.period;
			if (task.id == null)
			{
				NewPeriodicTaskWithOutId(task);
				return;
			}
			if (triggerFinishIfExists && periodicTasks.ContainsKey(task.id))
			{
				SafeRunAction(periodicTasks[task.id].finishAction);
			}
			periodicTasks[task.id] = task;
			logger?.Log($"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?.Log($"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?.Log($"ScheduleManager new timer no id task null error. Details info: {task}");
			}
			else
			{
				timerTasksNoId.Add(task);
				logger?.Log($"ScheduleManager new timer no id task {task}");
			}
		}

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

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

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

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

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

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

		public void RemoveAllTasks()
		{
			timerTasks.Clear();
			periodicTasks.Clear();
			timerTasksNoId.Clear();
			periodicTasksNoId.Clear();
			logger?.Log("ScheduleManager RemoveAllTasks");
		}

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

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

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

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

		public void FinishImmediatlyPeriodicTask(string id)
		{
			if (periodicTasks.ContainsKey(id))
			{
				SafeRunAction(periodicTasks[id].finishAction);
				periodicTasks.Remove(id);
				logger?.Log("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 value)
			{
				logger?.Log($"SafeRunAction error: {value}");
			}
		}
	}
}
namespace ModHelper
{
	public class CommandArgsReader
	{
		private readonly HelperLog logger;

		public CommandArgsReader(HelperLog 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 value)
			{
				logger?.Log($"CommandArgsReader: {value}");
				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 value)
			{
				logger?.Log($"CommandArgsReader: {value}");
				return defaultValue;
			}
		}

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

		public bool ReadBool(IEnumerator<string> args, bool defaultValue = false)
		{
			if (args == null || !args.MoveNext())
			{
				return defaultValue;
			}
			try
			{
				return bool.Parse(args.Current.ToLower());
			}
			catch (Exception value)
			{
				logger?.Log($"CommandArgsReader: {value}");
				return defaultValue;
			}
		}
	}
	public class CommandArgsValidator
	{
		private readonly HelperLog logger;

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

		public bool IsZeroArgs(IEnumerable<string> args)
		{
			int num = args?.Count() ?? 0;
			if (num != 0)
			{
				logger?.Log($"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?.Log("CommandArgsValidator wrong args count (more than needed)");
			return false;
		}

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

		public bool IsValidInt(IEnumerator<string> args, int minValue, int maxValue, bool isSkippable = false)
		{
			if (IsInvalidArgsCount(args))
			{
				if (isSkippable)
				{
					return true;
				}
				logger?.Log("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?.Log(obj);
					return false;
				}
			}
			catch (Exception)
			{
				logger?.Log("CommandArgsValidator can't parse integer value from '" + args.Current + "'");
				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?.Log("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?.Log(obj);
					return false;
				}
			}
			catch (Exception)
			{
				logger?.Log("CommandArgsValidator can't parse float value from '" + args.Current + "'");
			}
			return true;
		}

		public bool IsValidString(IEnumerator<string> args, Func<string, bool> validator, bool isSkippable = false)
		{
			if (IsInvalidArgsCount(args))
			{
				if (isSkippable)
				{
					return true;
				}
				logger?.Log("CommandArgsValidator wrong args count");
				return false;
			}
			if (validator == null || validator(args.Current))
			{
				return true;
			}
			logger?.Log("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?.Log("CommandArgsValidator wrong args count");
				return false;
			}
			try
			{
				bool.Parse(args.Current.ToLower());
			}
			catch (Exception)
			{
				logger?.Log("CommandArgsValidator can't parse bool value from '" + args.Current + "'");
				return false;
			}
			return true;
		}
	}
	public class PeriodicTaskData
	{
		public string id;

		public float period;

		internal float periodCalculated;

		public int triggerTimes;

		public bool isInfiniteRepeates = true;

		public Action periodicAction;

		public Action finishAction;

		public override string ToString()
		{
			return $"id={id}, period={period}s, calc_period={periodCalculated}s, triggerTimes={triggerTimes}, isInfiniteRepeates={isInfiniteRepeates}";
		}
	}
	public enum Languages
	{
		ru,
		en
	}
	public class Text
	{
		public string ru;

		public string en;

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

		public Text()
		{
		}

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

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

		private Languages GetLangFromAppLang(string lang)
		{
			lang = lang?.Trim()?.ToLower();
			switch (lang)
			{
			case "ru":
			case "russian":
			case "rus":
			case "русский":
			case "ру":
			case "рус":
				return Languages.ru;
			default:
				return Languages.en;
			}
		}
	}
	public class TimerTaskData
	{
		public string id;

		public float duration;

		public Action finishAction;

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

		protected readonly int bufferRecordsCount;

		public BufferedLogger(int bufferRecordsCount = 10, string path = "interactive_mod_log.txt", bool isDebug = false)
			: base(path, isDebug)
		{
			this.bufferRecordsCount = bufferRecordsCount;
			queue = new Queue<string>();
		}

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

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

		public override void LogDebugError(object obj)
		{
			Log($"error {obj}");
		}

		public override void LogDebugInfo(object obj)
		{
			Log($"info {obj}");
		}

		public override void LogDebugWarning(object obj)
		{
			Log($"warning {obj}");
		}

		public override void Log(object obj)
		{
			if (obj != null)
			{
				queue.Enqueue($"{DateTime.Now:h:mm:ss} {obj}");
				if (queue.Count >= bufferRecordsCount)
				{
					Flush(isNeedClearQueue: true);
				}
			}
		}

		~BufferedLogger()
		{
			Queue<string> obj = queue;
			if (obj != null && obj.Count > 0)
			{
				Flush();
			}
		}
	}
	public class HelperCommandManager
	{
		private readonly Dictionary<string, string> commandsDict;

		private readonly HelperLog logger;

		private readonly string errorString = string.Empty;

		public HelperCommandManager(HelperLog logger, string path = "commands.data")
		{
			this.logger = logger;
			try
			{
				path = Path.Combine(UtilitySettings.BaseFolder, path);
				HelperDictManager helperDictManager = new HelperDictManager();
				using StreamReader streamReader = new StreamReader(path);
				string data = streamReader.ReadToEnd();
				Dictionary<string, string> dictionary = helperDictManager.ParseDict(data);
				commandsDict = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase);
				logger?.Log($"HelperCommandManager: found commands {commandsDict.Count}");
				foreach (KeyValuePair<string, string> item in commandsDict)
				{
					logger?.Log("command: key=" + item.Key + ", value=" + item.Value);
				}
			}
			catch (Exception value)
			{
				logger?.Log($"HelperCommandManager load error: {value}");
				commandsDict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			}
		}

		public string GetCommandData(string eventKey, bool isLogError = false)
		{
			try
			{
				eventKey = eventKey.Trim();
				return commandsDict[eventKey] ?? throw new NullReferenceException();
			}
			catch (Exception value)
			{
				if (isLogError)
				{
					logger?.Log($"HelperCommandManager key {eventKey}, error: {value}");
				}
				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 HelperCommandManagerFormatted
	{
		private Dictionary<string, string> commandsDict;

		private readonly HelperLog logger;

		private readonly string errorString = string.Empty;

		public int logCommandMaxLength = 50;

		public bool isUseLogCommandLimit = true;

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

		public virtual void InitFromFile(string path)
		{
			try
			{
				path = Path.Combine(UtilitySettings.BaseFolder, path);
				Dictionary<string, string> dictionary = UtilityJson.Generate(logger).FromFile<Dictionary<string, string>>(path);
				commandsDict = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase);
				CheckLoadedDict();
			}
			catch (Exception value)
			{
				logger?.Log($"HelperCommandManagerFormatted InitFromFile load error: {value}");
				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 value)
			{
				logger?.Log($"HelperCommandManagerFormatted InitFromString load error: {value}");
				commandsDict = null;
			}
		}

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

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

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

		public virtual string[] GetCommands()
		{
			if (commandsDict == null)
			{
				logger?.Log("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 HelperDebugLog : HelperLog
	{
		protected bool isDebug;

		public HelperDebugLog(string path = "interactive_mod_log.txt", bool isDebug = false)
			: base(path)
		{
			this.isDebug = isDebug;
		}

		public virtual void LogDebugInfo(object obj)
		{
			if (isDebug)
			{
				Log($"info: {obj}");
			}
		}

		public virtual void LogDebugWarning(object obj)
		{
			if (isDebug)
			{
				Log($"warning: {obj}");
			}
		}

		public virtual void LogDebugError(object obj)
		{
			if (isDebug)
			{
				Log($"error: {obj}");
			}
		}
	}
	public class HelperDictManager
	{
		private readonly HelperLog logger;

		private readonly EventsDataEncoder encoder;

		private readonly EventsDataEncoder encoderParams;

		public HelperDictManager(HelperLog 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 = (encoder = 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?.Log("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?.Log("HelperDictManager error, invalid item: " + text);
						continue;
					}
					string text2 = array3[0];
					string text3 = array3[1];
					if (text3 == null || text2 == null)
					{
						logger?.Log("HelperDictManager error, invalid key/val: " + text2 + "/" + text3);
						continue;
					}
					string key = encoder.Decode(text2).Trim();
					string value = encoder.Decode(text3).Trim();
					dictionary.Add(key, value);
				}
			}
			catch (Exception value2)
			{
				logger?.Log($"HelperDictManager error: {value2}");
			}
			return dictionary;
		}
	}
	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, HelperLog logger = null)
		{
			try
			{
				return groupItemValidator?.Invoke(itemName) ?? true;
			}
			catch (Exception value)
			{
				logger?.Log($"RandomGroup.SafeApplyValidator unexpected error: {value}");
			}
			return false;
		}

		public static void InitGroupsFromFiles(Dictionary<string, List<string>> groups, string groupsPrefix, Func<string, bool> groupItemValidator = null, HelperLog logger = null)
		{
			try
			{
				if (string.IsNullOrEmpty(groupsPrefix))
				{
					logger?.Log("RandomGroup error: wrong groupsPrefix " + groupsPrefix);
					return;
				}
				string[] files = Directory.GetFiles(UtilitySettings.BaseFolder);
				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?.Log("RandomGroup validate list " + group.Key + ":");
					List<string> list = new List<string>();
					foreach (string item in group.Value)
					{
						if (!SafeApplyValidator(groupItemValidator, item, logger))
						{
							logger?.Log("invalid name " + item);
							list.Add(item);
						}
					}
					if (list.Count > 0)
					{
						foreach (string item2 in list)
						{
							group.Value.Remove(item2);
						}
						logger?.Log("error: list " + group.Key + " is invalid");
					}
					else
					{
						logger?.Log("list " + group.Key + " is valid");
					}
				}
			}
			catch (Exception value)
			{
				logger?.Log($"RandomGroup.InitGroupsFromFiles unexpected error: {value}");
			}
		}

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

		public static List<string> GetItemsFromFile(string path, HelperLog logger = null)
		{
			try
			{
				List<string> list = new HelperJson(logger).FromFile<List<string>>(path);
				if (list == null)
				{
					list = new List<string>();
				}
				logger?.Log($"Items from file {path}: found {list.Count}");
				foreach (string item in list)
				{
					logger?.Log("value " + item);
				}
				return list;
			}
			catch (Exception value)
			{
				logger?.Log($"HelperGroups.GetItemsFromFile unexpected error: {value}");
			}
			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, HelperLog logger, string groupsName = "default_name")
		{
			if (logger == null)
			{
				return;
			}
			if (dict == null || dict.Count == 0)
			{
				logger?.Log("No groups found for " + groupsName);
				return;
			}
			logger?.Log("---------------Groups " + groupsName + " list---------------");
			foreach (KeyValuePair<string, List<string>> item in dict)
			{
				logger?.Log(item.Key ?? "");
			}
			logger?.Log("---------------Groups " + groupsName + " list end---------------");
		}
	}
	public class HelperJson
	{
		private class ContainerObjAndInt
		{
			public object valueObj;

			public int valueInt;
		}

		private class ContainerStringAndInt
		{
			public string valueString;

			public int valueInt;
		}

		private HelperLog 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 isDebugLog;

		private void DebugLog(string s)
		{
			if (isDebugLog)
			{
				logger?.Log(s);
			}
		}

		public HelperJson(HelperLog logger = null, bool isDebugLog = false)
		{
			this.logger = logger;
			this.isDebugLog = isDebugLog;
		}

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

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

		private char GetSpecialChar(char c)
		{
			_ = 34;
			return c;
		}

		private void SetFieldClass<T, R>(T instance, string fieldName, R fieldValue) where T : class where R : class
		{
			Type type = instance.GetType();
			DebugLog("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];
				DebugLog($"debug {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;
						DebugLog("debug " + logMsgBase + " ParseNextStringValue is startString case");
						continue;
					}
					if (c == ']' || c == '}')
					{
						break;
					}
					if (c == ',' || c == ':')
					{
						i = SkipIgnoredChars(s, i, isSkipHasNextField: true, isSkipSep);
						break;
					}
				}
				else if (c == '\\')
				{
					DebugLog("debug " + 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 == '"')
				{
					DebugLog("debug " + logMsgBase + " ParseNextStringValue is startString end case");
					i = SkipIgnoredChars(s, ++i, isSkipHasNextField: true, isSkipSep);
					break;
				}
				DebugLog($"debug {logMsgBase} ParseNextStringValue append {c}");
				stringBuilder.Append(c);
			}
			string text = stringBuilder.ToString();
			DebugLog($"debug {logMsgBase} ParseNextStringValue {text}, end at index {i}");
			return new ContainerStringAndInt
			{
				valueString = text,
				valueInt = i
			};
		}

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

		private ContainerObjAndInt GetNextValue(Type valueType, string s, int index, bool isSkipSep)
		{
			DebugLog("debug " + logMsgBase + " GetNextValue");
			int num = SkipIgnoredChars(s, index, isSkipHasNextField: true, isSkipSep);
			if (num >= s.Length)
			{
				logger?.Log(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 value)
				{
					logger?.Log($"{logMsgBaseError} incorrect format, use default. Msg: {value}");
					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]))
				{
					DebugLog($"skip char '{s[i]}'");
					continue;
				}
				if (isSkipHasNextField && s[i] == ',')
				{
					DebugLog($"skip char '{s[i]}'");
					continue;
				}
				if (isSkipSep && s[i] == ':')
				{
					DebugLog($"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?.Log(logMsgBaseError + " can't create IList for item type " + itemType.Name);
				return new ContainerObjAndInt
				{
					valueObj = null,
					valueInt = s.Length
				};
			}
			do
			{
				ContainerObjAndInt nextValue = GetNextValue(itemType, s, index, isSkipSep: true);
				object valueObj = nextValue.valueObj;
				index = nextValue.valueInt;
				list.Add(valueObj);
				index = SkipIgnoredChars(s, index, isSkipHasNextField: true, isSkipSep: true);
			}
			while (index < s.Length && s[index] != ']' && s[index] != '}');
			return new ContainerObjAndInt
			{
				valueObj = list,
				valueInt = index + 1
			};
		}

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

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

		private ContainerObjAndInt ParseIDictionary(Type dictType, string s, int index)
		{
			Type[] genericArguments = dictType.GetGenericArguments();
			if (genericArguments.Length != 2)
			{
				logger?.Log(logMsgBaseError + " can't create IDictionary, invalid args");
			}
			if (dictType.IsGenericType)
			{
				if (!dictType.IsGenericTypeDefinition)
				{
					dictType = dictType.GetGenericTypeDefinition();
				}
				dictType = dictType.MakeGenericType(genericArguments);
			}
			if (!(Activator.CreateInstance(dictType) is IDictionary dictionary))
			{
				string name = dictType.GetType().Name;
				logger?.Log($"{logMsgBaseError} can't create IDictionary {name} for item type {genericArguments[0].Name}, {genericArguments[1].Name}");
				return new ContainerObjAndInt
				{
					valueObj = null,
					valueInt = s.Length
				};
			}
			Type valueType = genericArguments[0];
			Type valueType2 = genericArguments[1];
			do
			{
				ContainerObjAndInt nextValue = GetNextValue(valueType, s, index, isSkipSep: false);
				index = nextValue.valueInt;
				ContainerObjAndInt nextValue2 = GetNextValue(valueType2, s, index, isSkipSep: true);
				index = nextValue2.valueInt;
				dictionary.Add(nextValue.valueObj, nextValue2.valueObj);
				DebugLog($"debug {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))
			{
				DebugLog("debug " + logMsgBase + " is " + targetType.Name);
				return true;
			}
			Type[] types = sourceType.Assembly.GetTypes();
			foreach (Type type in types)
			{
				if (!type.IsClass)
				{
					continue;
				}
				Type[] interfaces = type.GetInterfaces();
				foreach (Type type2 in interfaces)
				{
					if (type2.IsGenericType && type2.GetGenericTypeDefinition() == targetType && sourceType.GetGenericArguments().Length == argsCount)
					{
						DebugLog($"debug {logMsgBase} is {targetType.Name} assembly interface");
						return true;
					}
				}
			}
			return false;
		}

		private ContainerObjAndInt GetFromString(Type resultType, string s, int index)
		{
			try
			{
				DebugLog("debug " + logMsgBase + " GetFromString");
				if (resultType.IsArray)
				{
					DebugLog("debug " + 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()))
					{
						DebugLog($"{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);
					DebugLog($"{logMsgBase} field {valueString}, class type {resultType.Name}");
					if (isDebugLog)
					{
						FieldInfo[] fields = resultType.GetFields();
						DebugLog(logMsgBase + " fields in class: ");
						FieldInfo[] array = fields;
						foreach (FieldInfo fieldInfo in array)
						{
							DebugLog(fieldInfo.Name);
						}
					}
					if (field == null)
					{
						logger?.Log($"{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 value)
			{
				logger?.Log($"{logMsgBaseError} {value}");
			}
			return new ContainerObjAndInt
			{
				valueObj = null,
				valueInt = s.Length
			};
		}
	}
	public class HelperLanguages
	{
		private readonly Dictionary<string, Text> transDict;

		private readonly HelperLog logger;

		private readonly string errorString = "trans_error";

		public HelperLanguages(HelperLog logger, string path = "langs.data")
		{
			this.logger = logger;
			try
			{
				path = Path.Combine(UtilitySettings.BaseFolder, path);
				HelperDictManager helperDictManager = new HelperDictManager(logger);
				using (StreamReader streamReader = new StreamReader(path))
				{
					string data = streamReader.ReadToEnd();
					Dictionary<string, string> source = helperDictManager.ParseDict(data);
					transDict = GetTransDict(source);
				}
				logger?.Log($"HelperLanguages: found translates {transDict.Count}");
			}
			catch (Exception value)
			{
				logger?.Log($"HelperLanguages load error: {value}");
				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?.Log($"HelperLanguages parse item error: {item}");
				}
				else
				{
					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 value)
			{
				logger?.Log($"HelperLanguages key {key} lang {lang}, error: {value}");
				return errorString;
			}
		}

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

		public void InitFromString(string data)
		{
			throw new NotImplementedException();
		}
	}
	public class HelperLanguagesFormatted
	{
		protected Dictionary<string, Text> transDict;

		protected readonly HelperLog logger;

		protected readonly string errorString = "trans_error";

		public bool isLogOnlyEnItems;

		public bool isSuppressLogItems = true;

		public HelperLanguagesFormatted(HelperLog 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 value)
			{
				logger?.Log($"HelperLanguagesFormatted InitFromFile load error: {value}");
				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 value)
			{
				logger?.Log($"HelperLanguagesFormatted InitFromString load error: {value}");
				transDict = null;
			}
		}

		protected virtual void CheckLoadedDict()
		{
			if (transDict == null)
			{
				logger?.Log("HelperLanguagesFormatted: transDict null");
				return;
			}
			logger?.Log($"HelperLanguagesFormatted: found translates {transDict.Count}");
			if (isSuppressLogItems || logger == null)
			{
				return;
			}
			foreach (KeyValuePair<string, Text> item in transDict)
			{
				if (isLogOnlyEnItems)
				{
					logger.Log("key=" + item.Key + ", en=" + item.Value.en);
					continue;
				}
				logger.Log($"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?.Log("HelperLanguagesFormatted transDict is null");
				return errorString;
			}
			try
			{
				key = key.Trim();
				lang = lang.Trim();
				return transDict[key].GetTrans(lang);
			}
			catch (Exception value)
			{
				logger?.Log($"HelperLanguagesFormatted key {key} lang {lang}, error: {value}");
				return errorString;
			}
		}
	}
	public class HelperLog
	{
		protected readonly string path;

		protected const string basePath = "interactive_mod_log.txt";

		public HelperLog(string path = "interactive_mod_log.txt")
		{
			if (string.IsNullOrEmpty(path))
			{
				path = "interactive_mod_log.txt";
			}
			this.path = Path.Combine(UtilitySettings.BaseFolder, path);
		}

		public virtual void Log(object obj)
		{
			using StreamWriter streamWriter = new StreamWriter(path, append: true, Encoding.UTF8);
			streamWriter.WriteLine(DateTime.Now.ToString("h:mm:ss ") + obj);
		}

		public virtual void LogClear()
		{
			using (new StreamWriter(path))
			{
			}
		}
	}
	public class HelperParse
	{
		private readonly HelperLog logger;

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

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

		public bool TryParseEnum<TEnum>(string arg, out TEnum result, TEnum defaultValue = default(TEnum))
		{
			Type typeFromHandle = typeof(TEnum);
			try
			{
				Type enumUnderlyingType = GetEnumUnderlyingType(typeFromHandle);
				if (enumUnderlyingType == typeof(int))
				{
					if (int.TryParse(arg, out var result2) && Enum.IsDefined(typeFromHandle, result2))
					{
						result = (TEnum)Enum.ToObject(typeFromHandle, result2);
						return true;
					}
					logger?.Log("TryParseEnum can't parse int from " + arg + " for enum " + typeFromHandle.Name);
				}
				else if (enumUnderlyingType == typeof(sbyte))
				{
					if (sbyte.TryParse(arg, out var result3) && Enum.IsDefined(typeFromHandle, result3))
					{
						result = (TEnum)Enum.ToObject(typeFromHandle, result3);
						return true;
					}
					logger?.Log("TryParseEnum can't parse sbyte from " + arg + " for enum " + typeFromHandle.Name);
				}
				else
				{
					foreach (TEnum value2 in Enum.GetValues(typeFromHandle))
					{
						if (Enum.GetName(typeFromHandle, value2).Equals(arg, StringComparison.OrdinalIgnoreCase))
						{
							result = value2;
							return true;
						}
					}
					logger?.Log("TryParseEnum can't find item by direct name " + arg + " for enum " + typeFromHandle.Name);
				}
			}
			catch (Exception value)
			{
				logger?.Log($"TryParseEnum error happened when process {arg} for enum {typeFromHandle.Name}: {value}");
			}
			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?.Log("TryParseBool error happened when process " + arg + ". Can't parse value like 1/0/true/false.");
			result = defaultValue;
			return false;
		}
	}
	public class UtilityConsole
	{
		private readonly Dictionary<string, ConsoleCommand> consoleCommandsDict;

		private readonly HelperDebugLog 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(HelperDebugLog logger = null, List<string> ignoreValidationCommands = null)
		{
			consoleCommandsDict = new Dictionary<string, ConsoleCommand>();
			this.logger = logger;
			this.ignoreValidationCommands = ignoreValidationCommands;
		}

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

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

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

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

		private void LogCommand(string funcPrefix, string cmd, bool isLog, bool isLogParams, int maxLen)
		{
			if (logger == null || !isLog)
			{
				return;
			}
			if (string.IsNullOrEmpty(cmd))
			{
				logger.Log(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");
						continue;
					}
					if (consoleCommandsDict.ContainsKey(text2))
					{
						flag &= consoleCommandsDict[text2].IsValidCommandArgs(array3.Skip(1));
						continue;
					}
					logger?.LogDebugError("UtilityConsole.IsValidCommandLine: can't find custom command with id " + text2);
					flag = false;
				}
				return flag;
			}
			catch (Exception value)
			{
				logger?.LogDebugError($"{"UtilityConsole.IsValidCommandLine:"} error: {value}");
				return false;
			}
		}

		public bool RunCommand(string commandLine, EventsData 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 ConsoleCommandWithData consoleCommandWithData)
							{
								consoleCommandWithData.Execute(array2.Skip(1), data);
							}
							else
							{
								consoleCommandsDict[key].Execute(array2.Skip(1));
							}
						}
						catch (Exception value)
						{
							logger?.Log($"{"UtilityConsole.RunCommand:"} execute command error {value}");
						}
					}
					else if (onCustomCommandNotFound != null)
					{
						onCustomCommandNotFound(text);
					}
					else
					{
						logger?.Log("UtilityConsole.RunCommand: execute command not found error");
					}
				}
			}
			catch (Exception value2)
			{
				logger?.Log($"{"UtilityConsole.RunCommand:"} error {value2}");
				return false;
			}
			return true;
		}
	}
	public class UtilityJson
	{
		public static HelperJson Generate(HelperLog logger)
		{
			return new HelperJson(logger, File.Exists(".mod_debug"));
		}
	}
	public static class UtilityRandom
	{
		private static readonly Random rnd = new Random(DateTime.Now.Millisecond);

		public static T GetRandomItemFromList<T>(IList<T> list)
		{
			if (list == null || list.Count <= 0)
			{
				return default(T);
			}
			return list[rnd.Next(list.Count)];
		}
	}
	public class 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>(HelperLog logger) where T : class
		{
			string text = string.Empty;
			try
			{
				text = SettingsPath;
				T result = UtilityJson.Generate(logger).FromFile<T>(text);
				logger?.Log("Settings loaded.");
				return result;
			}
			catch (FileNotFoundException)
			{
				logger?.Log("Can't load settings. File not found at " + text + ". Using standard.");
			}
			catch (Exception value)
			{
				logger?.Log($"error: {value}. \n Can't load settings. Using standard.");
			}
			T result2 = null;
			try
			{
				result2 = Activator.CreateInstance<T>();
				return result2;
			}
			catch (Exception value2)
			{
				logger?.Log($"error: {value2}. \n Can't create default data class.");
			}
			return result2;
		}
	}
}
namespace ModHelper.Data
{
	public class ConsoleCommand
	{
		public virtual string Id { get; }

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

		public virtual bool IsValidCommandArgs(IEnumerable<string> args)
		{
			return true;
		}
	}
	public class ConsoleCommandWithData : ConsoleCommand
	{
		public virtual bool Execute(IEnumerable<string> args, EventsData data)
		{
			return true;
		}
	}
}

plugins/ChaosTricks/ModHelperTextGUI.dll

Decompiled a month ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BFT")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ModHelperTextGUI")]
[assembly: AssemblyTitle("ModHelperTextGUI")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ModHelperTextGUI;

public class NameComponentTextMesh : MonoBehaviour
{
	public Camera gameCamera;

	public string displayedText;

	public int textFontSize = 14;

	public Vector3 textOffset = new Vector3(0f, 0.2f, 0f);

	public Color textColor = Color32.op_Implicit(new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue));

	public TextAnchor textAnchor = (TextAnchor)4;

	public TextAlignment textAlignment = (TextAlignment)1;

	public Font textFont;

	public Vector3 rootLocalScale;

	public int rootLayer;

	protected bool isActivated;

	protected TextMesh textMesh;

	protected GameObject root;

	public Func<Vector3> getCustomInitLocalPosition;

	public Func<Vector3> getCustomParentSize;

	public Action<string> debugLog;

	public bool isDisableTextByRange = true;

	public float disableTextRange = 150f;

	public Func<Vector3> getBasePointForDisableRange;

	protected virtual void DebugLog(string msg)
	{
		debugLog?.Invoke(msg);
	}

	protected virtual Vector3 GetParentSize()
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: 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_0066: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		if (getCustomParentSize != null)
		{
			return getCustomParentSize();
		}
		Renderer componentInChildren = ((Component)this).gameObject.GetComponentInChildren<Renderer>(true);
		Bounds bounds;
		if ((Object)(object)componentInChildren != (Object)null)
		{
			bounds = componentInChildren.bounds;
			if (((Bounds)(ref bounds)).size.y > 0.01f)
			{
				DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(21, 1);
				defaultInterpolatedStringHandler.AppendLiteral("ParentSize: renderer ");
				bounds = componentInChildren.bounds;
				defaultInterpolatedStringHandler.AppendFormatted<Vector3>(((Bounds)(ref bounds)).size);
				DebugLog(defaultInterpolatedStringHandler.ToStringAndClear());
				bounds = componentInChildren.bounds;
				return ((Bounds)(ref bounds)).size;
			}
		}
		Collider componentInChildren2 = ((Component)this).gameObject.GetComponentInChildren<Collider>(true);
		if ((Object)(object)componentInChildren2 != (Object)null)
		{
			bounds = componentInChildren2.bounds;
			if (((Bounds)(ref bounds)).size.y > 0.01f)
			{
				DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(21, 1);
				defaultInterpolatedStringHandler.AppendLiteral("ParentSize: collider ");
				bounds = componentInChildren2.bounds;
				defaultInterpolatedStringHandler.AppendFormatted<Vector3>(((Bounds)(ref bounds)).size);
				DebugLog(defaultInterpolatedStringHandler.ToStringAndClear());
				bounds = componentInChildren2.bounds;
				return ((Bounds)(ref bounds)).size;
			}
		}
		DebugLog("ParentSize: no renderer & collider bounds");
		return Vector3.zero;
	}

	protected virtual Vector3 GetDefaultInitLocalPosition()
	{
		//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_0012: 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_0021: 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_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)
		Vector3 parentSize = GetParentSize();
		Vector3 localPosition = root.transform.localPosition;
		localPosition.y += parentSize.y;
		return localPosition + textOffset;
	}

	public virtual void Init()
	{
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: 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_0037: Expected O, but got Unknown
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: 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)
		if ((Object)(object)gameCamera == (Object)null)
		{
			gameCamera = Camera.main;
		}
		if ((Object)(object)root == (Object)null)
		{
			root = new GameObject("bft_name");
			root.transform.localPosition = Vector3.zero;
			root.AddComponent<MeshRenderer>();
			textMesh = root.AddComponent<TextMesh>();
			root.transform.SetParent(((Component)this).gameObject.transform, false);
		}
		isActivated = true;
		textMesh.text = displayedText;
		textMesh.fontSize = textFontSize;
		textMesh.anchor = textAnchor;
		textMesh.alignment = textAlignment;
		textMesh.color = textColor;
		if ((Object)(object)textFont != (Object)null)
		{
			textMesh.font = textFont;
		}
		root.transform.localScale = rootLocalScale;
		if (getCustomInitLocalPosition != null)
		{
			root.transform.localPosition = getCustomInitLocalPosition();
		}
		else
		{
			root.transform.localPosition = GetDefaultInitLocalPosition();
		}
		root.layer = rootLayer;
		root.SetActive(true);
	}

	protected bool IsNeedDisableText()
	{
		//IL_0011: 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_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//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)
		if (getBasePointForDisableRange == null)
		{
			return false;
		}
		try
		{
			Vector3 val = getBasePointForDisableRange();
			Vector3 val2 = root.transform.position - val;
			return ((Vector3)(ref val2)).magnitude >= disableTextRange;
		}
		catch (Exception value)
		{
			DebugLog($"IsNeedDisableText error: {value}");
			return false;
		}
	}

	protected virtual void Update()
	{
		//IL_008b: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
		if (!isActivated || !((Object)(object)gameCamera != (Object)null))
		{
			return;
		}
		if (isDisableTextByRange)
		{
			bool flag = IsNeedDisableText();
			bool activeSelf = root.activeSelf;
			if (activeSelf && flag)
			{
				root.SetActive(false);
				DebugLog("name is disabled");
				return;
			}
			if (!activeSelf && !flag)
			{
				root.SetActive(true);
				DebugLog("name is enabled");
			}
			if (!activeSelf)
			{
				return;
			}
		}
		root.transform.rotation = Quaternion.LookRotation(((Component)gameCamera).transform.forward, ((Component)gameCamera).transform.up);
	}
}
public static class Utility
{
	public static bool IsCanBeSeen(Camera cam, GameObject obj)
	{
		//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_0012: 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_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: 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)
		Vector3 val = cam.WorldToViewportPoint(obj.transform.position);
		if (val.z > 0f && val.x > 0f && val.x < 1f && val.y > 0f)
		{
			return val.y < 1f;
		}
		return false;
	}
}

plugins/ChaosTricks/ModHelperUnity.dll

Decompiled a month 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.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using EventsIO;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Microsoft.CodeAnalysis;
using ModHelper;
using ModHelperUnity.Data;
using ModHelperUnity.UtilityGUI;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BFT")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ModHelperUnity")]
[assembly: AssemblyTitle("ModHelperUnity")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace ModHelperUnity
{
	public abstract class TypedNotifyBase
	{
		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 string lastLoadResourcesPath;

		protected Func<string, byte[]> lastCustomFileReader;

		protected int logLimit;

		protected HelperLog logger;

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

		protected Texture2D textureOnError;

		public TypedNotifySettings Settings { get; protected set; }

		protected TypedNotifyMessage CurrentMessage { get; private set; }

		protected TypedNotifyParameters CurrentNotifyParameters { get; private set; }

		protected virtual void Log(string msg)
		{
			HelperLog obj = logger;
			if (obj != null)
			{
				obj.Log((object)("TypedNotifyBase: " + msg));
			}
		}

		protected virtual void LimitedLog(string msg)
		{
			if (logLimit > 0)
			{
				HelperLog obj = logger;
				if (obj != null)
				{
					obj.Log((object)msg);
				}
				logLimit--;
			}
		}

		protected virtual Tuple<Texture2D, bool> GetMessageTexture(string type)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			if ((Object)(object)textureOnError == (Object)null)
			{
				textureOnError = new Texture2D(2, 2);
			}
			if (messageTextures.ContainsKey(type))
			{
				Texture2D val = messageTextures[type];
				if ((Object)(object)val == (Object)null)
				{
					return new Tuple<Texture2D, bool>(textureOnError, item2: true);
				}
				return new Tuple<Texture2D, bool>(val, item2: false);
			}
			return new Tuple<Texture2D, bool>(textureOnError, item2: true);
		}

		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 value)
			{
				Log($"LoadFadeSettings error: {value}");
			}
			if (Settings == null)
			{
				Settings = new TypedNotifySettings();
			}
		}

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

		protected void LoadResources(string folderPath, Func<string, byte[]> customFileReader = null, bool isLessLog = false)
		{
			try
			{
				lastLoadResourcesPath = folderPath;
				lastCustomFileReader = customFileReader;
				Log("LoadResources");
				string text = "notify_settings.data";
				string settingsFilePath = ((folderPath == null) ? text : Path.Combine(folderPath, text));
				ClearMessageTextures();
				LoadFadeSettings(settingsFilePath, customFileReader);
				messageTextures = new Dictionary<string, Texture2D>();
				if (Settings.notifyParameters == null)
				{
					return;
				}
				TypedNotifyParameters[] notifyParameters = Settings.notifyParameters;
				foreach (TypedNotifyParameters typedNotifyParameters in notifyParameters)
				{
					if (!isLessLog)
					{
						Log(typedNotifyParameters.ToString());
					}
					string imageFilePath = ((folderPath == null) ? typedNotifyParameters.imageFileName : Path.Combine(folderPath, typedNotifyParameters.imageFileName));
					Texture2D val = LoadImage(imageFilePath, customFileReader);
					if ((Object)(object)val != (Object)null)
					{
						messageTextures[typedNotifyParameters.type] = val;
						((Texture)val).filterMode = (FilterMode)2;
						((Texture)val).anisoLevel = 16;
					}
					else
					{
						Log("LoadResources loaded texture is null");
					}
				}
			}
			catch (Exception value)
			{
				Log($"LoadResources error: {value}");
			}
		}

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

		public virtual void ForcePostInit(string folderPath, HelperLog 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 value)
			{
				Log($"ForcePostInit error: {value}");
			}
			Log("force init");
		}

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

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

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

		protected virtual TypedNotifyParameters GetTypedNotifyParameters(EventsData 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(EventsData eventData, HelperLanguagesFormatted translation)
		{
			if (eventData == null)
			{
				Log("warning, eventData is null");
			}
			if (eventData == null)
			{
				Log("warning, translation is null");
			}
			TypedNotifyParameters typedNotifyParameters = GetTypedNotifyParameters(eventData);
			AddNotifyToQueue(new TypedNotifyMessage(GenerateMessage(eventData, translation), typedNotifyParameters.type, typedNotifyParameters.showMessageDuration, typedNotifyParameters.showFadeAnimationDuration, typedNotifyParameters.hideFadeAnimationDuration));
		}

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

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

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

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

		public 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 value)
			{
				LimitedLog($"error, {value}");
			}
		}

		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();
			}
		}

		public virtual void Start()
		{
		}

		public virtual void Awake()
		{
		}

		public 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)
			{
				if ((Object)(object)value != (Object)null)
				{
					((Object)value).hideFlags = (HideFlags)61;
					Object.Destroy((Object)(object)value);
				}
			}
		}

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

		~TypedNotifyBase()
		{
			Dispose(disposing: false);
		}
	}
	public static 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 UtilityUI
	{
		public static int StandardScreenWidth => 2560;

		public static int StandardScreenHeight => 1440;

		private static string ColorToHex(Color32 color)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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)
			return $"{color.r:X2}{color.g:X2}{color.b:X2}{color.a:X2}";
		}

		public static string GetColoredText(string text, Color32 color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			string value = ColorToHex(color);
			return $"<color=#{value}>{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_0028: Expected O, but got Unknown
			//IL_002a: 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, Il2CppStructArray<byte>.op_Implicit(array));
			return val;
		}

		public static float CalcScreenFactor(int baseScreenSize, int currentScreenSize)
		{
			if (baseScreenSize != currentScreenSize)
			{
				return (float)currentScreenSize / (float)baseScreenSize;
			}
			return 1f;
		}
	}
}
namespace ModHelperUnity.UtilityGUI
{
	public class TypedNotifyOnGUI : TypedNotifyBase
	{
		private float currentAlpha;

		private float targetAlpha;

		protected Dictionary<string, Font> fonts;

		public override void ForcePostInit(string folderPath, HelperLog 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 value)
					{
						if (logger != null)
						{
							logger.Log((object)$"TypedNotifyOnGUI loading font error: {value}");
						}
					}
				}
			}
			catch (Exception value2)
			{
				if (logger != null)
				{
					logger.Log((object)$"TypedNotifyOnGUI PostInit error: {value2}");
				}
			}
		}

		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 value)
			{
				HelperLog obj = logger;
				if (obj != null)
				{
					obj.Log((object)$"finding font error: {value}");
				}
			}
			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 + ">");
		}

		public 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_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Expected O, but got Unknown
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				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;
					float num = UtilityUI.CalcScreenFactor(UtilityUI.StandardScreenWidth, Screen.width);
					float num2 = UtilityUI.CalcScreenFactor(UtilityUI.StandardScreenHeight, Screen.height);
					float num3 = 0f;
					float num4 = 0f;
					Tuple<Texture2D, bool> messageTexture = GetMessageTexture(base.CurrentMessage.messageType);
					Texture2D item = messageTexture.Item1;
					if (messageTexture.Item2)
					{
						LoadResources(lastLoadResourcesPath, lastCustomFileReader, isLessLog: true);
						item = GetMessageTexture(base.CurrentMessage.messageType).Item1;
					}
					if ((Object)(object)item != (Object)null)
					{
						num3 = (float)((Texture)item).width * num;
						num4 = (float)((Texture)item).height * num2;
					}
					Rect val = default(Rect);
					((Rect)(ref val)).x = ((float)Screen.width - num3) * (0.5f + currentNotifyParameters.notifyHorisontalOffset);
					((Rect)(ref val)).y = ((float)Screen.height - num4) * (0.5f + currentNotifyParameters.notifyVerticalOffset);
					((Rect)(ref val)).width = num3;
					((Rect)(ref val)).height = num4;
					Rect val2 = val;
					float num5 = Math.Min(num, num2);
					float num6 = Math.Max(num, num2);
					int num7 = (int)((float)currentNotifyParameters.fontSize * num5);
					GUIStyle val3 = new GUIStyle(GUI.skin.label)
					{
						fontSize = num7,
						alignment = (TextAnchor)4,
						richText = true,
						fixedWidth = num3,
						fixedHeight = num4
					};
					Font font = GetFont(currentNotifyParameters.fontPath, num7);
					if ((Object)(object)font != (Object)null)
					{
						val3.font = font;
					}
					val3.padding.top = (int)((float)currentNotifyParameters.textPadding.top * num6);
					val3.padding.bottom = (int)((float)currentNotifyParameters.textPadding.bottom * num6);
					val3.padding.left = (int)((float)currentNotifyParameters.textPadding.left * num6);
					val3.padding.right = (int)((float)currentNotifyParameters.textPadding.right * num6);
					val3.normal.textColor = color;
					if ((Object)(object)item != (Object)null)
					{
						GUI.DrawTexture(val2, (Texture)(object)item);
					}
					if (((Rect)(ref val2)).width <= 200f || ((Rect)(ref val2)).height <= 80f)
					{
						LimitedLog("force fix rect for text to 200");
						num3 = 200f * num;
						num4 = 80f * num2;
						val = default(Rect);
						((Rect)(ref val)).x = ((float)Screen.width - num3) * (0.5f + currentNotifyParameters.notifyHorisontalOffset);
						((Rect)(ref val)).y = ((float)Screen.height - num4) * (0.5f + currentNotifyParameters.notifyVerticalOffset);
						((Rect)(ref val)).width = num3;
						((Rect)(ref val)).height = num4;
						val2 = val;
						val3.fixedWidth = num3;
						val3.fixedHeight = num4;
					}
					GUI.Label(val2, GetFadedText(base.CurrentMessage.message), val3);
					GUI.matrix = matrix;
				}
			}
			catch (Exception value)
			{
				LimitedLog($"TypedNotifyOnGUI->OnGUI {value}");
			}
		}
	}
	public class TypedNotifySettings
	{
		public bool isDisableNotify;

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

		public override string ToString()
		{
			if (notifyParameters == null)
			{
				return "TypedNotifySettings: not found notifyParameters";
			}
			string text = $"isDisableNotify={isDisableNotify}";
			TypedNotifyParameters[] array = notifyParameters;
			for (int i = 0; i < array.Length; i++)
			{
				_ = array[i];
				text = string.Join(Environment.NewLine, text, "notifyParameters:", notifyParameters.ToString());
			}
			return text;
		}
	}
}
namespace ModHelperUnity.Data
{
	public class NotifyMessage
	{
		private readonly string msg;

		private float duration;

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

		public string GetMessage()
		{
			return msg;
		}

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

		public void OnFrame(float dt)
		{
			if (!IsFinished())
			{
				duration -= dt;
			}
		}
	}
	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 TypedNotifyParameters
	{
		public bool isDisable;

		public string imageFileName = string.Empty;

		public string type = "default";

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

		public string fontPath = "";

		public float showMessageDuration = 5f;

		public float showFadeAnimationDuration = 1f;

		public float hideFadeAnimationDuration = 1f;

		public float delayAfterNotify = 1f;

		public float notifyHorisontalOffset;

		public float notifyVerticalOffset = -0.45f;

		public int fontSize = 19;

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

		public byte nicknameTextColorR = 65;

		public byte nicknameTextColorG = 160;

		public byte nicknameTextColorB = 94;

		public byte nicknameTextColorA = byte.MaxValue;

		public byte messageTextColorR = 65;

		public byte messageTextColorG = 160;

		public byte messageTextColorB = 94;

		public byte messageTextColorA = byte.MaxValue;

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

		public Color32 NicknameTextColor => new Color32(nicknameTextColorR, nicknameTextColorG, nicknameTextColorB, nicknameTextColorA);

		public Color32 MessageTextColor => new Color32(messageTextColorR, messageTextColorG, messageTextColorB, messageTextColorA);

		public override string ToString()
		{
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			return string.Join(Environment.NewLine, "imageFileName: " + imageFileName, "type: " + type, $"showMessageDuration: {showMessageDuration}", $"showFadeAnimationDuration: {showFadeAnimationDuration}", $"hideFadeAnimationDuration: {hideFadeAnimationDuration}", $"delayAfterNotify: {delayAfterNotify}", $"notifyHorisontalOffset: {notifyHorisontalOffset}", $"notifyVerticalOffset: {notifyVerticalOffset}", $"textPadding: {textPadding}", $"fontSize: {fontSize}", $"isDisable: {isDisable}", $"nicknameTextColor: {NicknameTextColor}", $"messageTextColor: {MessageTextColor}", "events: " + string.Join(Environment.NewLine, events), "fontPath: " + fontPath);
		}
	}
}