Decompiled source of Hikaria Core v0.0.12

BepInEx/plugins/Hikaria.Core/Hikaria.Core.dll

Decompiled 7 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Agents;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Hook;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using CellMenu;
using Clonesoft.Json;
using Clonesoft.Json.Converters;
using Clonesoft.Json.Serialization;
using GTFO.API;
using Hikaria.Core.Entities;
using Hikaria.Core.Extensions;
using Hikaria.Core.Features.Accessibility;
using Hikaria.Core.Features.Core;
using Hikaria.Core.Features.Dev;
using Hikaria.Core.Features.Security;
using Hikaria.Core.Interfaces;
using Hikaria.Core.Managers;
using Hikaria.Core.SNetworkExt;
using Hikaria.Core.Utility;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppInterop.Runtime.Runtime;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using LevelGeneration;
using Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour;
using Player;
using SNetwork;
using SemanticVersioning;
using Steamworks;
using TMPro;
using TheArchive;
using TheArchive.Core;
using TheArchive.Core.Attributes;
using TheArchive.Core.Attributes.Feature.Settings;
using TheArchive.Core.Bootstrap;
using TheArchive.Core.FeaturesAPI;
using TheArchive.Core.FeaturesAPI.Components;
using TheArchive.Core.FeaturesAPI.Settings;
using TheArchive.Core.Localization;
using TheArchive.Core.Managers;
using TheArchive.Features.Presence;
using TheArchive.Features.Security;
using TheArchive.Interfaces;
using TheArchive.Loader;
using TheArchive.Utilities;
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("Hikaria.Core")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+39283951571722e15e2250552ed931bb16ea9493")]
[assembly: AssemblyProduct("Hikaria.Core")]
[assembly: AssemblyTitle("Hikaria.Core")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
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;
		}
	}
	[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 NativeIntegerAttribute : Attribute
	{
		public readonly bool[] TransformFlags;

		public NativeIntegerAttribute()
		{
			TransformFlags = new bool[1] { true };
		}

		public NativeIntegerAttribute(bool[] P_0)
		{
			TransformFlags = P_0;
		}
	}
}
namespace Hikaria.Core
{
	public static class CoreAPI
	{
		public static event Action<SNet_Player, IEnumerable<pModInfo>> OnPlayerModsSynced
		{
			add
			{
				ModList.OnPlayerModsSynced += value;
			}
			remove
			{
				ModList.OnPlayerModsSynced -= value;
			}
		}

		public static bool IsPlayerInstalledCore(SNet_Player player, Version version = default(Version))
		{
			return IsPlayerInstalledMod(player, "Hikaria.Core", version);
		}

		public static bool IsPlayerInstalledMod(SNet_Player player, string guid, Version version = default(Version))
		{
			if ((Object)(object)player == (Object)null || player.IsBot)
			{
				return false;
			}
			if (player.IsLocal)
			{
				if (ModList.InstalledMods.TryGetValue(guid, out var value))
				{
					return value.Version >= version;
				}
				return false;
			}
			if (ModList.PlayerModsLookup.TryGetValue(player.Lookup, out var value2) && value2.TryGetValue(guid, out var value3))
			{
				return value3.Version >= version;
			}
			return false;
		}

		public static void RegisterSelf<T>(T instance)
		{
			Type type = instance.GetType();
			if (!type.IsInterface && !type.IsAbstract && typeof(IOnPlayerModsSynced).IsAssignableFrom(type))
			{
				ModList.PlayerModsSyncedListeners.Add((IOnPlayerModsSynced)(object)instance);
			}
		}

		public static void UnregisterSelf<T>(T instance)
		{
			Type type = instance.GetType();
			if (!type.IsInterface && !type.IsAbstract && typeof(IOnPlayerModsSynced).IsAssignableFrom(type))
			{
				ModList.PlayerModsSyncedListeners.Remove((IOnPlayerModsSynced)(object)instance);
			}
		}
	}
	public static class GameEventAPI
	{
		public static bool IsGamePaused
		{
			get
			{
				return PauseManager.IsPaused;
			}
			set
			{
				PauseManager.IsPaused = value;
			}
		}

		public static event Action<eBufferType> OnRecallComplete
		{
			add
			{
				GameEventListener.OnRecallComplete += value;
			}
			remove
			{
				GameEventListener.OnRecallComplete -= value;
			}
		}

		public static event Action OnGameDataInited
		{
			add
			{
				GameEventListener.OnGameDataInited += value;
			}
			remove
			{
				GameEventListener.OnGameDataInited -= value;
			}
		}

		public static event Action<eGameStateName, eGameStateName> OnGameStateChanged
		{
			add
			{
				GameEventListener.OnGameStateChanged += value;
			}
			remove
			{
				GameEventListener.OnGameStateChanged -= value;
			}
		}

		public static event Action<SNet_Player, string> OnReceiveChatMessage
		{
			add
			{
				GameEventListener.OnReceiveChatMessage += value;
			}
			remove
			{
				GameEventListener.OnReceiveChatMessage -= value;
			}
		}

		public static event Action<SNet_Player, SNet_PlayerEvent, SNet_PlayerEventReason> OnPlayerEvent
		{
			add
			{
				GameEventListener.OnPlayerEvent += value;
			}
			remove
			{
				GameEventListener.OnPlayerEvent -= value;
			}
		}

		public static event Action<SNet_Player, SessionMemberEvent> OnSessionMemberChanged
		{
			add
			{
				GameEventListener.OnSessionMemberChanged += value;
			}
			remove
			{
				GameEventListener.OnSessionMemberChanged -= value;
			}
		}

		public static event Action OnMasterChanged
		{
			add
			{
				GameEventListener.OnMasterChanged += value;
			}
			remove
			{
				GameEventListener.OnMasterChanged -= value;
			}
		}

		public static event Action<eMasterCommandType, int> OnMasterCommand
		{
			add
			{
				GameEventListener.OnMasterCommand += value;
			}
			remove
			{
				GameEventListener.OnMasterCommand -= value;
			}
		}

		public static event Action<SNet_Player, SNet_SlotType, SNet_SlotHandleType, int> OnPlayerSlotChanged
		{
			add
			{
				GameEventListener.OnPlayerSlotChanged += value;
			}
			remove
			{
				GameEventListener.OnPlayerSlotChanged -= value;
			}
		}

		public static event Action OnAfterLevelCleanup
		{
			add
			{
				GameEventListener.OnAfterLevelCleanup += value;
			}
			remove
			{
				GameEventListener.OnAfterLevelCleanup -= value;
			}
		}

		public static event Action OnResetSession
		{
			add
			{
				GameEventListener.OnResetSession += value;
			}
			remove
			{
				GameEventListener.OnResetSession -= value;
			}
		}

		public static event Action<eBufferType> OnRecallDone
		{
			add
			{
				GameEventListener.OnRecallDone += value;
			}
			remove
			{
				GameEventListener.OnRecallDone -= value;
			}
		}

		public static event Action<eBufferType> OnPrepareForRecall
		{
			add
			{
				GameEventListener.OnPrepareForRecall += value;
			}
			remove
			{
				GameEventListener.OnPrepareForRecall -= value;
			}
		}

		public static event Action OnGamePaused
		{
			add
			{
				PauseManager.OnPaused += value;
			}
			remove
			{
				PauseManager.OnPaused -= value;
			}
		}

		public static event Action OnGameUnpaused
		{
			add
			{
				PauseManager.OnUnpaused += value;
			}
			remove
			{
				PauseManager.OnUnpaused -= value;
			}
		}

		public static void RegisterSelf<T>(T instance)
		{
			GameEventListener.RegisterSelf(instance);
		}

		public static void UnregisterSelf<T>(T instance)
		{
			GameEventListener.UnregisterSelf(instance);
		}
	}
	public static class CoreGlobal
	{
		public const string OfficialServerUrl = "https://q1w2e3r4t5y6u7i8o9p0.top:50001/api/gtfo";

		public static string ThirdPartyServerUrl = string.Empty;

		public static bool UseThirdPartyServer = false;

		public static string ServerUrl
		{
			get
			{
				if (!UseThirdPartyServer)
				{
					return "https://q1w2e3r4t5y6u7i8o9p0.top:50001/api/gtfo";
				}
				return ThirdPartyServerUrl;
			}
		}

		public static int Revision => SNet.GameRevision;

		public static string RevisionString => SNet.GameRevisionString;

		public static bool ServerOnline { get; private set; } = true;


		public static IPLocationInfo IPLocation { get; private set; }

		public static void CheckIsServerOnline()
		{
			Task.Run(async delegate
			{
				try
				{
					ServerOnline = true;
					ServerOnline = await HttpHelper.GetAsync<bool>(ServerUrl + "/alive/checkalive");
				}
				catch
				{
					ServerOnline = false;
				}
				finally
				{
					if (!ServerOnline)
					{
						Logs.LogError("Server: \"" + ServerUrl + "\" is offline!!!");
						PopupMessageManager.ShowPopup(new PopupMessage
						{
							BlinkInContent = true,
							BlinkTimeInterval = 0.5f,
							Header = "Hikaria.Core",
							UpperText = "<color=#FF8C00><size=125%>警告 Warning</size></color>\n\n<size=150%><color=red>当前服务端不在线,某些功能无法正常工作!\nThe server is offline, some features won't work!</size></color>",
							LowerText = string.Empty,
							PopupType = (PopupType)3,
							OnCloseCallback = Action.op_Implicit(PopupMessageManager.EmptyAction)
						});
					}
				}
			});
		}

		public static void GetIPLocationInfo()
		{
			Task.Run(async delegate
			{
				IPLocation = await HttpHelper.GetAsync<IPLocationInfo>("https://api.ip.sb/geoip");
			});
		}
	}
	[ArchiveDependency(/*Could not decode attribute arguments.*/)]
	[ArchiveModule("Hikaria.Core", "HikariaCore", "0.0.12")]
	public class EntryPoint : IArchiveModule
	{
		internal class Groups
		{
			public static FeatureGroup ModuleGroup => FeatureGroups.GetOrCreateModuleGroup("Hikaria Core", (Dictionary<Language, string>)null);

			public static FeatureGroup Accessibility => ModuleGroup.GetOrCreateSubGroup("Accessibility", false);

			public static FeatureGroup Core => ModuleGroup.GetOrCreateSubGroup("Core", false);

			public static FeatureGroup Dev => ModuleGroup.GetOrCreateSubGroup("Developer", true);

			public static FeatureGroup Fixes => ModuleGroup.GetOrCreateSubGroup("Fixes", false);

			public static FeatureGroup Security => ModuleGroup.GetOrCreateSubGroup("Security", false);

			static Groups()
			{
				Core.SetLanguage(new Dictionary<Language, string>
				{
					{
						(Language)1,
						"核心"
					},
					{
						(Language)0,
						"Core"
					}
				});
				Accessibility.SetLanguage(new Dictionary<Language, string>
				{
					{
						(Language)1,
						"辅助功能"
					},
					{
						(Language)0,
						"Accessibility"
					}
				});
				Dev.SetLanguage(new Dictionary<Language, string>
				{
					{
						(Language)1,
						"开发者"
					},
					{
						(Language)0,
						"Developer"
					}
				});
				Fixes.SetLanguage(new Dictionary<Language, string>
				{
					{
						(Language)1,
						"修复"
					},
					{
						(Language)0,
						"Fixes"
					}
				});
				Security.SetLanguage(new Dictionary<Language, string>
				{
					{
						(Language)1,
						"安全"
					},
					{
						(Language)0,
						"Security"
					}
				});
			}
		}

		public bool ApplyHarmonyPatches => false;

		public bool UsesLegacyPatches => false;

		public ArchiveLegacyPatcher Patcher { get; set; }

		public string ModuleGroup => FeatureGroup.op_Implicit(FeatureGroups.GetOrCreateModuleGroup("Hikaria Core", (Dictionary<Language, string>)null));

		public Dictionary<Language, string> ModuleGroupLanguages => new Dictionary<Language, string>
		{
			{
				(Language)0,
				"Hikaria Core"
			},
			{
				(Language)1,
				"Hikaria 核心"
			}
		};

		public void Init()
		{
			JsonConvert.DefaultSettings = () => new JsonSerializerSettings
			{
				Formatting = (Formatting)1,
				ContractResolver = (IContractResolver)new DefaultContractResolver(),
				DateFormatHandling = (DateFormatHandling)1,
				DateFormatString = "yyyy-MM-dd HH:mm:ss",
				Converters = { (JsonConverter)new IsoDateTimeConverter
				{
					DateTimeFormat = "yyyy-MM-dd HH:mm:ss"
				} },
				Converters = { (JsonConverter)new StringEnumConverter() },
				ContractResolver = (IContractResolver)new DefaultContractResolver(),
				NullValueHandling = (NullValueHandling)0
			};
			Logs.LogMessage("OK");
		}

		public void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
		}

		public void OnLateUpdate()
		{
		}

