Decompiled source of Hikaria Core v1.0.1

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

Decompiled 6 days ago
using System;
using System.Buffers.Binary;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
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.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using AK;
using Agents;
using AssetShards;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Hook;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using CellMenu;
using CharacterDestruction;
using Clonesoft.Json;
using Clonesoft.Json.Converters;
using Clonesoft.Json.Serialization;
using Enemies;
using FX_EffectSystem;
using GTFO.API;
using GameData;
using GameEvent;
using Gear;
using Hikaria.Core.Components;
using Hikaria.Core.Features.Dev;
using Hikaria.Core.Interfaces;
using Hikaria.Core.Managers;
using Hikaria.Core.SNetworkExt;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Attributes;
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 TheArchive.Core;
using TheArchive.Core.Attributes;
using TheArchive.Core.Attributes.Feature;
using TheArchive.Core.Attributes.Feature.Members;
using TheArchive.Core.Attributes.Feature.Patches;
using TheArchive.Core.Attributes.Feature.Settings;
using TheArchive.Core.Bootstrap;
using TheArchive.Core.FeaturesAPI;
using TheArchive.Core.FeaturesAPI.Groups;
using TheArchive.Core.FeaturesAPI.Settings;
using TheArchive.Core.Localization;
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: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.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 delegate void PlayerModsSynced(SNet_Player player, IEnumerable<pModInfo> mods);

		public static event PlayerModsSynced OnPlayerModsSynced
		{
			add
			{
				CoreAPI_Impl.OnPlayerModsSynced += value;
			}
			remove
			{
				CoreAPI_Impl.OnPlayerModsSynced -= value;
			}
		}

		public static bool IsInstalledMod(string guid, VersionRange range = default(VersionRange))
		{
			if (CoreAPI_Impl.InstalledMods.TryGetValue(guid, out var value))
			{
				return range.Contains(value.Version);
			}
			return false;
		}

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

		public static bool IsPlayerInstalledMod(SNet_Player player, string guid, VersionRange range = default(VersionRange))
		{
			if ((Object)(object)player == (Object)null || player.IsBot)
			{
				return false;
			}
			if (player.IsLocal)
			{
				if (CoreAPI_Impl.InstalledMods.TryGetValue(guid, out var value))
				{
					return range.Contains(value.Version);
				}
				return false;
			}
			if (CoreAPI_Impl.OthersMods.TryGetValue(player.Lookup, out var value2) && value2.TryGetValue(guid, out var value3))
			{
				return range.Contains(value3.Version);
			}
			return false;
		}
	}
	public static class EnemyAPI
	{
		public delegate void EnemyReceivedDamage(EnemyAgent enemy, pFullEnemyReceivedDamageData data);

		public static event Action<Dam_EnemyDamageLimb> OnEnemyLimbDestroyed
		{
			add
			{
				EnemyAPI_Impl.OnEnemyLimbDestroyed += value;
			}
			remove
			{
				EnemyAPI_Impl.OnEnemyLimbDestroyed -= value;
			}
		}

		public static event Action<EnemyAgent> OnEnemyDead
		{
			add
			{
				EnemyAPI_Impl.OnEnemyDead += value;
			}
			remove
			{
				EnemyAPI_Impl.OnEnemyDead -= value;
			}
		}

		public static event Action<EnemyAgent> OnPostEnemyDead
		{
			add
			{
				EnemyAPI_Impl.OnPostEnemyDead += value;
			}
			remove
			{
				EnemyAPI_Impl.OnPostEnemyDead -= value;
			}
		}

		public static event EnemyReceivedDamage OnEnemyReceivedDamage
		{
			add
			{
				EnemyAPI_Impl.OnEnemyReceivedDamage += value;
			}
			remove
			{
				EnemyAPI_Impl.OnEnemyReceivedDamage -= value;
			}
		}

		public static event Action<EnemyAgent> OnEnemySpawned
		{
			add
			{
				EnemyAPI_Impl.OnEnemySpawned += value;
			}
			remove
			{
				EnemyAPI_Impl.OnEnemySpawned -= value;
			}
		}

		public static event Action<EnemyAgent> OnEnemyDespawn
		{
			add
			{
				EnemyAPI_Impl.OnEnemyDespawn += value;
			}
			remove
			{
				EnemyAPI_Impl.OnEnemyDespawn -= value;
			}
		}

		public static event Action<EnemyAgent> OnEnemyDespawnd
		{
			add
			{
				EnemyAPI_Impl.OnEnemyDespawnd += value;
			}
			remove
			{
				EnemyAPI_Impl.OnEnemyDespawnd -= value;
			}
		}
	}
	public static class GameEventAPI
	{
		public static bool IsGamePaused
		{
			get
			{
				return PauseManager.IsPaused;
			}
			set
			{
				PauseManager.IsPaused = value;
			}
		}

		public static event Action OnGameDataInitialized
		{
			add
			{
				GameEventAPI_Impl.OnGameDataInitialized += value;
			}
			remove
			{
				GameEventAPI_Impl.OnGameDataInitialized -= value;
			}
		}

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

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

		public static event Action OnAfterLevelCleanup
		{
			add
			{
				GameEventAPI_Impl.OnAfterLevelCleanup += value;
			}
			remove
			{
				GameEventAPI_Impl.OnAfterLevelCleanup -= 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 class SNetEventAPI
	{
		public static event Action<eBufferType> OnBufferCapture
		{
			add
			{
				SNetEventAPI_Impl.OnBufferCapture += value;
			}
			remove
			{
				SNetEventAPI_Impl.OnBufferCapture -= value;
			}
		}

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

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

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

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

		public static event Action<pBufferCommand> OnBufferCommand
		{
			add
			{
				SNetEventAPI_Impl.OnBufferCommand += value;
			}
			remove
			{
				SNetEventAPI_Impl.OnBufferCommand -= value;
			}
		}

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

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

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

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

		public static event Action<eMasterCommandType, int> OnMasterCommand
		{
			add
			{
				SNetEventAPI_Impl.OnMasterCommand += value;
			}
			remove
			{
				SNetEventAPI_Impl.OnMasterCommand -= value;
			}
		}
	}
	public static class SNetExtAPI
	{
		public static bool TryGetVanillaWrapper(IReplicator vanilla, out SNetExt_Replicator_VanillaWrapper wrapper)
		{
			return SNetExt_Replication.TryGetVanillaWrapper(vanilla, out wrapper);
		}
	}
	public static class WeaponAPI
	{
		public delegate void PreBulletWeaponFire(BulletWeapon bulletWeapon, bool resetRecoilSimilarity);

		public delegate void PostBulletWeaponFire(BulletWeapon bulletWeapon, bool resetRecoilSimilarity);

		public delegate void PreShotgunFire(Shotgun shotgun, bool resetRecoilSimilarity);

		public delegate void PostShotgunFire(Shotgun shotgun, bool resetRecoilSimilarity);

		public static event PreBulletWeaponFire OnPreBulletWeaponFire
		{
			add
			{
				WeaponAPI_Impl.OnPreBulletWeaponFire += value;
			}
			remove
			{
				WeaponAPI_Impl.OnPreBulletWeaponFire -= value;
			}
		}

		public static event PostBulletWeaponFire OnPostBulletWeaponFire
		{
			add
			{
				WeaponAPI_Impl.OnPostBulletWeaponFire += value;
			}
			remove
			{
				WeaponAPI_Impl.OnPostBulletWeaponFire -= value;
			}
		}

		public static event PreShotgunFire OnPreShotgunFire
		{
			add
			{
				WeaponAPI_Impl.OnPreShotgunFire += value;
			}
			remove
			{
				WeaponAPI_Impl.OnPreShotgunFire -= value;
			}
		}

		public static event PostShotgunFire OnPostShotgunFire
		{
			add
			{
				WeaponAPI_Impl.OnPostShotgunFire += value;
			}
			remove
			{
				WeaponAPI_Impl.OnPostShotgunFire -= value;
			}
		}
	}
	public static class CoreGlobal
	{
		public const string GUID = "Hikaria.Core";

		public const string NAME = "HikariaCore";

		public const string VERSION = "1.0.0";

		internal static ILocalizationService Localization { get; private set; }

		internal static JsonSerializerSettings JsonSerializerSettings { get; private set; }

		internal static void Setup(IArchiveModule module)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_004b: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			Localization = module.LocalizationService;
			Logs.Setup(module.Logger);
			JsonSerializerSettings = new JsonSerializerSettings
			{
				Formatting = (Formatting)1,
				ContractResolver = (IContractResolver)new DefaultContractResolver(),
				DateFormatHandling = (DateFormatHandling)1,
				DateFormatString = "yyyy-MM-dd HH:mm:ss",
				NullValueHandling = (NullValueHandling)0
			};
			JsonSerializerSettings.Converters.Add((JsonConverter)new IsoDateTimeConverter
			{
				DateTimeFormat = "yyyy-MM-dd HH:mm:ss"
			});
			JsonSerializerSettings.Converters.Add((JsonConverter)new StringEnumConverter());
		}
	}
	[ArchiveDependency(/*Could not decode attribute arguments.*/)]
	[ArchiveModule("Hikaria.Core", "HikariaCore", "1.0.0")]
	public class EntryPoint : IArchiveModule
	{
		public ILocalizationService LocalizationService { get; set; }

		public IArchiveLogger Logger { get; set; }

		public void Init()
		{
			CoreGlobal.Setup((IArchiveModule)(object)this);
		}
	}
	internal static class Logs
	{
		private static IArchiveLogger _logger;

		public static void Setup(IArchiveLogger logger)
		{
			_logger = logger;
		}

		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 enum SessionMemberEvent
	{
		JoinSessionHub,
		LeftSessionHub
	}
	public enum DamageTraceFlags : uint
	{
		None = 0u,
		Bullet = 1u,
		Melee = 2u,
		Explosion = 4u,
		Fire = 8u,
		Freeze = 0x10u,
		Push = 0x20u,
		SentryGun = 0x40u,
		Player = 0x80u,
		Enemy = 0x100u,
		Decoy = 0x200u,
		Unknown = 0x400u
	}
	public static class SharedExtensions
	{
		public static string[] SplitInChunks(this string str, int length)
		{
			return (from i in Enumerable.Range(0, (int)Math.Ceiling((double)str.Length / (double)length))
				select str.Substring(i * length, Math.Min(length, str.Length - i * length))).ToArray();
		}
	}
	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
	public struct pPopupMessage
	{
		public bool BlinkInContent;

		public float BlinkTimeInterval;

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

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

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		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;
		}
	}
	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
	public struct pModList : ISNetExt_ReplicatedPlayerData
	{
		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
		public pModInfo[] Mods;

		public int ModCount;

		public const int MOD_SYNC_COUNT = 256;

		public pPlayer PlayerData { get; set; }

		public pModList(SNet_Player player, IEnumerable<pModInfo> modList)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			Mods = new pModInfo[256];
			ModCount = 0;
			Array.Fill(Mods, default(pModInfo));
			pPlayer playerData = default(pPlayer);
			((pPlayer)(ref playerData)).SetPlayer(player);
			PlayerData = playerData;
			ModCount = Math.Clamp(modList.Count(), 0, 256);
			for (int i = 0; i < ModCount; i++)
			{
				Mods[i] = modList.ElementAt(i);
			}
		}

		public pModList()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			Mods = new pModInfo[256];
			ModCount = 0;
			Array.Fill(Mods, default(pModInfo));
			PlayerData = default(pPlayer);
		}
	}
	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
	public struct pModInfo
	{
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
		public string Name;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
		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;
		}
	}
	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
	public struct pFullEnemyReceivedDamageData
	{
		public pEnemyAgent enemy;

		public float damage;

		public pAgent damageSource;

		public Vector3 position;

		public Vector3 direction;

		public ES_HitreactType hitreact;

		public bool tryForceHitreact;

		public int limbID;

		public float staggerDamageMulti;

		public DamageNoiseLevel damageNoiseLevel;

		public uint gearCategoryId;

		public bool isKill;

		public uint gearChecksum;

		public DamageTraceFlags damageTraceFlags;

		public pFullEnemyReceivedDamageData(EnemyAgent enemy, bool isKill, float damage, Agent damageSource, Vector3 position, Vector3 direction, ES_HitreactType hitreact, bool tryForceHitreact = false, int limbID = -1, float staggerDamageMulti = 1f, DamageNoiseLevel damageNoiseLevel = 0, uint gearCategoryId = 0u, uint gearChecksum = 0u, DamageTraceFlags damageTraceFlags = DamageTraceFlags.None)
		{
			//IL_0006: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			this.enemy = default(pEnemyAgent);
			this.damage = 0f;
			this.damageSource = default(pAgent);
			this.position = Vector3.zero;
			this.direction = Vector3.zero;
			this.hitreact = (ES_HitreactType)0;
			this.tryForceHitreact = false;
			this.limbID = -1;
			this.staggerDamageMulti = 1f;
			this.damageNoiseLevel = (DamageNoiseLevel)0;
			this.gearCategoryId = 0u;
			this.isKill = false;
			this.gearChecksum = 0u;
			this.damageTraceFlags = DamageTraceFlags.None;
			this.enemy = default(pEnemyAgent);
			((pEnemyAgent)(ref this.enemy)).Set(enemy);
			this.isKill = isKill;
			this.damage = damage;
			this.damageSource = default(pAgent);
			((pAgent)(ref this.damageSource)).Set(damageSource);
			this.position = position;
			this.direction = direction;
			this.hitreact = hitreact;
			this.tryForceHitreact = tryForceHitreact;
			this.limbID = limbID;
			this.staggerDamageMulti = staggerDamageMulti;
			this.damageNoiseLevel = damageNoiseLevel;
			this.gearCategoryId = gearCategoryId;
			this.gearChecksum = gearChecksum;
			this.damageTraceFlags = damageTraceFlags;
		}
	}
	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
	public readonly struct Version : IComparable<Version>, IComparable, IEquatable<Version>
	{
		[CompilerGenerated]
		private sealed class <PartComparisons>d__18 : IEnumerable<int>, IEnumerable, IEnumerator<int>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private int <>2__current;

			private int <>l__initialThreadId;

			public Version <>4__this;

			public Version <>3__<>4__this;

			private Version other;

			public Version <>3__other;

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

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

			[DebuggerHidden]
			public <PartComparisons>d__18(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = <>4__this.Major.CompareTo(other.Major);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = <>4__this.Minor.CompareTo(other.Minor);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>2__current = <>4__this.Patch.CompareTo(other.Patch);
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					return false;
				}
			}

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

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

			[DebuggerHidden]
			IEnumerator<int> IEnumerable<int>.GetEnumerator()
			{
				<PartComparisons>d__18 <PartComparisons>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<PartComparisons>d__ = this;
				}
				else
				{
					<PartComparisons>d__ = new <PartComparisons>d__18(0);
				}
				<PartComparisons>d__.<>4__this = <>3__<>4__this;
				<PartComparisons>d__.other = <>3__other;
				return <PartComparisons>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<int>)this).GetEnumerator();
			}
		}

		public static readonly Version ZeroVersion = new Version(0, 0, 0);

		private static readonly Regex strictRegex = new Regex("^\r\n            \\s*\r\n            ([0-9]+)       # major version\r\n            \\.\r\n            ([0-9]+)       # minor version\r\n            \\.\r\n            ([0-9]+)       # patch version\r\n            \\s*\r\n            $", RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace);

		private readonly int _major;

		private readonly int _minor;

		private readonly int _patch;

		public int Major => _major;

		public int Minor => _minor;

		public int Patch => _patch;

		public Version(string input)
		{
			_major = 0;
			_minor = 0;
			_patch = 0;
			Match match = strictRegex.Match(input);
			if (!match.Success)
			{
				throw new ArgumentException("Invalid version string: " + input + ". Version must be in format 'X.Y.Z' where X, Y, Z are non-negative integers.");
			}
			_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)
			{
				return 1;
			}
			if (obj is Version other)
			{
				return CompareTo(other);
			}
			throw new ArgumentException("Object is not a Version");
		}

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

		[IteratorStateMachine(typeof(<PartComparisons>d__18))]
		private IEnumerable<int> PartComparisons(Version other)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <PartComparisons>d__18(-2)
			{
				<>3__<>4__this = this,
				<>3__other = other
			};
		}

		public override bool Equals(object other)
		{
			if (other == null)
			{
				return false;
			}
			if (other is Version other2)
			{
				return Equals(other2);
			}
			return false;
		}

		public static Version Parse(string input)
		{
			return new Version(input);
		}

		public static bool TryParse(string input, out Version result)
		{
			try
			{
				result = Parse(input);
				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;
		}

		public static implicit operator Version(string versionString)
		{
			return Parse(versionString);
		}

		public VersionRange To(Version maxVersion, bool includeMin = true, bool includeMax = true)
		{
			return new VersionRange(this, maxVersion, includeMin, includeMax);
		}

		public VersionRange AndAbove(bool includeThis = true)
		{
			return VersionRange.GreaterThan(this, includeThis);
		}

		public VersionRange AndBelow(bool includeThis = true)
		{
			return VersionRange.LessThan(this, includeThis);
		}
	}
	public struct VersionRange
	{
		private static readonly Regex RangeRegex = new Regex("^\\s*(?:(?:([\\[\\(])\\s*([0-9]+\\.[0-9]+\\.[0-9]+)\\s*,\\s*([0-9]+\\.[0-9]+\\.[0-9]+)\\s*([\\]\\)]))|(?:([<>]=?)\\s*([0-9]+\\.[0-9]+\\.[0-9]+))|(?:([0-9]+)(?:\\.([0-9]+|x))?(?:\\.([0-9]+|x))?))$", RegexOptions.Compiled);

		public Version Min { get; }

		public Version Max { get; }

		public bool IncludeMin { get; }

		public bool IncludeMax { get; }

		public VersionRange(Version min, Version max, bool includeMin = true, bool includeMax = true)
		{
			if (min.Equals(Version.ZeroVersion) && max.Equals(Version.ZeroVersion))
			{
				throw new ArgumentException("MinVersion 和 MaxVersion 不能同时为 \"0.0.0\"");
			}
			Min = min;
			Max = max;
			IncludeMin = includeMin;
			IncludeMax = includeMax;
		}

		public bool Contains(Version version)
		{
			if (version.Equals(Version.ZeroVersion))
			{
				return false;
			}
			if (!Min.Equals(Version.ZeroVersion))
			{
				int num = version.CompareTo(Min);
				if (num < 0 || (num == 0 && !IncludeMin))
				{
					return false;
				}
			}
			if (!Max.Equals(Version.ZeroVersion))
			{
				int num2 = version.CompareTo(Max);
				if (num2 > 0 || (num2 == 0 && !IncludeMax))
				{
					return false;
				}
			}
			return true;
		}

		public override string ToString()
		{
			string value = (IncludeMin ? "[" : "(");
			string value2 = (IncludeMax ? "]" : ")");
			string value3 = (Min.Equals(Version.ZeroVersion) ? "0.0.0" : Min.ToString());
			string value4 = (Max.Equals(Version.ZeroVersion) ? "∞" : Max.ToString());
			return $"{value}{value3}, {value4}{value2}";
		}

		public static VersionRange Parse(string input)
		{
			if (string.IsNullOrWhiteSpace(input))
			{
				throw new ArgumentException("输入字符串不能为空", "input");
			}
			Match match = RangeRegex.Match(input);
			if (!match.Success)
			{
				throw new ArgumentException("无效的版本范围格式: " + input, "input");
			}
			if (match.Groups[1].Success)
			{
				string value = match.Groups[1].Value;
				string value2 = match.Groups[4].Value;
				bool includeMin = value == "[";
				bool includeMax = value2 == "]";
				string value3 = match.Groups[2].Value;
				string value4 = match.Groups[3].Value;
				Version min = Version.Parse(value3);
				Version max = Version.Parse(value4);
				return new VersionRange(min, max, includeMin, includeMax);
			}
			if (match.Groups[5].Success)
			{
				string value5 = match.Groups[5].Value;
				Version version = Version.Parse(match.Groups[6].Value);
				return value5 switch
				{
					">" => GreaterThan(version, includeMin: false), 
					">=" => GreaterThan(version), 
					"<" => LessThan(version, includeMax: false), 
					"<=" => LessThan(version), 
					_ => throw new ArgumentException("不支持的操作符: " + value5, "input"), 
				};
			}
			int num = int.Parse(match.Groups[7].Value);
			bool flag = match.Groups[8].Success && match.Groups[8].Value != "x";
			int num2 = (flag ? int.Parse(match.Groups[8].Value) : 0);
			bool flag2 = match.Groups[9].Success && match.Groups[9].Value != "x";
			int num3 = (flag2 ? int.Parse(match.Groups[9].Value) : 0);
			Version version2 = new Version(num, flag ? num2 : 0, flag2 ? num3 : 0);
			Version max2 = ((!flag) ? new Version(num + 1, 0, 0) : (flag2 ? version2 : new Version(num, num2 + 1, 0)));
			return new VersionRange(version2, max2, includeMin: true, !max2.Equals(version2));
		}

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

		public static VersionRange GreaterThan(Version minVersion, bool includeMin = true)
		{
			return new VersionRange(minVersion, new Version(0, 0, 0), includeMin, includeMax: false);
		}

		public static VersionRange LessThan(Version maxVersion, bool includeMax = true)
		{
			return new VersionRange(new Version(0, 0, 0), maxVersion, includeMin: false, includeMax);
		}

		public static implicit operator VersionRange(string rangeString)
		{
			return Parse(rangeString);
		}
	}
}
namespace Hikaria.Core.Utility
{
	public static class HttpHelper
	{
		private static readonly HttpClient _httpClient = new HttpClient
		{
			Timeout = TimeSpan.FromSeconds(10.0)
		};

