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 SimpleAccessControl v1.0.9
BepInEx/plugins/SimpleAccessControl/SimpleAccessControl.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("SimpleAccessControl")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SimpleAccessControl")] [assembly: AssemblyTitle("SimpleAccessControl")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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 SimpleAccessControl { [BepInPlugin("zephyrfit.simpleaccesscontrol", "Simple Access Control", "1.0.9")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "zephyrfit.simpleaccesscontrol"; public const string PluginName = "Simple Access Control"; public const string PluginVersion = "1.0.9"; internal static ManualLogSource Log; internal static ConfigEntry<KeyCode> ManageModifier; internal static ConfigEntry<KeyCode> PanelKey; internal static ConfigEntry<bool> ProtectConfiguredPieces; internal static ConfigEntry<bool> AdminOverride; internal static ConfigEntry<bool> ShowHoverStatus; internal static ConfigEntry<bool> ShowDestructionOnlyWithBuildTool; internal static ConfigEntry<bool> DebugLogging; internal static ConfigEntry<bool> AssignedBedsForcePrivate; internal static ConfigEntry<bool> ManageContainers; internal static ConfigEntry<bool> ManageDoorsAndGates; internal static ConfigEntry<bool> ManageBeds; internal static ConfigEntry<bool> ManageCraftingStations; internal static ConfigEntry<bool> ManageCookingStations; internal static ConfigEntry<bool> ManageCartographyTables; internal static ConfigEntry<bool> ManageCarts; internal static ConfigEntry<bool> ManageShips; private Harmony _harmony; private void Awake() { //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ManageModifier = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ManageModifier", (KeyCode)304, "Modifier shared by the quick access cycle and the detailed panel. It combines with Valheim's current Use binding for the quick cycle. Restart after changing it."); PanelKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "PanelKey", (KeyCode)0, "Key used with ManageModifier to open the detailed ACL panel. None selects A when Valheim is in French and Q for every other game language. Restart after changing it."); ProtectConfiguredPieces = ((BaseUnityPlugin)this).Config.Bind<bool>("Security", "ProtectConfiguredPieces", true, "When an access restriction is effective, only the piece owner (or an admin override) may dismantle or damage the piece. Fully public pieces keep vanilla destruction rules."); AdminOverride = ((BaseUnityPlugin)this).Config.Bind<bool>("Security", "AdminOverride", true, "Server admins/host may manage and dismantle any supported piece."); AssignedBedsForcePrivate = ((BaseUnityPlugin)this).Config.Bind<bool>("Security", "AssignedBedsForcePrivate", true, "A claimed bed is always private to its assigned sleeper, who becomes its access/destruction owner. Admin override still applies."); ShowHoverStatus = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowHoverStatus", true, "Show Public/Private/Whitelist state and both access shortcuts in hover text."); ShowDestructionOnlyWithBuildTool = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowDestructionOnlyWithBuildTool", true, "Hide destruction status during normal interaction and show it only while a hammer/build tool is equipped."); DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DetailedLogging", false, "Write verbose access decisions to BepInEx/LogOutput.log."); ManageContainers = ((BaseUnityPlugin)this).Config.Bind<bool>("Object categories", "Containers", true, "Enable ACLs for player-built containers and chests."); ManageDoorsAndGates = ((BaseUnityPlugin)this).Config.Bind<bool>("Object categories", "DoorsAndGates", true, "Enable ACLs for normal doors and physical gates (wood, iron, etc.). This does not include teleport portals."); ManageBeds = ((BaseUnityPlugin)this).Config.Bind<bool>("Object categories", "Beds", true, "Enable ACLs for player-built beds."); ManageCraftingStations = ((BaseUnityPlugin)this).Config.Bind<bool>("Object categories", "CraftingStations", true, "Enable ACLs for workbenches, forges, cauldrons and other CraftingStation pieces."); ManageCookingStations = ((BaseUnityPlugin)this).Config.Bind<bool>("Object categories", "CookingStations", true, "Enable ACLs for cooking stations, including adding and collecting food."); ManageCartographyTables = ((BaseUnityPlugin)this).Config.Bind<bool>("Object categories", "CartographyTables", true, "Enable ACLs for both reading and depositing map data at cartography tables."); ManageCarts = ((BaseUnityPlugin)this).Config.Bind<bool>("Object categories", "Carts", true, "Enable ACLs for carts and their storage."); ManageShips = ((BaseUnityPlugin)this).Config.Bind<bool>("Object categories", "Ships", true, "Enable ACLs for ship controls and onboard storage."); _harmony = new Harmony("zephyrfit.simpleaccesscontrol"); if (!Application.isBatchMode && (Object)(object)((Component)this).GetComponent<AccessUiHost>() == (Object)null) { ((Component)this).gameObject.AddComponent<AccessUiHost>(); } PatchIndependently(); Log.LogInfo((object)"Simple Access Control v1.0.9 loaded. Supported player-built objects and vehicles are PUBLIC by default."); } private void OnDestroy() { if (_harmony != null) { _harmony.UnpatchSelf(); } } private void PatchIndependently() { int num = 0; int num2 = 0; Type[] source; try { source = Assembly.GetExecutingAssembly().GetTypes(); } catch (ReflectionTypeLoadException ex) { source = ex.Types.Where((Type x) => x != null).ToArray(); } foreach (Type item in source.Where((Type t) => t.GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Length != 0)) { try { _harmony.CreateClassProcessor(item).Patch(); num++; } catch (Exception ex2) { num2++; Log.LogError((object)("Harmony patch group skipped (" + item.Name + "): " + ex2)); } } Log.LogInfo((object)("Harmony patch groups: " + num + " applied, " + num2 + " skipped.")); } internal static bool ModifierHeld() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Invalid comparison between Unknown and I4 KeyCode val = (KeyCode)((ManageModifier == null) ? 304 : ((int)ManageModifier.Value)); if (Input.GetKey(val)) { return true; } if ((int)val == 304 && Input.GetKey((KeyCode)303)) { return true; } if ((int)val == 306 && Input.GetKey((KeyCode)305)) { return true; } if ((int)val == 308 && Input.GetKey((KeyCode)307)) { return true; } return false; } internal static void Debug(string message) { if (DebugLogging != null && DebugLogging.Value && Log != null) { Log.LogInfo((object)("[Debug] " + message)); } } internal static bool Enabled(ConfigEntry<bool> setting) { return setting?.Value ?? true; } } internal sealed class AccessUiHost : MonoBehaviour { private void Update() { AccessHotkeys.Tick(); AccessPanel.Tick(); } private void OnGUI() { AccessPanel.Draw(); } } internal enum AccessMode { Public = 0, Private = 2, Whitelist = 3 } internal enum PlayerRule { Default, Allow, Deny } internal sealed class RuleEntry { internal long PlayerId; internal string Name; internal PlayerRule Rule; } internal sealed class PlayerRecord { internal long PlayerId; internal string Name; } internal static class AccessPolicy { private const string KeyOwner = "sac_owner"; private const string KeyOwnerName = "sac_owner_name"; private const string KeyMode = "sac_mode"; private const string KeyAcl = "sac_acl_v1"; internal static bool TryContext(Component component, ZNetView preferredView, out Piece piece, out ZNetView view, out ZDO zdo) { piece = null; view = null; zdo = null; if ((Object)(object)component == (Object)null) { return false; } view = preferredView; if ((Object)(object)view == (Object)null) { view = component.GetComponent<ZNetView>(); } if ((Object)(object)view == (Object)null) { view = component.GetComponentInParent<ZNetView>(); } piece = component.GetComponentInParent<Piece>(); if ((Object)(object)piece == (Object)null) { piece = component.GetComponent<Piece>(); } if ((Object)(object)piece == (Object)null && (Object)(object)view != (Object)null) { piece = ((Component)view).GetComponent<Piece>(); } if ((Object)(object)piece == (Object)null && (Object)(object)view != (Object)null) { piece = ((Component)view).GetComponentInChildren<Piece>(true); } if ((Object)(object)piece == (Object)null && (Object)(object)view != (Object)null) { piece = ((Component)view).GetComponentInParent<Piece>(); } Transform val = (((Object)(object)component.transform != (Object)null) ? component.transform.root : null); if ((Object)(object)piece == (Object)null && (Object)(object)val != (Object)null) { piece = ((Component)val).GetComponentInChildren<Piece>(true); } if ((Object)(object)view == (Object)null && (Object)(object)piece != (Object)null) { view = ((Component)piece).GetComponent<ZNetView>(); } if ((Object)(object)view == (Object)null && (Object)(object)piece != (Object)null) { view = ((Component)piece).GetComponentInParent<ZNetView>(); } if ((Object)(object)view == (Object)null && (Object)(object)val != (Object)null) { view = ((Component)val).GetComponentInChildren<ZNetView>(true); } if ((Object)(object)piece == (Object)null || piece.GetCreator() == 0L) { return false; } if ((Object)(object)view == (Object)null || !view.IsValid()) { return false; } zdo = view.GetZDO(); return zdo != null; } internal static bool TryContext(Piece piece, out ZNetView view, out ZDO zdo) { Piece piece2; return TryContext((Component)(object)piece, null, out piece2, out view, out zdo); } private static T FindRelated<T>(Piece piece) where T : Component { if ((Object)(object)piece == (Object)null) { return default(T); } T val = ((Component)piece).GetComponent<T>(); if ((Object)(object)val == (Object)null) { val = ((Component)piece).GetComponentInChildren<T>(true); } if ((Object)(object)val == (Object)null) { val = ((Component)piece).GetComponentInParent<T>(); } if ((Object)(object)val != (Object)null) { return val; } ZNetView val2 = ((Component)piece).GetComponent<ZNetView>() ?? ((Component)piece).GetComponentInParent<ZNetView>(); if ((Object)(object)val2 != (Object)null) { val = ((Component)val2).GetComponent<T>(); if ((Object)(object)val == (Object)null) { val = ((Component)val2).GetComponentInChildren<T>(true); } if ((Object)(object)val == (Object)null) { val = ((Component)val2).GetComponentInParent<T>(); } } if ((Object)(object)val != (Object)null) { return val; } Transform val3 = (((Object)(object)((Component)piece).transform != (Object)null) ? ((Component)piece).transform.root : null); if (!((Object)(object)val3 != (Object)null)) { return default(T); } return ((Component)val3).GetComponentInChildren<T>(true); } internal static bool IsSupportedPiece(Piece piece) { if ((Object)(object)piece == (Object)null || piece.GetCreator() == 0L) { return false; } if ((Object)(object)FindRelated<Vagon>(piece) != (Object)null) { return Plugin.Enabled(Plugin.ManageCarts); } if ((Object)(object)FindRelated<Ship>(piece) != (Object)null || (Object)(object)FindRelated<ShipControlls>(piece) != (Object)null) { return Plugin.Enabled(Plugin.ManageShips); } if ((Object)(object)FindRelated<MapTable>(piece) != (Object)null) { return Plugin.Enabled(Plugin.ManageCartographyTables); } if ((Object)(object)FindRelated<CookingStation>(piece) != (Object)null) { return Plugin.Enabled(Plugin.ManageCookingStations); } if ((!Plugin.Enabled(Plugin.ManageContainers) || !((Object)(object)FindRelated<Container>(piece) != (Object)null)) && (!Plugin.Enabled(Plugin.ManageDoorsAndGates) || !((Object)(object)FindRelated<Door>(piece) != (Object)null)) && (!Plugin.Enabled(Plugin.ManageBeds) || !((Object)(object)FindRelated<Bed>(piece) != (Object)null))) { if (Plugin.Enabled(Plugin.ManageCraftingStations)) { return (Object)(object)FindRelated<CraftingStation>(piece) != (Object)null; } return false; } return true; } internal static bool IsContainerEnabled(Container container) { if ((Object)(object)container == (Object)null) { return false; } if (TryContext((Component)(object)container, null, out var piece, out var _, out var _)) { if ((Object)(object)FindRelated<Vagon>(piece) != (Object)null) { return Plugin.Enabled(Plugin.ManageCarts); } if ((Object)(object)FindRelated<Ship>(piece) != (Object)null || (Object)(object)FindRelated<ShipControlls>(piece) != (Object)null) { return Plugin.Enabled(Plugin.ManageShips); } } return Plugin.Enabled(Plugin.ManageContainers); } internal static long GetOwner(Piece piece, ZDO zdo) { if (TryGetAssignedBedOwner(piece, zdo, out var owner, out var _)) { return owner; } long result = (((Object)(object)piece != (Object)null) ? piece.GetCreator() : 0); if (zdo == null) { return result; } long num = zdo.GetLong("sac_owner", 0L); if (num == 0L) { return result; } return num; } internal static string GetOwnerName(Piece piece, ZDO zdo) { if (TryGetAssignedBedOwner(piece, zdo, out var owner, out var ownerName)) { if (!string.IsNullOrEmpty(ownerName)) { return ownerName; } return PlayerDirectory.ResolveName(owner); } string text = ((zdo != null) ? zdo.GetString("sac_owner_name", string.Empty) : string.Empty); if (!string.IsNullOrEmpty(text)) { return text; } long owner2 = GetOwner(piece, zdo); string text2 = PlayerDirectory.ResolveName(owner2); if (!string.IsNullOrEmpty(text2)) { return text2; } return owner2.ToString(); } internal static AccessMode GetMode(ZDO zdo) { if (zdo == null) { return AccessMode.Public; } switch (zdo.GetInt("sac_mode", 0)) { case 2: return AccessMode.Private; case 3: return AccessMode.Whitelist; case 1: if (!ReadRules(zdo).Any((RuleEntry x) => x.Rule == PlayerRule.Allow)) { return AccessMode.Private; } return AccessMode.Whitelist; default: return AccessMode.Public; } } internal static AccessMode GetEffectiveMode(Piece piece, ZDO zdo) { if (!TryGetAssignedBedOwner(piece, zdo, out var _, out var _)) { return GetMode(zdo); } return AccessMode.Private; } internal static bool TryGetAssignedBedOwner(Piece piece, ZDO zdo, out long owner, out string ownerName) { owner = 0L; ownerName = string.Empty; if (Plugin.AssignedBedsForcePrivate != null && !Plugin.AssignedBedsForcePrivate.Value) { return false; } if ((Object)(object)piece == (Object)null || zdo == null || (Object)(object)FindRelated<Bed>(piece) == (Object)null) { return false; } try { owner = zdo.GetLong("owner", 0L); if (owner == 0L) { return false; } ownerName = zdo.GetString("ownerName", string.Empty); return true; } catch { owner = 0L; ownerName = string.Empty; return false; } } internal static bool Evaluate(Piece piece, ZDO zdo, long playerId, out string reason) { reason = "public default"; if ((Object)(object)piece == (Object)null || zdo == null || playerId == 0L) { return true; } if (TryGetAssignedBedOwner(piece, zdo, out var owner, out var _)) { bool flag = playerId == owner; reason = (flag ? "assigned bed owner" : "bed assigned to another player"); return flag; } long owner2 = GetOwner(piece, zdo); if (owner2 != 0L && playerId == owner2) { reason = "owner"; return true; } AccessMode effectiveMode = GetEffectiveMode(piece, zdo); PlayerRule rule = GetRule(zdo, playerId); if (rule == PlayerRule.Deny) { reason = "explicit deny"; return false; } if (effectiveMode == AccessMode.Whitelist && rule == PlayerRule.Allow) { reason = "explicit allow"; return true; } bool flag2 = effectiveMode == AccessMode.Public; reason = (flag2 ? "public default" : ((effectiveMode == AccessMode.Whitelist) ? "not on whitelist" : "private owner-only")); return flag2; } internal static bool CanManageLocal(Piece piece, ZDO zdo) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } long playerID = localPlayer.GetPlayerID(); if (playerID != 0L && playerID == GetOwner(piece, zdo)) { return true; } if (Plugin.AdminOverride != null && Plugin.AdminOverride.Value) { return IsLocalAdmin(); } return false; } internal static bool HasEffectiveRestriction(Piece piece, ZDO zdo) { if (zdo == null) { return false; } if (TryGetAssignedBedOwner(piece, zdo, out var _, out var _)) { return true; } if (GetEffectiveMode(piece, zdo) != AccessMode.Public) { return true; } return ReadRules(zdo).Any((RuleEntry x) => x.Rule == PlayerRule.Deny); } internal static bool CanRemoveOrDamage(Piece piece, ZDO zdo, long playerId, bool admin) { if ((Object)(object)piece == (Object)null || zdo == null) { return true; } if (!HasEffectiveRestriction(piece, zdo)) { return true; } if (playerId != 0L && playerId == GetOwner(piece, zdo)) { return true; } if (admin && Plugin.AdminOverride != null) { return Plugin.AdminOverride.Value; } return false; } internal static bool IsLocalAdmin() { try { return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.LocalPlayerIsAdminOrHost(); } catch { return false; } } internal static void SetMode(Piece piece, ZNetView view, ZDO zdo, AccessMode mode) { if (CanManageLocal(piece, zdo) && !TryGetAssignedBedOwner(piece, zdo, out var _, out var _)) { EnsureOwnerMetadata(piece, view, zdo); Claim(view); zdo.Set("sac_mode", (int)mode); Plugin.Debug("Mode changed on " + SafePieceName(piece) + " to " + mode); } } internal static bool CycleMode(Piece piece, ZNetView view, ZDO zdo) { if (!CanManageLocal(piece, zdo)) { return false; } if (TryGetAssignedBedOwner(piece, zdo, out var _, out var _)) { Messages.Center(UiText.L("Ce lit attribué reste privé.", "This assigned bed remains private.")); return false; } AccessMode mode = GetMode(zdo) switch { AccessMode.Private => AccessMode.Whitelist, AccessMode.Public => AccessMode.Private, _ => AccessMode.Public, }; SetMode(piece, view, zdo, mode); Messages.Center(UiText.L("Accès : ", "Access: ") + UiText.ModeName(mode)); return true; } internal static void SetRule(Piece piece, ZNetView view, ZDO zdo, long playerId, string name, PlayerRule rule) { if (playerId != 0L && CanManageLocal(piece, zdo) && !TryGetAssignedBedOwner(piece, zdo, out var _, out var _) && playerId != GetOwner(piece, zdo)) { EnsureOwnerMetadata(piece, view, zdo); List<RuleEntry> list = ReadRules(zdo); list.RemoveAll((RuleEntry x) => x.PlayerId == playerId); if (rule != PlayerRule.Default) { list.Add(new RuleEntry { PlayerId = playerId, Name = (name ?? string.Empty), Rule = rule }); } Claim(view); zdo.Set("sac_acl_v1", Serialize(list)); Plugin.Debug("Rule changed on " + SafePieceName(piece) + ": " + playerId + " -> " + rule); } } internal static void ClearRules(Piece piece, ZNetView view, ZDO zdo) { if (CanManageLocal(piece, zdo)) { EnsureOwnerMetadata(piece, view, zdo); Claim(view); zdo.Set("sac_acl_v1", string.Empty); } } internal static PlayerRule GetRule(ZDO zdo, long playerId) { return ReadRules(zdo).FirstOrDefault((RuleEntry x) => x.PlayerId == playerId)?.Rule ?? PlayerRule.Default; } internal static List<RuleEntry> ReadRules(ZDO zdo) { List<RuleEntry> list = new List<RuleEntry>(); if (zdo == null) { return list; } string text = zdo.GetString("sac_acl_v1", string.Empty); if (string.IsNullOrEmpty(text)) { return list; } string[] array = text.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { ':' }, 3); if (array2.Length < 2 || !long.TryParse(array2[0], out var result) || !int.TryParse(array2[1], out var result2)) { continue; } string name = string.Empty; if (array2.Length == 3) { try { name = Encoding.UTF8.GetString(Convert.FromBase64String(array2[2])); } catch { name = string.Empty; } } PlayerRule playerRule = result2 switch { 2 => PlayerRule.Deny, 1 => PlayerRule.Allow, _ => PlayerRule.Default, }; if (playerRule != PlayerRule.Default) { list.Add(new RuleEntry { PlayerId = result, Name = name, Rule = playerRule }); } } return list; } private static string Serialize(IEnumerable<RuleEntry> entries) { List<string> list = new List<string>(); foreach (RuleEntry item in entries.OrderBy((RuleEntry x) => x.PlayerId)) { if (item.PlayerId != 0L && item.Rule != PlayerRule.Default) { string text = Convert.ToBase64String(Encoding.UTF8.GetBytes(item.Name ?? string.Empty)); string[] obj = new string[5] { item.PlayerId.ToString(), ":", null, null, null }; int rule = (int)item.Rule; obj[2] = rule.ToString(); obj[3] = ":"; obj[4] = text; list.Add(string.Concat(obj)); } } return string.Join(";", list.ToArray()); } private static void EnsureOwnerMetadata(Piece piece, ZNetView view, ZDO zdo) { if (zdo != null && !((Object)(object)piece == (Object)null)) { long owner = GetOwner(piece, zdo); Claim(view); if (zdo.GetLong("sac_owner", 0L) == 0L) { zdo.Set("sac_owner", owner); } if (string.IsNullOrEmpty(zdo.GetString("sac_owner_name", string.Empty))) { zdo.Set("sac_owner_name", PlayerDirectory.ResolveName(owner)); } } } private static void Claim(ZNetView view) { if ((Object)(object)view == (Object)null || !view.IsValid()) { return; } try { if (!view.IsOwner()) { view.ClaimOwnership(); } } catch (Exception ex) { Plugin.Debug("ClaimOwnership failed: " + ex.Message); } } internal static string SafePieceName(Piece piece) { if ((Object)(object)piece == (Object)null) { return "piece"; } string name = piece.m_name; if (string.IsNullOrEmpty(name)) { name = ((Object)piece).name; } return name ?? "piece"; } } internal static class PlayerDirectory { internal static List<PlayerRecord> GetPlayers(ZDO zdo) { Dictionary<long, PlayerRecord> dictionary = new Dictionary<long, PlayerRecord>(); AddConnectedRoster(dictionary); try { List<Player> allPlayers = Player.GetAllPlayers(); if (allPlayers != null) { foreach (Player item in allPlayers) { if (!((Object)(object)item == (Object)null)) { long playerID = item.GetPlayerID(); if (playerID != 0L) { dictionary[playerID] = new PlayerRecord { PlayerId = playerID, Name = item.GetPlayerName() }; } } } } } catch { } try { if ((Object)(object)Player.m_localPlayer != (Object)null) { long playerID2 = Player.m_localPlayer.GetPlayerID(); if (playerID2 != 0L) { dictionary[playerID2] = new PlayerRecord { PlayerId = playerID2, Name = Player.m_localPlayer.GetPlayerName() }; } } } catch { } foreach (RuleEntry item2 in AccessPolicy.ReadRules(zdo)) { if (!dictionary.ContainsKey(item2.PlayerId)) { dictionary[item2.PlayerId] = new PlayerRecord { PlayerId = item2.PlayerId, Name = (string.IsNullOrEmpty(item2.Name) ? ("Player " + item2.PlayerId) : item2.Name) }; } } return dictionary.Values.OrderBy<PlayerRecord, string>((PlayerRecord x) => x.Name, StringComparer.OrdinalIgnoreCase).ToList(); } private static void AddConnectedRoster(Dictionary<long, PlayerRecord> map) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) try { if (map == null || (Object)(object)ZNet.instance == (Object)null || ZDOMan.instance == null) { return; } MethodInfo methodInfo = AccessTools.Method(typeof(ZNet), "GetPlayerList", Type.EmptyTypes, (Type[])null); IEnumerable enumerable = ((methodInfo != null) ? (methodInfo.Invoke(ZNet.instance, null) as IEnumerable) : null); if (enumerable == null) { return; } foreach (object item in enumerable) { if (item == null) { continue; } Type type = item.GetType(); FieldInfo fieldInfo = AccessTools.Field(type, "m_name"); FieldInfo fieldInfo2 = AccessTools.Field(type, "m_characterID"); if (fieldInfo2 == null) { continue; } object value = fieldInfo2.GetValue(item); if (!(value is ZDOID)) { continue; } ZDO zDO = ZDOMan.instance.GetZDO((ZDOID)value); if (zDO == null) { continue; } long num = zDO.GetLong(ZDOVars.s_playerID, 0L); if (num != 0L) { string text = ((fieldInfo != null) ? (fieldInfo.GetValue(item) as string) : null); if (string.IsNullOrEmpty(text)) { text = "Player " + num; } map[num] = new PlayerRecord { PlayerId = num, Name = text }; } } } catch (Exception ex) { Plugin.Debug("Connected roster lookup failed: " + ex.Message); } } internal static string ResolveName(long playerId) { if (playerId == 0L) { return string.Empty; } try { if ((Object)(object)Player.m_localPlayer != (Object)null && Player.m_localPlayer.GetPlayerID() == playerId) { return Player.m_localPlayer.GetPlayerName(); } Dictionary<long, PlayerRecord> dictionary = new Dictionary<long, PlayerRecord>(); AddConnectedRoster(dictionary); if (dictionary.TryGetValue(playerId, out var value) && !string.IsNullOrEmpty(value.Name)) { return value.Name; } List<Player> allPlayers = Player.GetAllPlayers(); if (allPlayers != null) { foreach (Player item in allPlayers) { if ((Object)(object)item != (Object)null && item.GetPlayerID() == playerId) { return item.GetPlayerName(); } } } } catch { } return "Player " + playerId; } } internal static class RpcIdentity { internal static long ResolvePlayerId(long rpcSenderUid) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)ZNet.instance != (Object)null) { if (rpcSenderUid == ZNet.GetUID() && (Object)(object)Player.m_localPlayer != (Object)null) { return Player.m_localPlayer.GetPlayerID(); } ZNetPeer peer = ZNet.instance.GetPeer(rpcSenderUid); if (peer != null && ZDOMan.instance != null) { ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID); if (zDO != null) { return zDO.GetLong(ZDOVars.s_playerID, 0L); } } } } catch (Exception ex) { Plugin.Debug("RPC identity resolution failed: " + ex.Message); } return 0L; } internal static bool IsAdmin(long rpcSenderUid) { if (Plugin.AdminOverride == null || !Plugin.AdminOverride.Value) { return false; } try { if ((Object)(object)ZNet.instance == (Object)null) { return false; } if (rpcSenderUid == ZNet.GetUID()) { return ZNet.instance.LocalPlayerIsAdminOrHost(); } ZNetPeer peer = ZNet.instance.GetPeer(rpcSenderUid); return peer != null && ZNet.instance.IsAdmin(peer.m_socket.GetHostName()); } catch { return false; } } } internal static class Messages { internal static void Center(string text) { try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } MethodInfo methodInfo = (from m in typeof(Character).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == "Message" orderby m.GetParameters().Length descending select m).FirstOrDefault(); if (methodInfo == null) { return; } ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array = new object[parameters.Length]; for (int num = 0; num < parameters.Length; num++) { Type parameterType = parameters[num].ParameterType; if (num == 0 && parameterType.IsEnum) { array[num] = Enum.ToObject(parameterType, 2); } else if (parameterType == typeof(string)) { array[num] = text; } else if (parameterType == typeof(int)) { array[num] = 0; } else if (parameterType == typeof(bool)) { array[num] = false; } else { array[num] = null; } } methodInfo.Invoke(localPlayer, array); } catch { } } } internal static class UiText { private static bool _isFrench; private static float _nextLanguageRefresh; private static string _useKey = "E"; private static float _nextKeyRefresh; internal static string L(string fr, string en) { RefreshGameLanguage(); if (!_isFrench) { return en; } return fr; } internal static string CycleShortcut() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) return ModifierName((KeyCode)((Plugin.ManageModifier == null) ? 304 : ((int)Plugin.ManageModifier.Value))) + " + " + BoundUseKey(); } internal static string PanelShortcut() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) return ModifierName((KeyCode)((Plugin.ManageModifier == null) ? 304 : ((int)Plugin.ManageModifier.Value))) + " + " + PanelKeyLabel(); } internal static KeyCode PanelKey() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) KeyCode val = (KeyCode)((Plugin.PanelKey != null) ? ((int)Plugin.PanelKey.Value) : 0); if ((int)val != 0) { return val; } return (KeyCode)113; } private unsafe static string PanelKeyLabel() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) KeyCode val = (KeyCode)((Plugin.PanelKey != null) ? ((int)Plugin.PanelKey.Value) : 0); if ((int)val != 0) { return ((object)(*(KeyCode*)(&val))/*cast due to .constrained prefix*/).ToString(); } RefreshGameLanguage(); if (!_isFrench) { return "Q"; } return "A"; } internal static bool PanelKeyPressed() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Input.GetKeyDown(PanelKey()); } internal static string ModeName(AccessMode mode) { return mode switch { AccessMode.Private => L("PRIVÉ", "PRIVATE"), AccessMode.Whitelist => L("LISTE BLANCHE", "WHITELIST"), _ => "PUBLIC", }; } private unsafe static string ModifierName(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Invalid comparison between Unknown and I4 //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 if ((int)key == 304) { return L("Maj gauche", "Left Shift"); } if ((int)key == 303) { return L("Maj droite", "Right Shift"); } if ((int)key == 306) { return L("Ctrl gauche", "Left Ctrl"); } if ((int)key == 305) { return L("Ctrl droite", "Right Ctrl"); } if ((int)key == 308) { return L("Alt gauche", "Left Alt"); } if ((int)key == 307) { return L("Alt droite", "Right Alt"); } return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); } private static string BoundUseKey() { float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < _nextKeyRefresh) { return _useKey; } _nextKeyRefresh = realtimeSinceStartup + 2f; try { Type type = AccessTools.TypeByName("ZInput"); if (type != null) { MethodInfo methodInfo = (from m in type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where m.Name.IndexOf("BoundKeyString", StringComparison.OrdinalIgnoreCase) >= 0 where m.ReturnType == typeof(string) where m.GetParameters().Length != 0 && m.GetParameters()[0].ParameterType == typeof(string) orderby m.GetParameters().Length select m).FirstOrDefault(); if (methodInfo != null) { object obj = null; if (!methodInfo.IsStatic) { FieldInfo fieldInfo = type.GetField("instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("m_instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); PropertyInfo propertyInfo = type.GetProperty("instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetProperty("Instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); obj = ((fieldInfo != null) ? fieldInfo.GetValue(null) : ((propertyInfo != null) ? propertyInfo.GetValue(null, null) : null)); if (obj == null) { return _useKey; } } ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array = new object[parameters.Length]; array[0] = "Use"; for (int num = 1; num < parameters.Length; num++) { if (parameters[num].HasDefaultValue) { array[num] = parameters[num].DefaultValue; } else if (parameters[num].ParameterType == typeof(bool)) { array[num] = false; } else if (parameters[num].ParameterType.IsValueType) { array[num] = Activator.CreateInstance(parameters[num].ParameterType); } else { array[num] = null; } } string text = methodInfo.Invoke(obj, array) as string; if (!string.IsNullOrEmpty(text) && text.IndexOf('$') < 0) { _useKey = text; } } } } catch { } return _useKey; } private static void RefreshGameLanguage() { float realtimeSinceStartup = Time.realtimeSinceStartup; if (!(realtimeSinceStartup < _nextLanguageRefresh)) { _nextLanguageRefresh = realtimeSinceStartup + 2f; string text = ReadGameLanguage(); if (string.IsNullOrEmpty(text)) { _isFrench = false; return; } string text2 = text.Trim().ToLowerInvariant(); _isFrench = text2 == "fr" || text2.StartsWith("fr-") || text2.StartsWith("french") || text2.StartsWith("français") || text2.StartsWith("francais"); } } private static string ReadGameLanguage() { string[] array = new string[3] { "Localization", "LocalizationManager", "I2.Loc.LocalizationManager" }; for (int i = 0; i < array.Length; i++) { string text = ReadLanguageFromType(AccessTools.TypeByName(array[i])); if (!string.IsNullOrEmpty(text)) { return text; } } array = new string[4] { "language", "Language", "selectedLanguage", "SelectedLanguage" }; foreach (string text2 in array) { try { if (PlayerPrefs.HasKey(text2)) { string text3 = PlayerPrefs.GetString(text2, string.Empty); if (!string.IsNullOrEmpty(text3)) { return text3; } } } catch { } } return string.Empty; } private static string ReadLanguageFromType(Type type) { if (type == null) { return string.Empty; } try { object obj = null; FieldInfo fieldInfo = type.GetField("instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("m_instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); PropertyInfo propertyInfo = type.GetProperty("instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetProperty("Instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo != null && fieldInfo.IsStatic) { obj = fieldInfo.GetValue(null); } else if (propertyInfo != null) { MethodInfo getMethod = propertyInfo.GetGetMethod(nonPublic: true); if (getMethod != null && getMethod.IsStatic) { obj = propertyInfo.GetValue(null, null); } } string[] array = new string[4] { "CurrentLanguage", "SelectedLanguage", "Language", "m_language" }; foreach (string name in array) { PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property == null || property.PropertyType != typeof(string)) { continue; } MethodInfo getMethod2 = property.GetGetMethod(nonPublic: true); object obj2 = ((getMethod2 != null && getMethod2.IsStatic) ? null : obj); if (!(getMethod2 == null) && (getMethod2.IsStatic || obj2 != null)) { string text = property.GetValue(obj2, null) as string; if (!string.IsNullOrEmpty(text)) { return text; } } } array = new string[4] { "m_language", "s_language", "CurrentLanguage", "SelectedLanguage" }; foreach (string name2 in array) { FieldInfo field = type.GetField(name2, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || field.FieldType != typeof(string)) { continue; } object obj3 = (field.IsStatic ? null : obj); if (field.IsStatic || obj3 != null) { string text2 = field.GetValue(obj3) as string; if (!string.IsNullOrEmpty(text2)) { return text2; } } } array = new string[3] { "GetSelectedLanguage", "GetCurrentLanguage", "GetLanguage" }; foreach (string name3 in array) { MethodInfo method = type.GetMethod(name3, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method == null || method.ReturnType != typeof(string)) { continue; } object obj4 = (method.IsStatic ? null : obj); if (method.IsStatic || obj4 != null) { string text3 = method.Invoke(obj4, null) as string; if (!string.IsNullOrEmpty(text3)) { return text3; } } } } catch { } return string.Empty; } } internal static class PlayerArguments { internal static Player Find(object[] args) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown if (args == null) { return null; } foreach (object obj in args) { Player val = (Player)((obj is Player) ? obj : null); if ((Object)(object)val != (Object)null) { return val; } Humanoid val2 = (Humanoid)((obj is Humanoid) ? obj : null); if (val2 is Player) { return (Player)val2; } Collider val3 = (Collider)((obj is Collider) ? obj : null); if ((Object)(object)val3 != (Object)null) { Player componentInParent = ((Component)val3).GetComponentInParent<Player>(); if ((Object)(object)componentInParent != (Object)null) { return componentInParent; } } } return null; } } internal static class AccessHotkeys { private static readonly FieldInfo InteractMaskField = AccessTools.Field(typeof(Player), "m_interactMask"); private static readonly FieldInfo HoveringField = typeof(Player).GetField("m_hovering", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly MethodInfo HoverObjectMethod = typeof(Player).GetMethod("GetHoverObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); internal static void Tick() { if (AccessPanel.IsOpen || !Plugin.ModifierHeld() || !UiText.PanelKeyPressed()) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)GameCamera.instance == (Object)null) && !((Object)(object)((Character)localPlayer).m_eye == (Object)null)) { if (!TryFindLookTarget(localPlayer, out var piece, out var view, out var zdo)) { Messages.Center(UiText.L("Aucun objet compatible ciblé.", "No supported object targeted.")); } else if (!AccessPolicy.CanManageLocal(piece, zdo)) { Messages.Center(UiText.L("Vous n'êtes pas propriétaire de cet objet.", "You do not own this object.")); } else { AccessPanel.Open(piece, view, zdo); } } } private static bool TryFindLookTarget(Player player, out Piece piece, out ZNetView view, out ZDO zdo) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) piece = null; view = null; zdo = null; Component hoveredComponent = GetHoveredComponent(player); if ((Object)(object)hoveredComponent != (Object)null && AccessPolicy.TryContext(hoveredComponent, null, out var piece2, out var view2, out var zdo2) && AccessPolicy.IsSupportedPiece(piece2)) { piece = piece2; view = view2; zdo = zdo2; return true; } int num = -5; try { if (InteractMaskField != null) { num = (int)InteractMaskField.GetValue(player); } } catch { } float num2 = Mathf.Max(4f, player.m_maxPlaceDistance); foreach (RaycastHit item in from x in Physics.RaycastAll(((Component)GameCamera.instance).transform.position, ((Component)GameCamera.instance).transform.forward, num2, num) orderby ((RaycastHit)(ref x)).distance select x) { RaycastHit current = item; if (!((Object)(object)((RaycastHit)(ref current)).collider == (Object)null) && AccessPolicy.TryContext((Component)(object)((RaycastHit)(ref current)).collider, null, out var piece3, out var view3, out var zdo3) && AccessPolicy.IsSupportedPiece(piece3)) { piece = piece3; view = view3; zdo = zdo3; return true; } } return false; } private static Component GetHoveredComponent(Player player) { if ((Object)(object)player == (Object)null) { return null; } try { object obj = ((HoveringField != null) ? HoveringField.GetValue(player) : null); if (obj == null && HoverObjectMethod != null) { obj = HoverObjectMethod.Invoke(player, null); } Component val = (Component)((obj is Component) ? obj : null); if ((Object)(object)val != (Object)null) { return val; } GameObject val2 = (GameObject)((obj is GameObject) ? obj : null); return (Component)(object)(((Object)(object)val2 != (Object)null) ? val2.transform : null); } catch { return null; } } } internal static class InteractionGuard { internal static bool Check(Component component, Player player, bool repeat, string label, ref bool result) { if (repeat || (Object)(object)player == (Object)null) { return true; } if (!AccessPolicy.TryContext(component, null, out var piece, out var view, out var zdo)) { return true; } if ((Object)(object)player == (Object)(object)Player.m_localPlayer && Plugin.ModifierHeld()) { if (!AccessPolicy.CanManageLocal(piece, zdo)) { Messages.Center(UiText.L("Vous n'êtes pas propriétaire de cet objet.", "You do not own this object.")); result = true; return false; } AccessPolicy.CycleMode(piece, view, zdo); result = true; return false; } if (!AccessPolicy.Evaluate(piece, zdo, player.GetPlayerID(), out var reason)) { if ((Object)(object)player == (Object)(object)Player.m_localPlayer) { Messages.Center(UiText.L("Accès refusé.", "No access.")); } Plugin.Debug(label + " denied player=" + player.GetPlayerID() + " reason=" + reason); result = true; return false; } return true; } internal static bool ManageOnly(Component component, Player player, bool repeat, ref bool result) { if (repeat || !Plugin.ModifierHeld() || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer) { return true; } if (!AccessPolicy.TryContext(component, null, out var piece, out var view, out var zdo)) { return true; } if (!AccessPolicy.CanManageLocal(piece, zdo)) { Messages.Center(UiText.L("Vous n'êtes pas propriétaire de cet objet.", "You do not own this object.")); result = true; return false; } AccessPolicy.CycleMode(piece, view, zdo); result = true; return false; } } internal static class AccessPanel { [CompilerGenerated] private static class <>O { public static WindowFunction <0>__DrawWindow; } private static bool _open; private static Piece _piece; private static ZNetView _view; private static ZDO _zdo; private static Vector2 _scroll; private static Rect _window = new Rect(0f, 0f, 820f, 760f); internal static bool IsOpen => _open; internal static void Open(Piece piece, ZNetView view, ZDO zdo) { //IL_0037: 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) if (!((Object)(object)piece == (Object)null) && !((Object)(object)view == (Object)null) && zdo != null && AccessPolicy.CanManageLocal(piece, zdo)) { _piece = piece; _view = view; _zdo = zdo; _open = true; _scroll = Vector2.zero; ((Rect)(ref _window)).width = Mathf.Max(420f, Mathf.Min(820f, (float)Screen.width - 40f)); ((Rect)(ref _window)).height = Mathf.Max(520f, Mathf.Min(760f, (float)Screen.height - 40f)); ((Rect)(ref _window)).x = ((float)Screen.width - ((Rect)(ref _window)).width) * 0.5f; ((Rect)(ref _window)).y = ((float)Screen.height - ((Rect)(ref _window)).height) * 0.5f; Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; } } internal static void Close() { _open = false; _piece = null; _view = null; _zdo = null; } internal static void Tick() { if (!_open) { return; } if ((Object)(object)_piece == (Object)null || (Object)(object)_view == (Object)null || !_view.IsValid()) { Close(); return; } Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; if (Input.GetKeyDown((KeyCode)27)) { Close(); } } internal static void Draw() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0036: 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_0041: Expected O, but got Unknown if (_open && !((Object)(object)_piece == (Object)null) && _zdo != null) { Rect window = _window; object obj = <>O.<0>__DrawWindow; if (obj == null) { WindowFunction val = DrawWindow; <>O.<0>__DrawWindow = val; obj = (object)val; } _window = GUI.Window(987654, window, (WindowFunction)obj, L("Contrôle d'accès", "Access Control")); } } private static void DrawWindow(int id) { //IL_07af: Unknown result type (might be due to invalid IL or missing references) //IL_050c: Unknown result type (might be due to invalid IL or missing references) //IL_0521: Unknown result type (might be due to invalid IL or missing references) //IL_0526: Unknown result type (might be due to invalid IL or missing references) GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("<b>" + AccessPolicy.SafePieceName(_piece) + "</b>", Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); if (GUILayout.Button(L("X Fermer", "X Close"), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(110f), GUILayout.Height(26f) })) { GUILayout.EndHorizontal(); GUILayout.EndVertical(); Close(); return; } GUILayout.EndHorizontal(); GUILayout.Label(L("Propriétaire : ", "Owner: ") + AccessPolicy.GetOwnerName(_piece, _zdo), Array.Empty<GUILayoutOption>()); GUILayout.Space(8f); long owner; string ownerName; bool flag = AccessPolicy.TryGetAssignedBedOwner(_piece, _zdo, out owner, out ownerName); AccessMode effectiveMode = AccessPolicy.GetEffectiveMode(_piece, _zdo); bool flag2 = AccessPolicy.HasEffectiveRestriction(_piece, _zdo); if (flag) { GUILayout.Label(L("LIT ATTRIBUÉ — mode PRIVÉ forcé", "ASSIGNED BED — PRIVATE mode enforced"), Array.Empty<GUILayoutOption>()); GUILayout.Label(L("Seul le joueur auquel ce lit est attribué peut y dormir et le détruire. Les administrateurs conservent leur dérogation de gestion/destruction.", "Only the player assigned to this bed can sleep in it or destroy it. Administrators keep their management/destruction override."), Array.Empty<GUILayoutOption>()); GUILayout.Space(10f); } else { GUILayout.Label(L("Politique d'accès", "Access policy"), Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUI.enabled = effectiveMode != AccessMode.Public; if (GUILayout.Button(L("PUBLIC — tout le monde", "PUBLIC — everyone"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) })) { AccessPolicy.SetMode(_piece, _view, _zdo, AccessMode.Public); } GUI.enabled = effectiveMode != AccessMode.Private; if (GUILayout.Button(L("PRIVÉ — propriétaire uniquement", "PRIVATE — owner only"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) })) { AccessPolicy.SetMode(_piece, _view, _zdo, AccessMode.Private); } GUI.enabled = effectiveMode != AccessMode.Whitelist; if (GUILayout.Button(L("LISTE BLANCHE", "WHITELIST"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) })) { AccessPolicy.SetMode(_piece, _view, _zdo, AccessMode.Whitelist); } GUI.enabled = true; GUILayout.EndHorizontal(); GUILayout.Space(8f); } GUILayout.Label(flag2 ? L("Protection destruction : ACTIVE (propriétaire/admin uniquement)", "Destruction protection: ACTIVE (owner/admin only)") : L("Protection destruction : INACTIVE (règles vanilla)", "Destruction protection: INACTIVE (vanilla rules)"), Array.Empty<GUILayoutOption>()); GUILayout.Label(L("Changement rapide : ", "Quick cycle: ") + UiText.CycleShortcut() + L(" — PUBLIC → PRIVÉ → LISTE BLANCHE", " — PUBLIC → PRIVATE → WHITELIST"), Array.Empty<GUILayoutOption>()); GUILayout.Label(L("Ouvrir ce panneau : ", "Open this panel: ") + UiText.PanelShortcut() + L(" (A en français, Q dans les autres langues par défaut)", " (A in French, Q in other languages by default)"), Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(L("Modificateur rapide :", "Quick modifier:"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(145f) }); if (GUILayout.Button(L("Maj", "Shift"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) })) { Plugin.ManageModifier.Value = (KeyCode)304; } if (GUILayout.Button("Alt", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) })) { Plugin.ManageModifier.Value = (KeyCode)308; } if (GUILayout.Button("Ctrl", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) })) { Plugin.ManageModifier.Value = (KeyCode)306; } GUILayout.EndHorizontal(); GUILayout.Space(8f); if (!flag) { List<PlayerRecord> players = PlayerDirectory.GetPlayers(_zdo); long owner2 = AccessPolicy.GetOwner(_piece, _zdo); int num = AccessPolicy.ReadRules(_zdo).Count((RuleEntry x) => x.Rule == PlayerRule.Allow); string text = effectiveMode switch { AccessMode.Private => L("PRIVÉ — propriétaire uniquement", "PRIVATE — owner only"), AccessMode.Whitelist => L("LISTE BLANCHE ACTIVE — propriétaire + ", "WHITELIST ACTIVE — owner + ") + num + L(" joueur(s)", " player(s)"), _ => L("PUBLIC — sauf joueurs explicitement interdits", "PUBLIC — except explicitly denied players"), }; GUILayout.Label(L("État effectif : ", "Effective state: ") + text, Array.Empty<GUILayoutOption>()); GUILayout.Label(L("Liste blanche : sélectionnez LISTE BLANCHE, puis Autoriser pour chaque joueur admis.", "Whitelist: select WHITELIST, then Allow for each admitted player."), Array.Empty<GUILayoutOption>()); GUILayout.Label(L("PUBLIC applique Interdire ; PRIVÉ reste propriétaire uniquement ; LISTE BLANCHE applique Interdire puis Autoriser.", "PUBLIC applies Deny; PRIVATE remains owner-only; WHITELIST applies Deny then Allow."), Array.Empty<GUILayoutOption>()); if (players.All((PlayerRecord x) => x.PlayerId == owner2)) { GUILayout.Label(L("Aucun autre joueur détecté : le joueur à ajouter doit être connecté, puis il restera mémorisé hors ligne.", "No other player detected: the player to add must be connected once, then remains listed while offline."), Array.Empty<GUILayoutOption>()); } GUILayout.Space(4f); float num2 = Mathf.Max(100f, ((Rect)(ref _window)).height - 460f); _scroll = GUILayout.BeginScrollView(_scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(num2) }); foreach (PlayerRecord item in players) { GUILayout.BeginHorizontal(GUIStyle.op_Implicit("box"), Array.Empty<GUILayoutOption>()); GUILayout.Label(item.Name + ((item.PlayerId == owner2) ? L(" (propriétaire)", " (owner)") : string.Empty), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(260f) }); if (item.PlayerId == owner2) { GUILayout.Label(L("Toujours autorisé", "Always allowed"), Array.Empty<GUILayoutOption>()); } else { PlayerRule rule = AccessPolicy.GetRule(_zdo, item.PlayerId); GUI.enabled = rule != PlayerRule.Default; if (GUILayout.Button(L("Défaut", "Default"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) })) { AccessPolicy.SetRule(_piece, _view, _zdo, item.PlayerId, item.Name, PlayerRule.Default); } GUI.enabled = rule != PlayerRule.Allow; if (GUILayout.Button(L("Autoriser", "Allow"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) })) { AccessPolicy.SetRule(_piece, _view, _zdo, item.PlayerId, item.Name, PlayerRule.Allow); } GUI.enabled = rule != PlayerRule.Deny; if (GUILayout.Button(L("Interdire", "Deny"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) })) { AccessPolicy.SetRule(_piece, _view, _zdo, item.PlayerId, item.Name, PlayerRule.Deny); } GUI.enabled = true; } GUILayout.EndHorizontal(); } GUILayout.EndScrollView(); } GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (!flag && GUILayout.Button(L("Réinitialiser les exceptions", "Clear exceptions"), Array.Empty<GUILayoutOption>())) { AccessPolicy.ClearRules(_piece, _view, _zdo); } if (GUILayout.Button(L("Fermer", "Close"), (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(140f), GUILayout.Height(30f) })) { Close(); } GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 28f)); } private static string L(string fr, string en) { return UiText.L(fr, en); } } internal static class HoverText { internal static string Append(string original, Piece piece, ZDO zdo) { if (Plugin.ShowHoverStatus == null || !Plugin.ShowHoverStatus.Value || (Object)(object)piece == (Object)null || zdo == null) { return original; } AccessMode effectiveMode = AccessPolicy.GetEffectiveMode(piece, zdo); List<RuleEntry> list = AccessPolicy.ReadRules(zdo); bool flag = AccessPolicy.HasEffectiveRestriction(piece, zdo); long owner; string ownerName; bool num = AccessPolicy.TryGetAssignedBedOwner(piece, zdo, out owner, out ownerName); bool flag2 = !num && effectiveMode == AccessMode.Whitelist; bool flag3 = effectiveMode == AccessMode.Public && list.Any((RuleEntry x) => x.Rule == PlayerRule.Deny); string text = (flag ? "#F2B35D" : "#7DCE82"); string text2 = (num ? UiText.L("LIT ATTRIBUÉ — PRIVÉ", "ASSIGNED BED — PRIVATE") : (flag2 ? UiText.L("LISTE BLANCHE", "WHITELIST") : (flag3 ? UiText.L("PUBLIC AVEC EXCEPTIONS", "PUBLIC WITH EXCEPTIONS") : ((effectiveMode == AccessMode.Private) ? UiText.L("PRIVÉ", "PRIVATE") : "PUBLIC")))); string text3 = original + "\n<color=" + text + "><b>" + UiText.L("Accès : ", "Access: ") + text2 + "</b></color>"; if ((Plugin.ShowDestructionOnlyWithBuildTool != null && !Plugin.ShowDestructionOnlyWithBuildTool.Value) || IsBuildToolEquipped()) { string text4 = (flag ? UiText.L("Destruction : PROTÉGÉE (propriétaire/admin)", "Destruction: PROTECTED (owner/admin)") : UiText.L("Destruction : VANILLA", "Destruction: VANILLA")); text3 = text3 + "\n<color=" + text + ">" + text4 + "</color>"; } if (flag || list.Count != 0) { text3 = text3 + "\n<color=#CFCFCF>" + UiText.L("Propriétaire : ", "Owner: ") + AccessPolicy.GetOwnerName(piece, zdo) + "</color>"; } if (AccessPolicy.CanManageLocal(piece, zdo)) { text3 = text3 + "\n[<color=yellow><b>" + UiText.CycleShortcut() + "</b></color>] " + UiText.L("Changer l'accès", "Cycle access"); text3 = text3 + "\n[<color=yellow><b>" + UiText.PanelShortcut() + "</b></color>] " + UiText.L("Configurer les accès", "Configure access"); } return text3; } private static bool IsBuildToolEquipped() { try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } MethodInfo methodInfo = typeof(Humanoid).GetMethod("GetRightItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null) ?? typeof(Player).GetMethod("GetRightItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); ItemData val = (ItemData)((methodInfo != null) ? /*isinst with value type is only supported in some contexts*/: null); if (val == null || val.m_shared == null) { return false; } if ((Object)(object)val.m_shared.m_buildPieces != (Object)null) { return true; } string text = val.m_shared.m_name ?? string.Empty; return text.IndexOf("hammer", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("marteau", StringComparison.OrdinalIgnoreCase) >= 0; } catch { return false; } } } [HarmonyPatch(typeof(Container), "CheckAccess", new Type[] { typeof(long) })] internal static class ContainerCheckAccessPatch { private static bool Prepare() { if (!Plugin.Enabled(Plugin.ManageContainers) && !Plugin.Enabled(Plugin.ManageCarts)) { return Plugin.Enabled(Plugin.ManageShips); } return true; } private static bool Prefix(Container __instance, long __0, ref bool __result) { try { if (!AccessPolicy.IsContainerEnabled(__instance)) { return true; } long playerId = __0; if (!AccessPolicy.TryContext((Component)(object)__instance, null, out var piece, out var _, out var zdo)) { return true; } __result = AccessPolicy.Evaluate(piece, zdo, playerId, out var reason); Plugin.Debug("Container " + AccessPolicy.SafePieceName(piece) + " player=" + playerId + " allowed=" + __result + " reason=" + reason); return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Container access patch failed; falling back to vanilla: " + ex.Message)); return true; } } } [HarmonyPatch(typeof(Container), "Interact")] internal static class ContainerInteractPatch { private static bool Prepare() { if (!Plugin.Enabled(Plugin.ManageContainers) && !Plugin.Enabled(Plugin.ManageCarts)) { return Plugin.Enabled(Plugin.ManageShips); } return true; } private static bool Prefix(Container __instance, Humanoid __0, bool __1, bool __2, ref bool __result) { if (!AccessPolicy.IsContainerEnabled(__instance)) { return true; } return InteractionGuard.ManageOnly((Component)(object)__instance, (Player)(object)((__0 is Player) ? __0 : null), __1, ref __result); } } [HarmonyPatch(typeof(Container), "GetHoverText")] internal static class ContainerHoverPatch { private static bool Prepare() { if (!Plugin.Enabled(Plugin.ManageContainers) && !Plugin.Enabled(Plugin.ManageCarts)) { return Plugin.Enabled(Plugin.ManageShips); } return true; } private static void Postfix(Container __instance, ref string __result) { try { if (AccessPolicy.IsContainerEnabled(__instance) && AccessPolicy.TryContext((Component)(object)__instance, null, out var piece, out var _, out var zdo)) { __result = HoverText.Append(__result, piece, zdo); } } catch { } } } [HarmonyPatch(typeof(Door), "Interact")] internal static class DoorInteractPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageDoorsAndGates); } private static bool Prefix(Door __instance, Humanoid __0, bool __1, bool __2, ref bool __result) { return InteractionGuard.Check((Component)(object)__instance, (Player)(object)((__0 is Player) ? __0 : null), __1, "Door", ref __result); } } [HarmonyPatch(typeof(Door), "GetHoverText")] internal static class DoorHoverPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageDoorsAndGates); } private static void Postfix(Door __instance, ref string __result) { try { if (AccessPolicy.TryContext((Component)(object)__instance, null, out var piece, out var _, out var zdo)) { __result = HoverText.Append(__result, piece, zdo); } } catch { } } } [HarmonyPatch(typeof(Door), "RPC_UseDoor")] internal static class DoorRpcPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageDoorsAndGates); } private static bool Prefix(Door __instance, long __0, bool __1) { try { long rpcSenderUid = __0; if ((Object)(object)__instance == (Object)null) { return true; } if (!AccessPolicy.TryContext((Component)(object)__instance, null, out var piece, out var view, out var zdo)) { return true; } if (!view.IsOwner()) { return true; } long num = RpcIdentity.ResolvePlayerId(rpcSenderUid); if (num == 0L) { return true; } string reason; bool flag = AccessPolicy.Evaluate(piece, zdo, num, out reason); if (!flag) { Plugin.Debug("RPC_UseDoor denied sender=" + rpcSenderUid + " player=" + num + " reason=" + reason); } return flag; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Door RPC access check failed; falling back to vanilla: " + ex.Message)); return true; } } } [HarmonyPatch(typeof(Bed), "Interact")] internal static class BedInteractPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageBeds); } private static bool Prefix(Bed __instance, Humanoid __0, bool __1, bool __2, ref bool __result) { return InteractionGuard.Check((Component)(object)__instance, (Player)(object)((__0 is Player) ? __0 : null), __1, "Bed", ref __result); } } [HarmonyPatch(typeof(Bed), "GetHoverText")] internal static class BedHoverPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageBeds); } private static void Postfix(Bed __instance, ref string __result) { try { if (AccessPolicy.TryContext((Component)(object)__instance, null, out var piece, out var _, out var zdo)) { __result = HoverText.Append(__result, piece, zdo); } } catch { } } } [HarmonyPatch(typeof(CraftingStation), "Interact")] internal static class CraftingStationInteractPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageCraftingStations); } private static bool Prefix(CraftingStation __instance, Humanoid __0, bool __1, bool __2, ref bool __result) { return InteractionGuard.Check((Component)(object)__instance, (Player)(object)((__0 is Player) ? __0 : null), __1, "Crafting station", ref __result); } } [HarmonyPatch(typeof(CraftingStation), "GetHoverText")] internal static class CraftingStationHoverPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageCraftingStations); } private static void Postfix(CraftingStation __instance, ref string __result) { try { if (AccessPolicy.TryContext((Component)(object)__instance, null, out var piece, out var _, out var zdo)) { __result = HoverText.Append(__result, piece, zdo); } } catch { } } } [HarmonyPatch(typeof(CookingStation), "Interact")] internal static class CookingStationInteractPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageCookingStations); } private static bool Prefix(CookingStation __instance, Humanoid __0, bool __1, bool __2, ref bool __result) { return InteractionGuard.Check((Component)(object)__instance, (Player)(object)((__0 is Player) ? __0 : null), __1, "Cooking station collect", ref __result); } } [HarmonyPatch(typeof(CookingStation), "UseItem")] internal static class CookingStationUseItemPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageCookingStations); } private static bool Prefix(CookingStation __instance, Humanoid __0, ItemData __1, ref bool __result) { return InteractionGuard.Check((Component)(object)__instance, (Player)(object)((__0 is Player) ? __0 : null), repeat: false, "Cooking station add", ref __result); } } [HarmonyPatch(typeof(CookingStation), "GetHoverText")] internal static class CookingStationHoverPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageCookingStations); } private static void Postfix(CookingStation __instance, ref string __result) { try { if (AccessPolicy.TryContext((Component)(object)__instance, null, out var piece, out var _, out var zdo)) { __result = HoverText.Append(__result, piece, zdo); } } catch { } } } [HarmonyPatch] internal static class MapTableActionPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageCartographyTables); } private static IEnumerable<MethodBase> TargetMethods() { return (from m in typeof(MapTable).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where (m.Name == "OnRead" || m.Name == "OnWrite") && m.ReturnType == typeof(bool) select m).Cast<MethodBase>(); } private static bool Prefix(MapTable __instance, MethodBase __originalMethod, object[] __args, ref bool __result) { Player player = PlayerArguments.Find(__args); string label = ((__originalMethod != null && __originalMethod.Name == "OnWrite") ? "Cartography deposit" : "Cartography read"); return InteractionGuard.Check((Component)(object)__instance, player, repeat: false, label, ref __result); } } [HarmonyPatch(typeof(Switch), "GetHoverText")] internal static class MapTableSwitchHoverPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageCartographyTables); } private static void Postfix(Switch __instance, ref string __result) { try { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).GetComponentInParent<MapTable>() == (Object)null) && AccessPolicy.TryContext((Component)(object)__instance, null, out var piece, out var _, out var zdo)) { __result = HoverText.Append(__result, piece, zdo); } } catch { } } } [HarmonyPatch(typeof(Vagon), "Interact")] internal static class VagonInteractPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageCarts); } private static bool Prefix(Vagon __instance, Humanoid __0, bool __1, bool __2, ref bool __result) { return InteractionGuard.Check((Component)(object)__instance, (Player)(object)((__0 is Player) ? __0 : null), __1, "Cart", ref __result); } } [HarmonyPatch(typeof(Vagon), "GetHoverText")] internal static class VagonHoverPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageCarts); } private static void Postfix(Vagon __instance, ref string __result) { try { if (AccessPolicy.TryContext((Component)(object)__instance, null, out var piece, out var _, out var zdo)) { __result = HoverText.Append(__result, piece, zdo); } } catch { } } } [HarmonyPatch(typeof(ShipControlls), "Interact")] internal static class ShipControlsInteractPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageShips); } private static bool Prefix(ShipControlls __instance, Humanoid __0, bool __1, bool __2, ref bool __result) { return InteractionGuard.Check((Component)(object)__instance, (Player)(object)((__0 is Player) ? __0 : null), __1, "Ship controls", ref __result); } } [HarmonyPatch(typeof(ShipControlls), "GetHoverText")] internal static class ShipControlsHoverPatch { private static bool Prepare() { return Plugin.Enabled(Plugin.ManageShips); } private static void Postfix(ShipControlls __instance, ref string __result) { try { if (AccessPolicy.TryContext((Component)(object)__instance, null, out var piece, out var _, out var zdo)) { __result = HoverText.Append(__result, piece, zdo); } } catch { } } } [HarmonyPatch(typeof(Player), "RemovePiece")] internal static class RemovePiecePatch { private static readonly FieldInfo RemoveRayMaskField = AccessTools.Field(typeof(Player), "m_removeRayMask"); private static bool Prefix(Player __instance, ref bool __result) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) try { if (Plugin.ProtectConfiguredPieces == null || !Plugin.ProtectConfiguredPieces.Value || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } if ((Object)(object)GameCamera.instance == (Object)null || (Object)(object)((Character)__instance).m_eye == (Object)null) { return true; } int num = ((RemoveRayMaskField != null) ? ((int)RemoveRayMaskField.GetValue(__instance)) : (-5)); RaycastHit val = default(RaycastHit); if (!Physics.Raycast(((Component)GameCamera.instance).transform.position, ((Component)GameCamera.instance).transform.forward, ref val, 50f, num)) { return true; } if (Vector3.Distance(((RaycastHit)(ref val)).point, ((Character)__instance).m_eye.position) >= __instance.m_maxPlaceDistance) { return true; } Piece piece = (((Object)(object)((RaycastHit)(ref val)).collider != (Object)null) ? ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Piece>() : null); if (!AccessPolicy.IsSupportedPiece(piece)) { return true; } if (!AccessPolicy.TryContext(piece, out var _, out var zdo)) { return true; } if (AccessPolicy.CanRemoveOrDamage(piece, zdo, __instance.GetPlayerID(), AccessPolicy.IsLocalAdmin())) { return true; } Messages.Center("This protected object can only be dismantled by its owner."); __result = false; return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Hammer removal guard failed; falling back to vanilla: " + ex.Message)); return true; } } } [HarmonyPatch(typeof(WearNTear), "RPC_Remove")] internal static class WearNTearRemovePatch { private static bool Prefix(WearNTear __instance, long __0, bool __1) { try { long rpcSenderUid = __0; if (Plugin.ProtectConfiguredPieces == null || !Plugin.ProtectConfiguredPieces.Value || (Object)(object)__instance == (Object)null) { return true; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner()) { return true; } Piece component2 = ((Component)__instance).GetComponent<Piece>(); if (!AccessPolicy.IsSupportedPiece(component2)) { return true; } ZDO zDO = component.GetZDO(); if (zDO == null) { return true; } long num = RpcIdentity.ResolvePlayerId(rpcSenderUid); if (num == 0L) { return true; } bool num2 = AccessPolicy.CanRemoveOrDamage(component2, zDO, num, RpcIdentity.IsAdmin(rpcSenderUid)); if (!num2) { Plugin.Debug("RPC_Remove denied sender=" + rpcSenderUid + " player=" + num); } return num2; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Server removal guard failed; falling back to vanilla: " + ex.Message)); return true; } } } [HarmonyPatch(typeof(WearNTear), "RPC_Damage")] internal static class WearNTearDamagePatch { private static bool Prefix(WearNTear __instance, long __0, HitData __1) { try { long rpcSenderUid = __0; if (Plugin.ProtectConfiguredPieces == null || !Plugin.ProtectConfiguredPieces.Value || (Object)(object)__instance == (Object)null) { return true; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner()) { return true; } Piece component2 = ((Component)__instance).GetComponent<Piece>(); if (!AccessPolicy.IsSupportedPiece(component2)) { return true; } ZDO zDO = component.GetZDO(); if (zDO == null || !AccessPolicy.HasEffectiveRestriction(component2, zDO)) { return true; } long num = RpcIdentity.ResolvePlayerId(rpcSenderUid); if (num == 0L && __1 != null) { Character attacker = __1.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if ((Object)(object)val != (Object)null) { num = val.GetPlayerID(); } } if (num == 0L) { return true; } bool num2 = AccessPolicy.CanRemoveOrDamage(component2, zDO, num, RpcIdentity.IsAdmin(rpcSenderUid)); if (!num2) { Plugin.Debug("RPC_Damage denied sender=" + rpcSenderUid + " player=" + num); } return num2; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Server damage guard failed; falling back to vanilla: " + ex.Message)); return true; } } } [HarmonyPatch(typeof(Player), "TakeInput")] internal static class PlayerTakeInputPatch { private static void Postfix(Player __instance, ref bool __result) { if (AccessPanel.IsOpen && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { __result = false; } } } [HarmonyPatch(typeof(PlayerController), "TakeInput", new Type[] { typeof(bool) })] internal static class PlayerControllerTakeInputPatch { private static void Postfix(ref bool __result) { if (AccessPanel.IsOpen) { __result = false; } } } [HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")] internal static class MouseCapturePatch { private static bool Prefix() { if (!AccessPanel.IsOpen) { return true; } Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; return false; } } }