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 ValkyriesHatchery v0.6.0
ValkyriesHatchery.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("ValkyriesHatchery")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ValkyriesHatchery")] [assembly: AssemblyTitle("ValkyriesHatchery")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ValkyriesHatchery { public enum ProgressionSource { World, Player } [BepInPlugin("com.drakexi.valkyrieshatchery", "Valkyrie's Hatchery", "0.6.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGUID = "com.drakexi.valkyrieshatchery"; public const string PluginName = "Valkyrie's Hatchery"; public const string PluginVersion = "0.6.0"; public static Plugin Instance; public static ConfigEntry<int> Slots; public static ConfigEntry<float> HatchMinutes; public static ConfigEntry<float> XpMultiplier; public static ConfigEntry<int> HomeBiomeChance; public static ConfigEntry<ProgressionSource> Progression; public static ConfigEntry<int> RoePrice; public static ConfigEntry<bool> ShowXpMessage; public static ConfigEntry<bool> PlayHatchSoundSetting; private const string PiecePrefabName = "piece_ValkyriesHatchery"; private const string DisplayName = "Valkyrie's Hatchery"; public const string RoePrefabName = "ValkyriesHatchery_Roe"; private static readonly Color DarkStain = new Color(0.45f, 0.36f, 0.3f, 1f); private static readonly Color CaviarBlack = new Color(0.12f, 0.12f, 0.14f, 1f); public static readonly string[] FishIds = new string[12] { "Fish1", "Fish2", "Fish3", "Fish4_cave", "Fish5", "Fish6", "Fish7", "Fish8", "Fish9", "Fish10", "Fish11", "Fish12" }; private static readonly string[] HatchSequence = new string[4] { "fx_float_nibble", "fx_float_hitwater", "fx_float_nibble", "fx_float_hitwater" }; private const float HatchSoundGap = 0.5f; private TradeItem _roeTrade; private void Awake() { Instance = this; BindConfig(); PrefabManager.OnVanillaPrefabsAvailable += AddHatcheryPiece; PrefabManager.OnVanillaPrefabsAvailable += AddRoe; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Valkyrie's Hatchery 0.6.0 loaded."); } private void BindConfig() { Slots = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "Slots", 12, Server("Storage slots in each hatchery. Hatcheries resize live; anything in removed slots is moved to a free slot or dropped in front of the hatchery.", (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[4] { 4, 6, 8, 12 }))); HatchMinutes = ((BaseUnityPlugin)this).Config.Bind<float>("Server", "HatchMinutes", 10f, Server("Real minutes for one roe to hatch into a fish.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 120f))); XpMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Server", "XpMultiplier", 1f, Server("Scales the Fishing XP for each fish collected (2 = double, 0 = none).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f))); HomeBiomeChance = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "HomeBiomeChance", 80, Server("Percent of hatches that are fish from the hatchery's own biome, when other fish are also unlocked.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100))); Progression = ((BaseUnityPlugin)this).Config.Bind<ProgressionSource>("Server", "ProgressionSource", ProgressionSource.World, Server("Which boss kills unlock other biomes' fish: World (the world's kills) or Player (the kills of the player whose game is running the hatchery).", null)); RoePrice = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "RoePrice", 10, Server("Haldor's price for one Fish Roe.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000))); ShowXpMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("Personal", "ShowXpMessage", true, "Show a message with the Fishing XP gained when you collect fish."); PlayHatchSoundSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("Personal", "PlayHatchSound", true, "Play the nibble-and-splash sound when a fish hatches."); RoePrice.SettingChanged += delegate { if (_roeTrade != null) { _roeTrade.m_price = RoePrice.Value; } }; } private static ConfigDescription Server(string text, AcceptableValueBase range) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown return new ConfigDescription(text, range, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } }); } public static Vector2Int GridFor(int slots) { //IL_0020: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) return (Vector2Int)(slots switch { 4 => new Vector2Int(4, 1), 6 => new Vector2Int(3, 2), 8 => new Vector2Int(4, 2), _ => new Vector2Int(4, 3), }); } private void AddHatcheryPiece() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) PrefabManager.OnVanillaPrefabsAvailable -= AddHatcheryPiece; PieceConfig val = new PieceConfig(); val.Name = "Valkyrie's Hatchery"; val.Description = "Fill it with roe, wait, and collect your fish."; val.PieceTable = "Hammer"; val.Category = "Crafting"; val.CraftingStation = "piece_workbench"; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig("Wood", 20, 0, true), new RequirementConfig("FineWood", 10, 0, true), new RequirementConfig("Stone", 8, 0, true) }; PieceConfig val2 = val; CustomPiece val3 = new CustomPiece("piece_ValkyriesHatchery", "piece_bathtub", val2); if ((Object)(object)val3.PiecePrefab == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Could not clone piece_bathtub."); return; } GameObject piecePrefab = val3.PiecePrefab; StripHotTubParts(piecePrefab); AddStorage(piecePrefab); TintRenderers(piecePrefab, DarkStain, "WaterSurface"); Transform val4 = piecePrefab.transform.Find("water"); if ((Object)(object)val4 != (Object)null) { ((Component)val4).gameObject.SetActive(false); } piecePrefab.AddComponent<HatcheryBrain>(); PieceManager.Instance.AddPiece(val3); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Added Valkyrie's Hatchery piece."); } private void StripHotTubParts(GameObject prefab) { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) Smelter component = prefab.GetComponent<Smelter>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } string[] array = new string[4] { "add_fuel", "SitPoints", "_Enabled/fire", "_Enabled/WarmAndCozy" }; foreach (string text in array) { Transform val = prefab.transform.Find(text); if ((Object)(object)val != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)val).gameObject); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Hatchery: part '" + text + "' not found on the hot tub clone.")); } } Piece component2 = prefab.GetComponent<Piece>(); if ((Object)(object)component2 != (Object)null) { component2.m_comfort = 0; component2.m_comfortObject = null; component2.m_category = (PieceCategory)1; component2.m_usage = (UsageTagFlags)2; } } private void AddStorage(GameObject prefab) { //IL_002d: 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) GameObject prefab2 = PrefabManager.Instance.GetPrefab("piece_chest_wood"); Container val = ((prefab2 != null) ? prefab2.GetComponent<Container>() : null); Container val2 = prefab.AddComponent<Container>(); Vector2Int val3 = GridFor(Slots.Value); val2.m_name = "Valkyrie's Hatchery"; val2.m_width = ((Vector2Int)(ref val3)).x; val2.m_height = ((Vector2Int)(ref val3)).y; if ((Object)(object)val != (Object)null) { val2.m_bkg = val.m_bkg; val2.m_openEffects = val.m_openEffects; val2.m_closeEffects = val.m_closeEffects; } } private static void TintRenderers(GameObject prefab, Color tint, string skipName = null) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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) Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if ((skipName != null && ((Object)((Component)val).transform).name == skipName) || val is ParticleSystemRenderer) { continue; } Material[] sharedMaterials = val.sharedMaterials; for (int j = 0; j < sharedMaterials.Length; j++) { if (!((Object)(object)sharedMaterials[j] == (Object)null) && sharedMaterials[j].HasProperty("_Color")) { Material val2 = new Material(sharedMaterials[j]); val2.color = sharedMaterials[j].color * tint; sharedMaterials[j] = val2; } } val.sharedMaterials = sharedMaterials; } } private void AddRoe() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) PrefabManager.OnVanillaPrefabsAvailable -= AddRoe; ItemConfig val = new ItemConfig { Name = "Fish Roe", Description = "Fish eggs, glistening and black. Place them in a Valkyrie's Hatchery to raise fish.", CraftingStation = "piece_preptable", Amount = 2, Requirements = ((IEnumerable<string>)FishIds).Select((Func<string, RequirementConfig>)((string id) => new RequirementConfig(id, 1, 0, true))).ToArray() }; CustomItem val2 = new CustomItem("ValkyriesHatchery_Roe", "HatefulBlood", val); if ((Object)(object)val2.ItemPrefab == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Could not clone HatefulBlood for roe."); return; } Renderer[] componentsInChildren = val2.ItemPrefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val3 in componentsInChildren) { Material[] sharedMaterials = val3.sharedMaterials; for (int num2 = 0; num2 < sharedMaterials.Length; num2++) { if (!((Object)(object)sharedMaterials[num2] == (Object)null) && sharedMaterials[num2].HasProperty("_Color")) { Material val4 = new Material(sharedMaterials[num2]); val4.color = sharedMaterials[num2].color * CaviarBlack; sharedMaterials[num2] = val4; } } val3.sharedMaterials = sharedMaterials; } SharedData shared = val2.ItemDrop.m_itemData.m_shared; shared.m_maxStackSize = 50; shared.m_weight = 0.1f; shared.m_teleportable = true; Sprite val5 = RenderManager.Instance.Render(val2.ItemPrefab, RenderManager.IsometricRotation); if ((Object)(object)val5 != (Object)null) { shared.m_icons = (Sprite[])(object)new Sprite[1] { val5 }; } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Hatchery: could not render roe icon; keeping the original."); } ItemManager.Instance.AddItem(val2); CustomRecipe recipe = val2.Recipe; if ((Object)(object)((recipe != null) ? recipe.Recipe : null) != (Object)null) { val2.Recipe.Recipe.m_requireOnlyOneIngredient = true; Recipe prefab = Cache.GetPrefab<Recipe>("Recipe_Fish1"); val2.Recipe.Recipe.m_qualityResultAmountMultiplier = (((Object)(object)prefab != (Object)null) ? prefab.m_qualityResultAmountMultiplier : 1f); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Hatchery: roe recipe was not created."); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Added Fish Roe."); AddRoeToHaldor(val2.ItemDrop); } private void AddRoeToHaldor(ItemDrop roeDrop) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown GameObject prefab = PrefabManager.Instance.GetPrefab("Haldor"); Trader val = ((prefab != null) ? prefab.GetComponent<Trader>() : null); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Hatchery: couldn't find Haldor; roe won't be sold."); return; } _roeTrade = ((IEnumerable<TradeItem>)val.m_items).FirstOrDefault((Func<TradeItem, bool>)((TradeItem t) => (Object)(object)t.m_prefab != (Object)null && ((Object)t.m_prefab).name == "ValkyriesHatchery_Roe")); if (_roeTrade == null) { _roeTrade = new TradeItem { m_prefab = roeDrop, m_stack = 1, m_price = RoePrice.Value }; val.m_items.Add(_roeTrade); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Added Fish Roe to Haldor's shop."); } public static void PlayHatchSound(Vector3 position) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Instance != (Object)null) { ((MonoBehaviour)Instance).StartCoroutine(HatchSoundRoutine(position)); } } private static IEnumerator HatchSoundRoutine(Vector3 position) { //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) string[] hatchSequence = HatchSequence; for (int i = 0; i < hatchSequence.Length; i++) { GameObject prefab = Cache.GetPrefab<GameObject>(hatchSequence[i]); if ((Object)(object)prefab != (Object)null) { Object.Instantiate<GameObject>(prefab, position, Quaternion.identity); } yield return (object)new WaitForSeconds(0.5f); } } public static void Log(string msg) { Plugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)msg); } } public static void Warn(string msg) { Plugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)msg); } } } public static class HatchRules { private class FishInfo { public string Id; public Biome Home; public string UnlockKey; public float Xp; public float Weight; public FishInfo(string id, Biome home, string key, float xp, float weight = 1f) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Id = id; Home = home; UnlockKey = key; Xp = xp; Weight = weight; } } private static readonly FishInfo[] Fish = new FishInfo[12] { new FishInfo("Fish1", (Biome)9, "defeated_eikthyr", 10f), new FishInfo("Fish2", (Biome)9, "defeated_eikthyr", 10f), new FishInfo("Fish5", (Biome)8, "defeated_gdking", 15f), new FishInfo("Fish6", (Biome)2, "defeated_bonemass", 20f), new FishInfo("Fish4_cave", (Biome)4, "defeated_dragon", 25f, 0.25f), new FishInfo("Fish7", (Biome)16, "defeated_goblinking", 25f), new FishInfo("Fish3", (Biome)256, "defeated_queen", 30f), new FishInfo("Fish8", (Biome)256, "defeated_queen", 30f), new FishInfo("Fish12", (Biome)768, "defeated_queen", 35f), new FishInfo("Fish9", (Biome)512, "defeated_queen", 35f), new FishInfo("Fish11", (Biome)32, "defeated_fader", 40f), new FishInfo("Fish10", (Biome)64, "defeated_frozenking_p3", 40f) }; public static float XpFor(string fishId) { return Fish.FirstOrDefault((FishInfo f) => f.Id == fishId)?.Xp ?? 10f; } public static string RollFish(Vector3 position, Func<string, bool> fits) { //IL_001d: 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_0023: Unknown result type (might be due to invalid IL or missing references) Biome biome = (Biome)((WorldGenerator.instance == null) ? 1 : ((int)WorldGenerator.instance.GetBiome(position))); List<FishInfo> list = Fish.Where((FishInfo f) => (f.Home & biome) != 0 && fits(f.Id)).ToList(); List<FishInfo> list2 = Fish.Where((FishInfo f) => (f.Home & biome) == 0 && KeySet(f.UnlockKey) && fits(f.Id)).ToList(); if (list.Count == 0 && list2.Count == 0) { if (Fish.Any((FishInfo f) => (f.Home & biome) > 0) || !fits("Fish1")) { return null; } return "Fish1"; } if (list.Count == 0) { return Pick(list2); } if (list2.Count == 0 || Random.Range(0, 100) < Plugin.HomeBiomeChance.Value) { return Pick(list); } return Pick(list2); } private static string Pick(List<FishInfo> pool) { float num = pool.Sum((FishInfo f) => f.Weight); float num2 = Random.Range(0f, num); foreach (FishInfo item in pool) { if (num2 < item.Weight) { return item.Id; } num2 -= item.Weight; } return pool[pool.Count - 1].Id; } private static bool KeySet(string key) { if (Plugin.Progression.Value == ProgressionSource.Player) { if ((Object)(object)Player.m_localPlayer != (Object)null) { return ((Humanoid)Player.m_localPlayer).HaveUniqueKey(key); } return false; } if ((Object)(object)ZoneSystem.instance != (Object)null) { return ZoneSystem.instance.GetGlobalKey(key); } return false; } } public class HatcheryBrain : MonoBehaviour { private const string StartKey = "hatchery_start_ticks"; private const string HatchRpc = "RPC_HatcheryHatch"; private static readonly FieldInfo InvWidth = typeof(Inventory).GetField("m_width", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly MethodInfo InvChanged = typeof(Inventory).GetMethod("Changed", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); private static readonly FieldInfo InvHeight = typeof(Inventory).GetField("m_height", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private ZNetView _nview; private Container _container; private GameObject _water; private GameObject _bubbles; private Dictionary<string, int> _fishCounts = new Dictionary<string, int>(); private bool _busy; private bool _checkQueued; private void Start() { _nview = ((Component)this).GetComponent<ZNetView>(); _container = ((Component)this).GetComponent<Container>(); Transform obj = ((Component)this).transform.Find("water"); _water = ((obj != null) ? ((Component)obj).gameObject : null); Transform obj2 = ((Component)this).transform.Find("_Enabled"); _bubbles = ((obj2 != null) ? ((Component)obj2).gameObject : null); if ((Object)(object)_nview == (Object)null || _nview.GetZDO() == null || (Object)(object)_container == (Object)null) { return; } _nview.Register("RPC_HatcheryHatch", (Action<long>)delegate { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (Plugin.PlayHatchSoundSetting.Value) { Plugin.PlayHatchSound(((Component)this).transform.position); } }); Inventory inventory = _container.GetInventory(); if (inventory != null) { _fishCounts = CountFish(inventory); inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(OnInventoryChanged)); } ((MonoBehaviour)this).InvokeRepeating("Tick", 1f, 1f); } private void Tick() { if ((Object)(object)_nview == (Object)null || !_nview.IsValid()) { return; } Inventory inventory = _container.GetInventory(); if (inventory != null) { ApplySlotCount(inventory); if (_nview.IsOwner()) { Hatch(inventory); } UpdateVisuals(inventory); } } private void ApplySlotCount(Inventory inv) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) Vector2Int grid = Plugin.GridFor(Plugin.Slots.Value); if ((inv.GetWidth() == ((Vector2Int)(ref grid)).x && inv.GetHeight() == ((Vector2Int)(ref grid)).y) || InvWidth == null || InvHeight == null || _container.IsInUse()) { return; } _container.m_width = ((Vector2Int)(ref grid)).x; _container.m_height = ((Vector2Int)(ref grid)).y; InvWidth.SetValue(inv, ((Vector2Int)(ref grid)).x); InvHeight.SetValue(inv, ((Vector2Int)(ref grid)).y); if (!_nview.IsOwner()) { return; } _busy = true; try { foreach (ItemData item in inv.GetAllItems().ToList()) { if (item.m_gridPos.x >= ((Vector2Int)(ref grid)).x || item.m_gridPos.y >= ((Vector2Int)(ref grid)).y) { Vector2i? val = FindFreeSlot(inv, grid); if (val.HasValue) { item.m_gridPos = val.Value; continue; } ItemDrop.DropItem(item.Clone(), item.m_stack, ((Component)this).transform.position + ((Component)this).transform.forward * 2f + Vector3.up, Quaternion.identity); inv.RemoveItem(item); } } InvChanged?.Invoke(inv, null); } finally { _busy = false; } _fishCounts = CountFish(inv); Plugin.Log($"Hatchery resized to {((Vector2Int)(ref grid)).x}x{((Vector2Int)(ref grid)).y}."); } private static Vector2i? FindFreeSlot(Inventory inv, Vector2Int grid) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < ((Vector2Int)(ref grid)).y; i++) { for (int j = 0; j < ((Vector2Int)(ref grid)).x; j++) { if (inv.GetItemAt(j, i) == null) { return new Vector2i(j, i); } } } return null; } private void Hatch(Inventory inv) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = _nview.GetZDO(); long ticks = ZNet.instance.GetTime().Ticks; long num = zDO.GetLong("hatchery_start_ticks", 0L); long num2 = (long)(Plugin.HatchMinutes.Value * 60f * 10000000f); if (FindRoe(inv) == null) { if (num != 0L) { zDO.Set("hatchery_start_ticks", 0L); } return; } if (num == 0L) { zDO.Set("hatchery_start_ticks", ticks); return; } int num3 = 0; while (ticks - num >= num2) { ItemData val = FindRoe(inv); if (val == null) { num = 0L; break; } string text = HatchRules.RollFish(((Component)this).transform.position, (string id) => CanFit(inv, id)); if (text == null || !AddFish(inv, text)) { num = ticks; break; } _fishCounts.TryGetValue(text, out var value); _fishCounts[text] = value + 1; inv.RemoveItem(val, 1); num += num2; num3++; } if (num != 0L && FindRoe(inv) == null) { num = 0L; } zDO.Set("hatchery_start_ticks", num); if (num3 > 0) { _nview.InvokeRPC(ZNetView.Everybody, "RPC_HatcheryHatch", Array.Empty<object>()); Plugin.Log($"Hatchery hatched {num3} fish."); } } private static bool CanFit(Inventory inv, string fishId) { if (inv.GetEmptySlots() > 0) { return true; } return inv.GetAllItems().Any((ItemData i) => (Object)(object)i.m_dropPrefab != (Object)null && ((Object)i.m_dropPrefab).name == fishId && i.m_quality == 1 && i.m_stack < i.m_shared.m_maxStackSize); } private static ItemData FindRoe(Inventory inv) { return ((IEnumerable<ItemData>)inv.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => (Object)(object)i.m_dropPrefab != (Object)null && ((Object)i.m_dropPrefab).name == "ValkyriesHatchery_Roe")); } private static bool AddFish(Inventory inv, string fishId) { ObjectDB instance = ObjectDB.instance; GameObject val = ((instance != null) ? instance.GetItemPrefab(fishId) : null); ItemDrop val2 = ((val != null) ? val.GetComponent<ItemDrop>() : null); if ((Object)(object)val2 == (Object)null) { return false; } ItemData val3 = val2.m_itemData.Clone(); val3.m_dropPrefab = val; val3.m_stack = 1; val3.m_quality = 1; val3.m_durability = val3.GetMaxDurability(); return inv.AddItem(val3); } private void UpdateVisuals(Inventory inv) { bool flag = inv.NrOfItems() > 0; bool flag2 = inv.GetAllItems().Any(IsFish); if ((Object)(object)_water != (Object)null && _water.activeSelf != flag) { _water.SetActive(flag); } if ((Object)(object)_bubbles != (Object)null && _bubbles.activeSelf != flag2) { _bubbles.SetActive(flag2); } } private static bool IsRoe(ItemData i) { if ((Object)(object)i.m_dropPrefab != (Object)null) { return ((Object)i.m_dropPrefab).name == "ValkyriesHatchery_Roe"; } return false; } private static bool IsFish(ItemData i) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if ((int)i.m_shared.m_itemType == 21) { return (Object)(object)i.m_dropPrefab != (Object)null; } return false; } private static Dictionary<string, int> CountFish(Inventory inv) { Dictionary<string, int> dictionary = new Dictionary<string, int>(); foreach (ItemData allItem in inv.GetAllItems()) { if (IsFish(allItem)) { dictionary.TryGetValue(((Object)allItem.m_dropPrefab).name, out var value); dictionary[((Object)allItem.m_dropPrefab).name] = value + allItem.m_stack; } } return dictionary; } private bool LocalPlayerHasItOpen() { if (_container.IsInUse() && _nview.IsOwner()) { return InventoryGui.IsVisible(); } return false; } private void OnInventoryChanged() { if (!_busy && !_checkQueued) { _checkQueued = true; ((MonoBehaviour)this).Invoke("Enforce", 0f); } } private void Enforce() { _checkQueued = false; if (_busy || (Object)(object)_nview == (Object)null || !_nview.IsValid()) { return; } Inventory inventory = _container.GetInventory(); if (inventory == null) { return; } if (!_nview.IsOwner()) { _fishCounts = CountFish(inventory); return; } _busy = true; try { bool flag = false; foreach (ItemData item in inventory.GetAllItems().ToList()) { if (!IsRoe(item) && (!IsFish(item) || item.m_quality != 1)) { Eject(inventory, item, item.m_stack); flag = true; } } Dictionary<string, int> source = CountFish(inventory); foreach (KeyValuePair<string, int> kv in source.ToList()) { _fishCounts.TryGetValue(kv.Key, out var value); int num = kv.Value - value; while (num > 0) { ItemData val = ((IEnumerable<ItemData>)inventory.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => IsFish(i) && ((Object)i.m_dropPrefab).name == kv.Key)); if (val == null) { break; } int num2 = Mathf.Min(num, val.m_stack); Eject(inventory, val, num2); num -= num2; flag = true; } } source = CountFish(inventory); Dictionary<string, int> dictionary = new Dictionary<string, int>(); foreach (KeyValuePair<string, int> fishCount in _fishCounts) { source.TryGetValue(fishCount.Key, out var value2); if (value2 < fishCount.Value) { dictionary[fishCount.Key] = fishCount.Value - value2; } } if (dictionary.Count > 0 && LocalPlayerHasItOpen()) { AwardXp(dictionary); } _fishCounts = source; if (flag && LocalPlayerHasItOpen()) { Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Only Fish Roe can go in the hatchery.", 0, (Sprite)null, false); } } } finally { _busy = false; } } private void Eject(Inventory inv, ItemData item, int amount) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) ItemData val = item.Clone(); val.m_stack = amount; Player localPlayer = Player.m_localPlayer; bool flag = false; if ((Object)(object)localPlayer != (Object)null && LocalPlayerHasItOpen() && ((Humanoid)localPlayer).GetInventory().CanAddItem(val, -1)) { flag = ((Humanoid)localPlayer).GetInventory().AddItem(val); } if (!flag) { ItemDrop.DropItem(val, amount, ((Component)this).transform.position + ((Component)this).transform.forward * 2f + Vector3.up, Quaternion.identity); } inv.RemoveItem(item, amount); } private static void AwardXp(Dictionary<string, int> removed) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } float num = 0f; int num2 = 0; foreach (KeyValuePair<string, int> item in removed) { num += HatchRules.XpFor(item.Key) * (float)item.Value; num2 += item.Value; } num *= Plugin.XpMultiplier.Value; if (!(num <= 0f)) { ((Character)localPlayer).RaiseSkill((SkillType)104, num); if (Plugin.ShowXpMessage.Value) { ((Character)localPlayer).Message((MessageType)1, $"Fishing +{num:0} ({num2} fish)", 0, (Sprite)null, false); } Plugin.Log($"Hatchery: awarded {num} Fishing XP for {num2} fish."); } } } }