		private static IArchiveLogger _logger = LoaderWrapper.CreateArSubLoggerInstance("HttpHelper", ConsoleColor.White);

		public static async Task<T> GetAsync<T>(string url) where T : new()
		{
			_ = 1;
			try
			{
				HttpResponseMessage obj = await _httpClient.GetAsync(url);
				obj.EnsureSuccessStatusCode();
				return JsonConvert.DeserializeObject<T>(await obj.Content.ReadAsStringAsync(), CoreGlobal.JsonSerializerSettings);
			}
			catch (Exception)
			{
				_logger.Error("Error occurred while sending GET request. [" + url + "]");
				return new T();
			}
		}

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

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

		public static async Task<T> PatchAsync<T>(string url, object content) where T : new()
		{
			_ = 1;
			try
			{
				StringContent content2 = new StringContent(JsonConvert.SerializeObject(content, CoreGlobal.JsonSerializerSettings), Encoding.UTF8, "application/json");
				HttpResponseMessage obj = await _httpClient.PatchAsync(url, content2);
				obj.EnsureSuccessStatusCode();
				return JsonConvert.DeserializeObject<T>(await obj.Content.ReadAsStringAsync(), CoreGlobal.JsonSerializerSettings);
			}
			catch (Exception)
			{
				_logger.Error("Error occurred while sending PATCH request. [" + url + "]");
				return new T();
			}
		}
	}
	public static class Utils
	{
		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 TryGetPlayerByPlayerSlot(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 enum SNetExt_BufferOperationType : byte
	{
		StartReceive,
		StoreGameState,
		RecallGameState
	}
	public enum SNetExt_BufferType : byte
	{
		JoinedHub,
		DropIn,
		RestartLevel,
		Checkpoint,
		Migration_A,
		Migration_B
	}
	public enum SNetExt_CapturePass : byte
	{
		SessionPass,
		FirstPass,
		SecondPass,
		ThirdPass,
		FourthPass,
		Skip
	}
	public enum SNetExt_ReplicatorLifeTime
	{
		NeverDestroyed,
		DestroyedOnLevelReset,
		DynamicallyDestroyed
	}
	public enum SNetExt_ReplicatorType
	{
		Unspecified,
		Manager,
		SelfManaged,
		Dynamic,
		VanillaWrapper
	}
	public interface ICaptureCallbackObject
	{
		bool PersistAcrossSession { get; }

		void OnStateCapture();
	}
	public interface ISNetExt_DynamicReplication
	{
		pReplicationData ReplicationData { get; set; }

		Vector3 Position { get; set; }

		Quaternion Rotation { get; set; }
	}
	public interface ISNetExt_DynamicReplicatorSupplier<T> : ISNetExt_ReplicatorSupplier where T : struct, ISNetExt_DynamicReplication
	{
		void OnDespawn();

		void OnSpawn(T spawnData);

		bool TryCollectCaptureData(ref T spawnData, out SNetExt_CapturePass captureType);
	}
	public interface ISNetExt_Manager
	{
		void Setup();

		void SetupReplication();

		void OnResetSession();

		void OnValidateMasterData();
	}
	internal interface ISNetExt_MutableReplicator : ISNetExt_Replicator
	{
		void AssignKey(string key);

		void AssignKeyHash(in SNetExt_KeyHash16 keyHash);

		void ReceiveBytes(in SNetExt_KeyHash16 packetKeyHash, byte packetIndex, byte[] bytes);
	}
	internal interface ISNetExt_OwnedReplicator : ISNetExt_MutableReplicator, ISNetExt_Replicator
	{
		new SNet_Player OwningPlayer { get; set; }

		new bool OwnedByMaster { get; set; }
	}
	public interface ISNetExt_ReplicatedPlayerData
	{
		pPlayer PlayerData { get; set; }
	}
	public interface ISNetExt_Replicator
	{
		string Key { get; }

		string KeyHash { get; }

		ReadOnlySpan<byte> KeyHashBytes { get; }

		SNetExt_ReplicatorType Type { get; }

		bool LocallyOwned { get; }

		bool IsAnonymous { get; }

		bool HasValidKeyHash { get; }

		SNet_Player OwningPlayer { get; }

		bool OwnedByMaster { get; }

		ISNetExt_ReplicatorSupplier ReplicatorSupplier { get; set; }

		SNetExt_ReplicatedPacket<T> CreatePacket<T>(string packetKey, Action<T> receiveAction, Action<T> validateAction = null) where T : struct;

		SNetExt_ReplicatedPacketBytes CreatePacketBytes(string key, SNetExt_ReplicatedPacketBytes.SpanReceiveDelegate receiveAction);

		SNetExt_ReplicatedPacketBufferBytes CreatePacketBufferBytes(string key, SNetExt_ReplicatedPacketBufferBytes.SpanBufferReceiveDelegate receiveAction);

		void Despawn();

		Type GetPacketType(string key, int packetIndex);
	}
	public interface ISNetExt_ReplicatorSupplier
	{
		string Key { get; }

		ISNetExt_Replicator Replicator { get; set; }

		GameObject gameObject { get; }
	}
	public interface ISNetExt_StateReplicator
	{
		ISNetExt_Replicator Replicator { get; set; }
	}
	public interface ISNetExt_StateReplicatorProvider
	{
		GameObject gameObject { get; }

		ISNetExt_StateReplicator GetStateReplicator();
	}
	public interface ISNetExt_StateReplicatorProvider<S> : ISNetExt_StateReplicatorProvider where S : struct
	{
		void OnStateChange(S oldState, S newState, bool isRecall);
	}
	public interface ISNetExt_StateReplicatorProvider<S, I> : ISNetExt_StateReplicatorProvider where S : struct where I : struct
	{
		void OnStateChange(S oldState, S newState, bool isRecall);

		void AttemptInteract(I interaction);
	}
	internal static class SNetExt_HashUtil
	{
		[ThreadStatic]
		private static MD5 t_md5;

		private static readonly Dictionary<string, string> s_keyHexCache = new Dictionary<string, string>(65535);

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static MD5 GetMD5()
		{
			return t_md5 ?? (t_md5 = MD5.Create());
		}

		public static string KeyToHashHex(string key)
		{
			if (string.IsNullOrWhiteSpace(key))
			{
				return string.Empty;
			}
			lock (s_keyHexCache)
			{
				if (s_keyHexCache.TryGetValue(key, out var value))
				{
					return value;
				}
			}
			MD5 mD = GetMD5();
			int byteCount = Encoding.UTF8.GetByteCount(key);
			string text;
			if (byteCount <= 256)
			{
				int bytesWritten = byteCount;
				Span<byte> span = stackalloc byte[bytesWritten];
				Encoding.UTF8.GetBytes(key, span);
				Span<byte> span2 = stackalloc byte[16];
				mD.TryComputeHash(span, span2, out bytesWritten);
				text = Convert.ToHexString(span2);
			}
			else
			{
				text = Convert.ToHexString(mD.ComputeHash(Encoding.UTF8.GetBytes(key)));
			}
			lock (s_keyHexCache)
			{
				s_keyHexCache[key] = text;
				return text;
			}
		}

		public static void KeyToHashBytes(string key, Span<byte> destination16)
		{
			if (destination16.Length < 16)
			{
				throw new ArgumentException("destination must be at least 16 bytes", "destination16");
			}
			if (string.IsNullOrWhiteSpace(key))
			{
				destination16.Slice(0, 16).Clear();
				return;
			}
			MD5 mD = GetMD5();
			int byteCount = Encoding.UTF8.GetByteCount(key);
			if (byteCount <= 256)
			{
				int bytesWritten = byteCount;
				Span<byte> span = stackalloc byte[bytesWritten];
				Encoding.UTF8.GetBytes(key, span);
				mD.TryComputeHash(span, destination16, out bytesWritten);
			}
			else
			{
				mD.ComputeHash(Encoding.UTF8.GetBytes(key)).AsSpan(0, 16).CopyTo(destination16);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static byte[] HashHexToBytes(string keyHash)
		{
			return Convert.FromHexString(keyHash);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static string HashBytesToHex(ReadOnlySpan<byte> hash16)
		{
			return Convert.ToHexString(hash16);
		}
	}
	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	public readonly struct SNetExt_KeyHash16 : IEquatable<SNetExt_KeyHash16>
	{
		public readonly ulong Lower;

		public readonly ulong Upper;

		public bool IsEmpty
		{
			get
			{
				if (Lower == 0L)
				{
					return Upper == 0;
				}
				return false;
			}
		}

		public SNetExt_KeyHash16(ulong lower, ulong upper)
		{
			Lower = lower;
			Upper = upper;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static SNetExt_KeyHash16 FromSpan(ReadOnlySpan<byte> bytes16)
		{
			if (bytes16.Length < 16)
			{
				throw new ArgumentException("need 16 bytes", "bytes16");
			}
			return new SNetExt_KeyHash16(BinaryPrimitives.ReadUInt64LittleEndian(bytes16), BinaryPrimitives.ReadUInt64LittleEndian(bytes16.Slice(8)));
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static SNetExt_KeyHash16 FromHex(string hex32)
		{
			if (string.IsNullOrWhiteSpace(hex32) || hex32.Length != 32)
			{
				return default(SNetExt_KeyHash16);
			}
			Span<byte> span = stackalloc byte[16];
			if (!TryParseHex(hex32.AsSpan(), span))
			{
				return default(SNetExt_KeyHash16);
			}
			return FromSpan(span);
		}

		private static bool TryParseHex(ReadOnlySpan<char> hex, Span<byte> output)
		{
			for (int i = 0; i < 16; i++)
			{
				int num = ParseNibble(hex[i * 2]);
				int num2 = ParseNibble(hex[i * 2 + 1]);
				if (num < 0 || num2 < 0)
				{
					return false;
				}
				output[i] = (byte)((num << 4) | num2);
			}
			return true;
		}

		private static int ParseNibble(char c)
		{
			switch (c)
			{
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				return c - 48;
			case 'a':
			case 'b':
			case 'c':
			case 'd':
			case 'e':
			case 'f':
				return c - 97 + 10;
			case 'A':
			case 'B':
			case 'C':
			case 'D':
			case 'E':
			case 'F':
				return c - 65 + 10;
			default:
				return -1;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void WriteTo(Span<byte> destination16)
		{
			BinaryPrimitives.WriteUInt64LittleEndian(destination16, Lower);
			BinaryPrimitives.WriteUInt64LittleEndian(destination16.Slice(8), Upper);
		}

		public string ToHex()
		{
			Span<byte> span = stackalloc byte[16];
			WriteTo(span);
			return Convert.ToHexString(span);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public bool Equals(SNetExt_KeyHash16 other)
		{
			if (Lower == other.Lower)
			{
				return Upper == other.Upper;
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is SNetExt_KeyHash16 other)
			{
				return Equals(other);
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public override int GetHashCode()
		{
			long num = (long)Lower ^ ((long)Upper * -7046029254386353131L);
			long num2 = (num ^ (num >>> 30)) * -4658895280553007687L;
			long num3 = (num2 ^ (num2 >>> 27)) * -7723592293110705685L;
			long num4 = num3 ^ (num3 >>> 31);
			return (int)(num4 ^ (num4 >>> 32));
		}

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

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

		public override string ToString()
		{
			return ToHex();
		}
	}
	internal sealed class SNetExt_ReplicatorRegistry
	{
		public enum RegisterStatus
		{
			Success,
			Conflict,
			InvalidKeyHash
		}

		private readonly Dictionary<SNetExt_KeyHash16, ISNetExt_Replicator> _byKeyHash = new Dictionary<SNetExt_KeyHash16, ISNetExt_Replicator>(64);

		private readonly Dictionary<string, SNetExt_KeyHash16> _keyToKeyHash = new Dictionary<string, SNetExt_KeyHash16>(64);

		private readonly Dictionary<IntPtr, SNetExt_Replicator_VanillaWrapper> _byVanillaPtr = new Dictionary<IntPtr, SNetExt_Replicator_VanillaWrapper>(64);

		private readonly List<ISNetExt_Replicator> _assigned = new List<ISNetExt_Replicator>();

		public IReadOnlyList<ISNetExt_Replicator> Assigned => _assigned;

		public RegisterStatus Register(ISNetExt_MutableReplicator r)
		{
			if (!r.HasValidKeyHash)
			{
				return RegisterStatus.InvalidKeyHash;
			}
			SNetExt_KeyHash16 sNetExt_KeyHash = SNetExt_KeyHash16.FromHex(r.KeyHash);
			if (sNetExt_KeyHash.IsEmpty)
			{
				return RegisterStatus.InvalidKeyHash;
			}
			if (_byKeyHash.TryGetValue(sNetExt_KeyHash, out var value) && value != null)
			{
				return RegisterStatus.Conflict;
			}
			_byKeyHash[sNetExt_KeyHash] = r;
			if (!r.IsAnonymous)
			{
				_keyToKeyHash[r.Key] = sNetExt_KeyHash;
			}
			if (!_assigned.Contains(r))
			{
				_assigned.Add(r);
			}
			return RegisterStatus.Success;
		}

		public bool Unregister(ISNetExt_Replicator r)
		{
			if (r == null)
			{
				return false;
			}
			SNetExt_KeyHash16 key = SNetExt_KeyHash16.FromHex(r.KeyHash);
			if (key.IsEmpty || !_byKeyHash.TryGetValue(key, out var value) || value != r)
			{
				_assigned.Remove(r);
				return false;
			}
			_byKeyHash.Remove(key);
			if (!r.IsAnonymous)
			{
				_keyToKeyHash.Remove(r.Key);
			}
			_assigned.Remove(r);
			return true;
		}

		public RegisterStatus Reassign(ISNetExt_MutableReplicator r, in SNetExt_KeyHash16 newHash)
		{
			if (newHash.IsEmpty)
			{
				return RegisterStatus.InvalidKeyHash;
			}
			if (_byKeyHash.TryGetValue(newHash, out var value) && value != null && value != r)
			{
				return RegisterStatus.Conflict;
			}
			Unregister(r);
			r.AssignKey(string.Empty);
			r.AssignKeyHash(in newHash);
			return Register(r);
		}

		public bool TryGet(in SNetExt_KeyHash16 keyHash, out ISNetExt_Replicator r)
		{
			if (_byKeyHash.TryGetValue(keyHash, out r))
			{
				return r != null;
			}
			return false;
		}

		public bool TryGetByKey(string key, out ISNetExt_Replicator r)
		{
			r = null;
			if (!string.IsNullOrWhiteSpace(key) && _keyToKeyHash.TryGetValue(key, out var value) && _byKeyHash.TryGetValue(value, out r))
			{
				return r != null;
			}
			return false;
		}

		public bool TryGetByVanilla(IntPtr ptr, out SNetExt_Replicator_VanillaWrapper w)
		{
			if (_byVanillaPtr.TryGetValue(ptr, out w))
			{
				return w != null;
			}
			return false;
		}

		public RegisterStatus RegisterVanilla(SNetExt_Replicator_VanillaWrapper w)
		{
			RegisterStatus num = Register(w);
			if (num == RegisterStatus.Success)
			{
				_byVanillaPtr[((Il2CppObjectBase)w.Vanilla).Pointer] = w;
			}
			return num;
		}

		public bool UnregisterVanilla(SNetExt_Replicator_VanillaWrapper w)
		{
			if (!Unregister(w))
			{
				return false;
			}
			_byVanillaPtr.Remove(((Il2CppObjectBase)w.Vanilla).Pointer);
			return true;
		}

		public void Clear()
		{
			_byKeyHash.Clear();
			_keyToKeyHash.Clear();
			_byVanillaPtr.Clear();
			_assigned.Clear();
		}
	}
	internal class SNetExt_ReplicatorSupplierWrapper : Component
	{
		[HideFromIl2Cpp]
		public ISNetExt_ReplicatorSupplier ReplicatorSupplier { get; private set; }

		[HideFromIl2Cpp]
		public void Setup(ISNetExt_ReplicatorSupplier supplier)
		{
			ReplicatorSupplier = supplier;
		}
	}
	internal class SNetExt_StateReplicatorProviderWrapper : Component
	{
		[HideFromIl2Cpp]
		public ISNetExt_StateReplicatorProvider Provider { get; private set; }

		[HideFromIl2Cpp]
		public void Setup(ISNetExt_StateReplicatorProvider provider)
		{
			Provider = provider;
		}
	}
	public static class SNetExt
	{
		internal static readonly IArchiveLogger Logger = LoaderWrapper.CreateArSubLoggerInstance("SNetExt", ConsoleColor.White);

		private static readonly Dictionary<(ulong PlayerLookup, Type DataType), DataWrapper> s_dataWrappersLookup = new Dictionary<(ulong, Type), DataWrapper>(16);

		private static readonly List<ISNetExt_Manager> s_subManagers = new List<ISNetExt_Manager>();

		public static SNetExt_Replication Replication { get; private set; }

		public static SNetExt_Replicator SubManagerReplicator { get; private set; }

		public static SNetExt_Capture Capture { get; private set; }

		public static SNetExt_PrefabReplicationManager PrefabReplication { get; private set; }

		internal static GameObject RootObject { get; private set; }

		internal static void Setup()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			if (!((Object)(object)RootObject != (Object)null))
			{
				ClassInjector.RegisterTypeInIl2Cpp<SNetExt_StateReplicatorProviderWrapper>(false);
				ClassInjector.RegisterTypeInIl2Cpp<SNetExt_ReplicatorSupplierWrapper>(false);
				RootObject = new GameObject("SNetExt");
				Object.DontDestroyOnLoad((Object)(object)RootObject);
				Capture = CreateSubManager<SNetExt_Capture>(createSubGo: true, "Capture");
				Replication = CreateSubManager<SNetExt_Replication>(createSubGo: true, "Replication");
				PrefabReplication = CreateSubManager<SNetExt_PrefabReplicationManager>(createSubGo: false, "PrefabReplication");
				SubManagerReplicator = SNetExt_Replication.AddManagerReplicator("SNetExt_SubManager") as SNetExt_Replicator;
				SetupReplication();
			}
		}

		public static T CreateSubManager<T>(bool createSubGo = false, string name = "") where T : MonoBehaviour, ISNetExt_Manager
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			GameObject val;
			if (createSubGo)
			{
				val = new GameObject(name);
				val.transform.SetParent(RootObject.transform, false);
			}
			else
			{
				val = RootObject;
			}
			ClassInjector.RegisterTypeInIl2Cpp<T>(false);
			T val2 = val.AddComponent<T>();
			val2.Setup();
			s_subManagers.Add(val2);
			return val2;
		}

		public static void SendAllCustomData(SNet_Player sourcePlayer, SNet_Player toPlayer = null)
		{
			foreach (KeyValuePair<(ulong, Type), DataWrapper> item in s_dataWrappersLookup)
			{
				if (item.Key.Item1 == sourcePlayer.Lookup)
				{
					item.Value.Send(sourcePlayer, toPlayer);
				}
			}
		}

		public static void SetupCustomData<A>(string eventName, Action<SNet_Player, A> callback) where A : struct, ISNetExt_ReplicatedPlayerData
		{
			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) || (Object)(object)SNet.LocalPlayer == (Object)null)
			{
				return;
			}
			SNetExt_ReplicatedPlayerData<A>.SendData(SNet.LocalPlayer, GetLocalCustomData<A>(), toPlayer);
			if (!SNet.IsMaster)
			{
				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
		{
			(ulong, Type) key = (player.Lookup, typeof(A));
			if (!s_dataWrappersLookup.TryGetValue(key, out var value))
			{
				DataWrapper<A> dataWrapper = new DataWrapper<A>();
				s_dataWrappersLookup.Add(key, dataWrapper);
				return dataWrapper.Load();
			}
			return ((DataWrapper<A>)value).Load();
		}

		public static void StoreCustomData<A>(this SNet_Player player, A data) where A : struct
		{
			(ulong, Type) key = (player.Lookup, typeof(A));
			DataWrapper<A> dataWrapper;
			if (!s_dataWrappersLookup.TryGetValue(key, out var value))
			{
				dataWrapper = new DataWrapper<A>();
				s_dataWrappersLookup.Add(key, dataWrapper);
			}
			else
			{
				dataWrapper = (DataWrapper<A>)value;
			}
			dataWrapper.Store(player, data);
		}

		public static void StoreCustomDataLocal<A>(this SNet_Player player, A data) where A : struct
		{
			(ulong, Type) key = (player.Lookup, typeof(A));
			DataWrapper<A> dataWrapper;
			if (!s_dataWrappersLookup.TryGetValue(key, out var value))
			{
				dataWrapper = new DataWrapper<A>();
				s_dataWrappersLookup.Add(key, dataWrapper);
			}
			else
			{
				dataWrapper = (DataWrapper<A>)value;
			}
			dataWrapper.StoreLocal(data);
		}

		private static void SetupReplication()
		{
			for (int i = 0; i < s_subManagers.Count; i++)
			{
				s_subManagers[i].SetupReplication();
			}
		}

		internal static void ResetSession()
		{
			for (int i = 0; i < s_subManagers.Count; i++)
			{
				s_subManagers[i].OnResetSession();
			}
		}

		internal static void ValidateMasterData()
		{
			for (int i = 0; i < s_subManagers.Count; i++)
			{
				s_subManagers[i].OnValidateMasterData();
			}
		}

		internal static void DestroySelfManagedReplicatedObject(GameObject go)
		{
			Il2CppArrayBase<SNetExt_StateReplicatorProviderWrapper> componentsInChildren = go.GetComponentsInChildren<SNetExt_StateReplicatorProviderWrapper>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				ISNetExt_StateReplicator stateReplicator = componentsInChildren[i].Provider.GetStateReplicator();
				if (stateReplicator != null)
				{
					ISNetExt_Replicator replicator = stateReplicator.Replicator;
					if (stateReplicator is ICaptureCallbackObject syncInterface)
					{
						SNetExt_Capture.UnRegisterForDropInCallback(syncInterface);
					}
					SNetExt_Replication.DeallocateReplicator(replicator);
				}
			}
		}
	}
	public class SNetExt_AuthorativeAction<T> : SNetExt_SyncedAction<T> where T : struct
	{
		private Action<T> m_incomingActionValidation;

		protected SNetExt_AuthorativeAction()
		{
		}

		public static SNetExt_AuthorativeAction<T> Create(string eventName, Action<SNet_Player, 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_packet.Send(data, SNet.Master);
			}
		}

		public void Do(T data)
		{
			if (SNet.IsMaster)
			{
				m_packet.Send(data, m_listeners);
			}
			else if (SNet.HasMaster)
			{
				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<SNet_Player, 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);
		}
	}
	public class SNetExt_BufferSender
	{
		public enum State
		{
			Open,
			Send,
			Close,
			Done
		}

		private State m_state;

		private readonly float m_sendInterval;

		private readonly int m_packetsPerFrame;

		private int m_passIndex;

		private int m_packetIndex;

		private SNetExt_CaptureBuffer m_buffer;

		private readonly List<SNet_Player> m_sendToPlayers = new List<SNet_Player>();

		private readonly SNetExt_BufferType m_bufferType;

		private readonly SNet_ChannelType m_channelType;

		private float m_sendTimer;

		private byte[] m_bufferBytes = new byte[3];

		public SNetExt_BufferSender(int packetsPerFrame, float sendInterval, SNetExt_CaptureBuffer buffer, List<SNet_Player> players, SNet_ChannelType channelType)
		{
			//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)
			m_packetsPerFrame = packetsPerFrame;
			m_sendInterval = sendInterval;
			m_buffer = buffer;
			m_bufferType = buffer.type;
			m_channelType = channelType;
			for (int i = 0; i < players.Count; i++)
			{
				SNet_Player val = players[i];
				if ((Object)(object)val != (Object)null && val.IsInSessionHub && !val.IsBot)
				{
					m_sendToPlayers.Add(val);
				}
			}
		}

		private void UpdateBufferBytes()
		{
			SNetExt_ReplicatedPacketBufferBytes.WriteBufferDataBytes(new SNetExt_ReplicatedPacketBufferBytes.BufferData(m_buffer.data.bufferID, (byte)m_passIndex), m_bufferBytes.AsSpan());
		}

		private bool UpdatePlayerList()
		{
			for (int num = m_sendToPlayers.Count - 1; num >= 0; num--)
			{
				SNet_Player val = m_sendToPlayers[num];
				if ((Object)(object)val == (Object)null || !val.IsInSessionHub || val.IsBot)
				{
					m_sendToPlayers.RemoveAt(num);
				}
			}
			return m_sendToPlayers.Count > 0;
		}

		public bool Update()
		{
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			if (!SNet.IsMaster)
			{
				return true;
			}
			if (m_state == State.Send)
			{
				m_sendTimer += Clock.Delta;
				if (m_sendTimer < m_sendInterval)
				{
					return false;
				}
				m_sendTimer = 0f;
			}
			else
			{
				if (m_state == State.Done)
				{
					return true;
				}
				m_sendTimer = m_sendInterval + 1f;
			}
			if (!UpdatePlayerList())
			{
				m_state = State.Done;
				return true;
			}
			switch (m_state)
			{
			case State.Open:
				SNetExt.Capture.m_bufferCommandPacket.Send(new pBufferCommand
				{
					type = m_bufferType,
					operation = SNetExt_BufferOperationType.StartReceive,
					bufferID = m_buffer.data.bufferID
				}, m_channelType, m_sendToPlayers);
				UpdateBufferBytes();
				m_state = State.Send;
				break;
			case State.Send:
			{
				List<byte[]> list = m_buffer.m_passes[m_passIndex];
				int num = m_packetIndex;
				if (num >= list.Count)
				{
					list = null;
					m_passIndex++;
					while (m_passIndex < m_buffer.m_passes.Length)
					{
						List<byte[]> list2 = m_buffer.m_passes[m_passIndex];
						if (list2.Count > 0)
						{
							list = list2;
							m_packetIndex = 0;
							num = Mathf.Min(m_packetIndex + m_packetsPerFrame, list2.Count);
							UpdateBufferBytes();
							break;
						}
						m_passIndex++;
					}
					if (list == null)
					{
						m_state = State.Close;
						break;
					}
				}
				else
				{
					num = Mathf.Min(m_packetIndex + m_packetsPerFrame, list.Count);
				}
				for (int i = m_packetIndex; i < num; i++)
				{
					SNetExt.Capture.m_bufferBytesPacket.Send(list[i], m_bufferBytes, m_sendToPlayers);
					m_packetIndex++;
				}
				break;
			}
			case State.Close:
				SNetExt.Capture.m_bufferCompletionPacket.Send(new pBufferCompletion
				{
					type = m_bufferType,
					data = m_buffer.data
				}, m_channelType, m_sendToPlayers);
				m_state = State.Done;
				break;
			case State.Done:
				return true;
			}
			return false;
		}
	}
	public class SNetExt_Capture : MonoBehaviour, ISNetExt_Manager
	{
		public enum SNetExt_CaptureState
		{
			Idle,
			Capturing,
			Recalling
		}

		internal SNetExt_ReplicatedPacket<pBufferCommand> m_bufferCommandPacket;

		internal SNetExt_ReplicatedPacket<pBufferCompletion> m_bufferCompletionPacket;

		internal SNetExt_ReplicatedPacketBufferBytes m_bufferBytesPacket;

		private SNetExt_CaptureState _state;

		private SNetExt_CaptureBuffer _activeBuffer;

		private SNetExt_BufferType _activeBufferType;

		private SNetExt_CaptureBuffer[] m_buffers;

		private SNetExt_BufferSender m_passiveMigrationBufferSend;

		private float m_migrationTimer;

		private const float MIGRATION_CAPTURE_INTERVAL = 60f;

		private const float MIGRATION_CAPTURE_INTERVAL_MIN_DELAY = 20f;

		private ushort m_highestBufferID = 1;

		private float m_minTimeToSendNextBuffer;

		private readonly List<SNet_Player> m_migrationPlayerScratch = new List<SNet_Player>(8);

		private readonly List<pBuffersSummary> _summariesScratch = new List<pBuffersSummary>(8);

		private static readonly List<ICaptureCallbackObject> s_captureCallbackObjects = new List<ICaptureCallbackObject>();

		private readonly IArchiveLogger _logger = LoaderWrapper.CreateArSubLoggerInstance("SNetExt_Capture", ConsoleColor.White);

		[HideFromIl2Cpp]
		public SNetExt_CaptureState State => _state;

		[HideFromIl2Cpp]
		public bool IsCapturing => _state == SNetExt_CaptureState.Capturing;

		[HideFromIl2Cpp]
		public bool IsRecalling => _state == SNetExt_CaptureState.Recalling;

		[HideFromIl2Cpp]
		public SNetExt_CaptureBuffer PrimedBuffer
		{
			get
			{
				if (!IsCapturing)
				{
					return null;
				}
				return _activeBuffer;
			}
		}

		[HideFromIl2Cpp]
		public SNetExt_BufferType PrimedBufferType => _activeBufferType;

		[HideFromIl2Cpp]
		public void Setup()
		{
		}

		[HideFromIl2Cpp]
		public void SetupReplication()
		{
			m_bufferCommandPacket = SNetExt.SubManagerReplicator.CreatePacket<pBufferCommand>(typeof(pBufferCommand).FullName, OnReceiveBufferCommand);
			m_bufferCompletionPacket = SNetExt.SubManagerReplicator.CreatePacket<pBufferCompletion>(typeof(pBufferCompletion).FullName, OnReceiveBufferCompletion);
			m_bufferBytesPacket = SNetExt.SubManagerReplicator.CreatePacketBufferBytes(typeof(SNetExt_Capture).FullName + ".BufferBytes", OnReceiveBufferBytes);
			int length = Enum.GetValues(typeof(SNetExt_BufferType)).Length;
			m_buffers = new SNetExt_CaptureBuffer[length];
			for (int i = 0; i < length; i++)
			{
				m_buffers[i] = new SNetExt_CaptureBuffer((SNetExt_BufferType)i);
			}
		}

		[HideFromIl2Cpp]
		public void OnResetSession()
		{
			for (int i = 0; i < m_buffers.Length; i++)
			{
				m_buffers[i].Clear();
			}
			m_highestBufferID = 1;
			m_passiveMigrationBufferSend = null;
			_activeBuffer = null;
			_state = SNetExt_CaptureState.Idle;
		}

		[HideFromIl2Cpp]
		public void OnValidateMasterData()
		{
		}

		[HideFromIl2Cpp]
		internal static void RegisterCaptureCallback(ICaptureCallbackObject syncInterface)
		{
			s_captureCallbackObjects.Add(syncInterface);
		}

		[HideFromIl2Cpp]
		internal static void UnRegisterForDropInCallback(ICaptureCallbackObject syncInterface)
		{
			s_captureCallbackObjects.Remove(syncInterface);
		}

		[HideFromIl2Cpp]
		internal static void UnregisterCaptureCallback(ICaptureCallbackObject syncInterface)
		{
			UnRegisterForDropInCallback(syncInterface);
		}

		[HideFromIl2Cpp]
		internal static void CleanUpAllButManagersCaptureCallbacks()
		{
			int count = s_captureCallbackObjects.Count;
			while (count-- > 0)
			{
				ICaptureCallbackObject captureCallbackObject = s_captureCallbackObjects[count];
				if (captureCallbackObject == null || !captureCallbackObject.PersistAcrossSession)
				{
					s_captureCallbackObjects.RemoveAt(count);
				}
			}
		}

		[HideFromIl2Cpp]
		internal void InitCheckpointRecall()
		{
			IncreaseRecallCount(SNetExt_BufferType.Checkpoint);
		}

		[HideFromIl2Cpp]
		internal void IncreaseRecallCount(SNetExt_BufferType bufferType)
		{
			SNetExt_CaptureBuffer sNetExt_CaptureBuffer = m_buffers[(uint)bufferType];
			if (!sNetExt_CaptureBuffer.isValid)
			{
				_logger.Warning($"IncreaseRecallCount on invalid buffer {bufferType}");
			}
			else
			{
				sNetExt_CaptureBuffer.data.recallCount++;
			}
		}

		[HideFromIl2Cpp]
		public List<pBuffersSummary> GetBufferSummaries()
		{
			_summariesScratch.Clear();
			for (int i = 0; i < m_buffers.Length; i++)
			{
				SNetExt_CaptureBuffer sNetExt_CaptureBuffer = m_buffers[i];
				if (sNetExt_CaptureBuffer.type != 0 && sNetExt_CaptureBuffer.isValid)
				{
					_summariesScratch.Add(new pBuffersSummary(sNetExt_CaptureBuffer));
				}
			}
			return _summariesScratch;
		}

		[HideFromIl2Cpp]
		public bool HasCorrectMigrationBuffer(ref pBuffersSummary bufferSummary)
		{
			for (int i = 4; i <= 5; i++)
			{
				if (new pBuffersSummary(m_buffers[i]).IsSame(ref bufferSummary))
				{
					return true;
				}
			}
			return false;
		}

		[HideFromIl2Cpp]
		public bool TrySendMigrationBuffer(pBuffersSummary bufferSummary, SNet_Player toPlayer)
		{
			SNetExt_CaptureBuffer sNetExt_CaptureBuffer = m_buffers[(uint)bufferSummary.bufferType];
			if (!new pBuffersSummary(sNetExt_CaptureBuffer).IsSame(ref bufferSummary))
			{
				return false;
			}
			SendBuffer(sNetExt_CaptureBuffer.type, toPlayer, sendAsMigrationBuffer: true);
			return true;
		}

		[HideFromIl2Cpp]
		public bool TrySendLatestMigrationBuffer(SNet_Player toPlayer, bool forceCapture = false)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected I4, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected I4, but got Unknown
			if (SNet.Sync.IsBitSet(SNet.Sync.MASK_IN_SESSION_HUB, (int)SNet.LocalPlayer.Session.mode))
			{
				return false;
			}
			if (!TryGetNewestMigrationBuffer(out var type))
			{
				if (!forceCapture || !SNet.Sync.IsBitSet(SNet.Sync.MASK_MASTER_CAN_RECALL_GAMESTATE, (int)SNet.LocalPlayer.Session.mode))
				{
					return false;
				}
				SNetExt.Capture.CaptureGameState(GetOldestMigrationBuffer());
				if (!TryGetNewestMigrationBuffer(out type))
				{
					_logger.Error("TrySendLatestMigrationBuffer: forceCapture failed to produce usable buffer");
					return false;
				}
			}
			SendBuffer(type, toPlayer);
			return true;
		}

		[HideFromIl2Cpp]
		public bool GotBuffer(SNetExt_BufferType type)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			SNetExt_CaptureBuffer sNetExt_CaptureBuffer = m_buffers[(uint)type];
			if (sNetExt_CaptureBuffer.isValid)
			{
				return SNet.LocalPlayer.Session.levelChecksum == sNetExt_CaptureBuffer.data.levelChecksum;
			}
			return false;
		}

		[HideFromIl2Cpp]
		private SNetExt_BufferType GetOldestMigrationBuffer()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			SNetExt_CaptureBuffer sNetExt_CaptureBuffer = null;
			for (int i = 4; i <= 5; i++)
			{
				SNetExt_CaptureBuffer sNetExt_CaptureBuffer2 = m_buffers[i];
				if (!sNetExt_CaptureBuffer2.isValid || SNet.LocalPlayer.Session.levelChecksum != sNetExt_CaptureBuffer2.data.levelChecksum)
				{
					sNetExt_CaptureBuffer = sNetExt_CaptureBuffer2;
				}
				else if (sNetExt_CaptureBuffer == null || sNetExt_CaptureBuffer2.data.progressionTime < sNetExt_CaptureBuffer.data.progressionTime)
				{
					sNetExt_CaptureBuffer = sNetExt_CaptureBuffer2;
				}
			}
			return sNetExt_CaptureBuffer.type;
		}

		[HideFromIl2Cpp]
		public bool TryGetNewestMigrationBuffer(out SNetExt_BufferType type)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			SNetExt_CaptureBuffer sNetExt_CaptureBuffer = null;
			for (int i = 4; i <= 5; i++)
			{
				SNetExt_CaptureBuffer sNetExt_CaptureBuffer2 = m_buffers[i];
				if (sNetExt_CaptureBuffer2.isValid && SNet.LocalPlayer.Session.levelChecksum == sNetExt_CaptureBuffer2.data.levelChecksum && (sNetExt_CaptureBuffer == null || sNetExt_CaptureBuffer2.data.progressionTime > sNetExt_CaptureBuffer.data.progressionTime))
				{
					sNetExt_CaptureBuffer = sNetExt_CaptureBuffer2;
				}
			}
			if (sNetExt_CaptureBuffer != null)
			{
				type = sNetExt_CaptureBuffer.type;
				return true;
			}
			type = SNetExt_BufferType.JoinedHub;
			return false;
		}

		private void Update()
		{
			if (SNet.IsMaster)
			{
				UpdateMigrationSend();
			}
		}

		[HideFromIl2Cpp]
		private void UpdateMigrationSend()
		{
			//IL_0020: 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_002f: Expected I4, but got Unknown
			if (SNet.MasterManagement.IsMigrating || !SNet.Sync.IsBitSet(SNet.Sync.MASK_PLAYER_READY_TO_START_PLAYING, (int)SNet.LocalPlayer.Session.mode))
			{
				m_passiveMigrationBufferSend = null;
			}
			else if (m_passiveMigrationBufferSend != null)
			{
				if (m_passiveMigrationBufferSend.Update())
				{
					m_passiveMigrationBufferSend = null;
					m_minTimeToSendNextBuffer = Clock.Time + 20f;
				}
			}
			else
			{
				if (m_minTimeToSendNextBuffer > Clock.Time || m_migrationTimer >= Clock.Time)
				{
					return;
				}
				SNetExt_BufferType oldestMigrationBuffer = GetOldestMigrationBuffer();
				CaptureGameState(oldestMigrationBuffer);
				m_migrationPlayerScratch.Clear();
				List<SNet_Player> playersInSession = SNet.SessionHub.PlayersInSession;
				for (int i = 0; i < playersInSession.Count; i++)
				{
					SNet_Player val = playersInSession[i];
					if (!val.IsLocal && !val.IsBot)
					{
						m_migrationPlayerScratch.Add(val);
					}
				}
				if (m_migrationPlayerScratch.Count == 0)
				{
					m_minTimeToSendNextBuffer = Clock.Time + 20f;
					return;
				}
				m_passiveMigrationBufferSend = new SNetExt_BufferSender(5, 0.5f, m_buffers[(uint)oldestMigrationBuffer], m_migrationPlayerScratch, (SNet_ChannelType)1);
				m_migrationTimer = Clock.Time + 60f;
			}
		}

		[HideFromIl2Cpp]
		internal void CaptureGameState(SNetExt_BufferType buffer)
		{
			pBufferCommand pBufferCommand2 = default(pBufferCommand);
			pBufferCommand2.type = buffer;
			pBufferCommand2.operation = SNetExt_BufferOperationType.StoreGameState;
			pBufferCommand command = pBufferCommand2;
			OnBufferCommand(command);
		}

		[HideFromIl2Cpp]
		internal void RecallGameState(SNetExt_BufferType buffer)
		{
			pBufferCommand pBufferCommand2 = default(pBufferCommand);
			pBufferCommand2.type = buffer;
			pBufferCommand2.operation = SNetExt_BufferOperationType.RecallGameState;
			pBufferCommand command = pBufferCommand2;
			OnBufferCommand(command);
		}

		[HideFromIl2Cpp]
		internal void SendBufferCommand(SNetExt_BufferType buffer, SNetExt_BufferOperationType operation, SNet_Player toPlayer = null, ushort bufferID = 0)
		{
			if ((Object)(object)toPlayer != (Object)null)
			{
				m_bufferCommandPacket.Send(new pBufferCommand
				{
					type = buffer,
					operation = operation,
					bufferID = bufferID
				}, (SNet_ChannelType)0, toPlayer);
			}
			else
			{
				m_bufferCommandPacket.Send(new pBufferCommand
				{
					type = buffer,
					operation = operation,
					bufferID = bufferID
				}, (SNet_ChannelType)0);
			}
		}

		[HideFromIl2Cpp]
		private void OnReceiveBufferCommand(pBufferCommand command)
		{
			if (SNet.MasterManagement.IsMigrating)
			{
				OnBufferCommand(command);
			}
			else if (SNetExt.Replication.IsLastSenderMaster)
			{
				OnBufferCommand(command);
			}
		}

		[HideFromIl2Cpp]
		private void OnBufferCommand(pBufferCommand command)
		{
			switch (command.operation)
			{
			case SNetExt_BufferOperationType.StartReceive:
				OpenBuffer(command.type, command.bufferID);
				if (_activeBuffer != null)
				{
					_activeBuffer.data.sendingPlayerLookup = SNetExt.Replication.LastSenderID;
				}
				break;
			case SNetExt_BufferOperationType.StoreGameState:
				OpenBuffer(command.type, 0);
				TriggerCapture();
				CloseBuffer(command.type);
				break;
			case SNetExt_BufferOperationType.RecallGameState:
				RecallBuffer(command.type);
				break;
			}
		}

		[HideFromIl2Cpp]
		private void OpenBuffer(SNetExt_BufferType type, ushort bufferID = 0)
		{
			switch (bufferID)
			{
			case 0:
				m_highestBufferID++;
				if (m_highestBufferID == ushort.MaxValue)
				{
					m_highestBufferID = 1;
				}
				bufferID = m_highestBufferID;
				break;
			case 1:
				m_highestBufferID = 1;
				break;
			default:
				if (m_highestBufferID < bufferID)
				{
					m_highestBufferID = bufferID;
				}
				break;
			}
			_activeBufferType = type;
			_activeBuffer = m_buffers[(uint)type];
			_activeBuffer.Clear();
			_activeBuffer.data.bufferID = bufferID;
			_state = SNetExt_CaptureState.Capturing;
		}

		[HideFromIl2Cpp]
		private void TriggerCapture()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < SNetExt.Replication.ReplicationManagers.Count; i++)
			{
				SNetExt.Replication.ReplicationManagers[i].OnStateCapture();
			}
			for (int j = 0; j < s_captureCallbackObjects.Count; j++)
			{
				s_captureCallbackObjects[j].OnStateCapture();
			}
			if (_activeBuffer != null)
			{
				_activeBuffer.data.levelChecksum = SNet.LocalPlayer.Session.levelChecksum;
				_activeBuffer.data.progressionTime = Clock.ExpeditionProgressionTime;
			}
		}

		[HideFromIl2Cpp]
		internal void CaptureToBuffer(byte[] data, SNetExt_CapturePass captureDataType)
		{
			if (captureDataType != SNetExt_CapturePass.Skip && _activeBuffer != null)
			{
				byte[] array = new byte[data.Length];
				Buffer.BlockCopy(data, 0, array, 0, data.Length);
				_activeBuffer.GetPass(captureDataType).Add(array);
			}
		}

		[HideFromIl2Cpp]
		private bool IsValidBufferData(SNet_Player sender)
		{
			if (!SNet.MasterManagement.IsMigrating)
			{
				return SNetExt.Replication.IsLastSenderMaster;
			}
			return true;
		}

		[HideFromIl2Cpp]
		private void OnReceiveBufferCompletion(pBufferCompletion completion)
		{
			if (SNetExt.Replication.TryGetLastSender(out var sender) && sender.IsInSessionHub && _state == SNetExt_CaptureState.Capturing && _activeBuffer != null && SNetExt.Replication.LastSenderID == _activeBuffer.data.sendingPlayerLookup && _activeBufferType == completion.type && _activeBuffer.data.bufferID == completion.data.bufferID)
			{
				_activeBuffer.isValid = true;
				_activeBuffer.data = completion.data;
				_activeBuffer = null;
				_state = SNetExt_CaptureState.Idle;
			}
		}

		[HideFromIl2Cpp]
		private void CloseBuffer(SNetExt_BufferType type)
		{
			if (_state == SNetExt_CaptureState.Capturing && _activeBufferType == type)
			{
				if (_activeBuffer != null)
				{
					_activeBuffer.isValid = true;
				}
				_activeBuffer = null;
				_state = SNetExt_CaptureState.Idle;
			}
		}

		[HideFromIl2Cpp]
		public void SendBuffer(SNetExt_BufferType bufferType, SNet_Player player = null, bool sendAsMigrationBuffer = false)
		{
			m_minTimeToSendNextBuffer = Clock.Time + 20f;
			SNetExt_BufferType sNetExt_BufferType = (sendAsMigrationBuffer ? GetOldestMigrationBuffer() : bufferType);
			SNetExt_CaptureBuffer sNetExt_CaptureBuffer = m_buffers[(uint)sNetExt_BufferType];
			pBufferCommand pBufferCommand2 = default(pBufferCommand);
			pBufferCommand2.type = sNetExt_BufferType;
			pBufferCommand2.operation = SNetExt_BufferOperationType.StartReceive;
			pBufferCommand2.bufferID = sNetExt_CaptureBuffer.data.bufferID;
			pBufferCommand data = pBufferCommand2;
			if ((Object)(object)player != (Object)null)
			{
				m_bufferCommandPacket.Send(data, (SNet_ChannelType)0, player);
			}
			else
			{
				m_bufferCommandPacket.Send(data, (SNet_ChannelType)0);
			}
			pBufferCompletion pBufferCompletion2 = default(pBufferCompletion);
			pBufferCompletion2.type = sNetExt_BufferType;
			pBufferCompletion2.data = sNetExt_CaptureBuffer.data;
			pBufferCompletion data2 = pBufferCompletion2;
			byte[] array = new byte[3];
			if ((Object)(object)player != (Object)null)
			{
				for (int i = 0; i < SNetExt_CaptureBuffer.PassCount; i++)
				{
					List<byte[]> list = sNetExt_CaptureBuffer.m_passes[i];
					SNetExt_ReplicatedPacketBufferBytes.WriteBufferDataBytes(new SNetExt_ReplicatedPacketBufferBytes.BufferData(sNetExt_CaptureBuffer.data.bufferID, (byte)i), array.AsSpan());
					int count = list.Count;
					for (int j = 0; j < count; j++)
					{
						m_bufferBytesPacket.Send(list[j], array, player);
					}
				}
				m_bufferCompletionPacket.Send(data2, (SNet_ChannelType)0, player);
				return;
			}
			for (int k = 0; k < SNetExt_CaptureBuffer.PassCount; k++)
			{
				List<byte[]> list2 = sNetExt_CaptureBuffer.m_passes[k];
				SNetExt_ReplicatedPacketBufferBytes.WriteBufferDataBytes(new SNetExt_ReplicatedPacketBufferBytes.BufferData(sNetExt_CaptureBuffer.data.bufferID, (byte)k), array.AsSpan());
				int count2 = list2.Count;
				for (int l = 0; l < count2; l++)
				{
					m_bufferBytesPacket.Send(list2[l], array);
				}
			}
			m_bufferCompletionPacket.Send(data2, (SNet_ChannelType)0);
		}

		[HideFromIl2Cpp]
		public void OnReceiveBufferBytes(ReadOnlySpan<byte> bytes, SNetExt_ReplicatedPacketBufferBytes.BufferData bufferData)
		{
			if (_state == SNetExt_CaptureState.Capturing)
			{
				SNetExt_CaptureBuffer activeBuffer = _activeBuffer;
				if (activeBuffer != null && activeBuffer.data.bufferID == bufferData.bufferID && activeBuffer.data.sendingPlayerLookup == SNetExt.Replication.LastSenderID && (SNet.MasterManagement.IsMigrating || SNetExt.Replication.IsLastSenderMaster) && bufferData.pass < SNetExt_CaptureBuffer.PassCount)
				{
					activeBuffer.m_passes[bufferData.pass].Add(bytes.ToArray());
				}
			}
		}

		[HideFromIl2Cpp]
		public ulong GetRecallCount(SNetExt_BufferType type)
		{
			SNetExt_CaptureBuffer sNetExt_CaptureBuffer = m_buffers[(uint)type];
			if (!sNetExt_CaptureBuffer.isValid)
			{
				return 0uL;
			}
			return sNetExt_CaptureBuffer.data.recallCount;
		}

		[HideFromIl2Cpp]
		private void RecallBuffer(SNetExt_BufferType bufferType)
		{
			SNetExt_CaptureBuffer sNetExt_CaptureBuffer = m_buffers[(uint)bufferType];
			_state = SNetExt_CaptureState.Recalling;
			_activeBufferType = bufferType;
			try
			{
				if (!sNetExt_CaptureBuffer.isValid)
				{
					return;
				}
				List<SNetExt_ReplicationManager> replicationManagers = SNetExt.Replication.ReplicationManagers;
				for (int i = 0; i < replicationManagers.Count; i++)
				{
					replicationManagers[i].ClearAllLocal();
				}
				SNetExt.Replication.OnRecall();
				for (int j = 0; j < SNetExt_CaptureBuffer.PassCount; j++)
				{
					List<byte[]> list = sNetExt_CaptureBuffer.m_passes[j];
					int count = list.Count;
					for (int k = 0; k < count; k++)
					{
						byte[] bytes = list[k];
						SNetExt.Replication.RecallBytes(bytes);
					}
				}
				SNetExt.Replication.OnPostRecall();
			}
			finally
			{
				_state = SNetExt_CaptureState.Idle;
			}
		}

		[HideFromIl2Cpp]
		public static bool TryGetInterface<A, B>(A obj, out B intObj) where A : class where B : Object
		{
			intObj = (B)(object)((obj is B) ? obj : null);
			return (Object)(object)intObj != (Object)null;
		}
	}
	public class SNetExt_CaptureBuffer
	{
		public static readonly int PassCount = Enum.GetValues(typeof(SNetExt_BufferType)).Length - 1;

		public bool isValid;

		public SNetExt_BufferType type;

		public pBufferData data;

		public List<byte[]>[] m_passes;

		public SNetExt_CaptureBuffer(SNetExt_BufferType type)
		{
			this.type = type;
			m_passes = new List<byte[]>[PassCount];
			for (int i = 0; i < PassCount; i++)
			{
				m_passes[i] = new List<byte[]>();
			}
		}

		public List<byte[]> GetPass(SNetExt_CapturePass pass)
		{
			if ((int)pass < 0 || (int)pass >= PassCount)
			{
				throw new ArgumentOutOfRangeException("pass", $"pass={pass} must be < PassCount ({PassCount})");
			}
			return m_passes[(uint)pass];
		}

		public void Clear()
		{
			isValid = false;
			for (int i = 0; i < PassCount; i++)
			{
				m_passes[i].Clear();
			}
		}
	}
	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 void StoreLocal(A data)
		{
			m_data = data;
		}

		public override void Send(SNet_Player fromPlayer, SNet_Player toPlayer = null)
		{
			SNetExt_ReplicatedPlayerData<A>.SendData(fromPlayer, m_data, toPlayer);
		}
	}
	public class SNetExt_DynamicReplicator<T> : SNetExt_Replicator, ISNetExt_OwnedReplicator, ISNetExt_MutableReplicator, ISNetExt_Replicator where T : struct, ISNetExt_DynamicReplication
	{
		private bool m_isRegistered;

