Decompiled source of Hikaria Core v1.0.1
BepInEx/plugins/Hikaria.Core/Hikaria.Core.dll
Decompiled 6 days ago
The result has been truncated due to the large size, download it to view full contents!
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 agousing 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; } } } }