		public void OnExit()
		{
		}
	}
	internal static class Logs
	{
		private static IArchiveLogger _logger;

		private static IArchiveLogger Logger => _logger ?? (_logger = LoaderWrapper.CreateLoggerInstance("Hikaria.Core", ConsoleColor.White));

		public static void LogDebug(object data)
		{
			Logger.Debug(data.ToString());
		}

		public static void LogError(object data)
		{
			Logger.Error(data.ToString());
		}

		public static void LogInfo(object data)
		{
			Logger.Info(data.ToString());
		}

		public static void LogMessage(object data)
		{
			Logger.Msg(ConsoleColor.White, data.ToString());
		}

		public static void LogWarning(object data)
		{
			Logger.Warning(data.ToString());
		}

		public static void LogNotice(object data)
		{
			Logger.Notice(data.ToString());
		}

		public static void LogSuccess(object data)
		{
			Logger.Success(data.ToString());
		}

		public static void LogException(Exception ex)
		{
			Logger.Exception(ex);
		}
	}
	public static class PluginInfo
	{
		public const string GUID = "Hikaria.Core";

		public const string NAME = "HikariaCore";

		public const string VERSION = "0.0.12";
	}
	public struct pPopupMessage
	{
		public bool BlinkInContent;

		public float BlinkTimeInterval;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
		public string Header;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
		public string UpperText;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
		public string LowerText;

		public PopupType PopupType;

		public PopupMessage UnpackPopupMessage()
		{
			//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_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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_005e: Expected O, but got Unknown
			return new PopupMessage
			{
				BlinkInContent = BlinkInContent,
				BlinkTimeInterval = BlinkTimeInterval,
				Header = Header,
				UpperText = UpperText,
				LowerText = LowerText,
				PopupType = PopupType,
				OnCloseCallback = Action.op_Implicit(PopupMessageManager.EmptyAction)
			};
		}

		public pPopupMessage(string header, string upperText, string lowerText, bool blinkInContent = true, float blinkTimeInterval = 0.2f, PopupType type = 3)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			BlinkInContent = true;
			BlinkTimeInterval = 0.2f;
			PopupType = (PopupType)3;
			Header = header;
			UpperText = upperText;
			LowerText = lowerText;
			BlinkInContent = blinkInContent;
			BlinkTimeInterval = blinkTimeInterval;
			PopupType = type;
		}
	}
	public struct pModInfo
	{
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
		public string Name;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
		public string GUID;

		public Version Version;

		public pModInfo(string name, string guid, Version version)
		{
			Name = string.Empty;
			GUID = string.Empty;
			Version = default(Version);
			Name = name;
			GUID = guid;
			Version = version;
		}
	}
	public struct Version : IComparable<Version>, IComparable, IEquatable<Version>
	{
		private readonly int _major;

		private readonly int _minor;

		private readonly int _patch;

		private static Regex strictRegex = new Regex("^\n            \\s*v?\n            ([0-9]|[1-9][0-9]+)       # major version\n            \\.\n            ([0-9]|[1-9][0-9]+)       # minor version\n            \\.\n            ([0-9]|[1-9][0-9]+)       # patch version\n            (\\-([0-9A-Za-z\\-\\.]+))?   # pre-release version\n            (\\+([0-9A-Za-z\\-\\.]+))?   # build metadata\n            \\s*\n            $", RegexOptions.IgnorePatternWhitespace);

		private static Regex looseRegex = new Regex("^\n            [v=\\s]*\n            (\\d+)                     # major version\n            \\.\n            (\\d+)                     # minor version\n            \\.\n            (\\d+)                     # patch version\n            (\\-?([0-9A-Za-z\\-\\.]+))?  # pre-release version\n            (\\+([0-9A-Za-z\\-\\.]+))?   # build metadata\n            \\s*\n            $", RegexOptions.IgnorePatternWhitespace);

		public int Major => _major;

		public int Minor => _minor;

		public int Patch => _patch;

		public Version(string input, bool loose = false)
		{
			_major = 0;
			_minor = 0;
			_patch = 0;
			Match match = (loose ? looseRegex : strictRegex).Match(input);
			if (!match.Success)
			{
				throw new ArgumentException("Invalid version string: " + input);
			}
			_major = int.Parse(match.Groups[1].Value);
			_minor = int.Parse(match.Groups[2].Value);
			_patch = int.Parse(match.Groups[3].Value);
		}

		public Version(int major, int minor, int patch)
		{
			_major = 0;
			_minor = 0;
			_patch = 0;
			_major = major;
			_minor = minor;
			_patch = patch;
		}

		public override string ToString()
		{
			return $"{Major}.{Minor}.{Patch}";
		}

		public override int GetHashCode()
		{
			return ((17 * 23 + Major.GetHashCode()) * 23 + Minor.GetHashCode()) * 23 + Patch.GetHashCode();
		}

		public bool Equals(Version other)
		{
			return CompareTo(other) == 0;
		}

		public int CompareTo(object obj)
		{
			if (obj != null)
			{
				if (obj is Version other)
				{
					return CompareTo(other);
				}
				throw new ArgumentException("Object is not a Version");
			}
			return 1;
		}

		public int CompareTo(Version other)
		{
			foreach (int item in PartComparisons(other))
			{
				if (item != 0)
				{
					return item;
				}
			}
			return 0;
		}

		private IEnumerable<int> PartComparisons(Version other)
		{
			yield return Major.CompareTo(other.Major);
			yield return Minor.CompareTo(other.Minor);
			yield return Patch.CompareTo(other.Patch);
		}

		public override bool Equals(object other)
		{
			if (other != null)
			{
				if (other is Version other2)
				{
					return Equals(other2);
				}
				throw new ArgumentException("Object is not a Version");
			}
			return false;
		}

		public static Version Parse(string input, bool loose = false)
		{
			return new Version(input, loose);
		}

		public static bool TryParse(string input, out Version result)
		{
			return TryParse(input, loose: false, out result);
		}

		public static bool TryParse(string input, bool loose, out Version result)
		{
			try
			{
				result = Parse(input, loose);
				return true;
			}
			catch
			{
				result = default(Version);
				return false;
			}
		}

		public static bool operator ==(Version a, Version b)
		{
			return a.Equals(b);
		}

		public static bool operator !=(Version a, Version b)
		{
			return !(a == b);
		}

		public static bool operator >(Version a, Version b)
		{
			return a.CompareTo(b) > 0;
		}

		public static bool operator >=(Version a, Version b)
		{
			return a.CompareTo(b) >= 0;
		}

		public static bool operator <(Version a, Version b)
		{
			return a.CompareTo(b) < 0;
		}

		public static bool operator <=(Version a, Version b)
		{
			return a.CompareTo(b) <= 0;
		}
	}
}
namespace Hikaria.Core.Utility
{
	public interface IEasyDetour
	{
		bool Apply();

		void Unpatch();
	}
	public abstract class EasyDetourBase<TDelegate> : IEasyDetour where TDelegate : Delegate
	{
		private static TDelegate s_Original;

		private static INativeDetour s_Detour;

		public abstract TDelegate DetourTo { get; }

		public abstract DetourDescriptor Descriptor { get; }

		public TDelegate Original => s_Original;

		public INativeDetour NativeDetour => s_Detour;

		~EasyDetourBase()
		{
			Unpatch();
		}

		public bool Apply()
		{
			if (s_Detour != null)
			{
				((IDetour)s_Detour).Undo();
				((IDetour)s_Detour).Free();
				((IDisposable)s_Detour).Dispose();
			}
			return EasyDetour.TryCreate(Descriptor, DetourTo, out s_Original, out s_Detour);
		}

		public void Unpatch()
		{
			if (s_Detour != null)
			{
				((IDetour)s_Detour).Undo();
				((IDetour)s_Detour).Free();
				((IDisposable)s_Detour).Dispose();
			}
		}
	}
	public static class EasyDetour
	{
		public unsafe delegate void StaticVoidDelegate(Il2CppMethodInfo* methodInfo);

		public unsafe delegate void InstanceVoidDelegate(IntPtr instancePtr, Il2CppMethodInfo* methodInfo);

		private static IArchiveLogger _logger;

		private static IArchiveLogger Logger => _logger ?? (_logger = LoaderWrapper.CreateArSubLoggerInstance("EasyDetour", ConsoleColor.White));

		public static bool TryCreate<T>(DetourDescriptor descriptor, T to, out T originalCall, out INativeDetour detourInstance) where T : Delegate
		{
			try
			{
				nint methodPointer = descriptor.GetMethodPointer();
				detourInstance = INativeDetour.CreateAndApply<T>((IntPtr)methodPointer, to, ref originalCall);
				bool num = detourInstance != null;
				if (num)
				{
					Logger.Success($"NativeDetour Success: {descriptor}");
				}
				else
				{
					Logger.Fail($"NativeDetour Success: {descriptor}");
				}
				return num;
			}
			catch (Exception ex)
			{
				Logger.Error("Exception Thrown while creating Detour:");
				Logger.Error(ex.ToString());
			}
			originalCall = null;
			detourInstance = null;
			return false;
		}

		public static bool CreateAndApply<T>(out T easyDetour) where T : IEasyDetour
		{
			easyDetour = Activator.CreateInstance<T>();
			return easyDetour.Apply();
		}
	}
	public struct DetourDescriptor
	{
		public Type Type;

		public Type ReturnType;

		public Type[] ArgTypes;

		public string MethodName;

		public bool IsGeneric;

		public unsafe nint GetMethodPointer()
		{
			if (Type == null)
			{
				throw new MissingFieldException("Field Type is not set!");
			}
			if (ReturnType == null)
			{
				throw new MissingFieldException("Field ReturnType is not set! If you mean 'void' do typeof(void)");
			}
			if (string.IsNullOrEmpty(MethodName))
			{
				throw new MissingFieldException("Field MethodName is not set or valid!");
			}
			Il2CppType.From(Type, true);
			IntPtr nativeClassPointer = Il2CppClassPointerStore.GetNativeClassPointer(Type);
			string fullName = GetFullName(ReturnType);
			string[] array;
			if (ArgTypes == null || ArgTypes.Length == 0)
			{
				array = Array.Empty<string>();
			}
			else
			{
				int num = ArgTypes.Length;
				array = new string[num];
				for (int i = 0; i < num; i++)
				{
					Type type = ArgTypes[i];
					array[i] = GetFullName(type);
				}
			}
			void** ptr = (void**)IL2CPP.GetIl2CppMethod(nativeClassPointer, IsGeneric, MethodName, fullName, array).ToPointer();
			if (ptr == null)
			{
				return (nint)ptr;
			}
			return (nint)(*ptr);
		}

		private static string GetFullName(Type type)
		{
			bool isPointer = type.IsPointer;
			if (isPointer)
			{
				type = type.GetElementType();
			}
			if (type.IsPrimitive || type == typeof(string))
			{
				if (isPointer)
				{
					return type.MakePointerType().FullName;
				}
				return type.FullName;
			}
			Type val = Il2CppType.From(type, true);
			if (isPointer)
			{
				return val.MakePointerType().FullName;
			}
			return val.FullName;
		}

		public override string ToString()
		{
			return $"{Type.FullName}.{MethodName}{(IsGeneric ? "<>" : string.Empty)}({string.Join(", ", ArgTypes.Select((Type arg) => arg.FullName))})";
		}
	}
	public static class HttpHelper
	{
		private static readonly HttpClient _httpClient = new HttpClient
		{
			Timeout = TimeSpan.FromSeconds(10.0)
		};

		private static IArchiveLogger _logger;

		private static IArchiveLogger Logger => _logger ?? (_logger = LoaderWrapper.CreateLoggerInstance("HttpHelper", ConsoleColor.White));

		public static async Task<T> GetAsync<T>(string url) where T : new()
		{
			if (!CoreGlobal.ServerOnline)
			{
				return new T();
			}
			try
			{
				HttpResponseMessage obj = await _httpClient.GetAsync(url);
				obj.EnsureSuccessStatusCode();
				return JsonConvert.DeserializeObject<T>(await obj.Content.ReadAsStringAsync());
			}
			catch (Exception ex)
			{
				Logger.Error("Error occurred while sending GET request");
				Logger.Exception(ex);
				return new T();
			}
		}

		public static async Task<T> PostAsync<T>(string url, object content) where T : new()
		{
			if (!CoreGlobal.ServerOnline)
			{
				return new T();
			}
			try
			{
				StringContent content2 = new StringContent(JsonConvert.SerializeObject(content), Encoding.UTF8, "application/json");
				HttpResponseMessage obj = await _httpClient.PostAsync(url, content2);
				obj.EnsureSuccessStatusCode();
				return JsonConvert.DeserializeObject<T>(await obj.Content.ReadAsStringAsync());
			}
			catch (Exception ex)
			{
				Logger.Error("Error occurred while sending POST request");
				Logger.Exception(ex);
				return new T();
			}
		}

		public static async Task<T> PutAsync<T>(string url, object content) where T : new()
		{
			if (!CoreGlobal.ServerOnline)
			{
				return new T();
			}
			try
			{
				StringContent content2 = new StringContent(JsonConvert.SerializeObject(content), Encoding.UTF8, "application/json");
				HttpResponseMessage obj = await _httpClient.PutAsync(url, content2);
				obj.EnsureSuccessStatusCode();
				return JsonConvert.DeserializeObject<T>(await obj.Content.ReadAsStringAsync());
			}
			catch (Exception ex)
			{
				Logger.Error("Error occurred while sending PUT request");
				Logger.Exception(ex);
				return new T();
			}
		}