		private SNetExt_ReplicationManager<T> m_manager;

		private T m_spawnData;

		public override SNetExt_ReplicatorType Type => SNetExt_ReplicatorType.Dynamic;

		public override bool LocallyOwned
		{
			get
			{
				if (!OwnedByMaster)
				{
					if ((Object)(object)OwningPlayer != (Object)null)
					{
						return OwningPlayer.IsLocal;
					}
					return false;
				}
				return SNet.IsMaster;
			}
		}

		SNet_Player ISNetExt_OwnedReplicator.OwningPlayer
		{
			get
			{
				return OwningPlayer;
			}
			set
			{
				SetOwningPlayerInternal(value);
			}
		}

		bool ISNetExt_OwnedReplicator.OwnedByMaster
		{
			get
			{
				return OwnedByMaster;
			}
			set
			{
				SetOwnedByMasterInternal(value);
			}
		}

		public bool HasManager => m_manager != null;

		public void SetManager(SNetExt_ReplicationManager<T> manager)
		{
			m_manager = manager;
			m_isRegistered = manager != null;
		}

		internal void SetSpawnData(T spawnData)
		{
			m_spawnData = spawnData;
		}

		public T GetSpawnData()
		{
			return m_spawnData;
		}

		public bool TryInternalCollectCapture(out T spawnData, out SNetExt_CapturePass captureType)
		{
			if (base.ReplicatorSupplier is ISNetExt_DynamicReplicatorSupplier<T> iSNetExt_DynamicReplicatorSupplier && iSNetExt_DynamicReplicatorSupplier.TryCollectCaptureData(ref m_spawnData, out captureType))
			{
				pReplicationData replicationData = m_spawnData.ReplicationData;
				replicationData.isRecall = true;
				m_spawnData.ReplicationData = replicationData;
				spawnData = m_spawnData;
				return true;
			}
			captureType = SNetExt_CapturePass.Skip;
			spawnData = new T();
			return false;
		}

