using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; 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.Logging; using HarmonyLib; using Jotunn.Managers; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("FloorsAreRoofsPlugin")] [assembly: AssemblyDescription("A tiny mod that makes Valheim floors count as a roof so you can build a flat-roofed house")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("FloorsAreRoofsPlugin")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("f31344ca-e6be-44c2-8f7b-41fd6ac15b76")] [assembly: AssemblyFileVersion("2.0.2")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.2.0")] [module: UnverifiableCode] namespace FloorsAreRoofs; [BepInPlugin("bonesbro.val.floorsareroofs", "Floors Are Roofs", "2.0.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class FloorsAreRoofsPlugin : BaseUnityPlugin { private const string PluginId = "bonesbro.val.floorsareroofs"; public const string Version = "2.0.2"; public const string ModName = "Floors Are Roofs"; private const string DefaultPrefabsConfigSetting = "wood_floor,wood_floor_1x1,piece_ashwood_floor_1x1,piece_ashwood_floor_2x2,piece_ashwood_floor_half,piece_grausten_floor_1x1,piece_grausten_floor_2x2,piece_flametal_floor_1x1,piece_flametal_floor_2x2"; private const string DefaultHammersConfigSetting = "Hammer"; private const bool DefaultRainDamageConfigSetting = true; protected static bool PatchingHasAlreadySucceeded = false; internal static bool RemoveRainDamage = true; internal static string PrefabListInConfigSettings = ""; internal static string HammersListInConfigSettings = ""; internal static string[] PrefabList = new string[0]; internal static string[] HammerList = new string[0]; private Harmony _Harmony; public static ManualLogSource Log; private void Awake() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown Log = new ManualLogSource((string)null); _Harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null); ((BaseUnityPlugin)this).Config.Bind("General", "NexusID", 1039, "Nexus mod ID for updates"); PrefabListInConfigSettings = ((BaseUnityPlugin)this).Config.Bind("General", "PrefabsToChange", "wood_floor,wood_floor_1x1,piece_ashwood_floor_1x1,piece_ashwood_floor_2x2,piece_ashwood_floor_half,piece_grausten_floor_1x1,piece_grausten_floor_2x2,piece_flametal_floor_1x1,piece_flametal_floor_2x2", "List of the prefab pieces to weatherproof. Comma-separate each prefab name. Default: wood_floor,wood_floor_1x1,piece_ashwood_floor_1x1,piece_ashwood_floor_2x2,piece_ashwood_floor_half,piece_grausten_floor_1x1,piece_grausten_floor_2x2,piece_flametal_floor_1x1,piece_flametal_floor_2x2").Value; HammersListInConfigSettings = ((BaseUnityPlugin)this).Config.Bind("General", "Hammers", "Hammer", "List of hammer tools whose recipes we'll search to find the pieces to update. These are the prefab names for each hammer piece. Comma-separate each prefab name. Default: Hammer").Value; RemoveRainDamage = ((BaseUnityPlugin)this).Config.Bind("General", "RemoveRainDamage", true, "Prevent the floor pieces from taking wear and tear damage from rain.").Value; Debug.Log((object)string.Format("[floorsareroofs]: Initializing using config settings: PrefabsToChange:[{0}], Hammers:[{1}], RemoveRainDamage:[{2}]", PrefabListInConfigSettings ?? "null", HammersListInConfigSettings ?? "null", RemoveRainDamage)); if (string.IsNullOrWhiteSpace(PrefabListInConfigSettings)) { PrefabListInConfigSettings = "wood_floor,wood_floor_1x1,piece_ashwood_floor_1x1,piece_ashwood_floor_2x2,piece_ashwood_floor_half,piece_grausten_floor_1x1,piece_grausten_floor_2x2,piece_flametal_floor_1x1,piece_flametal_floor_2x2"; } if (string.IsNullOrWhiteSpace(HammersListInConfigSettings)) { HammersListInConfigSettings = "Hammer"; } string text = PrefabListInConfigSettings.Replace(" ", ""); string text2 = HammersListInConfigSettings.Replace(" ", ""); char[] separator = new char[1] { ',' }; PrefabList = text.Split(separator, StringSplitOptions.RemoveEmptyEntries); HammerList = text2.Split(separator, StringSplitOptions.RemoveEmptyEntries); PieceManager.OnPiecesRegistered += PieceManager_OnPiecesRegistered; } private void PieceManager_OnPiecesRegistered() { Debug.Log((object)"[floorsareroofs]: Triggered from PieceManager_OnPiecesRegistered"); LogAshwoodPrefabs(); PatchFloor(); } private static void LogAshwoodPrefabs() { Debug.Log((object)"[floorsareroofs]: Searching for ashwood/floor prefabs..."); if ((Object)(object)ObjectDB.instance == (Object)null) { Debug.LogError((object)"[floorsareroofs]: ObjectDB is null in LogAshwoodPrefabs"); return; } foreach (GameObject item in ObjectDB.instance.m_items) { if ((Object)(object)item == (Object)null) { continue; } string text = ((Object)item).name ?? ""; if (text.IndexOf("ash", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("floor", StringComparison.OrdinalIgnoreCase) >= 0) { Debug.Log((object)("[floorsareroofs] Prefab: " + text)); Transform transform = item.transform; for (int i = 0; i < transform.childCount; i++) { Transform child = transform.GetChild(i); Debug.Log((object)("[floorsareroofs] child: " + ((Object)child).name + " tag: " + ((Component)child).tag)); } WearNTear component = item.GetComponent(); Debug.Log((object)$"[floorsareroofs] Has WearNTear: {(Object)(object)component != (Object)null}"); } } } private void OnDestroy() { Harmony harmony = _Harmony; if (harmony != null) { harmony.UnpatchAll("bonesbro.val.floorsareroofs"); } } internal static void PatchFloor() { Debug.Log((object)"[floorsareroofs]: Beginning patch attempt"); if (PrefabList.Length == 0) { Debug.LogError((object)"[floorsareroofs]: Error: No prefabs defined in config setting PrefabsToChange."); return; } if (HammerList.Length == 0) { Debug.LogError((object)"[floorsareroofs]: Error: No prefabs defined in config setting Hammers."); return; } if ((Object)(object)ObjectDB.instance == (Object)null) { Debug.LogError((object)"[floorsareroofs]: ObjectDB is null"); return; } int num = 0; bool flag = true; string[] hammerList = HammerList; foreach (string hammerName in hammerList) { int cFloorsUpdated = 0; flag &= UpdatePiecesInHammer(hammerName, out cFloorsUpdated); num += cFloorsUpdated; } Debug.Log((object)$"[floorsareroofs]: Successfully updated {num} floors. Config setting has {PrefabList.Length} floors specified."); if (flag) { if (num == PrefabList.Length) { Debug.Log((object)"[floorsareroofs]: Floors updated finished successfully."); return; } Debug.Log((object)"[floorsareroofs]: Floor update finished, but it looks like we couldn't find some of the floors you specified. Please doublecheck your config settings."); LogConfigSettingHelp(); } else { Debug.LogError((object)"[floorsareroofs]: Floor update finished, but there were errors. Please doublecheck your config settings."); LogConfigSettingHelp(); } } private static void LogConfigSettingHelp() { Debug.Log((object)"[floorsareroofs]: The config settings are case-sensitive, each item should be separated by a comma, and there should be no spaces before or after the commas."); if (HammersListInConfigSettings != "Hammer") { Debug.Log((object)("[floorsareroofs]: You have a non-default config setting for Hammers. Default: Hammer. Your setting: " + HammersListInConfigSettings)); } if (PrefabListInConfigSettings != "wood_floor,wood_floor_1x1,piece_ashwood_floor_1x1,piece_ashwood_floor_2x2,piece_ashwood_floor_half,piece_grausten_floor_1x1,piece_grausten_floor_2x2,piece_flametal_floor_1x1,piece_flametal_floor_2x2") { Debug.Log((object)("[floorsareroofs]: You have a non-default config setting for PrefabsToChange. Default: wood_floor,wood_floor_1x1,piece_ashwood_floor_1x1,piece_ashwood_floor_2x2,piece_ashwood_floor_half,piece_grausten_floor_1x1,piece_grausten_floor_2x2,piece_flametal_floor_1x1,piece_flametal_floor_2x2. Your setting: " + PrefabListInConfigSettings)); } } private static bool UpdatePiecesInHammer(string hammerName, out int cFloorsUpdated) { cFloorsUpdated = 0; Debug.Log((object)("[floorsareroofs]: Starting to patches pieces in Hammer " + hammerName + ".")); GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(hammerName); if ((Object)(object)itemPrefab == (Object)null) { Debug.LogError((object)("[floorsareroofs]: Could not find tool " + hammerName + " in ObjectDB.")); return false; } ItemDrop val = default(ItemDrop); if (!itemPrefab.TryGetComponent(ref val)) { Debug.LogError((object)("[floorsareroofs]: Could not get itemdrop from hammer " + hammerName)); return false; } PieceTable val2 = val?.m_itemData?.m_shared?.m_buildPieces; if ((Object)(object)val2 == (Object)null) { Debug.LogError((object)("[floorsareroofs]: Could not find piecetable in hammer " + hammerName)); return false; } if (val2.m_pieces == null || val2.m_pieces.Count == 0) { Debug.LogError((object)("[floorsareroofs]: Could not find any pieces in hammerPieceTable for hammer " + hammerName)); return false; } List list = val2.m_pieces.FindAll((GameObject i) => PrefabList.Contains((i != null) ? ((Object)i).name : null)); if (list == null || list.Count == 0) { Debug.Log((object)("[floorsareroofs]: Could not find any of the specified floors in hammer piece " + hammerName + ". Continuing...")); return true; } foreach (GameObject item in list) { if (PatchAFloor(item)) { cFloorsUpdated++; } } Debug.Log((object)$"[floorsareroofs]: Finished with hammer {hammerName}. Sucessfully updated {cFloorsUpdated} floors."); return true; } private static bool PatchAFloor(GameObject go) { Debug.Log((object)("[floorsareroofs]: Preparing to patch " + ((Object)go).name)); Transform val = default(Transform); if (!go.TryGetComponent(ref val)) { Debug.LogError((object)("[floorsareroofs]: Could not find Transform in floor " + ((Object)go).name)); return false; } WearNTear val2 = default(WearNTear); if (!go.TryGetComponent(ref val2)) { Debug.LogError((object)("[floorsareroofs]: Could not find WearNTear in floor " + ((Object)go).name)); return false; } bool flag = false; for (int i = 0; i < val.childCount; i++) { Transform child = val.GetChild(i); if (!(((child != null) ? ((Object)child).name : null) != "collider")) { flag = true; if (((Component)child).tag == "leaky") { ((Component)child).tag = "roof"; Debug.Log((object)("[floorsareroofs] Successfully patched " + ((Object)go).name + " into a roof")); continue; } if (((Component)child).tag == "roof") { Debug.Log((object)("[floorsareroofs] " + ((Object)go).name + " is already a roof")); continue; } Debug.LogError((object)("[floorsareroofs]: Could not patch " + ((Object)go).name + ". Its collider has tag '" + (((Component)child).tag ?? "[null]") + "' instead of 'leaky'")); } } if (!flag) { Debug.LogError((object)("[floorsareroofs]: Could not find collider in " + ((Object)go).name)); return false; } if (RemoveRainDamage) { if (val2.m_noRoofWear) { Debug.Log((object)("[floorsareroofs] " + ((Object)go).name + " patched to not degrade in the rain")); val2.m_noRoofWear = false; } else { Debug.Log((object)("[floorsareroofs] " + ((Object)go).name + " already does not degrade in the rain")); } } else { Debug.Log((object)("[floorsareroofs] Not updating " + ((Object)go).name + ".m_noRoofWear because config setting RemoveRainDamage is false")); } return true; } }