		public static async Task<T> PatchAsync<T>(string url, object content) where T : new()
		{
			if (!CoreGlobal.ServerOnline)
			{
				return new T();
			}
			try
			{
				StringContent content2 = new StringContent(JsonConvert.SerializeObject(content), Encoding.UTF8, "application/json");
				HttpResponseMessage obj = await _httpClient.PatchAsync(url, content2);
				obj.EnsureSuccessStatusCode();
				return JsonConvert.DeserializeObject<T>(await obj.Content.ReadAsStringAsync());
			}
			catch (Exception ex)
			{
				Logger.Error("Error occurred while sending PATCH request");
				Logger.Exception(ex);
				return new T();
			}
		}
	}
	public static class SharedUtils
	{
		public static bool TryGetPlayerByCharacterSlot(int slot, out SNet_Player player)
		{
			player = null;
			int num = slot - 1;
			if (num < 0 || num > 4)
			{
				return false;
			}
			player = ((Il2CppArrayBase<SNet_Slot>)(object)SNet.Slots.CharacterSlots)[num].player;
			return (Object)(object)player != (Object)null;
		}

		public static bool TryGetPlayerBySlotIndex(int slot, out SNet_Player player)
		{
			player = null;
			int num = slot - 1;
			if (num < 0 || num > 4)
			{
				return false;
			}
			player = ((Il2CppArrayBase<SNet_Slot>)(object)SNet.Slots.PlayerSlots)[num].player;
			return (Object)(object)player != (Object)null;
		}
	}
}
namespace Hikaria.Core.SNetworkExt
{
	public interface IReplicatedPlayerData
	{
		pPlayer PlayerData { get; set; }
	}
	public interface ISNetExt_PacketDataWrapper
	{
		int GetTotalByteSize();

		int GetCount();

		void Serialize(byte[] bytes, ref int byteIndexOffset);

		void Deserialize(int objCount, byte[] bytes, ref int byteIndexOffset);
	}
	public static class SNetExt
	{
		private static Dictionary<ulong, Dictionary<Type, DataWrapper>> DataWrappersLookup = new Dictionary<ulong, Dictionary<Type, DataWrapper>>();

		public static void SendAllCustomData(SNet_Player sourcePlayer, SNet_Player toPlayer = null)
		{
			if (!DataWrappersLookup.TryGetValue(sourcePlayer.Lookup, out var value))
			{
				return;
			}
			foreach (DataWrapper value2 in value.Values)
			{
				value2.Send(sourcePlayer, toPlayer);
			}
		}

		public static void SetupCustomData<A>(string eventName, Action<SNet_Player, A> callback) where A : struct, IReplicatedPlayerData
		{
			SNetExt_ReplicatedPlayerData<A>.Setup(eventName, callback);
		}

		public static void SetLocalCustomData<A>(A data) where A : struct
		{
			if ((Object)(object)SNet.LocalPlayer != (Object)null)
			{
				SNet.LocalPlayer.StoreCustomData(data);
			}
		}

		public static void SendCustomData<A>(SNet_Player toPlayer = null) where A : struct
		{
			if ((Object)(object)toPlayer != (Object)null && toPlayer.IsBot)
			{
				return;
			}
			if ((Object)(object)SNet.LocalPlayer != (Object)null)
			{
				SNetExt_ReplicatedPlayerData<A>.SendData(SNet.LocalPlayer, GetLocalCustomData<A>(), toPlayer);
			}
			if (!SNet.IsMaster || !((Object)(object)toPlayer != (Object)null) || toPlayer.IsBot)
			{
				return;
			}
			List<SNet_Player> allBots = SNet.Core.GetAllBots(true);
			for (int i = 0; i < allBots.Count; i++)
			{
				SNet_Player val = allBots[i];
				if ((Object)(object)val != (Object)null && val.IsBot)
				{
					SNetExt_ReplicatedPlayerData<A>.SendData(val, val.LoadCustomData<A>(), toPlayer);
				}
			}
		}

		public static A GetLocalCustomData<A>() where A : struct
		{
			if ((Object)(object)SNet.LocalPlayer != (Object)null)
			{
				return SNet.LocalPlayer.LoadCustomData<A>();
			}
			return new A();
		}

		public static A LoadCustomData<A>(this SNet_Player player) where A : struct
		{
			Type typeFromHandle = typeof(A);
			if (!DataWrappersLookup.TryGetValue(player.Lookup, out var value))
			{
				DataWrappersLookup[player.Lookup] = new Dictionary<Type, DataWrapper>();
				value = DataWrappersLookup[player.Lookup];
			}
			DataWrapper<A> dataWrapper;
			if (!value.TryGetValue(typeFromHandle, out var value2))
			{
				dataWrapper = new DataWrapper<A>();
				value.Add(typeFromHandle, dataWrapper);
			}
			else
			{
				dataWrapper = (DataWrapper<A>)value2;
			}
			return dataWrapper.Load();
		}

		public static void StoreCustomData<A>(this SNet_Player player, A data) where A : struct
		{
			Type typeFromHandle = typeof(A);
			if (!DataWrappersLookup.TryGetValue(player.Lookup, out var value))
			{
				DataWrappersLookup[player.Lookup] = new Dictionary<Type, DataWrapper>();
				value = DataWrappersLookup[player.Lookup];
			}
			DataWrapper<A> dataWrapper;
			if (!value.TryGetValue(typeFromHandle, out var value2))
			{
				dataWrapper = new DataWrapper<A>();
				value.Add(typeFromHandle, dataWrapper);
			}
			else
			{
				dataWrapper = (DataWrapper<A>)value2;
			}
			dataWrapper.Store(player, data);
		}
	}
	public class SNetExt_AuthorativeAction<T> : SNetExt_SyncedAction<T> where T : struct
	{
		private Action<T> m_incomingActionValidation;

		public static SNetExt_AuthorativeAction<T> Create(string eventName, Action<ulong, T> incomingAction, Action<T> incomingActionValidation, Func<SNet_Player, bool> listenerFilter = null, SNet_ChannelType channelType = 2)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			SNetExt_AuthorativeAction<T> sNetExt_AuthorativeAction = new SNetExt_AuthorativeAction<T>();
			sNetExt_AuthorativeAction.Setup(eventName, incomingAction, incomingActionValidation, listenerFilter, channelType);
			sNetExt_AuthorativeAction.m_incomingActionValidation = incomingActionValidation;
			return sNetExt_AuthorativeAction;
		}

		public void Ask(T data)
		{
			if (SNet.IsMaster)
			{
				m_incomingActionValidation(data);
			}
			else if (SNet.HasMaster && m_listenersLookup.ContainsKey(SNet.Master.Lookup))
			{
				m_packet.Send(data, SNet.Master);
			}
		}

		public void Do(T data)
		{
			if (SNet.IsMaster)
			{
				m_packet.Send(data, m_listeners);
				m_incomingAction(SNet.LocalPlayer.Lookup, data);
			}
			else if (SNet.HasMaster && m_listenersLookup.ContainsKey(SNet.Master.Lookup))
			{
				m_packet.Send(data, SNet.Master);
			}
		}
	}
	public class SNetExt_BroadcastAction<T> : SNetExt_SyncedAction<T> where T : struct
	{
		public static SNetExt_BroadcastAction<T> Create(string eventName, Action<ulong, T> incomingAction, Func<SNet_Player, bool> listenerFilter = null, SNet_ChannelType channelType = 2)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			SNetExt_BroadcastAction<T> sNetExt_BroadcastAction = new SNetExt_BroadcastAction<T>();
			sNetExt_BroadcastAction.Setup(eventName, incomingAction, null, listenerFilter, channelType);
			return sNetExt_BroadcastAction;
		}

		public void Do(T data)
		{
			m_packet.Send(data, m_listeners);
			m_incomingAction(SNet.LocalPlayer.Lookup, data);
		}
	}
	public abstract class DataWrapper
	{
		public abstract void Send(SNet_Player fromPlayer, SNet_Player toPlayer = null);
	}
	public class DataWrapper<A> : DataWrapper where A : struct
	{
		private A m_data;

		public A Load()
		{
			return m_data;
		}

		public void Store(SNet_Player player, A data)
		{
			m_data = data;
			SNetExt_ReplicatedPlayerData<A>.SendData(player, m_data);
		}

		public override void Send(SNet_Player fromPlayer, SNet_Player toPlayer = null)
		{
			SNetExt_ReplicatedPlayerData<A>.SendData(fromPlayer, m_data, toPlayer);
		}
	}
	public abstract class SNetExt_Packet
	{
		internal string EventName { get; set; }

		internal bool AllowSendToLocal { get; set; }

		internal SNet_ChannelType ChannelType { get; set; }
	}
	public class SNetExt_Packet<T> : SNetExt_Packet where T : struct
	{
		private T m_data = new T();

		private bool m_hasValidateAction;

		private Action<T> ValidateAction { get; set; }

		private Action<ulong, T> ReceiveAction { get; set; }

		public static SNetExt_Packet<T> Create(string eventName, Action<ulong, T> receiveAction, Action<T> validateAction = null, bool allowSendToLocal = false, SNet_ChannelType channelType = 2)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			SNetExt_Packet<T> sNetExt_Packet = new SNetExt_Packet<T>
			{
				EventName = eventName,
				ChannelType = channelType,
				ReceiveAction = receiveAction,
				ValidateAction = validateAction,
				m_hasValidateAction = (validateAction != null),
				AllowSendToLocal = allowSendToLocal
			};
			NetworkAPI.RegisterEvent<T>(eventName, (Action<ulong, T>)sNetExt_Packet.OnReceiveData);
			return sNetExt_Packet;
		}

		public void Ask(T data)
		{
			if (SNet.IsMaster)
			{
				ValidateAction(data);
			}
			else if (SNet.HasMaster)
			{
				Send(data, SNet.Master);
			}
		}

		public void Send(T data, SNet_Player player = null)
		{
			//IL_0025: 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)
			if ((Object)(object)player == (Object)null)
			{
				NetworkAPI.InvokeEvent<T>(base.EventName, data, base.ChannelType);
				return;
			}
			NetworkAPI.InvokeEvent<T>(base.EventName, data, player, base.ChannelType);
			if (base.AllowSendToLocal && player.IsLocal)
			{
				OnReceiveData(SNet.LocalPlayer.Lookup, data);
			}
		}

		public void Send(T data, params SNet_Player[] players)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (players != null && players.Any())
			{
				NetworkAPI.InvokeEvent<T>(base.EventName, data, players.ToList(), base.ChannelType);
				if (base.AllowSendToLocal && players.Any((SNet_Player p) => p.IsLocal))
				{
					OnReceiveData(SNet.LocalPlayer.Lookup, data);
				}
			}
		}

		public void Send(T data, List<SNet_Player> players)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (players != null && players.Any())
			{
				NetworkAPI.InvokeEvent<T>(base.EventName, data, players, base.ChannelType);
				if (base.AllowSendToLocal && players.Any((SNet_Player p) => p.IsLocal))
				{
					OnReceiveData(SNet.LocalPlayer.Lookup, data);
				}
			}
		}

		public void OnReceiveData(ulong sender, T data)
		{
			m_data = data;
			if (m_hasValidateAction && SNet.IsMaster)
			{
				ValidateAction(m_data);
			}
			else
			{
				ReceiveAction(sender, m_data);
			}
		}
	}
	public class SNetExt_ReplicatedPlayerData<A> where A : struct
	{
		public delegate bool delegateComparisonAction(A playerData, SNet_Player player, A comparisonData);

		private static SNetExt_ReplicatedPlayerData<A> s_singleton;

		private SNetExt_Packet<A> m_syncPacket;

		private Action<SNet_Player, A> m_onChangeCallback;

		public static void Setup(string eventName, Action<SNet_Player, A> callback)
		{
			if (s_singleton == null)
			{
				s_singleton = new SNetExt_ReplicatedPlayerData<A>();
				s_singleton.m_syncPacket = SNetExt_Packet<A>.Create(eventName, OnReceiveData, null, allowSendToLocal: false, (SNet_ChannelType)0);
			}
			s_singleton.m_onChangeCallback = callback;
		}

		private static void OnReceiveData(ulong sender, A wrappedData)
		{
			//IL_000b: 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)
			pPlayer playerData = ((IReplicatedPlayerData)(object)wrappedData).PlayerData;
			SNet_Player val = default(SNet_Player);
			if (((pPlayer)(ref playerData)).TryGetPlayer(ref val) && !val.IsLocal)
			{
				val.StoreCustomData(wrappedData);
				s_singleton.m_onChangeCallback?.Invoke(val, wrappedData);
			}
		}

		public static void SendData(SNet_Player player, A data, SNet_Player toPlayer = null)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if ((!((Object)(object)toPlayer != (Object)null) || !toPlayer.IsBot) && (player.IsLocal || SNet.IsMaster))
			{
				pPlayer playerData = default(pPlayer);
				((pPlayer)(ref playerData)).SetPlayer(player);
				IReplicatedPlayerData obj = (IReplicatedPlayerData)(object)data;
				obj.PlayerData = playerData;
				data = (A)obj;
				if ((Object)(object)toPlayer != (Object)null)
				{
					s_singleton.m_syncPacket.Send(data, toPlayer);
				}
				else
				{
					s_singleton.m_syncPacket.Send(data);
				}
			}
		}

		public static bool Compare(delegateComparisonAction comparisonAction, A comparisonValue, eComparisonGroup group, bool includeBots = false)
		{
			//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_0005: Invalid comparison between Unknown and I4
			List<SNet_Player> val;
			if ((int)group != 0)
			{
				if ((int)group != 1)
				{
					return false;
				}
				val = SNet.Slots.PlayersSynchedWithGame;
			}
			else
			{
				val = SNet.Slots.SlottedPlayers;
			}
			int count = val.Count;
			for (int i = 0; i < count; i++)
			{
				SNet_Player val2 = val[i];
				if (includeBots || !val2.IsBot)
				{
					A playerData = val2.LoadCustomData<A>();
					if (!comparisonAction(playerData, val2, comparisonValue))
					{
						return false;
					}
				}
			}
			return true;
		}
	}
	public abstract class SNetExt_SyncedAction<T> : IOnSessionMemberChanged, IOnPlayerModsSynced where T : struct
	{
		protected SNetExt_Packet<T> m_packet;

		protected Action<ulong, T> m_incomingAction;

		protected Func<SNet_Player, bool> m_listenerFilter;

		protected bool m_hasListenerFilter;

		protected List<SNet_Player> m_listeners = new List<SNet_Player>();

		protected Dictionary<ulong, SNet_Player> m_listenersLookup = new Dictionary<ulong, SNet_Player>();

		public IEnumerable<SNet_Player> Listeners => m_listeners;

		public IReadOnlyDictionary<ulong, SNet_Player> ListenersLookup => m_listenersLookup;

		public event Action<SNet_Player> OnPlayerAddedToListeners;

		public event Action<SNet_Player> OnPlayerRemovedFromListeners;

		~SNetExt_SyncedAction()
		{
			GameEventAPI.UnregisterSelf(this);
			CoreAPI.UnregisterSelf(this);
		}

		protected void Setup(string eventName, Action<ulong, T> incomingAction, Action<T> incomingActionValidation = null, Func<SNet_Player, bool> listenerFilter = null, SNet_ChannelType channelType = 2)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			m_packet = SNetExt_Packet<T>.Create(eventName, incomingAction, incomingActionValidation, allowSendToLocal: false, channelType);
			m_incomingAction = incomingAction;
			m_listenerFilter = listenerFilter;
			m_hasListenerFilter = listenerFilter != null;
			GameEventAPI.RegisterSelf(this);
			CoreAPI.RegisterSelf(this);
		}

		public void SyncToPlayer(SNet_Player player, T data)
		{
			if (!player.IsLocal)
			{
				m_packet.Send(data, player);
			}
		}

		public void SyncToPlayer(SNet_Player player, params T[] datas)
		{
			foreach (T data in datas)
			{
				SyncToPlayer(player, data);
			}
		}

		public void SyncToPlayer(SNet_Player player, IEnumerable<T> datas)
		{
			foreach (T data in datas)
			{
				SyncToPlayer(player, data);
			}
		}

		public void OnPlayerModsSynced(SNet_Player player, IEnumerable<pModInfo> mods)
		{
			if (m_hasListenerFilter && m_listenerFilter(player) && player.IsInSessionHub)
			{
				Internal_AddPlayerToListeners(player);
			}
		}

		public void OnSessionMemberChanged(SNet_Player player, SessionMemberEvent playerEvent)
		{
			switch (playerEvent)
			{
			case SessionMemberEvent.JoinSessionHub:
				if (!m_hasListenerFilter || m_listenerFilter(player))
				{
					Internal_AddPlayerToListeners(player);
				}
				break;
			case SessionMemberEvent.LeftSessionHub:
				Internal_RemovePlayerFromListeners(player);
				break;
			}
		}

		private void Internal_AddPlayerToListeners(SNet_Player player)
		{
			m_listeners.RemoveAll((SNet_Player p) => p.Lookup == player.Lookup);
			m_listeners.Add(player);
			m_listenersLookup[player.Lookup] = player;
			this.OnPlayerAddedToListeners?.Invoke(player);
		}

		private void Internal_RemovePlayerFromListeners(SNet_Player player)
		{
			if (player.IsLocal)
			{
				Action<SNet_Player> onPlayerRemovedFromListeners = this.OnPlayerRemovedFromListeners;
				{
					foreach (SNet_Player item in m_listeners.ToList())
					{
						m_listeners.RemoveAll((SNet_Player p) => p.Lookup == player.Lookup);
						m_listenersLookup.Remove(player.Lookup);
						onPlayerRemovedFromListeners?.Invoke(item);
					}
					return;
				}
			}
			m_listeners.RemoveAll((SNet_Player p) => p.Lookup == player.Lookup);
			m_listenersLookup.Remove(player.Lookup);
			this.OnPlayerRemovedFromListeners?.Invoke(player);
		}

		public void AddPlayerToListeners(SNet_Player player)
		{
			if (!m_hasListenerFilter || m_listenerFilter(player))
			{
				Internal_AddPlayerToListeners(player);
			}
		}

		public void RemovePlayerFromListeners(SNet_Player player)
		{
			Internal_RemovePlayerFromListeners(player);
		}

		public bool IsListener(SNet_Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if (!m_listeners.Contains(player))
			{
				return IsListener(player.Lookup);
			}
			return true;
		}

		public bool IsListener(ulong lookup)
		{
			return m_listenersLookup.ContainsKey(lookup);
		}
	}
}
namespace Hikaria.Core.Managers
{
	public sealed class ChatManager : MonoBehaviour, IPauseable
	{
		private static Queue<Tuple<string, SNet_Player>> queue = new Queue<Tuple<string, SNet_Player>>();

