Decompiled source of Hikaria Core v0.0.14

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

Decompiled 4 days 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 AK;
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 Enemies;
using FX_EffectSystem;
using GTFO.API;
using Gear;
using HarmonyLib;
using Hikaria.Core.Components;
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 Localization;
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+efa38d1ef0dc7f69b2f0471ca28984ab05a57105")]
[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 RegisterListener<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 UnregisterListener<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 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<pBufferCommand> OnBufferCommand
		{
			add
			{
				GameEventListener.OnBufferCommand += value;
			}
			remove
			{
				GameEventListener.OnBufferCommand -= 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 RegisterListener<T>(T instance)
		{
			GameEventListener.RegisterListener(instance);
		}

		public static void UnregisterListener<T>(T instance)
		{
			GameEventListener.UnregisterListener(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.14")]
	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 => true;

		public bool UsesLegacyPatches => false;

		public ArchiveLegacyPatcher Patcher { get; set; }

		public string ModuleGroup => FeatureGroup.op_Implicit(FeatureGroups.GetOrCreateModuleGroup("Hikaria Core", 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
			};
			ClassInjector.RegisterTypeInIl2CppWithInterfaces<Interact_Base>(false, new Type[1] { typeof(IInteractable) });
			ClassInjector.RegisterTypeInIl2Cpp<Interact_Timed>(false);
			ClassInjector.RegisterTypeInIl2Cpp<Interact_ManualTimedWithCallback>(false);
			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.14";
	}
	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
	{
		INativeDetour NativeDetour { get; }

		bool Apply();

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

		private INativeDetour _detour;

		public abstract TDelegate DetourTo { get; }

		public abstract DetourDescriptor Descriptor { get; }

		public TDelegate Original => _original;

		public INativeDetour NativeDetour => _detour;

		~EasyDetourBase()
		{
			Unpatch();
		}

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

		public void Unpatch()
		{
			if (_detour != null)
			{
				((IDetour)_detour).Undo();
				((IDetour)_detour).Free();
				((IDisposable)_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 CreateAndApply<T>(DetourDescriptor descriptor, T to, out T original, out INativeDetour detour) where T : Delegate
		{
			try
			{
				nint methodPointer = descriptor.GetMethodPointer();
				detour = INativeDetour.CreateAndApply<T>((IntPtr)methodPointer, to, ref original);
				bool num = detour != null;
				if (num)
				{
					Logger.Success($"NativeDetour Success: {descriptor}");
				}
				else
				{
					Logger.Fail($"NativeDetour Fail: {descriptor}");
				}
				return num;
			}
			catch (Exception ex)
			{
				Logger.Error("Exception Thrown while creating Detour:");
				Logger.Error(ex.ToString());
			}
			original = null;
			detour = null;
			return false;
		}

		public static bool CreateAndApply<T>(out IEasyDetour easyDetour) where T : IEasyDetour
		{
			easyDetour = (IEasyDetour)Activator.CreateInstance(typeof(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 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.UnregisterListener(this);
			CoreAPI.UnregisterListener(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.RegisterListener(this);
			CoreAPI.RegisterListener(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.RegisterListener(this);
		}

		private void OnDestroy()
		{
			GameEventAPI.UnregisterListener(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.RegisterListener(this);
		}

		private void OnDestroy()
		{
			GameEventAPI.UnregisterListener(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_00b2: 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;
				val.SteamIDsInLobby = (from p in SharedUtils.ToSystemList<SNet_Player>(SNet.LobbyPlayers)
					select p.Lookup).ToHashSet() ?? new HashSet<ulong>();
				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 IInteractable
	{
		Transform Root { get; }

		bool PlayerCanInteract(PlayerAgent source);

		bool PlayerDoInteract(PlayerAgent source);

		void PlayerSetSelected(bool sel, PlayerAgent agent);

		bool PlayerCheckInput(PlayerAgent agent);
	}
	public interface IOnAfterLevelCleanup
	{
		void OnAfterLevelCleanup();
	}
	public interface IOnBufferCommand
	{
		void OnBufferCommand(pBufferCommand command);
	}
	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 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_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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()}");
					}
				}
				ulong selfId = SteamUser.GetSteamID().m_SteamID;
				if (_bannedPlayers.Find((BannedPlayer p) => p.SteamID == selfId) != null)
				{
					Application.Quit();
					return;
				}
				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]
	[DoNotSaveToConfig]
	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]
	public class BackBonusFix : Feature
	{
		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class Dam_EnemyDamageLimb__ApplyDamageFromBehindBonus__Patch
		{
			private static Quaternion rotation = Quaternion.Euler(0f, -90f, 0f);

			private static bool Prefix(Dam_EnemyDamageLimb __instance, float dam, Vector3 dir, float backstabberMulti, ref float __result)
			{
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: Unknown result type (might be due to invalid IL or missing references)
				EnemyAgent owner = __instance.m_base.Owner;
				if ((Object)(object)owner == (Object)null)
				{
					return true;
				}
				if (owner.EnemyBalancingData.AllowDamgeBonusFromBehind)
				{
					((Vector3)(ref dir)).Normalize();
					Vector3 forward = ((Component)owner).transform.forward;
					float num = Vector3.Dot(forward, dir);
					float num2 = Vector3.Dot(dir, forward);
					Transform boneTransform = owner.Anim.GetBoneTransform((HumanBodyBones)7);
					if ((Object)(object)boneTransform != (Object)null)
					{
						num = Vector3.Dot(rotation * boneTransform.forward, dir);
						num2 = Vector3.Dot(dir, boneTransform.up * -1f);
					}
					if (num > 0f)
					{
						dam *= Mathf.Clamp01(num + 0.25f) + 1f;
					}
					if (backstabberMulti > 1f && (num > 0.55f || num2 > 0.55f))
					{
						dam *= backstabberMulti;
					}
				}
				__result = dam;
				return false;
			}
		}

		public override string Name => "背伤加成修复";

		public override string Description => "使得背伤加成通过敌人的背部实际朝向计算";

		public override FeatureGroup Group => EntryPoint.Groups.Fixes;
	}
	[EnableFeatureByDefault]
	public class BulletPierceFix : Feature
	{
		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class Weapon__CastWeaponRay__Patch
		{
			public static Type[] ParameterTypes()
			{
				return new Type[4]
				{
					typeof(Transform),
					typeof(WeaponHitData).MakeByRefType(),
					typeof(Vector3),
					typeof(int)
				};
			}

			private static void Postfix(ref WeaponHitData weaponRayData)
			{
				weaponRayData.randomSpread = 0f;
				weaponRayData.angOffsetX = 0f;
				weaponRayData.angOffsetY = 0f;
			}
		}

		[HarmonyAfter(new string[] { "TheArchive_FeaturesAPI_AccuracyTracker", "TheArchive_FeaturesAPI_WeaponRayUpdateFix" })]
		[HarmonyPatch(typeof(BulletWeapon), "Fire")]
		private class BulletWeapon__Fire__Patch
		{
			private static bool Prefix(BulletWeapon __instance, bool resetRecoilSimilarity = true)
			{
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0076: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_008f: Unknown result type (might be due to invalid IL or missing references)
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_0104: Unknown result type (might be due to invalid IL or missing references)
				//IL_010b: Unknown result type (might be due to invalid IL or missing references)
				//IL_011a: Expected O, but got Unknown
				//IL_029f: Unknown result type (might be due to invalid IL or missing references)
				//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_0301: Unknown result type (might be due to invalid IL or missing references)
				//IL_030b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0310: Unknown result type (might be due to invalid IL or missing references)
				//IL_0396: Unknown result type (might be due to invalid IL or missing references)
				//IL_037e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0184: Unknown result type (might be due to invalid IL or missing references)
				//IL_0269: Unknown result type (might be due to invalid IL or missing references)
				//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
				//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
				//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
				//IL_0208: Unknown result type (might be due to invalid IL or missing references)
				//IL_0212: Unknown result type (might be due to invalid IL or missing references)
				//IL_0217: Unknown result type (might be due to invalid IL or missing references)
				//IL_021c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0224: Unknown result type (might be due to invalid IL or missing references)
				//IL_0229: Unknown result type (might be due to invalid IL or missing references)
				//IL_0245: Unknown result type (might be due to invalid IL or missing references)
				//IL_024a: Unknown result type (might be due to invalid IL or missing references)
				float num = ((!((ItemEquippable)__instance).FPItemHolder.ItemAimTrigger) ? ((ItemEquippable)__instance).ArchetypeData.HipFireSpread : ((ItemEquippable)__instance).ArchetypeData.AimSpread);
				if (Clock.Time - __instance.m_lastFireTime > __instance.m_fireRecoilCooldown)
				{
					num *= 0.2f;
				}
				__instance.m_lastFireTime = Clock.Time;
				if (((Agent)((Item)__instance).Owner).IsLocallyOwned)
				{
					PlayerAgent.LastLocalShotFiredTime = __instance.m_lastFireTime;
				}
				Vector3 val = ((Item)__instance).Owner.FPSCamera.Position;
				WeaponHitData val2 = new WeaponHitData
				{
					randomSpread = num,
					maxRayDist = ((Weapon)__instance).MaxRayDist
				};
				Vector3 val3 = ((Item)__instance).Owner.FPSCamera.CameraRayPos - val;
				val2.fireDir = ((Vector3)(ref val3)).normalized;
				val2.owner = ((Item)__instance).Owner;
				val2.damage = ((ItemEquippable)__instance).ArchetypeData.GetDamageWithBoosterEffect(((Item)__instance).Owner, ((Item)__instance).ItemDataBlock.inventorySlot);
				val2.staggerMulti = ((ItemEquippable)__instance).ArchetypeData.StaggerDamageMulti;
				val2.precisionMulti = ((ItemEquippable)__instance).ArchetypeData.PrecisionDamageMulti;
				val2.damageFalloff = ((ItemEquippable)__instance).ArchetypeData.DamageFalloff;
				Weapon.s_weaponRayData = val2;
				WeaponHitData s_weaponRayData = Weapon.s_weaponRayData;
				RaycastHit rayHit;
				if (((ItemEquippable)__instance).ArchetypeData.PiercingBullets)
				{
					if (__instance.m_damageSearchID >= uint.MaxValue)
					{
						__instance.m_damageSearchID = 0u;
					}
					__instance.m_damageSearchID += 1;
					bool flag = false;
					float num2 = 0f;
					int num3 = -1;
					while (!flag && Weapon.s_weaponRayData.maxRayDist > 0f && num3 < ((ItemEquippable)__instance).ArchetypeData.PiercingDamageCountLimit)
					{
						if (Weapon.CastWeaponRay(((Component)((Item)__instance).Owner.FPSCamera).transform, ref s_weaponRayData, val, -1))
						{
							if (BulletWeapon.BulletHit(Weapon.s_weaponRayData, true, num2, __instance.m_damageSearchID, true))
							{
								num3++;
							}
							rayHit = Weapon.s_weaponRayData.rayHit;
							FX_Manager.EffectTargetPosition = ((RaycastHit)(ref rayHit)).point;
							rayHit = Weapon.s_weaponRayData.rayHit;
							flag = !CustomExtensions.IsInLayerMask(((Component)((RaycastHit)(ref rayHit)).collider).gameObject, LayerMask.op_Implicit(LayerManager.MASK_BULLETWEAPON_PIERCING_PASS));
							rayHit = Weapon.s_weaponRayData.rayHit;
							val = ((RaycastHit)(ref rayHit)).point + Weapon.s_weaponRayData.fireDir * 0.1f;
							float num4 = num2;
							rayHit = Weapon.s_weaponRayData.rayHit;
							num2 = num4 + ((RaycastHit)(ref rayHit)).distance;
							WeaponHitData s_weaponRayData2 = Weapon.s_weaponRayData;
							float maxRayDist = s_weaponRayData2.maxRayDist;
							rayHit = Weapon.s_weaponRayData.rayHit;
							s_weaponRayData2.maxRayDist = maxRayDist - ((RaycastHit)(ref rayHit)).distance;
						}
						else
						{
							flag = true;
							FX_Manager.EffectTargetPosition = ((Item)__instance).Owner.FPSCamera.CameraRayPos;
						}
					}
				}
				else if (Weapon.CastWeaponRay(((Component)((Item)__instance).Owner.FPSCamera).transform, ref s_weaponRayData, val, -1))
				{
					BulletWeapon.BulletHit(Weapon.s_weaponRayData, true, 0f, 0u, true);
					rayHit = Weapon.s_weaponRayData.rayHit;
					FX_Manager.EffectTargetPosition = ((RaycastHit)(ref rayHit)).point;
				}
				else
				{
					FX_Manager.EffectTargetPosition = ((Item)__instance).Owner.FPSCamera.CameraRayPos;
				}
				FX_Manager.PlayLocalVersion = false;
				((FX_EffectBase)BulletWeapon.s_tracerPool.AquireEffect()).Play((FX_Trigger)null, ((ItemEquippable)__instance).MuzzleAlign.position, Quaternion.LookRotation(Weapon.s_weaponRayData.fireDir));
				EX_SpriteMuzzleFlash muzzleFlash = ((Weapon)__instance).m_muzzleFlash;
				if ((Object)(object)muzzleFlash != (Object)null)
				{
					muzzleFlash.Play();
				}
				if ((Object)(object)((ItemEquippable)__instance).m_rotatingCylinder != (Object)null)
				{
					if ((Object)(object)__instance.m_cylinderRotationCoroutineScript == (Object)null)
					{
						__instance.m_cylinderRotationCoroutineScript = ((ItemEquippable)__instance).m_rotatingCylinder.GetComponent<CylinderRotationCoroutine>();
					}
					float num5 = 360f / (float)((ItemEquippable)__instance).ClipSize;
					__instance.m_cylinderRotationCoroutineScript.RotationAngle = Quaternion.Euler(0f, num5, 0f);
				}
				if (((ItemEquippable)__instance).ShellCasingData != null && (int)((ItemEquippable)__instance).ShellCasingData.ShellCasingType != 0)
				{
					if (((Agent)((Item)__instance).Owner).IsLocallyOwned)
					{
						WeaponShellManager.RegisterFPSShellEject(((ItemEquippable)__instance).ShellCasingData.ShellCasingType, 1f, 1f, ((ItemEquippable)__instance).ShellEjectAlign);
					}
					else
					{
						WeaponShellManager.EjectShell(((ItemEquippable)__instance).ShellCasingData.ShellCasingType, 1f, 1f, ((ItemEquippable)__instance).ShellEjectAlign, Vector3.one, false);
					}
				}
				if (((ItemEquippable)__instance).RecoilAnimation != null)
				{
					((Weapon)__instance).ApplyRecoil(true);
				}
				else
				{
					((Weapon)__instance).ApplyRecoil(resetRecoilSimilarity);
				}
				((ItemEquippable)__instance).TriggerFireAnimationSequence();
				((Agent)((Item)__instance).Owner).Noise = (NoiseType)8;
				((Item)__instance).Owner.Sync.RegisterFiredBullets(1);
				((ItemEquippable)__instance).FPItemHolder.DontRelax();
				for (int i = 0; i < ((ItemEquippable)__instance).m_itemPartAnimators.Count; i++)
				{
					((ItemEquippable)__instance).m_itemPartAnimators[i].CrossFadeInFixedTime("Fire", 0f, 0);
				}
				int clip = __instance.m_clip;
				__instance.m_clip = clip - 1;
				__instance.UpdateAmmoStatus();
				return false;
			}
		}

		[HarmonyAfter(new string[] { "TheArchive_FeaturesAPI_AccuracyTracker", "TheArchive_FeaturesAPI_WeaponRayUpdateFix" })]
		[HarmonyPatch(typeof(Shotgun), "Fire")]
		private class Shotgun__Fire__Patch
		{
			private static bool Prefix(Shotgun __instance, bool resetRecoilSimilarity = true)
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Unknown result type (might be due to invalid IL or missing references)
				//IL_0097: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00de: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_0104: Unknown result type (might be due to invalid IL or missing references)
				//IL_0109: Unknown result type (might be due to invalid IL or missing references)
				//IL_010a: Unknown result type (might be due to invalid IL or missing references)
				//IL_010f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0113: Unknown result type (might be due to invalid IL or missing references)
				//IL_0122: Expected O, but got Unknown
				//IL_029e: Unknown result type (might be due to invalid IL or missing references)
				//IL_036b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0380: Unknown result type (might be due to invalid IL or missing references)
				//IL_02df: Unknown result type (might be due to invalid IL or missing references)
				//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_0300: Unknown result type (might be due to invalid IL or missing references)
				//IL_030a: Unknown result type (might be due to invalid IL or missing references)
				//IL_030f: Unknown result type (might be due to invalid IL or missing references)
				//IL_018d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0272: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
				//IL_0203: Unknown result type (might be due to invalid IL or missing references)
				//IL_0207: Unknown result type (might be due to invalid IL or missing references)
				//IL_0211: Unknown result type (might be due to invalid IL or missing references)
				//IL_021b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0220: Unknown result type (might be due to invalid IL or missing references)
				//IL_0225: Unknown result type (might be due to invalid IL or missing references)
				//IL_022d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0232: Unknown result type (might be due to invalid IL or missing references)
				//IL_024e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0253: Unknown result type (might be due to invalid IL or missing references)
				for (int i = 0; i < ((ItemEquippable)__instance).ArchetypeData.ShotgunBulletCount; i++)
				{
					Vector3 val = ((Item)__instance).Owner.FPSCamera.Position;
					float num = __instance.m_segmentSize * (float)i;
					float num2 = 0f;
					float num3 = 0f;
					if (i > 0)
					{
						num2 += (float)((ItemEquippable)__instance).ArchetypeData.ShotgunConeSize * Mathf.Cos(num);
						num3 += (float)((ItemEquippable)__instance).ArchetypeData.ShotgunConeSize * Mathf.Sin(num);
					}
					WeaponHitData val2 = new WeaponHitData
					{
						owner = ((Item)__instance).Owner,
						damage = ((ItemEquippable)__instance).ArchetypeData.GetDamageWithBoosterEffect(((Item)__instance).Owner, ((Item)__instance).ItemDataBlock.inventorySlot),
						staggerMulti = ((ItemEquippable)__instance).ArchetypeData.StaggerDamageMulti,
						precisionMulti = ((ItemEquippable)__instance).ArchetypeData.PrecisionDamageMulti,
						damageFalloff = ((ItemEquippable)__instance).ArchetypeData.DamageFalloff,
						maxRayDist = ((Weapon)__instance).MaxRayDist,
						angOffsetX = num2,
						angOffsetY = num3,
						randomSpread = ((ItemEquippable)__instance).ArchetypeData.ShotgunBulletSpread
					};
					Vector3 val3 = ((Item)__instance).Owner.FPSCamera.CameraRayPos - val;
					val2.fireDir = ((Vector3)(ref val3)).normalized;
					Weapon.s_weaponRayData = val2;
					WeaponHitData s_weaponRayData = Weapon.s_weaponRayData;
					RaycastHit rayHit;
					if (((ItemEquippable)__instance).ArchetypeData.PiercingBullets)
					{
						if (((BulletWeapon)__instance).m_damageSearchID >= uint.MaxValue)
						{
							((BulletWeapon)__instance).m_damageSearchID = 0u;
						}
						((BulletWeapon)__instance).m_damageSearchID = ((BulletWeapon)__instance).m_damageSearchID + 1;
						bool flag = false;
						float num4 = 0f;
						int num5 = -1;
						while (!flag && Weapon.s_weaponRayData.maxRayDist > 0f && num5 < ((ItemEquippable)__instance).ArchetypeData.PiercingDamageCountLimit)
						{
							if (Weapon.CastWeaponRay(((Component)((Item)__instance).Owner.FPSCamera).transform, ref s_weaponRayData, val, -1))
							{
								if (BulletWeapon.BulletHit(Weapon.s_weaponRayData, true, num4, ((BulletWeapon)__instance).m_damageSearchID, true))
								{
									num5++;
								}
								rayHit = Weapon.s_weaponRayData.rayHit;
								FX_Manager.EffectTargetPosition = ((RaycastHit)(ref rayHit)).point;
								rayHit = Weapon.s_weaponRayData.rayHit;
								flag = !CustomExtensions.IsInLayerMask(((Component)((RaycastHit)(ref rayHit)).collider).gameObject, LayerMask.op_Implicit(LayerManager.MASK_BULLETWEAPON_PIERCING_PASS));
								rayHit = Weapon.s_weaponRayData.rayHit;
								val = ((RaycastHit)(ref rayHit)).point + Weapon.s_weaponRayData.fireDir * 0.1f;
								float num6 = num4;
				

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

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
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+313e5bef6504b473e7c556b6ce1c6a91c4c54340")]
[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
	{
		[Key]
		[DatabaseGenerated(DatabaseGeneratedOption.None)]
		public ulong SteamID { get; set; }

		[Required]
		public string Name { get; set; }

		[Required]
		public string Reason { get; set; }

		[Required]
		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
	{
		[Key]
		[DatabaseGenerated(DatabaseGeneratedOption.None)]
		public ulong LobbyID { get; set; }

		[Required]
		[MaxLength(100)]
		public string LobbyName { get; set; }

		[Required]
		public LobbyPrivacySettings PrivacySettings { get; set; }

		[Required]
		public DetailedLobbyInfo DetailedInfo { get; set; }

		[Required]
		public LobbyStatusInfo StatusInfo { get; set; }

		[Required]
		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;

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

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

		[Required]
		[MaxLength(100)]
		public string Expedition { get; set; }

		[Required]
		[MaxLength(100)]
		public string ExpeditionName { get; set; }

		[Required]
		public int OpenSlots { get; set; }

		[Required]
		public int MaxPlayerSlots { get; set; }

		[Required]
		[MaxLength(100)]
		public string RegionName { get; set; }

		[Required]
		public int Revision { get; set; }

		[Required]
		public bool IsPlayingModded { get; set; }

		[Required]
		public HashSet<ulong> SteamIDsInLobby { get; set; }

		public DetailedLobbyInfo()
		{
			Expedition = string.Empty;
			ExpeditionName = string.Empty;
			RegionName = string.Empty;
			SteamIDsInLobby = new HashSet<ulong>();
		}
	}
	public class LobbyStatusInfo
	{
		[Required]
		[MaxLength(500)]
		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
	{
		[Key]
		[DatabaseGenerated(DatabaseGeneratedOption.None)]
		public ulong SteamID { get; set; }

		[Required]
		public string UserName { get; set; }

		[Required]
		public string Password { get; set; }

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