		public override void Despawn()
		{
			if (m_isRegistered && SNet.IsMaster)
			{
				m_manager.DeSpawn(this);
				return;
			}
			ISNetExt_ReplicatorSupplier replicatorSupplier = base.ReplicatorSupplier;
			base.ReplicatorSupplier = null;
			if ((Object)(object)replicatorSupplier?.gameObject != (Object)null)
			{
				Object.Destroy((Object)(object)replicatorSupplier.gameObject);
			}
		}
	}
	public static class SNetExt_Marshal
	{
		public static SNetExt_Marshaller<T> GetMarshaler<T>() where T : struct
		{
			SNetExt_Marshaller<T> sNetExt_Marshaller = new SNetExt_Marshaller<T>();
			sNetExt_Marshaller.Setup(Marshal.SizeOf<T>());
			return sNetExt_Marshaller;
		}
	}
	public abstract class SNetExt_Marshaller
	{
		protected Type m_marshallingType;

		public abstract void Setup(int size);

		public Type MarshalsType()
		{
			return m_marshallingType;
		}
	}
	public class SNetExt_Marshaller<T> : SNetExt_Marshaller where T : struct
	{
		public int SizeWithIDs;

		public int Size;

		public bool IsBlittable { get; private set; }

		public override void Setup(int size)
		{
			Size = size;
			SizeWithIDs = Size + 33;
			m_marshallingType = typeof(T);
			IsBlittable = DetectBlittable(typeof(T));
		}