		private float _timer;

		public static ChatManager Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			GameEventAPI.RegisterSelf(this);
		}

		private void OnDestroy()
		{
			GameEventAPI.UnregisterSelf(this);
		}

		private void FixedUpdate()
		{
			_timer += Time.fixedDeltaTime;
			if (!((double)_timer < 0.333))
			{
				_timer = 0f;
				if (queue.TryDequeue(out var result))
				{
					Speak(result);
				}
			}
		}

		public static void AddQueue(string[] msgs, SNet_Player player = null)
		{
			List<string> list = new List<string>();
			for (int i = 0; i < msgs.Length; i++)
			{
				string[] array = msgs[i].Split('\n');
				foreach (string text in array)
				{
					if (text.Length > 50)
					{
						string[] array2 = text.SplitInChunks(50);
						foreach (string item in array2)
						{
							list.Add(item);
						}
					}
					else
					{
						list.Add(text);
					}
				}
			}
			foreach (string item2 in list)
			{
				queue.Enqueue(Tuple.Create<string, SNet_Player>(item2, player));
			}
		}

		public static void AddQueue(string msg, SNet_Player player = null)
		{
			string[] array = msg.Split("\n");
			if (array.Length == 1)
			{
				if (array[0].Length > 50)
				{
					string[] array2 = array[0].SplitInChunks(50);
					foreach (string item in array2)
					{
						queue.Enqueue(Tuple.Create<string, SNet_Player>(item, player));
					}
				}
				else
				{
					queue.Enqueue(Tuple.Create<string, SNet_Player>(array[0], player));
				}
			}
			else
			{
				string[] array2 = array;
				foreach (string item2 in array2)
				{
					queue.Enqueue(Tuple.Create<string, SNet_Player>(item2, player));
				}
			}
		}

		public static void ClearQueue()
		{
			queue.Clear();
		}

		private static void Speak(Tuple<string, SNet_Player> tuple)
		{
			if ((Object)(object)tuple.Item2 != (Object)null && tuple.Item2.HasPlayerAgent)
			{
				PlayerAgent val = ((Il2CppObjectBase)tuple.Item2.PlayerAgent).Cast<PlayerAgent>();
				PlayerChatManager.WantToSentTextMessage(PlayerManager.GetLocalPlayerAgent(), tuple.Item1, val);
			}
			else
			{
				PlayerChatManager.WantToSentTextMessage(PlayerManager.GetLocalPlayerAgent(), tuple.Item1, (PlayerAgent)null);
			}
		}

		public void PausedUpdate()
		{
			_timer += PauseManager.PauseUpdateInterval;
			if (!((double)_timer < 0.333))
			{
				_timer = 0f;
				if (queue.TryDequeue(out var result))
				{
					Speak(result);
				}
			}
		}

		public void OnPaused()
		{
		}

