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 SealantTool v0.3.1
SealantTool.dll
Decompiled 5 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using SealantTool.Commands; using SealantTool.Config; using SealantTool.Items; using SealantTool.Locale; using SealantTool.Network; using SealantTool.Patches; using SealantTool.Protection; using SealantTool.Tool; using TMPro; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("SealantTool")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.3.1.0")] [assembly: AssemblyInformationalVersion("0.3.1+8b3992acf4e7cc444c3abadcee038e32d0fc81e7")] [assembly: AssemblyProduct("SealantTool")] [assembly: AssemblyTitle("SealantTool")] [assembly: InternalsVisibleTo("SealantTool.Tests")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.3.1.0")] [module: UnverifiableCode] [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 SealantTool { [BepInPlugin("SealantTool", "Sealant Tool", "0.3.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginId = "SealantTool"; public const string PluginName = "Sealant Tool"; public const string PluginVersion = "0.3.1"; internal static ManualLogSource Log; private Harmony _harmony; private void Awake() { Log = ((BaseUnityPlugin)this).Logger; SealantConfig.Bind(((BaseUnityPlugin)this).Config); LeakyRoofPatch.Init(); Tokens.Register(); PrefabManager.OnVanillaPrefabsAvailable += RegisterItems; CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new CheckSealCommand()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new SetSealCommand()); _harmony = Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, "SealantTool"); } private static void RegisterItems() { PrefabManager.OnVanillaPrefabsAvailable -= RegisterItems; WaterSealantItem.Register(); SealantToolItem.Register(); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class ModVersion { internal const string Value = "0.3.1"; } } namespace SealantTool.Tool { internal static class ObjMesh { internal static Mesh Load(Stream stream, string name) { //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Expected O, but got Unknown //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) List<Vector3> positions = new List<Vector3>(); List<Vector2> uvs = new List<Vector2>(); List<Vector3> normals = new List<Vector3>(); Dictionary<string, int> corners = new Dictionary<string, int>(); List<Vector3> vertices = new List<Vector3>(); List<Vector2> vertexUvs = new List<Vector2>(); List<Vector3> vertexNormals = new List<Vector3>(); List<int> list = new List<int>(); using (StreamReader streamReader = new StreamReader(stream)) { string text; while ((text = streamReader.ReadLine()) != null) { string[] array = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { continue; } switch (array[0]) { case "v": positions.Add(new Vector3(0f - F(array[1]), F(array[2]), F(array[3]))); break; case "vt": uvs.Add(new Vector2(F(array[1]), F(array[2]))); break; case "vn": normals.Add(new Vector3(0f - F(array[1]), F(array[2]), F(array[3]))); break; case "f": { for (int i = 2; i < array.Length - 1; i++) { list.Add(Corner(array[i + 1])); list.Add(Corner(array[i])); list.Add(Corner(array[1])); } break; } } } } Mesh val = new Mesh { name = name }; val.SetVertices(vertices); val.SetUVs(0, vertexUvs); val.SetNormals(vertexNormals); val.SetTriangles(list, 0); val.RecalculateBounds(); val.RecalculateTangents(); return val; int Corner(string corner) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (corners.TryGetValue(corner, out var value)) { return value; } string[] array2 = corner.Split(new char[1] { '/' }); vertices.Add(positions[int.Parse(array2[0]) - 1]); vertexUvs.Add(uvs[int.Parse(array2[1]) - 1]); vertexNormals.Add(normals[int.Parse(array2[2]) - 1]); return corners[corner] = vertices.Count - 1; } } private static float F(string value) { return float.Parse(value, CultureInfo.InvariantCulture); } } [HarmonyPatch(typeof(Player), "TryPlacePiece")] internal static class SealAction { private static bool Prefix(Player __instance, Piece piece, ref bool __result) { if (!Object.op_Implicit((Object)(object)piece)) { return true; } string prefabName = Utils.GetPrefabName(((Component)piece).gameObject); if (prefabName == "SealantTool_Strip") { Strip(__instance); } else { if (!SealantToolItem.SealEntries.TryGetValue(prefabName, out var value)) { return true; } Seal(__instance, piece, value); } __result = false; return false; } private static void Seal(Player player, Piece entry, ProtectionFlag flag) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (!Target(player, out var target, out var wear)) { return; } SealRefusal sealRefusal = ((!Object.op_Implicit((Object)(object)wear)) ? SealRefusal.NotNeeded : Eligibility.CheckSeal(wear.m_nview.GetZDO(), flag)); if (sealRefusal != SealRefusal.None) { Say(player, RefusalMessage(sealRefusal), target); return; } if (!player.NoCostCheat() && !ZoneSystem.instance.GetGlobalKey(entry.FreeBuildKey())) { player.ConsumeResources(entry.m_resources, 0, -1, 1); } ProtectionRpc.RequestSeal(wear, flag); UseTool(player, target); Say(player, "sealanttool_msg_watersealed", target); } private static void Strip(Player player) { if (Target(player, out var target, out var wear)) { if (!Object.op_Implicit((Object)(object)wear) || !ProtectionStore.SealantOf(wear.m_nview.GetZDO()).HasValue) { Say(player, "sealanttool_msg_nothingtostrip", target); return; } ProtectionRpc.RequestStrip(wear); UseTool(player, target); Say(player, "sealanttool_msg_stripped", target); } } private static bool Target(Player player, out Piece target, out WearNTear wear) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) target = player.m_hoveringPiece; wear = null; if (!Object.op_Implicit((Object)(object)target) || !player.CheckCanRemovePiece(target) || !PrivateArea.CheckAccess(((Component)target).transform.position, 0f, true, false)) { return false; } wear = ((Component)target).GetComponent<WearNTear>(); if (Object.op_Implicit((Object)(object)wear) && !wear.m_nview.IsValid()) { wear = null; } return true; } private static void UseTool(Player player, Piece target) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) ItemData rightItem = ((Humanoid)player).GetRightItem(); player.FaceLookDirection(); ((Character)player).m_zanim.SetTrigger(rightItem.m_shared.m_attack.m_attackAnimation); target.m_placeEffect.Create(((Component)target).transform.position, ((Component)target).transform.rotation, (Transform)null, 1f, -1, ((Character)player).GetZDOID()); ((Character)player).UseStamina(player.GetBuildStamina()); ((Character)player).UseEitr(rightItem.m_shared.m_attack.m_attackEitr); if (rightItem.m_shared.m_useDurability) { rightItem.m_durability -= rightItem.m_shared.m_useDurabilityDrain * Game.m_durabilityRate; } } private static void Say(Player player, string token, Piece target) { ((Character)player).Message((MessageType)1, Localization.instance.Localize("$" + token, new string[1] { target.m_name }), 0, (Sprite)null, false); } private static string RefusalMessage(SealRefusal refusal) { return refusal switch { SealRefusal.NotPlayerBuilt => "sealanttool_msg_notplayerbuilt", SealRefusal.AlreadySealed => "sealanttool_msg_alreadysealed", _ => "sealanttool_msg_waternotneeded", }; } } internal static class SealantToolItem { internal const string PieceTableName = "_SealerPieceTable"; internal const string StripPieceName = "SealantTool_Strip"; private const string WaterSealPieceName = "SealantTool_WaterSeal"; internal static readonly Dictionary<string, ProtectionFlag> SealEntries = new Dictionary<string, ProtectionFlag> { { "SealantTool_WaterSeal", ProtectionFlag.Wet } }; internal static bool IsActive(Player player) { if (Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)player.m_buildPieces)) { return ((Object)player.m_buildPieces).name == "_SealerPieceTable"; } return false; } internal static void Register() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Expected O, but got Unknown //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Expected O, but got Unknown CustomPieceTable val = new CustomPieceTable("_SealerPieceTable", new PieceTableConfig { CanRemovePieces = false }); val.PieceTable.m_hideAdvancedMenu = true; PieceManager.Instance.AddPieceTable(val); ItemConfig val2 = new ItemConfig(); val2.Name = "$sealanttool_sealer"; val2.Description = "$sealanttool_sealer_desc"; val2.CraftingStation = CraftingStations.Forge; val2.MinStationLevel = 2; val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[2] { new RequirementConfig("Wood", 2, 0, true), new RequirementConfig("Iron", 1, 0, true) }; CustomItem val3 = new CustomItem("Sealer", "Hammer", val2); val3.ItemDrop.m_itemData.m_shared.m_buildPieces = val.PieceTable; ItemManager.Instance.AddItem(val3); ItemAssets.SetMesh(val3.ItemPrefab, "sealer.obj"); ItemAssets.SetIcon(val3, "Sealer.png"); GameObject repairEntry = PrefabManager.Instance.GetPrefab("Hammer").GetComponent<ItemDrop>().m_itemData.m_shared.m_buildPieces.m_pieces.First((GameObject p) => Object.op_Implicit((Object)(object)p) && Object.op_Implicit((Object)(object)p.GetComponent<Piece>()) && p.GetComponent<Piece>().m_repairPiece); PieceConfig val4 = new PieceConfig(); val4.Name = "$sealanttool_waterseal"; val4.Description = "$sealanttool_waterseal_desc"; val4.Icon = WaterSealantItem.Icon; val4.Requirements = (RequirementConfig[])(object)new RequirementConfig[1] { new RequirementConfig("WaterSealant", 1, 0, true) }; AddEntry(repairEntry, "SealantTool_WaterSeal", val4); AddEntry(repairEntry, "SealantTool_Strip", new PieceConfig { Name = "$sealanttool_strip", Description = "$sealanttool_strip_desc" }); } private static void AddEntry(GameObject repairEntry, string name, PieceConfig config) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown config.PieceTable = "_SealerPieceTable"; CustomPiece val = new CustomPiece(PrefabManager.Instance.CreateClonedPrefab(name, repairEntry), false, config); val.Piece.m_repairPiece = false; PieceManager.Instance.AddPiece(val); } } [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] internal static class SealerPlacementMarkerPatch { private static void Postfix(Player __instance) { if (SealantToolItem.IsActive(__instance) && Object.op_Implicit((Object)(object)__instance.m_placementMarkerInstance)) { __instance.m_placementMarkerInstance.SetActive(false); } } } [HarmonyPatch(typeof(Player), "GetHoveringPiece")] internal static class SealerHoveringPiecePatch { private static bool Prefix(Player __instance, ref Piece __result) { if (!SealantToolItem.IsActive(__instance)) { return true; } __result = null; return false; } } [HarmonyPatch(typeof(KeyHints), "UpdateHints")] internal static class SealerKeyHintsPatch { private static TMP_Text[] s_placeLabels; private static List<GameObject> s_otherEntries; private static readonly HashSet<GameObject> s_hidden = new HashSet<GameObject>(); private static bool s_applied; private static void Postfix(KeyHints __instance) { if (!Object.op_Implicit((Object)(object)__instance.m_buildHints)) { return; } if (__instance.m_buildHints.activeSelf && SealantToolItem.IsActive(Player.m_localPlayer)) { if (s_placeLabels == null) { Discover(__instance); } SetPlaceLabel(Localization.instance.Localize("$" + ActionToken(Player.m_localPlayer.GetSelectedPiece()))); foreach (GameObject s_otherEntry in s_otherEntries) { if (Object.op_Implicit((Object)(object)s_otherEntry) && s_otherEntry.activeSelf) { s_hidden.Add(s_otherEntry); s_otherEntry.SetActive(false); } } s_applied = true; } else { if (!s_applied) { return; } SetPlaceLabel(Localization.instance.Localize("$hud_place")); foreach (GameObject item in s_hidden) { if (Object.op_Implicit((Object)(object)item)) { item.SetActive(true); } } s_hidden.Clear(); s_applied = false; } } private static string ActionToken(Piece selected) { if (!Object.op_Implicit((Object)(object)selected) || !(Utils.GetPrefabName(((Component)selected).gameObject) == "SealantTool_Strip")) { return "sealanttool_hint_seal"; } return "sealanttool_strip"; } private static void SetPlaceLabel(string label) { TMP_Text[] array = s_placeLabels; foreach (TMP_Text val in array) { if (Object.op_Implicit((Object)(object)val) && val.text != label) { val.text = label; } } } private static void Discover(KeyHints hints) { TMP_Text[] componentsInChildren = hints.m_buildHints.GetComponentsInChildren<TMP_Text>(true); s_placeLabels = componentsInChildren.Where((TMP_Text t) => Is(t, "$hud_place")).ToArray(); TMP_Text[] kept = s_placeLabels.Concat(componentsInChildren.Where((TMP_Text t) => Is(t, "$hud_buildmenu"))).ToArray(); Transform[] menuHints = (from g in ((IEnumerable<GameObject>)(((object)hints.m_buildMenuHintsKB) ?? ((object)new GameObject[0]))).Concat((IEnumerable<GameObject>)(((object)hints.m_buildMenuHintsGP) ?? ((object)new GameObject[0]))) where Object.op_Implicit((Object)(object)g) select g.transform).ToArray(); s_otherEntries = (from e in (from t in s_placeLabels select (!Object.op_Implicit((Object)(object)t.transform.parent)) ? null : t.transform.parent.parent into row where Object.op_Implicit((Object)(object)row) select row).Distinct().SelectMany((Transform row) => ((IEnumerable)row).Cast<Transform>()) where !menuHints.Any((Transform m) => e.IsChildOf(m)) && !kept.Any((TMP_Text k) => k.transform.IsChildOf(e)) select ((Component)e).gameObject).ToList(); if (s_placeLabels.Length == 0) { Plugin.Log.LogWarning((object)"Key hints: no Place hint found; the Sealer keeps the hammer's hints."); } static bool Is(TMP_Text t, string token) { if (!(t.text == token)) { return t.text == Localization.instance.Localize(token); } return true; } } } [HarmonyPatch(typeof(WearNTear), "Highlight")] internal static class SealHighlight { private static void Postfix(WearNTear __instance) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!SealantToolItem.IsActive(localPlayer) || !__instance.m_nview.IsValid()) { return; } ZDO zDO = __instance.m_nview.GetZDO(); Color? val = null; if (ProtectionStore.SealantOf(zDO).HasValue) { val = SealantConfig.WaterSealColor.Value; } else { Piece selectedPiece = localPlayer.GetSelectedPiece(); if (Object.op_Implicit((Object)(object)selectedPiece) && SealantToolItem.SealEntries.TryGetValue(Utils.GetPrefabName(((Component)selectedPiece).gameObject), out var value) && Eligibility.CheckSeal(zDO, value) == SealRefusal.None) { val = SealantConfig.UnsealedColor.Value; } } GameObject gameObject = ((Component)__instance).gameObject; if (val.HasValue) { Color valueOrDefault = val.GetValueOrDefault(); MaterialMan.instance.SetValue<Color>(gameObject, ShaderProps._EmissionColor, valueOrDefault * 0.4f, false); MaterialMan.instance.SetValue<Color>(gameObject, ShaderProps._Color, valueOrDefault, false); } else { MaterialMan.instance.ResetValue(gameObject, ShaderProps._Color); MaterialMan.instance.ResetValue(gameObject, ShaderProps._EmissionColor); } } } } namespace SealantTool.Protection { public enum SealRefusal { None, NotNeeded, NotPlayerBuilt, AlreadySealed } public static class Eligibility { private static HashSet<int> s_hammerPieces; public static SealRefusal CheckSeal(ZDO zdo, ProtectionFlag flag) { GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab(zdo.GetPrefab()) : null); WearNTear val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<WearNTear>() : null); if (!Object.op_Implicit((Object)(object)val2) || !Applies(val2, flag)) { return SealRefusal.NotNeeded; } if (!IsHammerPiece(zdo.GetPrefab())) { return SealRefusal.NotNeeded; } if (zdo.GetLong(ZDOVars.s_creator, 0L) == 0L) { return SealRefusal.NotPlayerBuilt; } if (ProtectionStore.SealantOf(zdo).HasValue) { return SealRefusal.AlreadySealed; } return SealRefusal.None; } private static bool Applies(WearNTear wear, ProtectionFlag flag) { if (flag == ProtectionFlag.Wet) { return wear.m_noRoofWear; } return false; } private static bool IsHammerPiece(int prefabHash) { return HammerPieces().Contains(prefabHash); } private static HashSet<int> HammerPieces() { if (s_hammerPieces != null) { return s_hammerPieces; } ObjectDB instance = ObjectDB.instance; object obj; if (instance == null) { obj = null; } else { GameObject itemPrefab = instance.GetItemPrefab("Hammer"); obj = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces); } PieceTable val = (PieceTable)obj; if (!Object.op_Implicit((Object)(object)val)) { return new HashSet<int>(); } s_hammerPieces = new HashSet<int>(); foreach (GameObject piece in val.m_pieces) { if (Object.op_Implicit((Object)(object)piece)) { s_hammerPieces.Add(StringExtensionMethods.GetStableHashCode(((Object)piece).name)); } } return s_hammerPieces; } } public enum ProtectionFlag { Wet } public static class ProtectionStore { private static readonly int[] s_keys = new int[Enum.GetValues(typeof(ProtectionFlag)).Length]; private static readonly bool[] s_hashed = new bool[s_keys.Length]; public static string KeyName(ProtectionFlag flag) { return $"SealantTool.{flag}Sealed"; } public static int Key(ProtectionFlag flag) { if (!s_hashed[(int)flag]) { s_keys[(int)flag] = StringExtensionMethods.GetStableHashCode(KeyName(flag)); s_hashed[(int)flag] = true; } return s_keys[(int)flag]; } public static bool Has(WearNTear piece, ProtectionFlag flag) { if (Object.op_Implicit((Object)(object)piece) && Object.op_Implicit((Object)(object)piece.m_nview) && piece.m_nview.IsValid()) { return piece.m_nview.GetZDO().GetBool(Key(flag), false); } return false; } public static ProtectionFlag? SealantOf(ZDO zdo) { for (int i = 0; i < s_keys.Length; i++) { if (zdo.GetBool(Key((ProtectionFlag)i), false)) { return (ProtectionFlag)i; } } return null; } } } namespace SealantTool.Patches { [HarmonyPatch] internal static class LeakyRoofPatch { private static readonly HashSet<int> RoofPrefabs = new HashSet<int>(); private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(WearNTear), "RoofCheck", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Cover), "IsUnderRoof", (Type[])null, (Type[])null); } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original) { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(GameObject), "CompareTag", new Type[1] { typeof(string) }, (Type[])null); List<CodeInstruction> list = new List<CodeInstruction>(instructions); int index = -1; int num = 0; for (int i = 1; i < list.Count; i++) { if (list[i - 1].opcode == OpCodes.Ldstr && (string)list[i - 1].operand == "leaky" && CodeInstructionExtensions.Calls(list[i], methodInfo)) { index = i; num++; } } if (num != 1) { Plugin.Log.LogError((object)$"{original.DeclaringType?.Name}.{original.Name}: expected 1 leaky check, found {num}; sealed pieces won't act as roofs there."); return list; } list[index] = CodeInstructionExtensions.MoveLabelsFrom(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(LeakyRoofPatch), "IsLeaky", (Type[])null, (Type[])null)), list[index]); return list; } internal static bool IsLeaky(GameObject hit, string tag) { if (!hit.CompareTag(tag)) { return false; } WearNTear componentInParent = hit.GetComponentInParent<WearNTear>(); if (ProtectionStore.Has(componentInParent, ProtectionFlag.Wet)) { return !RoofPrefabs.Contains(componentInParent.m_nview.GetZDO().GetPrefab()); } return true; } internal static void Init() { RebuildRoofPrefabs(); SealantConfig.WaterSealRoofPieces.SettingChanged += delegate { RebuildRoofPrefabs(); }; } internal static void RebuildRoofPrefabs() { RoofPrefabs.Clear(); string[] array = SealantConfig.ParseList(SealantConfig.WaterSealRoofPieces.Value); foreach (string text in array) { RoofPrefabs.Add(StringExtensionMethods.GetStableHashCode(text)); if (Object.op_Implicit((Object)(object)ZNetScene.instance) && !Object.op_Implicit((Object)(object)ZNetScene.instance.GetPrefab(text))) { Plugin.Log.LogWarning((object)("RoofPieces: no prefab named '" + text + "'; it will never act as a roof.")); } } } } [HarmonyPatch(typeof(WearNTear), "HaveRoof")] internal static class HaveRoofPatch { private static void Prefix(WearNTear __instance) { if (Object.op_Implicit((Object)(object)__instance.m_roof) && LeakyRoofPatch.IsLeaky(__instance.m_roof, "leaky")) { __instance.m_roof = null; } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class RoofListValidationPatch { private static void Postfix() { LeakyRoofPatch.RebuildRoofPrefabs(); } } [HarmonyPatch(typeof(WearNTear), "UpdateWear")] internal static class WetWearPatch { private static void Prefix(WearNTear __instance, float time) { if (__instance.m_rainTimer != 0f && ProtectionStore.Has(__instance, ProtectionFlag.Wet)) { __instance.m_rainTimer = time; } } } } namespace SealantTool.Network { [HarmonyPatch] internal static class ProtectionRpc { private const string RequestRpc = "SealantTool_Request"; private const string SetRpc = "SealantTool_Set"; private const int StripFlag = -1; [HarmonyPatch(typeof(Game), "Start")] [HarmonyPostfix] private static void RegisterRequest() { ZRoutedRpc.instance.Register<ZDOID, int>("SealantTool_Request", (Action<long, ZDOID, int>)OnRequest); } [HarmonyPatch(typeof(WearNTear), "Awake")] [HarmonyPostfix] private static void RegisterSet(WearNTear __instance) { if (Object.op_Implicit((Object)(object)__instance.m_nview) && __instance.m_nview.GetZDO() != null) { __instance.m_nview.Register<int>("SealantTool_Set", (Action<long, int>)delegate(long sender, int flag) { OnSet(__instance, sender, flag); }); } } internal static void RequestSeal(WearNTear piece, ProtectionFlag flag) { Send(piece, (int)flag); } internal static void RequestStrip(WearNTear piece) { Send(piece, -1); } private static void Send(WearNTear piece, int flag) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "SealantTool_Request", new object[2] { piece.m_nview.GetZDO().m_uid, flag }); } private static void OnRequest(long sender, ZDOID target, int flag) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { return; } ZDO zDO = ZDOMan.instance.GetZDO(target); if (zDO == null || zDO.GetOwner() == 0L) { return; } if (flag == -1) { if (!ProtectionStore.SealantOf(zDO).HasValue) { return; } } else { SealRefusal sealRefusal = ((!Enum.IsDefined(typeof(ProtectionFlag), flag)) ? SealRefusal.NotNeeded : Eligibility.CheckSeal(zDO, (ProtectionFlag)flag)); if (sealRefusal != SealRefusal.None) { Plugin.Log.LogWarning((object)$"Seal request from {sender} (sealant {flag}) refused by the server: {sealRefusal}."); return; } } ZRoutedRpc.instance.InvokeRoutedRPC(zDO.GetOwner(), target, "SealantTool_Set", new object[1] { flag }); } private static void OnSet(WearNTear piece, long sender, int flag) { ZNetView nview = piece.m_nview; if (sender != ZRoutedRpc.instance.GetServerPeerID() || !nview.IsValid() || !nview.IsOwner()) { return; } ZDO zDO = nview.GetZDO(); if (flag == -1) { foreach (ProtectionFlag value in Enum.GetValues(typeof(ProtectionFlag))) { zDO.Set(ProtectionStore.Key(value), false); } return; } if (Enum.IsDefined(typeof(ProtectionFlag), flag)) { zDO.Set(ProtectionStore.Key((ProtectionFlag)flag), true); } } } } namespace SealantTool.Locale { internal static class Tokens { internal const string ToolName = "sealanttool_sealer"; internal const string ToolDescription = "sealanttool_sealer_desc"; internal const string WaterSealantName = "sealanttool_watersealant"; internal const string WaterSealantDescription = "sealanttool_watersealant_desc"; internal const string WaterSealantBaseName = "sealanttool_watersealantbase"; internal const string WaterSealantBaseDescription = "sealanttool_watersealantbase_desc"; internal const string WaterSealPiece = "sealanttool_waterseal"; internal const string WaterSealDescription = "sealanttool_waterseal_desc"; internal const string StripPiece = "sealanttool_strip"; internal const string StripDescription = "sealanttool_strip_desc"; internal const string HintSeal = "sealanttool_hint_seal"; internal const string MsgWaterSealed = "sealanttool_msg_watersealed"; internal const string MsgStripped = "sealanttool_msg_stripped"; internal const string MsgWaterNotNeeded = "sealanttool_msg_waternotneeded"; internal const string MsgAlreadySealed = "sealanttool_msg_alreadysealed"; internal const string MsgNothingToStrip = "sealanttool_msg_nothingtostrip"; internal const string MsgNotPlayerBuilt = "sealanttool_msg_notplayerbuilt"; internal static Dictionary<string, string> English() { return new Dictionary<string, string> { { "sealanttool_sealer", "Sealer" }, { "sealanttool_sealer_desc", "Applies sealant to building pieces, one piece at a time." }, { "sealanttool_watersealant", "Water Sealant" }, { "sealanttool_watersealant_desc", "Keeps the rain from wearing down whatever it's applied to." }, { "sealanttool_watersealantbase", "Water Sealant Base" }, { "sealanttool_watersealantbase_desc", "Keeps the rain from wearing down whatever it's applied to." }, { "sealanttool_waterseal", "Water Seal" }, { "sealanttool_waterseal_desc", "Can be applied to prevent water damage and seal roofs" }, { "sealanttool_strip", "Strip" }, { "sealanttool_strip_desc", "Removes a piece's sealant" }, { "sealanttool_hint_seal", "Seal" }, { "sealanttool_msg_watersealed", "$1 water sealed" }, { "sealanttool_msg_stripped", "$1 stripped" }, { "sealanttool_msg_waternotneeded", "$1 doesn't need water sealing" }, { "sealanttool_msg_alreadysealed", "$1 is already sealed" }, { "sealanttool_msg_nothingtostrip", "$1 has no sealant" }, { "sealanttool_msg_notplayerbuilt", "$1 wasn't built by a player" } }; } internal static void Register() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, English()); } } } namespace SealantTool.Items { internal static class ItemAssets { internal static Material OwnMaterial(GameObject prefab) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_0019: Expected O, but got Unknown MeshRenderer componentInChildren = prefab.GetComponentInChildren<MeshRenderer>(true); Material val = new Material(((Renderer)componentInChildren).sharedMaterial); Material result = val; ((Renderer)componentInChildren).sharedMaterial = val; return result; } internal static void SetMesh(GameObject prefab, string resource) { using Stream stream = Open(resource); prefab.GetComponentInChildren<MeshFilter>(true).sharedMesh = ObjMesh.Load(stream, Path.GetFileNameWithoutExtension(resource)); } internal static void SetIcon(CustomItem item, string resource) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) Texture2D val = LoadTexture(resource); item.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)) }; } internal static Texture2D LoadTexture(string resource) { using Stream stream = Open(resource); using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return AssetUtils.LoadImage(memoryStream.ToArray()); } private static Stream Open(string resource) { return typeof(ItemAssets).Assembly.GetManifestResourceStream(resource); } } internal static class WaterSealantItem { internal const string PrefabName = "WaterSealant"; private const string BasePrefabName = "WaterSealantBase"; private const int FermentYield = 6; private static readonly Color SealantColor = new Color(0.23f, 0.23f, 0.23f); private static CustomItem s_sealant; private static CustomItem s_base; internal static Sprite Icon { get { CustomItem obj = s_sealant; if (obj == null) { return null; } return obj.ItemDrop.m_itemData.m_shared.m_icons[0]; } } internal static void Register() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown s_sealant = new CustomItem("WaterSealant", "YmirRemains", new ItemConfig { Name = "$sealanttool_watersealant", Description = "$sealanttool_watersealant_desc" }); ItemManager.Instance.AddItem(s_sealant); ItemAssets.OwnMaterial(s_sealant.ItemPrefab).color = SealantColor; ItemAssets.SetIcon(s_sealant, "WaterSealant.png"); ItemConfig val = new ItemConfig(); val.Name = "$sealanttool_watersealantbase"; val.Description = "$sealanttool_watersealantbase_desc"; val.CraftingStation = CraftingStations.MeadKetill; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2] { new RequirementConfig("Resin", 4, 0, true), new RequirementConfig("Guck", 2, 0, true) }; s_base = new CustomItem("WaterSealantBase", "MeadBaseStrength", val); s_base.ItemDrop.m_itemData.m_shared.m_consumeStatusEffect = null; ItemManager.Instance.AddItem(s_base); ItemAssets.OwnMaterial(s_base.ItemPrefab).mainTexture = (Texture)(object)ItemAssets.LoadTexture("WaterSealantBase_d.png"); ItemAssets.SetIcon(s_base, "WaterSealantBase.png"); ItemManager.Instance.AddItemConversion(new CustomItemConversion((ConversionConfig)new FermenterConversionConfig { Station = Fermenters.Fermenter, FromItem = "WaterSealantBase", ToItem = "WaterSealant", ProducedItems = 6 })); } } } namespace SealantTool.Config { internal static class SealantConfig { internal static ConfigEntry<string> WaterSealRoofPieces; internal static ConfigEntry<Color> WaterSealColor; internal static ConfigEntry<Color> UnsealedColor; internal const string DefaultWaterSealRoofPieces = "wood_floor,wood_floor_1x1,ashwood_floor_2x2,ashwood_floor_1x1,ashwood_deco_floor,wood_stair,ashwood_stair,piece_dvergr_spiralstair,piece_dvergr_spiralstair_right,wood_stepladder,wood_wall_log,wood_wall_log_4x0.5,wood_pole_log,wood_pole_log_4"; internal static void Bind(ConfigFile config) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { IsAdminOnly = true }; WaterSealRoofPieces = config.Bind<string>("Water Seal", "RoofPieces", "wood_floor,wood_floor_1x1,ashwood_floor_2x2,ashwood_floor_1x1,ashwood_deco_floor,wood_stair,ashwood_stair,piece_dvergr_spiralstair,piece_dvergr_spiralstair_right,wood_stepladder,wood_wall_log,wood_wall_log_4x0.5,wood_pole_log,wood_pole_log_4", new ConfigDescription("Prefab names that act as roofs when water sealed, comma-separated. Pieces not listed never do.", (AcceptableValueBase)null, new object[1] { val })); WaterSealColor = config.Bind<Color>("Highlight", "WaterSealColor", new Color(0f, 1f, 1f), "Sealer highlight for water sealed pieces."); UnsealedColor = config.Bind<Color>("Highlight", "UnsealedColor", new Color(0.5f, 0.5f, 0.5f), "Sealer highlight for pieces that can be sealed but aren't."); } internal static string[] ParseList(string list) { List<string> list2 = new List<string>(); string[] array = (list ?? "").Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (text.Length > 0) { list2.Add(text); } } return list2.ToArray(); } } } namespace SealantTool.Commands { internal sealed class CheckSealCommand : ConsoleCommand { public override string Name => "checkseal"; public override string Help => "reports the sealant state of the piece you're looking at"; public override bool IsCheat => true; public override void Run(string[] args) { WearNTear val = DebugCommands.LookedAtPiece(); DebugCommands.Print(Object.op_Implicit((Object)(object)val) ? Report(val) : "checkseal: look at a building piece"); } internal static string Report(WearNTear piece) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) ZDO zdo = piece.m_nview.GetZDO(); ProtectionFlag? held = ProtectionStore.SealantOf(zdo); string text = ((!held.HasValue) ? "none" : DebugCommands.Sealants.First((KeyValuePair<string, ProtectionFlag> s) => s.Value == held.Value).Key); string text2 = string.Join(" ", DebugCommands.Sealants.Select((KeyValuePair<string, ProtectionFlag> s) => $"canSeal({s.Key})={Eligibility.CheckSeal(zdo, s.Value)}")); Transform transform = ((Component)piece).transform; GameObject val = default(GameObject); string text3 = (WearNTear.RoofCheck(transform, transform.position, ref val, piece.m_roofCheckOffset) ? Utils.GetPrefabName(((Component)val.transform.root).gameObject) : "none"); string text4 = ((piece.m_rainTimer == 0f) ? "idle" : (held.HasValue ? "held" : $"{Mathf.Max(0f, 60f - (Time.time - piece.m_rainTimer)):0}s")); return "checkseal: " + Utils.GetPrefabName(((Component)piece).gameObject) + " sealant=" + text + $" health={piece.GetHealthPercentage() * 100f:0}% wet={piece.IsWet()} roof={text3} wear={text4} {text2}"; } } internal static class DebugCommands { internal static readonly Dictionary<string, ProtectionFlag> Sealants = new Dictionary<string, ProtectionFlag> { { "water", ProtectionFlag.Wet } }; internal static WearNTear LookedAtPiece() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)GameCamera.instance)) { return null; } Transform transform = ((Component)GameCamera.instance).transform; RaycastHit val = default(RaycastHit); if (!Physics.Raycast(transform.position, transform.forward, ref val, 50f, localPlayer.m_removeRayMask)) { return null; } WearNTear componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<WearNTear>(); if (!Object.op_Implicit((Object)(object)componentInParent) || !componentInParent.m_nview.IsValid()) { return null; } return componentInParent; } internal static void Print(string line) { Console instance = Console.instance; if (instance != null) { instance.Print(line); } Plugin.Log.LogInfo((object)line); } } internal sealed class SetSealCommand : ConsoleCommand { public override string Name => "setseal"; public override string Help => "<water> <on|off> sets or clears a sealant on the piece you're looking at"; public override bool IsCheat => true; public override List<string> CommandOptionList() { return DebugCommands.Sealants.Keys.ToList(); } public override void Run(string[] args) { if (args.Length != 2 || !DebugCommands.Sealants.TryGetValue(args[0].ToLowerInvariant(), out var value) || (args[1] != "on" && args[1] != "off")) { DebugCommands.Print("setseal: use <sealant> on|off (sealants: " + string.Join(", ", DebugCommands.Sealants.Keys) + ")"); return; } WearNTear val = DebugCommands.LookedAtPiece(); if (!Object.op_Implicit((Object)(object)val)) { DebugCommands.Print("setseal: look at a building piece"); return; } if (!val.m_nview.IsOwner()) { val.m_nview.ClaimOwnership(); } val.m_nview.GetZDO().Set(ProtectionStore.Key(value), args[1] == "on"); DebugCommands.Print(CheckSealCommand.Report(val)); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }