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 Offspring Portal v1.4.4
OffspringPortal.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using OffspringPortal.UI; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("OffspringPortal")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Automatically teleports juvenile animals from breeding pens to configured grow-up pens.")] [assembly: AssemblyFileVersion("1.4.4.0")] [assembly: AssemblyInformationalVersion("1.4.4+f5f268a123fc599d22c0d0c9ecc6bdf9303bf553")] [assembly: AssemblyProduct("OffspringPortal")] [assembly: AssemblyTitle("OffspringPortal")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.4.4.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace OffspringPortal { public static class AdultPortalRouter { public static bool IsAdultRoutingMaturingPortal(OPTeleportWorld portal) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)portal == (Object)null) { return false; } ZNetView component = ((Component)portal).GetComponent<ZNetView>(); ZDO val = ((component != null) ? component.GetZDO() : null); if (val == null || !PortalConfigGate.IsConfiguredForAutomation(val)) { return false; } PortalRecord portalRecord = DestinationRegistry.Get(val.m_uid); if (portalRecord != null) { if (portalRecord.Role == PortalRole.Maturing) { return portalRecord.AdultDestination != AdultDestination.None; } return false; } if (PortalRoleCatalog.FromZdo(val) == PortalRole.Maturing) { return PortalRoleCatalog.GetAdultDestination(val) != AdultDestination.None; } return false; } public static bool TryRoute(OPTeleportWorld portal, Character character, Dictionary<int, float> cooldowns, ref float lastNoDestinationMessageTime) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: 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_00f1: 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_0136: 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) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013d: 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_014b: 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_016c: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)portal == (Object)null || (Object)(object)character == (Object)null || !OffspringPortalPrefabs.IsOffspringPortal(portal)) { return false; } if (!SpeciesHelper.IsEligibleAdult(character)) { return false; } ZNetView component = ((Component)portal).GetComponent<ZNetView>(); PortalRecord portalRecord = (((Object)(object)component != (Object)null) ? DestinationRegistry.Get(component.GetZDO()?.m_uid ?? ZDOID.None) : null); if (portalRecord == null || portalRecord.Role != PortalRole.Maturing || portalRecord.AdultDestination == AdultDestination.None) { return false; } int instanceID = ((Object)character).GetInstanceID(); float time = Time.time; if (cooldowns.TryGetValue(instanceID, out var value) && time < value) { return false; } string adultSpeciesKey = SpeciesHelper.GetAdultSpeciesKey(character); if (!SpeciesHelper.SpeciesKeyMatches(adultSpeciesKey, portalRecord.DeclaredSpeciesKey)) { return false; } ZNetView nview = character.GetNview(); ZDOID val = (ZDOID)(((??)((nview == null) ? ((ZDOID?)null) : nview.GetZDO()?.m_uid)) ?? ZDOID.None); ZDOID val2 = (ZDOID)(((??)((component == null) ? ((ZDOID?)null) : component.GetZDO()?.m_uid)) ?? ZDOID.None); if (val == ZDOID.None || val2 == ZDOID.None) { return false; } if (ZNet.instance.IsServer()) { return TryRouteOnServer(portal, character, adultSpeciesKey, portalRecord, val, val2, cooldowns, ref lastNoDestinationMessageTime, time, instanceID); } if (!RoutingRpc.CanSendRequests()) { return false; } RoutingRpc.RequestAdultRoute(val, val2, adultSpeciesKey); cooldowns[instanceID] = time + ModConfig.TeleportCooldownSec.Value; return false; } public static bool ExecuteApprovedRoute(ZDOID characterId, ZDOID sourcePortalId, PortalRecord destination, Character character = null, OPTeleportWorld sourcePortal = null) { //IL_0003: 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_0085: Unknown result type (might be due to invalid IL or missing references) if (character == null) { character = ResolveCharacter(characterId); } if (sourcePortal == null) { sourcePortal = ResolvePortal(sourcePortalId); } if ((Object)(object)character == (Object)null || (Object)(object)sourcePortal == (Object)null || destination == null) { return false; } PortalRecord portalRecord = DestinationRegistry.Get(sourcePortalId); if (portalRecord == null || portalRecord.Role != PortalRole.Maturing) { return false; } string adultSpeciesKey = SpeciesHelper.GetAdultSpeciesKey(character); if (!SpeciesHelper.SpeciesKeyMatches(adultSpeciesKey, portalRecord.DeclaredSpeciesKey)) { return false; } if (!JuvenileTeleporter.TryExecuteApproved(character, destination, sourcePortal)) { return false; } OffspringPortalPlugin.Log.LogInfo((object)$"Teleported {SpeciesKey.GetDisplayName(adultSpeciesKey)} adult to {portalRecord.AdultDestination} portal at {destination.Position}."); PlayPortalActivation(sourcePortal); return true; } private static bool TryRouteOnServer(OPTeleportWorld portal, Character character, string speciesKey, PortalRecord source, ZDOID characterId, ZDOID sourcePortalId, Dictionary<int, float> cooldowns, ref float lastNoDestinationMessageTime, float now, int bodyId) { //IL_0048: 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) PortalRecord destination; switch (source.AdultDestination) { case AdultDestination.Farm: if (!DestinationRegistry.TryResolveFarmDestination(speciesKey, out destination)) { string message = "No Farm portal exists."; return WarnMissingDestination(now, ref lastNoDestinationMessageTime, message); } break; case AdultDestination.Cull: if (!DestinationRegistry.TryResolveCullDestination(out destination)) { string message = "No Cull portal exists."; return WarnMissingDestination(now, ref lastNoDestinationMessageTime, message); } break; default: return false; } if (ExecuteApprovedRoute(characterId, sourcePortalId, destination, character, portal)) { cooldowns[bodyId] = now + ModConfig.TeleportCooldownSec.Value; return true; } OffspringPortalPlugin.Log.LogWarning((object)("Failed to teleport " + SpeciesKey.GetDisplayName(speciesKey) + " adult.")); return false; } private static bool WarnMissingDestination(float now, ref float lastMessageTime, string message) { if (now - lastMessageTime <= 5f) { return false; } lastMessageTime = now; OffspringPortalPlugin.Log.LogWarning((object)message); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)2, message, 0, (Sprite)null, false); } return false; } private static Character ResolveCharacter(ZDOID characterId) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.FindInstance(characterId) : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<Character>(); } private static OPTeleportWorld ResolvePortal(ZDOID portalId) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.FindInstance(portalId) : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<OPTeleportWorld>(); } private static void PlayPortalActivation(OPTeleportWorld portal) { portal?.PlayActivationEffect(); } } public sealed class BreedableSpeciesInfo { public string Key; public string DisplayName; public bool IsEggLayer; public bool IsDualPurposeEgg; public string EggCollectorKey; public string EggPrefabName; public string AdultPrefabName; public string HatchlingPrefabName; } public static class BreedableSpeciesRegistry { private static readonly Dictionary<string, BreedableSpeciesInfo> RegisteredSpecies = new Dictionary<string, BreedableSpeciesInfo>(StringComparer.OrdinalIgnoreCase); public static void Clear() { RegisteredSpecies.Clear(); } public static void Register(BreedableSpeciesInfo info) { if (info != null && !string.IsNullOrWhiteSpace(info.Key)) { info.Key = SpeciesKey.Canonicalize(info.Key); if (string.IsNullOrEmpty(info.DisplayName)) { info.DisplayName = SpeciesKey.GetDisplayName(info.Key); } if (info.IsDualPurposeEgg) { info.EggCollectorKey = SpeciesKey.BuildEggCollectorKey(info.Key); } RegisteredSpecies[info.Key] = info; } } public static bool TryGet(string key, out BreedableSpeciesInfo info) { if (RegisteredSpecies.TryGetValue(key, out info)) { return true; } if (SpeciesKey.IsEggCollectorKey(key)) { string key2 = key.Substring("Egg:".Length); return RegisteredSpecies.TryGetValue(key2, out info); } return false; } public static bool TryGetByEggPrefab(string eggPrefabName, out BreedableSpeciesInfo info) { info = null; string value = SpeciesKey.Normalize(eggPrefabName); if (string.IsNullOrEmpty(value)) { return false; } foreach (BreedableSpeciesInfo value2 in RegisteredSpecies.Values) { if (value2.IsEggLayer && !string.IsNullOrEmpty(value2.EggPrefabName) && value2.EggPrefabName.Equals(value, StringComparison.OrdinalIgnoreCase)) { info = value2; return true; } } return false; } public static bool HasDualPurposeEggLayers() { return RegisteredSpecies.Values.Any((BreedableSpeciesInfo species) => species.IsDualPurposeEgg); } public static IReadOnlyList<string> GetMaturingOptionKeys() { List<string> list = RegisteredSpecies.Values.Select((BreedableSpeciesInfo species) => species.Key).Distinct<string>(StringComparer.OrdinalIgnoreCase).OrderBy<string, string>((string key) => SpeciesKey.GetDisplayName(key), StringComparer.OrdinalIgnoreCase) .ToList(); list.Add("All"); return list; } public static IReadOnlyList<string> GetEggCollectorOptionKeys() { return GetEggCollectorOptionKeys(null); } public static IReadOnlyList<string> GetEggCollectorOptionKeys(string additionalSpeciesKey) { HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (BreedableSpeciesInfo value in RegisteredSpecies.Values) { if (value.IsDualPurposeEgg && !string.IsNullOrEmpty(value.EggCollectorKey)) { hashSet.Add(value.EggCollectorKey); } } foreach (PortalRecord item in DestinationRegistry.GetAll()) { if (item.Role == PortalRole.EggCollector && !string.IsNullOrWhiteSpace(item.DeclaredSpeciesKey)) { string text = SpeciesKey.BuildEggCollectorKey(item.DeclaredSpeciesKey); if (!string.IsNullOrEmpty(text)) { hashSet.Add(text); } } } AddEggCollectorOptionKey(hashSet, additionalSpeciesKey); return hashSet.OrderBy<string, string>((string key) => SpeciesKey.GetEggCollectorDisplayName(key), StringComparer.OrdinalIgnoreCase).ToList(); } private static void AddEggCollectorOptionKey(HashSet<string> keys, string speciesKey) { if (!string.IsNullOrWhiteSpace(speciesKey)) { string text = SpeciesKey.BuildEggCollectorKey(speciesKey); if (!string.IsNullOrEmpty(text)) { keys.Add(text); } } } public static IReadOnlyList<string> GetMaturingOptionKeysWithFallback() { if (RegisteredSpecies.Count == 0) { return SpeciesCatalog.LegacyDestinationOptionKeys; } return GetMaturingOptionKeys(); } public static IReadOnlyList<string> GetDestinationOptionKeysWithFallback() { return GetMaturingOptionKeysWithFallback(); } public static void DiscoverInRange(Vector3 center, float range) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) float num = range * range; foreach (Character allCharacter in Character.GetAllCharacters()) { if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsPlayer()) { Vector3 val = ((Component)allCharacter).transform.position - center; if (!(((Vector3)(ref val)).sqrMagnitude > num) && (SpeciesDiscovery.TryDiscoverFromCharacter(allCharacter, out var info) || SpeciesDiscovery.TryDiscoverFallback(allCharacter, out info))) { Register(info); } } } } public static void RefreshFromAllBreeders() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) float discoveryScanRange = ModConfig.GetDiscoveryScanRange(); foreach (PortalRecord breederPortal in DestinationRegistry.GetBreederPortals()) { DiscoverInRange(breederPortal.Position, discoveryScanRange); } } } public static class BreedingCapData { public static int GetCapLimit(SpeciesType species) { return species switch { SpeciesType.Boar => 5, SpeciesType.Wolf => 4, SpeciesType.Lox => 4, SpeciesType.Chicken => 10, SpeciesType.Asksvin => 10, SpeciesType.Moose => 4, _ => 0, }; } public static float GetCapRadius(SpeciesType species) { switch (species) { case SpeciesType.Boar: case SpeciesType.Wolf: case SpeciesType.Chicken: case SpeciesType.Asksvin: return 10f; case SpeciesType.Lox: case SpeciesType.Moose: return 20f; default: return 0f; } } } public sealed class PortalRecord { public ZDOID Id; public Vector3 Position; public Quaternion Rotation = Quaternion.identity; public PortalRole Role; public SpeciesType DeclaredSpecies; public string DeclaredSpeciesKey; public AdultDestination AdultDestination; } public static class DestinationRegistry { private static readonly Dictionary<ZDOID, PortalRecord> Portals = new Dictionary<ZDOID, PortalRecord>(); private static readonly Dictionary<string, int> MaturingRoundRobinIndex = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, int> FarmRoundRobinIndex = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); private static int cullRoundRobinIndex; private static readonly Dictionary<string, int> EggCollectorRoundRobinIndex = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); private static float nextCapWarningRefreshTime; public static void Clear() { Portals.Clear(); } public static void RegisterOrUpdate(ZDOID id, Vector3 position, PortalRole role, SpeciesType declaredSpecies, AdultDestination adultDestination) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) string declaredSpeciesKey = ((declaredSpecies == SpeciesType.None) ? string.Empty : SpeciesCatalog.ToStorageValue(declaredSpecies)); RegisterOrUpdate(id, position, role, declaredSpeciesKey, adultDestination); } public static void RegisterOrUpdate(ZDOID id, Vector3 position, PortalRole role, string declaredSpeciesKey, AdultDestination adultDestination) { //IL_0005: 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_002a: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!Portals.TryGetValue(id, out var value)) { value = new PortalRecord { Id = id }; Portals[id] = value; } value.Position = position; value.Role = role; value.DeclaredSpeciesKey = NormalizeDeclaredSpeciesKey(role, declaredSpeciesKey); value.DeclaredSpecies = SpeciesCatalog.FromStorageValue(value.DeclaredSpeciesKey); value.AdultDestination = adultDestination; } public static void RegisterSnapshot(ZDOID id, Vector3 position, Quaternion rotation) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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) if (!(id == ZDOID.None)) { if (!Portals.TryGetValue(id, out var value)) { value = new PortalRecord { Id = id }; Portals[id] = value; } value.Position = position; value.Rotation = rotation; } } public static void Remove(ZDOID id) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) Portals.Remove(id); } public static PortalRecord Get(ZDOID id) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) Portals.TryGetValue(id, out var value); return value; } public static void RefreshPortalPosition(PortalRecord record) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (record != null && ZDOMan.instance != null) { ZDO val = ZdoIdUtility.TryGetZdo(record.Id); if (val != null) { record.Position = val.GetPosition(); record.Rotation = val.GetRotation(); } } } public static bool TryResolveMaturingDestination(SpeciesType juvenileSpecies, out PortalRecord destination) { return TryResolveMaturingDestination((juvenileSpecies == SpeciesType.None) ? string.Empty : SpeciesCatalog.ToStorageValue(juvenileSpecies), out destination); } public static bool TryResolveMaturingDestination(string speciesKey, out PortalRecord destination) { return TryResolveDestination(speciesKey, PortalRole.Maturing, MaturingRoundRobinIndex, out destination); } public static bool TryResolveFarmDestination(SpeciesType adultSpecies, out PortalRecord destination) { return TryResolveFarmDestination((adultSpecies == SpeciesType.None) ? string.Empty : SpeciesCatalog.ToStorageValue(adultSpecies), out destination); } public static bool TryResolveFarmDestination(string speciesKey, out PortalRecord destination) { return TryResolveDestination(speciesKey, PortalRole.Farm, FarmRoundRobinIndex, out destination); } public static bool TryResolveCullDestination(out PortalRecord destination) { destination = null; List<PortalRecord> list = (from p in Portals.Values where p.Role == PortalRole.Cull orderby ZdoIdUtility.Format(p.Id) select p).ToList(); if (list.Count == 0) { return false; } destination = list[cullRoundRobinIndex % list.Count]; cullRoundRobinIndex++; RefreshPortalPosition(destination); return true; } public static bool TryResolveEggCollectorDestination(string eggCollectorKey, out PortalRecord destination) { return TryResolveEggCollectorRoundRobin(new string[1] { eggCollectorKey ?? string.Empty }, BuildEggCollectorRoundRobinKey(eggCollectorKey), out destination); } public static bool TryResolveEggCollectorRoundRobin(IReadOnlyList<string> eggCollectorKeys, string roundRobinKey, out PortalRecord destination) { destination = null; if (eggCollectorKeys == null || eggCollectorKeys.Count == 0) { return false; } List<PortalRecord> list = CollectMatchingEggCollectors(eggCollectorKeys); if (list.Count == 0) { return false; } string key = (string.IsNullOrWhiteSpace(roundRobinKey) ? BuildEggCollectorRoundRobinKey(eggCollectorKeys[0]) : roundRobinKey); destination = PickRoundRobin(key, list, EggCollectorRoundRobinIndex); RefreshPortalPosition(destination); return destination != null; } internal static List<PortalRecord> CollectMatchingEggCollectors(IReadOnlyList<string> eggCollectorKeys) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) List<PortalRecord> list = new List<PortalRecord>(); HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); if (eggCollectorKeys == null) { return list; } foreach (string eggCollectorKey in eggCollectorKeys) { if (string.IsNullOrWhiteSpace(eggCollectorKey)) { continue; } foreach (PortalRecord matchingEggCollector in GetMatchingEggCollectors(eggCollectorKey)) { string item = ZdoIdUtility.Format(matchingEggCollector.Id); if (hashSet.Add(item)) { list.Add(matchingEggCollector); } } } list.Sort((PortalRecord left, PortalRecord right) => ZdoIdUtility.Compare(left.Id, right.Id)); return list; } private static List<PortalRecord> GetMatchingEggCollectors(string eggCollectorKey) { string normalizedEggKey = SpeciesKey.BuildEggCollectorKey(eggCollectorKey); string speciesKey = (SpeciesKey.IsEggCollectorKey(normalizedEggKey) ? normalizedEggKey.Substring("Egg:".Length) : SpeciesKey.Canonicalize(eggCollectorKey)); return (from p in Portals.Values where IsLivePortalRecord(p) && p.Role == PortalRole.EggCollector && PortalAcceptsEggCollector(p.DeclaredSpeciesKey, normalizedEggKey, speciesKey) orderby ZdoIdUtility.Format(p.Id) select p).ToList(); } private static string BuildEggCollectorRoundRobinKey(string eggCollectorKey) { string text = SpeciesKey.BuildEggCollectorKey(eggCollectorKey); if (!string.IsNullOrWhiteSpace(text)) { return text; } return SpeciesKey.Canonicalize(eggCollectorKey); } public static bool HasCullReceiver() { return Portals.Values.Any((PortalRecord p) => p.Role == PortalRole.Cull); } public static bool HasEggCollector() { return Portals.Values.Any((PortalRecord p) => p.Role == PortalRole.EggCollector); } public static bool HasFarmReceiver(SpeciesType maturingReceives) { return HasFarmReceiver((maturingReceives == SpeciesType.None) ? string.Empty : SpeciesCatalog.ToStorageValue(maturingReceives)); } public static bool HasFarmReceiver(string maturingReceivesKey) { if (!string.IsNullOrEmpty(maturingReceivesKey) && !maturingReceivesKey.Equals("All", StringComparison.OrdinalIgnoreCase) && TryResolveFarmDestination(maturingReceivesKey, out var destination)) { return true; } if (TryResolveFarmDestination("All", out destination)) { return true; } if (maturingReceivesKey != null && maturingReceivesKey.Equals("All", StringComparison.OrdinalIgnoreCase)) { return Portals.Values.Any((PortalRecord p) => p.Role == PortalRole.Farm); } return false; } public static IEnumerable<PortalRecord> GetBreederPortals() { return Portals.Values.Where((PortalRecord p) => p.Role == PortalRole.Breeder); } public static IEnumerable<PortalRecord> GetAll() { return Portals.Values; } public static string BuildSummaryCounts() { int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; using (Dictionary<ZDOID, PortalRecord>.ValueCollection.Enumerator enumerator = Portals.Values.GetEnumerator()) { while (enumerator.MoveNext()) { switch (enumerator.Current.Role) { case PortalRole.Maturing: num2++; break; case PortalRole.Farm: num3++; break; case PortalRole.Cull: num4++; break; case PortalRole.EggCollector: num5++; break; default: num++; break; } } } return $"{num} breeder(s), {num2} maturing, {num3} farm, {num4} cull, {num5} egg collector(s)"; } public static string FormatPortalRecord(PortalRecord record) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (record == null) { return " (null portal record)"; } string text = (string.IsNullOrEmpty(record.DeclaredSpeciesKey) ? "(none)" : record.DeclaredSpeciesKey); string text2 = (IsLivePortalRecord(record) ? "live" : "missing-zdo"); return $" {record.Role} receives={text} id={ZdoIdUtility.Format(record.Id)} pos=({record.Position.x:F1}, {record.Position.y:F1}, {record.Position.z:F1}) [{text2}]"; } public static void LogMaturingResolutionFailure(string speciesKey, string context) { DiagnosticLog.Warning("No maturing portal registered for '" + speciesKey + "' during " + context + ". Registry: " + BuildSummaryCounts() + "."); foreach (PortalRecord item in Portals.Values.Where((PortalRecord p) => p.Role == PortalRole.Maturing)) { DiagnosticLog.Warning(FormatPortalRecord(item)); } if (!Portals.Values.Any((PortalRecord p) => p.Role == PortalRole.Maturing)) { DiagnosticLog.Warning("No Maturing portals are registered on this game instance. Place/configure a Maturing portal and confirm the server log shows it after configuration."); } } public static void RefreshCapWarningsThrottled() { if (!(Time.time < nextCapWarningRefreshTime)) { nextCapWarningRefreshTime = Time.time + ModConfig.CapWarningRefreshIntervalSec.Value; RefreshCapWarnings(); } } public static void RefreshCapWarnings() { //IL_0092: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.EnableCapWarning.Value || ZDOMan.instance == null) { return; } foreach (PortalRecord destination in Portals.Values.Where((PortalRecord p) => p.Role == PortalRole.Maturing && !"All".Equals(p.DeclaredSpeciesKey, StringComparison.OrdinalIgnoreCase))) { SpeciesType species = destination.DeclaredSpecies; if (species != SpeciesType.None) { bool flag = GetBreederPortals().Any((PortalRecord source) => Vector3.Distance(source.Position, destination.Position) <= BreedingCapData.GetCapRadius(species)); ZDO val = ZdoIdUtility.TryGetZdo(destination.Id); if (val != null) { val.Set("op_cap_warning", flag); } } } } private static bool TryResolveDestination(string speciesKey, PortalRole requiredRole, Dictionary<string, int> roundRobinIndex, out PortalRecord destination) { destination = null; if (string.IsNullOrWhiteSpace(speciesKey)) { return false; } List<PortalRecord> list = (from p in Portals.Values where IsLivePortalRecord(p) && p.Role == requiredRole && !SpeciesKey.IsAll(p.DeclaredSpeciesKey) && SpeciesKey.PortalAcceptsSpecies(p.DeclaredSpeciesKey, speciesKey) orderby ZdoIdUtility.Format(p.Id) select p).ToList(); if (list.Count > 0) { destination = PickRoundRobin(speciesKey, list, roundRobinIndex); RefreshPortalPosition(destination); return destination != null; } List<PortalRecord> list2 = (from p in Portals.Values where IsLivePortalRecord(p) && p.Role == requiredRole && "All".Equals(p.DeclaredSpeciesKey, StringComparison.OrdinalIgnoreCase) orderby ZdoIdUtility.Format(p.Id) select p).ToList(); if (list2.Count > 0) { destination = PickRoundRobin("All", list2, roundRobinIndex); RefreshPortalPosition(destination); return destination != null; } return false; } internal static bool IsLivePortalRecord(PortalRecord record) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (record == null) { return false; } if (!ZdoIdUtility.IsValidId(record.Id)) { return false; } if (ZDOMan.instance == null) { return true; } ZDO val = ZdoIdUtility.TryGetZdo(record.Id); if (val == null) { if ((Object)(object)ZNet.instance != (Object)null) { return !ZNet.instance.IsServer(); } return false; } if (!val.IsValid()) { return false; } bool flag = val.GetPrefab() == StringExtensionMethods.GetStableHashCode("offspring_portal"); bool flag2 = !string.IsNullOrEmpty(val.GetString("op_portal_role", string.Empty)); return flag || flag2; } private static string NormalizeDeclaredSpeciesKey(PortalRole role, string declaredSpeciesKey) { if (role == PortalRole.EggCollector) { return SpeciesKey.BuildEggCollectorKey(declaredSpeciesKey); } return declaredSpeciesKey ?? string.Empty; } private static bool PortalAcceptsEggCollector(string portalSpeciesKey, string normalizedEggKey, string speciesKey) { if (string.IsNullOrWhiteSpace(portalSpeciesKey)) { return false; } if (SpeciesKey.PortalAcceptsEgg(portalSpeciesKey, normalizedEggKey)) { return true; } if (SpeciesKey.PortalAcceptsSpecies(portalSpeciesKey, speciesKey)) { return true; } return SpeciesKey.Canonicalize(portalSpeciesKey).Equals(speciesKey, StringComparison.OrdinalIgnoreCase); } private static PortalRecord PickRoundRobin(string key, List<PortalRecord> candidates, Dictionary<string, int> roundRobinIndex) { if (candidates.Count == 0) { return null; } if (!roundRobinIndex.TryGetValue(key, out var value)) { value = 0; } PortalRecord result = candidates[value % candidates.Count]; roundRobinIndex[key] = value + 1; return result; } } public static class DiagnosticLog { public static void Info(string message) { OPLog.Info(message); } public static void Warning(string message) { OPLog.Warning(message); } public static void Verbose(string message) { if (ModConfig.VerboseLogging.Value) { OPLog.Debug(message); } } public static bool ShouldLogRateLimited(ref float lastLogTime, float intervalSeconds) { float time = Time.time; if (time - lastLogTime < intervalSeconds) { return false; } lastLogTime = time; return true; } public static void LogPortalRegistry(string context, bool includeAllPortals = true) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("Portal registry snapshot (").Append(context).Append("): "); stringBuilder.Append(DestinationRegistry.BuildSummaryCounts()); Info(stringBuilder.ToString()); if (!includeAllPortals) { return; } foreach (PortalRecord item in DestinationRegistry.GetAll()) { Info(DestinationRegistry.FormatPortalRecord(item)); } } public static void LogNetworkContext(string context) { if ((Object)(object)ZNet.instance == (Object)null) { Verbose(context + ": ZNet not ready."); return; } string arg = ((!ZNet.instance.IsServer()) ? "client" : (ZNet.instance.IsDedicated() ? "dedicated server" : "listen server")); Verbose($"{context}: role={arg}, peers={ZNet.instance.GetNrOfPlayers()}."); } } public static class EggPortalRouter { public static bool TryRoute(OPTeleportWorld portal, ItemDrop egg, Dictionary<int, float> cooldowns, ref float lastNoDestinationMessageTime) { //IL_00ef: 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_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0166: 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_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)portal == (Object)null || (Object)(object)egg == (Object)null || !OffspringPortalPrefabs.IsOffspringPortal(portal)) { return false; } if ((Object)(object)((Component)egg).GetComponent<EggGrow>() == (Object)null) { return false; } if (!JuvenilePortalRouter.IsBreederPortal(portal)) { return false; } ZNetView component = ((Component)egg).GetComponent<ZNetView>(); ZDO val = ((component != null) ? component.GetZDO() : null); if (val != null && val.GetBool("op_transported", false) && !ModConfig.AllowRetransport.Value) { return false; } int instanceID = ((Object)egg).GetInstanceID(); float time = Time.time; if (!SpeciesDiscovery.TryGetEggSpeciesInfo(egg, out var info)) { if (time - lastNoDestinationMessageTime > 5f) { lastNoDestinationMessageTime = time; string text = SpeciesKey.Normalize(((Object)egg).name); OffspringPortalPlugin.Log.LogWarning((object)("Breeder portal could not classify egg '" + text + "' for routing (missing EggGrow chain or species not discovered).")); } return false; } if (cooldowns.TryGetValue(instanceID, out var value) && time < value) { return false; } ZDOID val2 = (ZDOID)(((??)((component == null) ? ((ZDOID?)null) : component.GetZDO()?.m_uid)) ?? ZDOID.None); ZNetView component2 = ((Component)portal).GetComponent<ZNetView>(); ZDOID val3 = (ZDOID)(((??)((component2 == null) ? ((ZDOID?)null) : component2.GetZDO()?.m_uid)) ?? ZDOID.None); if (val2 == ZDOID.None || val3 == ZDOID.None) { return false; } if (ZNet.instance.IsServer()) { return TryRouteOnServer(portal, egg, info, val2, val3, cooldowns, ref lastNoDestinationMessageTime, time, instanceID); } if (!RoutingRpc.CanSendRequests()) { return false; } RoutingRpc.RequestEggRoute(val2, val3, info.Key, info.IsDualPurposeEgg, info.EggCollectorKey); cooldowns[instanceID] = time + ModConfig.TeleportCooldownSec.Value; return false; } public static bool ExecuteApprovedRoute(ZDOID eggId, ZDOID sourcePortalId, PortalRecord destination, ItemDrop egg = null, OPTeleportWorld sourcePortal = null) { //IL_0003: 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_007f: Unknown result type (might be due to invalid IL or missing references) if (egg == null) { egg = ResolveEgg(eggId); } if (sourcePortal == null) { sourcePortal = ResolvePortal(sourcePortalId); } if ((Object)(object)egg == (Object)null || (Object)(object)sourcePortal == (Object)null || destination == null) { return false; } if (!JuvenilePortalRouter.IsBreederPortal(sourcePortal)) { return false; } if (!EggTeleporter.TryExecuteApproved(egg, destination, sourcePortal)) { return false; } if (SpeciesDiscovery.TryGetEggSpeciesInfo(egg, out var info)) { string arg = ((destination.Role == PortalRole.EggCollector) ? SpeciesKey.GetEggCollectorDisplayName(info.EggCollectorKey) : "maturing portal"); OffspringPortalPlugin.Log.LogInfo((object)$"Teleported {info.DisplayName} egg to {arg} at {destination.Position}."); } PlayPortalActivation(sourcePortal); return true; } private static bool TryRouteOnServer(OPTeleportWorld portal, ItemDrop egg, BreedableSpeciesInfo speciesInfo, ZDOID eggId, ZDOID sourcePortalId, Dictionary<int, float> cooldowns, ref float lastNoDestinationMessageTime, float now, int bodyId) { //IL_004a: 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) if (!EggRoutingResolver.TryResolveDestination(speciesInfo, out var destination)) { if (now - lastNoDestinationMessageTime > 5f) { lastNoDestinationMessageTime = now; string eggRoutingFailureMessage = GetEggRoutingFailureMessage(speciesInfo); OffspringPortalPlugin.Log.LogWarning((object)eggRoutingFailureMessage); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)2, eggRoutingFailureMessage, 0, (Sprite)null, false); } } return false; } if (ExecuteApprovedRoute(eggId, sourcePortalId, destination, egg, portal)) { cooldowns[bodyId] = now + ModConfig.TeleportCooldownSec.Value; return true; } return false; } private static string GetEggRoutingFailureMessage(BreedableSpeciesInfo speciesInfo) { if (speciesInfo.IsDualPurposeEgg && EggRoutingResolver.IsHenEgg(speciesInfo)) { if (DestinationRegistry.HasEggCollector()) { return EggRoutingResolver.GetHenRoutingFailureMessage(); } return "No Egg Collector or Maturing portal registered for Hen eggs."; } if (speciesInfo.IsDualPurposeEgg) { string eggCollectorDisplayName = SpeciesKey.GetEggCollectorDisplayName(speciesInfo.EggCollectorKey); return "No egg collector for " + eggCollectorDisplayName + " and no maturing fallback registered."; } return "No maturing portal registered for " + speciesInfo.DisplayName + " eggs."; } private static ItemDrop ResolveEgg(ZDOID eggId) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.FindInstance(eggId) : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<ItemDrop>(); } private static OPTeleportWorld ResolvePortal(ZDOID portalId) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.FindInstance(portalId) : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<OPTeleportWorld>(); } private static void PlayPortalActivation(OPTeleportWorld portal) { portal?.PlayActivationEffect(); } } public static class EggRecipeHelper { private static readonly string[] KnownDualPurposeEggPrefabs = new string[1] { "Egg" }; public static bool IsUsedInRecipe(SharedData shared) { if (shared == null || (Object)(object)ObjectDB.instance == (Object)null) { return false; } string name = shared.m_name; foreach (Recipe recipe in ObjectDB.instance.m_recipes) { if ((Object)(object)recipe == (Object)null || !recipe.m_enabled || recipe.m_resources == null) { continue; } Requirement[] resources = recipe.m_resources; foreach (Requirement val in resources) { if (!((Object)(object)val?.m_resItem == (Object)null)) { SharedData val2 = val.m_resItem.m_itemData?.m_shared; if (val2 != null && val2.m_name == name) { return true; } } } } return false; } public static bool IsUsedInRecipe(ItemDrop itemDrop) { if ((Object)(object)itemDrop == (Object)null) { return false; } if (IsKnownDualPurposeEggPrefab(((Object)itemDrop).name)) { return true; } return IsUsedInRecipe(itemDrop.m_itemData?.m_shared); } private static bool IsKnownDualPurposeEggPrefab(string prefabName) { string text = SpeciesKey.Normalize(prefabName); if (string.IsNullOrEmpty(text)) { return false; } string[] knownDualPurposeEggPrefabs = KnownDualPurposeEggPrefabs; foreach (string value in knownDualPurposeEggPrefabs) { if (text.Equals(value, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } } public static class EggRoutingResolver { private static readonly string[] HenEggCollectorLookupKeys = new string[4] { "Egg:Chicken", "Chicken", "Hen", "Egg:Hen" }; private const string HenEggCollectorRoundRobinKey = "Egg:Chicken"; public static bool IsHenEgg(BreedableSpeciesInfo speciesInfo) { if (speciesInfo == null) { return false; } return SpeciesKey.Canonicalize(speciesInfo.Key).Equals(SpeciesCatalog.ToStorageValue(SpeciesType.Chicken), StringComparison.OrdinalIgnoreCase); } public static bool TryResolveDestination(BreedableSpeciesInfo speciesInfo, out PortalRecord destination) { destination = null; if (speciesInfo == null) { return false; } if (speciesInfo.IsDualPurposeEgg && IsHenEgg(speciesInfo)) { if (TryResolveHenEggCollector(out destination)) { return true; } if (DestinationRegistry.HasEggCollector()) { return false; } return DestinationRegistry.TryResolveMaturingDestination(speciesInfo.Key, out destination); } if (speciesInfo.IsDualPurposeEgg) { if (DestinationRegistry.TryResolveEggCollectorDestination(speciesInfo.EggCollectorKey, out destination) || DestinationRegistry.TryResolveMaturingDestination(speciesInfo.Key, out destination)) { return destination != null; } return false; } return DestinationRegistry.TryResolveMaturingDestination(speciesInfo.Key, out destination); } public static string GetHenRoutingFailureMessage() { return "Hen egg not routed: an Egg Collector portal exists but none are configured for Hen eggs."; } private static bool TryResolveHenEggCollector(out PortalRecord destination) { return DestinationRegistry.TryResolveEggCollectorRoundRobin(HenEggCollectorLookupKeys, "Egg:Chicken", out destination); } } public static class EggTeleporter { public static bool TryTeleport(ItemDrop egg, PortalRecord destination, OPTeleportWorld sourcePortal) { return TryExecuteApproved(egg, destination, sourcePortal); } public static bool TryExecuteApproved(ItemDrop egg, PortalRecord destination, OPTeleportWorld sourcePortal) { //IL_001e: 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_0029: 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_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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)egg == (Object)null || destination == null || (Object)(object)sourcePortal == (Object)null) { return false; } DestinationRegistry.RefreshPortalPosition(destination); Vector3 exitPosition = PortalPlacement.GetExitPosition(destination.Id, sourcePortal); Quaternion exitRotation = PortalPlacement.GetExitRotation(destination.Id, sourcePortal); ZNetView component = ((Component)egg).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || component.GetZDO() == null) { return false; } if (!component.IsOwner()) { component.ClaimOwnership(); if (!component.IsOwner() && !ZNet.instance.IsServer()) { return false; } } Vector3 position = exitPosition + exitRotation * Vector3.right * Random.Range(-0.15f, 0.15f); ((Component)egg).transform.position = position; ((Component)egg).transform.rotation = exitRotation; ZDO zDO = component.GetZDO(); if (zDO != null) { zDO.SetPosition(position); zDO.SetRotation(exitRotation); zDO.Set("op_transported", true); } Rigidbody component2 = ((Component)egg).GetComponent<Rigidbody>(); if ((Object)(object)component2 != (Object)null) { component2.linearVelocity = Vector3.zero; component2.angularVelocity = Vector3.zero; } return true; } } public static class JuvenileFollow { internal const string LetsGoPluginGuid = "hardwire99.letsgo"; public static bool TryCommand(Character character, Player player, bool showMessage) { //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null || (Object)(object)player == (Object)null) { return false; } if (!ModConfig.EnableFollowCommand.Value) { DiagnosticLog.Verbose("Follow command ignored: EnableFollowCommand is off."); return false; } if (IsLetsGoLoaded()) { DiagnosticLog.Verbose("Follow command ignored: LetsGo mod is loaded."); return false; } if (!SpeciesHelper.IsEligibleJuvenile(character) || !character.IsTamed()) { DiagnosticLog.Verbose($"Follow command ignored for {character.GetHoverName()}: eligible={SpeciesHelper.IsEligibleJuvenile(character)}, tamed={character.IsTamed()}."); return false; } ZNetView nview = character.GetNview(); if ((Object)(object)nview == (Object)null || !nview.IsValid()) { DiagnosticLog.Verbose("Follow command ignored for " + character.GetHoverName() + ": invalid ZNetView."); return false; } JuvenileGroundSnapper.EnsureAttached(character); JuvenileFollowController.EnsureAttached(character); if (ZNet.instance.IsServer()) { DiagnosticLog.Verbose("Follow command handled locally on server for " + character.GetHoverName() + "."); return ApplyFollowToggle(character, player, showMessage); } string hoverName = character.GetHoverName(); ZDO zDO = nview.GetZDO(); DiagnosticLog.Verbose($"Follow command sending RPC for {hoverName} (owner={((zDO != null) ? zDO.GetOwner() : 0)})."); JuvenileFollowRpc.RequestToggle(nview.GetZDO().m_uid, ((Character)player).GetZDOID(), showMessage); return true; } public static bool ApplyFollowToggle(Character character, Player player, bool showMessage) { if ((Object)(object)character == (Object)null || (Object)(object)player == (Object)null) { return false; } if ((Object)(object)((Component)character).GetComponent<AnimalAI>() != (Object)null) { return ApplyAnimalFollowToggle(character, player, showMessage); } MonsterAI component = ((Component)character).GetComponent<MonsterAI>(); if ((Object)(object)component != (Object)null) { Tameable component2 = ((Component)character).GetComponent<Tameable>(); if ((Object)(object)component2 != (Object)null) { component2.m_commandable = true; } ApplyMonsterFollowToggle(character, component, player, showMessage); return true; } return false; } internal static bool IsLetsGoLoaded() { return Chainloader.PluginInfos.ContainsKey("hardwire99.letsgo"); } public static bool IsFollowing(Character character) { //IL_003b: 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) if ((Object)(object)character == (Object)null) { return false; } MonsterAI component = ((Component)character).GetComponent<MonsterAI>(); if ((Object)(object)component != (Object)null && (Object)(object)component.GetFollowTarget() != (Object)null) { return true; } ZDO zdo = character.GetZdo(); if (zdo != null) { return zdo.GetZDOID("op_follow_target") != ZDOID.None; } return false; } private static void ApplyMonsterFollowToggle(Character character, MonsterAI monsterAi, Player player, bool showMessage) { ZNetView component = ((Component)character).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && !component.IsOwner()) { component.ClaimOwnership(); } string hoverName = character.GetHoverName(); if ((Object)(object)monsterAi.GetFollowTarget() != (Object)null) { monsterAi.SetFollowTarget((GameObject)null); ((BaseAI)monsterAi).SetPatrolPoint(); if ((Object)(object)component != (Object)null && component.IsOwner()) { ZDO zDO = component.GetZDO(); if (zDO != null) { zDO.Set(ZDOVars.s_follow, string.Empty); } } if (showMessage) { ((Character)player).Message((MessageType)2, hoverName + " " + Localization.instance.Localize("$hud_tamestay"), 0, (Sprite)null, false); } return; } ((BaseAI)monsterAi).ResetPatrolPoint(); monsterAi.SetFollowTarget(((Component)player).gameObject); if ((Object)(object)component != (Object)null && component.IsOwner()) { ZDO zDO2 = component.GetZDO(); if (zDO2 != null) { zDO2.Set(ZDOVars.s_follow, player.GetPlayerName()); } } if (showMessage) { ((Character)player).Message((MessageType)2, hoverName + " " + Localization.instance.Localize("$hud_tamefollow"), 0, (Sprite)null, false); } } public static bool ApplyAnimalFollowToggle(Character character, Player player, bool showMessage) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_0094: 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) ZNetView nview = character.GetNview(); if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return false; } if (!nview.IsOwner()) { nview.ClaimOwnership(); } ZDO zdo = character.GetZdo(); if (zdo == null) { return false; } ZDOID zDOID = ((Character)player).GetZDOID(); ZDOID zDOID2 = zdo.GetZDOID("op_follow_target"); string hoverName = character.GetHoverName(); if (zDOID2 == zDOID) { zdo.Set("op_follow_target", ZDOID.None); if (showMessage) { ((Character)player).Message((MessageType)2, hoverName + " " + Localization.instance.Localize("$hud_tamestay"), 0, (Sprite)null, false); } } else { zdo.Set("op_follow_target", zDOID); if (showMessage) { ((Character)player).Message((MessageType)2, hoverName + " " + Localization.instance.Localize("$hud_tamefollow"), 0, (Sprite)null, false); } } return true; } } public sealed class JuvenileFollowController : MonoBehaviour { public static bool TryApplyAnimalFollow(AnimalAI animalAi, float dt) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_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_00b4: 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_00e1: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.EnableFollowCommand.Value || (Object)(object)animalAi == (Object)null) { return false; } Character component = ((Component)animalAi).GetComponent<Character>(); ZNetView component2 = ((Component)animalAi).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || !component2.IsValid()) { return false; } if (!component2.IsOwner()) { return false; } if (!SpeciesHelper.IsEligibleJuvenile(component) || !component.IsTamed()) { return false; } ZDO zdo = component.GetZdo(); if (zdo == null) { return false; } ZDOID zDOID = zdo.GetZDOID("op_follow_target"); if (zDOID == ZDOID.None) { return false; } Player val = ResolvePlayer(zDOID); if ((Object)(object)val == (Object)null) { return false; } Vector3 val2 = ((Component)val).transform.position - ((Component)component).transform.position; val2.y = 0f; float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude < 2f) { ((BaseAI)animalAi).StopMoving(); return true; } ((BaseAI)animalAi).MoveTowards(val2 / magnitude, magnitude > 10f); return true; } public static void EnsureAttached(Character character) { if (!((Object)(object)character == (Object)null) && !((Object)(object)((Component)character).GetComponent<AnimalAI>() == (Object)null) && (Object)(object)((Component)character).GetComponent<JuvenileFollowController>() == (Object)null) { ((Component)character).gameObject.AddComponent<JuvenileFollowController>(); } } private static Player ResolvePlayer(ZDOID followId) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.FindInstance(followId) : null); Player val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Player>() : null); if ((Object)(object)val2 != (Object)null) { return val2; } foreach (Player allPlayer in Player.GetAllPlayers()) { ZNetView val3 = ((Character)(object)allPlayer)?.GetNview(); if ((Object)(object)val3 != (Object)null) { ZDO zDO = val3.GetZDO(); if (zDO != null && zDO.m_uid == followId) { return allPlayer; } } } return null; } } public static class JuvenileFollowDisplay { public static void ApplyFollowHover(Character character, ref string hoverText) { if (ModConfig.EnableFollowCommand.Value && !JuvenileFollow.IsLetsGoLoaded() && !((Object)(object)character == (Object)null) && SpeciesHelper.IsEligibleJuvenile(character) && character.IsTamed() && (!((Object)(object)((Component)character).GetComponent<MonsterAI>() == (Object)null) || !((Object)(object)((Component)character).GetComponent<AnimalAI>() == (Object)null))) { string text = (JuvenileFollow.IsFollowing(character) ? "$hud_tamestay" : "$hud_tamefollow"); string newValue = Localization.instance.Localize(text); string text2 = Localization.instance.Localize("$hud_pet"); if (!string.IsNullOrEmpty(hoverText) && hoverText.Contains(text2)) { hoverText = hoverText.Replace(text2, newValue); } else if (!string.IsNullOrEmpty(hoverText)) { hoverText += Localization.instance.Localize("\n[<color=yellow><b>$KEY_Use</b></color>] " + text); } else { hoverText = Localization.instance.Localize(character.GetHoverName() + "\n[<color=yellow><b>$KEY_Use</b></color>] " + text); } } } } public static class JuvenileFollowRpc { private const string RpcToggleFollow = "OffspringPortal_ToggleJuvenileFollow"; private const string RpcExecuteToggleFollow = "OffspringPortal_ExecuteJuvenileFollow"; private static ZRoutedRpc registeredInstance; public static void Register() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null && registeredInstance != instance) { instance.Register<ZDOID, ZDOID, bool>("OffspringPortal_ToggleJuvenileFollow", (Action<long, ZDOID, ZDOID, bool>)OnToggleFollowRpc); instance.Register<ZDOID, ZDOID, bool>("OffspringPortal_ExecuteJuvenileFollow", (Action<long, ZDOID, ZDOID, bool>)OnExecuteToggleFollowRpc); registeredInstance = instance; DiagnosticLog.Info("Juvenile follow RPC handlers registered on current ZRoutedRpc instance."); } } public static void RequestToggle(ZDOID creatureId, ZDOID playerId, bool showMessage) { //IL_0045: 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_0060: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) if (ZRoutedRpc.instance == null) { DiagnosticLog.Warning("Cannot request juvenile follow toggle: ZRoutedRpc.instance is null."); return; } try { Register(); if ((Object)(object)ZNet.instance == (Object)null) { DiagnosticLog.Warning("Cannot request juvenile follow toggle: ZNet.instance is null."); return; } if (ZNet.instance.IsServer()) { DiagnosticLog.Verbose($"Local server handling juvenile follow request: creature={creatureId}, player={playerId}."); OnToggleFollowRpc(ZNet.GetUID(), creatureId, playerId, showMessage); return; } ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer == null || serverPeer.m_uid == 0L) { DiagnosticLog.Warning("Cannot send juvenile follow RPC: server peer unavailable."); return; } DiagnosticLog.Verbose($"Sending juvenile follow RPC to server peer {serverPeer.m_uid}: creature={creatureId}, player={playerId}."); ZRoutedRpc.instance.InvokeRoutedRPC(serverPeer.m_uid, "OffspringPortal_ToggleJuvenileFollow", new object[3] { creatureId, playerId, showMessage }); } catch (Exception exception) { OPLog.Exception("Failed to send juvenile follow RPC", exception); } } private static void OnToggleFollowRpc(long sender, ZDOID creatureId, ZDOID playerId, bool showMessage) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { DiagnosticLog.Warning($"Follow RPC reached a non-server peer unexpectedly. sender={sender}, creature={creatureId}"); return; } ZDOMan instance = ZDOMan.instance; ZDO obj = ((instance != null) ? instance.GetZDO(creatureId) : null); long num = ((obj != null) ? obj.GetOwner() : 0); DiagnosticLog.Verbose($"Server received follow request: sender={sender}, creature={creatureId}, owner={num}, player={playerId}."); if (num != 0L) { DiagnosticLog.Verbose($"Routing follow execution to ZDO owner {num}."); ZRoutedRpc.instance.InvokeRoutedRPC(num, "OffspringPortal_ExecuteJuvenileFollow", new object[3] { creatureId, playerId, showMessage }); } else { DiagnosticLog.Verbose("Follow target has no remote owner; applying on server."); ApplyToggle(creatureId, playerId, showMessage, sender); } } catch (Exception exception) { OPLog.Exception($"Server failed processing juvenile follow request from {sender}", exception); } } private static void OnExecuteToggleFollowRpc(long sender, ZDOID creatureId, ZDOID playerId, bool showMessage) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) try { DiagnosticLog.Verbose($"Executing juvenile follow RPC: sender={sender}, creature={creatureId}, player={playerId}."); ApplyToggle(creatureId, playerId, showMessage, sender); } catch (Exception exception) { OPLog.Exception($"Failed executing juvenile follow RPC for creature {creatureId}", exception); } } private static void ApplyToggle(ZDOID creatureId, ZDOID playerId, bool showMessage, long sender) { //IL_0000: 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_002e: 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) Character val = ResolveCreature(creatureId); Player val2 = ResolveRequestingPlayer(sender, playerId); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { DiagnosticLog.Warning($"Could not resolve follow RPC targets. creature={creatureId} resolved={(Object)(object)val != (Object)null}, player={playerId} resolved={(Object)(object)val2 != (Object)null}, sender={sender}."); } else if (!SpeciesHelper.IsEligibleJuvenile(val) || !val.IsTamed()) { DiagnosticLog.Verbose("Ignoring follow RPC for '" + val.GetHoverName() + "': not an eligible tamed juvenile."); } else { JuvenileGroundSnapper.EnsureAttached(val); JuvenileFollowController.EnsureAttached(val); JuvenileFollow.ApplyFollowToggle(val, val2, showMessage); } } private static Character ResolveCreature(ZDOID creatureId) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.FindInstance(creatureId) : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<Character>(); } private static Player ResolveRequestingPlayer(long sender, ZDOID playerId) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) Player player = Player.GetPlayer(sender); if ((Object)(object)player != (Object)null) { return player; } ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.FindInstance(playerId) : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<Player>(); } } public sealed class JuvenileGroundSnapper : MonoBehaviour { private Character character; private ZNetView nview; private float nextCheckTime; private void Awake() { character = ((Component)this).GetComponent<Character>(); nview = ((Component)this).GetComponent<ZNetView>(); } private void Start() { TrySnapToGround(force: true); } private void LateUpdate() { if (!(Time.time < nextCheckTime) && !((Object)(object)character == (Object)null) && !((Object)(object)nview == (Object)null) && nview.IsValid() && ZNet.instance.IsServer() && nview.IsOwner() && SpeciesHelper.IsEligibleJuvenile(character)) { nextCheckTime = Time.time + 1f; TrySnapToGround(force: false); } } public static void EnsureAttached(Character character) { if (!((Object)(object)character == (Object)null) && SpeciesHelper.IsEligibleJuvenile(character)) { JuvenileGroundSnapper juvenileGroundSnapper = ((Component)character).GetComponent<JuvenileGroundSnapper>(); if ((Object)(object)juvenileGroundSnapper == (Object)null) { juvenileGroundSnapper = ((Component)character).gameObject.AddComponent<JuvenileGroundSnapper>(); } juvenileGroundSnapper.TrySnapToGround(force: true); } } private void TrySnapToGround(bool force) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) if (JuvenilePlacement.TryGetFloorPosition(((Component)this).transform.position, out var grounded)) { float num = ((Component)this).transform.position.y - grounded.y; if (force || !(num < 0.35f)) { JuvenilePlacement.ApplyPosition(character, grounded, ((Component)this).transform.rotation); } } } } public static class JuvenileInteractHelper { private static ZDOID lastLoggedResolvedJuvenileId; private static bool hasLastLoggedResolvedJuvenileId; private static void LogResolvedJuvenile(Character juvenile, string source, float? distance = null) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_007f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)juvenile == (Object)null) { return; } ZNetView nview = juvenile.GetNview(); ZDO val = ((nview != null) ? nview.GetZDO() : null); if (val != null && (!hasLastLoggedResolvedJuvenileId || !(lastLoggedResolvedJuvenileId == val.m_uid))) { hasLastLoggedResolvedJuvenileId = true; lastLoggedResolvedJuvenileId = val.m_uid; if (distance.HasValue) { DiagnosticLog.Verbose($"Crosshair search resolved '{juvenile.GetHoverName()}' from {source} at {distance.Value:F2}m (id={val.m_uid})."); } else { DiagnosticLog.Verbose($"Crosshair search resolved '{juvenile.GetHoverName()}' from {source} (id={val.m_uid})."); } } } public static Character FindJuvenileUnderCrosshair(Player player, float maxDistance = 6f) { return FindTamedCharacterUnderCrosshair(player, maxDistance, juvenilesOnly: true); } public static Character FindTamedCharacterUnderCrosshair(Player player, float maxDistance, bool juvenilesOnly) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_003a: 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_00ce: 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_0105: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)GameCamera.instance == (Object)null) { return null; } Character hoverCreature = player.GetHoverCreature(); if (IsValidCandidate(hoverCreature, player, juvenilesOnly) && Vector3.Distance(((Character)player).m_eye.position, ((Component)hoverCreature).transform.position) <= maxDistance + 0.5f) { LogResolvedJuvenile(hoverCreature, "Player.GetHoverCreature()"); return hoverCreature; } Vector3 position = ((Component)GameCamera.instance).transform.position; Vector3 forward = ((Component)GameCamera.instance).transform.forward; RaycastHit[] source = Physics.RaycastAll(position, forward, Mathf.Max(0.1f, maxDistance), -1, (QueryTriggerInteraction)1); Character val = null; float num = maxDistance; foreach (RaycastHit item in source.OrderBy((RaycastHit h) => ((RaycastHit)(ref h)).distance)) { RaycastHit current = item; if ((Object)(object)((RaycastHit)(ref current)).collider == (Object)null) { continue; } Character characterFromCollider = GetCharacterFromCollider(((RaycastHit)(ref current)).collider); if (IsValidCandidate(characterFromCollider, player, juvenilesOnly)) { float num2 = Vector3.Distance(((Character)player).m_eye.position, ((RaycastHit)(ref current)).point); if (num2 <= num) { val = characterFromCollider; num = num2; } } } if ((Object)(object)val != (Object)null) { LogResolvedJuvenile(val, "raycast", num); } return val; } private static Character GetCharacterFromCollider(Collider collider) { if ((Object)(object)collider == (Object)null) { return null; } Character componentInParent = ((Component)collider).GetComponentInParent<Character>(); if ((Object)(object)componentInParent != (Object)null) { return componentInParent; } if ((Object)(object)collider.attachedRigidbody != (Object)null) { componentInParent = ((Component)collider.attachedRigidbody).GetComponentInParent<Character>(); } return componentInParent; } private static bool IsValidCandidate(Character character, Player player, bool juvenilesOnly) { if ((Object)(object)character == (Object)null || (Object)(object)character == (Object)(object)player || character.IsPlayer() || !character.IsTamed()) { return false; } if (juvenilesOnly) { return SpeciesHelper.IsEligibleJuvenile(character); } return (Object)(object)((Component)character).GetComponent<Tameable>() != (Object)null; } } public static class JuvenilePlacement { private static readonly int FloorMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "piece", "piece_nonsolid", "terrain", "water" }); public static bool TryGetFloorPosition(Vector3 position, out Vector3 grounded) { //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_0016: 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_0036: 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_005c: 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_0082: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) grounded = position; if ((Object)(object)ZoneSystem.instance == (Object)null) { return false; } float num = Mathf.Max(position.y + 30f, 128f); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(position.x, num, position.z); float solidHeight = default(float); if (!ZoneSystem.instance.GetGroundHeight(val, ref solidHeight)) { solidHeight = ZoneSystem.instance.GetSolidHeight(position); } if (position.y - solidHeight > 2f) { grounded.y = solidHeight + 0.2f; return true; } float num2 = solidHeight + 0.2f; RaycastHit[] array = Physics.RaycastAll(val, Vector3.down, num + 100f, FloorMask); for (int i = 0; i < array.Length; i++) { RaycastHit val2 = array[i]; if (!(((RaycastHit)(ref val2)).point.y > position.y + 1f) && !(((RaycastHit)(ref val2)).point.y < solidHeight - 1f) && ((RaycastHit)(ref val2)).point.y > num2) { num2 = ((RaycastHit)(ref val2)).point.y + 0.15f; } } grounded.y = num2; return true; } public static void ApplyLivePosition(Character character, Vector3 position, Quaternion rotation) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)character == (Object)null)) { ((Component)character).transform.position = position; ((Component)character).transform.rotation = rotation; Rigidbody component = ((Component)character).GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null) { component.linearVelocity = Vector3.zero; component.angularVelocity = Vector3.zero; } character.SetLookDir(position, 0f); } } public static void ApplyPosition(Character character, Vector3 position, Quaternion rotation) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)character == (Object)null)) { ((Component)character).transform.position = position; ((Component)character).transform.rotation = rotation; Rigidbody component = ((Component)character).GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null) { component.linearVelocity = Vector3.zero; component.angularVelocity = Vector3.zero; } character.SetLookDir(position, 0f); ZNetView nview = character.GetNview(); ZDO val = ((nview != null) ? nview.GetZDO() : null); if (val != null) { val.SetPosition(position); val.SetRotation(rotation); } } } } public static class JuvenilePortalRouter { public static bool IsBreederPortal(OPTeleportWorld portal) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)portal == (Object)null) { return false; } ZNetView component = ((Component)portal).GetComponent<ZNetView>(); ZDO val = ((component != null) ? component.GetZDO() : null); if (val == null || !PortalConfigGate.IsConfiguredForAutomation(val)) { return false; } PortalRecord portalRecord = DestinationRegistry.Get(val.m_uid); if (portalRecord != null) { return portalRecord.Role == PortalRole.Breeder; } return PortalRoleCatalog.FromZdo(val) == PortalRole.Breeder; } public static bool TryRoute(OPTeleportWorld portal, Character character, Dictionary<int, float> cooldowns, ref float lastNoDestinationMessageTime) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0125: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_015d: 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_0174: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)portal == (Object)null || (Object)(object)character == (Object)null || !OffspringPortalPrefabs.IsOffspringPortal(portal)) { return false; } if (!SpeciesHelper.IsEligibleJuvenile(character)) { return false; } int instanceID = ((Object)character).GetInstanceID(); float time = Time.time; if (cooldowns.TryGetValue(instanceID, out var value) && time < value) { return false; } ZDO zdo = character.GetZdo(); if (zdo != null && zdo.GetBool("op_transported", false) && !ModConfig.AllowRetransport.Value) { return false; } if (!IsBreederPortal(portal)) { return false; } string juvenileSpeciesKey = SpeciesHelper.GetJuvenileSpeciesKey(character); if (string.IsNullOrEmpty(juvenileSpeciesKey)) { return false; } ZNetView nview = character.GetNview(); ZDOID val = (ZDOID)(((??)((nview == null) ? ((ZDOID?)null) : nview.GetZDO()?.m_uid)) ?? ZDOID.None); ZNetView component = ((Component)portal).GetComponent<ZNetView>(); ZDOID val2 = (ZDOID)(((??)((component == null) ? ((ZDOID?)null) : component.GetZDO()?.m_uid)) ?? ZDOID.None); if (val == ZDOID.None || val2 == ZDOID.None) { return false; } if (ZNet.instance.IsServer()) { DiagnosticLog.Verbose($"Juvenile scan on server: {SpeciesKey.GetDisplayName(juvenileSpeciesKey)} at breeder {val2}."); return TryRouteOnServer(portal, character, juvenileSpeciesKey, val, val2, cooldowns, ref lastNoDestinationMessageTime, time, instanceID); } if (!RoutingRpc.CanSendRequests()) { DiagnosticLog.Verbose("Juvenile route skipped on client: routing RPC unavailable."); return false; } DiagnosticLog.Verbose($"Juvenile route client request: {SpeciesKey.GetDisplayName(juvenileSpeciesKey)} creature={val}, breeder={val2}."); RoutingRpc.RequestJuvenileRoute(val, val2, juvenileSpeciesKey); cooldowns[instanceID] = time + ModConfig.TeleportCooldownSec.Value; return false; } public static bool ExecuteApprovedRoute(ZDOID characterId, ZDOID sourcePortalId, PortalRecord destination, Character character = null, OPTeleportWorld sourcePortal = null) { //IL_0003: 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_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: 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_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_006a: 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_008f: 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) if (character == null) { character = ResolveCharacter(characterId); } if (sourcePortal == null) { sourcePortal = ResolvePortal(sourcePortalId); } if (destination == null) { return false; } if ((Object)(object)character != (Object)null && (Object)(object)sourcePortal != (Object)null) { if (!SpeciesHelper.IsEligibleJuvenile(character) || !IsBreederPortal(sourcePortal)) { return false; } string juvenileSpeciesKey = SpeciesHelper.GetJuvenileSpeciesKey(character); Vector3 val = JuvenileTeleporter.ResolveDestinationPosition(destination, sourcePortal); bool allowStoredHeight = (Object)(object)ZNetScene.instance == (Object)null || !ZNetScene.instance.IsAreaReady(val); if (JuvenileTeleporter.TryExecuteApproved(character, destination, sourcePortal, allowStoredHeight)) { DiagnosticLog.Info($"Teleported {SpeciesKey.GetDisplayName(juvenileSpeciesKey)} juvenile to maturing portal at {destination.Position}."); PlayPortalActivation(sourcePortal); return true; } object arg = characterId; ZNetScene instance = ZNetScene.instance; DiagnosticLog.Verbose($"Juvenile teleport TryExecuteApproved failed for {arg}; areaReady={instance != null && instance.IsAreaReady(val)}."); } if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && JuvenileTeleporter.TryMoveZdo(characterId, destination, sourcePortalId)) { DiagnosticLog.Info($"Teleported juvenile via ZDO to maturing portal at {destination.Position}."); PlayPortalActivation(sourcePortal); return true; } DiagnosticLog.Verbose($"ExecuteApprovedRoute failed for creature {characterId}: character={(Object)(object)character != (Object)null}, source={(Object)(object)sourcePortal != (Object)null}, destination={destination.Id}."); return false; } private static bool TryRouteOnServer(OPTeleportWorld portal, Character character, string speciesKey, ZDOID characterId, ZDOID sourcePortalId, Dictionary<int, float> cooldowns, ref float lastNoDestinationMessageTime, float now, int bodyId) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_008d: Unknown result type (might be due to invalid IL or missing references) if (!DestinationRegistry.TryResolveMaturingDestination(speciesKey, out var destination)) { if (DiagnosticLog.ShouldLogRateLimited(ref lastNoDestinationMessageTime, 5f)) { string displayName = SpeciesKey.GetDisplayName(speciesKey); DestinationRegistry.LogMaturingResolutionFailure(speciesKey, "breeder scan"); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)2, "No maturing portal registered for " + displayName + ".", 0, (Sprite)null, false); } } return false; } if (ExecuteApprovedRoute(characterId, sourcePortalId, destination, character, portal)) { cooldowns[bodyId] = now + ModConfig.TeleportCooldownSec.Value; return true; } DiagnosticLog.Warning($"Failed to teleport {SpeciesKey.GetDisplayName(speciesKey)} juvenile from breeder {sourcePortalId} to maturing {destination.Id}."); return false; } private static Character ResolveCharacter(ZDOID characterId) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.FindInstance(characterId) : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<Character>(); } private static OPTeleportWorld ResolvePortal(ZDOID portalId) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.FindInstance(portalId) : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<OPTeleportWorld>(); } private static void PlayPortalActivation(OPTeleportWorld portal) { portal?.PlayActivationEffect(); } } public static class JuvenileTeleporter { public static bool TryTeleport(Character juvenile, PortalRecord destination, OPTeleportWorld sourcePortal) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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) if ((Object)(object)juvenile == (Object)null || destination == null || (Object)(object)sourcePortal == (Object)null) { return false; } if (!ZNet.instance.IsServer() && !CanExecuteLocally(juvenile)) { return false; } DestinationRegistry.RefreshPortalPosition(destination); Vector3 exitPosition = PortalPlacement.GetExitPosition(destination.Id, sourcePortal); if ((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.IsAreaReady(exitPosition)) { return TryExecuteApproved(juvenile, destination, sourcePortal); } if (TryExecuteApproved(juvenile, destination, sourcePortal, allowStoredHeight: true)) { DiagnosticLog.Info($"Cross-zone teleport of {SpeciesCatalog.GetDisplayName(SpeciesHelper.GetJuvenileSpecies(juvenile))} to {exitPosition}."); return true; } DiagnosticLog.Info("Deferring teleport of " + SpeciesCatalog.GetDisplayName(SpeciesHelper.GetJuvenileSpecies(juvenile)) + " until pen zone loads."); if (ZNet.instance.IsServer()) { return OffspringPortalRuntime.Instance.TryQueueDistantTeleport(juvenile, destination, sourcePortal); } return false; } public static bool TryTeleportNow(Character juvenile, PortalRecord destination, OPTeleportWorld sourcePortal, bool allowStoredHeight = false) { return TryExecuteApproved(juvenile, destination, sourcePortal, allowStoredHeight); } public static bool TryExecuteApproved(Character juvenile, PortalRecord destination, OPTeleportWorld sourcePortal, bool allowStoredHeight = false) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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) if ((Object)(object)juvenile == (Object)null || destination == null || (Object)(object)sourcePortal == (Object)null) { return false; } ZNetView nview = juvenile.GetNview(); if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return false; } if (!nview.IsOwner()) { nview.ClaimOwnership(); if (!nview.IsOwner() && !ZNet.instance.IsServer()) { return false; } } Tameable component = ((Component)juvenile).GetComponent<Tameable>(); if ((Object)(object)component != (Object)null) { component.m_unsummonDistance = 0f; } DestinationRegistry.RefreshPortalPosition(destination); Vector3 exitPosition = PortalPlacement.GetExitPosition(destination.Id, sourcePortal); Quaternion exitRotation = PortalPlacement.GetExitRotation(destination.Id, sourcePortal); if (!TryPlaceCharacter(juvenile, exitPosition, exitRotation, allowStoredHeight)) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)2, "Could not place " + SpeciesCatalog.GetDisplayName(SpeciesHelper.GetJuvenileSpecies(juvenile)) + " at destination.", 0, (Sprite)null, false); } return false; } JuvenileGroundSnapper.EnsureAttached(juvenile); JuvenileFollowController.EnsureAttached(juvenile); ZDO zDO = nview.GetZDO(); if (zDO != null) { zDO.Set("op_transported", true); } return true; } public static bool TryMoveZdo(ZDOID characterId, PortalRecord destination, ZDOID sourcePortalId) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //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_00bd: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_015b: 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_016d: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: 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_01ba: 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_01d1: 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_0198: Unknown result type (might be due to invalid IL or missing references) if (!ZNet.instance.IsServer() || characterId == ZDOID.None || destination == null || ZDOMan.instance == null) { return false; } ZDO zDO = ZDOMan.instance.GetZDO(characterId); if (zDO == null || !zDO.IsValid()) { DiagnosticLog.Verbose($"Authoritative juvenile move failed: creature ZDO {characterId} is unavailable or invalid."); return false; } if (zDO.GetBool("op_transported", false) && !ModConfig.AllowRetransport.Value) { DiagnosticLog.Verbose($"Authoritative juvenile move skipped: {characterId} is already marked transported."); return false; } OPTeleportWorld fallbackPortal = null; ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.FindInstance(sourcePortalId) : null); if ((Object)(object)val != (Object)null) { fallbackPortal = val.GetComponent<OPTeleportWorld>(); } DestinationRegistry.RefreshPortalPosition(destination); Vector3 val2 = PortalPlacement.GetExitPosition(destination.Id, fallbackPortal); Quaternion exitRotation = PortalPlacement.GetExitRotation(destination.Id, fallbackPortal); bool flag = (Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.IsAreaReady(val2); if (flag && JuvenilePlacement.TryGetFloorPosition(val2, out var grounded)) { val2 = grounded; } long owner = zDO.GetOwner(); zDO.SetOwner(ZNet.GetUID()); zDO.SetPosition(val2); zDO.SetRotation(exitRotation); zDO.Set("op_transported", true); zDO.Set(ZDOVars.s_velHash, Vector3.zero); zDO.Set(ZDOVars.s_bodyVelHash, Vector3.zero); zDO.Set(ZDOVars.s_bodyAVelHash, Vector3.zero); ZDOMan.instance.ForceSendZDO(characterId); ZNetScene instance2 = ZNetScene.instance; GameObject val3 = ((instance2 != null) ? instance2.FindInstance(characterId) : null); Character val4 = (((Object)(object)val3 != (Object)null) ? val3.GetComponent<Character>() : null); if ((Object)(object)val4 != (Object)null) { JuvenilePlacement.ApplyLivePosition(val4, val2, exitRotation); JuvenileGroundSnapper.EnsureAttached(val4); JuvenileFollowController.EnsureAttached(val4); } DiagnosticLog.Verbose($"Authoritative juvenile ZDO move: creature={characterId}, destination={destination.Id}, target={val2}, areaReady={flag}, instantiatedOnServer={(Object)(object)val4 != (Object)null}, previousOwner={owner}."); return true; } public static bool TryApplyLiveTransfer(ZDOID characterId, Vector3 targetPos, Quaternion targetRot) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.FindInstance(characterId) : null); Character val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Character>() : null); if ((Object)(object)val2 == (Object)null) { return false; } JuvenilePlacement.ApplyLivePosition(val2, targetPos, targetRot); JuvenileGroundSnapper.EnsureAttached(val2); JuvenileFollowController.EnsureAttached(val2); return true; } public static Vector3 ResolveDestinationPosition(PortalRecord destination, OPTeleportWorld sourcePortal) { //IL_0001: 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) return PortalPlacement.GetExitPosition(destination.Id, sourcePortal); } public static Quaternion ResolveDestinationRotation(PortalRecord destination, OPTeleportWorld sourcePortal) { //IL_0001: 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) return PortalPlacement.GetExitRotation(destination.Id, sourcePortal); } private static bool CanExecuteLocally(Character juvenile) { ZNetView val = juvenile?.GetNview(); if ((Object)(object)val != (Object)null && val.IsValid()) { return val.IsOwner(); } return false; } private static bool TryPlaceCharacter(Character character, Vector3 destination, Quaternion rotation, bool allowStoredHeight) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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 referenc