		public void OnUnpaused()
		{
		}
	}
	public class GameEventLogManager : MonoBehaviour, IPauseable
	{
		private static Queue<string> queue = new Queue<string>();

		private float timer;

		public static GameEventLogManager Instance { get; private set; }

		private static PUI_GameEventLog PageLoadoutLog => MainMenuGuiLayer.Current.PageLoadout.m_gameEventLog;

		private static PUI_GameEventLog PlayerLayerLog => GuiManager.PlayerLayer.m_gameEventLog;

		private void Awake()
		{
			Instance = this;
			GameEventAPI.RegisterSelf(this);
		}

		private void OnDestroy()
		{
			GameEventAPI.UnregisterSelf(this);
		}

		private void FixedUpdate()
		{
			timer += Time.fixedDeltaTime;
			if (!((double)timer < 0.333))
			{
				timer = 0f;
				if (queue.TryDequeue(out var result))
				{
					PageLoadoutLog.AddLogItem(result, (eGameEventChatLogType)2);
					PlayerLayerLog.AddLogItem(result, (eGameEventChatLogType)2);
				}
			}
		}

		public static void AddLog(string log)
		{
			queue.Enqueue(log);
		}

		public static void AddLogInSeparate(string log, int chunkSize = 50)
		{
			string[] array = log.SplitInChunks(chunkSize);
			foreach (string item in array)
			{
				queue.Enqueue(item);
			}
		}

		public void PausedUpdate()
		{
			timer += PauseManager.PauseUpdateInterval;
			if (!((double)timer < 0.333))
			{
				timer = 0f;
				if (queue.TryDequeue(out var result))
				{
					PageLoadoutLog.AddLogItem(result, (eGameEventChatLogType)2);
					PlayerLayerLog.AddLogItem(result, (eGameEventChatLogType)2);
				}
			}
		}

		public void OnPaused()
		{
		}

		public void OnUnpaused()
		{
		}
	}
	public static class LiveLobbyPresenceManager
	{
		public static int Revision => SNet.GameRevision;

		public static bool IsPlayingModded => ArchiveMod.IsPlayingModded;

		public static string Expedition => PresenceManager.Expedition;

		public static string ExpeditionName => RichPresenceCore.ExpeditionName;

		public static int MaxPlayerSlots => ((IEnumerable<SlotPermission>)SNet.Slots.m_playerSlotPermissions).Where((SlotPermission _, int i) => SNet.Slots.IsHumanPermittedInSlot(i)).Count();

		public static int OpenSlots => ((IEnumerable<SlotPermission>)SNet.Slots.m_playerSlotPermissions).Where((SlotPermission _, int i) => SNet.Slots.IsHumanPermittedInSlot(i) && ((Object)(object)((Il2CppArrayBase<SNet_Slot>)(object)SNet.Slots.PlayerSlots)[i].player == (Object)null || ((Il2CppArrayBase<SNet_Slot>)(object)SNet.Slots.PlayerSlots)[i].player.IsBot)).Count();

		public static bool IsLobbyFull => !SNet.Slots.HasFreeHumanSlot();

		public static ulong LobbyID
		{
			get
			{
				SNet_Lobby lobby = SNet.Lobby;
				if (lobby == null)
				{
					return 0uL;
				}
				return lobby.Identifier.ID;
			}
		}

		public static string LobbyName
		{
			get
			{
				SNet_Lobby lobby = SNet.Lobby;
				return ((lobby != null) ? lobby.Identifier.Name : null) ?? string.Empty;
			}
		}

		public static LobbyPrivacySettings PrivacySettings => new LobbyPrivacySettings
		{
			Privacy = LobbySettingsOverride.LobbySettingsManager.CurrentSettings.Privacy,
			HasPassword = LobbySettingsOverride.LobbySettingsManager.CurrentSettings.HasPassword
		};

		public static DetailedLobbyInfo DetailedInfo
		{
			get
			{
				//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_0010: 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_0033: 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_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a6: Expected O, but got Unknown
				DetailedLobbyInfo val = new DetailedLobbyInfo
				{
					Expedition = Expedition,
					ExpeditionName = ExpeditionName
				};
				SNet_Player master = SNet.Master;
				val.HostSteamID = ((master != null) ? master.Lookup : 0);
				val.IsPlayingModded = IsPlayingModded;
				val.MaxPlayerSlots = MaxPlayerSlots;
				val.OpenSlots = OpenSlots;
				val.RegionName = RegionInfo.CurrentRegion.TwoLetterISORegionName;
				val.Revision = Revision;
				SNet_Lobby lobby = SNet.Lobby;
				object obj;
				if (lobby == null)
				{
					obj = null;
				}
				else
				{
					SNet_Lobby_STEAM obj2 = ((Il2CppObjectBase)lobby).TryCast<SNet_Lobby_STEAM>();
					obj = ((obj2 != null) ? SharedUtils.ToSystemList<ulong>(obj2.m_steamIDsInLobby).ToHashSet() : null);
				}
				if (obj == null)
				{
					obj = new HashSet<ulong>();
				}
				val.SteamIDsInLobby = (HashSet<ulong>)obj;
				return val;
			}
		}

		public static LobbyStatusInfo StatusInfo => new LobbyStatusInfo();

		public static LobbyPrivacy GetLobbyTypeFromSNetLobbyType(LobbyType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected I4, but got Unknown
			//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_0021: 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_002a: 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)
			return (LobbyPrivacy)((int)type switch
			{
				3 => 3, 
				0 => 2, 
				2 => 0, 
				1 => 1, 
				_ => 3, 
			});
		}
	}
	internal class PauseManager : MonoBehaviour
	{
		private Coroutine m_pauseUpdateCoroutine;

		private static HashSet<IPauseable> m_pausableUpdaters = new HashSet<IPauseable>();

		private static bool s_isPaused;

		private static IArchiveLogger _logger;

		public static bool IsPaused
		{
			get
			{
				return s_isPaused;
			}
			set
			{
				if (s_isPaused != value)
				{
					s_isPaused = value;
					if (value)
					{
						Current.SetPaused();
					}
					else
					{
						Current.SetUnpaused();
					}
				}
			}
		}

		public static float PauseUpdateInterval => Time.fixedDeltaTime;

		public static PauseManager Current { get; private set; }

		private static IArchiveLogger Logger => _logger ?? (_logger = LoaderWrapper.CreateLoggerInstance("PauseManager", ConsoleColor.White));

		public static event Action OnPaused;

		public static event Action OnUnpaused;

		private void Awake()
		{
			Current = this;
		}

		private void SetPaused()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			if (SNet.IsMaster && (int)GameStateManager.CurrentStateName == 10)
			{
				SNet.Capture.CaptureGameState((eBufferType)4);
			}
			if (m_pauseUpdateCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(m_pauseUpdateCoroutine);
			}
			m_pauseUpdateCoroutine = ((MonoBehaviour)this).StartCoroutine(CollectionExtensions.WrapToIl2Cpp(UpdateRegistered()));
			foreach (IPauseable pausableUpdater in m_pausableUpdaters)
			{
				try
				{
					pausableUpdater.OnPaused();
				}
				catch
				{
				}
			}
			PauseManager.OnPaused?.Invoke();
			Logger.Notice("Game Paused");
		}

		private void SetUnpaused()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Invalid comparison between Unknown and I4
			if (m_pauseUpdateCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(m_pauseUpdateCoroutine);
				m_pauseUpdateCoroutine = null;
			}
			foreach (IPauseable pausableUpdater in m_pausableUpdaters)
			{
				try
				{
					pausableUpdater.OnUnpaused();
				}
				catch
				{
				}
			}
			PauseManager.OnUnpaused?.Invoke();
			if (SNet.IsMaster && (int)GameStateManager.CurrentStateName == 10)
			{
				SNet.Sync.StartRecallWithAllSyncedPlayers((eBufferType)4, false);
			}
			Logger.Notice("Game Unpaused");
		}

		private IEnumerator UpdateRegistered()
		{
			WaitForSecondsRealtime yielder = new WaitForSecondsRealtime(PauseUpdateInterval);
			while (true)
			{
				foreach (IPauseable pausableUpdater in m_pausableUpdaters)
				{
					try
					{
						pausableUpdater.PausedUpdate();
					}
					catch
					{
					}
				}
				yield return yielder;
			}
		}

		public static void RegisterPauseable(IPauseable pu)
		{
			m_pausableUpdaters.Add(pu);
		}

		public static void UnregisterPauseable(IPauseable pu)
		{
			m_pausableUpdaters.Remove(pu);
		}
	}
	public static class PopupMessageManager
	{
		private static IArchiveLogger _logger;

		private static IArchiveLogger Logger;

		private static SNetExt_Packet<pPopupMessage> s_PopupMessagePacket;

		private static readonly Queue<PopupMessage> _popupQueue;

		private static bool _runningAllPopups;

		public static Action EmptyAction { get; private set; }

		public static bool AllowToShowPopup
		{
			get
			{
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Invalid comparison between Unknown and I4
				if (((CM_PageBase)MainMenuGuiLayer.Current.PageRundownNew).m_isActive || ((CM_PageBase)MainMenuGuiLayer.Current.PageLoadout).m_isActive)
				{
					return (int)GameStateManager.CurrentStateName <= 5;
				}
				return false;
			}
		}

		static PopupMessageManager()
		{
			Logger = _logger ?? (_logger = LoaderWrapper.CreateLoggerInstance("PopupMessageManager", ConsoleColor.White));
			EmptyAction = Empty;
			_popupQueue = new Queue<PopupMessage>();
			_runningAllPopups = false;
			s_PopupMessagePacket = SNetExt_Packet<pPopupMessage>.Create(typeof(pPopupMessage).FullName, OnReceivePopupMessage, null, allowSendToLocal: true, (SNet_ChannelType)0);
		}

		internal static void Setup()
		{
			CoroutineManager.StartPersistantCoroutine(CollectionExtensions.WrapToIl2Cpp(ShowAllPopups()));
		}

		private static void OnReceivePopupMessage(ulong sender, pPopupMessage data)
		{
			Logger.Notice($"Receive pPopupMessage from {sender}");
			ShowPopup(data.UnpackPopupMessage());
		}

		public static void SendPopupMessage(pPopupMessage data, params SNet_Player[] players)
		{
			s_PopupMessagePacket.Send(data, players);
		}

		private static void Empty()
		{
		}

		public static void ShowPopup(PopupMessage popupMessage)
		{
			_popupQueue.Enqueue(popupMessage);
		}

		private static IEnumerator ShowAllPopups()
		{
			if (_runningAllPopups)
			{
				yield break;
			}
			_runningAllPopups = true;
			WaitForSeconds yielder = new WaitForSeconds(0.1f);
			yield return yielder;
			while (true)
			{
				try
				{
					if (AllowToShowPopup && _popupQueue.TryDequeue(out var result))
					{
						GlobalPopupMessageManager.ShowPopup(result);
					}
				}
				catch (Exception ex)
				{
					Logger.Error("Failed to show popup.");
					Logger.Exception(ex);
				}
				yield return yielder;
			}
		}
	}
}
namespace Hikaria.Core.Interfaces
{
	public interface IOnAfterLevelCleanup
	{
		void OnAfterLevelCleanup();
	}
	public interface IOnGameStateChanged
	{
		void OnGameStateChanged(eGameStateName preState, eGameStateName nextState);
	}
	public interface IOnMasterChanged
	{
		void OnMasterChanged();
	}
	public interface IOnMasterCommand
	{
		void OnMasterCommand(eMasterCommandType type, int refA);
	}
	public interface IOnPlayerEvent
	{
		void OnPlayerEvent(SNet_Player player, SNet_PlayerEvent playerEvent, SNet_PlayerEventReason reason);
	}
	public interface IOnPlayerModsSynced
	{
		void OnPlayerModsSynced(SNet_Player player, IEnumerable<pModInfo> mods);
	}
	public interface IOnPlayerSlotChanged
	{
		void OnPlayerSlotChanged(SNet_Player player, SNet_SlotType type, SNet_SlotHandleType handle, int index);
	}
	public interface IOnPrepareForRecall
	{
		void OnPrepareForRecall(eBufferType bufferType);
	}
	public interface IOnRecallComplete
	{
		void OnRecallComplete(eBufferType bufferType);
	}
	public interface IOnRecallDone
	{
		void OnRecallDone(eBufferType bufferType);
	}
	public interface IOnReceiveChatMessage
	{
		void OnReceiveChatMessage(SNet_Player player, string message);
	}
	public interface IOnResetSession
	{
		void OnResetSession();
	}
	public interface IOnSessionMemberChanged
	{
		void OnSessionMemberChanged(SNet_Player player, SessionMemberEvent playerEvent);
	}
	public enum SessionMemberEvent
	{
		JoinSessionHub,
		LeftSessionHub
	}
	public interface IPauseable
	{
		void PausedUpdate();

		void OnPaused();

		void OnUnpaused();
	}
}
namespace Hikaria.Core.Features.Security
{
	[AutomatedFeature]
	[DoNotSaveToConfig]
	internal class GlobalBan : Feature
	{
		public class GlobalBanListSettings
		{
			private List<BannedPlayerEntry> _bannedPlayersEnties = new List<BannedPlayerEntry>();

			[FSDisplayName("封禁玩家")]
			public List<BannedPlayerEntry> BannedPlayers
			{
				get
				{
					int i;
					for (i = 0; i < _bannedPlayers.Count; i++)
					{
						if (!_bannedPlayersEnties.Any((BannedPlayerEntry p) => p.SteamID == _bannedPlayers[i].SteamID))
						{
							_bannedPlayersEnties.Add(new BannedPlayerEntry(_bannedPlayers[i]));
						}
					}
					return _bannedPlayersEnties;
				}
				set
				{
				}
			}
		}

		public class BannedPlayerEntry
		{
			[FSSeparator]
			[FSReadOnly(true)]
			[FSDisplayName("SteamID")]
			public ulong SteamID { get; set; }

			[FSReadOnly(true)]
			[FSDisplayName("玩家名称")]
			public string Name { get; set; }

			[FSReadOnly(true)]
			[FSDisplayName("封禁原因")]
			public string Reason { get; set; }

			[FSReadOnly(true)]
			[FSTimestamp("")]
			[FSDisplayName("封禁时间")]
			public long TimeStamp { get; set; }

			public BannedPlayerEntry(BannedPlayer bannedPlayer)
			{
				SteamID = bannedPlayer.SteamID;
				Name = bannedPlayer.Name;
				Reason = bannedPlayer.Reason;
				TimeStamp = bannedPlayer.DateBanned.Ticks;
			}
		}

		private static List<BannedPlayer> _bannedPlayers = new List<BannedPlayer>();

		private static Task<List<BannedPlayer>> _task;

		public override string Name => "在线全局封禁名单";

		public override FeatureGroup Group => EntryPoint.Groups.Security;

		public static IArchiveLogger FeatureLogger { get; set; }

		[FeatureConfig]
		public static GlobalBanListSettings Settings { get; set; }

		public override void OnEnable()
		{
			if (_task == null || _task.IsCompleted || _task.IsFaulted || _task.IsCanceled)
			{
				_task = Task.Run((Func<Task<List<BannedPlayer>>?>)GetBannedPlayers);
			}
		}

		public override void Update()
		{
			//IL_0078: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Expected O, but got Unknown
			if (_task == null || _task.IsCanceled || _task.IsFaulted)
			{
				FeatureManager.DisableAutomatedFeature(typeof(GlobalBan));
			}
			else
			{
				if (!_task.IsCompleted)
				{
					return;
				}
				_bannedPlayers = _task.Result;
				for (int i = 0; i < _bannedPlayers.Count; i++)
				{
					BannedPlayer val = _bannedPlayers[i];
					if (!PlayerLobbyManagement.IsPlayerBanned(val.SteamID))
					{
						PlayerLobbyManagement.Settings.BanList.Add(new BanListEntry
						{
							SteamID = val.SteamID,
							Name = val.Name,
							Timestamp = val.DateBanned.Ticks
						});
						FeatureLogger.Notice($"SteamID: {val.SteamID}, Name: {val.Name}, DateBanned: {val.DateBanned.ToLongDateString()}");
					}
				}
				Feature.MarkSettingsAsDirty<LobbyManagementSettings>(PlayerLobbyManagement.Settings);
				FeatureManager.DisableAutomatedFeature(typeof(GlobalBan));
			}
		}

		private static async Task<List<BannedPlayer>> GetBannedPlayers()
		{
			return await HttpHelper.GetAsync<List<BannedPlayer>>(CoreGlobal.ServerUrl + "/bannedplayers/GetAllBannedPlayers");
		}
	}
	[DisallowInGameToggle]
	[EnableFeatureByDefault]
	internal class LobbySettingsOverride : Feature, IOnSessionMemberChanged
	{
		public class LobbySettingOverrideSettings
		{
			[JsonIgnore]
			[FSDisplayName("Privacy")]
			public LobbyPrivacy Privacy
			{
				get
				{
					//IL_0005: Unknown result type (might be due to invalid IL or missing references)
					return LobbySettingsManager.CurrentSettings.Privacy;
				}
				set
				{
					//IL_0005: 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)
					LobbySettingsManager.CurrentSettings.Privacy = value;
					LobbySettingsManager.OnLobbySettingsChanged();
				}
			}

			[JsonIgnore]
			[FSMaxLength(25)]
			[FSDisplayName("Password")]
			public string Password
			{
				get
				{
					return LobbySettingsManager.CurrentSettings.Password;
				}
				set
				{
					LobbySettingsManager.CurrentSettings.Password = value;
					LobbySettingsManager.OnLobbySettingsChanged();
				}
			}

