Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of BSAntiGrief v0.0.1
AntiGrief.dll
Decompiled 13 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using AntiGrief.NetcodePatcher; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LobbyCompatibility.Enums; using LobbyCompatibility.Features; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: AssemblyCompany("AntiGrief")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Some anti-griefing features")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("AntiGrief")] [assembly: AssemblyTitle("AntiGrief")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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; } } } namespace AntiGrief { internal class AGNetworker : NetworkBehaviour { internal static GameObject prefab; internal static AGNetworker Instance { get; private set; } internal NetworkVariable<bool> DisableMasks { get; private set; } = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariable<bool> DisableEggs { get; private set; } = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariable<bool> DisableShovels { get; private set; } = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariable<bool> DisableFriendlyFire { get; private set; } = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariable<bool> DisableMisfire { get; private set; } = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariable<bool> PermanentLuck { get; private set; } = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariable<bool> DisableTriggerItems { get; private set; } = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal static void Init() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown if ((Object)(object)prefab != (Object)null) { Plugin.Logger.LogDebug((object)"Skipped network handler registration, because it has already been initialized"); return; } try { prefab = new GameObject("AGNetworker") { hideFlags = (HideFlags)61 }; NetworkObject val = prefab.AddComponent<NetworkObject>(); byte[] value = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(typeof(AGNetworker).Assembly.GetName().Name + ((Object)prefab).name)); val.GlobalObjectIdHash = BitConverter.ToUInt32(value, 0); prefab.AddComponent<AGNetworker>(); NetworkManager.Singleton.AddNetworkPrefab(prefab); Plugin.Logger.LogDebug((object)$"Successfully registered network handler (#{val.GlobalObjectIdHash})"); } catch (Exception arg) { Plugin.Logger.LogError((object)$"Encountered some fatal error while registering network handler. The mod will not function like this!\n{arg}"); } } internal static void Create() { try { if (NetworkManager.Singleton.IsServer && (Object)(object)prefab != (Object)null) { Object.Instantiate<GameObject>(prefab).GetComponent<NetworkObject>().Spawn(true); } } catch { Plugin.Logger.LogError((object)"Encountered some fatal error while spawning network handler. It is likely that registration failed earlier on start-up, please consult your logs."); } } private void Awake() { Instance = this; } public override void OnNetworkSpawn() { ((NetworkBehaviour)this).OnNetworkSpawn(); if ((Object)(object)Instance != (Object)(object)this) { NetworkObject val = default(NetworkObject); if (((Component)Instance).TryGetComponent<NetworkObject>(ref val) && !val.IsSpawned && (Object)(object)Instance != (Object)(object)prefab) { Object.Destroy((Object)(object)Instance); } Plugin.Logger.LogWarning((object)"There are 2 AGNetworkers instantiated, and the wrong one was assigned as Instance. This shouldn't happen, but is recoverable"); Instance = this; } Plugin.Logger.LogDebug((object)"Successfully spawned network handler."); } private void Start() { if (!((Object)(object)this != (Object)(object)Instance) && ((NetworkBehaviour)this).IsSpawned && ((NetworkBehaviour)this).IsServer) { DisableMasks.Value = Plugin.configDisableMasks.Value; DisableEggs.Value = Plugin.configDisableEggs.Value; DisableShovels.Value = Plugin.configDisableShovels.Value; DisableFriendlyFire.Value = Plugin.configDisableFriendlyFire.Value; DisableMisfire.Value = Plugin.configDisableMisfire.Value; PermanentLuck.Value = Plugin.configPermanentLuck.Value; DisableTriggerItems.Value = Plugin.configDisableTriggerItems.Value; } } protected override void __initializeVariables() { if (DisableMasks == null) { throw new Exception("AGNetworker.<DisableMasks>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)DisableMasks).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)DisableMasks, "DisableMasks"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)DisableMasks); if (DisableEggs == null) { throw new Exception("AGNetworker.<DisableEggs>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)DisableEggs).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)DisableEggs, "DisableEggs"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)DisableEggs); if (DisableShovels == null) { throw new Exception("AGNetworker.<DisableShovels>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)DisableShovels).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)DisableShovels, "DisableShovels"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)DisableShovels); if (DisableFriendlyFire == null) { throw new Exception("AGNetworker.<DisableFriendlyFire>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)DisableFriendlyFire).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)DisableFriendlyFire, "DisableFriendlyFire"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)DisableFriendlyFire); if (DisableMisfire == null) { throw new Exception("AGNetworker.<DisableMisfire>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)DisableMisfire).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)DisableMisfire, "DisableMisfire"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)DisableMisfire); if (PermanentLuck == null) { throw new Exception("AGNetworker.<PermanentLuck>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)PermanentLuck).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)PermanentLuck, "PermanentLuck"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)PermanentLuck); if (DisableTriggerItems == null) { throw new Exception("AGNetworker.<DisableTriggerItems>k__BackingField cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)DisableTriggerItems).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)DisableTriggerItems, "DisableTriggerItems"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)DisableTriggerItems); ((NetworkBehaviour)this).__initializeVariables(); } protected override void __initializeRpcs() { ((NetworkBehaviour)this).__initializeRpcs(); } protected internal override string __getTypeName() { return "AGNetworker"; } } internal static class LobbyCompatibility { internal static void Init() { PluginHelper.RegisterPlugin("butterystancakes.lethalcompany.antigrief", Version.Parse("0.0.1"), (CompatibilityLevel)2, (VersionStrictness)3); } } [HarmonyPatch] internal static class Patches { [HarmonyPatch(typeof(GameNetworkManager), "Start")] [HarmonyPostfix] private static void GameNetworkManager_Post_Start() { AGNetworker.Init(); } [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] private static void StartOfRound_Post_Awake() { AGNetworker.Create(); } [HarmonyPatch(typeof(HauntedMaskItem), "EquipItem")] [HarmonyPrefix] private static void HauntedMaskItem_Pre_EquipItem(HauntedMaskItem __instance) { if (__instance.maskIsHaunted && !StartOfRound.Instance.isChallengeFile && AGNetworker.Instance.DisableMasks.Value) { __instance.maskIsHaunted = false; Plugin.Logger.LogDebug((object)$"Mask \"{((Object)__instance).name}\" (#{((Object)__instance).GetInstanceID()}) is no longer haunted"); } } [HarmonyPatch(typeof(ShotgunItem), "Update")] [HarmonyPrefix] private static void ShotgunItem_Pre_Update(ShotgunItem __instance) { if (!StartOfRound.Instance.isChallengeFile && AGNetworker.Instance.DisableMisfire.Value) { if (!__instance.hasHitGroundWithSafetyOff) { Plugin.Logger.LogDebug((object)$"Shotgun \"{((Object)__instance).name}\" (#{((Object)__instance).GetInstanceID()}) will not fire when dropped"); __instance.hasHitGroundWithSafetyOff = true; } __instance.misfireTimer = 50f; } } [HarmonyPatch(typeof(GrabbableObjectPhysicsTrigger), "OnTriggerEnter")] [HarmonyPrefix] private static bool GrabbableObjectPhysicsTrigger_Pre_OnTriggerEnter(GrabbableObjectPhysicsTrigger __instance, Collider other) { if (StartOfRound.Instance.isChallengeFile || !AGNetworker.Instance.DisableTriggerItems.Value || (!__instance.itemScript.isInShipRoom && !StartOfRound.Instance.inShipPhase)) { return true; } if ((Object)(object)__instance.itemScript != (Object)null && !__instance.itemScript.isHeld && (((Component)other).gameObject.CompareTag("Player") || ((Component)other).gameObject.CompareTag("Enemy"))) { Plugin.Logger.LogDebug((object)$"Item \"{((Object)__instance.itemScript).name}\" (#{((Object)__instance.itemScript).GetInstanceID()}) can't be triggered while inside of ship"); } return false; } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayerFromOtherClientClientRpc")] [HarmonyPrefix] private static void PlayerControllerB_Pre_DamagePlayerFromOtherClientClientRpc(PlayerControllerB __instance, ref int damageAmount) { if (!StartOfRound.Instance.isChallengeFile && AGNetworker.Instance.DisableShovels.Value) { Plugin.Logger.LogDebug((object)$"Melee damage on player \"{__instance.playerUsername}\" nullified ({damageAmount} -> 0)"); damageAmount = 0; } } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPrefix] private static bool PlayerControllerB_Pre_DamagePlayer(int damageNumber, CauseOfDeath causeOfDeath) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 if (!StartOfRound.Instance.isChallengeFile && damageNumber <= 0) { if ((int)causeOfDeath != 1) { return (int)causeOfDeath != 7; } return false; } return true; } [HarmonyPatch(typeof(StunGrenadeItem), "SetExplodeOnThrowClientRpc")] [HarmonyPrefix] private static void StunGrenadeItem_Pre_SetExplodeOnThrowClientRpc(StunGrenadeItem __instance, ref bool explode) { if (explode && !StartOfRound.Instance.isChallengeFile && AGNetworker.Instance.DisableEggs.Value) { explode = false; Plugin.Logger.LogDebug((object)$"Easter egg \"{((Object)__instance).name}\" (#{((Object)__instance).GetInstanceID()}) had its explosion chance reset"); } } private static int ShotgunPlayerDamagePostProcess(ShotgunItem shotgunItem, int damage) { if (!((GrabbableObject)shotgunItem).isHeldByEnemy && !StartOfRound.Instance.isChallengeFile && AGNetworker.Instance.DisableFriendlyFire.Value) { if (damage > 0) { Plugin.Logger.LogDebug((object)$"Shotgun \"{((Object)shotgunItem).name}\" (#{((Object)shotgunItem).GetInstanceID()}) damage on player \"{GameNetworkManager.Instance.localPlayerController.playerUsername}\" nullified ({damage} -> 0)"); } return 0; } return damage; } [HarmonyPatch(typeof(ShotgunItem), "ShootGun")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ShotgunItem_Trans_ShootGun(IEnumerable<CodeInstruction> instructions) { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); MethodInfo methodInfo = AccessTools.Method(typeof(PlayerControllerB), "DamagePlayer", (Type[])null, (Type[])null); int num = -1; for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Brfalse) { num = i; } else if (num >= 0 && num + 3 < list.Count && list[i].opcode == OpCodes.Callvirt && list[i].operand as MethodInfo == methodInfo && list[num + 2].opcode == OpCodes.Ldloc_S) { list.Insert(num + 3, new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Patches), "ShotgunPlayerDamagePostProcess", (Type[])null, (Type[])null))); list.Insert(num + 2, new CodeInstruction(OpCodes.Ldarg_0, (object)null)); Plugin.Logger.LogDebug((object)"Transpiler (Shotgun): Alter damage call"); return list; } } Plugin.Logger.LogError((object)"Shotgun transpiler failed"); return list; } [HarmonyPatch(typeof(TimeOfDay), "CalculateLuckValue")] [HarmonyPostfix] private static void TimeOfDay_Post_CalculateLuckValue(TimeOfDay __instance) { if (StartOfRound.Instance.isChallengeFile || !AGNetworker.Instance.PermanentLuck.Value) { return; } for (int i = 0; i < StartOfRound.Instance.unlockablesList.unlockables.Count; i++) { if (StartOfRound.Instance.unlockablesList.unlockables[i].luckValue > 0f && StartOfRound.Instance.unlockablesList.unlockables[i].hasBeenUnlockedByPlayer && !__instance.furniturePlacedAtQuotaStart.Contains(i)) { __instance.furniturePlacedAtQuotaStart.Add(i); __instance.luckValue = Mathf.Clamp(__instance.luckValue + StartOfRound.Instance.unlockablesList.unlockables[i].luckValue, -0.5f, 1f); Plugin.Logger.LogDebug((object)$"Furniture luck forced to track unlockable #{i}: \"{StartOfRound.Instance.unlockablesList.unlockables[i].unlockableName}\""); } } } [HarmonyPatch(typeof(TimeOfDay), "SetNewProfitQuota")] [HarmonyPostfix] private static void TimeOfDay_Post_SetNewProfitQuota(TimeOfDay __instance) { if (!((NetworkBehaviour)__instance).IsServer || StartOfRound.Instance.isChallengeFile || !AGNetworker.Instance.PermanentLuck.Value) { return; } for (int i = 0; i < StartOfRound.Instance.unlockablesList.unlockables.Count; i++) { if (StartOfRound.Instance.unlockablesList.unlockables[i].luckValue > 0f && StartOfRound.Instance.unlockablesList.unlockables[i].hasBeenUnlockedByPlayer && !__instance.furniturePlacedAtQuotaStart.Contains(i)) { __instance.furniturePlacedAtQuotaStart.Add(i); Plugin.Logger.LogDebug((object)$"Furniture luck forced to track unlockable #{i}: \"{StartOfRound.Instance.unlockablesList.unlockables[i].unlockableName}\""); } } } [HarmonyPatch(typeof(ShipBuildModeManager), "StoreObjectServerRpc")] [HarmonyPrefix] private static void ShipBuildModeManager_Pre_StoreObjectServerRpc(ref List<int> __state) { __state = new List<int>(TimeOfDay.Instance.furniturePlacedAtQuotaStart); } [HarmonyPatch(typeof(ShipBuildModeManager), "StoreObjectServerRpc")] [HarmonyPostfix] private static void ShipBuildModeManager_Post_StoreObjectServerRpc(List<int> __state) { if (!StartOfRound.Instance.isChallengeFile && __state.Count > TimeOfDay.Instance.furniturePlacedAtQuotaStart.Count && AGNetworker.Instance.PermanentLuck.Value) { TimeOfDay.Instance.furniturePlacedAtQuotaStart = TimeOfDay.Instance.furniturePlacedAtQuotaStart.Union(__state).Distinct().ToList(); Plugin.Logger.LogDebug((object)"Furniture luck blocked from untracking unlockables"); } } [HarmonyPatch(typeof(RandomPeriodicAudioPlayer), "Update")] [HarmonyPrefix] private static void RandomPeriodicAudioPlayer_Pre_Update(RandomPeriodicAudioPlayer __instance) { if (((NetworkBehaviour)__instance).IsServer && !StartOfRound.Instance.isChallengeFile && (Object)(object)__instance.attachedGrabbableObject != (Object)null && __instance.attachedGrabbableObject.isInShipRoom && AGNetworker.Instance.DisableMasks.Value && AGNetworker.Instance.DisableTriggerItems.Value) { __instance.lastIntervalTime = Time.realtimeSinceStartup; } } } [BepInPlugin("butterystancakes.lethalcompany.antigrief", "Anti-Grief", "0.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal const string PLUGIN_GUID = "butterystancakes.lethalcompany.antigrief"; internal const string PLUGIN_NAME = "Anti-Grief"; internal const string PLUGIN_VERSION = "0.0.1"; internal static ManualLogSource Logger; private const string GUID_LOBBY_COMPATIBILITY = "BMX.LobbyCompatibility"; internal static ConfigEntry<bool> configDisableMasks; internal static ConfigEntry<bool> configDisableEggs; internal static ConfigEntry<bool> configDisableShovels; internal static ConfigEntry<bool> configDisableFriendlyFire; internal static ConfigEntry<bool> configDisableMisfire; internal static ConfigEntry<bool> configPermanentLuck; internal static ConfigEntry<bool> configDisableTriggerItems; private void Awake() { //IL_011b: Unknown result type (might be due to invalid IL or missing references) NetcodePatch(); Logger = ((BaseUnityPlugin)this).Logger; if (Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility")) { Logger.LogInfo((object)"CROSS-COMPATIBILITY - Lobby Compatibility detected"); LobbyCompatibility.Init(); } configDisableMasks = ((BaseUnityPlugin)this).Config.Bind<bool>("Items", "Block Mask Possession", true, "Comedy/Tragedy will no longer kill players and spawn \"masked\" enemies when they are worn."); configDisableEggs = ((BaseUnityPlugin)this).Config.Bind<bool>("Items", "Block Egg Explosions", true, "Easter eggs can never explode when hitting the ground."); configDisableShovels = ((BaseUnityPlugin)this).Config.Bind<bool>("Items", "Block Shovel Damage", true, "Shovels no longer deal damage when hitting players."); configDisableFriendlyFire = ((BaseUnityPlugin)this).Config.Bind<bool>("Items", "Block Friendly Fire", true, "Double barrels no longer damage players when fired by another player. Nutcrackers are unaffected."); configDisableMisfire = ((BaseUnityPlugin)this).Config.Bind<bool>("Items", "Block Misfires", true, "Double barrels no longer fire randomly upon hitting the ground or when being held by a player, even if the safety is off."); configDisableTriggerItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Items", "Block Triggering Items in Ship", true, "\"Trigger items\" (whoopie cushions and soccer balls) no longer activate when touched by players or enemies while they are inside the ship."); configPermanentLuck = ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "Permanent Luck", false, "Furniture will always be factored into luck calculations as long as it has been purchased.\nThis prevents players from irreversibly nullifying luck by storing furniture mid-quota, but *also allows you to benefit from furniture luck while keeping it in storage.*"); new Harmony("butterystancakes.lethalcompany.antigrief").PatchAll(); Logger.LogInfo((object)"Anti-Grief v0.0.1 loaded"); } private void NetcodePatch() { Type[] types = Assembly.GetExecutingAssembly().GetTypes(); for (int i = 0; i < types.Length; i++) { MethodInfo[] methods = types[i].GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false).Length != 0) { methodInfo.Invoke(null, null); } } } } } public static class PluginInfo { public const string PLUGIN_GUID = "AntiGrief"; public const string PLUGIN_NAME = "AntiGrief"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } namespace __GEN { internal class NetworkVariableSerializationHelper { [RuntimeInitializeOnLoadMethod] internal static void InitializeSerialization() { NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<bool>(); NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<bool>(); } } } namespace AntiGrief.NetcodePatcher { [AttributeUsage(AttributeTargets.Module)] internal class NetcodePatchedAssemblyAttribute : Attribute { } }