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 LeashMe Nursery v0.1.0
LeashMe.Nursery.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using BepInEx; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; using UnityEngine.AI; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("LeashMe.Nursery")] [assembly: AssemblyProduct("LeashMe.Nursery")] [assembly: ComVisible(false)] [assembly: Guid("6f1c2a4e-8b3d-4e5f-9a71-2c4d8e0b5f13")] [assembly: AssemblyFileVersion("0.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] namespace LeashMe { internal static class EmbeddedSprite { public static Sprite Load(string fileName) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) using Stream stream = typeof(EmbeddedSprite).Assembly.GetManifestResourceStream("LeashMe." + fileName); if (stream == null) { Logger.LogWarning((object)("Embedded icon " + fileName + " not found.")); return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = AssetUtils.LoadImage(array); return Object.op_Implicit((Object)(object)val) ? Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)) : null; } } internal static class ModelIcon { private const int RenderSize = 256; [Conditional("DEBUG")] public static void Export(GameObject visual, Quaternion rotation, string fileName, int thicken = 0, float brightness = 1f) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown string environmentVariable = Environment.GetEnvironmentVariable("LEASHME_ICON_EXPORT"); if (string.IsNullOrWhiteSpace(environmentVariable) || !Object.op_Implicit((Object)(object)visual)) { return; } Texture2D val = null; try { Sprite val2 = RenderManager.Instance.Render(new RenderRequest(visual) { Width = 256, Height = 256, Rotation = rotation, UseCache = false, ParticleSimulationTime = -1f }); if (!Object.op_Implicit((Object)(object)val2) || ((Texture)val2.texture).width != 256 || ((Texture)val2.texture).height != 256) { Logger.LogWarning((object)("Could not render icon " + fileName + ".")); return; } Rect val3 = VisibleSquare(val2.texture); val = new Texture2D((int)((Rect)(ref val3)).width, (int)((Rect)(ref val3)).height, (TextureFormat)4, false); val.SetPixels(val2.texture.GetPixels((int)((Rect)(ref val3)).x, (int)((Rect)(ref val3)).y, (int)((Rect)(ref val3)).width, (int)((Rect)(ref val3)).height)); val.SetPixels32(Emphasize(val.GetPixels32(), ((Texture)val).width, ((Texture)val).height, thicken, brightness)); val.Apply(); Directory.CreateDirectory(environmentVariable); string text = Path.Combine(environmentVariable, fileName + ".png"); File.WriteAllBytes(text, ImageConversion.EncodeToPNG(val)); Logger.LogInfo((object)("Exported icon: " + text)); } catch (Exception arg) { Logger.LogWarning((object)$"Could not export icon {fileName}: {arg}"); } finally { if (Object.op_Implicit((Object)(object)val)) { Object.Destroy((Object)(object)val); } } } private static Color32[] Emphasize(Color32[] source, int width, int height, int radius, float brightness) { //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: 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) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])source.Clone(); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { if (radius <= 0 || source[i * width + j].a >= 128) { continue; } int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; for (int k = -radius; k <= radius; k++) { for (int l = -radius; l <= radius; l++) { int num5 = j + l; int num6 = i + k; if (l * l + k * k <= radius * radius && num5 >= 0 && num6 >= 0 && num5 < width && num6 < height) { Color32 val = source[num6 * width + num5]; if (val.a >= 128) { num2 += val.r; num3 += val.g; num4 += val.b; num++; } } } } if (num > 0) { array[i * width + j] = new Color32((byte)(num2 / num), (byte)(num3 / num), (byte)(num4 / num), byte.MaxValue); } } } for (int m = 0; m < array.Length; m++) { Color32 val2 = array[m]; array[m] = new Color32((byte)Mathf.Min(255f, (float)(int)val2.r * brightness), (byte)Mathf.Min(255f, (float)(int)val2.g * brightness), (byte)Mathf.Min(255f, (float)(int)val2.b * brightness), val2.a); } return array; } private static Rect VisibleSquare(Texture2D texture) { //IL_0102: 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) int width = ((Texture)texture).width; int height = ((Texture)texture).height; Color32[] pixels = texture.GetPixels32(); int num = width; int num2 = height; int num3 = -1; int num4 = -1; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { if (pixels[i * width + j].a != 0) { num = Mathf.Min(num, j); num2 = Mathf.Min(num2, i); num3 = Mathf.Max(num3, j); num4 = Mathf.Max(num4, i); } } } if (num3 < num) { return new Rect(0f, 0f, (float)width, (float)height); } int num5 = Mathf.Max(num3 - num + 1, num4 - num2 + 1); int num6 = Mathf.CeilToInt((float)num5 * 0.04f); int num7 = Mathf.Min(num5 + 2 * num6, Mathf.Min(width, height)); int num8 = Mathf.Clamp((num + num3 + 1 - num7) / 2, 0, width - num7); int num9 = Mathf.Clamp((num2 + num4 + 1 - num7) / 2, 0, height - num7); return new Rect((float)num8, (float)num9, (float)num7, (float)num7); } } } namespace LeashMe.Nursery { [HarmonyPatch] internal static class NurseryAnimals { private enum Phase { Free, Requested, Confirmed } private sealed class State { public NurseryFood.Species Species; public bool Owned; public Phase Phase; public NurseryStation Station; public long RequestId; public Vector3 Center; public Vector3 Ground; public bool Arrived; public float PickTimer; public bool Paused; public Vector3 WaitPoint; public float SearchTimer; public float RequestTimer; public float RenewTimer; public float PauseTimer; public NurseryStation Retry; public float RetryTimer; public NurseryStation Remembered; public float RememberTimer; public float RememberFailTime; public float NoWayAt = -1f; public readonly List<NurseryStation> Round = new List<NurseryStation>(); public Dictionary<NurseryStation, float> NoPathUntil; public int Cursor; } private const float SearchSeconds = 2f; private const float NoPathSeconds = 10f; private const float WayCheckSeconds = 10f; private const float SearchAfterDropSeconds = 0.5f; private const float RetrySeconds = 30f; private const float RequestTimeoutSeconds = 20f; private const float RenewSeconds = 10f; private const float PauseCheckSeconds = 30f; private const float RememberFirstSeconds = 1f; private const float RememberMinSeconds = 2f; private const float RememberMaxSeconds = 5f; private const float RememberGiveUpSeconds = 60f; private const float NoWayMinSeconds = 5f; private const float NoWayMaxSeconds = 60f; private const int PathChecksPerSearch = 2; private const float MaxCenterShift = 4f; private const float EdgeMargin = 0.3f; private const float MinCutLength = 1.5f; private const float GapMargin = 0.5f; private const float PickRetryMinSeconds = 0.5f; private const float PickRetryMaxSeconds = 1.5f; private static readonly ConditionalWeakTable<BaseAI, State> s_states = new ConditionalWeakTable<BaseAI, State>(); private static readonly List<NurseryStation> s_expired = new List<NurseryStation>(); public static void ReleaseAll() { foreach (BaseAI instance in BaseAI.m_instances) { if (Object.op_Implicit((Object)(object)instance) && s_states.TryGetValue(instance, out var value) && value.Phase != Phase.Free) { Drop(instance, value); } } } [HarmonyPatch(typeof(BaseAI), "UpdateAI")] [HarmonyPostfix] private static void UpdateAIPostfix(BaseAI __instance, float dt, bool __result) { if (NurseryStation.All.Count == 0) { return; } State value = s_states.GetValue(__instance, Create); if (value.Species == null) { return; } if (!__result || !__instance.m_character.IsTamed()) { if (value.Phase != Phase.Free) { Drop(__instance, value); } value.Owned = false; return; } if (!value.Owned) { value.Owned = true; TakeOver(__instance, value); } Maintain(__instance, value, dt); } [HarmonyPatch(typeof(BaseAI), "IdleMovement")] [HarmonyPrefix] private static bool IdleMovementPrefix(BaseAI __instance, float dt) { if (NurseryStation.All.Count == 0 || !s_states.TryGetValue(__instance, out var value) || value.Species == null || !value.Owned) { return true; } switch (value.Phase) { case Phase.Free: TickFree(__instance, value, dt); return true; case Phase.Requested: return true; default: Move(__instance, value, dt); return false; } } [HarmonyPatch(typeof(Tameable), "GetHoverText")] [HarmonyPostfix] private static void TameableHoverPostfix(Tameable __instance) { ShowStationConnection(__instance.m_nview); } [HarmonyPatch(typeof(Character), "GetHoverText")] [HarmonyPostfix] private static void CharacterHoverPostfix(Character __instance) { if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<Tameable>())) { ShowStationConnection(__instance.m_nview); } } private static void ShowStationConnection(ZNetView nview) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (NurseryStation.All.Count != 0 && Object.op_Implicit((Object)(object)nview) && nview.IsValid()) { NurseryStation nurseryStation = NurseryStation.Of(nview.GetZDO().m_uid); if (Object.op_Implicit((Object)(object)nurseryStation)) { nurseryStation.ShowConnection(nview.GetZDO().m_uid); } } } private static State Create(BaseAI ai) { return new State { Species = NurseryFood.FindYoung(((Component)ai).gameObject), SearchTimer = Random.Range(0f, 2f), RememberTimer = Random.Range(0f, 1f) }; } private static void Maintain(BaseAI ai, State state, float dt) { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0167: 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_018c: Unknown result type (might be due to invalid IL or missing references) if (state.Phase != Phase.Free && (!Object.op_Implicit((Object)(object)state.Station) || !state.Station.IsValid)) { Drop(ai, state); } switch (state.Phase) { case Phase.Requested: if (state.Station.LeaseOf(ai.m_nview.GetZDO().m_uid) == state.RequestId) { Confirm(ai, state); Remember(ai, state.Station); break; } state.RequestTimer -= dt; if (state.RequestTimer <= 0f) { if (Remembers(ai, state.Station) && !state.Station.InUse && !state.Station.HasFreePlace) { Forget(ai); } Drop(ai, state); } return; case Phase.Free: return; } if (state.Station.LeaseOf(ai.m_nview.GetZDO().m_uid) != state.RequestId) { Drop(ai, state); state.RememberTimer = 0f; return; } state.RenewTimer -= dt; if (state.RenewTimer <= 0f) { state.RenewTimer = 10f; Invoke(ai, state, "LeashMe_NurseryRenew"); Remember(ai, state.Station); } state.SearchTimer -= dt; if (state.SearchTimer <= 0f) { state.SearchTimer = 10f; if (Utils.DistanceXZ(((Component)ai).transform.position, state.Center) > 2f * state.Species.MoveRadius && !ai.HavePath(state.Center)) { NoWay(ai, state); } } } private static void Move(BaseAI ai, State state, float dt) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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_0030: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0217: 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_0157: Unknown result type (might be due to invalid IL or missing references) if (!state.Paused && !state.Arrived && state.Station.InUse) { state.Paused = true; state.WaitPoint = ((Component)ai).transform.position; state.PauseTimer = Random.Range(0.5f, 1f) * 30f; ai.m_randomMoveUpdateTimer = 0f; } if (state.Paused) { state.PauseTimer -= dt; if (state.PauseTimer <= 0f) { state.PauseTimer = 30f; if (!state.Station.InUse) { state.Paused = false; ai.m_randomMoveUpdateTimer = 0f; } } if (state.Paused) { ai.RandomMovement(dt, state.WaitPoint, true); return; } } float moveRadius = state.Species.MoveRadius; float num = Utils.DistanceXZ(((Component)ai).transform.position, state.Center); if (state.Arrived && num > 2f * moveRadius) { state.Arrived = false; } if (!state.Arrived) { float num2 = moveRadius / 2f; if (num <= num2) { state.Arrived = true; state.PickTimer = 0f; ai.m_randomMoveUpdateTimer = 0f; } else if (ai.MoveTo(dt, state.Center, num2, num > 2f * moveRadius)) { if (Utils.DistanceXZ(((Component)ai).transform.position, state.Center) <= num2 + 0.5f) { state.Arrived = true; state.PickTimer = 0f; ai.m_randomMoveUpdateTimer = 0f; } else { NoWay(ai, state); } } if (!state.Arrived) { return; } } if (ai.m_randomMoveUpdateTimer <= 0f) { state.PickTimer -= dt; if (state.PickTimer > 0f || !TryPickTarget(ai, state, moveRadius)) { if (state.PickTimer <= 0f) { state.PickTimer = Random.Range(0.5f, 1.5f); } ai.m_reachedRandomMoveTarget = true; ai.StopMoving(); return; } state.PickTimer = 0f; } float randomMoveRange = ai.m_randomMoveRange; try { ai.m_randomMoveRange = moveRadius; ai.RandomMovement(dt, state.Ground, false); } finally { ai.m_randomMoveRange = randomMoveRange; } } private static bool TryPickTarget(BaseAI ai, State state, float radius) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_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_0048: 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_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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_00a0: Unknown result type (might be due to invalid IL or missing references) Pathfinding.instance.PokeArea(state.Ground, ai.m_pathAgentType); Vector3 val = Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f) * Vector3.forward * Random.Range(0.7f * radius, radius); Vector3 val2 = state.Ground + val; if (!state.Station.TryGetGround(val2, state.Center.y, out var height) || !TryCutToEdge(ai, state, new Vector3(val2.x, height, val2.z), out var target) || !ai.IsValidRandomMovePoint(target)) { return false; } ai.m_randomMoveTarget = target; ai.m_reachedRandomMoveTarget = false; float randomMoveInterval = ai.m_randomMoveInterval; ai.m_randomMoveUpdateTimer = Random.Range(randomMoveInterval, randomMoveInterval + randomMoveInterval / 2f); ai.m_lastFindPathTime = float.MinValue; return true; } private static bool TryCutToEdge(BaseAI ai, State state, Vector3 to, out Vector3 target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //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_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00c0: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_0111: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) target = to; Vector3 val = to - state.Ground; val.y = 0f; float num = Utils.DistanceXZ(state.Center, state.Ground) + 0.5f; if (((Vector3)(ref val)).magnitude <= num) { return false; } AgentSettings settings = Pathfinding.instance.GetSettings(ai.m_pathAgentType); NavMeshQueryFilter val2 = default(NavMeshQueryFilter); ((NavMeshQueryFilter)(ref val2)).agentTypeID = ((NavMeshBuildSettings)(ref settings.m_build)).agentTypeID; ((NavMeshQueryFilter)(ref val2)).areaMask = settings.m_areaMask; NavMeshQueryFilter val3 = val2; Vector3 val4 = state.Ground + ((Vector3)(ref val)).normalized * num; val4.y = state.Center.y; NavMeshHit val5 = default(NavMeshHit); if (!NavMesh.SamplePosition(val4, ref val5, 1.5f, val3)) { return false; } Vector3 position = ((NavMeshHit)(ref val5)).position; NavMeshHit val6 = default(NavMeshHit); if (!NavMesh.Raycast(position, to, ref val6, val3)) { return true; } Vector3 val7 = ((NavMeshHit)(ref val6)).position - position; val7.y = 0f; float num2 = ((Vector3)(ref val7)).magnitude - 0.3f; if (num2 < 1.5f) { return false; } target = position + ((Vector3)(ref val7)).normalized * num2; target.y = ((NavMeshHit)(ref val6)).position.y; return state.Station.InTargetHeight(target.y); } private static bool TryGetCenter(BaseAI ai, NurseryStation station, out Vector3 center, out Vector3 ground) { //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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0068: Unknown result type (might be due to invalid IL or missing references) center = (ground = Vector3.zero); Pathfinding instance = Pathfinding.instance; if (!Object.op_Implicit((Object)(object)instance) || !station.TryGetTargetPoint(out ground)) { return false; } instance.PokeArea(ground, ai.m_pathAgentType); center = ground; if (instance.SnapToNavMesh(ref center, true, instance.GetSettings(ai.m_pathAgentType)) && Utils.DistanceXZ(center, ground) <= 4f && Mathf.Abs(center.y - ground.y) <= 4f) { return station.InTargetHeight(center.y); } return false; } private static void TickFree(BaseAI ai, State state, float dt) { if (TickRemembered(ai, state, dt)) { return; } if (Object.op_Implicit((Object)(object)state.Retry)) { state.RetryTimer -= dt; if (!(state.RetryTimer > 0f)) { NurseryStation retry = state.Retry; state.Retry = null; if (retry.IsValid && retry.InUse) { state.Retry = retry; state.RetryTimer = 30f; } else if (retry.IsValid && Fits(ai, state, retry)) { TryRequest(ai, state, retry); } } } else { state.SearchTimer -= dt; if (!(state.SearchTimer > 0f)) { state.SearchTimer = 2f; Search(ai, state); } } } private static bool TickRemembered(BaseAI ai, State state, float dt) { if (Object.op_Implicit((Object)(object)state.Remembered) && state.Remembered.IsValid && !state.Remembered.InUse) { state.RememberFailTime += dt; } state.RememberTimer -= dt; if (state.RememberTimer <= 0f) { state.RememberTimer = Random.Range(2f, 5f); state.Remembered = FindRemembered(ai); NurseryStation remembered = state.Remembered; if (!Object.op_Implicit((Object)(object)remembered) || remembered.InUse) { state.RememberFailTime = 0f; } else if (remembered.Generation != ai.m_nview.GetZDO().GetInt(NurseryStation.MemberGenerationKey, 0)) { Forget(ai); state.Remembered = null; } else if (state.RememberFailTime >= 60f) { Forget(ai); state.Remembered = null; state.RememberFailTime = 0f; } else if (remembered.Species == state.Species) { TryRequest(ai, state, remembered); } } if (Object.op_Implicit((Object)(object)state.Remembered)) { return state.Remembered.IsValid; } return false; } private static void NoWay(BaseAI ai, State state) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) float num = Time.time - state.NoWayAt; if (state.NoWayAt >= 0f && num >= 5f && num <= 60f && !ai.HavePath(state.Center)) { Forget(ai); state.NoWayAt = -1f; } else if (state.NoWayAt < 0f || num > 60f) { state.NoWayAt = Time.time; } Drop(ai, state); } private static NurseryStation FindRemembered(BaseAI ai) { int num = ai.m_nview.GetZDO().GetInt(NurseryStation.MemberKey, 0); if (num == 0) { return null; } foreach (NurseryStation item in NurseryStation.All) { if (item.IsValid && item.Number == num) { return item; } } return null; } private static bool Remembers(BaseAI ai, NurseryStation station) { int number = station.Number; if (number > 0) { return ai.m_nview.GetZDO().GetInt(NurseryStation.MemberKey, 0) == number; } return false; } private static void Remember(BaseAI ai, NurseryStation station) { int number = station.Number; int generation = station.Generation; ZDO zDO = ai.m_nview.GetZDO(); if (number > 0 && (zDO.GetInt(NurseryStation.MemberKey, 0) != number || zDO.GetInt(NurseryStation.MemberGenerationKey, 0) != generation)) { zDO.Set(NurseryStation.MemberKey, number, false); zDO.Set(NurseryStation.MemberGenerationKey, generation, false); } } private static void Forget(BaseAI ai) { ZDO zDO = ai.m_nview.GetZDO(); if (zDO.GetInt(NurseryStation.MemberKey, 0) != 0) { zDO.Set(NurseryStation.MemberKey, 0, false); zDO.Set(NurseryStation.MemberGenerationKey, 0, false); } } private static void Search(BaseAI ai, State state) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) if (state.Cursor >= state.Round.Count) { state.Round.Clear(); state.Cursor = 0; foreach (NurseryStation item in NurseryStation.All) { if (Fits(ai, state, item)) { state.Round.Add(item); } } Vector3 position = ((Component)ai).transform.position; state.Round.Sort((NurseryStation a, NurseryStation b) => Utils.DistanceXZ(position, ((Component)a).transform.position).CompareTo(Utils.DistanceXZ(position, ((Component)b).transform.position))); } int num = 0; while (state.Cursor < state.Round.Count && num < 2) { NurseryStation nurseryStation = state.Round[state.Cursor++]; if (!Object.op_Implicit((Object)(object)nurseryStation) || !nurseryStation.IsValid || !Fits(ai, state, nurseryStation) || NoPath(state, nurseryStation)) { continue; } if (nurseryStation.InUse) { if (!Object.op_Implicit((Object)(object)state.Retry)) { state.Retry = nurseryStation; state.RetryTimer = Random.Range(0.8f, 1.2f) * 30f; } continue; } num++; if (TryRequest(ai, state, nurseryStation)) { state.Round.Clear(); state.Cursor = 0; break; } SetNoPath(state, nurseryStation); } } private static bool NoPath(State state, NurseryStation station) { if (state.NoPathUntil != null && state.NoPathUntil.TryGetValue(station, out var value)) { return Time.time < value; } return false; } private static void SetNoPath(State state, NurseryStation station) { if (state.NoPathUntil == null) { state.NoPathUntil = new Dictionary<NurseryStation, float>(); } else { s_expired.Clear(); foreach (KeyValuePair<NurseryStation, float> item in state.NoPathUntil) { if (!Object.op_Implicit((Object)(object)item.Key) || Time.time >= item.Value) { s_expired.Add(item.Key); } } foreach (NurseryStation item2 in s_expired) { state.NoPathUntil.Remove(item2); } } state.NoPathUntil[station] = Time.time + 10f; } private static bool Fits(BaseAI ai, State state, NurseryStation station) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (station.Species == state.Species && station.HasFreePlace) { return Utils.DistanceXZ(((Component)ai).transform.position, ((Component)station).transform.position) <= state.Species.PickupRadius; } return false; } private static bool TryRequest(BaseAI ai, State state, NurseryStation station) { //IL_000e: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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) if (!TryGetCenter(ai, station, out var center, out var ground) || !ai.HavePath(center)) { return false; } state.Station = station; state.Center = center; state.Ground = ground; state.RequestId = NewRequestId(); state.Phase = Phase.Requested; state.RequestTimer = 20f; state.Retry = null; Invoke(ai, state, "LeashMe_NurseryRequest"); return true; } private static void TakeOver(BaseAI ai, State state) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) ZDOID uid = ai.m_nview.GetZDO().m_uid; NurseryStation nurseryStation = null; long requestId = 0L; float num = float.MaxValue; foreach (NurseryStation item in NurseryStation.All) { long num2 = (item.IsValid ? item.LeaseOf(uid) : 0); float num3 = Utils.DistanceXZ(((Component)ai).transform.position, ((Component)item).transform.position); if (num2 != 0L && num3 < num) { nurseryStation = item; requestId = num2; num = num3; } } if (Object.op_Implicit((Object)(object)nurseryStation) && TryGetCenter(ai, nurseryStation, out var center, out var ground)) { state.Station = nurseryStation; state.Center = center; state.Ground = ground; state.RequestId = requestId; state.Phase = Phase.Requested; Confirm(ai, state); Remember(ai, state.Station); Invoke(ai, state, "LeashMe_NurseryRenew"); } } private static void Confirm(BaseAI ai, State state) { state.RememberFailTime = 0f; state.SearchTimer = 10f; state.Phase = Phase.Confirmed; state.Arrived = false; state.Paused = false; state.RenewTimer = Random.Range(0.5f, 1f) * 10f; ai.m_randomMoveUpdateTimer = 0f; } private static void Drop(BaseAI ai, State state) { if (state.Phase == Phase.Confirmed) { ai.m_randomMoveUpdateTimer = 0f; } state.Phase = Phase.Free; state.Station = null; state.SearchTimer = Random.Range(0f, 0.5f); state.RequestId = 0L; state.Paused = false; state.Arrived = false; } private static void Invoke(BaseAI ai, State state, string rpc) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) state.Station.NetView.InvokeRPC(rpc, new object[3] { ai.m_nview.GetZDO().m_uid, state.RequestId, state.Station.Generation }); } private static long NewRequestId() { long num; do { num = ((long)Random.Range(int.MinValue, int.MaxValue) << 32) ^ (uint)Random.Range(int.MinValue, int.MaxValue); } while (num == 0L); return num; } } [HarmonyPatch] internal static class NurseryContainerPatches { private static readonly object Filled = new object(); private static readonly ConditionalWeakTable<Inventory, object> s_filled = new ConditionalWeakTable<Inventory, object>(); private static bool s_loading; [HarmonyPatch(typeof(Inventory), "Load", new Type[] { typeof(ZPackage) })] [HarmonyPatch(typeof(Inventory), "Load", new Type[] { typeof(ZPackage), typeof(bool) })] [HarmonyPrefix] private static void LoadPrefix() { s_loading = true; } [HarmonyPatch(typeof(Inventory), "Load", new Type[] { typeof(ZPackage) })] [HarmonyPatch(typeof(Inventory), "Load", new Type[] { typeof(ZPackage), typeof(bool) })] [HarmonyFinalizer] private static void LoadFinalizer() { s_loading = false; } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(int), typeof(int), typeof(int), typeof(bool) })] [HarmonyPrefix] private static bool AddAmountPrefix(Inventory __instance, ItemData item, ref int amount, ref bool __result) { if (s_loading || !IsNursery(__instance)) { return true; } int num = Allowed(__instance, item); if (num <= 0) { __result = false; return false; } amount = Mathf.Min(amount, num); return true; } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })] [HarmonyPrefix] private static bool AddItemPrefix(Inventory __instance, ItemData item, ref bool __result) { return WholeItemPrefix(__instance, item, ref __result); } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(Vector2i) })] [HarmonyPrefix] private static bool AddItemAtPrefix(Inventory __instance, ItemData item, ref bool __result) { return WholeItemPrefix(__instance, item, ref __result); } private static bool WholeItemPrefix(Inventory inventory, ItemData item, ref bool result) { //IL_004b: 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_0050: 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_005a: Unknown result type (might be due to invalid IL or missing references) if (s_loading || !IsNursery(inventory)) { return true; } int num = Allowed(inventory, item); if (num >= item.m_stack) { return true; } if (num > 0) { Vector2i val = (Vector2i)((inventory.m_inventory.Count > 0) ? inventory.m_inventory[0].m_gridPos : new Vector2i(0, 0)); inventory.AddItem(item, num, val.x, val.y, false); } result = false; return false; } [HarmonyPatch(typeof(InventoryGrid), "DropItem")] [HarmonyPrefix] private static bool DropItemPrefix(InventoryGrid __instance, Inventory fromInventory, ItemData item, int amount, Vector2i pos, ref bool __result) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!IsNursery(__instance.m_inventory) && !IsNursery(fromInventory)) { return true; } ItemData itemAt = __instance.m_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)) { return true; } __result = false; return false; } [HarmonyPatch(typeof(Inventory), "Changed")] [HarmonyPostfix] private static void ChangedPostfix(Inventory __instance) { if (!IsNursery(__instance)) { return; } object value; bool num = s_filled.TryGetValue(__instance, out value); bool flag = __instance.m_inventory.Count > 0; if (num == flag) { return; } if (flag) { s_filled.Add(__instance, Filled); } else { s_filled.Remove(__instance); } if (!s_loading && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { NurseryFood.Species species = (flag ? NurseryFood.Find(__instance.m_inventory[0]) : null); if (!flag || species != null) { ((Character)Player.m_localPlayer).Message((MessageType)2, flag ? Localization.instance.Localize("$leashme_nursery_now", new string[1] { Localization.instance.Localize(species.YoungName) }) : "$leashme_nursery_none", 0, (Sprite)null, false); } } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] [HarmonyPostfix] private static void UpdateGuiPostfix(InventoryGrid __instance) { Inventory inventory = __instance.m_inventory; if (inventory != null && IsNursery(inventory) && inventory.m_inventory.Count != 0) { ItemData val = inventory.m_inventory[0]; NurseryFood.Species species = NurseryFood.Find(val); InventoryElement val2 = ((species != null) ? __instance.GetElement(val.m_gridPos.x, val.m_gridPos.y, inventory.GetWidth()) : null); if ((Object)(object)val2 != (Object)null) { val2.m_amount.text = $"{val.m_stack}/{species.Limit}"; } } } [HarmonyPatch(typeof(Container), "GetHoverText")] [HarmonyPostfix] private static void GetHoverTextPostfix(Container __instance, ref string __result) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (!TryGetStation(__instance, out var station) || (__instance.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, false, false))) { return; } Player localPlayer = Player.m_localPlayer; station.ShowAreas((Object.op_Implicit((Object)(object)localPlayer) && ((Character)localPlayer).TakeInput() && ZInput.GetKeyDown((KeyCode)110, true)) ? 15f : 0.5f); string text = station.DisplayName; if (__instance.m_inventory.NrOfItems() == 0) { text += Localization.instance.Localize(" ( $piece_container_empty )"); } NurseryFood.Species species = station.Species; if (species != null) { string text2 = Localization.instance.Localize(species.YoungName); if (text2.Length > 0) { text2 = char.ToUpper(text2[0]) + text2.Substring(1); } text += $"\n{text2}: {station.Occupied}/{station.Capacity}"; } text += Localization.instance.Localize("\n[<color=yellow><b>$KEY_Use</b></color>] $piece_container_open $msg_stackall_hover"); if (species != null) { text += Localization.instance.Localize((ZInput.IsNonClassicFunctionality() && ZInput.IsGamepadActive()) ? "\n[<color=yellow><b>$KEY_AltKeys + $KEY_Use</b></color>] $leashme_nursery_show" : "\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] $leashme_nursery_show"); if (!ZInput.IsGamepadActive()) { text += Localization.instance.Localize("\n[<color=yellow><b>N</b></color>] $leashme_nursery_areas"); } } __result = text; } [HarmonyPatch(typeof(Container), "Interact")] [HarmonyPrefix] private static bool InteractPrefix(Container __instance, Humanoid character, bool hold, bool alt, ref bool __result) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!alt || !TryGetStation(__instance, out var station)) { return true; } __result = false; if (hold || (__instance.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, true, false))) { return false; } if (!__instance.CheckAccess(Game.instance.GetPlayerProfile().GetPlayerID())) { ((Character)character).Message((MessageType)2, "$msg_cantopen", 0, (Sprite)null, false); return false; } if (station.Species != null) { station.ShowConnections(); } return false; } private static bool TryGetStation(Container container, out NurseryStation station) { station = null; if (container.m_name == "$leashme_nursery") { return ((Component)container).TryGetComponent<NurseryStation>(ref station); } return false; } private static bool IsNursery(Inventory inventory) { return inventory.m_name == "$leashme_nursery"; } private static int Allowed(Inventory inventory, ItemData item) { if (inventory.m_inventory.Count == 0) { return NurseryFood.Find(item)?.Limit ?? 0; } ItemData val = inventory.m_inventory[0]; NurseryFood.Species species = NurseryFood.Find(val); if (species == null || val.m_shared.m_name != item.m_shared.m_name) { return 0; } return species.Limit - val.m_stack; } } internal static class NurseryFood { internal sealed class Species { public readonly string AdultPrefab; public readonly string YoungName; public readonly string StationName; public readonly int Limit; public readonly float MoveRadius; public readonly float PickupRadius; public readonly string[] FoodPrefabs; private float m_breedFreeRadius = -1f; public float BreedFreeRadius { get { if (m_breedFreeRadius < 0f && Object.op_Implicit((Object)(object)ZNetScene.instance)) { GameObject prefab = ZNetScene.instance.GetPrefab(AdultPrefab); Procreation val = default(Procreation); m_breedFreeRadius = ((Object.op_Implicit((Object)(object)prefab) && prefab.TryGetComponent<Procreation>(ref val)) ? (val.m_totalCheckRange + MoveRadius) : 0f); } return Mathf.Max(0f, m_breedFreeRadius); } } public Species(string adultPrefab, string youngName, int limit, float moveRadius, float pickupRadius, params string[] foodPrefabs) { AdultPrefab = adultPrefab; YoungName = youngName; StationName = youngName.Replace("_young_", "_station_"); Limit = limit; MoveRadius = moveRadius; PickupRadius = pickupRadius; FoodPrefabs = foodPrefabs; } } private static readonly Species[] All = new Species[6] { new Species("Boar", "$leashme_nursery_young_boar", 20, 5f, 30f, "Blueberries", "Carrot", "Onion", "Raspberry", "Mushroom", "Turnip"), new Species("Wolf", "$leashme_nursery_young_wolf", 20, 5f, 30f, "RawMeat", "DeerMeat", "LoxMeat", "NeckTail", "FishRaw", "ChickenMeat", "Sausages"), new Species("Lox", "$leashme_nursery_young_lox", 10, 10f, 45f, "Barley", "Cloudberry", "Flax"), new Species("Hen", "$leashme_nursery_young_hen", 20, 5f, 30f, "CarrotSeeds", "TurnipSeeds", "OnionSeeds", "BeechSeeds", "BirchSeeds", "Dandelion"), new Species("Asksvin", "$leashme_nursery_young_asksvin", 10, 10f, 35f, "MushroomSmokePuff", "Vineberry", "Fiddleheadfern"), new Species("Moose", "$leashme_nursery_young_moose", 10, 10f, 35f, "Lingonberry") }; private static Dictionary<string, Species> s_byItemName; private static Dictionary<string, GameObject> s_prefabByItemName; public static Species FindYoung(GameObject prefab) { Growup val = default(Growup); if (!Object.op_Implicit((Object)(object)prefab) || !prefab.TryGetComponent<Growup>(ref val)) { return null; } GameObject val2 = val.m_grownPrefab; if (val.m_altGrownPrefabs != null && val.m_altGrownPrefabs.Count > 0) { val2 = val.m_altGrownPrefabs[0].m_prefab; foreach (GrownEntry altGrownPrefab in val.m_altGrownPrefabs) { if ((Object)(object)altGrownPrefab.m_prefab != (Object)(object)val2) { return null; } } } if (!Object.op_Implicit((Object)(object)val2) || Object.op_Implicit((Object)(object)val2.GetComponent<Growup>())) { return null; } string prefabName = Utils.GetPrefabName(val2); Species[] all = All; foreach (Species species in all) { if (species.AdultPrefab == prefabName) { return species; } } return null; } public static Species Find(ItemData item) { Resolve(); if (!s_byItemName.TryGetValue(item.m_shared.m_name, out var value)) { return null; } return value; } public static GameObject GetPrefab(ItemData item) { Resolve(); if (!s_prefabByItemName.TryGetValue(item.m_shared.m_name, out var value)) { return null; } return value; } private static void Resolve() { if (s_byItemName != null) { return; } s_byItemName = new Dictionary<string, Species>(); s_prefabByItemName = new Dictionary<string, GameObject>(); Species[] all = All; foreach (Species species in all) { string[] foodPrefabs = species.FoodPrefabs; foreach (string text in foodPrefabs) { GameObject prefab = PrefabManager.Instance.GetPrefab(text); ItemDrop val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<ItemDrop>() : null); if (!Object.op_Implicit((Object)(object)val)) { Logger.LogWarning((object)("Nursery food " + text + " not found; it is not accepted.")); continue; } s_byItemName[val.m_itemData.m_shared.m_name] = species; s_prefabByItemName[val.m_itemData.m_shared.m_name] = prefab; } } } } internal class NurseryFoodVisual : MonoBehaviour { private Inventory m_inventory; private Transform m_anchor; private GameObject m_visual; private GameObject m_shownPrefab; private void Start() { Container component = ((Component)this).GetComponent<Container>(); m_inventory = (Object.op_Implicit((Object)(object)component) ? component.GetInventory() : null); m_anchor = ((Component)this).transform.Find("FoodAnchor"); if (m_inventory != null && Object.op_Implicit((Object)(object)m_anchor)) { Inventory inventory = m_inventory; inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(Refresh)); Refresh(); } } private void OnDestroy() { if (m_inventory != null) { Inventory inventory = m_inventory; inventory.m_onChanged = (Action)Delegate.Remove(inventory.m_onChanged, new Action(Refresh)); } } private void Refresh() { GameObject val = ((m_inventory.m_inventory.Count > 0) ? NurseryFood.GetPrefab(m_inventory.m_inventory[0]) : null); if (!((Object)(object)val == (Object)(object)m_shownPrefab)) { if (Object.op_Implicit((Object)(object)m_visual)) { Object.Destroy((Object)(object)m_visual); } m_shownPrefab = val; m_visual = (Object.op_Implicit((Object)(object)val) ? Build(val) : null); } } private GameObject Build(GameObject prefab) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //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) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017f: 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) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00b5: 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) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("FoodVisual") { layer = ((Component)this).gameObject.layer }; val.transform.SetParent(m_anchor, false); Transform transform = prefab.transform; Matrix4x4 val2 = Matrix4x4.Scale(transform.localScale) * transform.worldToLocalMatrix; MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val3 in componentsInChildren) { MeshFilter component = ((Component)val3).GetComponent<MeshFilter>(); if (((Renderer)val3).enabled && Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.sharedMesh) && IsActive(((Component)val3).transform, transform)) { Matrix4x4 val4 = val2 * ((Component)val3).transform.localToWorldMatrix; GameObject val5 = new GameObject(((Object)val3).name) { layer = val.layer }; val5.transform.SetParent(val.transform, false); val5.transform.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref val4)).GetColumn(3)); val5.transform.localRotation = ((Matrix4x4)(ref val4)).rotation; val5.transform.localScale = ((Matrix4x4)(ref val4)).lossyScale; val5.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh; MeshRenderer obj = val5.AddComponent<MeshRenderer>(); ((Renderer)obj).sharedMaterials = ((Renderer)val3).sharedMaterials; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1; } } Bounds val6 = NurseryPiece.LocalBounds(m_anchor, val); val.transform.localPosition = new Vector3(0f - ((Bounds)(ref val6)).center.x, 0f - ((Bounds)(ref val6)).min.y, 0f - ((Bounds)(ref val6)).center.z); return val; } private static bool IsActive(Transform t, Transform root) { while (Object.op_Implicit((Object)(object)t) && (Object)(object)t != (Object)(object)root) { if (!((Component)t).gameObject.activeSelf) { return false; } t = t.parent; } return true; } } [HarmonyPatch] internal static class NurseryNumbers { public static readonly int NumberKey = StringExtensionMethods.GetStableHashCode("LeashMe_nurseryNumber"); private const string RequestRpc = "LeashMe_NurseryNumberRequest"; private static readonly int PrefabHash = StringExtensionMethods.GetStableHashCode("LeashMe_Nursery"); private static HashSet<int> s_used; private static Dictionary<ZDOID, int> s_assigned; [HarmonyPatch(typeof(ZNet), "Awake")] [HarmonyPostfix] private static void ZNetAwakePostfix() { s_used = null; s_assigned = null; ZRoutedRpc.instance.Register<ZDOID>("LeashMe_NurseryNumberRequest", (Action<long, ZDOID>)RPC_Request); } public static void Request(ZDOID station) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "LeashMe_NurseryNumberRequest", new object[1] { station }); } private static void RPC_Request(long sender, ZDOID station) { //IL_001e: 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_005d: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer()) { ZDO zDO = ZDOMan.instance.GetZDO(station); if (zDO != null && zDO.GetPrefab() == PrefabHash && zDO.GetInt(NumberKey, 0) == 0) { ZRoutedRpc.instance.InvokeRoutedRPC(zDO.GetOwner(), station, "LeashMe_NurseryNumber", new object[1] { Assign(station) }); } } } private static int Assign(ZDOID station) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) if (s_used == null) { s_used = new HashSet<int>(); s_assigned = new Dictionary<ZDOID, int>(); foreach (ZDO value2 in ZDOMan.instance.m_objectsByID.Values) { int num = ((value2.GetPrefab() == PrefabHash) ? value2.GetInt(NumberKey, 0) : 0); if (num > 0) { s_used.Add(num); } } } if (s_assigned.TryGetValue(station, out var value)) { return value; } for (value = 1; s_used.Contains(value); value++) { } s_used.Add(value); s_assigned[station] = value; return value; } } internal static class NurseryPiece { public const string PrefabName = "LeashMe_Nursery"; public const string ContainerName = "$leashme_nursery"; public const string FoodAnchorName = "FoodAnchor"; private const string BasePrefabName = "iron_wall_1x1"; private const string FloorPrefabName = "wood_floor_1x1"; private const string ChestPrefabName = "piece_chest_wood"; private const string IconName = "buildmenu_icon_nursery_256"; private const float IconTilt = 15f; private const float IconYaw = 20f; private const int GrateParts = 5; private static readonly string[] States = new string[3] { "New", "Worn", "Broken" }; public static void Register() { PrefabManager.OnVanillaPrefabsAvailable += AddPiece; } private static void AddPiece() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) PrefabManager.OnVanillaPrefabsAvailable -= AddPiece; GameObject prefab = PrefabManager.Instance.GetPrefab("wood_floor_1x1"); if (!Object.op_Implicit((Object)(object)prefab)) { Logger.LogError((object)"wood_floor_1x1 not found; nursery not added."); return; } GameObject prefab2 = PrefabManager.Instance.GetPrefab("piece_chest_wood"); Container val = (Object.op_Implicit((Object)(object)prefab2) ? prefab2.GetComponent<Container>() : null); if (!Object.op_Implicit((Object)(object)val)) { Logger.LogError((object)"piece_chest_wood not found; nursery not added."); return; } PieceConfig val2 = new PieceConfig(); val2.Name = "$leashme_nursery"; val2.Description = "$leashme_nursery_desc"; val2.PieceTable = PieceTables.Hammer; val2.CraftingStation = "forge"; val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[2] { new RequirementConfig("RoundLog", 1, 0, true), new RequirementConfig("Iron", 5, 0, true) }; PieceConfig val3 = val2; Sprite val4 = EmbeddedSprite.Load("buildmenu_icon_nursery_256.png"); if (Object.op_Implicit((Object)(object)val4)) { val3.Icon = val4; } CustomPiece val5 = new CustomPiece("LeashMe_Nursery", "iron_wall_1x1", val3); if (!Object.op_Implicit((Object)(object)val5.PiecePrefab)) { Logger.LogError((object)"iron_wall_1x1 not found; nursery not added."); return; } val5.Piece.m_category = (PieceCategory)0; val5.Piece.m_usage = (UsageTagFlags)1; if (!BuildCube(val5.PiecePrefab, prefab)) { Logger.LogError((object)"iron_wall_1x1 or wood_floor_1x1 visuals not found; nursery not added."); return; } AddContainer(val5.PiecePrefab, val); val5.PiecePrefab.AddComponent<NurseryFoodVisual>(); val5.PiecePrefab.AddComponent<NurseryStation>(); PieceManager.Instance.AddPiece(val5); } private static void AddContainer(GameObject prefab, Container chest) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) Container obj = prefab.AddComponent<Container>(); obj.m_name = "$leashme_nursery"; obj.m_bkg = chest.m_bkg; obj.m_width = 1; obj.m_height = 1; obj.m_openEffects = chest.m_openEffects; obj.m_closeEffects = chest.m_closeEffects; obj.m_privacy = chest.m_privacy; obj.m_checkGuardStone = chest.m_checkGuardStone; obj.m_autoDestroyEmpty = false; } private static bool BuildCube(GameObject prefab, GameObject floor) { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0114: 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_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) Transform root = prefab.transform; WearNTear component = prefab.GetComponent<WearNTear>(); BoxCollider component2 = prefab.GetComponent<BoxCollider>(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2) || States.Any((string s) => !Object.op_Implicit((Object)(object)root.Find(s)) || !Object.op_Implicit((Object)(object)floor.transform.Find(s)))) { return false; } int layer = prefab.layer; GameObject[] array = (GameObject[])(object)new GameObject[States.Length]; float num = -0.5f; for (int num2 = 0; num2 < States.Length; num2++) { GameObject gameObject = ((Component)root.Find(States[num2])).gameObject; GameObject gameObject2 = ((Component)floor.transform.Find(States[num2])).gameObject; GameObject val = new GameObject(States[num2]) { layer = layer }; val.transform.SetParent(root, false); AddPart(root, val.transform, gameObject, Quaternion.identity, Vector3.forward); AddPart(root, val.transform, gameObject, Quaternion.Euler(0f, 180f, 0f), Vector3.back); AddPart(root, val.transform, gameObject, Quaternion.Euler(0f, 90f, 0f), Vector3.right); AddPart(root, val.transform, gameObject, Quaternion.Euler(0f, -90f, 0f), Vector3.left); AddPart(root, val.transform, gameObject, Quaternion.Euler(90f, 0f, 0f), Vector3.up); GameObject part = AddPart(root, val.transform, gameObject2, Quaternion.identity, Vector3.down); if (num2 == 0) { Bounds val2 = LocalBounds(root, part); num = ((Bounds)(ref val2)).max.y; } val.SetActive(gameObject.activeSelf); array[num2] = val; } foreach (string item in States.Concat(new string[1] { "Destruction" })) { Transform val3 = root.Find(item); if (Object.op_Implicit((Object)(object)val3)) { Object.DestroyImmediate((Object)(object)((Component)val3).gameObject); } } component.m_health *= 5f; component.m_new = array[0]; component.m_worn = array[1]; component.m_broken = array[2]; component.m_fragmentRoots = null; component2.center = Vector3.zero; component2.size = Vector3.one; ReplaceSnapPoints(prefab); GameObject val4 = new GameObject("FoodAnchor") { layer = layer }; val4.transform.SetParent(root, false); val4.transform.localPosition = new Vector3(0f, num, 0f); return true; } private static GameObject AddPart(Transform root, Transform cube, GameObject source, Quaternion rotation, Vector3 face) { //IL_00de: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(source, cube, false); ((Object)val).name = ((Object)source).name; val.SetActive(true); LODGroup[] componentsInChildren = val.GetComponentsInChildren<LODGroup>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } foreach (Transform item in (from t in val.GetComponentsInChildren<Transform>(true) where ((Object)t).name == "lod" select t).ToList()) { Object.DestroyImmediate((Object)(object)((Component)item).gameObject); } Transform[] componentsInChildren2 = val.GetComponentsInChildren<Transform>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { ((Component)componentsInChildren2[i]).gameObject.layer = ((Component)cube).gameObject.layer; } val.transform.localPosition = Vector3.zero; val.transform.localRotation = rotation; Bounds val2 = LocalBounds(root, val); float num = Vector3.Dot(((Bounds)(ref val2)).extents, new Vector3(Mathf.Abs(face.x), Mathf.Abs(face.y), Mathf.Abs(face.z))); val.transform.localPosition = -((Bounds)(ref val2)).center + face * (0.5f - num); return val; } public static Bounds LocalBounds(Transform root, GameObject part) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0046: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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) Bounds result = default(Bounds); bool flag = true; MeshFilter[] componentsInChildren = part.GetComponentsInChildren<MeshFilter>(true); foreach (MeshFilter val in componentsInChildren) { if (!Object.op_Implicit((Object)(object)val.sharedMesh)) { continue; } Matrix4x4 val2 = root.worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix; Bounds bounds = val.sharedMesh.bounds; for (int j = 0; j < 8; j++) { Vector3 val3 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3(((j & 1) == 0) ? (-1f) : 1f, ((j & 2) == 0) ? (-1f) : 1f, ((j & 4) == 0) ? (-1f) : 1f)); Vector3 val4 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(val3); if (flag) { ((Bounds)(ref result))..ctor(val4, Vector3.zero); flag = false; } else { ((Bounds)(ref result)).Encapsulate(val4); } } } return result; } private static void ReplaceSnapPoints(GameObject prefab) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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) foreach (Transform item in (from t in prefab.GetComponentsInChildren<Transform>(true) where ((Component)t).CompareTag("snappoint") select t).ToList()) { Object.DestroyImmediate((Object)(object)((Component)item).gameObject); } for (int num = 0; num < 8; num++) { bool flag = (num & 4) != 0; GameObject val = new GameObject(string.Format("$hud_snappoint_{0} {1}", flag ? "top" : "bottom", (num & 3) + 1)) { layer = prefab.layer, tag = "snappoint" }; val.transform.SetParent(prefab.transform, false); val.transform.localPosition = new Vector3(((num & 1) == 0) ? 0.5f : (-0.5f), flag ? 0.5f : (-0.5f), ((num & 2) == 0) ? 0.5f : (-0.5f)); val.SetActive(false); } } } [BepInPlugin("de.evabs.valheim.leashme.nursery", "LeashMe Nursery", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class NurseryPlugin : BaseUnityPlugin { public const string PluginGUID = "de.evabs.valheim.leashme.nursery"; public const string PluginName = "LeashMe Nursery"; public const string PluginVersion = "0.1.0"; public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization(); private void Awake() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) AddTranslations(); NurseryPiece.Register(); new Harmony("de.evabs.valheim.leashme.nursery").PatchAll(typeof(NurseryContainerPatches).Assembly); } private static void AddTranslations() { CustomLocalization localization = Localization; string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "leashme_nursery", "Nursery Beacon" }, { "leashme_nursery_desc", "Fill with adult animal food to attract youngs of that species." }, { "leashme_nursery_now", "Nursery now attracts $1" }, { "leashme_nursery_none", "Nursery no longer attracts animals" }, { "leashme_nursery_show", "Show animals" }, { "leashme_nursery_areas", "Show areas (15 s)" }, { "leashme_nursery_lost", "$1 $2 are no longer attracted to this nursery" }, { "leashme_nursery_young_boar", "piglets" }, { "leashme_nursery_young_wolf", "wolf cubs" }, { "leashme_nursery_young_lox", "lox calves" }, { "leashme_nursery_young_hen", "chicks" }, { "leashme_nursery_young_asksvin", "asksvin hatchlings" }, { "leashme_nursery_young_moose", "moose calves" }, { "leashme_nursery_station_boar", "Boar Nursery" }, { "leashme_nursery_station_wolf", "Wolf Nursery" }, { "leashme_nursery_station_lox", "Lox Nursery" }, { "leashme_nursery_station_hen", "Chicken Nursery" }, { "leashme_nursery_station_asksvin", "Asksvin Nursery" }, { "leashme_nursery_station_moose", "Moose Nursery" } }); CustomLocalization localization2 = Localization; text = "German"; localization2.AddTranslation(ref text, new Dictionary<string, string> { { "leashme_nursery", "Jungtier-Sammelplatz" }, { "leashme_nursery_desc", "Mit Futter für erwachsene Tiere füllen, um Jungtiere dieser Art anzulocken." }, { "leashme_nursery_now", "Der Sammelplatz lockt jetzt $1 an" }, { "leashme_nursery_none", "Der Sammelplatz lockt keine Tiere mehr an" }, { "leashme_nursery_show", "Tiere zeigen" }, { "leashme_nursery_areas", "Bereiche zeigen (15 s)" }, { "leashme_nursery_lost", "$1 $2 werden nicht mehr von diesem Sammelplatz angelockt" }, { "leashme_nursery_young_boar", "Ferkel" }, { "leashme_nursery_young_wolf", "Wolfsjunge" }, { "leashme_nursery_young_lox", "Loxkälber" }, { "leashme_nursery_young_hen", "Küken" }, { "leashme_nursery_young_asksvin", "Asksvin-Jungtiere" }, { "leashme_nursery_young_moose", "Elchkälber" }, { "leashme_nursery_station_boar", "Wildschwein-Sammelplatz" }, { "leashme_nursery_station_wolf", "Wolf-Sammelplatz" }, { "leashme_nursery_station_lox", "Lox-Sammelplatz" }, { "leashme_nursery_station_hen", "Hühner-Sammelplatz" }, { "leashme_nursery_station_asksvin", "Asksvin-Sammelplatz" }, { "leashme_nursery_station_moose", "Elch-Sammelplatz" } }); } } internal class NurseryStation : MonoBehaviour { internal struct Lease { public ZDOID Animal; public long RequestId; public double Expiry; public int Grant; } public const string RequestRpc = "LeashMe_NurseryRequest"; public const string RenewRpc = "LeashMe_NurseryRenew"; public const string NumberRpc = "LeashMe_NurseryNumber"; private const float NumberRetrySeconds = 10f; public const float LeaseSeconds = 30f; private const float RenewWriteSeconds = 5f; private const float PriorityWindowSeconds = 60f; private const float MaxTargetDrop = 6f; private static readonly int LeasesKey = StringExtensionMethods.GetStableHashCode("LeashMe_nurseryLeases"); private static readonly int GenerationKey = StringExtensionMethods.GetStableHashCode("LeashMe_nurseryGen"); public static readonly int MemberKey = StringExtensionMethods.GetStableHashCode("LeashMe_nurseryMember"); public static readonly int MemberGenerationKey = StringExtensionMethods.GetStableHashCode("LeashMe_nurseryMemberGen"); private static int s_groundMask; public static readonly List<NurseryStation> All = new List<NurseryStation>(); private ZNetView m_nview; private Container m_container; private Transform m_anchor; private uint m_cacheRevision = uint.MaxValue; private double m_cacheValidUntil; private readonly List<Lease> m_leases = new List<Lease>(); private int m_generation; private bool m_inUse; private NurseryFood.Species m_species; private int m_capacity; private readonly Dictionary<ZDOID, long> m_renewals = new Dictionary<ZDOID, long>(); private float m_renewWriteTimer; private float m_numberTimer; private bool m_windowChecked; private float m_windowStart = -1f; private int m_reserved; private int m_windowGeneration; private readonly HashSet<ZDOID> m_freeShare = new HashSet<ZDOID>(); private static readonly RaycastHit[] s_hits = (RaycastHit[])(object)new RaycastHit[16]; private const string AreaSourcePrefab = "piece_workbench"; public const float AreaHoverSeconds = 0.5f; public const float AreaKeySeconds = 15f; private CircleProjector m_pickupArea; private CircleProjector m_breedArea; private CircleProjector m_moveArea; private float m_areasUntil; private static bool s_areaSourceMissing; private const float ConnectionsSeconds = 10f; private const float ConnectionHoverSeconds = 0.5f; private static GameObject s_beamPrefab; private static bool s_beamSearched; private static readonly Dictionary<ZDOID, Character> s_wanted = new Dictionary<ZDOID, Character>(); private static readonly List<ZDOID> s_removed = new List<ZDOID>(); private float m_connectionsUntil; private readonly Dictionary<ZDOID, float> m_hoverUntil = new Dictionary<ZDOID, float>(); private readonly Dictionary<ZDOID, GameObject> m_beams = new Dictionary<ZDOID, GameObject>(); public int Number { get { if (!IsValid) { return 0; } return m_nview.GetZDO().GetInt(NurseryNumbers.NumberKey, 0); } } public string DisplayName { get { NurseryFood.Species species = Species; return Localization.instance.Localize((species != null) ? species.StationName : "$leashme_nursery"); } } public bool IsValid { get { if (Object.op_Implicit((Object)(object)m_nview)) { return m_nview.IsValid(); } return false; } } public ZNetView NetView => m_nview; public NurseryFood.Species Species { get { Refresh(); return m_species; } } public bool InUse { get { Refresh(); return m_inUse; } } public int Generation { get { Refresh(); return m_generation; } } public int Occupied { get { Refresh(); return m_leases.Count; } } public int Capacity { get { Refresh(); return m_capacity; } } public bool HasFreePlace => Capacity > Occupied; private Vector3 Floor { get { //IL_001f: 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) if (!Object.op_Implicit((Object)(object)m_anchor)) { return ((Component)this).transform.position; } return m_anchor.position; } } private void Awake() { m_nview = ((Component)this).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)m_nview) && m_nview.GetZDO() != null) { m_container = ((Component)this).GetComponent<Container>(); m_anchor = ((Component)this).transform.Find("FoodAnchor"); m_nview.Register<ZDOID, long, int>("LeashMe_NurseryRequest", (Action<long, ZDOID, long, int>)RPC_Request); m_nview.Register<ZDOID, long, int>("LeashMe_NurseryRenew", (Action<long, ZDOID, long, int>)RPC_Renew); m_nview.Register<int>("LeashMe_NurseryNumber", (Action<long, int>)RPC_SetNumber); All.Add(this); } } public static NurseryStation Of(ZDOID animal) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) foreach (NurseryStation item in All) { if (item.IsValid && item.LeaseOf(animal) != 0L) { return item; } } return null; } private void UpdateNumber() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (m_nview.IsValid() && m_nview.IsOwner() && Number == 0) { m_numberTimer -= Time.deltaTime; if (!(m_numberTimer > 0f)) { m_numberTimer = 10f; NurseryNumbers.Request(m_nview.GetZDO().m_uid); } } } private void RPC_SetNumber(long sender, int number) { if (m_nview.IsValid() && m_nview.IsOwner() && Number == 0 && number > 0) { m_nview.GetZDO().Set(NurseryNumbers.NumberKey, number, false); } } private void Start() { Inventory val = (Object.op_Implicit((Object)(object)m_container) ? m_container.GetInventory() : null); if (val != null) { val.m_onChanged = (Action)Delegate.Combine(val.m_onChanged, new Action(OnInventoryChanged)); } } private void OnDestroy() { if (All.Remove(this) && All.Count == 0) { NurseryAnimals.ReleaseAll(); } Inventory val = (Object.op_Implicit((Object)(object)m_container) ? m_container.GetInventory() : null); if (val != null) { val.m_onChanged = (Action)Delegate.Remove(val.m_onChanged, new Action(OnInventoryChanged)); } foreach (GameObject value in m_beams.Values) { Object.Destroy((Object)(object)value); } } private void UpdateGeneration() { if (m_nview.IsValid() && m_nview.IsOwner() && m_nview.GetZDO().GetInt(GenerationKey, 0) == 0) { m_nview.GetZDO().Set(GenerationKey, NewGeneration(0), false); } } private static int NewGeneration(int current) { int num; do { num = Random.Range(1, int.MaxValue); } while (num == current); return num; } private void Update() { //IL_012a: Unknown result type (might be due to invalid IL or missing references) UpdateNumber(); UpdateGeneration(); ClearStaleInUse(); if (m_beams.Count > 0 || m_connectionsUntil > 0f || m_hoverUntil.Count > 0) { UpdateBeams(); } if (!m_windowChecked && SessionId() != 0L) { m_windowChecked = true; m_reserved = ((Number > 0 && m_nview.IsValid()) ? StoredCount() : 0); if (m_reserved > 0) { m_windowStart = Time.time; m_windowGeneration = m_nview.GetZDO().GetInt(GenerationKey, 0); } } if (m_renewals.Count == 0) { return; } if (!m_nview.IsValid() || !m_nview.IsOwner()) { m_renewals.Clear(); return; } m_renewWriteTimer -= Time.deltaTime; if (m_renewWriteTimer > 0f) { return; } List<Lease> list = ReadValid(); double expiry = Now() + 30.0; for (int i = 0; i < list.Count; i++) { Lease value = list[i]; if (m_renewals.TryGetValue(value.Animal, out var value2) && value2 == value.RequestId) { value.Expiry = expiry; list[i] = value; } } m_renewals.Clear(); Write(list, ReadNextGrant()); } public long LeaseOf(ZDOID animal) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) Refresh(); foreach (Lease lease in m_leases) { if (lease.Animal == animal) { return lease.RequestId; } } return 0L; } public bool TryGetTargetPoint(out Vector3 point) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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) //IL_003c: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) int num = Physics.RaycastNonAlloc(Floor + Vector3.up * 0.05f, Vector3.down, s_hits, 6.05f, GroundMask(), (QueryTriggerInteraction)1); float num2 = float.MaxValue; point = Vector3.zero; for (int i = 0; i < num; i++) { if (((RaycastHit)(ref s_hits[i])).distance < num2 && !((Component)((RaycastHit)(ref s_hits[i])).collider).transform.IsChildOf(((Component)this).transform)) { num2 = ((RaycastHit)(ref s_hits[i])).distance; point = ((RaycastHit)(ref s_hits[i])).point; } } return num2 < float.MaxValue; } public bool TryGetGround(Vector3 position, float centerHeight, out float height) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_00a4: Unknown result type (might be due to invalid IL or missing references) float y = Floor.y; int num = Physics.RaycastNonAlloc(new Vector3(position.x, y + 6f, position.z), Vector3.down, s_hits, 12f, GroundMask(), (QueryTriggerInteraction)1); float num2 = float.MaxValue; height = 0f; for (int i = 0; i < num; i++) { float num3 = Mathf.Abs(((RaycastHit)(ref s_hits[i])).point.y - centerHeight); if (num3 < num2 && !((Component)((RaycastHit)(ref s_hits[i])).collider).transform.IsChildOf(((Component)this).transform)) { num2 = num3; height = ((RaycastHit)(ref s_hits[i])).point.y; } } return num2 < float.MaxValue; } public bool InTargetHeight(float y) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return Mathf.Abs(y - Floor.y) <= 6f; } private static int GroundMask() { if (s_groundMask == 0) { s_groundMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "terrain", "piece", "vehicle" }); } return s_groundMask; } public void ShowAreas(float seconds) { if (Species == null) { HideAreas(); return; } m_areasUntil = Mathf.Max(m_areasUntil, Time.time + seconds); UpdateAreas(); } private void UpdateAreas() { NurseryFood.Species species = Species; if (species == null || !CreateAreas()) { HideAreas(); return; } SetArea(m_pickupArea, species.PickupRadius); float breedFreeRadius = species.BreedFreeRadius; if (breedFreeRadius > 0f) { SetArea(m_breedArea, breedFreeRadius); } else { ((Component)m_breedArea).gameObject.SetActive(false); } SetArea(m_moveArea, species.MoveRadius); ((MonoBehaviour)this).CancelInvoke("HideAreas"); ((MonoBehaviour)this).Invoke("HideAreas", m_areasUntil - Time.time); } private void HideAreas() { m_areasUntil = 0f; ((MonoBehaviour)this).CancelInvoke("HideAreas"); if (Object.op_Implicit((Object)(object)m_pickupArea)) { ((Component)m_pickupArea).gameObject.SetActive(false); ((Component)m_breedArea).gameObject.SetActive(false); ((Component)m_moveArea).gameObject.SetActive(false); } } private bool CreateAreas() { if (Object.op_Implicit((Object)(object)m_pickupArea)) { return true; } GameObject val = ((!s_areaSourceMissing && Object.op_Implicit((Object)(object)ZNetScene.instance)) ? ZNetScene.instance.GetPrefab("piece_workbench") : null); CraftingStation val3 = default(CraftingStation); CircleProjector val2 = ((Object.op_Implicit((Object)(object)val) && val.TryGetComponent<CraftingStation>(ref val3) && Object.op_Implicit((Object)(object)val3.m_areaMarker)) ? val3.m_areaMarker.GetComponent<CircleProjector>() : null); if (!Object.op_Implicit((Object)(object)val2)) { if (!s_areaSourceMissing) { s_areaSourceMissing = true; Logger.LogWarning((object)"Nursery area circle: no area marker at piece_workbench; areas are not shown."); } return false; } m_pickupArea = CreateArea(val2); m_breedArea = CreateArea(val2); m_moveArea = CreateArea(val2); return true; } private CircleProjector CreateArea(CircleProjector source) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) CircleProjector component = Object.Instantiate<GameObject>(((Component)source).gameObject, ((Component)this).transform.position, Quaternion.identity, ((Component)this).transform).GetComponent<CircleProjector>(); ((Component)component).gameObject.SetActive(false); ParticleSystem[] componentsInChildren = ((Component)component).GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val in componentsInChildren) { if ((Object)(object)((Component)val).gameObject != (Object)(object)((Component)component).gameObject) { Object.Destroy((Object)(object)((Component)val).gameObject); } } return component; } private static void SetArea(CircleProjector area, float radius) { if (area.m_radius != radius) { float num = area.m_radius / (float)area.m_nrOfSegments; area.m_radius = radius; area.m_nrOfSegments = Mathf.Max(8, Mathf.RoundToInt(radius / num)); } ((Component)area).gameObject.SetActive(true); } public void ShowConnections() { if (BeamPrefab()) { m_connectionsUntil = Time.time + 10f; } } public void ShowConnection(ZDOID animal) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (BeamPrefab()) { m_hoverUntil[animal] = Time.time + 0.5f; } } private static bool BeamPrefab() { if (!s_beamSearched && Object.op_Implicit((Object)(object)ZNetScene.instance)) { s_beamSearched = true; StationExtension val = default(StationExtension); foreach (GameObject prefab in ZNetScene.instance.m_prefabs) { if (Object.op_Implicit((Object)(object)prefab) && prefab.TryGetComponent<StationExtension>(ref val) && Object.op_Implicit((Object)(object)val.m_connectionPrefab)) { s_beamPrefab = val.m_connectionPrefab; break; } } if (!Object.op_Implicit((Object)(object)s_beamPrefab)) { Logger.LogWarning((object)"Nursery connection beam: no station extension with a connection prefab; beams are not shown."); } } return Object.op_Implicit((Object)(object)s_beamPrefab); } private void UpdateBeams() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0109: 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_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_0281: 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_0246: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) float time = Time.time; bool flag = time < m_connectionsUntil; if (!flag) { m_connectionsUntil = 0f; } s_removed.Clear(); foreach (KeyValuePair<ZDOID, float> item in m_hoverUntil) { if (item.Value <= time) { s_removed.Add(item.Key); } } foreach (ZDOID item2 in s_removed) { m_hoverUntil.Remove(item2); } Refresh(); s_wanted.Clear(); if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { Character value = default(Character); foreach (Lease lease in m_leases) { GameObject val = ((flag || m_hoverUntil.ContainsKey(lease.Animal)) ? ZNetScene.instance.FindInstance(lease.Animal) : null); if (Object.op_Implicit((Object)(object)val) && val.TryGetComponent<Character>(ref value)) { s_wanted[lease.Animal] = value; } } } s_removed.Clear(); foreach (KeyValuePair<ZDOID, GameObject> beam in m_beams) { if (!s_wanted.ContainsKey(beam.Key)) { s_removed.Add(beam.Key); } } foreach (ZDOID item3 in s_removed) { Object.Destroy((Object)(object)m_beams[item3]); m_beams.Remove(item3); } Vector3 position = ((Component)this).transform.position; foreach (KeyValuePair<ZDOID, Character> item4 in s_wanted) { if (!m_beams.TryGetValue(item4.Key, out var value2)) { value2 = Object.Instantiate<GameObject>(s_beamPrefab, position, Quaternion.identity); m_beams[item4.Key] = value2; } Vector3 val2 = item4.Value.GetCenterPoint() - position; value2.transform.SetPositionAndRotation(position, (((Vector3)(ref val2)).sqrMagnitude > 0f) ? Quaternion.LookRotation(val2) : Quaternion.identity); value2.transform.localScale = new Vector3(1f, 1f, ((Vector3)(ref val2)).magnitude); } } private void RPC_Request(long sender, ZDOID animal, long requestId, int generation) { //IL_0002: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) if (!CheckRequest(sender, animal, generation, out var zdo) || m_container.IsInUse()) { return; } List<Lease> list = ReadValid(); int num = ReadNextGrant(); for (int i = 0; i < list.Count; i++) { if (list[i].Animal == animal) { Lease value = list[i]; value.RequestId = requestId; list[i] = value; Write(list, num); return; } } int num2 = CurrentCapacity(); bool flag = InPriorityWindow() && (m_freeShare.Contains(animal) || !Remembers(zdo)); if (list.Count < num2 && (!flag || FreeShareHeld(list) < num2 - m_reserved)) { if (flag) { m_freeShare.Add(animal); } list.Add(new Lease { Animal = animal, RequestId = requestId, Expiry = Now() + 30.0, Grant = num }); Write(list, num + 1); } } private void RPC_Renew(long sender, ZDOID animal, long requestId, int generation) { //IL_0002: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if (!CheckRequest(sender, animal, generation, out var _)) { return; } foreach (Lease item in ReadValid()) { if (item.Animal == animal && item.RequestId == requestId) { if (m_renewals.Count == 0) { m_renewWriteTimer = 5f; } m_renewals[animal] = requestId; break; } } } private bool CheckRequest(long sender, ZDOID animal, int generation, out ZDO zdo) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) zdo = null; if (!m_nview.IsOwner() || SessionId() == 0L || generation != m_nview.GetZDO().GetInt(GenerationKey, 0)) { return false; } zdo = ZDOMan.instance.GetZDO(animal); if (zdo == null || zdo.GetOwner() != sender || !zdo.GetBool(ZDOVars.s_tamed, false)) { return false; } GameObject prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab()); NurseryFood.Species species = StoredSpecies(); if (species != null) { return NurseryFood.FindYoung(prefab) == species; } return false; } private bool InPriorityWindow() { if (m_windowStart >= 0f && Time.time - m_windowStart < 60f) { return m_nview.GetZDO().GetInt(GenerationKey, 0) == m_windowGeneration; } return false; } private int FreeShareHeld(List<Lease> leases) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) int num = 0; foreach (Lease lease in leases) { if (m_freeShare.Contains(lease.Animal)) { num++; } } return num; } private int StoredCount() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown byte[] byteArray = m_nview.GetZDO().GetByteArray(LeasesKey, (byte[])null); if (byteArray == null) { return 0; } ZPackage val = new ZPackage(byteArray); val.ReadLong(); if (val.ReadInt() != m_nview.GetZDO().GetInt(GenerationKey, 0)) { return 0; } val.ReadInt(); return val.ReadInt(); } private bool Remembers(ZDO animal) { if (animal.GetInt(MemberKey, 0) == Number) { return animal.GetInt(MemberGenerationKey, 0) == m_nview.GetZDO().GetInt(GenerationKey, 0); } return false; } private void OnInventoryChanged() { m_cacheRevision = uint.MaxValue; if (m_areasUntil > Time.time) { UpdateAreas(); } if (!m_nview.IsValid() || !m_nview.IsOwner() || SessionId() == 0L) { return; } ZDO zDO = m_nview.GetZDO(); if (m_container.GetInventory().m_inventory.Count == 0) { if (zDO.GetByteArray(LeasesKey, (byte[])null) != null) { zDO.RemoveByteArray(LeasesKey); zDO.Set(GenerationKey, NewGeneration(zDO.GetInt(GenerationKey, 0)), false); m_renewals.Clear(); } return; } List<Lease> list = ReadValid(); int num = CurrentCapacity(); if (list.Count > num) { int count = list.Count - num; list.Sort((Lease a, Lease b) => a.Grant.CompareTo(b.Grant)); list.RemoveRange(num, count); Write(list, ReadNextGrant()); NurseryFood.Species species = StoredSpecies(); if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && species != null) { ((Character)Player.m_localPlayer).Message((MessageType)2, Localization.instance.Localize("$leashme_nursery_lost", new string[2] { count.ToString(), Localization.instance.Localize(species.YoungName) }), 0, (Sprite)null, false); } } } private bool IsChestOpen() { return m_nview.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 1; } private void ClearStaleInUse() { if (m_nview.IsValid() && m_nview.IsOwner() && !m_container.IsInUse() && IsChestOpen()) { m_nview.GetZDO().Set(ZDOVars.s_inUse, 0, false); } } private NurseryFood.Species StoredSpecies() { Inventory val = (Object.op_Implicit((Object)(object)m_container) ? m_container.GetInventory() : null); if (val == null || val.m_inventory.Count <= 0) { return null; } return NurseryFood.Find(val.m_inventory[0]); } private int CurrentCapacity() { Inventory val = (Object.op_Implicit((Object)(object)m_container) ? m_container.GetInvento