			[JsonIgnore]
			[FSHeader("Join Other Lobby", true)]
			[FSMaxLength(25)]
			[FSDisplayName("Password For Join Other Lobby")]
			public string PasswordForJoinOthers
			{
				get
				{
					return LobbySettingsManager.PasswordForJoinOtherLobby;
				}
				set
				{
					LobbySettingsManager.PasswordForJoinOtherLobby = value;
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class SNet_SessionHub__SlaveSendSessionQuestion__Patch
		{
			private static void Prefix(SlaveSessionQuestion question)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				LobbySettingsManager.SlaveSendSessionRequest(question);
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class SNet_SessionHub__OnSlaveQuestion__Patch
		{
			private static bool Prefix(pSlaveQuestion data)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				return LobbySettingsManager.OnSlaveQuestionOverride(data);
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class SNet_LobbyManager__CreateLobby__Patch
		{
			private static void Prefix(ref SNet_LobbySettings settings)
			{
				if (settings != null)
				{
					LobbySettingsManager.ApplyLobbySettings(ref settings);
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class SteamMatchmaking__InviteUserToLobby__Patch
		{
			private static void Postfix(CSteamID steamIDInvitee)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				LobbySettingsManager.WhitelistPlayer(steamIDInvitee.m_SteamID);
			}
		}

		public static class LobbySettingsManager
		{
			public enum SlaveRequest : byte
			{
				WantsToJoin,
				Leaving
			}

			public enum MasterAnswer : byte
			{
				LeaveLobby,
				AllowToJoin
			}

			[Flags]
			public enum MasterAnswerReason
			{
				None = 0,
				Public = 1,
				Banned = 2,
				PasswordMismatch = 3,
				IsNotFriend = 4,
				InvisibleLobby = 5,
				PasswordMatch = 6,
				IsFriend = 7,
				Whitelist = 8
			}

			public struct pSlaveRequest
			{
				public SlaveRequest Request;

				[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 25)]
				public string Password;

				public pSlaveRequest(SlaveRequest question, string password = "")
				{
					Request = question;
					if (password == null)
					{
						password = string.Empty;
					}
					Password = password.Substring(0, Math.Min(password.Length, 25));
				}
			}

			public struct pLobbyMasterAnswer
			{
				public LobbyPrivacy LobbyPrivacy;

				public MasterAnswer Answer;

				public MasterAnswerReason Reason;

				public pLobbyMasterAnswer(LobbyPrivacy privacy, MasterAnswer answer, MasterAnswerReason reason)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0002: Unknown result type (might be due to invalid IL or missing references)
					LobbyPrivacy = privacy;
					Answer = answer;
					Reason = reason;
				}
			}

			public class LobbySettings
			{
				public LobbyPrivacy Privacy;

				public const int PASSWORD_MAX_LENGTH = 25;

				private string _password = string.Empty;

				public string LobbyName { get; set; }

				public string Password
				{
					get
					{
						return _password;
					}
					set
					{
						if (value == null)
						{
							value = string.Empty;
						}
						value = value.Substring(0, Math.Min(value.Length, 25));
						_password = value;
						HasPassword = !string.IsNullOrEmpty(_password);
					}
				}

				public bool HasPassword { get; private set; }

				public LobbyType Type => ToSNetLobbyType(Privacy);
			}

			private static IArchiveLogger _logger;

			private static SNetExt_Packet<pSlaveRequest> s_slaveSessionRequestPacket;

			private static SNetExt_Packet<pLobbyMasterAnswer> s_lobbySettingsAnswerPacket;

			private static Dictionary<ulong, pSlaveRequest> s_receivedSlaveRequestsLookup = new Dictionary<ulong, pSlaveRequest>();

			private static HashSet<ulong> s_tempWhitelist = new HashSet<ulong>();

			private static string _passwordForJoinOthers = string.Empty;

			private static IArchiveLogger Logger => _logger ?? (_logger = LoaderWrapper.CreateLoggerInstance("LobbySettingsManager", ConsoleColor.White));

			public static LobbySettings CurrentSettings { get; private set; } = new LobbySettings();


			public static SNet_Lobby_STEAM SteamLobby
			{
				get
				{
					SNet_Lobby lobby = SNet.Lobby;
					if (lobby == null)
					{
						return null;
					}
					return ((Il2CppObjectBase)lobby).TryCast<SNet_Lobby_STEAM>();
				}
			}

			public static SNet_Core_STEAM Core => ((Il2CppObjectBase)SNet.Core).TryCast<SNet_Core_STEAM>();

			public static string PasswordForJoinOtherLobby
			{
				get
				{
					return _passwordForJoinOthers;
				}
				set
				{
					if (value == null)
					{
						value = string.Empty;
					}
					value = value.Substring(0, Math.Min(value.Length, 25));
					_passwordForJoinOthers = value;
				}
			}

			private static PopupMessage Popup_Banned => new PopupMessage
			{
				BlinkInContent = true,
				BlinkTimeInterval = 0.5f,
				Header = LocalizationService.Get(1u),
				UpperText = "<color=red>无法加入大厅</color>\n\n原因:被封禁的玩家",
				LowerText = string.Empty,
				PopupType = (PopupType)3,
				OnCloseCallback = Action.op_Implicit((Action)delegate
				{
					if (SNet.LocalPlayer.IsOutOfSync)
					{
						SNet.SessionHub.LeaveHub(false);
					}
				})
			};

			private static PopupMessage Popup_InvisibleLobby => new PopupMessage
			{
				BlinkInContent = true,
				BlinkTimeInterval = 0.5f,
				Header = LocalizationService.Get(1u),
				UpperText = "<color=red>无法加入大厅</color>\n\n原因:大厅已锁定",
				LowerText = string.Empty,
				PopupType = (PopupType)3,
				OnCloseCallback = Action.op_Implicit((Action)delegate
				{
					if (SNet.LocalPlayer.IsOutOfSync)
					{
						SNet.SessionHub.LeaveHub(false);
					}
				})
			};

			private static PopupMessage Popup_PasswordMismatch => new PopupMessage
			{
				BlinkInContent = true,
				BlinkTimeInterval = 0.5f,
				Header = LocalizationService.Get(1u),
				UpperText = "<color=red>无法加入大厅</color>\n\n原因:密码错误",
				LowerText = string.Empty,
				PopupType = (PopupType)3,
				OnCloseCallback = Action.op_Implicit((Action)delegate
				{
					if (SNet.LocalPlayer.IsOutOfSync)
					{
						SNet.SessionHub.LeaveHub(false);
					}
				})
			};

			private static PopupMessage Popup_IsNotFriend => new PopupMessage
			{
				BlinkInContent = true,
				BlinkTimeInterval = 0.5f,
				Header = LocalizationService.Get(1u),
				UpperText = "<color=red>无法加入大厅</color>\n\n原因:您不是房主好友",
				LowerText = string.Empty,
				PopupType = (PopupType)3,
				OnCloseCallback = Action.op_Implicit((Action)delegate
				{
					if (SNet.LocalPlayer.IsOutOfSync)
					{
						SNet.SessionHub.LeaveHub(false);
					}
				})
			};

			public static void Setup()
			{
				s_slaveSessionRequestPacket = SNetExt_Packet<pSlaveRequest>.Create(typeof(pSlaveRequest).FullName, OnReceiveSlaveRequest, null, allowSendToLocal: false, (SNet_ChannelType)0);
				s_lobbySettingsAnswerPacket = SNetExt_Packet<pLobbyMasterAnswer>.Create(typeof(pLobbyMasterAnswer).FullName, OnReceiveLobbySettingsAnswer, null, allowSendToLocal: false, (SNet_ChannelType)0);
			}

			public static void ApplyLobbySettings(ref SNet_LobbySettings settings)
			{
				//IL_0018: 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)
				settings.Password = CurrentSettings.Password;
				settings.LobbyType = ToSNetLobbyType(CurrentSettings.Privacy);
				settings.LobbyName = CurrentSettings.LobbyName;
			}

			public static void OnLobbySettingsChanged()
			{
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				if (SNet.IsInLobby && SNet.IsMaster && !((Object)(object)SteamLobby == (Object)null))
				{
					SNet_LobbySettings lastLobbySettings = Core.m_lastLobbySettings;
					lastLobbySettings.Password = CurrentSettings.Password;
					lastLobbySettings.LobbyType = ToSNetLobbyType(CurrentSettings.Privacy);
					lastLobbySettings.LobbyName = CurrentSettings.LobbyName;
					((SNet_Lobby)SteamLobby).Password = CurrentSettings.Password;
					SteamLobby.Name = CurrentSettings.LobbyName;
					((SNet_Lobby)SteamLobby).Identifier.Name = CurrentSettings.LobbyName;
				}
			}

			private static void OnReceiveSlaveRequest(ulong sender, pSlaveRequest data)
			{
				if (SNet.IsMaster)
				{
					s_receivedSlaveRequestsLookup[sender] = data;
				}
			}

			private static void OnReceiveLobbySettingsAnswer(ulong sender, pLobbyMasterAnswer data)
			{
				//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_0031: 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_0045: Expected I4, but got Unknown
				if (!SNet.Replication.IsLastSenderMaster() || data.Answer != 0)
				{
					return;
				}
				if (data.Reason == MasterAnswerReason.Banned)
				{
					PopupMessageManager.ShowPopup(Popup_Banned);
					return;
				}
				LobbyPrivacy lobbyPrivacy = data.LobbyPrivacy;
				switch (lobbyPrivacy - 1)
				{
				case 2:
					PopupMessageManager.ShowPopup(Popup_InvisibleLobby);
					break;
				case 1:
					if (data.Reason == MasterAnswerReason.PasswordMismatch)
					{
						PopupMessageManager.ShowPopup(Popup_PasswordMismatch);
					}
					break;
				case 0:
					if (data.Reason == MasterAnswerReason.IsNotFriend)
					{
						PopupMessageManager.ShowPopup(Popup_IsNotFriend);
					}
					break;
				}
			}

			public static void SlaveSendSessionRequest(SlaveSessionQuestion question)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				if (SNet.HasMaster && (int)question == 0)
				{
					s_slaveSessionRequestPacket.Send(new pSlaveRequest(SlaveRequest.WantsToJoin, PasswordForJoinOtherLobby), SNet.Master);
				}
			}

			public static bool OnSlaveQuestionOverride(pSlaveQuestion data)
			{
				//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)
				//IL_0080: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				if (!SNet.IsMaster || !SNet.LocalPlayer.IsInSessionHub || (int)data.question != 0)
				{
					return true;
				}
				SNet_Player val = default(SNet_Player);
				if (!SNet.Core.TryGetPlayer(SNet.Replication.LastSenderID, ref val, true))
				{
					return false;
				}
				if (val.IsLocal)
				{
					return true;
				}
				if (!IsPlayerAllowedToJoinLobby(val, out var reason))
				{
					s_lobbySettingsAnswerPacket.Send(new pLobbyMasterAnswer(CurrentSettings.Privacy, MasterAnswer.LeaveLobby, reason), val);
					SNet.SessionHub.RemovePlayerFromSession(val, true);
					return false;
				}
				s_lobbySettingsAnswerPacket.Send(new pLobbyMasterAnswer(CurrentSettings.Privacy, MasterAnswer.AllowToJoin, reason), val);
				return true;
			}

			public static void DoPlayerLeftCleanup(SNet_Player player)
			{
				if (player.IsLocal)
				{
					s_tempWhitelist.Clear();
					s_receivedSlaveRequestsLookup.Clear();
				}
				else
				{
					s_tempWhitelist.Remove(player.Lookup);
				}
			}

			public static void WhitelistPlayer(ulong steamid)
			{
				s_tempWhitelist.Add(steamid);
			}

			public static bool IsPlayerAllowedToJoinLobby(SNet_Player player, out MasterAnswerReason reason)
			{
				//IL_0085: Unknown result type (might be due to invalid IL or missing references)
				//IL_008a: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a1: Expected I4, but got Unknown
				string name = player.GetName();
				if (PlayerLobbyManagement.IsPlayerBanned(player.Lookup))
				{
					reason = MasterAnswerReason.Banned;
					Logger.Notice($"Player {name} failed to join. Reason: {reason}.");
					return false;
				}
				if (s_tempWhitelist.Contains(player.Lookup))
				{
					reason = MasterAnswerReason.Whitelist;
					return true;
				}
				LobbyPrivacy privacy = CurrentSettings.Privacy;
				switch ((int)privacy)
				{
				case 3:
					reason = MasterAnswerReason.InvisibleLobby;
					Logger.Notice($"Player {name} failed to join. Reason: {reason}.");
					return false;
				case 1:
					if (!SharedUtils.IsFriend(player))
					{
						reason = MasterAnswerReason.IsNotFriend;
						Logger.Notice($"Player {name} failed to join. Reason: {reason}.");
						return false;
					}
					reason = MasterAnswerReason.IsFriend;
					return true;
				case 2:
				{
					if (!CurrentSettings.HasPassword)
					{
						reason = MasterAnswerReason.Public;
						return true;
					}
					if (s_receivedSlaveRequestsLookup.TryGetValue(player.Lookup, out var value) && value.Password == CurrentSettings.Password)
					{
						reason = MasterAnswerReason.PasswordMatch;
						return true;
					}
					reason = MasterAnswerReason.PasswordMismatch;
					Logger.Notice($"Player {name} failed to join. Reason: {reason}. Lobby: {CurrentSettings.Password}, Slave: {value.Password}");
					return false;
				}
				case 0:
					reason = MasterAnswerReason.Public;
					return true;
				default:
					reason = MasterAnswerReason.None;
					return true;
				}
			}

			public static LobbyType ToSNetLobbyType(LobbyPrivacy privacy)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Expected I4, but got Unknown
				//IL_0019: 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_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_002a: 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)
				return (LobbyType)((int)privacy switch
				{
					0 => 2, 
					2 => 0, 
					1 => 1, 
					3 => 3, 
					_ => 3, 
				});
			}
		}

		public override string Name => "大厅设置覆盖";

		public override string Description => "提供大厅权限和密码的设置。";

		public override FeatureGroup Group => EntryPoint.Groups.Security;

		public static IArchiveLogger FeatureLogger { get; set; }

		public static ILocalizationService LocalizationService { get; private set; }

		public override Type[] LocalizationExternalTypes => new Type[1] { typeof(LobbyPrivacy) };

		[FeatureConfig]
		public static LobbySettingOverrideSettings Settings { get; set; }

		public override void OnFeatureSettingChanged(FeatureSetting setting)
		{
			if (SNet.IsMaster && SNet.IsInLobby)
			{
				LiveLobbyList.UpdateLobbyPrivacySettings(((Il2CppObjectBase)SNet.Lobby).TryCast<SNet_Lobby_STEAM>());
			}
		}

		public override void Init()
		{
			LocalizationService = ((Feature)this).Localization;
			LobbySettingsManager.Setup();
		}

		public void OnSessionMemberChanged(SNet_Player player, SessionMemberEvent playerEvent)
		{
			if (playerEvent == SessionMemberEvent.LeftSessionHub)
			{
				LobbySettingsManager.DoPlayerLeftCleanup(player);
			}
		}
	}
}
namespace Hikaria.Core.Features.Fixes
{
	[EnableFeatureByDefault]
	internal class EnemyDamageSync : Feature
	{
		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class Dam_EnemyDamageBase__ProcessReceivedDamage__Patch
		{
			private static void Postfix(Dam_EnemyDamageBase __instance)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				if (SNet.IsMaster)
				{
					pSetHealthData val = default(pSetHealthData);
					((SFloat16)(ref val.health)).Set(((Dam_SyncedDamageBase)__instance).Health, ((Dam_SyncedDamageBase)__instance).HealthMax);
					((Dam_SyncedDamageBase)__instance).m_setHealthPacket.Send(val, (SNet_ChannelType)4);
				}
			}
		}

