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 Runebourne v0.8.5
plugins/Runebourne.dll
Decompiled 18 hours ago
The result has been truncated due to the large size, download it to view full contents!
using 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.InteropServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Runebourne.Away; using Runebourne.Diagnostics; using Runebourne.Farming; using Runebourne.General; using Runebourne.Guide; using Runebourne.Hauling; using Runebourne.Mining; using Runebourne.Planting; using Runebourne.Progression; using Runebourne.Serpents; using Runebourne.Vault; using Splatform; using TMPro; using UnityEngine; using UnityEngine.AI; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Runebourne")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Runebourne")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.8.5")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.8.5.0")] namespace Runebourne { [BepInPlugin("com.yohanb.runebourne", "Runebourne", "0.8.5")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class Runebourne : BaseUnityPlugin { public const string PluginGUID = "com.yohanb.runebourne"; public const string PluginName = "Runebourne"; public const string PluginVersion = "0.8.5"; public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization(); private void Awake() { Logger.LogInfo((object)"Runebourne has loaded"); FarmPostRegistration.Start(); FarmSpiritRegistration.Start(); SpiritDamage.Start(); FarmUpgradeRegistration.Start(); DeerRegistration.Start(); FarmTrough.Start(); FarmAnimalSounds.Start(); CenterMessageWrap.Start(); FarmAnimalDrawing.Start(); FarmHerdCollisions.Start(); FarmHerdCalm.Start(); FieldRune.Start(); LightningRune.Start(); SerpentDepot.Start(); VaultRegistration.Start(); SerpentCartography.Initialize(); SerpentPatches.Start(); SerpentLure.StartPatches(); SerpentCargoPanel.StartPatches(); SerpentRecovery.Start(); PlantingRegistration.Start(); BerryRegistration.Start(); HaulerRegistration.Start(); GeneralPatches.Start(); GeneralRegistration.Start(); HaulerInput.Start(); PlantHarvestPatches.Start(); PlantGrowth.StartPatches(); ContainerInputTiming.Start(); PlantTreePatches.Start(); PlantStorage.BlocksUnlink = PlantWork.BlocksUnlink; FarmCommandWand.Start(); WandBuildMode.Start(); LecternRegistration.Start(); ReevesBoardRegistration.Start(); FarmRecoveryRecord.StartRegistration(); FarmHarvestPatches.Start(); FarmInventoryPanel.StartPatches(); HaulerCargoPanel.StartPatches(); GeneralCargoPanel.StartPatches(); MiningRegistration.Start(); RenewalRune.Start(); MiningCargoPanel.StartPatches(); MiningPatches.Start(); VaultPatches.Start(); PostWork.EnableGate = MiningPost.WorkGate; ((Component)this).gameObject.AddComponent<MiningNetwork>(); ((Component)this).gameObject.AddComponent<MiningMapRing>(); ((Component)this).gameObject.AddComponent<WorkerWatchReport>(); ((Component)this).gameObject.AddComponent<WorkerWatchMap>(); ((Component)this).gameObject.AddComponent<HaulerMap>(); ((Component)this).gameObject.AddComponent<FarmHarvestNetwork>(); ((Component)this).gameObject.AddComponent<RuntimePerformance>(); ((Component)this).gameObject.AddComponent<HaulerNetwork>(); ((Component)this).gameObject.AddComponent<GeneralNetwork>(); ((Component)this).gameObject.AddComponent<ProgressionNetwork>(); ((Component)this).gameObject.AddComponent<ContentGate>(); ((Component)this).gameObject.AddComponent<SerpentNetwork>(); ((Component)this).gameObject.AddComponent<SerpentCatalogue>(); ((Component)this).gameObject.AddComponent<SerpentFleet>(); ((Component)this).gameObject.AddComponent<WorkerDirectory>(); ((Component)this).gameObject.AddComponent<SerpentMap>(); ((Component)this).gameObject.AddComponent<SerpentActivity>(); ((Component)this).gameObject.AddComponent<MiningActivity>(); ((Component)this).gameObject.AddComponent<HaulerActivity>(); AwayWork.Bind(((BaseUnityPlugin)this).Config); ((Component)this).gameObject.AddComponent<AwayWork>(); ((Component)this).gameObject.AddComponent<SerpentTravel>(); ((Component)this).gameObject.AddComponent<SerpentHover>(); ((Component)this).gameObject.AddComponent<SerpentLure>(); SerpentBody.OpenPanel = SerpentPanel.Open; SerpentBody.WandUsed = SerpentSelection.UseMounted; SerpentBody.CanBoard = delegate(ZDO z) { SerpentState serpentState = SerpentRecord.Read(z); return serpentState != null && serpentState.TravelMode == SerpentState.Mode.Passenger && !serpentState.HasCargo && !serpentState.Pending && !serpentState.Dead; }; SerpentNetwork.Tamed = SerpentVisual.Strike; ((Component)this).gameObject.AddComponent<HaulerFilterButton>(); ((Component)this).gameObject.AddComponent<VaultWindow>(); ((Component)this).gameObject.AddComponent<WorkerSelectionVisual>(); ((Component)this).gameObject.AddComponent<WandAreaPreview>(); ((Component)this).gameObject.AddComponent<FarmStorageNetwork>(); ((Component)this).gameObject.AddComponent<FarmSpiritNetwork>(); ((Component)this).gameObject.AddComponent<FarmSettingsNetwork>(); ((Component)this).gameObject.AddComponent<PlantingSettingsNetwork>(); ((Component)this).gameObject.AddComponent<FarmCensusNetwork>(); ((Component)this).gameObject.AddComponent<FarmBreedingNetwork>(); FarmBreedingPatches.Start(); FarmAnimalTiming.StartPatches(); FarmAttachment.StartPatches(); HaulerAttachment.StartPatches(); HaulerRelay.StartPatches(); PostSpacing.StartPatches(); MiningAttachment.StartPatches(); FarmStarFood.StartPatches(); FarmBoarVisuals.StartPatches(); ((Component)this).gameObject.AddComponent<FarmStarFood>(); TestFieldTerrain.Start(); ProgressionRecord.StartRegistration(); ProgressionPatches.Start(); ContentGate.StartPatches(); PieceManager.OnPiecesRegistered += WorkGates.LogMissing; DevConsole.Start(((BaseUnityPlugin)this).Config); } private void OnDestroy() { FarmPostRegistration.Stop(); ProgressionRecord.StopRegistration(); ProgressionPatches.Stop(); ContentGate.StopPatches(); PieceManager.OnPiecesRegistered -= WorkGates.LogMissing; FarmSpiritRegistration.Stop(); SpiritDamage.Stop(); FarmUpgradeRegistration.Stop(); DeerRegistration.Stop(); FarmTrough.Stop(); FarmAnimalSounds.Stop(); CenterMessageWrap.Stop(); FarmAnimalDrawing.Stop(); FarmHerdCollisions.Stop(); FarmHerdCalm.Stop(); FieldRune.Stop(); LightningRune.Stop(); SerpentDepot.Stop(); VaultRegistration.Stop(); SerpentCartography.Shutdown(); SerpentPatches.Stop(); SerpentLure.StopPatches(); SerpentCargoPanel.StopPatches(); SerpentRecovery.Stop(); SerpentSelection.Cancel(); SerpentPanel.Close(); SerpentDepotPanel.Close(); SerpentBody.OpenPanel = null; SerpentBody.WandUsed = null; SerpentBody.CanBoard = null; SerpentNetwork.Tamed = null; PlantingRegistration.Stop(); BerryRegistration.Stop(); HaulerRegistration.Stop(); GeneralRegistration.Stop(); GeneralPatches.Stop(); GeneralSelection.Cancel(); HaulerInput.Stop(); HaulerSelection.Cancel(); PlantHarvestPatches.Stop(); PlantGrowth.StopPatches(); ContainerInputTiming.Stop(); PlantTreePatches.Stop(); PlantStorage.BlocksUnlink = null; FarmCommandWand.Stop(); WandBuildMode.Stop(); LecternRegistration.Stop(); LecternWindow.Close(); ReevesBoardRegistration.Stop(); ReevesBoardWindow.Close(); FarmRecoveryRecord.StopRegistration(); FarmHarvestPatches.Stop(); FarmInventoryPanel.StopPatches(); HaulerCargoPanel.StopPatches(); GeneralCargoPanel.StopPatches(); MiningRegistration.Stop(); RenewalRune.Stop(); MiningCargoPanel.StopPatches(); MiningPatches.Stop(); VaultPatches.Stop(); MiningExcavation.Unregister(); MiningSelection.Cancel(); MiningPanel.Close(); PostWork.EnableGate = null; FarmBreedingPatches.Stop(); FarmAnimalTiming.StopPatches(); FarmAttachment.StopPatches(); HaulerAttachment.StopPatches(); HaulerRelay.StopPatches(); PostSpacing.StopPatches(); MiningAttachment.StopPatches(); FarmStarFood.StopPatches(); FarmBoarVisuals.StopPatches(); DevConsole.Stop(); TestFieldTerrain.Stop(); } } } namespace Runebourne.Vault { internal sealed class VaultChest : MonoBehaviour { internal const string IdentityKey = "runebourne.vault.identity.v1"; internal const string ItemKey = "runebourne.vault.item.v1"; internal const string LevelKey = "runebourne.vault.level.v1"; internal const string StoredKey = "runebourne.vault.stored.v1"; internal const string CapacityKey = "runebourne.vault.capacity.v1"; private const string ClearRpc = "Runebourne_VaultClear"; internal static readonly List<VaultChest> Loaded = new List<VaultChest>(); private readonly Guid settler = Guid.NewGuid(); private ZNetView view; private Container chest; private float nextCapacity; private float nextNudge; internal Container Chest => chest; internal ZDO Zdo { get { if (!Object.op_Implicit((Object)(object)view) || !view.IsValid()) { return null; } return view.GetZDO(); } } internal string Item { get { ZDO zdo = Zdo; return ((zdo != null) ? zdo.GetString("runebourne.vault.item.v1", "") : null) ?? ""; } } internal int ItemLevel { get { ZDO zdo = Zdo; if (zdo == null) { return 0; } return zdo.GetInt("runebourne.vault.level.v1", 0); } } internal long Stored { get { long val = 0L; ZDO zdo = Zdo; return Math.Max(val, (zdo != null) ? zdo.GetLong("runebourne.vault.stored.v1", 0L) : 0); } } internal int CapacityStacks { get { ZDO zdo = Zdo; if (zdo == null) { return VaultRules.LevelStacks[0]; } return zdo.GetInt("runebourne.vault.capacity.v1", VaultRules.LevelStacks[0]); } } internal string Identity { get { ZDO zdo = Zdo; return ((zdo != null) ? zdo.GetString("runebourne.vault.identity.v1", "") : null) ?? ""; } } internal GameObject ItemPrefab { get { if (Item.Length <= 0 || !Object.op_Implicit((Object)(object)ObjectDB.instance)) { return null; } return ObjectDB.instance.GetItemPrefab(Item); } } internal int StackSize { get { GameObject itemPrefab = ItemPrefab; if (!Object.op_Implicit((Object)(object)itemPrefab)) { return 1; } return Math.Max(1, itemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxStackSize); } } private long SlotAmount { get { if (!Object.op_Implicit((Object)(object)chest) || chest.GetInventory() == null) { return 0L; } return ((IEnumerable<ItemData>)chest.GetInventory().GetAllItems()).Sum((Func<ItemData, long>)((ItemData i) => i.m_stack)); } } internal long Total => SlotAmount + Stored; internal static VaultChest For(Container container) { if (!Object.op_Implicit((Object)(object)container)) { return null; } return ((Component)container).GetComponent<VaultChest>(); } internal static VaultChest For(Inventory inventory) { if (inventory == null) { return null; } foreach (VaultChest item in Loaded) { if (Object.op_Implicit((Object)(object)item) && Object.op_Implicit((Object)(object)item.chest) && item.chest.GetInventory() == inventory) { return item; } } return null; } private void Awake() { view = ((Component)this).GetComponent<ZNetView>(); chest = ((Component)this).GetComponent<Container>(); if (Object.op_Implicit((Object)(object)view) && view.IsValid() && !view.m_ghost && Object.op_Implicit((Object)(object)chest)) { view.Register("Runebourne_VaultClear", (Action<long>)RpcClear); Loaded.Add(this); ((MonoBehaviour)this).InvokeRepeating("Settle", 1f, 1f); } } private void OnDestroy() { ((MonoBehaviour)this).CancelInvoke(); Loaded.Remove(this); } internal bool Matches(ItemData item) { if (item != null && Object.op_Implicit((Object)(object)item.m_dropPrefab)) { return VaultRules.Matches(((Object)item.m_dropPrefab).name, item.m_worldLevel, item.m_quality, item.m_customData?.Count ?? 0, Item, ItemLevel); } return false; } internal string ItemName() { GameObject itemPrefab = ItemPrefab; if (!Object.op_Implicit((Object)(object)itemPrefab) || Localization.instance == null) { return Item; } return Localization.instance.Localize(itemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name); } internal string Title() { return VaultRules.Title((Item.Length > 0) ? ItemName() : null, Total, CapacityStacks, StackSize); } internal string WindowLine() { return VaultRules.WindowLine((Item.Length > 0) ? ItemName() : null, Total, CapacityStacks, StackSize); } internal void Nudge() { Inventory val = (Object.op_Implicit((Object)(object)chest) ? chest.GetInventory() : null); if (val != null && !(Time.time < nextNudge) && Item.Length != 0 && (val.GetItemAt(0, 0)?.m_stack ?? 0) < Math.Min(StackSize, Total)) { nextNudge = Time.time + 0.2f; Settle(); } } internal bool MayPut(ItemData item, out string refusal) { refusal = null; ZDO zdo = Zdo; if (zdo == null || item == null || !Object.op_Implicit((Object)(object)item.m_dropPrefab)) { refusal = "The Deephold isn't ready; open it again"; return false; } if (!VaultRules.Qualifies(item.m_shared.m_maxStackSize, item.m_quality, item.m_customData?.Count ?? 0)) { refusal = "A Deephold holds only plain stackable items"; return false; } if (Item.Length == 0) { if (!view.IsOwner()) { refusal = "Open the Deephold again"; return false; } if (!VaultRules.Empty(chest.GetInventory().NrOfItems(), Stored)) { refusal = "Empty the Deephold first"; return false; } zdo.Set("runebourne.vault.item.v1", ((Object)item.m_dropPrefab).name); zdo.Set("runebourne.vault.level.v1", item.m_worldLevel); return true; } if (!Matches(item)) { refusal = "This Deephold holds only " + ItemName(); return false; } int stackSize = StackSize; int capacityStacks = CapacityStacks; if (!VaultRules.Accepts(itemSet: true, Total, VaultRules.Capacity(capacityStacks, stackSize), Stored, VaultRules.StoreLimit(capacityStacks, stackSize))) { refusal = "This Deephold is full"; return false; } return true; } private unsafe void Settle() { //IL_023e: 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) ZDO zdo = Zdo; Inventory val = (Object.op_Implicit((Object)(object)chest) ? chest.GetInventory() : null); if (zdo == null || !view.IsOwner() || val == null) { return; } if (zdo.GetString("runebourne.vault.identity.v1", "").Length == 0) { zdo.Set("runebourne.vault.identity.v1", Guid.NewGuid().ToString("N")); } if (Time.time >= nextCapacity) { nextCapacity = Time.time + 2f; RefreshCapacity(zdo); } if (WorkerResources.Prepared(zdo) || Dragging()) { return; } GameObject itemPrefab = ItemPrefab; bool flag = Item.Length > 0 && Object.op_Implicit((Object)(object)itemPrefab); if (Item.Length == 0 && Stored == 0L && VaultFill.Adopt(val.GetAllItems(), out var prefab, out var level)) { zdo.Set("runebourne.vault.item.v1", prefab); zdo.Set("runebourne.vault.level.v1", level); itemPrefab = ItemPrefab; flag = Item.Length > 0 && Object.op_Implicit((Object)(object)itemPrefab); } if (flag) { if (val.GetAllItems().Any((ItemData i) => !Matches(i))) { WriteFilter(zdo, accepts: false); return; } int[] array = new int[24]; foreach (ItemData allItem in val.GetAllItems()) { int num = allItem.m_gridPos.y * 8 + allItem.m_gridPos.x; if (allItem.m_gridPos.x < 0 || allItem.m_gridPos.x >= 8 || num < 0 || num >= 24 || array[num] != 0) { return; } array[num] = allItem.m_stack; } int stackSize = StackSize; long stored = Stored; int[] array2; long newStore; try { array2 = VaultRules.Layout(array, stored, stackSize, VaultRules.StoreLimit(CapacityStacks, stackSize), out newStore); } catch (Exception ex) when (ex is ArgumentException || ex is InvalidOperationException) { ZDOID uid = zdo.m_uid; Logger.LogWarning((object)("Deephold " + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString() + " not settled: " + ex.Message)); WriteFilter(zdo, accepts: false); return; } if (newStore != stored || !array2.SequenceEqual(array)) { Apply(zdo, val, itemPrefab, array, array2, stored, newStore); } } int capacityStacks = CapacityStacks; int stackSize2 = StackSize; WriteFilter(zdo, VaultRules.Accepts(flag, Total, VaultRules.Capacity(capacityStacks, stackSize2), Stored, VaultRules.StoreLimit(capacityStacks, stackSize2))); } private bool Dragging() { InventoryGui instance = InventoryGui.instance; if (Object.op_Implicit((Object)(object)instance) && (Object)(object)instance.m_currentContainer == (Object)(object)chest) { if (instance.m_dragItem == null) { return instance.m_splitItem != null; } return true; } return false; } private unsafe void Apply(ZDO zdo, Inventory inventory, GameObject prefab, int[] slots, int[] target, long stored, long store) { //IL_005a: 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) if (((IEnumerable<int>)slots).Sum((Func<int, long>)((int n) => n)) + stored != ((IEnumerable<int>)target).Sum((Func<int, long>)((int n) => n)) + store) { ZDOID uid = zdo.m_uid; Logger.LogError((object)("Deephold " + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString() + " settle would change its total; nothing written")); return; } Dictionary<int, ItemData> dictionary = new Dictionary<int, ItemData>(); for (int num = 0; num < 24; num++) { if (target[num] > 0 && inventory.GetItemAt(num % 8, num / 8) == null) { dictionary[num] = NewStack(prefab, target[num], num % 8, num / 8); } } Guid operation = Guid.NewGuid(); if (!WorkerResources.TryAcquire(zdo, settler, operation, ZNet.instance.GetTime().Ticks + 50000000)) { return; } FarmHarvestWork.Mutating.Add(chest); try { List<ItemData> allItems = inventory.GetAllItems(); for (int num2 = 0; num2 < 24; num2++) { ItemData itemAt = inventory.GetItemAt(num2 % 8, num2 / 8); if (target[num2] == 0) { if (itemAt != null) { allItems.Remove(itemAt); } } else if (itemAt != null) { itemAt.m_stack = target[num2]; } else { allItems.Add(dictionary[num2]); } } zdo.Set("runebourne.vault.stored.v1", store); } finally { FarmHarvestWork.Mutating.Remove(chest); WorkerResources.Release(zdo, settler, operation); } inventory.Changed(false, false); chest.Save(); } private ItemData NewStack(GameObject prefab, int amount, int x, int y) { //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) ItemData obj = prefab.GetComponent<ItemDrop>().m_itemData.Clone(); obj.m_dropPrefab = prefab; obj.m_stack = amount; obj.m_worldLevel = ItemLevel; obj.m_gridPos = new Vector2i(x, y); return obj; } private void WriteFilter(ZDO zdo, bool accepts) { HaulerFilter haulerFilter = VaultRules.Filter(Item, accepts); HaulerFilter haulerFilter2 = HaulerFilter.Read(zdo.GetByteArray("runebourne.chest.hauler.filter.v1", (byte[])null)); if (haulerFilter2 == null || !haulerFilter2.SameRules(haulerFilter)) { haulerFilter.Revision = ((haulerFilter2 == null || haulerFilter2.Revision == long.MaxValue) ? 1 : (haulerFilter2.Revision + 1)); zdo.Set("runebourne.chest.hauler.filter.v1", haulerFilter.Serialize()); } } private void RefreshCapacity(ZDO zdo) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) string identity = zdo.GetString("runebourne.vault.identity.v1", ""); if (identity.Length == 0) { return; } List<int> list = new List<int>(); List<ZDO> list2 = new List<ZDO>(); for (int i = 0; i < VaultRegistration.UpgradeNames.Length; i++) { if (FarmCensus.CollectPrefab(((Component)this).transform.position, 5f, StringExtensionMethods.GetStableHashCode(VaultRegistration.UpgradeNames[i]), list2) != FarmCensus.State.Ready) { return; } if (list2.Any((ZDO r) => r != null && r.IsValid() && r.GetString("runebourne.vault.upgrade.vault.v1", "") == identity)) { list.Add(i + 1); } } int num = VaultRules.CapacityStacks(VaultRules.BestLevel(list)); if (zdo.GetInt("runebourne.vault.capacity.v1", VaultRules.LevelStacks[0]) != num) { zdo.Set("runebourne.vault.capacity.v1", num); } } internal void RequestClear() { if (Zdo != null) { view.InvokeRPC("Runebourne_VaultClear", Array.Empty<object>()); } } private void RpcClear(long sender) { ZDO zdo = Zdo; if (zdo != null && view.IsOwner() && Object.op_Implicit((Object)(object)chest) && VaultRules.Empty(chest.GetInventory().NrOfItems(), Stored)) { zdo.Set("runebourne.vault.item.v1", ""); zdo.Set("runebourne.vault.level.v1", 0); WriteFilter(zdo, accepts: false); } } } internal static class VaultFill { internal static bool Open(ZDO z, Inventory inventory) { if (VaultHint.Unset(z) && inventory != null && inventory.NrOfItems() == 0) { return z.GetLong("runebourne.vault.stored.v1", 0L) <= 0; } return false; } internal static bool Qualifies(ItemData item) { if (item != null && Object.op_Implicit((Object)(object)item.m_dropPrefab) && item.m_shared != null) { return VaultRules.Qualifies(item.m_shared.m_maxStackSize, item.m_quality, item.m_customData?.Count ?? 0); } return false; } internal static HaulerFilter Filter(ZDO z, Inventory inventory, IEnumerable<ItemData> items) { if (!Open(z, inventory)) { return WorkerChestFilter.Read(z); } ItemData val = items.FirstOrDefault((Func<ItemData, bool>)Qualifies); HaulerFilter haulerFilter = new HaulerFilter { SelectedOnly = true }; if (val != null) { haulerFilter.Items.Add(((Object)val.m_dropPrefab).name); } return haulerFilter; } internal static bool Adopt(IList<ItemData> items, out string prefab, out int level) { prefab = null; level = 0; if (items == null || items.Count == 0 || !items.All(Qualifies)) { return false; } string name = ((Object)items[0].m_dropPrefab).name; int world = items[0].m_worldLevel; if (items.Any((ItemData i) => ((Object)i.m_dropPrefab).name != name || i.m_worldLevel != world)) { return false; } prefab = name; level = world; return true; } } internal static class VaultHint { internal const string NoItem = "The Deephold has no item yet. Put one in to choose it."; internal const string WandNote = "Workers skip this Deephold until it has an item. Put one in to choose it."; internal const string Row = "No item yet: put one in to choose it"; private static int prefab; private static int Prefab { get { if (prefab == 0) { return prefab = StringExtensionMethods.GetStableHashCode("Runebourne_Vault"); } return prefab; } } internal static bool Unset(ZDO zdo) { if (zdo != null && zdo.IsValid() && zdo.GetPrefab() == Prefab) { return zdo.GetString("runebourne.vault.item.v1", "").Length == 0; } return false; } internal static bool Unset(Container chest) { ZNetView val = (Object.op_Implicit((Object)(object)chest) ? ((Component)chest).GetComponent<ZNetView>() : null); if (Object.op_Implicit((Object)(object)val) && val.IsValid()) { return Unset(val.GetZDO()); } return false; } internal static bool Deephold(int linkPrefab) { return linkPrefab == Prefab; } internal static string Explain(string status, int unset, int tried) { if (unset > 0) { if (unset < tried) { return Join(status, "The Deephold has no item yet. Put one in to choose it."); } return "The Deephold has no item yet. Put one in to choose it."; } return status; } internal static string Join(string status, string hint) { return status.TrimEnd('.', ' ') + ". " + hint; } internal static bool Means(string status, string key) { if (!(status == key) && !(status == "The Deephold has no item yet. Put one in to choose it.")) { return status == Join(key, "The Deephold has no item yet. Put one in to choose it."); } return true; } internal static void Wand(Container chest) { if (Unset(chest) && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { ((Character)Player.m_localPlayer).Message((MessageType)1, "Workers skip this Deephold until it has an item. Put one in to choose it.", 0, (Sprite)null, false); } } } internal static class VaultPatches { private static Harmony patches; private static bool removing; internal static void Start() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Expected O, but got Unknown //IL_0168: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Expected O, but got Unknown //IL_0208: 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_022a: Expected O, but got Unknown //IL_022a: Expected O, but got Unknown //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Expected O, but got Unknown Stop(); patches = new Harmony("com.yohanb.runebourne.vault"); patches.Patch((MethodBase)AccessTools.Method(typeof(InventoryGrid), "DropItem", (Type[])null, (Type[])null), new HarmonyMethod(typeof(VaultPatches), "Drop", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); patches.Patch((MethodBase)AccessTools.Method(typeof(Inventory), "MoveItemToThis", new Type[2] { typeof(Inventory), typeof(ItemData) }, (Type[])null), new HarmonyMethod(typeof(VaultPatches), "Move", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); patches.Patch((MethodBase)AccessTools.Method(typeof(Inventory), "StackAll", (Type[])null, (Type[])null), new HarmonyMethod(typeof(VaultPatches), "StackAll", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); patches.Patch((MethodBase)AccessTools.Method(typeof(Container), "CanBeRemoved", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(VaultPatches), "Removable", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); patches.Patch((MethodBase)AccessTools.Method(typeof(Player), "RemovePiece", (Type[])null, (Type[])null), new HarmonyMethod(typeof(VaultPatches), "BeginRemove", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(VaultPatches), "EndRemove", (Type[])null), (HarmonyMethod)null); patches.Patch((MethodBase)AccessTools.Method(typeof(WearNTear), "ApplyDamage", (Type[])null, (Type[])null), new HarmonyMethod(typeof(VaultPatches), "Undamaged", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); patches.Patch((MethodBase)AccessTools.Method(typeof(Container), "GetHoverText", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(VaultPatches), "Hover", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); patches.Patch((MethodBase)AccessTools.Method(typeof(InventoryGui), "UpdateContainer", (Type[])null, (Type[])null), new HarmonyMethod(typeof(VaultPatches), "WindowReset", (Type[])null), new HarmonyMethod(typeof(VaultPatches), "WindowTitle", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); patches.Patch((MethodBase)AccessTools.Method(typeof(Player), "TryPlacePiece", (Type[])null, (Type[])null), new HarmonyMethod(typeof(VaultPatches), "Place", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } internal static void Stop() { Harmony obj = patches; if (obj != null) { obj.UnpatchSelf(); } patches = null; removing = false; } private static bool Drop(InventoryGrid __instance, Inventory fromInventory, ItemData item, int amount, Vector2i pos, ref bool __result) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = __instance.GetInventory(); if (inventory == null || fromInventory == null || inventory == fromInventory || item == null) { return true; } VaultChest vaultChest = VaultChest.For(inventory); VaultChest vaultChest2 = VaultChest.For(fromInventory); if (!Object.op_Implicit((Object)(object)vaultChest) && !Object.op_Implicit((Object)(object)vaultChest2)) { return true; } if (Object.op_Implicit((Object)(object)vaultChest)) { __result = false; if (!vaultChest.MayPut(item, out var refusal)) { FarmCommandWand.Say(refusal); return false; } Vector2i val = ((inventory.GetItemAt(pos.x, pos.y) == null) ? pos : inventory.FindEmptySlot(false)); if (val.x < 0) { FarmCommandWand.Say("The Deephold is still storing. Try again in a moment."); return false; } __result = inventory.MoveItemToThis(fromInventory, item, amount, val.x, val.y); return false; } ItemData itemAt = inventory.GetItemAt(pos.x, pos.y); if (itemAt != null && itemAt != item && item.m_stack == amount && (itemAt.m_shared.m_name != item.m_shared.m_name || (item.m_shared.m_maxQuality > 1 && itemAt.m_quality != item.m_quality) || itemAt.m_shared.m_maxStackSize == 1)) { __result = false; FarmCommandWand.Say("Drop it on an empty slot: a Deephold can't swap items"); return false; } return true; } private static bool Move(Inventory __instance, Inventory fromInventory, ItemData item) { if (__instance == fromInventory) { return true; } VaultChest vaultChest = VaultChest.For(__instance); if (!Object.op_Implicit((Object)(object)vaultChest) || vaultChest.MayPut(item, out var refusal)) { return true; } FarmCommandWand.Say(refusal); return false; } private static bool StackAll(Inventory __instance, Inventory fromInventory, bool message, ref int __result) { VaultChest vaultChest = VaultChest.For(__instance); if (!Object.op_Implicit((Object)(object)vaultChest)) { return true; } __result = 0; string refusal = null; if (vaultChest.Item.Length > 0) { foreach (ItemData item in fromInventory.GetAllItems().ToList()) { if (vaultChest.Matches(item) && (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || !((Humanoid)Player.m_localPlayer).IsItemEquiped(item))) { if (!vaultChest.MayPut(item, out refusal)) { break; } int stack = item.m_stack; if (__instance.AddItem(item)) { fromInventory.RemoveItem(item); __result += stack; } else { __result += stack - item.m_stack; } } } } if (message && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { ((Character)Player.m_localPlayer).Message((MessageType)2, (__result > 0) ? ("$msg_stackall " + __result) : (refusal ?? "$msg_stackall_none"), 0, (Sprite)null, false); } __instance.Changed(false, false); fromInventory.Changed(false, false); return false; } private static void Removable(Container __instance, ref bool __result) { VaultChest vaultChest = VaultChest.For(__instance); if (Object.op_Implicit((Object)(object)vaultChest) && !VaultRules.Empty(__instance.GetInventory().NrOfItems(), vaultChest.Stored)) { __result = false; if (removing && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { ((Character)Player.m_localPlayer).Message((MessageType)1, "Empty the Deephold first: it still holds " + vaultChest.Total.ToString("N0"), 0, (Sprite)null, false); } } } private static void BeginRemove() { removing = true; } private static Exception EndRemove(Exception __exception) { removing = false; return __exception; } private static bool Undamaged(WearNTear __instance, ref bool __result) { if (!Object.op_Implicit((Object)(object)__instance) || (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<VaultChest>()) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<VaultUpgrade>()))) { return true; } __result = false; return false; } private static void Hover(Container __instance, ref string __result) { VaultChest vaultChest = VaultChest.For(__instance); if (Object.op_Implicit((Object)(object)vaultChest) && !string.IsNullOrEmpty(__result)) { int num = __result.IndexOf('\n'); __result = vaultChest.Title() + ((num >= 0) ? __result.Substring(num) : ""); } } private static void WindowReset(InventoryGui __instance) { if (!Object.op_Implicit((Object)(object)VaultChest.For(__instance.m_currentContainer))) { VaultWindow.Unshape(__instance.m_containerGrid); } } private static void WindowTitle(InventoryGui __instance) { VaultChest vaultChest = VaultChest.For(__instance.m_currentContainer); if (Object.op_Implicit((Object)(object)vaultChest) && Object.op_Implicit((Object)(object)__instance.m_container) && ((Component)__instance.m_container).gameObject.activeInHierarchy) { if (Object.op_Implicit((Object)(object)__instance.m_containerName)) { __instance.m_containerName.text = VaultRules.WindowTitle(); } VaultWindow.Shape(__instance.m_containerGrid, vaultChest); } } private static bool Place(Player __instance, Piece __0, ref bool __result) { //IL_0034: 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_006b: Unknown result type (might be due to invalid IL or missing references) VaultUpgrade vaultUpgrade = (Object.op_Implicit((Object)(object)__0) ? ((Component)__0).GetComponent<VaultUpgrade>() : null); if (!Object.op_Implicit((Object)(object)vaultUpgrade)) { return true; } GameObject placementGhost = __instance.m_placementGhost; VaultChest vaultChest = (Object.op_Implicit((Object)(object)placementGhost) ? VaultUpgrade.Nearest(placementGhost.transform.position) : null); if (Object.op_Implicit((Object)(object)vaultChest) && (vaultChest.Identity.Length == 0 || !VaultUpgrade.Duplicate(vaultChest.Identity, vaultUpgrade.Level, ((Component)vaultChest).transform.position, ZDOID.None))) { return true; } __result = false; FarmCommandWand.Say(Object.op_Implicit((Object)(object)vaultChest) ? ("This Deephold already has a " + vaultUpgrade.GetHoverName()) : "Build it within 5 m of a Deephold"); return false; } } internal static class VaultRegistration { internal const string VaultName = "Runebourne_Vault"; internal static readonly string[] UpgradeNames = new string[3] { "Runebourne_VaultUpgrade1", "Runebourne_VaultUpgrade2", "Runebourne_VaultUpgrade3" }; internal static readonly string[] UpgradeTitles = new string[3] { "Silverdeep Stone", "Tarflame Pillar", "Svelgr Frame" }; internal static readonly (string Item, int Amount)[] VaultCost = new(string, int)[4] { ("FineWood", 10), ("ElderBark", 10), ("Iron", 6), ("SurtlingCore", 2) }; internal static readonly (string Item, int Amount)[][] UpgradeCosts = new(string, int)[3][] { new(string, int)[3] { ("Stone", 15), ("Silver", 6), ("Crystal", 3) }, new(string, int)[3] { ("FineWood", 10), ("BlackMetal", 8), ("Tar", 5) }, new(string, int)[4] { ("BlackMarble", 10), ("YggdrasilWood", 10), ("Eitr", 6), ("BlackCore", 1) } }; internal static string UpgradeEffect(int level) { if (level < 3) { return VaultRules.LevelStacks[level] + " stacks"; } return "unlimited"; } internal static void Start() { PrefabManager.OnVanillaPrefabsAvailable += Register; } internal static void Stop() { PrefabManager.OnVanillaPrefabsAvailable -= Register; } private static RequirementConfig[] Requirements((string Item, int Amount)[] cost) { return Array.ConvertAll(cost, (Converter<(string, int), RequirementConfig>)(((string Item, int Amount) c) => new RequirementConfig(c.Item, c.Amount, 0, true))); } private static void Register() { //IL_001b: 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_002b: 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_0041: 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) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Expected O, but got Unknown PrefabManager.OnVanillaPrefabsAvailable -= Register; CustomPiece val = new CustomPiece("Runebourne_Vault", "piece_chest", new PieceConfig { Name = "Deephold", Description = "Holds 75 stacks of one item, more with upgrades within 5 m. The first item put in picks it. Can't be damaged; empty it to remove it.", PieceTable = "Runebourne_WandPieces", Category = "Runebourne", Enabled = true, Requirements = Requirements(VaultCost) }); Container component = val.PiecePrefab.GetComponent<Container>(); component.m_name = "Deephold"; component.m_width = 8; component.m_height = 3; val.PiecePrefab.AddComponent<VaultChest>(); BlenderPieceVisual.Install(val.PiecePrefab, BlenderPieceVisual.Deephold); if (!PieceManager.Instance.AddPiece(val)) { throw new InvalidOperationException("Deephold registration failed"); } for (int i = 0; i < UpgradeNames.Length; i++) { CustomPiece val2 = new CustomPiece(UpgradeNames[i], "stone_pillar", new PieceConfig { Name = UpgradeTitles[i], Description = "A Deephold within 5 m holds " + UpgradeEffect(i + 1) + ". One per Deephold.", PieceTable = "Runebourne_WandPieces", Category = "Runebourne", Enabled = true, Requirements = Requirements(UpgradeCosts[i]) }); val2.PiecePrefab.AddComponent<VaultUpgrade>().Level = i + 1; BlenderPieceVisual.Install(val2.PiecePrefab, BlenderPieceVisual.DeepholdUpgrades[i]); if (!PieceManager.Instance.AddPiece(val2)) { throw new InvalidOperationException(UpgradeTitles[i] + " registration failed"); } } } } internal static class VaultRules { internal const string Name = "Deephold"; internal const int Width = 8; internal const int Height = 3; internal const int Slots = 24; internal const int TopSlots = 8; internal const int Unlimited = 0; internal const float Reach = 5f; internal static readonly int[] LevelStacks = new int[4] { 75, 200, 500, 0 }; internal static int CapacityStacks(int level) { if (level < 0 || level >= LevelStacks.Length) { return LevelStacks[0]; } return LevelStacks[level]; } internal static int BestLevel(IEnumerable<int> levels) { return levels?.Where((int l) => l >= 1 && l < LevelStacks.Length).DefaultIfEmpty(0).Max() ?? 0; } internal static long Capacity(int stacks, int stackSize) { if (stacks != 0) { return (long)stacks * (long)Math.Max(1, stackSize); } return long.MaxValue; } internal static long StoreLimit(int stacks, int stackSize) { if (stacks != 0) { return Math.Max(0L, (long)(stacks - 24) * (long)Math.Max(1, stackSize)); } return long.MaxValue; } internal static int[] Layout(int[] slots, long store, int stackSize, long storeLimit, out long newStore) { if (slots == null || slots.Length != 24 || stackSize < 1 || store < 0) { throw new ArgumentException("Bad vault layout input"); } long num = 0L; long num2 = 0L; for (int i = 0; i < 24; i++) { if (slots[i] < 0) { throw new ArgumentException("Negative vault slot"); } if (i < 8) { num += slots[i]; } else { num2 += slots[i]; } } long num3 = Math.Max(0L, 8L * (long)stackSize - num); long num4 = Math.Min(num3, num2); num2 -= num4; num += num4; long num5 = Math.Min(num3 - num4, store); store -= num5; num += num5; long num6 = ((storeLimit == long.MaxValue) ? num2 : Math.Max(0L, Math.Min(num2, storeLimit - store))); num2 -= num6; store += num6; int[] array = new int[24]; Pack(array, 0, 8, num, stackSize); Pack(array, 8, 16, num2, stackSize); newStore = store; return array; } private static void Pack(int[] slots, int start, int count, long amount, int stackSize) { for (int i = 0; i < count; i++) { if (amount <= 0) { break; } amount -= (slots[start + i] = (int)Math.Min(stackSize, amount)); } if (amount > 0) { throw new InvalidOperationException("Vault slots overflow"); } } internal static bool Accepts(bool itemSet, long total, long capacity, long store, long storeLimit) { if (itemSet && total >= 0 && store >= 0 && total < capacity) { return store <= storeLimit; } return false; } internal static bool Qualifies(int maxStack, int quality, int customData) { if (maxStack > 1 && quality <= 1) { return customData == 0; } return false; } internal static bool Matches(string prefab, int worldLevel, int quality, int customData, string item, int itemLevel) { if (!string.IsNullOrEmpty(item) && prefab == item && worldLevel == itemLevel && quality <= 1) { return customData == 0; } return false; } internal static bool Empty(int slotItems, long store) { if (slotItems == 0) { return store == 0; } return false; } internal static string Title(string itemName, long total, int stacks, int stackSize) { if (string.IsNullOrEmpty(itemName)) { return "Deephold · empty, put an item in to choose it"; } string text = total.ToString("N0", CultureInfo.InvariantCulture); if (stacks == 0) { return "Deephold · " + itemName + " " + text + " (unlimited)"; } long num = Capacity(stacks, stackSize); return "Deephold · " + itemName + " " + text + " / " + num.ToString("N0", CultureInfo.InvariantCulture) + ((total > num) ? " · over capacity" : ((total == num) ? " · full" : "")); } internal static string WindowTitle() { return "Deephold"; } internal static string WindowLine(string itemName, long total, int stacks, int stackSize) { if (string.IsNullOrEmpty(itemName)) { return "Empty. Put an item in to choose what it holds."; } string text = total.ToString("N0", CultureInfo.InvariantCulture); if (stacks == 0) { return itemName + " · " + text + " · no limit"; } long num = Capacity(stacks, stackSize); return itemName + " · " + text + " / " + num.ToString("N0", CultureInfo.InvariantCulture) + ((total > num) ? " · over capacity" : ((total == num) ? " · full" : "")); } internal static string SlotCount(long total) { if (total >= 100000) { if (total >= 1000000) { if (total >= 10000000) { return (total / 1000000).ToString(CultureInfo.InvariantCulture) + "M"; } return ((double)(total / 100000) / 10.0).ToString("0.0", CultureInfo.InvariantCulture) + "M"; } return (total / 1000).ToString(CultureInfo.InvariantCulture) + "k"; } return total.ToString("N0", CultureInfo.InvariantCulture); } internal static HaulerFilter Filter(string item, bool accepts) { HaulerFilter haulerFilter = new HaulerFilter { SelectedOnly = true }; if (accepts && !string.IsNullOrEmpty(item)) { haulerFilter.Items.Add(item); } return haulerFilter; } } internal sealed class VaultUpgrade : MonoBehaviour, Hoverable { internal const string BindingKey = "runebourne.vault.upgrade.vault.v1"; [SerializeField] internal int Level; private ZNetView view; internal static readonly List<VaultUpgrade> Loaded = new List<VaultUpgrade>(); internal static readonly Color Color = new Color(1f, 0.72f, 0.25f, 1f); private void Awake() { view = ((Component)this).GetComponent<ZNetView>(); Loaded.Add(this); } private void Start() { ((MonoBehaviour)this).InvokeRepeating("Bind", 0.3f, 2f); } private void OnDestroy() { ((MonoBehaviour)this).CancelInvoke(); Loaded.Remove(this); } private void Bind() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)view) || !view.IsValid() || !view.IsOwner() || view.m_ghost || Level < 1 || Level > VaultRegistration.UpgradeNames.Length) { return; } ZDO zDO = view.GetZDO(); if (zDO.GetString("runebourne.vault.upgrade.vault.v1", "").Length > 0) { return; } Piece component = ((Component)this).GetComponent<Piece>(); if (!Object.op_Implicit((Object)(object)component) || component.GetCreator() == 0L) { return; } VaultChest vaultChest = Nearest(((Component)this).transform.position); if (!Object.op_Implicit((Object)(object)vaultChest)) { Reject(); return; } string identity = vaultChest.Identity; if (identity.Length != 0) { if (Duplicate(identity, Level, ((Component)vaultChest).transform.position, zDO.m_uid)) { Reject(); } else { zDO.Set("runebourne.vault.upgrade.vault.v1", identity); } } } private void Reject() { WearNTear component = ((Component)this).GetComponent<WearNTear>(); if (Object.op_Implicit((Object)(object)component)) { component.Destroy((HitData)null, false); } } internal VaultChest BoundVault() { string bound = ((Object.op_Implicit((Object)(object)view) && view.IsValid() && !view.m_ghost) ? view.GetZDO().GetString("runebourne.vault.upgrade.vault.v1", "") : ""); if (bound.Length != 0) { return VaultChest.Loaded.FirstOrDefault((VaultChest v) => Object.op_Implicit((Object)(object)v) && v.Identity == bound); } return null; } internal static Transform[] VisualTargets(VaultChest vault, VaultUpgrade ghost) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) List<Transform> list = (from u in Loaded where Object.op_Implicit((Object)(object)u) && ((Behaviour)u).isActiveAndEnabled && (Object)(object)u.BoundVault() == (Object)(object)vault select ((Component)u).transform).ToList(); if (Object.op_Implicit((Object)(object)ghost) && ((Component)ghost).gameObject.activeInHierarchy && (Object)(object)Nearest(((Component)ghost).transform.position) == (Object)(object)vault) { list.Add(((Component)ghost).transform); } return list.Distinct().Take(4).ToArray(); } internal static VaultChest Nearest(Vector3 position) { //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_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) VaultChest vaultChest = null; float num = 25f; foreach (VaultChest item in VaultChest.Loaded) { if (Object.op_Implicit((Object)(object)item) && item.Zdo != null) { Vector3 val = ((Component)item).transform.position - position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (!(sqrMagnitude > num) && (sqrMagnitude != num || !Object.op_Implicit((Object)(object)vaultChest) || string.CompareOrdinal(item.Identity, vaultChest.Identity) < 0)) { num = sqrMagnitude; vaultChest = item; } } } return vaultChest; } internal static bool Duplicate(string identity, int level, Vector3 near, ZDOID except) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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) List<ZDO> list = new List<ZDO>(); if (FarmCensus.CollectPrefab(near, 5f, StringExtensionMethods.GetStableHashCode(VaultRegistration.UpgradeNames[level - 1]), list) != FarmCensus.State.Ready) { return true; } return list.Any((ZDO z) => z != null && z.IsValid() && z.m_uid != except && z.GetString("runebourne.vault.upgrade.vault.v1", "") == identity); } public string GetHoverName() { if (Level < 1 || Level > VaultRegistration.UpgradeTitles.Length) { return "Deephold upgrade"; } return VaultRegistration.UpgradeTitles[Level - 1]; } public float GetHoverOffset() { return 0f; } public string GetHoverText() { string text = GetHoverName() + "\nA Deephold within 5 m holds " + VaultRegistration.UpgradeEffect(Level) + "."; string bound = ((Object.op_Implicit((Object)(object)view) && view.IsValid()) ? view.GetZDO().GetString("runebourne.vault.upgrade.vault.v1", "") : ""); if (bound.Length == 0) { return text + "\nNot connected — build it within 5 m of a Deephold"; } bool flag = VaultChest.Loaded.Any(delegate(VaultChest v) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)v) && v.Identity == bound) { Vector3 val = ((Component)v).transform.position - ((Component)this).transform.position; return ((Vector3)(ref val)).sqrMagnitude <= 25f; } return false; }); return text + (flag ? "" : "\nIts Deephold is gone; remove this to get the materials back"); } } internal sealed class VaultWindow : MonoBehaviour { private Button clear; private float next; private static InventoryGrid shaped; private static Text line; private void Update() { //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0137: 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_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) if (Time.unscaledTime < next || GUIManager.IsHeadless()) { return; } next = Time.unscaledTime + 0.25f; InventoryGui instance = InventoryGui.instance; VaultChest vaultChest = (Object.op_Implicit((Object)(object)instance) ? VaultChest.For(instance.m_currentContainer) : null); if (!Object.op_Implicit((Object)(object)vaultChest) || !Object.op_Implicit((Object)(object)instance.m_container) || !((Component)instance.m_container).gameObject.activeInHierarchy || vaultChest.Item.Length <= 0 || vaultChest.Total != 0) { if (Object.op_Implicit((Object)(object)clear)) { ((Component)clear).gameObject.SetActive(false); } return; } if (!Object.op_Implicit((Object)(object)clear) || (Object)(object)((Component)clear).transform.parent != (Object)(object)instance.m_container) { if (Object.op_Implicit((Object)(object)clear)) { Object.Destroy((Object)(object)((Component)clear).gameObject); } clear = HaulerUI.Button((Transform)(object)instance.m_container, "Clear item", 0f, -30f, 220f, Clear); RectTransform val = (RectTransform)((Component)clear).transform; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 0f); val.anchorMax = val2; val.anchorMin = val2; val.anchoredPosition = new Vector2(0f, -28f); } ((Component)clear).gameObject.SetActive(true); } private void Clear() { InventoryGui instance = InventoryGui.instance; VaultChest vaultChest = (Object.op_Implicit((Object)(object)instance) ? VaultChest.For(instance.m_currentContainer) : null); if (Object.op_Implicit((Object)(object)vaultChest)) { if (vaultChest.Total != 0L) { FarmCommandWand.Say("Empty the Deephold first"); return; } vaultChest.RequestClear(); FarmCommandWand.Say("Deephold cleared: put an item in to choose a new one"); } } private void OnDestroy() { if (Object.op_Implicit((Object)(object)clear)) { Object.Destroy((Object)(object)((Component)clear).gameObject); } } internal static void Shape(InventoryGrid grid, VaultChest vault) { //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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)grid) || grid.m_width != 8 || grid.m_height != 3 || grid.m_elements.Count != 24) { return; } shaped = grid; InventoryElement val = grid.m_elements[0]; float elementSpace = grid.m_elementSpace; Rect rect = ((RectTransform)((Component)grid).transform).rect; float num = ((Rect)(ref rect)).width / 2f - grid.GetWidgetSize().x / 2f; ((RectTransform)((Component)val).transform).anchoredPosition = new Vector2(num + 7f * elementSpace / 2f, 0f - elementSpace); for (int i = 1; i < grid.m_elements.Count; i++) { if (((Component)grid.m_elements[i]).gameObject.activeSelf) { ((Component)grid.m_elements[i]).gameObject.SetActive(false); } } if (vault.Chest.GetInventory().GetItemAt(0, 0) != null && Object.op_Implicit((Object)(object)val.m_amount)) { ((Behaviour)val.m_amount).enabled = true; val.m_amount.text = VaultRules.SlotCount(vault.Total); } if (!Object.op_Implicit((Object)(object)line) || (Object)(object)((Component)line).transform.parent != (Object)(object)((Component)val).transform) { if (Object.op_Implicit((Object)(object)line)) { Object.Destroy((Object)(object)((Component)line).gameObject); } Transform transform = ((Component)val).transform; rect = ((RectTransform)((Component)val).transform).rect; line = HaulerUI.Label(transform, "", 0f, (0f - ((Rect)(ref rect)).height) / 2f - 24f, 520f); line.alignment = (TextAnchor)4; } line.text = vault.WindowLine(); vault.Nudge(); } internal static void Unshape(InventoryGrid grid) { if (Object.op_Implicit((Object)(object)shaped) && !((Object)(object)shaped != (Object)(object)grid)) { shaped = null; grid.m_width = 0; if (Object.op_Implicit((Object)(object)line)) { Object.Destroy((Object)(object)((Component)line).gameObject); } } } } } namespace Runebourne.Serpents { internal static class LightningRune { internal const string Name = "RunebourneLightningRune"; private static Harmony patches; internal static void Start() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown PrefabManager.OnVanillaPrefabsAvailable += Register; patches = new Harmony("com.yohanb.runebourne.lightning.rune"); patches.Patch((MethodBase)AccessTools.Method(typeof(Humanoid), "UseItem", new Type[3] { typeof(Inventory), typeof(ItemData), typeof(bool) }, (Type[])null), new HarmonyMethod(typeof(LightningRune), "Use", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } internal static void Stop() { PrefabManager.OnVanillaPrefabsAvailable -= Register; Harmony obj = patches; if (obj != null) { obj.UnpatchSelf(); } patches = null; } private static void Register() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) PrefabManager.OnVanillaPrefabsAvailable -= Register; ItemConfig val = new ItemConfig(); val.Name = "Lightning rune"; val.Description = "Tames a wild sea serpent below 10% health within 50 m. Use it with the command wand equipped. Half of tries work; each uses a rune."; val.CraftingStation = "forge"; val.MinStationLevel = 1; val.Amount = 1; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig("Stone", 5, 0, true), new RequirementConfig("Iron", 1, 0, true), new RequirementConfig("GreydwarfEye", 3, 0, true) }; CustomItem val2 = new CustomItem("RunebourneLightningRune", "BoneFragments", val); ItemData itemData = val2.ItemPrefab.GetComponent<ItemDrop>().m_itemData; itemData.m_shared.m_itemType = (ItemType)1; itemData.m_shared.m_maxStackSize = 10; itemData.m_shared.m_weight = 0.2f; RunicItemVisual.Install(val2.ItemPrefab, BlenderPieceVisual.LightningRune); if (!ItemManager.Instance.AddItem(val2)) { throw new InvalidOperationException("Lightning rune registration failed"); } } private static bool Use(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui) { if ((Object)(object)item?.m_dropPrefab == (Object)null || ((Object)item.m_dropPrefab).name != "RunebourneLightningRune") { return true; } Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || (Object)(object)__instance != (Object)(object)localPlayer || ((Character)localPlayer).IsDead()) { return false; } if (!FarmCommandWand.IsWand(((Humanoid)localPlayer).GetRightItem())) { FarmCommandWand.Say("Equip the command wand first, then use the lightning rune."); return false; } Inventory inventory2 = ((Humanoid)localPlayer).GetInventory(); if ((inventory != null && inventory != inventory2) || !inventory2.GetAllItems().Contains(item) || item.m_stack < 1) { return false; } if (!Object.op_Implicit((Object)(object)SerpentNetwork.Instance)) { FarmCommandWand.Say("Serpent taming isn't ready yet. Try again in a moment."); return false; } SerpentNetwork.Instance.Request(new SerpentNetwork.Command { Action = SerpentNetwork.Action.Tame, X = item.m_gridPos.x, Y = item.m_gridPos.y, Data = FarmWorkerInventory.Signature(item) }); return false; } } internal sealed class SerpentActivity : MonoBehaviour { private sealed class Lease { internal Guid Key; internal ZDOID Subject; internal float Touched; internal bool Retain; internal bool Granted; internal bool Free; internal readonly HashSet<Vector2s> Sectors = new HashSet<Vector2s>(); internal readonly HashSet<ZDOID> Records = new HashSet<ZDOID>(); } internal const int SectorBudget = 32; internal const double SoftBudgetMs = 2.0; internal static SerpentActivity Instance; private readonly Dictionary<Guid, Lease> leases = new Dictionary<Guid, Lease>(); private readonly Dictionary<Vector2s, int> sectors = new Dictionary<Vector2s, int>(); private readonly Dictionary<Vector2s, int> budgeted = new Dictionary<Vector2s, int>(); private readonly HashSet<Vector2s> residents = new HashSet<Vector2s>(); private readonly Queue<Lease> waiting = new Queue<Lease>(); private readonly List<ZDO> retained = new List<ZDO>(); private readonly List<ZDO> terrain = new List<ZDO>(); private readonly HashSet<ZDOID> terrainIds = new HashSet<ZDOID>(); private readonly Dictionary<Vector2s, List<ZDO>> terrainWitnesses = new Dictionary<Vector2s, List<ZDO>>(); private readonly Dictionary<Vector2s, float> terrainAt = new Dictionary<Vector2s, float>(); private readonly Stopwatch timer = new Stopwatch(); private Harmony harmony; private ZNet world; private int cursor; internal double NativeMilliseconds { get; private set; } internal int ActiveSectors => BudgetCount(); internal int FreeSectors => sectors.Keys.Count((Vector2s s) => !budgeted.ContainsKey(s)); private void Awake() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown Instance = this; harmony = new Harmony("com.yohanb.runebourne.serpentactivity"); harmony.Patch((MethodBase)AccessTools.Method(typeof(ZNetScene), "RemoveObjects", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SerpentActivity), "KeepRequested", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } Clear(); } private void Clear() { leases.Clear(); sectors.Clear(); budgeted.Clear(); residents.Clear(); waiting.Clear(); retained.Clear(); terrainIds.Clear(); terrainWitnesses.Clear(); terrainAt.Clear(); cursor = 0; } internal bool Acquire(Guid key, ZDOID subject, Vector3 anchor, IEnumerable<ZDO> objects, bool retain, IEnumerable<Vector2s> sectors = null, bool budgeted = true) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: 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) if (key == Guid.Empty || !SerpentRoute.Point(anchor)) { return false; } if (!leases.TryGetValue(key, out var value)) { value = new Lease { Key = key, Subject = subject, Free = !budgeted }; value.Sectors.Add(ZoneSystem.GetZone(anchor)); leases.Add(key, value); if (value.Free) { Grant(value); } else { waiting.Enqueue(value); } } value.Touched = Time.unscaledTime; value.Retain = retain; foreach (ZDO @object in objects) { if (@object != null && @object.IsValid()) { Reserve(value, @object.GetSector()); value.Records.Add(@object.m_uid); } } if (sectors != null) { foreach (Vector2s sector in sectors) { Reserve(value, sector); } } return Ready(key); } private void Reserve(Lease lease, Vector2s sector) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (lease.Sectors.Contains(sector)) { return; } if (lease.Free) { lease.Sectors.Add(sector); if (lease.Granted) { Count(sectors, sector, 1); } return; } if (lease.Granted) { Unreserve(lease); waiting.Enqueue(lease); } lease.Sectors.Add(sector); } private static void Count(Dictionary<Vector2s, int> counts, Vector2s sector, int change) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) counts.TryGetValue(sector, out var value); value += change; if (value <= 0) { counts.Remove(sector); } else { counts[sector] = value; } } private void Grant(Lease lease) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) lease.Granted = true; foreach (Vector2s sector in lease.Sectors) { Count(sectors, sector, 1); if (!lease.Free) { Count(budgeted, sector, 1); } } } internal bool Ready(Guid key) { return Check(key, explain: false) == null; } internal string Blocker(Guid key) { return Check(key, explain: true); } private string Check(Guid key, bool explain) { //IL_010b: 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_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0127: 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_0156: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) if (!leases.TryGetValue(key, out var value)) { if (!explain) { return ""; } return "no lease"; } if (!value.Granted) { if (!explain) { return ""; } return "waiting its turn: " + (waiting.ToList().IndexOf(value) + 1) + " of " + waiting.Count + " in the queue, " + BudgetCount() + " of " + 32 + " zones in use, needs " + value.Sectors.Count; } if (!Object.op_Implicit((Object)(object)ZoneSystem.instance) || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { if (!explain) { return ""; } return "world not ready"; } foreach (Vector2s sector in value.Sectors) { if (Ungenerated(sector)) { continue; } object obj; if (!explain) { obj = null; } else { short x = sector.x; string text = x.ToString(); x = sector.y; obj = "zone " + text + "," + x; } string text2 = (string)obj; if (!ZoneSystem.instance.IsZoneLoaded(sector)) { return explain ? (text2 + (ZoneSystem.instance.m_zones.ContainsKey(sector) ? " still loading its objects" : " not loaded")) : ""; } if (!terrainWitnesses.TryGetValue(sector, out var value2)) { return explain ? (text2 + " ground edits not scanned yet") : ""; } foreach (ZDO item in value2) { if (item.IsValid() && !ZNetScene.instance.HaveInstance(item)) { return explain ? (text2 + " ground edit not created yet") : ""; } } } foreach (ZDOID record in value.Records) { ZDO zDO = ZDOMan.instance.GetZDO(record); if (zDO != null && zDO.IsValid() && !ZNetScene.instance.HaveInstance(zDO)) { if (!explain) { return ""; } GameObject prefab = ZNetScene.instance.GetPrefab(zDO.GetPrefab()); string[] obj2 = new string[9] { "not created: ", Object.op_Implicit((Object)(object)prefab) ? ((Object)prefab).name : ("prefab " + zDO.GetPrefab()), " at ", null, null, null, null, null, null }; Vector3 position = zDO.GetPosition(); obj2[3] = ((Vector3)(ref position)).ToString("0"); obj2[4] = " (zone "; obj2[5] = zDO.GetSector().x.ToString(); obj2[6] = ","; obj2[7] = zDO.GetSector().y.ToString(); obj2[8] = (ZoneSystem.instance.IsZoneLoaded(zDO.GetSector()) ? " loaded)" : " not loaded)"); return string.Concat(obj2); } } return null; } internal void Release(Guid key) { if (leases.TryGetValue(key, out var value) && !value.Retain) { Unreserve(value); leases.Remove(key); } } internal void Settle(Guid key) { if (leases.TryGetValue(key, out var value)) { value.Retain = false; } Release(key); } private void Unreserve(Lease lease) { //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) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!lease.Granted) { return; } foreach (Vector2s sector in lease.Sectors) { Count(sectors, sector, -1); if (!lease.Free) { Count(budgeted, sector, -1); } } lease.Granted = false; } internal static bool Fits(int active, int additional) { if (active >= 0 && additional >= 0) { return active + additional <= 32; } return false; } private int BudgetCount() { return budgeted.Count + residents.Count((Vector2s s) => !sectors.ContainsKey(s)); } internal bool GrantNext() { while (waiting.Count > 0) { Lease lease = waiting.Peek(); if (!leases.TryGetValue(lease.Key, out var value) || value != lease || lease.Granted) { waiting.Dequeue(); continue; } int additional = lease.Sectors.Count((Vector2s s) => !budgeted.ContainsKey(s) && (!residents.Contains(s) || sectors.ContainsKey(s))); if (!Fits(BudgetCount(), additional)) { return false; } waiting.Dequeue(); Grant(lease); return true; } return false; } private void Update() { //IL_008e: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0153: 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_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_03e0: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_053e: Unknown result type (might be due to invalid IL or missing references) //IL_05e1: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_0472: Unknown result type (might be due to invalid IL or missing references) //IL_0477: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_056e: Unknown result type (might be due to invalid IL or missing references) //IL_051d: Unknown result type (might be due to invalid IL or missing references) //IL_052c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)world != (Object)(object)ZNet.instance) { Clear(); world = ZNet.instance; } if (!Object.op_Implicit((Object)(object)world) || !world.IsServer() || !Object.op_Implicit((Object)(object)ZoneSystem.instance) || !Object.op_Implicit((Object)(object)ZNetScene.instance) || ZDOMan.instance == null) { return; } timer.Restart(); NativeMilliseconds = 0.0; Vector2s[] array = residents.ToArray(); foreach (Vector2s val in array) { if (!ZoneSystem.instance.m_zones.TryGetValue(val, out var value)) { residents.Remove(val); terrainAt.Remove(val); terrainWitnesses.Remove(val); } else if (!sectors.ContainsKey(val) && !PlayerArea(ZoneSystem.GetZonePos(val))) { value.m_ttl = Mathf.Max(value.m_ttl, ZoneSystem.instance.m_zoneTTL + 1f); } } KeyValuePair<Guid, Lease>[] array2 = leases.ToArray(); for (int i = 0; i < array2.Length; i++) { KeyValuePair<Guid, Lease> keyValuePair = array2[i]; Lease value2 = keyValuePair.Value; if (ZDOMan.instance.GetZDO(value2.Subject) == null || (!value2.Retain && Time.unscaledTime - value2.Touched > 3f)) { value2.Retain = false; Release(keyValuePair.Key); } } while (timer.Elapsed.TotalMilliseconds < 2.0 && GrantNext()) { } Vector2s[] array3 = sectors.Keys.ToArray(); bool flag = false; for (int j = 0; j < array3.Length; j++) { if (!(timer.Elapsed.TotalMilliseconds - NativeMilliseconds < 2.0)) { break; } Vector2s val2 = array3[(cursor + j) % array3.Length]; if (ZoneSystem.instance.m_zones.TryGetValue(val2, out var value3)) { value3.m_ttl = 0f; } else if (!flag && ZoneSystem.instance.IsZoneGenerated(val2)) { double totalMilliseconds = timer.Elapsed.TotalMilliseconds; ZoneSystem.instance.PokeLocalZone(val2); NativeMilliseconds += timer.Elapsed.TotalMilliseconds - totalMilliseconds; flag = true; if (ZoneSystem.instance.m_zones.ContainsKey(val2)) { residents.Add(val2); } } } if (array3.Length != 0) { cursor = (cursor + 1) % array3.Length; } retained.Clear(); terrainIds.Clear(); foreach (Lease value6 in leases.Values) { if (!value6.Granted) { continue; } foreach (ZDOID record in value6.Records) { ZDO zDO = ZDOMan.instance.GetZDO(record); if (zDO != null && zDO.IsValid()) { if (zDO.GetOwner() != ZNet.GetUID() && !PlayerArea(zDO.GetPosition())) { zDO.SetOwner(ZNet.GetUID()); ZDOMan.instance.ForceSendZDO(zDO.m_uid); } retained.Add(zDO); } } } bool flag2 = false; array = array3; foreach (Vector2s val3 in array) { if (!ZoneSystem.instance.IsZoneLoaded(val3)) { continue; } if (!flag2 && timer.Elapsed.TotalMilliseconds - NativeMilliseconds < 2.0 && (!terrainAt.TryGetValue(val3, out var value4) || Time.unscaledTime - value4 > 5f)) { flag2 = true; terrain.Clear(); double totalMilliseconds2 = timer.Elapsed.TotalMilliseconds; ZDOMan.instance.FindSectorObjects(val3, new SimulationDistance(0, 0, false), terrain, (List<ZDO>)null); NativeMilliseconds += timer.Elapsed.TotalMilliseconds - totalMilliseconds2; List<ZDO> list = new List<ZDO>(); foreach (ZDO item in terrain) { GameObject prefab = ZNetScene.instance.GetPrefab(item.GetPrefab()); if (Object.op_Implicit((Object)(object)prefab) && Object.op_Implicit((Object)(object)prefab.GetComponent<TerrainComp>())) { list.Add(item); } } terrainWitnesses[val3] = list; terrainAt[val3] = Time.unscaledTime; } if (!terrainWitnesses.TryGetValue(val3, out var value5)) { continue; } foreach (ZDO item2 in value5) { if (item2.IsValid() && terrainIds.Add(item2.m_uid)) { retained.Add(item2); } } } for (int k = 0; k < retained.Count; k++) { ZDO val4 = retained[(cursor + k) % retained.Count]; if (ZoneSystem.instance.IsZoneLoaded(val4.GetSector()) && !ZNetScene.instance.HaveInstance(val4)) { double totalMilliseconds3 = timer.Elapsed.TotalMilliseconds; ZNetScene.instance.CreateObject(val4); NativeMilliseconds += timer.Elapsed.TotalMilliseconds - totalMilliseconds3; break; } } timer.Stop(); } private static void KeepRequested(List<ZDO> currentNearObjects) { if (!Object.op_Implicit((Object)(object)Instance) || !Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { return; } foreach (ZDO item in Instance.retained) { if (item != null && item.IsValid()) { currentNearObjects.Add(item); } } AwayWork.Instance?.Keep(currentNearObjects); } internal static bool Ungenerated(Vector2s zone) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer() && Object.op_Implicit((Object)(object)ZoneSystem.instance)) { return !ZoneSystem.instance.IsZoneGenerated(zone); } return false; } internal static bool Ungenerated(Vector3 point) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Ungenerated(ZoneSystem.GetZone(point)); } internal static bool PlayerArea(Vector3 point) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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) if (!Object.op_Implicit((Object)(object)ZNet.instance) || !Object.op_Implicit((Object)(object)ZoneSystem.instance)) { return true; } if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && ZNetScene.InActiveArea(point, ZNet.instance.GetReferencePosition())) { return true; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { if (peer.IsReady() && peer.m_characterID != ZDOID.None && ZNetScene.InActiveArea(point, peer.GetRefPos())) { return true; } } return false; } } internal sealed class SerpentBody : MonoBehaviour, Interactable, Hoverable { internal sealed class HeightTrail { private readonly float[] times; private readonly float[] heights; private int count; private int next; internal int Count => count; internal HeightTrail(int size) { times = new float[Mathf.Max(2, size)]; heights = new float[times.Length]; } internal void Push(float time, float height) { if (float.IsNaN(time) || float.IsInfinity(time) || float.IsNaN(height) || float.IsInfinity(height)) { return; } int num = (next - 1 + times.Length) % times.Length; if (count > 0 && time <= times[num]) { heights[num] = height; return; } times[next] = time; heights[next] = height; next = (next + 1) % times.Length; if (count < times.Length) { count++; } } internal float At(float time, float nowTime, float nowHeight) { if (count == 0 || float.IsNaN(time) || time >= nowTime) { return nowHeight; } int num = (next - 1 + times.Length) % times.Length; float num2 = times[num]; float num3 = heights[num]; if (time >= num2) { if (!(nowTime - num2 > 1E-05f)) { return nowHeight; } return Mathf.Lerp(num3, nowHeight, (time - num2) / (nowTime - num2)); } for (int i = 1; i < count; i++) { int num4 = (num - i + times.Length) % times.Length; float num5 = times[num4]; float num6 = heights[num4]; if (time >= num5) { if (!(num2 - num5 > 1E-05f)) { return num3; } return Mathf.Lerp(num6, num3, (time - num5) / (num2 - num5)); } num2 = num5; num3 = num6; } return num3; } } internal const string Marker = "rb_serpent_tamed"; private const string BoardRpc = "Runebourne.Serpent.Board.v1"; private const string ReplyRpc = "Runebourne.Serpent.Seat.v1"; private const string ReleaseRpc = "Runebourne.Serpent.Leave.v1"; private const string ControlRpc = "Runebourne.Serpent.Control.v1"; private const string DriverKey = "rb_serpent_driver"; private const string PassengerKey = "rb_serpent_passenger"; private const float SeatRange = 12f; private const float LeaseSeconds = 5f; internal const float HealDelay = 20f; internal const float HealPerSecond = 0.02f; private const float LungeForce = 60f; private const float LungeCooldown = 1.2f; internal const float SeatHeight = 0.65f; internal const float BobSlot = 14f; internal const float BobSkip = 0.3f; internal const float BobMinLift = 0.75f; internal const float BobMaxLift = 1f; internal const float BobMinHold = 1f; internal const float BobMaxHold = 3f; internal const float BobRise = 1.2f; internal const float LeapApex = 1.5f; internal const float LeapDuration = 1.4f; internal const float LeapMaxSpeed = 25f; internal const float JumpCooldown = 2.5f; internal const float JumpWindow = 1.6f; internal const float TeleportDistance = 5f; internal const float SwimSpeed = 10f; internal const float RideSpeed = 17.5f; internal const float WaveMinSpeed = 3f; internal const float WavePitchMax = 35f; private static readonly int SerpentPrefab = StringExtensionMethods.GetStableHashCode("Serpent"); private static readonly int PlayerPrefab = StringExtensionMethods.GetStableHashCode("Player"); internal static readonly List<SerpentBody> Loaded = new List<SerpentBody>(); internal static Func<ZDO, bool> CanBoard; internal static Action<SerpentBody> OpenPanel; internal static Action<SerpentBody> WandUsed; private MonsterAI ai; private readonly float[] heartbeat = new float[2]; private Vector3 direction; private float controlTime; private float maintenance; private float requestUntil; private bool requestedPassenger; private bool ownerReady; private string requestToken; private long observedOwner; private long observedStrike; private float nextVisual; private Vector3 idleAnchor; private Vector3 shoreProbePosition; private Vector3 shoreProbeDirection; private float nextShoreProbe; private float shoreMessage; private float lastHealth = -1f; private float healAfter; private float lastRegen; private float nextLunge; private float slowSince; private float restDepth = -1f; private float bobPhase; private int bobSeed; private bool jumpRequested; private float nextJump; private float leapStart; private float leapUntil; private float leapFrom; private float leapTop; private Transform visual; private Vector3 visualRestPos; private Quaternion visualRestRot = Quaternion.identity; private Vector3 stepPos; private Quaternion stepRot = Quaternion.identity; private bool stepKnown; private bool smoothable; private readonly HeightTrail trail = new HeightTrail(320); private Transform[] spine; private float[] spineOffset; private Vector3[] boneWorldPos; private Vector3[] baseLocalPos; private Vector3[] writtenLocalPos; private Quaternion[] boneWorldRot; private Quaternion[] baseLocalRot; private Quaternion[] writtenLocalRot; private bool[] baseKnown; private GameObject[] travelHarness = Array.Empty<GameObject>(); private GameObject[] cargoHarness = Array.Empty<GameObject>(); private const float HoverSeconds = 1f; private string hoverText; private float hoverAt; internal ZNetView View { get; private set; } internal Character Character { get; private set; } internal bool HasRiders { get { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!(Rider(passenger: false) != ZDOID.None)) { return Rider(passenger: true) != ZDOID.None; } return true; } } internal long DriverPlayer { get { //IL_0016: Unknown result type (might be due to invalid IL or missing references) ZDOMan instance = ZDOMan.instance; long? obj; if (instance == null) { obj = null; } else { ZDO zDO = instance.GetZDO(Rider(passenger: false)); obj = ((zDO != null) ? new long?(zDO.GetLong(ZDOVars.s_playerID, 0L)) : ((long?)null)); } long? num = obj; return num.GetValueOrDefault(); } } internal SerpentMount Driver { get; private set; } internal SerpentMount Passenger { get; private set; } internal bool ShoreBlocked { get; private set; } internal bool ShoreUnloaded { get; private set; } internal bool InWaterForRoute() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return SerpentDepot.WaterPosition(((Component)this).transform.position); } internal static bool Marked(ZDO record) { if (record != null && record.GetPrefab() == SerpentPrefab) { return record.GetBool("rb_serpent_tamed", false); } return false; } internal static SerpentBody Ensure(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return null; } SerpentBody component = ((Component)character).GetComponent<SerpentBody>(); if (Object.op_Implicit((Object)(object)component)) { return component; } ZNetView component2 = ((Component)character).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)component2) || !Marked(component2.GetZDO())) { return null; } return ((Component)character).gameObject.AddComponent<SerpentBody>(); } private void Awake() { //IL_006a: 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_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Invalid comparison between Unknown and I4 //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) Character = ((Component)this).GetComponent<Character>(); View = ((Component)this).GetComponent<ZNetView>(); ai = ((Component)this).GetComponent<MonsterAI>(); if (!Object.op_Implicit((Object)(object)Character) || !Object.op_Implicit((Object)(object)View) || !Marked(View.GetZDO())) { ((Behaviour)this).enabled = false; return; } Driver = CreateSeat(passenger: false, new Vector3(0.6f, 0.65f, -1.4f)); Passenger = CreateSeat(passenger: true, new Vector3(-0.6f, 0.65f, -3.15f)); restDepth = Character.m_swimDepth; bobSeed = ((object)Unsafe.As<ZDOID, ZDOID>(ref View.GetZDO().m_uid)/*cast due to .constrained prefix*/).GetHashCode(); bobPhase = (float)Mathf.Abs(bobSeed % 1000) / 1000f * 14f; visual = (Object.op_Implicit((Object)(object)Character.GetVisual()) ? Character.GetVisual().transform : ((Component)this).transform.Find("Visual")); if (Object.op_Implicit((Object)(object)visual)) { visualRestPos = visual.localPosition; visualRestRot = visual.localRotation; } smoothable = Object.op_Implicit((Object)(object)visual) && (int)Character.m_groundTilt == 0; SkinnedMeshRenderer componentInChildren = ((Component)this).GetComponentInChildren<SkinnedMeshRenderer>(true); if (Object.op_Implicit((Object)(object)componentInChildren) && componentInChildren.bones != null) { Transform[] array = componentInChildren.bones.Where((Transform b) => Object.op_Implicit((Object)(object)b)).Distinct().OrderBy(Depth) .ToArray(); float snout = ((array.Length != 0) ? array.Max((Transform b) => ((Component)this).transform.InverseTransformPoint(b.position).z) : 0f); spine = array; spineOffset = array.Select((Transform b) => Mathf.Max(0f, snout - ((Component)this).transform.InverseTransformPoint(b.position).z)).ToArray(); boneWorldPos = (Vector3[])(object)new Vector3[array.Length]; boneWorldRot = (Quaternion[])(object)new Quaternion[array.Length]; } View.Register<ZDOID, long, bool, string>("Runebourne.Serpent.Board.v1", (Method<ZDOID, long, bool, string>)Board); View.Register<bool, bool, string>("Runebourne.Serpent.Seat.v1", (Action<long, bool, bool, string>)Reply); View.Register<ZDOID>("Runebourne.Serpent.Leave.v1", (Action<long, ZDOID>)Release); View.Register<ZDOID, Vector3>("Runebourne.Serpent.Control.v1", (Action<long, ZDOID, Vector3>)Control); idleAnchor = ((Component)this).transform.position; Loaded.Add(this); healAfter = Time.time + 20f; lastRegen = Time.time; SerpentTravel.Watch(View.GetZDO()); SerpentVisual.Apply(((Component)this).gameObject, out travelHarness, out cargoHarness); ShowHarness(); } private void ShowHarness() { bool flag = View.GetZDO().GetBool("rb_serpent_cargo", false); GameObject[] array = travelHarness; foreach (GameObject val in array) { if (Object.op_Implicit((Object)(object)val) && val.activeSelf == flag) { val.SetActive(!flag); } } array = cargoHarness; foreach (GameObject val2 in array) { if (Object.op_Implicit((Object)(object)val2) && val2.activeSelf != flag) { val2.SetActive(flag); } } } private SerpentMount CreateSeat(bool passenger, Vector3 position) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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) GameObject val = new GameObject(passenger ? "Runebourne passenger seat" : "Runebourne driver seat"); val.transform.SetParent(((Component)this).transform, false); val.transform.localPosition = position; SerpentVisual.MountAtRest(val.transform, ((Component)this).gameObject, position); SerpentMount serpentMount = val.AddComponent<SerpentMount>(); serpentMount.Body = this; serpentMount.Passenger = passenger; return serpentMount; } internal ZDOID Rider(bool passenger) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)View) || !View.IsValid()) { return ZDOID.None; } return View.GetZDO().GetZDOID(passenger ? "rb_serpent_passenger" : "rb_serpent_driver"); } private void SetRider(bool passenger, ZDOID id) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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) View.GetZDO().Set(passenger ? "rb_serpent_passenger" : "rb_serpent_driver", id); heartbeat[passenger ? 1u : 0u] = Time.unscaledTime; if (!passenger) { direction = Vector3.zero; jumpRequested = false; idleAnchor = ((Component)this).transform.position; if (Object.op_Implicit((Object)(object)ai) && id == ZDOID.None) { ((BaseAI)ai).SetPatrolPoint(); } } } internal static bool ActorWitness(ZDO actor, long sender, long player, Vector3 seat, float range) { //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) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (actor != null && sender != 0L && actor.GetOwner() == sender && actor.GetPrefab() == PlayerPrefab && player != 0L && actor.GetLong(ZDOVars.s_playerID, 0L) == player) { Vector3 val = actor.GetPosition() - seat; return ((Vector3)(ref val)).sqrMagnitude <= range * range; } return false; } private Player Actor(long sender, ZDOID id, long player, bool passenger, bool ward) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_00a4: Unknown result type (might be due to invalid IL or missing references) ZDOMan instance = ZDOMan.instance; ZDO actor = ((instance != null) ? instance.GetZDO(id) : null); SerpentMount serpentMount = (passenger ? Passenger : Driver); if (!Object.op_Implicit((Object)(object)serpentMount) || !ActorWitness(actor, sender, player, ((Component)serpentMount).transform.position, 12f)) { return null; } GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.FindInstance(id) : null); Player val2 = (Object.op_Implicit((Object)