		private static bool DetectBlittable(Type type)
		{
			if (type.IsPrimitive)
			{
				return true;
			}
			if (type.IsEnum)
			{
				return true;
			}
			if (type == typeof(string))
			{
				return false;
			}
			if (!type.IsValueType)
			{
				return false;
			}
			if (type == typeof(IntPtr) || type == typeof(UIntPtr))
			{
				return true;
			}
			if (type == typeof(decimal))
			{
				return false;
			}
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (fieldInfo.GetCustomAttribute<MarshalAsAttribute>() != null)
				{
					return false;
				}
				if (!fieldInfo.FieldType.IsValueType)
				{
					return false;
				}
				if (!fieldInfo.FieldType.IsPrimitive && !fieldInfo.FieldType.IsEnum && !DetectBlittable(fieldInfo.FieldType))
				{
					return false;
				}
			}
			return true;
		}

		public virtual void MarshalToBytes(T data, byte[] bytes)
		{
			if (IsBlittable)
			{
				MemoryMarshal.Write(bytes.AsSpan(33, Size), ref data);
				return;
			}
			IntPtr intPtr = Marshal.AllocHGlobal(Size);
			try
			{
				Marshal.StructureToPtr(data, intPtr, fDeleteOld: false);
				Marshal.Copy(intPtr, bytes, 33, Size);
			}
			finally
			{
				Marshal.DestroyStructure<T>(intPtr);
				Marshal.FreeHGlobal(intPtr);
			}
		}

		public void MarshalToData(byte[] bytes, ref T data)
		{
			if (IsBlittable)
			{
				data = MemoryMarshal.Read<T>(bytes.AsSpan(33, Size));
				return;
			}
			IntPtr intPtr = Marshal.AllocHGlobal(Size);
			try
			{
				Marshal.Copy(bytes, 33, intPtr, Size);
				data = (T)Marshal.PtrToStructure(intPtr, m_marshallingType);
			}
			finally
			{
				Marshal.FreeHGlobal(intPtr);
			}
		}
	}
	public class SNetExt_Packet<T> where T : struct
	{
		[ThreadStatic]
		private List<SNet_Player> t_remotePlayerScratch;

		private T m_data = new T();

		private bool m_hasValidateAction;

		public string EventName { get; private set; }

		public SNet_ChannelType ChannelType { get; private set; }

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

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