		public override string Name => "敌人生命值同步";

		public override string Description => "使客机可以获取敌人的实时生命值。\n在作为主机时启用后会将敌人生命值同步至客机,该功能应保持启用。";

		public override FeatureGroup Group => EntryPoint.Groups.Fixes;
	}
	[EnableFeatureByDefault]
	internal class LobbyGhostPlayerFix : Feature, IOnSessionMemberChanged
	{
		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class SNet_PlayerSlotManager__SetSlotPermission__Patch
		{
			private static void Postfix(SNet_PlayerSlotManager __instance, int playerIndex, SlotPermission permission)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Invalid comparison between Unknown and I4
				if (SNet.IsMaster && (int)permission == 1)
				{
					CleanupForPlayer(((Il2CppArrayBase<SNet_Slot>)(object)__instance.PlayerSlots)[playerIndex].player);
				}
			}
		}

		public override string Name => "卡房修复";

		public override string Description => "在玩家离开大厅时自动检查是否有位置被卡,另外可通过锁定位置的方法手动修复特定位置被卡的问题。";

		public override FeatureGroup Group => EntryPoint.Groups.Fixes;

		public override void OnEnable()
		{
			GameEventAPI.RegisterSelf(this);
		}

		public override void OnDisable()
		{
			GameEventAPI.UnregisterSelf(this);
		}

		public void OnSessionMemberChanged(SNet_Player player, SessionMemberEvent playerEvent)
		{
			if (SNet.IsMaster && !player.IsLocal && playerEvent == SessionMemberEvent.LeftSessionHub && CheckNeedCleanup(player))
			{
				CleanupForPlayer(player);
			}
		}

		private static bool CheckNeedCleanup(SNet_Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			SNet_PlayerSlotManager slots = SNet.Slots;
			for (int i = 0; i < ((Il2CppArrayBase<SNet_Slot>)(object)slots.CharacterSlots).Count; i++)
			{
				SNet_Slot val = ((Il2CppArrayBase<SNet_Slot>)(object)slots.CharacterSlots)[i];
				if ((Object)(object)val.player != (Object)null && val.player.Lookup == player.Lookup)
				{
					return true;
				}
			}
			for (int j = 0; j < ((Il2CppArrayBase<SNet_Slot>)(object)slots.PlayerSlots).Count; j++)
			{
				SNet_Slot val2 = ((Il2CppArrayBase<SNet_Slot>)(object)slots.PlayerSlots)[j];
				if ((Object)(object)val2.player != (Object)null && val2.player.Lookup == player.Lookup)
				{
					return true;
				}
			}
			for (int k = 0; k < SNet.Lobby.Players.Count; k++)
			{
				if (SNet.Lobby.Players[k].Lookup == player.Lookup)
				{
					return true;
				}
			}
			return false;
		}

		private static void CleanupForPlayer(SNet_Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			SNet_PlayerSlotManager slots = SNet.Slots;
			SNet.Sync.KickPlayer(player, (SNet_PlayerEventReason)1);
			for (int i = 0; i < ((Il2CppArrayBase<SNet_Slot>)(object)slots.CharacterSlots).Count; i++)
			{
				SNet_Slot val = ((Il2CppArrayBase<SNet_Slot>)(object)slots.CharacterSlots)[i];
				if ((Object)(object)val.player != (Object)null && val.player.Lookup == player.Lookup)
				{
					slots.Internal_ManageSlot(player, ref val, slots.CharacterSlots, (SNet_SlotType)1, (SNet_SlotHandleType)2, -1);
				}
			}
			for (int j = 0; j < ((Il2CppArrayBase<SNet_Slot>)(object)slots.PlayerSlots).Count; j++)
			{
				SNet_Slot val2 = ((Il2CppArrayBase<SNet_Slot>)(object)slots.PlayerSlots)[j];
				if ((Object)(object)val2.player != (Object)null && val2.player.Lookup == player.Lookup)
				{
					slots.Internal_ManageSlot(player, ref val2, slots.PlayerSlots, (SNet_SlotType)0, (SNet_SlotHandleType)2, -1);
				}
			}
			SNet.Lobby.Players.RemoveAll(Predicate<SNet_Player>.op_Implicit((Func<SNet_Player, bool>)((SNet_Player p) => p.Lookup == player.Lookup)));
		}
	}
}
namespace Hikaria.Core.Features.Dev
{
	[EnableFeatureByDefault]
	[DisallowInGameToggle]
	[HideInModSettings]
	internal class CoreBootstrap : Feature
	{
		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class SNet_Player__SendAllCustomData__Patch
		{
			private static void Postfix(SNet_Player __instance, SNet_Player toPlayer)
			{
				SNetExt.SendAllCustomData(__instance, toPlayer);
			}
		}

		private const string CompsObjName = "Hikaria.Core.Comps.obj";

		private static GameObject CompsObj;

		public override string Name => "核心引导";

		public override string Description => "负责一些主要部件的初始化和钩子";

		public override FeatureGroup Group => EntryPoint.Groups.Dev;

		public override void Init()
		{
			ClassInjector.RegisterTypeInIl2Cpp<ChatManager>(false);
			ClassInjector.RegisterTypeInIl2Cpp<GameEventLogManager>(false);
			ClassInjector.RegisterTypeInIl2Cpp<PauseManager>(false);
		}

		public override void OnGameDataInitialized()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			if ((Object)(object)CompsObj == (Object)null)
			{
				CompsObj = new GameObject("Hikaria.Core.Comps.obj");
				Object.DontDestroyOnLoad((Object)(object)CompsObj);
			}
			if ((Object)(object)CompsObj.GetComponent<PauseManager>() == (Object)null)
			{
				CompsObj.AddComponent<PauseManager>();
			}
			if ((Object)(object)CompsObj.GetComponent<ChatManager>() == (Object)null)
			{
				CompsObj.AddComponent<ChatManager>();
			}
			if ((Object)(object)CompsObj.GetComponent<GameEventLogManager>() == (Object)null)
			{
				CompsObj.AddComponent<GameEventLogManager>();
			}
			PopupMessageManager.Setup();
			FeatureManager.EnableAutomatedFeature(typeof(GlobalBan));
		}
	}
	[EnableFeatureByDefault]
	[HideInModSettings]
	[DisallowInGameToggle]
	internal class CoreSettings : Feature
	{
		public class CoreSettingsSettings
		{
			[FSDisplayName("使用第三方服务器")]
			public bool UseThirdPartyServer
			{
				get
				{
					return CoreGlobal.UseThirdPartyServer;
				}
				set
				{
					CoreGlobal.UseThirdPartyServer = value;
				}
			}

			[FSDisplayName("第三方服务器链接")]
			public string ThirdPartyServerUrl
			{
				get
				{
					return CoreGlobal.ThirdPartyServerUrl;
				}
				set
				{
					CoreGlobal.ThirdPartyServerUrl = value;
				}
			}
		}

		public override string Name => "Core Settings";

		public override FeatureGroup Group => EntryPoint.Groups.Dev;

		public override bool RequiresRestart => true;

		[FeatureConfig]
		public static CoreSettingsSettings Settings { get; set; }

		public override void Init()
		{
			Task.Run(delegate
			{
				while (CoreGlobal.ServerOnline)
				{
					CoreGlobal.CheckIsServerOnline();
					Thread.Sleep(TimeSpan.FromMinutes(5.0));
				}
			});
		}

		public override void OnFeatureSettingChanged(FeatureSetting setting)
		{
			CoreGlobal.CheckIsServerOnline();
		}
	}
	[EnableFeatureByDefault]
	[DisallowInGameToggle]
	[HideInModSettings]
	internal class GameEventListener : Feature
	{
		private class SNet_PlayerSlotManager__Internal_ManageSlot__NativeDetour : EasyDetourBase<SNet_PlayerSlotManager__Internal_ManageSlot__NativeDetour.Internal_ManageSlotDel>
		{
			public unsafe delegate bool Internal_ManageSlotDel(IntPtr instancePtr, IntPtr playerPtr, IntPtr slotPtr, IntPtr slotsPtr, SNet_SlotType type, SNet_SlotHandleType handle, int index, Il2CppMethodInfo* methodInfo);

			public unsafe override Internal_ManageSlotDel DetourTo => Detour;

			public override DetourDescriptor Descriptor
			{
				get
				{
					DetourDescriptor result = default(DetourDescriptor);
					result.Type = typeof(SNet_PlayerSlotManager);
					result.MethodName = "Internal_ManageSlot";
					result.ArgTypes = new Type[6]
					{
						typeof(SNet_Player),
						typeof(SNet_Slot),
						typeof(Il2CppReferenceArray<SNet_Slot>),
						typeof(SNet_SlotType),
						typeof(SNet_SlotHandleType),
						typeof(int)
					};
					result.ReturnType = typeof(bool);
					result.IsGeneric = false;
					return result;
				}
			}

