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 Dvala v1.1.0
plugins/Dvala/Dvala.dll
Decompiled 3 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Ezomic.Core; using HarmonyLib; using Microsoft.CodeAnalysis; using SoftReferenceableAssets; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("Thijssen Software")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) 2026 Robbin Thijssen")] [assembly: AssemblyDescription("A dungeon left alone long enough fills back up.")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0+b27086ed223c2097327d030adc96f1239d0e188c")] [assembly: AssemblyProduct("Dvala")] [assembly: AssemblyTitle("Dvala")] [assembly: AssemblyVersion("1.1.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 Dvala { internal static class DevConsole { [HarmonyPatch(typeof(Terminal), "InitTerminal")] internal static class Hook { [CompilerGenerated] private static class <>O { public static ConsoleEvent <0>__OnCommand; } private static void Postfix() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if (!_registered) { _registered = true; object obj = <>O.<0>__OnCommand; if (obj == null) { ConsoleEvent val = OnCommand; <>O.<0>__OnCommand = val; obj = (object)val; } new ConsoleCommand("dvala", "restock - restock the dungeon whose entrance you stand at now, pickups included. scan - every dungeon generator loaded, networked or not. wanted - whether the config covers the dungeon whose entrance you stand at, by its room themes, which is the test a visit restocks by", (ConsoleEvent)obj, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } } } private static bool _registered; private static void OnCommand(ConsoleEventArgs args) { Terminal context = args.Context; if ((Object)(object)context == (Object)null) { return; } string text = ((args.Length > 1) ? args[1].ToLowerInvariant() : ""); if (text == "scan") { foreach (string item in Scan()) { context.AddString("dvala scan: " + item); DvalaPlugin.Log.LogInfo((object)("scan: " + item)); } return; } if (text == "wanted") { context.AddString("dvala wanted: " + Wanted()); } else if (text != "restock") { context.AddString("dvala: try 'dvala restock', 'dvala wanted' or 'dvala scan' while standing at a dungeon entrance."); } else { context.AddString("dvala restock: " + Restock()); } } private static List<string> Scan() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected I4, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) List<string> list = new List<string>(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { list.Add("refused no player in a world"); return list; } DungeonGenerator[] array = Object.FindObjectsOfType<DungeonGenerator>(true); List<KeyValuePair<float, string>> list2 = new List<KeyValuePair<float, string>>(); DungeonGenerator[] array2 = array; foreach (DungeonGenerator val in array2) { if (!((Object)(object)val == (Object)null)) { Vector3 val2 = ((Component)val).transform.position - ((Component)localPlayer).transform.position; val2.y = 0f; ZNetView component = ((Component)val).GetComponent<ZNetView>(); string text = (((Object)(object)component == (Object)null) ? "none" : (component.IsValid() ? "valid" : "invalid")); list2.Add(new KeyValuePair<float, string>(((Vector3)(ref val2)).magnitude, "name=" + ((Object)val).name.Replace("(Clone)", "") + " themes=" + (int)val.m_themes + " znetview=" + text + " active=" + (((Component)val).gameObject.activeInHierarchy ? "yes" : "no") + " away=" + Mathf.RoundToInt(((Vector3)(ref val2)).magnitude) + "m y=" + Mathf.RoundToInt(((Component)val).transform.position.y))); } } list2.Sort((KeyValuePair<float, string> x, KeyValuePair<float, string> y) => x.Key.CompareTo(y.Key)); list.Add("count=" + list2.Count); for (int num = 0; num < list2.Count && num < 12; num++) { list.Add(list2[num].Value); } return list; } private static string Wanted() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected I4, but got Unknown string refusal; DungeonGenerator val = Nearest(out refusal); if ((Object)(object)val == (Object)null) { return refusal; } return "name=" + ((Object)val).name.Replace("(Clone)", "") + " themes=" + (int)val.m_themes + " covered=" + (Dungeons.Wanted(val) ? "yes" : "no"); } private static string Restock() { string refusal; DungeonGenerator val = Nearest(out refusal); if ((Object)(object)val == (Object)null) { return refusal; } if (Dungeons.Occupied(val)) { return "refused you are inside it, stand at the entrance outside the rooms"; } if (Dungeons.HoldsTombstone(val)) { return "refused a gravestone stands in its rooms"; } if (!((Component)val).GetComponent<ZNetView>().IsOwner()) { return "refused this machine does not own the dungeon"; } Restore.Counts counts = Restore.Dungeon(val); ManualLogSource log = DvalaPlugin.Log; string[] obj = new string[5] { "Command: restock ", Dungeons.Describe(val), ": ", null, null }; Restore.Counts counts2 = counts; obj[3] = counts2.ToString(); obj[4] = "."; log.LogInfo((object)string.Concat(obj)); counts2 = counts; return "ok " + counts2.ToString(); } private static DungeonGenerator Nearest(out string refusal) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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) refusal = null; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)ZNetScene.instance == (Object)null) { refusal = "refused no player in a world"; return null; } Vector2s zone = ZoneSystem.GetZone(((Component)localPlayer).transform.position); DungeonGenerator val = null; float num = float.MaxValue; foreach (DungeonGenerator item in Dungeons.Live()) { if (!(ZoneSystem.GetZone(((Component)item).transform.position) != zone)) { Vector3 val2 = ((Component)item).transform.position - ((Component)localPlayer).transform.position; val2.y = 0f; if (!(((Vector3)(ref val2)).sqrMagnitude >= num)) { num = ((Vector3)(ref val2)).sqrMagnitude; val = item; } } } if ((Object)(object)val == (Object)null) { refusal = "refused no dungeon generator in this zone"; } return val; } } internal static class Dungeons { private static readonly int StampKey = StringExtensionMethods.GetStableHashCode("dvala_day"); private static readonly List<DungeonGenerator> Managed = new List<DungeonGenerator>(); private static float _managedAt = -999f; internal static IEnumerable<DungeonGenerator> Live() { if ((Object)(object)ZNetScene.instance == (Object)null) { yield break; } DungeonGenerator[] array = Object.FindObjectsOfType<DungeonGenerator>(); foreach (DungeonGenerator val in array) { if (!((Object)(object)val == (Object)null)) { ZNetView component = ((Component)val).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { yield return val; } } } } internal static bool Wanted(DungeonGenerator generator) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 return (generator.m_themes & DvalaConfig.Themes()) > 0; } internal static int Stamped(DungeonGenerator generator) { ZNetView component = ((Component)generator).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return -1; } return component.GetZDO().GetInt(StampKey, -1); } internal static void Stamp(DungeonGenerator generator, int day) { ZNetView component = ((Component)generator).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { component.ClaimOwnership(); component.GetZDO().Set(StampKey, day, false); } } internal static bool Inside(Vector3 point) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) if (Time.realtimeSinceStartup - _managedAt > 2f) { _managedAt = Time.realtimeSinceStartup; Managed.Clear(); foreach (DungeonGenerator item in Live()) { if (Wanted(item)) { Managed.Add(item); } } } if (Managed.Count == 0) { return false; } for (int i = 0; i < Managed.Count; i++) { DungeonGenerator val = Managed[i]; if (!((Object)(object)val == (Object)null) && Inside(val, point)) { return true; } } return false; } internal unsafe static string Describe(DungeonGenerator generator) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) ZNetView component = ((Component)generator).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return ((Object)generator).name; } string name = ((Object)generator).name; ZDOID uid = component.GetZDO().m_uid; return name + " " + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString(); } internal static int Today() { EnvMan instance = EnvMan.instance; if (!((Object)(object)instance == (Object)null)) { return instance.GetDay(); } return -1; } internal static bool Occupied(DungeonGenerator generator) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) foreach (Player allPlayer in Player.GetAllPlayers()) { if (!((Object)(object)allPlayer == (Object)null) && Inside(generator, ((Component)allPlayer).transform.position)) { return true; } } return false; } internal static bool HoldsTombstone(DungeonGenerator generator) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) TombStone[] array = Object.FindObjectsOfType<TombStone>(); if (array.Length == 0) { return false; } TombStone[] array2 = array; foreach (TombStone val in array2) { if (!((Object)(object)val == (Object)null) && Inside(generator, ((Component)val).transform.position)) { return true; } } return false; } internal static bool Inside(DungeonGenerator generator, Vector3 point) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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) float num = Mathf.Max(0f, DvalaConfig.RoomPadding.Value); Room[] componentsInChildren = ((Component)generator).GetComponentsInChildren<Room>(); foreach (Room val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { Vector3 val2 = Quaternion.Inverse(((Component)val).transform.rotation) * (point - ((Component)val).transform.position); Vector3 val3 = Vector3Int.op_Implicit(val.m_size) * 0.5f; if (Mathf.Abs(val2.x) <= val3.x + num && Mathf.Abs(val2.y) <= val3.y + num && Mathf.Abs(val2.z) <= val3.z + num) { return true; } } } return false; } } internal static class DvalaConfig { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<int> Days; internal static ConfigEntry<bool> SkipOccupied; internal static ConfigEntry<float> RoomPadding; internal static ConfigEntry<float> CheckSeconds; internal static ConfigEntry<bool> Crypts; internal static ConfigEntry<bool> Caves; internal static ConfigEntry<bool> Mines; internal static ConfigEntry<bool> Ashlands; internal static ConfigEntry<bool> Tunnels; internal static ConfigEntry<bool> Morkhalla; internal static ConfigEntry<bool> HildirRooms; internal static ConfigEntry<bool> Camps; internal static ConfigEntry<bool> KeepVeins; internal static ConfigEntry<bool> Pickups; internal static ConfigEntry<bool> Verbose; internal static void Bind(ConfigFile cfg) { Enabled = cfg.Bind<bool>("Dvala", "Enabled", true, "Off leaves the plugin loaded and changing nothing."); Days = cfg.Bind<int>("Dvala", "Days", 30, "In-game days a dungeon must be left alone before it fills back up. A day is 20 minutes of a running world, so 30 is about 10 hours of play - and on a dedicated server the clock keeps turning while nobody is on. The count starts when Dvala first sees the dungeon, never at day zero, so installing this on an old world does not restock everything in it at once."); SkipOccupied = cfg.Bind<bool>("Dvala", "SkipOccupied", true, "Never restock a dungeon with a player inside it. Off means a dungeon can refill around you mid-run, which re-arms the spawners you just cleared and puts fresh loot in chests you already emptied. It also makes the day it happens unpredictable, since it turns on where people happen to be."); RoomPadding = cfg.Bind<float>("Dvala", "RoomPadding", 1.5f, "Metres of slack when asking whether a point is inside a dungeon room. Only raise it if a player standing in a doorway is treated as outside; a large value starts catching the ground above a shallow crypt."); CheckSeconds = cfg.Bind<float>("Dvala", "CheckSeconds", 30f, "How often to look, in real seconds. This is not how often anything resets - that is Days. Lower costs nothing measurable and only changes how soon after midnight a due dungeon notices."); Crypts = cfg.Bind<bool>("Contents", "Crypts", true, "Burial chambers, forest crypts and sunken crypts."); Caves = cfg.Bind<bool>("Contents", "Caves", true, "Troll caves and the frost caves in the mountains."); Mines = cfg.Bind<bool>("Contents", "Mines", true, "Mistlands infested mines. The Queen's own room is never included."); Ashlands = cfg.Bind<bool>("Contents", "Ashlands", true, "Ashlands ruins and fortresses."); Tunnels = cfg.Bind<bool>("Contents", "Tunnels", true, "The winding tunnels, a dungeon type new in Valheim 1.0."); Morkhalla = cfg.Bind<bool>("Contents", "Morkhalla", true, "Morkhalla, a dungeon type new in Valheim 1.0, with its chests and ore veins."); HildirRooms = cfg.Bind<bool>("Contents", "HildirRooms", true, "Hildir's three: the Sealed Tower, the Howling Cavern and the Smouldering Tomb. On, so their mini-bosses return on the timer like anything else. If you use Lur, its horn still works and still wakes one immediately - what this takes away is the horn being the only way. Turn it off to keep that."); Camps = cfg.Bind<bool>("Contents", "Camps", false, "Fuling camps, Meadows villages and farms. These are built by the dungeon generator but they sit on the surface where people build, so restocking them means re-arming spawners next door to somebody's house."); KeepVeins = cfg.Bind<bool>("Contents", "KeepVeins", true, "Stop a fully mined vein from deleting itself, so it can be restocked later. Without this, a vein you strip bare is gone for good and only the chests, spawners and pickables in that room come back. What is left behind is an invisible husk you can walk through, holding nothing, until the timer fills it back in - and it costs the world exactly what a half-mined vein already costs it, one saved object. Interiors only: veins on the surface are never held back, whatever else is switched on here."); Pickups = cfg.Bind<bool>("Contents", "Pickups", true, "Put back pickups that are destroyed when taken: the hanging items and pedestal pieces in the frost caves, and any other pickable with no picked flag. They are rebuilt from the dungeon's own room prefabs, and only ever added, never deleted. While this is on, only the peer that owns a dungeon restocks it, so two players cannot both spawn the same pickup. Off restocks only what has a flag to clear."); Verbose = cfg.Bind<bool>("Dvala", "Verbose", false, "Write what was found and what was changed to BepInEx/LogOutput.log. Off unless something looks wrong; it is one line per dungeon and one per item."); } internal static Theme Themes() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) Theme val = (Theme)0; if (Crypts.Value) { val = (Theme)(val | 0xB); } if (Caves.Value) { val = (Theme)(val | 4); } if (Mines.Value) { val = (Theme)(val | 0x80); } if (Ashlands.Value) { val = (Theme)(val | 0x3000); } if (Tunnels.Value) { val = (Theme)(val | 0x4000); } if (Morkhalla.Value) { val = (Theme)(val | 0x20000); } if (HildirRooms.Value) { val = (Theme)(val | 0xE00); } if (Camps.Value) { val = (Theme)(val | 0x70); } return val; } } internal static class DvalaPatches { [HarmonyPatch(typeof(MineRock5), "AllDestroyed")] [HarmonyPostfix] private static void KeepMinedVeins(MineRock5 __instance, ref bool __result) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (__result && DvalaConfig.Enabled.Value && DvalaConfig.KeepVeins.Value && !((Object)(object)__instance == (Object)null) && Dungeons.Inside(((Component)__instance).transform.position)) { __result = false; } } } [BepInPlugin("ezomic.valheim.dvala", "Dvala", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class DvalaPlugin : BaseUnityPlugin { public const string PluginGuid = "ezomic.valheim.dvala"; public const string PluginName = "Dvala"; public const string PluginVersion = "1.1.0"; public const string PluginAuthor = "Robbin Thijssen"; private const string CoreGuid = "ezomic.valheim.core"; internal static ManualLogSource Log; internal static bool CorePresent; private Harmony _harmony; private float _since; private bool _faulted; private readonly HashSet<string> _graveLogged = new HashSet<string>(); private void Awake() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; DvalaConfig.Bind(((BaseUnityPlugin)this).Config); TryRegisterWithCore(); _harmony = new Harmony("ezomic.valheim.dvala"); _harmony.PatchAll(typeof(DvalaPatches)); _harmony.PatchAll(typeof(Rearm)); PatchOptional(typeof(DevConsole.Hook), "the dvala console command"); Log.LogInfo((object)"Dvala 1.1.0 by Robbin Thijssen - ready."); } private void PatchOptional(Type patch, string what) { try { _harmony.PatchAll(patch); } catch (Exception ex) { Log.LogError((object)("Could not patch in " + what + " (" + patch.Name + "), so it stays out this session. Nothing else is affected. " + ex.Message)); } } private void TryRegisterWithCore() { CorePresent = Chainloader.PluginInfos.ContainsKey("ezomic.valheim.core"); if (!CorePresent) { Log.LogInfo((object)"Core not installed - running standalone, without the version gate."); } else { RegisterWithCore(); } } [MethodImpl(MethodImplOptions.NoInlining)] private void RegisterWithCore() { Suite.Register("ezomic.valheim.dvala", "Dvala", "1.1.0", ((BaseUnityPlugin)this).Config, (Requirement)0, (Assembly)null); Suite.Sync((ConfigEntryBase)(object)DvalaConfig.Enabled); } private void OnDestroy() { if (_harmony != null) { _harmony.UnpatchSelf(); } } private void Update() { if (!DvalaConfig.Enabled.Value) { return; } _since += Time.deltaTime; if (_since < Mathf.Max(1f, DvalaConfig.CheckSeconds.Value)) { return; } _since = 0f; try { Sweep(); } catch (Exception ex) { if (!_faulted) { _faulted = true; Log.LogError((object)("Dvala's sweep threw and will keep being attempted, but this is reported once: " + ex)); } } } private void Sweep() { if ((Object)(object)ZNetScene.instance == (Object)null || (Object)(object)EnvMan.instance == (Object)null) { return; } int num = Dungeons.Today(); if (num < 0) { return; } int num2 = Mathf.Max(1, DvalaConfig.Days.Value); foreach (DungeonGenerator item in Dungeons.Live()) { if (!Dungeons.Wanted(item)) { continue; } int num3 = Dungeons.Stamped(item); if (num3 < 0) { Dungeons.Stamp(item, num); } else { if (num - num3 < num2) { continue; } if (Dungeons.HoldsTombstone(item)) { if (DvalaConfig.Verbose.Value && _graveLogged.Add(Dungeons.Describe(item))) { Log.LogInfo((object)(Dungeons.Describe(item) + " is due but a gravestone stands in its rooms, so it is left alone until it is collected.")); } continue; } _graveLogged.Remove(Dungeons.Describe(item)); if ((DvalaConfig.Pickups.Value && !((Component)item).GetComponent<ZNetView>().IsOwner()) || (DvalaConfig.SkipOccupied.Value && Dungeons.Occupied(item))) { continue; } Restore.Counts counts = Restore.Dungeon(item); if (counts.ChestsDeferred > 0) { ManualLogSource log = Log; string[] obj = new string[5] { "Restocked ", Dungeons.Describe(item), " only in part: ", null, null }; Restore.Counts counts2 = counts; obj[3] = counts2.ToString(); obj[4] = ". It will be tried again on the next sweep."; log.LogInfo((object)string.Concat(obj)); continue; } Dungeons.Stamp(item, num); int num4 = Dungeons.Stamped(item); if (DvalaConfig.Verbose.Value || counts.Total > 0) { ManualLogSource log2 = Log; string[] obj2 = new string[7] { "Restocked ", Dungeons.Describe(item), " after ", (num - num3).ToString(), " days: ", null, null }; Restore.Counts counts2 = counts; obj2[5] = counts2.ToString(); obj2[6] = "."; log2.LogInfo((object)string.Concat(obj2)); } if (num4 != num) { Log.LogWarning((object)("Stamp did not stick on " + Dungeons.Describe(item) + ": wrote " + num + ", reads back " + num4 + ". It will restock again on the next sweep.")); } } } } } internal static class Pickups { private struct Candidate { internal ZNetView View; internal int Hash; internal Vector3 Position; internal Quaternion Rotation; } private static class Walk { internal unsafe static void Run(DungeonGenerator generator, Room placed, RoomData data, GameObject asset, Dictionary<Vector2s, List<ZDO>> sectors, HashSet<ZDOID> matched, ref Restore.Counts counts) { //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) Room component = asset.GetComponent<Room>(); if ((Object)(object)component == (Object)null) { return; } ZNetView[] enabledComponentsInChildren = Utils.GetEnabledComponentsInChildren<ZNetView>(asset); RandomObject[] enabledComponentsInChildren2 = Utils.GetEnabledComponentsInChildren<RandomObject>(asset); RandomSpawn[] enabledComponentsInChildren3 = Utils.GetEnabledComponentsInChildren<RandomSpawn>(asset); bool flag = false; ZNetView[] array = enabledComponentsInChildren; Pickable val2 = default(Pickable); PickableItem val3 = default(PickableItem); foreach (ZNetView val in array) { if (((Component)val).TryGetComponent<Pickable>(ref val2) || ((Component)val).TryGetComponent<PickableItem>(ref val3)) { flag = true; break; } } if (!flag) { return; } Vector3 position = ((Component)placed).transform.position; Quaternion rotation = ((Component)placed).transform.rotation; Vector3 position2 = ((Component)component).transform.position; Quaternion val4 = Quaternion.Inverse(((Component)component).transform.rotation); int num = Seed(generator, placed, position); List<Candidate> list = new List<Candidate>(); RandomSpawn[] array2 = enabledComponentsInChildren3; for (int i = 0; i < array2.Length; i++) { array2[i].Prepare(); } State state = Random.state; try { Random.InitState(num); array2 = enabledComponentsInChildren3; foreach (RandomSpawn val5 in array2) { Vector3 val6 = val4 * (((Component)val5).transform.position - position2); val5.Randomize(position + rotation * val6, (Location)null, generator); } RandomObject[] array3 = enabledComponentsInChildren2; foreach (RandomObject val7 in array3) { Vector3 val8 = val4 * (((Component)val7).transform.position - position2); val7.Randomize(position + rotation * val8, (Location)null, generator); } array = enabledComponentsInChildren; foreach (ZNetView val9 in array) { if (((Component)val9).gameObject.activeSelf && (((Component)val9).TryGetComponent<Pickable>(ref val2) || ((Component)val9).TryGetComponent<PickableItem>(ref val3))) { int stableHashCode = StringExtensionMethods.GetStableHashCode(Utils.GetPrefabName(((Component)val9).gameObject)); if ((Object)(object)ZNetScene.instance.GetPrefab(stableHashCode) == (Object)null) { Verbose("no registered prefab for " + ((Object)val9).name + ", left out"); continue; } Vector3 val10 = val4 * (((Component)val9).transform.position - position2); list.Add(new Candidate { View = val9, Hash = stableHashCode, Position = position + rotation * val10, Rotation = rotation * (val4 * ((Component)val9).transform.rotation) }); } } } finally { Random.state = state; } try { ZNetView val11 = default(ZNetView); foreach (Candidate item in list) { counts.PickupsSeen++; if (!Present(item, sectors, matched)) { GameObject obj = Object.Instantiate<GameObject>(((Component)item.View).gameObject, item.Position, item.Rotation); GameObjectExtentions.HoldReferenceTo(obj, data.m_prefab); if (!obj.TryGetComponent<ZNetView>(ref val11) || !val11.IsValid()) { Verbose("spawning " + ((Object)item.View).name + " made no ZDO"); continue; } matched.Add(val11.GetZDO().m_uid); AddToSector(sectors, val11.GetZDO()); counts.Pickups++; string name = ((Object)item.View).name; Vector3 position3 = item.Position; Verbose("put back " + name + " at " + ((object)(*(Vector3*)(&position3))/*cast due to .constrained prefix*/).ToString()); } } } finally { array2 = enabledComponentsInChildren3; for (int i = 0; i < array2.Length; i++) { array2[i].Reset(); } RandomObject[] array3 = enabledComponentsInChildren2; for (int i = 0; i < array3.Length; i++) { array3[i].Reset(); } array = enabledComponentsInChildren; for (int i = 0; i < array.Length; i++) { ((Component)array[i]).gameObject.SetActive(true); } } } private static int Seed(DungeonGenerator generator, Room placed, Vector3 pos) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (placed.m_seed != 0) { return placed.m_seed; } Vector3 val = pos; if (generator.m_useCustomInteriorTransform) { val = pos - ((Component)generator).transform.position; } int num = (int)val.x * 4271 + (int)val.y * 9187 + (int)val.z * 2134; if (generator.m_addBaseSeedToRandomSpawn) { num += generator.GetSeed(); } return num; } private static bool Present(Candidate candidate, Dictionary<Vector2s, List<ZDO>> sectors, HashSet<ZDOID> matched) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_009e: Unknown result type (might be due to invalid IL or missing references) Vector2s zone = ZoneSystem.GetZone(candidate.Position); if (!sectors.TryGetValue(zone, out var value)) { value = new List<ZDO>(); ZDOMan.instance.FindSectorObjects(zone, new SimulationDistance(0, 0, false), value, (List<ZDO>)null); sectors[zone] = value; } float num = 0.5625f; foreach (ZDO item in value) { if (item != null && item.IsValid() && item.GetPrefab() == candidate.Hash && !matched.Contains(item.m_uid)) { Vector3 val = item.GetPosition() - candidate.Position; if (!(((Vector3)(ref val)).sqrMagnitude > num)) { matched.Add(item.m_uid); return true; } } } return false; } private static void AddToSector(Dictionary<Vector2s, List<ZDO>> sectors, ZDO zdo) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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) Vector2s zone = ZoneSystem.GetZone(zdo.GetPosition()); if (sectors.TryGetValue(zone, out var value)) { value.Add(zdo); } } } private const float Radius = 0.75f; internal static void Run(DungeonGenerator generator, ref Restore.Counts counts) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) if (!DvalaConfig.Pickups.Value || (Object)(object)DungeonDB.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || ZDOMan.instance == null || (Object)(object)ZoneSystem.instance == (Object)null) { return; } ZNetView component = ((Component)generator).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner()) { return; } Room[] componentsInChildren = ((Component)generator).GetComponentsInChildren<Room>(); Room[] array = componentsInChildren; foreach (Room val in array) { if (!((Object)(object)val == (Object)null) && !ZNetScene.instance.IsAreaReady(((Component)val).transform.position)) { Verbose("area not ready around " + ((Object)val).name + ", pickups wait for the next sweep"); return; } } Dictionary<Vector2s, List<ZDO>> sectors = new Dictionary<Vector2s, List<ZDO>>(); HashSet<ZDOID> matched = new HashSet<ZDOID>(); array = componentsInChildren; foreach (Room val2 in array) { if ((Object)(object)val2 == (Object)null) { continue; } RoomData room = DungeonDB.instance.GetRoom(val2.GetHash()); if (room == null) { continue; } _ = room.m_prefab; room.m_prefab.Load(); try { GameObject asset = room.m_prefab.Asset; if (!((Object)(object)asset == (Object)null)) { Walk.Run(generator, val2, room, asset, sectors, matched, ref counts); } } finally { room.m_prefab.Release(); } } } private static void Verbose(string text) { if (DvalaConfig.Verbose.Value) { DvalaPlugin.Log.LogInfo((object)(" pickups: " + text)); } } } internal static class Rearm { internal static readonly int Key = StringExtensionMethods.GetStableHashCode("dvala_rearm"); internal static void Mark(ZDO zdo, int day) { zdo.Set(Key, Mathf.Max(1, day), false); } [HarmonyPatch(typeof(CreatureSpawner), "UpdateSpawner")] [HarmonyPrefix] private static void BeforeUpdate(CreatureSpawner __instance) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) ZNetView val = default(ZNetView); if (!DvalaConfig.Enabled.Value || (Object)(object)__instance == (Object)null || !((Component)__instance).TryGetComponent<ZNetView>(ref val) || !val.IsValid() || !val.IsOwner()) { return; } ZDO zDO = val.GetZDO(); if (zDO.GetInt(Key, 0) > 0 && (int)zDO.GetConnectionType() == 3) { ZDOID connectionZDOID = zDO.GetConnectionZDOID((ConnectionType)3); if (!((ZDOID)(ref connectionZDOID)).IsNone() && ZDOMan.instance.GetZDO(connectionZDOID) != null) { zDO.Set(Key, 0, false); } else { zDO.SetConnection((ConnectionType)0, ZDOID.None); } } } [HarmonyPatch(typeof(CreatureSpawner), "Spawn")] [HarmonyPostfix] private static void AfterSpawn(CreatureSpawner __instance, ZNetView __result) { ZNetView val = default(ZNetView); if (!((Object)(object)__result == (Object)null) && !((Object)(object)__instance == (Object)null) && ((Component)__instance).TryGetComponent<ZNetView>(ref val) && val.IsValid() && val.IsOwner()) { ZDO zDO = val.GetZDO(); if (zDO.GetInt(Key, 0) > 0) { zDO.Set(Key, 0, false); } } } } internal static class Restore { internal struct Counts { internal int Pickables; internal int Chests; internal int Veins; internal int Spawners; internal int Pickups; internal int ChestsDeferred; internal int PickablesSeen; internal int ChestsSeen; internal int VeinsSeen; internal int SpawnersSeen; internal int PickupsSeen; internal int Total => Pickables + Chests + Veins + Spawners + Pickups; public override string ToString() { return "pickables " + Pickables + "/" + PickablesSeen + ", chests " + Chests + "/" + ChestsSeen + ", veins " + Veins + "/" + VeinsSeen + ", spawners " + Spawners + "/" + SpawnersSeen + ", pickups " + Pickups + "/" + PickupsSeen + ((ChestsDeferred > 0) ? (", chests deferred " + ChestsDeferred) : ""); } } internal static Counts Dungeon(DungeonGenerator generator) { Counts counts = default(Counts); Pickables(generator, ref counts); Chests(generator, ref counts); Veins(generator, ref counts); Spawners(generator, ref counts); Pickups.Run(generator, ref counts); return counts; } private static void Pickables(DungeonGenerator generator, ref Counts counts) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) Pickable[] array = Object.FindObjectsOfType<Pickable>(); foreach (Pickable val in array) { if ((Object)(object)val == (Object)null || !Dungeons.Inside(generator, ((Component)val).transform.position)) { continue; } ZNetView component = ((Component)val).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { counts.PickablesSeen++; if (component.GetZDO().GetBool(ZDOVars.s_picked, false)) { component.ClaimOwnership(); component.InvokeRPC(ZNetView.Everybody, "RPC_SetPicked", new object[1] { false }); counts.Pickables++; } } } } private static void Chests(DungeonGenerator generator, ref Counts counts) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) Container[] array = Object.FindObjectsOfType<Container>(); Piece val2 = default(Piece); foreach (Container val in array) { if ((Object)(object)val == (Object)null || !Dungeons.Inside(generator, ((Component)val).transform.position)) { continue; } if (((Component)val).TryGetComponent<Piece>(ref val2) && val2.GetCreator() != 0L) { SkipChest(val, "placed by a player"); continue; } if (val.m_defaultItems == null || val.m_defaultItems.m_drops == null || val.m_defaultItems.m_drops.Count == 0) { SkipChest(val, "no drop table"); continue; } ZNetView component = ((Component)val).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { SkipChest(val, "no live ZDO"); continue; } Inventory inventory = val.GetInventory(); if (inventory == null) { SkipChest(val, "no inventory"); continue; } counts.ChestsSeen++; if (inventory.NrOfItems() > 0) { SkipChest(val, "not empty (" + inventory.NrOfItems() + " items)"); continue; } int num = SavedItems(component.GetZDO()); if (num > 0) { SkipChest(val, "not empty in the ZDO (" + num + " items, the component has not loaded them yet)"); continue; } component.ClaimOwnership(); if (!component.IsOwner()) { counts.ChestsDeferred++; SkipChest(val, "ownership not granted, will retry"); continue; } int num2 = 0; foreach (ItemData dropListItem in val.m_defaultItems.GetDropListItems()) { inventory.AddItem(dropListItem); num2++; } if (num2 == 0) { SkipChest(val, "the drop table rolled nothing"); } else if (SavedItems(component.GetZDO()) == 0) { counts.ChestsDeferred++; SkipChest(val, "filled " + num2 + " items but the ZDO still reads empty, will retry"); } else { counts.Chests++; } } } private static void SkipChest(Container container, string why) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (DvalaConfig.Verbose.Value) { DvalaPlugin.Log.LogInfo((object)(" chest " + ((Object)container).name + " at " + ((object)((Component)container).transform.position/*cast due to .constrained prefix*/).ToString() + " skipped: " + why)); } } private static int SavedItems(ZDO zdo) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) byte[] byteArray = zdo.GetByteArray(ZDOVars.s_items, (byte[])null); if (byteArray == null || byteArray.Length < 6) { return 0; } ZPackage val = new ZPackage(byteArray); val.ReadInt(); return val.ReadUShort(); } private static void Veins(DungeonGenerator generator, ref Counts counts) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown MineRock5[] array = Object.FindObjectsOfType<MineRock5>(); foreach (MineRock5 val in array) { if ((Object)(object)val == (Object)null || !Dungeons.Inside(generator, ((Component)val).transform.position)) { continue; } ZNetView component = ((Component)val).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { continue; } counts.VeinsSeen++; if (component.GetZDO().GetString(ZDOVars.s_health, "").Length == 0) { continue; } int num = ((Component)val).GetComponentsInChildren<Collider>(true).Length; if (num != 0) { float num2 = val.m_health + (float)Game.m_worldLevel * val.m_health * Game.instance.m_worldLevelMineHPMultiplier; ZPackage val2 = new ZPackage(); val2.Write(num); for (int j = 0; j < num; j++) { val2.Write(num2); } string text = Convert.ToBase64String(val2.GetArray()); if (!(component.GetZDO().GetString(ZDOVars.s_health, "") == text)) { component.ClaimOwnership(); component.GetZDO().Set(ZDOVars.s_health, text); counts.Veins++; } } } } private static void Spawners(DungeonGenerator generator, ref Counts counts) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Invalid comparison between Unknown and I4 //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) CreatureSpawner[] array = Object.FindObjectsOfType<CreatureSpawner>(); foreach (CreatureSpawner val in array) { if ((Object)(object)val == (Object)null || !Dungeons.Inside(generator, ((Component)val).transform.position)) { continue; } ZNetView component = ((Component)val).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { continue; } counts.SpawnersSeen++; ZDO zDO = component.GetZDO(); if ((int)zDO.GetConnectionType() == 3) { ZDOID connectionZDOID = zDO.GetConnectionZDOID((ConnectionType)3); if (((ZDOID)(ref connectionZDOID)).IsNone() || ZDOMan.instance.GetZDO(connectionZDOID) == null) { component.ClaimOwnership(); zDO.SetConnection((ConnectionType)0, ZDOID.None); Rearm.Mark(zDO, Dungeons.Today()); counts.Spawners++; } } } } } }