Decompiled source of ShopKeeper Controller v1.0.0

EmpressShopkeeperClientLock.dll

Decompiled 5 hours ago
using 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);
		}
	}
}