			private unsafe bool Detour(IntPtr instancePtr, IntPtr playerPtr, IntPtr slotPtr, IntPtr slotsPtr, SNet_SlotType type, SNet_SlotHandleType handle, int index, Il2CppMethodInfo* methodInfo)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Expected O, but got Unknown
				bool result = base.Original(instancePtr, playerPtr, slotPtr, slotsPtr, type, handle, index, methodInfo);
				OnPlayerSlotChangedM(new SNet_Player(playerPtr), type, handle, index);
				return result;
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class SNet_GlobalManager__Setup__Patch
		{
			private static void Postfix()
			{
				SNet_Events.OnMasterCommand += Action<pMasterCommand>.op_Implicit((Action<pMasterCommand>)OnMasterCommandM);
				SNet_Events.OnPlayerEvent += Action<SNet_Player, SNet_PlayerEvent, SNet_PlayerEventReason>.op_Implicit((Action<SNet_Player, SNet_PlayerEvent, SNet_PlayerEventReason>)OnPlayerEventM);
				SNet_Events.OnRecallComplete += Action<eBufferType>.op_Implicit((Action<eBufferType>)OnRecallCompleteM);
				SNet_Events.OnMasterChanged += Action.op_Implicit((Action)OnMasterChangedM);
				SNet_Events.OnPrepareForRecall += Action<eBufferType>.op_Implicit((Action<eBufferType>)OnPrepareForRecallM);
				SNet_Events.OnResetSessionEvent += Action.op_Implicit((Action)OnResetSessionM);
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class GS_AfterLevel__CleanupAfterExpedition__Patch
		{
			private static void Postfix()
			{
				CleanupAfterExpeditionM();
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class SNet_SyncManager__OnRecallDone__Patch
		{
			private static void Postfix(eBufferType bufferType)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				OnRecallDoneM(bufferType);
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class SNet_SessionHub__AddPlayerToSession__Patch
		{
			private static void Postfix(SNet_Player player)
			{
				OnSessionMemberChangedM(player, SessionMemberEvent.JoinSessionHub);
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class GameStateManager__DoChangeState__Patch
		{
			private static eGameStateName preState;

			private static void Prefix(GameStateManager __instance)
			{
				//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)
				preState = __instance.m_currentStateName;
			}

			private static void Postfix(eGameStateName nextState)
			{
				//IL_0016: 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_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				foreach (IOnGameStateChanged gameStateChangeListener in GameStateChangeListeners)
				{
					try
					{
						gameStateChangeListener.OnGameStateChanged(preState, nextState);
					}
					catch (Exception ex)
					{
						FeatureLogger.Exception(ex);
					}
				}
				try
				{
					GameEventListener.OnGameStateChanged?.Invoke(preState, nextState);
				}
				catch (Exception ex2)
				{
					FeatureLogger.Exception(ex2);
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class PlayerCharManager__DoSendChatMessage__Patch
		{
			private static void Postfix(pChatMessage data)
			{
				//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)
				pPlayer fromPlayer = data.fromPlayer;
				SNet_Player val = default(SNet_Player);
				if (!((pPlayer)(ref fromPlayer)).TryGetPlayer(ref val))
				{
					return;
				}
				foreach (IOnReceiveChatMessage chatMessageListener in ChatMessageListeners)
				{
					try
					{
						chatMessageListener.OnReceiveChatMessage(val, data.message.data);
					}
					catch (Exception ex)
					{
						FeatureLogger.Exception(ex);
					}
				}
				try
				{
					GameEventListener.OnReceiveChatMessage?.Invoke(val, data.message.data);
				}
				catch (Exception ex2)
				{
					FeatureLogger.Exception(ex2);
				}
			}
		}

		private static HashSet<IOnGameStateChanged> GameStateChangeListeners = new HashSet<IOnGameStateChanged>();

		private static HashSet<IOnReceiveChatMessage> ChatMessageListeners = new HashSet<IOnReceiveChatMessage>();

		private static HashSet<IOnPlayerEvent> PlayerEventListeners = new HashSet<IOnPlayerEvent>();

		private static HashSet<IOnRecallComplete> RecallCompleteListeners = new HashSet<IOnRecallComplete>();

		private static HashSet<IOnSessionMemberChanged> SessionMemberChangedListeners = new HashSet<IOnSessionMemberChanged>();

		private static HashSet<IOnMasterChanged> MasterChangedListeners = new HashSet<IOnMasterChanged>();

		private static HashSet<IOnMasterCommand> MasterCommandListeners = new HashSet<IOnMasterCommand>();

		private static HashSet<IOnPlayerSlotChanged> PlayerSlotChangedListener = new HashSet<IOnPlayerSlotChanged>();

		private static HashSet<IOnPrepareForRecall> PrepareForRecallListeners = new HashSet<IOnPrepareForRecall>();

		private static HashSet<IOnRecallDone> RecallDoneListeners = new HashSet<IOnRecallDone>();

		private static HashSet<IOnAfterLevelCleanup> AfterLevelCleanupListeners = new HashSet<IOnAfterLevelCleanup>();

		private static HashSet<IOnResetSession> ResetSessionListeners = new HashSet<IOnResetSession>();

		public override string Name => "游戏事件监听";

		public override string Description => "负责游戏事件的钩子。\n属于核心功能,插件的正常运作离不开该功能。";

		public override FeatureGroup Group => EntryPoint.Groups.Dev;

		public static IArchiveLogger FeatureLogger { get; set; }

		public static event Action OnGameDataInited;

		public static event Action<eBufferType> OnRecallComplete;

		public static event Action<eBufferType> OnPrepareForRecall;

		public static event Action<eBufferType> OnRecallDone;

		public static event Action<eGameStateName, eGameStateName> OnGameStateChanged;

		public static event Action<SNet_Player, string> OnReceiveChatMessage;

		public static event Action<SNet_Player, SNet_PlayerEvent, SNet_PlayerEventReason> OnPlayerEvent;

		public static event Action<SNet_Player, SessionMemberEvent> OnSessionMemberChanged;

		public static event Action OnMasterChanged;

		public static event Action<eMasterCommandType, int> OnMasterCommand;

		public static event Action<SNet_Player, SNet_SlotType, SNet_SlotHandleType, int> OnPlayerSlotChanged;

		public static event Action OnAfterLevelCleanup;

		public static event Action OnResetSession;

		public override void Init()
		{
			EasyDetour.CreateAndApply<SNet_PlayerSlotManager__Internal_ManageSlot__NativeDetour>(out var _);
		}

		private static void CleanupAfterExpeditionM()
		{
			foreach (IOnAfterLevelCleanup afterLevelCleanupListener in AfterLevelCleanupListeners)
			{
				try
				{
					afterLevelCleanupListener.OnAfterLevelCleanup();
				}
				catch (Exception ex)
				{
					FeatureLogger.Exception(ex);
				}
			}
			try
			{
				GameEventListener.OnAfterLevelCleanup?.Invoke();
			}
			catch (Exception ex2)
			{
				FeatureLogger.Exception(ex2);
			}
		}

		private static void OnMasterChangedM()
		{
			foreach (IOnMasterChanged masterChangedListener in MasterChangedListeners)
			{
				try
				{
					masterChangedListener.OnMasterChanged();
				}
				catch (Exception ex)
				{
					FeatureLogger.Exception(ex);
				}
			}
			try
			{
				GameEventListener.OnMasterChanged?.Invoke();
			}
			catch (Exception ex2)
			{
				FeatureLogger.Exception(ex2);
			}
		}

		private static void OnPrepareForRecallM(eBufferType bufferType)
		{
			//IL_0016: 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)
			foreach (IOnPrepareForRecall prepareForRecallListener in PrepareForRecallListeners)
			{
				try
				{
					prepareForRecallListener.OnPrepareForRecall(bufferType);
				}
				catch (Exception ex)
				{
					FeatureLogger.Exception(ex);
				}
			}
			try
			{
				GameEventListener.OnPrepareForRecall?.Invoke(bufferType);
			}
			catch (Exception ex2)
			{
				FeatureLogger.Exception(ex2);
			}
		}

		private static void OnRecallDoneM(eBufferType bufferType)
		{
			//IL_0016: 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)
			foreach (IOnRecallDone recallDoneListener in RecallDoneListeners)
			{
				try
				{
					recallDoneListener.OnRecallDone(bufferType);
				}
				catch (Exception ex)
				{
					FeatureLogger.Exception(ex);
				}
			}
			try
			{
				GameEventListener.OnRecallDone?.Invoke(bufferType);
			}
			catch (Exception ex2)
			{
				FeatureLogger.Exception(ex2);
			}
		}

		private static void OnRecallCompleteM(eBufferType bufferType)
		{
			//IL_0016: 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)
			foreach (IOnRecallComplete recallCompleteListener in RecallCompleteListeners)
			{
				try
				{
					recallCompleteListener.OnRecallComplete(bufferType);
				}
				catch (Exception ex)
				{
					FeatureLogger.Exception(ex);
				}
			}
			try
			{
				GameEventListener.OnRecallComplete?.Invoke(bufferType);
			}
			catch (Exception ex2)
			{
				FeatureLogger.Exception(ex2);
			}
		}

		private static void OnPlayerEventM(SNet_Player player, SNet_PlayerEvent playerEvent, SNet_PlayerEventReason reason)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Invalid comparison between Unknown and I4
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			foreach (IOnPlayerEvent playerEventListener in PlayerEventListeners)
			{
				try
				{
					playerEventListener.OnPlayerEvent(player, playerEvent, reason);
				}
				catch (Exception ex)
				{
					FeatureLogger.Exception(ex);
				}
			}
			try
			{
				GameEventListener.OnPlayerEvent?.Invoke(player, playerEvent, reason);
			}
			catch (Exception ex2)
			{
				FeatureLogger.Exception(ex2);
			}
			if ((int)playerEvent == 0)
			{
				OnSessionMemberChangedM(player, SessionMemberEvent.LeftSessionHub);
			}
		}

		private static void OnPlayerSlotChangedM(SNet_Player player, SNet_SlotType type, SNet_SlotHandleType handle, int index)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			foreach (IOnPlayerSlotChanged item in PlayerSlotChangedListener)
			{
				try
				{
					item.OnPlayerSlotChanged(player, type, handle, index);
				}
				catch (Exception ex)
				{
					FeatureLogger.Exception(ex);
				}
			}
			try
			{
				GameEventListener.OnPlayerSlotChanged?.Invoke(player, type, handle, index);
			}
			catch (Exception ex2)
			{
				FeatureLogger.Exception(ex2);
			}
		}

		private static void OnMasterCommandM(pMasterCommand command)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due

BepInEx/plugins/Hikaria.Core/Hikaria.Core.Entities.dll

Decompiled 7 months ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Hikaria.Core.Entities")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+39283951571722e15e2250552ed931bb16ea9493")]
[assembly: AssemblyProduct("Hikaria.Core.Entities")]
[assembly: AssemblyTitle("Hikaria.Core.Entities")]
[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 Hikaria.Core.Entities
{
	public class BannedPlayer
	{
		[DisplayName("SteamID")]
		public ulong SteamID { get; set; }

		[DisplayName("玩家名称")]
		public string Name { get; set; }

		[DisplayName("封禁原因")]
		public string Reason { get; set; }

		[DisplayName("封禁时间")]
		public DateTime DateBanned { get; set; }
	}
	public class IPLocationInfo
	{
		public string Organization { get; set; }

		public float Longitude { get; set; }

		public string City { get; set; }

		public string Timezone { get; set; }

		public string ISP { get; set; }

		public int Offset { get; set; }

		public string Region { get; set; }

		public int ASN { get; set; }

		public string ASN_Organization { get; set; }

		public string Country { get; set; }

		public string IP { get; set; }

		public float Latitude { get; set; }

		public string Continent_Code { get; set; }

		public string Country_Code { get; set; }

		public string Region_Code { get; set; }
	}
	public class LiveLobby
	{
		public ulong LobbyID { get; set; }

		public string LobbyName { get; set; }

		public LobbyPrivacySettings PrivacySettings { get; set; }

		public DetailedLobbyInfo DetailedInfo { get; set; }

		public LobbyStatusInfo StatusInfo { get; set; }

		public DateTime ExpirationTime { get; set; }

		public LiveLobby()
		{
			LobbyName = string.Empty;
			PrivacySettings = new LobbyPrivacySettings();
			DetailedInfo = new DetailedLobbyInfo();
			StatusInfo = new LobbyStatusInfo();
			ExpirationTime = DateTime.Now.AddSeconds(30.0);
		}

		public LiveLobby(ulong lobbyID, string lobbyName, LobbyPrivacySettings lobbyPrivacySettings, DetailedLobbyInfo detailedInfo)
			: this()
		{
			LobbyID = lobbyID;
			LobbyName = lobbyName;
			PrivacySettings = lobbyPrivacySettings;
			DetailedInfo = detailedInfo;
		}
	}
	public class LobbyPrivacySettings
	{
		private LobbyPrivacy _privacy;

		public LobbyPrivacy Privacy
		{
			get
			{
				if (HasPassword && _privacy == LobbyPrivacy.Private)
				{
					return LobbyPrivacy.Private;
				}
				return _privacy;
			}
			set
			{
				_privacy = value;
			}
		}

		public bool HasPassword { get; set; }
	}
	public class DetailedLobbyInfo
	{
		public ulong HostSteamID { get; set; }

		public string Expedition { get; set; }

		public string ExpeditionName { get; set; }

		public int OpenSlots { get; set; }

		public int MaxPlayerSlots { get; set; }

		public string RegionName { get; set; }

		public int Revision { get; set; }

		public bool IsPlayingModded { get; set; }

		public HashSet<ulong> SteamIDsInLobby { get; set; }

		public DetailedLobbyInfo()
		{
			Expedition = string.Empty;
			ExpeditionName = string.Empty;
			RegionName = string.Empty;
			SteamIDsInLobby = new HashSet<ulong>();
		}
	}
	public class LobbyStatusInfo
	{
		public string StatusInfo { get; set; }

		public LobbyStatusInfo()
		{
			StatusInfo = string.Empty;
		}
	}
	public class LiveLobbyQueryBase
	{
		public virtual bool IgnoreFullLobby { get; set; } = true;


		public virtual bool IsPlayingModded { get; set; }

		public virtual string LobbyName { get; set; } = string.Empty;


		public virtual LobbyPrivacy Privacy { get; set; }

		public virtual string Expedition { get; set; } = string.Empty;


		public virtual string ExpeditionName { get; set; } = string.Empty;


		public virtual string RegionName { get; set; } = string.Empty;


		public virtual int Revision { get; set; } = -1;

	}
	public enum LobbyPrivacy
	{
		Public,
		FriendsOnly,
		Private,
		Invisible
	}
	public class SteamUser
	{
		public ulong SteamID { get; set; }

		public string UserName { get; set; }

		public string Password { get; set; }

		public UserPrivilege Privilege { get; set; }
	}
	[Flags]
	public enum UserPrivilege : ulong
	{
		None = 0uL,
		BanPlayer = 1uL,
		Admin = ulong.MaxValue
	}
}