using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("AichoGuardian")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("AichoGuardian")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("D28110A9-E229-4700-AD4D-DCD37486A82B")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace NazhiMods.AichoGuardian; [BepInPlugin("nazhi.aicho.guardian", "Aicho Guardian", "1.3.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class AichoGuardianPlugin : BaseUnityPlugin { public const string PluginGuid = "nazhi.aicho.guardian"; public const string PluginName = "Aicho Guardian"; public const string PluginVersion = "1.3.0"; internal const string GuardianPrefabName = "Aicho_Guardian"; internal const string WallSourcePrefabName = "piece_dvergr_metal_wall_2x2"; internal const string WallClonePrefabName = "AichoDverg_Wall"; public static ConfigEntry CFG_SearchRadius; public static ConfigEntry CFG_ResetSeconds; private Harmony _harmony; private void Awake() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown CFG_SearchRadius = ((BaseUnityPlugin)this).Config.Bind("AichoGuardian", "SearchRadius", 5f, new ConfigDescription("Radio máximo para buscar muros AichoDverg_Wall.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 100f), Array.Empty())); CFG_ResetSeconds = ((BaseUnityPlugin)this).Config.Bind("AichoGuardian", "ResetSeconds", 5f, new ConfigDescription("Segundos para que el tótem vuelva a su estado visual activo tras usarse.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 600f), Array.Empty())); PrefabManager.OnVanillaPrefabsAvailable += RegisterAichoGuardianAndWall; _harmony = new Harmony("nazhi.aicho.guardian"); _harmony.PatchAll(typeof(AichoGuardianPlugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Aicho Guardian cargado con SearchRadius={CFG_SearchRadius.Value}, ResetSeconds={CFG_ResetSeconds.Value}"); } private void OnDestroy() { PrefabManager.OnVanillaPrefabsAvailable -= RegisterAichoGuardianAndWall; try { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch { } } private void RegisterAichoGuardianAndWall() { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Expected O, but got Unknown //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Expected O, but got Unknown //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Expected O, but got Unknown //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Expected O, but got Unknown try { GameObject prefab = PrefabManager.Instance.GetPrefab("piece_dvergr_metal_wall_2x2"); if ((Object)(object)prefab == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"No se encontró el prefab 'piece_dvergr_metal_wall_2x2'."); return; } GameObject val = PrefabManager.Instance.CreateClonedPrefab("AichoDverg_Wall", prefab); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"No se pudo clonar 'piece_dvergr_metal_wall_2x2' a 'AichoDverg_Wall'."); return; } EnsureAdminOnlyPlacement(val, "AichoDverg_Wall"); Piece component = val.GetComponent(); if ((Object)(object)component != (Object)null) { component.m_name = "$piece_aicho_dverg_wall"; component.m_description = "$piece_aicho_dverg_wall_desc"; } PieceConfig val2 = new PieceConfig(); val2.PieceTable = "_HammerPieceTable"; val2.Category = "Misc"; val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[1] { new RequirementConfig { Item = "Stone", Amount = 10 } }; PieceConfig val3 = val2; PieceManager.Instance.AddPiece(new CustomPiece(val, true, val3)); LocalizationManager.Instance.AddToken("piece_aicho_dverg_wall", "Aicho Dvergr Wall", false); LocalizationManager.Instance.AddToken("piece_aicho_dverg_wall_desc", "Muro especial (solo admins).", false); GameObject prefab2 = PrefabManager.Instance.GetPrefab("guard_stone"); if ((Object)(object)prefab2 == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"No se encontró el prefab base del tótem (guard_stone / dverger_guardstone)."); return; } GameObject val4 = PrefabManager.Instance.CreateClonedPrefab("Aicho_Guardian", prefab2); if ((Object)(object)val4 == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"No se pudo clonar el prefab base del tótem."); return; } PrivateArea component2 = val4.GetComponent(); if ((Object)(object)component2 != (Object)null) { Object.Destroy((Object)(object)component2); } Transform val5 = val4.transform.Find("AreaMarker"); if ((Object)(object)val5 != (Object)null) { Object.Destroy((Object)(object)((Component)val5).gameObject); } CircleProjector[] componentsInChildren = val4.GetComponentsInChildren(true); foreach (CircleProjector val6 in componentsInChildren) { Object.Destroy((Object)(object)((Component)val6).gameObject); } EnsureAdminOnlyPlacement(val4, "Aicho_Guardian"); Piece component3 = val4.GetComponent(); if ((Object)(object)component3 != (Object)null) { component3.m_name = "$piece_aicho_guardian"; component3.m_description = "$piece_aicho_guardian_desc"; } AichoGuardianBehaviour aichoGuardianBehaviour = val4.GetComponent(); if ((Object)(object)aichoGuardianBehaviour == (Object)null) { aichoGuardianBehaviour = val4.AddComponent(); } aichoGuardianBehaviour.TargetPrefabName = "AichoDverg_Wall"; val2 = new PieceConfig(); val2.PieceTable = "_HammerPieceTable"; val2.Category = "Misc"; val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[1] { new RequirementConfig { Item = "Stone", Amount = 10 } }; PieceConfig val7 = val2; PieceManager.Instance.AddPiece(new CustomPiece(val4, true, val7)); LocalizationManager.Instance.AddToken("piece_aicho_guardian", "Aicho Guardian", false); LocalizationManager.Instance.AddToken("piece_aicho_guardian_desc", "Una piedra guardiana que destruye muros Aicho cercanos al activarse.", false); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Registrado OK: Aicho_Guardian + AichoDverg_Wall (admin-only wall + admin-only guardian)."); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Error registrando Aicho Guardian/Wall: {arg}"); } } private static void EnsureAdminOnlyPlacement(GameObject go, string targetPrefabName) { AichoAdminOnlyPlacement aichoAdminOnlyPlacement = go.GetComponent(); if ((Object)(object)aichoAdminOnlyPlacement == (Object)null) { aichoAdminOnlyPlacement = go.AddComponent(); } aichoAdminOnlyPlacement.TargetPrefabName = targetPrefabName; } internal static bool IsSinglePlayerHost() { try { return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && ZNet.instance.GetConnectedPeers().Count == 0; } catch { return false; } } internal static long GetPlayerIdSafe(Player p) { try { return ((Object)(object)p != (Object)null) ? p.GetPlayerID() : 0; } catch { return 0L; } } internal static bool IsAdminLocal() { try { if ((Object)(object)ZNet.instance == (Object)null) { return false; } if (IsSinglePlayerHost()) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } long playerIdSafe = GetPlayerIdSafe(localPlayer); return playerIdSafe != 0L && ZNetExtension.IsAdmin(ZNet.instance, playerIdSafe); } catch { return false; } } internal static bool IsAdminId(long playerId) { try { if ((Object)(object)ZNet.instance == (Object)null) { return false; } if (IsSinglePlayerHost()) { return true; } return playerId != 0L && ZNetExtension.IsAdmin(ZNet.instance, playerId); } catch { return false; } } } public class AichoGuardianBehaviour : MonoBehaviour, Interactable { [CompilerGenerated] private sealed class d__10 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float seconds; public AichoGuardianBehaviour <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown int num = <>1__state; AichoGuardianBehaviour aichoGuardianBehaviour = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(seconds); <>1__state = 1; return true; case 1: <>1__state = -1; aichoGuardianBehaviour.SetActiveVisual(active: true); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public float SearchRadius = 5f; public string TargetPrefabName = "AichoDverg_Wall"; private Coroutine _resetCoroutine; private void Start() { SetActiveVisual(active: true); } public string GetHoverText() { string text = Localization.instance.Localize("$piece_aicho_guardian"); return Localization.instance.Localize(text + "\n[$KEY_Use] Romper muros Aicho cercanos"); } public string GetHoverName() { return Localization.instance.Localize("$piece_aicho_guardian"); } public bool Interact(Humanoid user, bool hold, bool alt) { if (hold) { return false; } if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { return false; } if (!IsAdminUser(user)) { return false; } float radius = ((AichoGuardianPlugin.CFG_SearchRadius != null) ? AichoGuardianPlugin.CFG_SearchRadius.Value : SearchRadius); float seconds = ((AichoGuardianPlugin.CFG_ResetSeconds != null) ? Mathf.Max(0.01f, AichoGuardianPlugin.CFG_ResetSeconds.Value) : 5f); int num = DestroyNearbyWalls(radius); Logger.LogInfo((object)$"[AichoGuardian] Muros destruidos: {num}"); SetActiveVisual(active: false); if (_resetCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_resetCoroutine); } _resetCoroutine = ((MonoBehaviour)this).StartCoroutine(ResetVisualAfterDelay(seconds)); return true; } private static bool IsAdminUser(Humanoid user) { if (AichoGuardianPlugin.IsSinglePlayerHost()) { return true; } Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)val == (Object)null) { return false; } long playerIdSafe = AichoGuardianPlugin.GetPlayerIdSafe(val); return AichoGuardianPlugin.IsAdminId(playerIdSafe); } public bool UseItem(Humanoid user, ItemData item) { return false; } private int DestroyNearbyWalls(float radius) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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) int num = 0; Vector3 position = ((Component)this).transform.position; List list = new List(); Piece.GetAllPiecesInRadius(position, radius, list); foreach (Piece item in list) { if ((Object)(object)item == (Object)null) { continue; } string prefabName = Utils.GetPrefabName(((Component)item).gameObject); if (string.Equals(prefabName, TargetPrefabName, StringComparison.Ordinal)) { WearNTear component = ((Component)item).GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component.m_nview == (Object)null) && component.m_nview.IsValid()) { component.m_nview.ClaimOwnership(); ZNetScene.instance.Destroy(((Component)component).gameObject); num++; } } } return num; } [IteratorStateMachine(typeof(d__10))] private IEnumerator ResetVisualAfterDelay(float seconds) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__10(0) { <>4__this = this, seconds = seconds }; } private void SetActiveVisual(bool active) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)MaterialMan.instance == (Object)null)) { if (active) { MaterialMan.instance.ResetValue(((Component)this).gameObject, ShaderProps._Color); MaterialMan.instance.ResetValue(((Component)this).gameObject, ShaderProps._EmissionColor); } else { MaterialMan.instance.SetValue(((Component)this).gameObject, ShaderProps._Color, Color.grey); MaterialMan.instance.SetValue(((Component)this).gameObject, ShaderProps._EmissionColor, Color.grey * 0.1f); } } } catch (Exception ex) { Logger.LogWarning((object)("[AichoGuardian] Error en SetActiveVisual: " + ex.Message)); } } } public class AichoAdminOnlyPlacement : MonoBehaviour { [CompilerGenerated] private sealed class d__2 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public AichoAdminOnlyPlacement <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__2(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown int num = <>1__state; AichoAdminOnlyPlacement aichoAdminOnlyPlacement = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return false; } <>2__current = (object)new WaitForSeconds(0.15f); <>1__state = 1; return true; case 1: <>1__state = -1; try { if (string.IsNullOrEmpty(aichoAdminOnlyPlacement.TargetPrefabName)) { return false; } string prefabName = Utils.GetPrefabName(((Component)aichoAdminOnlyPlacement).gameObject); if (!string.Equals(prefabName, aichoAdminOnlyPlacement.TargetPrefabName, StringComparison.Ordinal)) { return false; } if (AichoGuardianPlugin.IsSinglePlayerHost()) { return false; } Piece component = ((Component)aichoAdminOnlyPlacement).GetComponent(); if ((Object)(object)component == (Object)null) { return false; } long creatorIdBestEffort = GetCreatorIdBestEffort(component); Player localPlayer = Player.m_localPlayer; long num2 = (((Object)(object)localPlayer != (Object)null) ? AichoGuardianPlugin.GetPlayerIdSafe(localPlayer) : 0); if (creatorIdBestEffort != 0L && creatorIdBestEffort == num2) { return false; } if (creatorIdBestEffort != 0L && !AichoGuardianPlugin.IsAdminId(creatorIdBestEffort)) { Logger.LogWarning((object)$"[AichoGuardian] Bloqueada colocación de {prefabName} por no-admin (creator={creatorIdBestEffort})."); WearNTear component2 = ((Component)aichoAdminOnlyPlacement).GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.m_nview != (Object)null && component2.m_nview.IsValid()) { component2.m_nview.ClaimOwnership(); } if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.Destroy(((Component)aichoAdminOnlyPlacement).gameObject); } else { Object.Destroy((Object)(object)((Component)aichoAdminOnlyPlacement).gameObject); } } } catch (Exception ex) { Logger.LogWarning((object)("[AichoGuardian] Error en AichoAdminOnlyPlacement: " + ex.Message)); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public string TargetPrefabName = ""; private const float CheckDelay = 0.15f; [IteratorStateMachine(typeof(d__2))] private IEnumerator Start() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__2(0) { <>4__this = this }; } private static long GetCreatorIdBestEffort(Piece piece) { try { MethodInfo method = typeof(Piece).GetMethod("GetCreator", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null && method.ReturnType == typeof(long)) { return (long)method.Invoke(piece, null); } FieldInfo field = typeof(Piece).GetField("m_creator", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(long)) { return (long)field.GetValue(piece); } } catch { } return 0L; } } [HarmonyPatch(typeof(PieceTable), "UpdateAvailable")] public static class AichoHammerVisibilityPatches { [HarmonyPostfix] private static void PieceTable_UpdateAvailable_Postfix(PieceTable __instance, HashSet knownRecipies, Player player, bool hideUnavailable, bool noPlacementCost) { try { if ((Object)(object)__instance == (Object)null || AichoGuardianPlugin.IsAdminLocal() || __instance.m_availablePieces == null || __instance.m_availablePieces.Count == 0) { return; } for (int i = 0; i < __instance.m_availablePieces.Count; i++) { List list = __instance.m_availablePieces[i]; if (list == null || list.Count == 0) { continue; } list.RemoveAll(delegate(Piece piece) { if ((Object)(object)piece == (Object)null) { return false; } string prefabName = Utils.GetPrefabName(((Component)piece).gameObject); return string.Equals(prefabName, "AichoDverg_Wall", StringComparison.Ordinal) || string.Equals(prefabName, "Aicho_Guardian", StringComparison.Ordinal); }); } } catch { } } }