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 ShopKeeper Controller v1.0.0
EmpressShopkeeperClientLock.dll
Decompiled 5 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; 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: AssemblyCompany("Empress")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("EmpressShopkeeperClientLock")] [assembly: AssemblyTitle("EmpressShopkeeperClientLock")] [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] [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; } } } namespace EmpressShopkeeperClientLock { [BepInPlugin("empress.repo.shopkeeperclientlock", "Empress Shopkeeper Client Lock", "1.0.0")] public sealed class EmpressShopkeeperClientLockPlugin : BaseUnityPlugin { internal const string PluginGuid = "empress.repo.shopkeeperclientlock"; internal const string PluginName = "Empress Shopkeeper Client Lock"; internal const string PluginVersion = "1.0.0"; private static ConfigEntry<bool>? _clientsCanPressShopkeeperButton; private static readonly Dictionary<int, float> ReleaseCooldowns = new Dictionary<int, float>(); private readonly Harmony _harmony = new Harmony("empress.repo.shopkeeperclientlock"); private void Awake() { _clientsCanPressShopkeeperButton = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ClientsCanPressShopkeeperButton", false, "Controls whether non-host clients can use the shopkeeper on/off switch in multiplayer."); _harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Empress Shopkeeper Client Lock 1.0.0 loaded."); } internal static bool ShouldBlockSwitchActivation(ShopKeeper shopKeeper) { if (!ShouldEnforceOnHost() || (Object)(object)shopKeeper == (Object)null) { return false; } GameObject onOffSwitch = shopKeeper.OnOffSwitch; if ((Object)(object)onOffSwitch == (Object)null) { return false; } if (!HasClientGrabber(FindSwitchPhysGrabObject(onOffSwitch))) { return HasClientGrabber(FindSwitchStaticGrabObject(onOffSwitch)); } return true; } internal static bool ShouldBlockPhysGrabStarted(PhysGrabObject physGrabObject, int playerPhotonID) { if (!ShouldBlockGrabStarted((Component)(object)physGrabObject, playerPhotonID, out PhysGrabber grabber)) { return false; } ReleaseClientGrabber(grabber, physGrabObject); return true; } internal static bool ShouldBlockStaticGrabStarted(StaticGrabObject staticGrabObject, int playerPhotonID) { if (!ShouldBlockGrabStarted((Component)(object)staticGrabObject, playerPhotonID, out PhysGrabber grabber)) { return false; } ReleaseClientGrabber(grabber, staticGrabObject); return true; } internal static void ReleaseClientSwitchGrabbers(ShopKeeper shopKeeper) { if (!ShouldEnforceOnHost() || (Object)(object)shopKeeper == (Object)null) { return; } GameObject onOffSwitch = shopKeeper.OnOffSwitch; if ((Object)(object)onOffSwitch == (Object)null) { return; } PhysGrabObject val = FindSwitchPhysGrabObject(onOffSwitch); if ((Object)(object)val != (Object)null) { foreach (PhysGrabber item in new List<PhysGrabber>(val.playerGrabbing)) { if (IsNonHostGrabber(item)) { ReleaseClientGrabber(item, val); } } } StaticGrabObject val2 = FindSwitchStaticGrabObject(onOffSwitch); if (!((Object)(object)val2 != (Object)null)) { return; } foreach (PhysGrabber item2 in new List<PhysGrabber>(val2.playerGrabbing)) { if (IsNonHostGrabber(item2)) { ReleaseClientGrabber(item2, val2); } } } private static bool ShouldBlockGrabStarted(Component grabObject, int playerPhotonID, out PhysGrabber? grabber) { grabber = null; if (!ShouldEnforceOnHost() || !IsShopkeeperSwitchGrabObject(grabObject)) { return false; } PhotonView val = PhotonView.Find(playerPhotonID); if (!Object.op_Implicit((Object)(object)val)) { return false; } grabber = ((Component)val).GetComponent<PhysGrabber>(); return IsNonHostGrabber(grabber); } private static bool ShouldEnforceOnHost() { ConfigEntry<bool>? clientsCanPressShopkeeperButton = _clientsCanPressShopkeeperButton; if ((clientsCanPressShopkeeperButton == null || !clientsCanPressShopkeeperButton.Value) && SemiFunc.IsMultiplayer()) { return SemiFunc.IsMasterClient(); } return false; } private static bool HasClientGrabber(PhysGrabObject? physGrabObject) { if ((Object)(object)physGrabObject == (Object)null) { return false; } foreach (PhysGrabber item in physGrabObject.playerGrabbing) { if (IsNonHostGrabber(item)) { return true; } } return false; } private static bool HasClientGrabber(StaticGrabObject? staticGrabObject) { if ((Object)(object)staticGrabObject == (Object)null) { return false; } foreach (PhysGrabber item in staticGrabObject.playerGrabbing) { if (IsNonHostGrabber(item)) { return true; } } return false; } private static bool IsNonHostGrabber(PhysGrabber? grabber) { if ((Object)(object)grabber == (Object)null) { return false; } PlayerAvatar playerAvatar = grabber.playerAvatar; if ((Object)(object)playerAvatar == (Object)null || (Object)(object)playerAvatar.photonView == (Object)null) { return false; } return playerAvatar.photonView.Owner != PhotonNetwork.MasterClient; } private static bool IsShopkeeperSwitchGrabObject(Component grabObject) { if ((Object)(object)grabObject == (Object)null || (Object)(object)ShopKeeper.instance == (Object)null) { return false; } GameObject onOffSwitch = ShopKeeper.instance.OnOffSwitch; if ((Object)(object)onOffSwitch == (Object)null) { return false; } Transform transform = onOffSwitch.transform; Transform transform2 = grabObject.transform; if (!((Object)(object)transform == (Object)(object)transform2) && !transform.IsChildOf(transform2)) { return transform2.IsChildOf(transform); } return true; } private static PhysGrabObject? FindSwitchPhysGrabObject(GameObject switchObject) { if ((Object)(object)switchObject == (Object)null) { return null; } return switchObject.GetComponent<PhysGrabObject>() ?? switchObject.GetComponentInParent<PhysGrabObject>() ?? switchObject.GetComponentInChildren<PhysGrabObject>(true); } private static StaticGrabObject? FindSwitchStaticGrabObject(GameObject switchObject) { if ((Object)(object)switchObject == (Object)null) { return null; } return switchObject.GetComponent<StaticGrabObject>() ?? switchObject.GetComponentInParent<StaticGrabObject>() ?? switchObject.GetComponentInChildren<StaticGrabObject>(true); } private static void ReleaseClientGrabber(PhysGrabber? grabber, PhysGrabObject physGrabObject) { if (!((Object)(object)grabber == (Object)null) && !((Object)(object)physGrabObject == (Object)null)) { PhotonView component = ((Component)physGrabObject).GetComponent<PhotonView>(); if (!((Object)(object)component == (Object)null) && TryBeginRelease(grabber)) { grabber.photonView.RPC("ReleaseObjectRPC", (RpcTarget)0, new object[3] { false, 0.5f, component.ViewID }); } } } private static void ReleaseClientGrabber(PhysGrabber? grabber, StaticGrabObject staticGrabObject) { if (!((Object)(object)grabber == (Object)null) && !((Object)(object)staticGrabObject == (Object)null)) { PhotonView component = ((Component)staticGrabObject).GetComponent<PhotonView>(); if (!((Object)(object)component == (Object)null) && TryBeginRelease(grabber)) { grabber.photonView.RPC("ReleaseObjectRPC", (RpcTarget)0, new object[3] { true, 0.5f, component.ViewID }); } } } private static bool TryBeginRelease(PhysGrabber grabber) { if ((Object)(object)grabber.photonView == (Object)null) { return false; } int viewID = grabber.photonView.ViewID; float time = Time.time; if (ReleaseCooldowns.TryGetValue(viewID, out var value) && value > time) { return false; } ReleaseCooldowns[viewID] = time + 0.25f; return true; } } [HarmonyPatch(typeof(ShopKeeper), "WakeUpOrSleepLogic")] internal static class EmpressShopkeeperClientLockWakeUpOrSleepPatch { [HarmonyPrefix] private static bool EmpressPrefix(ShopKeeper __instance) { return !EmpressShopkeeperClientLockPlugin.ShouldBlockSwitchActivation(__instance); } } [HarmonyPatch(typeof(ShopKeeper), "Update")] internal static class EmpressShopkeeperClientLockShopKeeperUpdatePatch { [HarmonyPostfix] private static void EmpressPostfix(ShopKeeper __instance) { EmpressShopkeeperClientLockPlugin.ReleaseClientSwitchGrabbers(__instance); } } [HarmonyPatch(typeof(PhysGrabObject), "GrabStartedRPC")] internal static class EmpressShopkeeperClientLockPhysGrabStartedPatch { [HarmonyPrefix] private static bool EmpressPrefix(PhysGrabObject __instance, int playerPhotonID) { return !EmpressShopkeeperClientLockPlugin.ShouldBlockPhysGrabStarted(__instance, playerPhotonID); } } [HarmonyPatch(typeof(StaticGrabObject), "GrabStartedRPC")] internal static class EmpressShopkeeperClientLockStaticGrabStartedPatch { [HarmonyPrefix] private static bool EmpressPrefix(StaticGrabObject __instance, int playerPhotonID) { return !EmpressShopkeeperClientLockPlugin.ShouldBlockStaticGrabStarted(__instance, playerPhotonID); } } }