		public static SNetExt_Packet<T> Create(string eventName, Action<SNet_Player, T> receiveAction, Action<T> validateAction = null, 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)
			};
			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)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			NetworkAPI.InvokeEvent<T>(EventName, data, ChannelType);
		}

		public void Send(T data, SNet_Player player)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (player.IsLocal)
			{
				OnReceiveData(player, data);
			}
			else
			{
				NetworkAPI.InvokeEvent<T>(EventName, data, player, ChannelType);
			}
		}

		public void Send(T data, List<SNet_Player> players)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			if (players == null || players.Count == 0)
			{
				return;
			}
			bool flag = false;
			int num = 0;
			for (int i = 0; i < players.Count; i++)
			{
				if (players[i].IsLocal)
				{
					flag = true;
				}
				else
				{
					num++;
				}
			}
			if (num > 0)
			{
				if (!flag)
				{
					NetworkAPI.InvokeEvent<T>(EventName, data, players, ChannelType);
				}
				else
				{
					List<SNet_Player> remotePlayerScratchList = GetRemotePlayerScratchList();
					remotePlayerScratchList.Clear();
					if (remotePlayerScratchList.Capacity < num)
					{
						remotePlayerScratchList.Capacity = num;
					}
					for (int j = 0; j < players.Count; j++)
					{
						if (!players[j].IsLocal)
						{
							remotePlayerScratchList.Add(players[j]);
						}
					}
					NetworkAPI.InvokeEvent<T>(EventName, data, remotePlayerScratchList, ChannelType);
				}
			}
			if (flag)
			{
				OnReceiveData(SNet.LocalPlayer, data);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private List<SNet_Player> GetRemotePlayerScratchList()
		{
			return t_remotePlayerScratch ?? (t_remotePlayerScratch = new List<SNet_Player>(8));
		}

		private void OnReceiveData(ulong senderId, T data)
		{
			SNet_Player sender = default(SNet_Player);
			if (SNet.TryGetPlayer(senderId, ref sender))
			{
				OnReceiveData(sender, data);
			}
		}

		private void OnReceiveData(SNet_Player sender, T data)
		{
			m_data = data;
			if (m_hasValidateAction && SNet.IsMaster)
			{
				ValidateAction(m_data);
			}
			else
			{
				ReceiveAction(sender, m_data);
			}
		}

		protected SNetExt_Packet()
		{
		}
	}
	public class SNetExt_PrefabReplicationManager : MonoBehaviour, ISNetExt_Manager
	{
		private readonly Dictionary<Type, SNetExt_ReplicationManager> m_repManagers = new Dictionary<Type, SNetExt_ReplicationManager>(16);

		[HideFromIl2Cpp]
		public void OnValidateMasterData()
		{
		}

		[HideFromIl2Cpp]
		public void SetupReplicationFor<TData>(Action<ISNetExt_Replicator, bool> callback = null) where TData : struct, ISNetExt_DynamicReplication
		{
			GetRepManager(out SNetExt_ReplicationManager<TData, SNetExt_DynamicReplicator<TData>> repManager);
			repManager.SpawnDespawnCallback = callback;
		}

		[HideFromIl2Cpp]
		public void ClearPrefabs<TData>() where TData : struct, ISNetExt_DynamicReplication
		{
			GetRepManager(out SNetExt_ReplicationManager<TData, SNetExt_DynamicReplicator<TData>> repManager);
			repManager.ClearPrefabs();
		}

		[HideFromIl2Cpp]
		public void AddPrefab<TData>(string prefabKey, GameObject prefab) where TData : struct, ISNetExt_DynamicReplication
		{
			GetRepManager(out SNetExt_ReplicationManager<TData, SNetExt_DynamicReplicator<TData>> repManager);
			repManager.AddPrefab(prefabKey, prefab);
		}

		[HideFromIl2Cpp]
		public bool RemovePrefab<TData>(string prefabKey) where TData : struct, ISNetExt_DynamicReplication
		{
			GetRepManager(out SNetExt_ReplicationManager<TData, SNetExt_DynamicReplicator<TData>> repManager);
			return repManager.RemovePrefab(prefabKey);
		}

		[HideFromIl2Cpp]
		public bool RemovePrefab<TData>(GameObject prefab) where TData : struct, ISNetExt_DynamicReplication
		{
			GetRepManager(out SNetExt_ReplicationManager<TData, SNetExt_DynamicReplicator<TData>> repManager);
			return repManager.RemovePrefab(prefab);
		}

		[HideFromIl2Cpp]
		private void GetRepManager<TReplicator, TData>(out SNetExt_ReplicationManager<TData, TReplicator> repManager) where TReplicator : SNetExt_DynamicReplicator<TData>, new() where TData : struct, ISNetExt_DynamicReplication
		{
			Type typeFromHandle = typeof(TData);
			if (m_repManagers.TryGetValue(typeFromHandle, out var value))
			{
				repManager = value as SNetExt_ReplicationManager<TData, TReplicator>;
				if (repManager == null)
				{
					throw new InvalidOperationException($"Manager for {typeFromHandle.Name} was registered with a different TReplicator (existing: {value.GetType().Name})");
				}
			}
			else
			{
				repManager = new SNetExt_ReplicationManager<TData, TReplicator>((SNet_ChannelType)2);
				m_repManagers.Add(typeFromHandle, repManager);
			}
		}

		[HideFromIl2Cpp]
		public void Spawn<TData>(GameObject prefab, TData spawnData) where TData : struct, ISNetExt_DynamicReplication
		{
			GetRepManager(out SNetExt_ReplicationManager<TData, SNetExt_DynamicReplicator<TData>> repManager);
			repManager.Spawn(prefab, spawnData);
		}

		[HideFromIl2Cpp]
		public List<SNetExt_DynamicReplicator<TData>> GetReplicatorList<TData>() where TData : struct, ISNetExt_DynamicReplication
		{
			GetRepManager(out SNetExt_ReplicationManager<TData, SNetExt_DynamicReplicator<TData>> repManager);
			return repManager.m_replicators;
		}

		[HideFromIl2Cpp]
		public void Setup()
		{
		}

		[HideFromIl2Cpp]
		public void SetupReplication()
		{
		}

		[HideFromIl2Cpp]
		public void OnResetSession()
		{
		}

		[HideFromIl2Cpp]
		public void OnClearAllSpawnedLocal()
		{
			foreach (KeyValuePair<Type, SNetExt_ReplicationManager> repManager in m_repManagers)
			{
				repManager.Value.ClearAllLocal();
			}
		}
	}
	public abstract class SNetExt_ReplicatedPacket
	{
		private string m_key;

		private string m_keyHash;

		private byte[] m_keyHashBytes;

		private static readonly byte[] s_emptyHashBytes = new byte[16];

		public ISNetExt_Replicator Replicator { get; private set; }

		public byte Index { get; private set; }

		public string Key
		{
			get
			{
				return m_key;
			}
			set
			{
				m_key = value ?? string.Empty;
				if (string.IsNullOrWhiteSpace(m_key))
				{
					m_keyHash = string.Empty;
					m_keyHashBytes = s_emptyHashBytes;
					return;
				}
				Span<byte> span = stackalloc byte[16];
				SNetExt_HashUtil.KeyToHashBytes(m_key, span);
				m_keyHash = SNetExt_HashUtil.HashBytesToHex(span);
				m_keyHashBytes = span.ToArray();
			}
		}

		public string KeyHash
		{
			get
			{
				return m_keyHash;
			}
			set
			{
				m_keyHash = value ?? string.Empty;
				if (string.IsNullOrWhiteSpace(m_keyHash) || m_keyHash.Length != 32)
				{
					m_keyHashBytes = s_emptyHashBytes;
				}
				else
				{
					m_keyHashBytes = SNetExt_HashUtil.HashHexToBytes(m_keyHash);
				}
			}
		}

		public byte[] KeyHashBytes
		{
			get
			{
				return m_keyHashBytes;
			}
			private set
			{
				m_keyHashBytes = value;
			}
		}

		public bool IsAnonymous => string.IsNullOrWhiteSpace(Key);

		public bool HasValidKeyHash
		{
			get
			{
				if (!string.IsNullOrWhiteSpace(KeyHash))
				{
					return KeyHash.Length == 32;
				}
				return false;
			}
		}

		public virtual void Setup(ISNetExt_Replicator replicator, byte index)
		{
			if (string.IsNullOrWhiteSpace(Key))
			{
				Key = GetType().FullName;
			}
			Replicator = replicator;
			Index = index;
		}

		public virtual void ReceiveBytes(byte[] bytes)
		{
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		protected void InjectIDPacketIndex(byte[] bytes)
		{
			Replicator.KeyHashBytes.CopyTo(bytes.AsSpan(0, 16));
			Buffer.BlockCopy(KeyHashBytes, 0, bytes, 16, 16);
			bytes[32] = Index;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void InjectIDPacketIndex(SNetExt_ReplicatedPacket packet, byte[] bytes, ReadOnlySpan<byte> replicatorKeyHashBytes, byte[] packetKeyHashBytes)
		{
			replicatorKeyHashBytes.CopyTo(bytes.AsSpan(0, 16));
			Buffer.BlockCopy(packetKeyHashBytes, 0, bytes, 16, 16);
			bytes[32] = packet.Index;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static byte[] PacketKeyHashToBytes(string keyHash)
		{
			return SNetExt_HashUtil.HashHexToBytes(keyHash);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static string PacketKeyToHash(string key)
		{
			return SNetExt_HashUtil.KeyToHashHex(key);
		}
	}
	public class SNetExt_ReplicatedPacket<T> : SNetExt_ReplicatedPacket where T : struct
	{
		private T m_data = new T();

		private byte[] m_internalBytes;

		private bool m_hasValidateAction;

		private static bool s_hasMarshaller;

		private static SNetExt_Marshaller<T> s_marshaller;

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

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

		public override void Setup(ISNetExt_Replicator replicator, byte index)
		{
			if (string.IsNullOrWhiteSpace(base.Key))
			{
				base.Key = typeof(T).FullName;
			}
			base.Setup(replicator, index);
			SetInternalSize();
		}

		public static SNetExt_ReplicatedPacket<T> Create(string key, Action<T> receiveAction, Action<T> validateAction = null)
		{
			if (!s_hasMarshaller)
			{
				s_marshaller = SNetExt_Marshal.GetMarshaler<T>();
				s_hasMarshaller = s_marshaller != null;
				if (!s_hasMarshaller)
				{
					return null;
				}
			}
			return new SNetExt_ReplicatedPacket<T>
			{
				Key = (string.IsNullOrWhiteSpace(key) ? typeof(T).FullName : key),
				ReceiveAction = receiveAction,
				ValidateAction = validateAction,
				m_hasValidateAction = (validateAction != null)
			};
		}

		public void Ask(T data, SNet_ChannelType channelType = 0)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (SNet.IsMaster)
			{
				ValidateAction(data);
			}
			else if (SNet.HasMaster)
			{
				Send(data, channelType, SNet.Master);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void Send(T data, SNet_ChannelType type)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			WritePayload(data);
			NetworkAPI.InvokeFreeSizedEvent("SNetExt_Replication", m_internalBytes, type);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void Send(T data, SNet_ChannelType type, SNet_Player player)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			WritePayload(data);
			NetworkAPI.InvokeFreeSizedEvent("SNetExt_Replication", m_internalBytes, player, type);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public void Send(T data, SNet_ChannelType type, List<SNet_Player> players)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			WritePayload(data);
			NetworkAPI.InvokeFreeSizedEvent("SNetExt_Replication", m_internalBytes, (IEnumerable<SNet_Player>)players, type);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void WritePayload(T data)
		{
			if (s_marshaller.IsBlittable)
			{
				MemoryMarshal.Write(m_internalBytes.AsSpan(33, s_marshaller.Size), ref data);
				return;
			}
			IntPtr intPtr = Marshal.AllocHGlobal(s_marshaller.Size);
			try
			{
				Marshal.StructureToPtr(data, intPtr, fDeleteOld: false);
				Marshal.Copy(intPtr, m_internalBytes, 33, s_marshaller.Size);
			}
			finally
			{
				Marshal.DestroyStructure<T>(intPtr);
				Marshal.FreeHGlobal(intPtr);
			}
		}

		internal void CaptureToBuffer(T data, SNetExt_CapturePass captureDataType)
		{
			s_marshaller.MarshalToBytes(data, m_internalBytes);
			SNetExt.Capture.CaptureToBuffer(m_internalBytes, captureDataType);
		}

		public override void ReceiveBytes(byte[] bytes)
		{
			if (bytes.Length != s_marshaller.SizeWithIDs)
			{
				SNetExt.Logger.Warning($"ReceiveBytes<{typeof(T).Name}>: size mismatch (expected {s_marshaller.SizeWithIDs}, got {bytes.Length})");
			}
			else
			{
				s_marshaller.MarshalToData(bytes, ref m_data);
				if (m_hasValidateAction && SNet.IsMaster)
				{
					ValidateAction(m_data);
				}
				else
				{
					ReceiveAction(m_data);
				}
			}
		}

		private void SetInternalSize()
		{
			m_internalBytes = new byte[s_marshaller.SizeWithIDs];
			InjectIDPacketIndex(m_internalBytes);
		}
	}
	public class SNetExt_ReplicatedPacketBufferBytes : SNetExt_ReplicatedPacket
	{
		public delegate void SpanBufferReceiveDelegate(ReadOnlySpan<byte> payload, BufferData bufferData);

		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
		public struct BufferData
		{
			public ushort bufferID;

			public byte pass;

			public BufferData(ushort bufferID, byte pass)
			{
				this.bufferID = bufferID;
				this.pass = pass;
			}
		}

		public static readonly int BUFFER_DATA_BYTE_SIZE = Marshal.SizeOf<BufferData>();

		private SNet_ChannelType m_channelType;

		public SNet_ChannelType ChannelType
		{
			get
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return m_channelTyp

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

Decompiled 6 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using Hikaria.Core.SourceGenerators.Emitters;
using Hikaria.Core.SourceGenerators.Internal;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("Hikaria.Core.SourceGenerators")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+8e797dd13b1c12c7844f86fafa6094111cf7b07a")]
[assembly: AssemblyProduct("Hikaria.Core.SourceGenerators")]
[assembly: AssemblyTitle("Hikaria.Core.SourceGenerators")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
	internal static class IsExternalInit
	{
	}
}
namespace Hikaria.Core.SourceGenerators
{
	internal static class Diagnostics
	{
		private const string Category = "NativeDetour";

		public static readonly DiagnosticDescriptor EZD001_NotPartial = new DiagnosticDescriptor("EZD001", "包含 [NativeDetour] 方法的类必须声明为 partial", "类 '{0}' 含有 [NativeDetour] 方法,必须声明为 partial 才能由源生成器扩展", "NativeDetour", (DiagnosticSeverity)3, true, (string)null, (string)null, Array.Empty<string>());

		public static readonly DiagnosticDescriptor EZD002_NotStatic = new DiagnosticDescriptor("EZD002", "[NativeDetour] hook 方法必须 static", "[NativeDetour] hook 方法 '{0}' 必须是 static", "NativeDetour", (DiagnosticSeverity)3, true, (string)null, (string)null, Array.Empty<string>());

		public static readonly DiagnosticDescriptor EZD003_BadLastParam = new DiagnosticDescriptor("EZD003", "hook 末参必须是 Il2CppMethodInfo*", "[NativeDetour] hook 方法 '{0}' 的最后一个参数必须是 'Il2CppMethodInfo*' 类型,实际为 '{1}'", "NativeDetour", (DiagnosticSeverity)3, true, (string)null, (string)null, Array.Empty<string>());

		public static readonly DiagnosticDescriptor EZD004_BadFirstParam = new DiagnosticDescriptor("EZD004", "实例方法首参必须是 IntPtr", "[NativeDetour] 实例方法 hook '{0}' 的第一个参数必须是 IntPtr;若目标是静态方法,请在 attribute 上设置 'Static = true'", "NativeDetour", (DiagnosticSeverity)3, true, (string)null, (string)null, Array.Empty<string>());

		public static readonly DiagnosticDescriptor EZD005_DuplicateTarget = new DiagnosticDescriptor("EZD005", "目标方法被多个 hook 重复 detour", "目标方法 '{0}' 已被 '{1}' 注解,不能再由 '{2}' 重复 detour", "NativeDetour", (DiagnosticSeverity)3, true, (string)null, (string)null, Array.Empty<string>());

		public static readonly DiagnosticDescriptor EZD006_StemConflict = new DiagnosticDescriptor("EZD006", "Stem 命名冲突", "类 '{0}' 中存在多个 hook 方法导致生成名称 '{1}_Handle' 冲突", "NativeDetour", (DiagnosticSeverity)3, true, (string)null, (string)null, Array.Empty<string>());

		public static readonly DiagnosticDescriptor EZD007_GenericContainer = new DiagnosticDescriptor("EZD007", "包含类不能是泛型", "[NativeDetour] hook 不能位于泛型类 '{0}<...>' 中", "NativeDetour", (DiagnosticSeverity)3, true, (string)null, (string)null, Array.Empty<string>());

		public static readonly DiagnosticDescriptor EZD008_BadModifier = new DiagnosticDescriptor("EZD008", "hook 方法形态不合法", "[NativeDetour] hook 方法 '{0}' 不能是 {1}", "NativeDetour", (DiagnosticSeverity)3, true, (string)null, (string)null, Array.Empty<string>());

		public static readonly DiagnosticDescriptor EZD009_CtorWithMethodName = new DiagnosticDescriptor("EZD009", "构造器不应填 MethodName", "当 Member=Constructor 时,MethodName 应省略或为空(SG 自动解糖为 \".ctor\")", "NativeDetour", (DiagnosticSeverity)3, true, (string)null, (string)null, Array.Empty<string>());

		public static readonly DiagnosticDescriptor EZD010_PropMissingName = new DiagnosticDescriptor("EZD010", "Getter/Setter 必须有属性名", "Member={0} 时必须提供属性名作为 MethodName", "NativeDetour", (DiagnosticSeverity)3, true, (string)null, (string)null, Array.Empty<string>());

		public static readonly DiagnosticDescriptor EZD011_UnresolvedDeclaringType = new DiagnosticDescriptor("EZD011", "DeclaringType 必须可解析", "[NativeDetour] 的 DeclaringType 无法解析为已知类型", "NativeDetour", (DiagnosticSeverity)3, true, (string)null, (string)null, Array.Empty<string>());

		public static readonly DiagnosticDescriptor EZD012_TypeArgsIgnored = new DiagnosticDescriptor("EZD012", "TypeArguments 与 Member 不兼容", "TypeArguments 仅在 Member=Method 时有效,当前 Member={0} 将被忽略", "NativeDetour", (DiagnosticSeverity)2, true, (string)null, (string)null, Array.Empty<string>());

		public static readonly DiagnosticDescriptor EZD014_GenericMethodExperimental = new DiagnosticDescriptor("EZD014", "方法级泛型 detour 是试验性能力", "方法级泛型 detour 是试验性能力,请验证目标方法能正确解析", "NativeDetour", (DiagnosticSeverity)1, true, (string)null, (string)null, Array.Empty<string>());
	}
	public sealed record HookInfo(string ContainingNamespace, EquatableArray<string> ContainingTypeChain, bool ContainingIsPartial, bool ContainingIsStatic, Accessibility ContainingAccessibility, string HookMethodName, string Stem, string ReturnTypeSyntax, EquatableArray<ParamInfo> Parameters, bool HookIsStatic, string TargetDeclaringTypeSyntax, string TargetMethodNameOrCtor, NativeDetourMember TargetMember, bool TargetIsStatic, EquatableArray<string> TargetTypeArgumentSyntax, FileLinePositionSpan HookSpan, EquatableArray<DiagnosticInfo> Diagnostics)
	{
		[CompilerGenerated]
		private bool PrintMembers(StringBuilder builder)
		{
			//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_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			RuntimeHelpers.EnsureSufficientExecutionStack();
			builder.Append("ContainingNamespace = ");
			builder.Append((object?)ContainingNamespace);
			builder.Append(", ContainingTypeChain = ");
			builder.Append(ContainingTypeChain.ToString());
			builder.Append(", ContainingIsPartial = ");
			builder.Append(ContainingIsPartial.ToString());
			builder.Append(", ContainingIsStatic = ");
			builder.Append(ContainingIsStatic.ToString());
			builder.Append(", ContainingAccessibility = ");
			Accessibility containingAccessibility = ContainingAccessibility;
			builder.Append(((object)(Accessibility)(ref containingAccessibility)).ToString());
			builder.Append(", HookMethodName = ");
			builder.Append((object?)HookMethodName);
			builder.Append(", Stem = ");
			builder.Append((object?)Stem);
			builder.Append(", ReturnTypeSyntax = ");
			builder.Append((object?)ReturnTypeSyntax);
			builder.Append(", Parameters = ");
			builder.Append(Parameters.ToString());
			builder.Append(", HookIsStatic = ");
			builder.Append(HookIsStatic.ToString());
			builder.Append(", TargetDeclaringTypeSyntax = ");
			builder.Append((object?)TargetDeclaringTypeSyntax);
			builder.Append(", TargetMethodNameOrCtor = ");
			builder.Append((object?)TargetMethodNameOrCtor);
			builder.Append(", TargetMember = ");
			builder.Append(TargetMember.ToString());
			builder.Append(", TargetIsStatic = ");
			builder.Append(TargetIsStatic.ToString());
			builder.Append(", TargetTypeArgumentSyntax = ");
			builder.Append(TargetTypeArgumentSyntax.ToString());
			builder.Append(", HookSpan = ");
			FileLinePositionSpan hookSpan = HookSpan;
			builder.Append(((object)(FileLinePositionSpan)(ref hookSpan)).ToString());
			builder.Append(", Diagnostics = ");
			builder.Append(Diagnostics.ToString());
			return true;
		}

		[CompilerGenerated]
		public void Deconstruct(out string ContainingNamespace, out EquatableArray<string> ContainingTypeChain, out bool ContainingIsPartial, out bool ContainingIsStatic, out Accessibility ContainingAccessibility, out string HookMethodName, out string Stem, out string ReturnTypeSyntax, out EquatableArray<ParamInfo> Parameters, out bool HookIsStatic, out string TargetDeclaringTypeSyntax, out string TargetMethodNameOrCtor, out NativeDetourMember TargetMember, out bool TargetIsStatic, out EquatableArray<string> TargetTypeArgumentSyntax, out FileLinePositionSpan HookSpan, out EquatableArray<DiagnosticInfo> Diagnostics)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected I4, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			ContainingNamespace = this.ContainingNamespace;
			ContainingTypeChain = this.ContainingTypeChain;
			ContainingIsPartial = this.ContainingIsPartial;
			ContainingIsStatic = this.ContainingIsStatic;
			ContainingAccessibility = (Accessibility)(int)this.ContainingAccessibility;
			HookMethodName = this.HookMethodName;
			Stem = this.Stem;
			ReturnTypeSyntax = this.ReturnTypeSyntax;
			Parameters = this.Parameters;
			HookIsStatic = this.HookIsStatic;
			TargetDeclaringTypeSyntax = this.TargetDeclaringTypeSyntax;
			TargetMethodNameOrCtor = this.TargetMethodNameOrCtor;
			TargetMember = this.TargetMember;
			TargetIsStatic = this.TargetIsStatic;
			TargetTypeArgumentSyntax = this.TargetTypeArgumentSyntax;
			HookSpan = this.HookSpan;
			Diagnostics = this.Diagnostics;
		}
	}
	public sealed record ParamInfo(string TypeSyntax, string Name) : IEquatable<ParamInfo>;
	public sealed record DiagnosticInfo(string Id, string Message, FileLinePositionSpan Span) : IEquatable<DiagnosticInfo>
	{
		[CompilerGenerated]
		private bool PrintMembers(StringBuilder builder)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			RuntimeHelpers.EnsureSufficientExecutionStack();
			builder.Append("Id = ");
			builder.Append((object?)Id);
			builder.Append(", Message = ");
			builder.Append((object?)Message);
			builder.Append(", Span = ");
			FileLinePositionSpan span = Span;
			builder.Append(((object)(FileLinePositionSpan)(ref span)).ToString());
			return true;
		}
	}
	public enum NativeDetourMember
	{
		Method,
		Constructor,
		Getter,
		Setter
	}
	internal static class HookMethodAnalyzer
	{
		internal record struct AttrInfo(string DeclaringTypeSyntax, string MethodName, bool IsStatic, NativeDetourMember Member, EquatableArray<string> TypeArgumentSyntax);

		private const string Il2CppMethodInfoFullName = "global::Il2CppInterop.Runtime.Runtime.Il2CppMethodInfo*";

		public static HookInfo? Analyze(GeneratorAttributeSyntaxContext ctx, CancellationToken ct)
		{
			//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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			ISymbol targetSymbol = ((GeneratorAttributeSyntaxContext)(ref ctx)).TargetSymbol;
			IMethodSymbol val = (IMethodSymbol)(object)((targetSymbol is IMethodSymbol) ? targetSymbol : null);
			if (val == null)
			{
				return null;
			}
			SyntaxNode targetNode = ((GeneratorAttributeSyntaxContext)(ref ctx)).TargetNode;
			MethodDeclarationSyntax val2 = (MethodDeclarationSyntax)(object)((targetNode is MethodDeclarationSyntax) ? targetNode : null);
			if (val2 == null)
			{
				return null;
			}
			List<DiagnosticInfo> list = new List<DiagnosticInfo>();
			SyntaxToken identifier = val2.Identifier;
			FileLinePositionSpan lineSpan = ((SyntaxToken)(ref identifier)).GetLocation().GetLineSpan();
			(string, EquatableArray<string>, bool, bool, Accessibility) tuple = ExtractContainingType(val, val2, lineSpan, list);
			ValidateHookMethodForm(val, val2, lineSpan, list);
			AttributeData val3 = ((GeneratorAttributeSyntaxContext)(ref ctx)).Attributes.FirstOrDefault();
			if (val3 == null)
			{
				return null;
			}
			AttrInfo attr = ExtractAttributeInfo(val3, lineSpan, list);
			ValidateSignature(val, attr.IsStatic, attr.Member, lineSpan, list);
			ValidateMemberAndMethodName(attr, lineSpan, list);
			ValidateTypeArguments(attr, lineSpan, list);
			EquatableArray<ParamInfo> parameters = ExtractParameters(val);
			string returnTypeSyntax = TypeSyntax(val.ReturnType);
			string stem = DeriveStem(((ISymbol)val).Name);
			string targetMethodNameOrCtor = DesugarTargetMethodName(attr);
			return new HookInfo(tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4, tuple.Item5, ((ISymbol)val).Name, stem, returnTypeSyntax, parameters, ((ISymbol)val).IsStatic, attr.DeclaringTypeSyntax, targetMethodNameOrCtor, attr.Member, attr.IsStatic, attr.TypeArgumentSyntax, lineSpan, new EquatableArray<DiagnosticInfo>(list));
		}

		private static (string Namespace, EquatableArray<string> Chain, bool IsPartial, bool IsStatic, Accessibility Accessibility) ExtractContainingType(IMethodSymbol m, MethodDeclarationSyntax decl, FileLinePositionSpan loc, List<DiagnosticInfo> diags)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			INamedTypeSymbol containingType = ((ISymbol)m).ContainingType;
			string item = (((ISymbol)containingType).ContainingNamespace.IsGlobalNamespace ? string.Empty : ((ISymbol)((ISymbol)containingType).ContainingNamespace).ToDisplayString((SymbolDisplayFormat)null));
			List<string> list = new List<string>();
			for (INamedTypeSymbol val = containingType; val != null; val = ((ISymbol)val).ContainingType)
			{
				list.Insert(0, ((ISymbol)val).Name);
			}
			if (containingType.IsGenericType || containingType.TypeParameters.Length > 0)
			{
				diags.Add(new DiagnosticInfo("EZD007", $"[NativeDetour] hook 不能位于泛型类 '{((ISymbol)containingType).Name}<...>' 中", loc));
			}
			bool item2 = true;
			SyntaxNode parent = ((SyntaxNode)decl).Parent;
			TypeDeclarationSyntax val2 = (TypeDeclarationSyntax)(object)((parent is TypeDeclarationSyntax) ? parent : null);
			while (val2 != null)
			{
				if (!((IEnumerable<SyntaxToken>)(object)((MemberDeclarationSyntax)val2).Modifiers).Any((SyntaxToken m2) => CSharpExtensions.IsKind(m2, (SyntaxKind)8406)))
				{
					item2 = false;
					SyntaxToken identifier = ((BaseTypeDeclarationSyntax)val2).Identifier;
					diags.Add(new DiagnosticInfo("EZD001", $"类 '{((SyntaxToken)(ref identifier)).Text}' 含有 [NativeDetour] 方法,必须声明为 partial 才能由源生成器扩展", loc));
				}
				SyntaxNode parent2 = ((SyntaxNode)val2).Parent;
				val2 = (TypeDeclarationSyntax)(object)((parent2 is TypeDeclarationSyntax) ? parent2 : null);
			}
			return (item, new EquatableArray<string>(list), item2, ((ISymbol)containingType).IsStatic, ((ISymbol)containingType).DeclaredAccessibility);
		}

		private static void ValidateHookMethodForm(IMethodSymbol m, MethodDeclarationSyntax decl, FileLinePositionSpan loc, List<DiagnosticInfo> diags)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			if (!((ISymbol)m).IsStatic)
			{
				diags.Add(new DiagnosticInfo("EZD002", $"[NativeDetour] hook 方法 '{((ISymbol)m).Name}' 必须是 static", loc));
			}
			string text = null;
			if (((ISymbol)m).IsAbstract)
			{
				text = "abstract";
			}
			else if (((ISymbol)m).IsVirtual)
			{
				text = "virtual";
			}
			else if (((ISymbol)m).IsExtern)
			{
				text = "extern";
			}
			else if (m.IsAsync)
			{
				text = "async";
			}
			else if (m.IsPartialDefinition)
			{
				text = "partial";
			}
			if (text != null)
			{
				diags.Add(new DiagnosticInfo("EZD008", $"[NativeDetour] hook 方法 '{((ISymbol)m).Name}' 不能是 {text}", loc));
			}
		}

		private static AttrInfo ExtractAttributeInfo(AttributeData attr, FileLinePositionSpan loc, List<DiagnosticInfo> diags)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Invalid comparison between Unknown and I4
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			string declaringTypeSyntax = "global::System.Object";
			string methodName = string.Empty;
			bool isStatic = false;
			NativeDetourMember member = NativeDetourMember.Method;
			List<string> list = new List<string>();
			ImmutableArray<TypedConstant> constructorArguments = attr.ConstructorArguments;
			TypedConstant val;
			if (constructorArguments.Length >= 1)
			{
				val = constructorArguments[0];
				object value = ((TypedConstant)(ref val)).Value;
				INamedTypeSymbol val2 = (INamedTypeSymbol)((value is INamedTypeSymbol) ? value : null);
				if (val2 != null && (int)((ITypeSymbol)val2).TypeKind != 6)
				{
					declaringTypeSyntax = ((ISymbol)val2).ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
				}
				else
				{
					diags.Add(new DiagnosticInfo("EZD011", "[NativeDetour] 的 DeclaringType 无法解析为已知类型", loc));
				}
			}
			if (constructorArguments.Length >= 2)
			{
				val = constructorArguments[1];
				if (((TypedConstant)(ref val)).Value is string text)
				{
					methodName = text;
					goto IL_00b1;
				}
			}
			if (constructorArguments.Length == 1)
			{
				member = NativeDetourMember.Constructor;
				methodName = string.Empty;
			}
			goto IL_00b1;
			IL_00b1:
			ImmutableArray<KeyValuePair<string, TypedConstant>>.Enumerator enumerator = attr.NamedArguments.GetEnumerator();
			while (enumerator.MoveNext())
			{
				KeyValuePair<string, TypedConstant> current = enumerator.Current;
				string key = current.Key;
				TypedConstant value2 = current.Value;
				switch (key)
				{
				case "Static":
					isStatic = (bool)(((TypedConstant)(ref value2)).Value ?? ((object)false));
					break;
				case "Member":
					member = (NativeDetourMember)(int)(((TypedConstant)(ref value2)).Value ?? ((object)0));
					break;
				case "TypeArguments":
				{
					if (((TypedConstant)(ref value2)).Values.IsDefaultOrEmpty)
					{
						break;
					}
					ImmutableArray<TypedConstant>.Enumerator enumerator2 = ((TypedConstant)(ref value2)).Values.GetEnumerator();
					while (enumerator2.MoveNext())
					{
						TypedConstant current2 = enumerator2.Current;
						object value3 = ((TypedConstant)(ref current2)).Value;
						ITypeSymbol val3 = (ITypeSymbol)((value3 is ITypeSymbol) ? value3 : null);
						if (val3 != null)
						{
							list.Add(((ISymbol)val3).ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));
						}
					}
					break;
				}
				}
			}
			return new AttrInfo(declaringTypeSyntax, methodName, isStatic, member, new EquatableArray<string>(list));
		}

		private static void ValidateSignature(IMethodSymbol m, bool targetIsStatic, NativeDetourMember member, FileLinePositionSpan loc, List<DiagnosticInfo> diags)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Invalid comparison between Unknown and I4
			ImmutableArray<IParameterSymbol> parameters = m.Parameters;
			if (parameters.Length == 0)
			{
				diags.Add(new DiagnosticInfo("EZD003", "[NativeDetour] hook 方法 '" + ((ISymbol)m).Name + "' 的最后一个参数必须是 'Il2CppMethodInfo*' 类型,实际为 '(无参)'", loc));
				return;
			}
			string text = ((ISymbol)parameters[parameters.Length - 1].Type).ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
			if (text != "global::Il2CppInterop.Runtime.Runtime.Il2CppMethodInfo*")
			{
				diags.Add(new DiagnosticInfo("EZD003", "[NativeDetour] hook 方法 '" + ((ISymbol)m).Name + "' 的最后一个参数必须是 'Il2CppMethodInfo*' 类型,实际为 '" + text + "'", loc));
			}
			if (!targetIsStatic && (parameters.Length < 1 || (int)parameters[0].Type.SpecialType != 21))
			{
				diags.Add(new DiagnosticInfo("EZD004", "[NativeDetour] 实例方法 hook '" + ((ISymbol)m).Name + "' 的第一个参数必须是 IntPtr;若目标是静态方法,请在 attribute 上设置 'Static = true'", loc));
			}
		}

		private static void ValidateMemberAndMethodName(AttrInfo attr, FileLinePositionSpan loc, List<DiagnosticInfo> diags)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			if (attr.Member == NativeDetourMember.Constructor && !string.IsNullOrEmpty(attr.MethodName))
			{
				diags.Add(new DiagnosticInfo("EZD009", "当 Member=Constructor 时,MethodName 应省略或为空(SG 自动解糖为 \".ctor\")", loc));
			}
			if ((attr.Member == NativeDetourMember.Getter || attr.Member == NativeDetourMember.Setter) && string.IsNullOrWhiteSpace(attr.MethodName))
			{
				diags.Add(new DiagnosticInfo("EZD010", $"Member={attr.Member} 时必须提供属性名作为 MethodName", loc));
			}
		}

		private static void ValidateTypeArguments(AttrInfo attr, FileLinePositionSpan loc, List<DiagnosticInfo> diags)
		{
			//IL_0051: 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)
			if (!attr.TypeArgumentSyntax.IsEmpty)
			{
				if (attr.Member != 0)
				{
					diags.Add(new DiagnosticInfo("EZD012", $"TypeArguments 仅在 Member=Method 时有效,当前 Member={attr.Member} 将被忽略", loc));
				}
				else
				{
					diags.Add(new DiagnosticInfo("EZD014", "方法级泛型 detour 是试验性能力,请验证目标方法能正确解析", loc));
				}
			}
		}

		private static EquatableArray<ParamInfo> ExtractParameters(IMethodSymbol m)
		{
			List<ParamInfo> list = new List<ParamInfo>(m.Parameters.Length);
			ImmutableArray<IParameterSymbol>.Enumerator enumerator = m.Parameters.GetEnumerator();
			while (enumerator.MoveNext())
			{
				IParameterSymbol current = enumerator.Current;
				list.Add(new ParamInfo(((ISymbol)current.Type).ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat), ((ISymbol)current).Name));
			}
			return new EquatableArray<ParamInfo>(list);
		}

		private static string TypeSyntax(ITypeSymbol t)
		{
			return ((ISymbol)t).ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
		}

		private static string DeriveStem(string hookName)
		{
			if (!hookName.EndsWith("_Hook"))
			{
				return hookName;
			}
			return hookName.Substring(0, hookName.Length - "_Hook".Length);
		}

		private static string DesugarTargetMethodName(AttrInfo attr)
		{
			return attr.Member switch
			{
				NativeDetourMember.Constructor => ".ctor", 
				NativeDetourMember.Getter => "get_" + attr.MethodName, 
				NativeDetourMember.Setter => "set_" + attr.MethodName, 
				_ => attr.MethodName, 
			};
		}
	}
	[Generator("C#", new string[] { })]
	public sealed class NativeDetourGenerator : IIncrementalGenerator
	{
		public const string AttributeFullName = "Hikaria.Core.Detour.NativeDetourAttribute";

		public void Initialize(IncrementalGeneratorInitializationContext context)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			SyntaxValueProvider syntaxProvider = ((IncrementalGeneratorInitializationContext)(ref context)).SyntaxProvider;
			IncrementalValueProvider<ImmutableArray<HookInfo>> val = IncrementalValueProviderExtensions.Collect<HookInfo>(IncrementalValueProviderExtensions.Select<HookInfo, HookInfo>(IncrementalValueProviderExtensions.Where<HookInfo>(((SyntaxValueProvider)(ref syntaxProvider)).ForAttributeWithMetadataName<HookInfo>("Hikaria.Core.Detour.NativeDetourAttribute", (Func<SyntaxNode, CancellationToken, bool>)((SyntaxNode node, CancellationToken _) => node is MethodDeclarationSyntax), (Func<GeneratorAttributeSyntaxContext, CancellationToken, HookInfo>)((GeneratorAttributeSyntaxContext ctx, CancellationToken ct) => HookMethodAnalyzer.Analyze(ctx, ct))), (Func<HookInfo, bool>)((HookInfo info) => (object)info != null)), (Func<HookInfo, CancellationToken, HookInfo>)((HookInfo info, CancellationToken _) => info)));
			((IncrementalGeneratorInitializationContext)(ref context)).RegisterSourceOutput<ImmutableArray<HookInfo>>(val, (Action<SourceProductionContext, ImmutableArray<HookInfo>>)delegate(SourceProductionContext ctx, ImmutableArray<HookInfo> all)
			{
				List<DiagnosticInfo> list = DetectCrossHookConflicts(all);
				ImmutableArray<HookInfo>.Enumerator enumerator = all.GetEnumerator();
				while (enumerator.MoveNext())
				{
					foreach (DiagnosticInfo diagnostic in enumerator.Current.Diagnostics)
					{
						((SourceProductionContext)(ref ctx)).ReportDiagnostic(MakeDiagnostic(diagnostic));
					}
				}
				foreach (DiagnosticInfo item in list)
				{
					((SourceProductionContext)(ref ctx)).ReportDiagnostic(MakeDiagnostic(item));
				}
				Dictionary<string, List<HookInfo>> dictionary = new Dictionary<string, List<HookInfo>>();
				enumerator = all.GetEnumerator();
				while (enumerator.MoveNext())
				{
					HookInfo current3 = enumerator.Current;
					if (!current3.Diagnostics.AsImmutableArray().Any(delegate(DiagnosticInfo d)
					{
						switch (d.Id)
						{
						case "EZD001":
						case "EZD011":
						case "EZD002":
						case "EZD003":
						case "EZD004":
						case "EZD007":
						case "EZD008":
						case "EZD009":
						case "EZD010":
							return true;
						default:
							return false;
						}
					}))
					{
						string key = current3.ContainingNamespace + "::" + string.Join("+", current3.ContainingTypeChain.AsImmutableArray());
						if (!dictionary.TryGetValue(key, out var value))
						{
							value = (dictionary[key] = new List<HookInfo>());
						}
						value.Add(current3);
					}
				}
				foreach (KeyValuePair<string, List<HookInfo>> item2 in dictionary)
				{
					HookInfo hookInfo = item2.Value[0];
					string text = CompanionEmitter.Emit(hookInfo.ContainingNamespace, hookInfo.ContainingTypeChain.AsImmutableArray(), item2.Value);
					string text2 = string.Join("+", hookInfo.ContainingTypeChain.AsImmutableArray()) + ".NativeDetour.g.cs";
					((SourceProductionContext)(ref ctx)).AddSource(text2, text);
				}
			});
		}

		private static List<DiagnosticInfo> DetectCrossHookConflicts(ImmutableArray<HookInfo> all)
		{
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			List<DiagnosticInfo> list = new List<DiagnosticInfo>();
			Dictionary<string, HookInfo> dictionary = new Dictionary<string, HookInfo>();
			ImmutableArray<HookInfo>.Enumerator enumerator = all.GetEnumerator();
			while (enumerator.MoveNext())
			{
				HookInfo current = enumerator.Current;
				if (!current.Diagnostics.AsImmutableArray().Any((DiagnosticInfo d) => d.Id == "EZD011"))
				{
					string key = string.Format("{0}.{1}<{2}>[{3}]", current.TargetDeclaringTypeSyntax, current.TargetMethodNameOrCtor, current.TargetMember, string.Join(",", current.TargetTypeArgumentSyntax.AsImmutableArray()));
					if (dictionary.TryGetValue(key, out var value))
					{
						list.Add(new DiagnosticInfo("EZD005", "目标方法 '" + current.TargetDeclaringTypeSyntax + "." + current.TargetMethodNameOrCtor + "' 已被 '" + value.HookMethodName + "' 注解,不能再由 '" + current.HookMethodName + "' 重复 detour", current.HookSpan));
					}
					else
					{
						dictionary[key] = current;
					}
				}
			}
			Dictionary<string, HookInfo> dictionary2 = new Dictionary<string, HookInfo>();
			enumerator = all.GetEnumerator();
			while (enumerator.MoveNext())
			{
				HookInfo current2 = enumerator.Current;
				string text = current2.ContainingNamespace + "." + string.Join("+", current2.ContainingTypeChain.AsImmutableArray());
				string key2 = text + "::" + current2.Stem;
				if (dictionary2.TryGetValue(key2, out var _))
				{
					list.Add(new DiagnosticInfo("EZD006", "类 '" + text + "' 中存在多个 hook 方法导致生成名称 '" + current2.Stem + "_Handle' 冲突", current2.HookSpan));
				}
				else
				{
					dictionary2[key2] = current2;
				}
			}
			return list;
		}

		private static Diagnostic MakeDiagnostic(DiagnosticInfo info)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			DiagnosticDescriptor val = ResolveDescriptor(info.Id);
			FileLinePositionSpan span = info.Span;
			string path = ((FileLinePositionSpan)(ref span)).Path;
			span = info.Span;
			Location val2 = Location.Create(path, default(TextSpan), ((FileLinePositionSpan)(ref span)).Span);
			return Diagnostic.Create(new DiagnosticDescriptor(val.Id, val.Title, LocalizableString.op_Implicit(info.Message), val.Category, val.DefaultSeverity, val.IsEnabledByDefault, (LocalizableString)null, (string)null, Array.Empty<string>()), val2, Array.Empty<object>());
		}

		private static DiagnosticDescriptor ResolveDescriptor(string id)
		{
			return (DiagnosticDescriptor)(id switch
			{
				"EZD001" => Diagnostics.EZD001_NotPartial, 
				"EZD002" => Diagnostics.EZD002_NotStatic, 
				"EZD003" => Diagnostics.EZD003_BadLastParam, 
				"EZD004" => Diagnostics.EZD004_BadFirstParam, 
				"EZD005" => Diagnostics.EZD005_DuplicateTarget, 
				"EZD006" => Diagnostics.EZD006_StemConflict, 
				"EZD007" => Diagnostics.EZD007_GenericContainer, 
				"EZD008" => Diagnostics.EZD008_BadModifier, 
				"EZD009" => Diagnostics.EZD009_CtorWithMethodName, 
				"EZD010" => Diagnostics.EZD010_PropMissingName, 
				"EZD011" => Diagnostics.EZD011_UnresolvedDeclaringType, 
				"EZD012" => Diagnostics.EZD012_TypeArgsIgnored, 
				"EZD014" => Diagnostics.EZD014_GenericMethodExperimental, 
				_ => throw new InvalidOperationException("未知 EZD: " + id), 
			});
		}
	}
}
namespace Hikaria.Core.SourceGenerators.Internal
{
	public readonly struct EquatableArray<T> : IEquatable<EquatableArray<T>>, IEnumerable<T>, IEnumerable where T : IEquatable<T>
	{
		public static readonly EquatableArray<T> Empty = new EquatableArray<T>(ImmutableArray<T>.Empty);

		private readonly ImmutableArray<T> _array;

		public int Length
		{
			get
			{
				if (!_array.IsDefault)
				{
					return _array.Length;
				}
				return 0;
			}
		}

		public bool IsEmpty => Length == 0;

		public T this[int index] => _array[index];

		public EquatableArray(ImmutableArray<T> array)
		{
			_array = array;
		}

		public EquatableArray(IEnumerable<T> source)
		{
			_array = source?.ToImmutableArray() ?? ImmutableArray<T>.Empty;
		}

		public ImmutableArray<T> AsImmutableArray()
		{
			if (!_array.IsDefault)
			{
				return _array;
			}
			return ImmutableArray<T>.Empty;
		}

		public bool Equals(EquatableArray<T> other)
		{
			if (Length != other.Length)
			{
				return false;
			}
			for (int i = 0; i < Length; i++)
			{
				if (!_array[i].Equals(other._array[i]))
				{
					return false;
				}
			}
			return true;
		}

		public override bool Equals(object obj)
		{
			if (obj is EquatableArray<T> other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			if (_array.IsDefault)
			{
				return 0;
			}
			int num = 17;
			ImmutableArray<T>.Enumerator enumerator = _array.GetEnumerator();
			while (enumerator.MoveNext())
			{
				num = num * 31 + (enumerator.Current?.GetHashCode() ?? 0);
			}
			return num;
		}

		public IEnumerator<T> GetEnumerator()
		{
			return AsImmutableArray().AsEnumerable().GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		public static bool operator ==(EquatableArray<T> a, EquatableArray<T> b)
		{
			return a.Equals(b);
		}

		public static bool operator !=(EquatableArray<T> a, EquatableArray<T> b)
		{
			return !a.Equals(b);
		}
	}
}
namespace Hikaria.Core.SourceGenerators.Emitters
{
	internal static class CompanionEmitter
	{
		private const string HandleType = "global::Hikaria.Core.Detour.NativeDetourHandle";

		private const string DescriptorType = "global::Hikaria.Core.Detour.DetourDescriptor";

		private const string NativeDetourType = "global::Hikaria.Core.Detour.NativeDetour";

		private const string TypeArrayType = "global::System.Type";

		private const string UnmanagedFunctionPointerAttr = "global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute";

		private const string CallingConvCdecl = "global::System.Runtime.InteropServices.CallingConvention.Cdecl";

		public static string Emit(string @namespace, IReadOnlyList<string> typeChain, IReadOnlyList<HookInfo> hooks)
		{
			StringBuilder stringBuilder = new StringBuilder(2048);
			EmitHeader(stringBuilder);
			EmitNamespaceOpen(stringBuilder, @namespace);
			EmitTypeChainOpen(stringBuilder, typeChain);
			foreach (HookInfo hook in hooks)
			{
				EmitHookMembers(stringBuilder, hook);
			}
			EmitContainerAggregators(stringBuilder, hooks);
			EmitTypeChainClose(stringBuilder, typeChain);
			EmitNamespaceClose(stringBuilder, @namespace);
			return stringBuilder.ToString();
		}

		private static void EmitHeader(StringBuilder sb)
		{
			sb.AppendLine("// <auto-generated/>");
			sb.AppendLine("// Generated by Hikaria.Core.SourceGenerators.NativeDetourGenerator");
			sb.AppendLine("#nullable disable");
			sb.AppendLine("#pragma warning disable CS8019  // unused usings");
			sb.AppendLine();
		}

		private static void EmitNamespaceOpen(StringBuilder sb, string ns)
		{
			if (!string.IsNullOrEmpty(ns))
			{
				sb.Append("namespace ").Append(ns).AppendLine()
					.AppendLine("{");
			}
		}

		private static void EmitNamespaceClose(StringBuilder sb, string ns)
		{
			if (!string.IsNullOrEmpty(ns))
			{
				sb.AppendLine("}");
			}
		}

		private static void EmitTypeChainOpen(StringBuilder sb, IReadOnlyList<string> chain)
		{
			for (int i = 0; i < chain.Count; i++)
			{
				sb.Append("    unsafe partial class ").Append(chain[i]).AppendLine()
					.AppendLine("    {");
			}
		}

		private static void EmitTypeChainClose(StringBuilder sb, IReadOnlyList<string> chain)
		{
			for (int num = chain.Count - 1; num >= 0; num--)
			{
				sb.AppendLine("    }");
			}
		}

		private static void EmitHookMembers(StringBuilder sb, HookInfo h)
		{
			string stem = h.Stem;
			sb.Append("        [").Append("global::System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute").Append('(')
				.Append("global::System.Runtime.InteropServices.CallingConvention.Cdecl")
				.AppendLine(")]");
			sb.Append("        private delegate ").Append(h.ReturnTypeSyntax).Append(' ')
				.Append(stem)
				.Append("_HookDelegate(");
			EmitParamList(sb, h.Parameters);
			sb.AppendLine(");");
			sb.AppendLine();
			sb.Append("        private static readonly ").Append("global::Hikaria.Core.Detour.NativeDetourHandle").Append('<')
				.Append(stem)
				.Append("_HookDelegate> ");
			sb.Append(stem).Append("_Handle = ").Append("global::Hikaria.Core.Detour.NativeDetour")
				.Append(".Create<")
				.Append(stem)
				.Append("_HookDelegate>(")
				.AppendLine();
			sb.Append("            new ").Append("global::Hikaria.Core.Detour.DetourDescriptor").AppendLine();
			sb.AppendLine("            {");
			sb.Append("                Type        = typeof(").Append(h.TargetDeclaringTypeSyntax).AppendLine("),");
			sb.Append("                MethodName  = \"").Append(h.TargetMethodNameOrCtor).AppendLine("\",");
			sb.Append("                ReturnType  = typeof(").Append(EmitDescriptorReturnType(h)).AppendLine("),");
			sb.Append("                ArgTypes    = new ").Append("global::System.Type").Append("[] { ");
			EmitDescriptorArgTypes(sb, h);
			sb.AppendLine(" },");
			sb.Append("                IsGeneric   = ").Append(h.TargetTypeArgumentSyntax.IsEmpty ? "false" : "true").AppendLine(",");
			if (!h.TargetTypeArgumentSyntax.IsEmpty)
			{
				sb.Append("                GenericTypeArguments = new ").Append("global::System.Type").Append("[] { ");
				bool flag = true;
				foreach (string item in h.TargetTypeArgumentSyntax)
				{
					if (!flag)
					{
						sb.Append(", ");
					}
					sb.Append("typeof(").Append(item).Append(')');
					flag = false;
				}
				sb.AppendLine(" },");
			}
			sb.AppendLine("            },");
			sb.Append("            ").Append(h.HookMethodName).AppendLine(");");
			sb.AppendLine();
			sb.Append("        private static ").Append(stem).Append("_HookDelegate ")
				.Append(stem)
				.Append("_Original => ")
				.Append(stem)
				.AppendLine("_Handle.Original;");
			sb.AppendLine();
			sb.Append("        public static bool ").Append(stem).Append("_Apply() => ")
				.Append(stem)
				.AppendLine("_Handle.Apply();");
			sb.Append("        public static void ").Append(stem).Append("_Dispose() => ")
				.Append(stem)
				.AppendLine("_Handle.Dispose();");
			sb.AppendLine();
		}

		private static void EmitContainerAggregators(StringBuilder sb, IReadOnlyList<HookInfo> hooks)
		{
			sb.AppendLine("        public static void ApplyAll()");
			sb.AppendLine("        {");
			foreach (HookInfo hook in hooks)
			{
				sb.Append("            ").Append(hook.Stem).AppendLine("_Apply();");
			}
			sb.AppendLine("        }");
			sb.AppendLine();
			sb.AppendLine("        public static void DisposeAll()");
			sb.AppendLine("        {");
			foreach (HookInfo hook2 in hooks)
			{
				sb.Append("            ").Append(hook2.Stem).AppendLine("_Dispose();");
			}
			sb.AppendLine("        }");
			sb.AppendLine();
		}

		private static void EmitParamList(StringBuilder sb, EquatableArray<ParamInfo> ps)
		{
			bool flag = true;
			foreach (ParamInfo item in ps)
			{
				if (!flag)
				{
					sb.Append(", ");
				}
				sb.Append(item.TypeSyntax).Append(' ').Append(item.Name);
				flag = false;
			}
		}

		private static string EmitDescriptorReturnType(HookInfo h)
		{
			if (h.TargetMember != NativeDetourMember.Constructor)
			{
				return h.ReturnTypeSyntax;
			}
			return "void";
		}

		private static void EmitDescriptorArgTypes(StringBuilder sb, HookInfo h)
		{
			bool num = !h.TargetIsStatic;
			int num2 = h.Parameters.Length - 1;
			bool flag = true;
			for (int i = (num ? 1 : 0); i < num2; i++)
			{
				if (!flag)
				{
					sb.Append(", ");
				}
				sb.Append("typeof(").Append(h.Parameters[i].TypeSyntax).Append(')');
				flag = false;
			}
		}
	}
}