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.2.0
OffspringPortal.dll
Decompiled a day 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.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.2.0.0")] [assembly: AssemblyInformationalVersion("1.2.0+12e3506d23ba3e111aeeb745594ae197341def4b")] [assembly: AssemblyProduct("OffspringPortal")] [assembly: AssemblyTitle("OffspringPortal")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.0.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_0024: 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) { 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 (from species in RegisteredSpecies.Values where species.IsDualPurposeEgg && !string.IsNullOrEmpty(species.EggCollectorKey) select species.EggCollectorKey).Distinct<string>(StringComparer.OrdinalIgnoreCase).OrderBy<string, string>((string key) => SpeciesKey.GetEggCollectorDisplayName(key), StringComparer.OrdinalIgnoreCase).ToList(); } 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_0023: Unknown result type (might be due to invalid IL or missing references) RegisteredSpecies.Clear(); 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 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 int eggCollectorRoundRobinIndex; 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 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_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_0026: Unknown result type (might be due to invalid IL or missing references) if (record != null && ZDOMan.instance != null) { ZDO zDO = ZDOMan.instance.GetZDO(record.Id); if (zDO != null) { record.Position = zDO.GetPosition(); } } } 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 ((object)Unsafe.As<ZDOID, ZDOID>(ref p.Id)/*cast due to .constrained prefix*/).ToString() 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) { destination = null; if (string.IsNullOrWhiteSpace(eggCollectorKey)) { return false; } string normalizedEggKey = SpeciesKey.BuildEggCollectorKey(eggCollectorKey); string speciesKey = (SpeciesKey.IsEggCollectorKey(normalizedEggKey) ? normalizedEggKey.Substring("Egg:".Length) : SpeciesKey.Canonicalize(eggCollectorKey)); List<PortalRecord> list = (from p in Portals.Values where p.Role == PortalRole.EggCollector && PortalAcceptsEggCollector(p.DeclaredSpeciesKey, normalizedEggKey, speciesKey) orderby ((object)Unsafe.As<ZDOID, ZDOID>(ref p.Id)/*cast due to .constrained prefix*/).ToString() select p).ToList(); if (list.Count == 0) { return false; } destination = list[eggCollectorRoundRobinIndex % list.Count]; eggCollectorRoundRobinIndex++; RefreshPortalPosition(destination); return true; } 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 void RefreshCapWarnings() { //IL_0097: 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 zDO = ZDOMan.instance.GetZDO(destination.Id); if (zDO != null) { zDO.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 p.Role == requiredRole && !SpeciesKey.IsAll(p.DeclaredSpeciesKey) && SpeciesKey.PortalAcceptsSpecies(p.DeclaredSpeciesKey, speciesKey) orderby ((object)Unsafe.As<ZDOID, ZDOID>(ref p.Id)/*cast due to .constrained prefix*/).ToString() 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 p.Role == requiredRole && "All".Equals(p.DeclaredSpeciesKey, StringComparison.OrdinalIgnoreCase) orderby ((object)Unsafe.As<ZDOID, ZDOID>(ref p.Id)/*cast due to .constrained prefix*/).ToString() select p).ToList(); if (list2.Count > 0) { destination = PickRoundRobin("All", list2, roundRobinIndex); RefreshPortalPosition(destination); return destination != null; } return false; } 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 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" }; 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) { string[] henEggCollectorLookupKeys = HenEggCollectorLookupKeys; for (int i = 0; i < henEggCollectorLookupKeys.Length; i++) { if (DestinationRegistry.TryResolveEggCollectorDestination(henEggCollectorLookupKeys[i], out destination)) { return true; } } destination = null; return false; } } 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_007c: 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) if ((Object)(object)character == (Object)null || (Object)(object)player == (Object)null) { return false; } if (!ModConfig.EnableFollowCommand.Value || IsLetsGoLoaded()) { return false; } if (!SpeciesHelper.IsEligibleJuvenile(character) || !character.IsTamed()) { return false; } ZNetView nview = character.GetNview(); if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return false; } JuvenileGroundSnapper.EnsureAttached(character); JuvenileFollowController.EnsureAttached(character); if (ZNet.instance.IsServer()) { return ApplyFollowToggle(character, player, showMessage); } 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 bool registered; public static void Register() { if (!registered && ZRoutedRpc.instance != null) { ZRoutedRpc instance = ZRoutedRpc.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); registered = true; } } public static void RequestToggle(ZDOID creatureId, ZDOID playerId, bool showMessage) { //IL_0012: 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) ZRoutedRpc.instance.InvokeRoutedRPC("OffspringPortal_ToggleJuvenileFollow", new object[3] { creatureId, playerId, showMessage }); } private static void OnToggleFollowRpc(long sender, ZDOID creatureId, ZDOID playerId, bool showMessage) { //IL_0020: 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) if (ZNet.instance.IsServer()) { ZRoutedRpc.instance.InvokeRoutedRPC(sender, "OffspringPortal_ExecuteJuvenileFollow", new object[3] { creatureId, playerId, showMessage }); } } private static void OnExecuteToggleFollowRpc(long sender, ZDOID creatureId, ZDOID playerId, bool showMessage) { //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) ApplyToggle(creatureId, playerId, showMessage, sender); } 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) Character val = ResolveCreature(creatureId); Player val2 = ResolveRequestingPlayer(sender, playerId); if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && SpeciesHelper.IsEligibleJuvenile(val) && val.IsTamed()) { 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 readonly int InteractMask = LayerMask.GetMask(new string[10] { "item", "piece", "piece_nonsolid", "Default", "static_solid", "Default_small", "character", "character_net", "terrain", "vehicle" }); 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_0022: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)GameCamera.instance == (Object)null) { return null; } Vector3 position = ((Component)GameCamera.instance).transform.position; Vector3 forward = ((Component)GameCamera.instance).transform.forward; Vector3 position2 = ((Character)player).m_eye.position; RaycastHit[] source = Physics.RaycastAll(position, forward, 50f, InteractMask); Character result = 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 || ((Object)(object)((RaycastHit)(ref current)).collider.attachedRigidbody != (Object)null && (Object)(object)((Component)((RaycastHit)(ref current)).collider.attachedRigidbody).gameObject == (Object)(object)((Component)player).gameObject)) { continue; } Character val = (((Object)(object)((RaycastHit)(ref current)).collider.attachedRigidbody != (Object)null) ? ((Component)((RaycastHit)(ref current)).collider.attachedRigidbody).GetComponent<Character>() : ((Component)((RaycastHit)(ref current)).collider).GetComponentInParent<Character>()); if (!((Object)(object)val == (Object)null) && !val.IsPlayer() && val.IsTamed() && (!juvenilesOnly || SpeciesHelper.IsEligibleJuvenile(val)) && (juvenilesOnly || !((Object)(object)((Component)val).GetComponent<Tameable>() == (Object)null))) { float num2 = Vector3.Distance(position2, ((RaycastHit)(ref current)).point); if (num2 <= num) { result = val; num = num2; } } } return result; } } 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 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_0024: 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) { 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_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //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) 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()) { return TryRouteOnServer(portal, character, juvenileSpeciesKey, val, val2, cooldowns, ref lastNoDestinationMessageTime, time, instanceID); } if (!RoutingRpc.CanSendRequests()) { return false; } 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) 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); if (JuvenileTeleporter.TryExecuteApproved(character, destination, sourcePortal)) { OffspringPortalPlugin.Log.LogInfo((object)$"Teleported {SpeciesKey.GetDisplayName(juvenileSpeciesKey)} juvenile to maturing portal at {destination.Position}."); PlayPortalActivation(sourcePortal); return true; } } if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && JuvenileTeleporter.TryMoveZdo(characterId, destination, sourcePortalId)) { OffspringPortalPlugin.Log.LogInfo((object)$"Teleported juvenile via ZDO to maturing portal at {destination.Position}."); PlayPortalActivation(sourcePortal); return true; } 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (!DestinationRegistry.TryResolveMaturingDestination(speciesKey, out var destination)) { if (now - lastNoDestinationMessageTime > 5f) { lastNoDestinationMessageTime = now; string displayName = SpeciesKey.GetDisplayName(speciesKey); OffspringPortalPlugin.Log.LogWarning((object)("No maturing portal registered for " + displayName + ".")); 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; } OffspringPortalPlugin.Log.LogWarning((object)("Failed to teleport " + SpeciesKey.GetDisplayName(speciesKey) + " juvenile.")); 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_0084: 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)) { OffspringPortalPlugin.Log.LogInfo((object)$"Cross-zone teleport of {SpeciesCatalog.GetDisplayName(SpeciesHelper.GetJuvenileSpecies(juvenile))} to {exitPosition}."); return true; } OffspringPortalPlugin.Log.LogInfo((object)("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_006b: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: 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) { return false; } if (zDO.GetBool("op_transported", false) && !ModConfig.AllowRetransport.Value) { return false; } zDO.SetOwner(ZDOMan.GetSessionID()); 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>(); } Vector3 position = PortalPlacement.GetExitPosition(destination.Id, fallbackPortal); Quaternion exitRotation = PortalPlacement.GetExitRotation(destination.Id, fallbackPortal); if (JuvenilePlacement.TryGetFloorPosition(position, out var grounded)) { position = grounded; } zDO.SetPosition(position); zDO.SetRotation(exitRotation); zDO.Set("op_transported", true); 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 references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) Vector3 val = rotation * Vector3.right; for (int i = 0; i < 5; i++) { if (JuvenilePlacement.TryGetFloorPosition(destination + val * Random.Range(-0.2f, 0.2f), out var grounded)) { JuvenilePlacement.ApplyPosition(character, grounded, rotation); JuvenileGroundSnapper.EnsureAttached(character); return true; } } if (!allowStoredHeight) { return false; } if (JuvenilePlacement.TryGetFloorPosition(destination, out var grounded2)) { JuvenilePlacement.ApplyPosition(character, grounded2, rotation); return true; } return false; } } public static class MateDrawController { public static bool TryApplyMonsterMateDraw(MonsterAI monsterAi, float dt) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //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_00a1: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.EnableMateDraw.Value || (Object)(object)monsterAi == (Object)null) { return false; } Character component = ((Component)monsterAi).GetComponent<Character>(); if (!CanApplyMateDraw(component, out var partner, out var stopDistance)) { return false; } Vector3 val = ((Component)partner).transform.position - ((Component)component).transform.position; val.y = 0f; float magnitude = ((Vector3)(ref val)).magnitude; Procreation component2 = ((Component)component).GetComponent<Procreation>(); if (ShouldYieldBreedingToVanilla(component, component2, magnitude, stopDistance)) { return false; } bool flag = magnitude > 10f; Traverse.Create((object)monsterAi).Method("MoveTo", new object[4] { dt, ((Component)partner).transform.position, 0f, flag }).GetValue(); return true; } public static bool TryApplyAnimalMateDraw(AnimalAI animalAi, float dt) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.EnableMateDraw.Value || (Object)(object)animalAi == (Object)null) { return false; } Character component = ((Component)animalAi).GetComponent<Character>(); if (!CanApplyMateDraw(component, out var partner, out var stopDistance)) { return false; } Vector3 val = ((Component)partner).transform.position - ((Component)component).transform.position; val.y = 0f; float magnitude = ((Vector3)(ref val)).magnitude; Procreation component2 = ((Component)component).GetComponent<Procreation>(); if (ShouldYieldBreedingToVanilla(component, component2, magnitude, stopDistance)) { return false; } ((BaseAI)animalAi).MoveTowards(val / magnitude, magnitude > 10f); return true; } public static void SetMateDrawTarget(Character character, Character partner) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null || (Object)(object)partner == (Object)null) { return; } ZNetView nview = character.GetNview(); ZDO zdo = character.GetZdo(); if (!((Object)(object)nview == (Object)null) && zdo != null) { if (!nview.IsOwner()) { nview.ClaimOwnership(); } ZNetView nview2 = partner.GetNview(); zdo.Set("op_mate_draw_target", (ZDOID)(((??)((nview2 == null) ? ((ZDOID?)null) : nview2.GetZDO()?.m_uid)) ?? ZDOID.None)); } } public static void ClearMateDraw(Character character) { //IL_0016: 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_002e: Unknown result type (might be due to invalid IL or missing references) ZDO val = character?.GetZdo(); if (val != null && !(val.GetZDOID("op_mate_draw_target") == ZDOID.None)) { val.Set("op_mate_draw_target", ZDOID.None); } } private static bool CanApplyMateDraw(Character character, out Character partner, out float stopDistance) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) partner = null; stopDistance = ModConfig.MateDrawStopDistance.Value; if ((Object)(object)character == (Object)null) { return false; } ZNetView nview = character.GetNview(); if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner()) { return false; } if (!ProcreationHelper.IsMateDrawEligible(character)) { ClearMateDraw(character); return false; } Procreation component = ((Component)character).GetComponent<Procreation>(); if ((Object)(object)component == (Object)null) { ClearMateDraw(character); return false; } if (ProcreationHelper.HasMateInBreedingRange(character, component)) { ClearMateDraw(character); return false; } ZDO zdo = character.GetZdo(); ZDOID val = ((zdo != null) ? zdo.GetZDOID("op_mate_draw_target") : ZDOID.None); if (val == ZDOID.None) { return false; } partner = ResolveCharacter(val); if ((Object)(object)partner == (Object)null || !ProcreationHelper.IsMateDrawEligible(partner)) { ClearMateDraw(character); return false; } if (!SpeciesHelper.SpeciesKeyMatches(SpeciesHelper.GetAdultSpeciesKey(character), SpeciesHelper.GetAdultSpeciesKey(partner))) { ClearMateDraw(character); return false; } stopDistance = ProcreationHelper.GetStopDistance(component); return true; } private static bool ShouldYieldBreedingToVanilla(Character character, Procreation procreation, float distance, float stopDistance) { if ((Object)(object)procreation != (Object)null && distance <= procreation.m_partnerCheckRange) { ClearMateDraw(character); return true; } if (distance <= stopDistance) { ClearMateDraw(character); return true; } return false; } private static Character ResolveCharacter(ZDOID characterId) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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) { Character component = val.GetComponent<Character>(); if ((Object)(object)component != (Object)null) { return component; } } foreach (Character allCharacter in Character.GetAllCharacters()) { ZNetView val2 = allCharacter?.GetNview(); if ((Object)(object)val2 != (Object)null) { ZDO zDO = val2.GetZDO(); if (zDO != null && zDO.m_uid == characterId) { return allCharacter; } } } return null; } } public static class MateDrawScanner { public static void ScanPortal(OPTeleportWorld portal, Vector3 center) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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) if (!ModConfig.EnableMateDraw.Value || (Object)(object)portal == (Object)null || !PortalScanHelper.ShouldScanPortal(portal) || !JuvenilePortalRouter.IsBreederPortal(portal)) { return; } float value = ModConfig.MateDrawRange.Value; float num = value * value; List<Character> list = new List<Character>(); 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) { MateDrawController.ClearMateDraw(allCharacter); } else if (!ProcreationHelper.IsMateDrawEligible(allCharacter)) { MateDrawController.ClearMateDraw(allCharacter); } else { list.Add(allCharacter); } } } AssignMateTargets(list, value); } private static void AssignMateTargets(List<Character> eligible, float drawRange) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_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_00ab: 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) float num = drawRange * drawRange; foreach (Character item in eligible) { Procreation component = ((Component)item).GetComponent<Procreation>(); if ((Object)(object)component == (Object)null) { MateDrawController.ClearMateDraw(item); continue; } if (ProcreationHelper.HasMateInBreedingRange(item, component)) { MateDrawController.ClearMateDraw(item); continue; } string adultSpeciesKey = SpeciesHelper.GetAdultSpeciesKey(item); float partnerCheckRange = component.m_partnerCheckRange; float num2 = partnerCheckRange * partnerCheckRange; Character val = null; float num3 = float.MaxValue; Vector3 position = ((Component)item).transform.position; foreach (Character item2 in eligible) { if (!((Object)(object)item2 == (Object)(object)item) && SpeciesHelper.SpeciesKeyMatches(SpeciesHelper.GetAdultSpeciesKey(item2), adultSpeciesKey)) { Vector3 val2 = ((Component)item2).transform.position - position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude <= num2) && !(sqrMagnitude > num) && sqrMagnitude < num3) { num3 = sqrMagnitude; val = item2; } } } if ((Object)(object)val == (Object)null) { MateDrawController.ClearMateDraw(item); } else { MateDrawController.SetMateDrawTarget(item, val); } } } } public static class ModConfig { public static ConfigEntry<float> TeleportCooldownSec; public static ConfigEntry<float> BreederScanRange; public static ConfigEntry<float> BreederScanIntervalSec; public static ConfigEntry<float> DistantTeleportTimeoutSec; public static ConfigEntry<bool> AllowRetransport; public static ConfigEntry<bool> EnableFollowCommand; public static ConfigEntry<bool> EnableCapWarning; public static ConfigEntry<float> MaturingAdultScanIntervalSec; public static ConfigEntry<float> DiscoveryScanRange; public static ConfigEntry<bool> EnableMateDraw; public static ConfigEntry<float> MateDrawRange; public static ConfigEntry<float> MateDrawIntervalSec; public static ConfigEntry<float> MateDrawStopDistance; public static void Bind(ConfigFile config) { TeleportCooldownSec = config.Bind<float>("General", "TeleportCooldownSec", 2f, "Seconds between successive teleports at the same source portal."); BreederScanRange = config.Bind<float>("General", "BreederScanRange", 10f, "Breeder portals automatically teleport tamed juveniles within this radius (meters)."); BreederScanIntervalSec = config.Bind<float>("General", "BreederScanIntervalSec", 0.5f, "How often breeder portals scan for nearby juveniles."); DistantTeleportTimeoutSec = config.Bind<float>("General", "DistantTeleportTimeoutSec", 15f, "How long to wait for a distant pen zone to load before giving up."); AllowRetransport = config.Bind<bool>("General", "AllowRetransport", false, "If true, a juvenile can use the portal more than once."); EnableFollowCommand = config.Bind<bool>("General", "EnableFollowCommand", true, "Press E on tamed juveniles to toggle follow/stay (Boar, Wolf, Lox, Hen, Asksvin, Moose)."); EnableCapWarning = config.Bind<bool>("General", "EnableCapWarning", true, "Show warning when a maturing portal is within species cap radius of a breeder portal."); MaturingAdultScanIntervalSec = config.Bind<float>("General", "MaturingAdultScanIntervalSec", 30f, "How often maturing portals scan for nearby adults to forward to cull pens."); DiscoveryScanRange = config.Bind<float>("Breeding", "DiscoveryScanRange", 0f, "Radius for discovering breedable species at breeder portals (0 = max of breeder scan and mate draw range)."); EnableMateDraw = config.Bind<bool>("Breeding", "EnableMateDraw", true, "Draw fed, ready-to-breed adults toward each other within breeder portal range."); MateDrawRange = config.Bind<float>("Breeding", "MateDrawRange", 15f, "How far apart mates can be before breeder portals nudge them together (meters)."); MateDrawIntervalSec = config.Bind<float>("Breeding", "MateDrawIntervalSec", 1.5f, "How often breeder portals scan for mate-draw pairing."); MateDrawStopDistance = config.Bind<float>("Breeding", "MateDrawStopDistance", 2.5f, "How close mates move before stopping (should be within vanilla breeding range)."); } public static float GetDiscoveryScanRange() { if (DiscoveryScanRange.Value > 0f) { return DiscoveryScanRange.Value; } float value = BreederScanRange.Value; if (!EnableMateDraw.Value) { return value; } return Mathf.Max(value, MateDrawRange.Value); } } internal static class OffspringPortalLocalization { internal static void Register() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "piece_offspring_portal", "Offspring Portal" }, { "piece_offspring_portal_description", "Routes tamed juveniles and breedable eggs between configured breeding pens." } }); } } public static class OffspringPortalPrefabs { private static bool pieceRegistered; private static bool retryScheduled; public static GameObject Prefab { get; private set; } public static bool Registered { get; private set; } public static void Initialize() { PrefabManager.OnVanillaPrefabsAvailable += RegisterPrefab; PrefabManager.OnPrefabsRegistered += RegisterPrefab; PieceManager.OnPiecesRegistered += RegisterPiece; PrefabManager.OnPrefabsRegistered += RegisterPiece; } public static void EnsureRegistered() { RegisterPrefab(); } public static void EnsurePieceRegistered() { RegisterPiece(); } private static void RegisterPrefab() { if (Registered) { return; } try { GameObject val = PrefabManager.Instance.CreateClonedPrefab("offspring_portal", "portal_wood"); if ((Object)(object)val == (Object)null) { ScheduleRegisterRetry(); return; } ConfigureClone(val); EnsureRuntimeTriggers(ConvertFromVanillaPortal(val)); PrefabManager.Instance.AddPrefab(val); Prefab = val; Registered = true; retryScheduled = false; PrefabManager.OnVanillaPrefabsAvailable -= RegisterPrefab; PrefabManager.OnPrefabsRegistered -= RegisterPrefab; OffspringPortalPlugin.Log.LogInfo((object)"Registered offspring_portal prefab (cloned from portal_wood)."); RegisterPiece(); } catch (Exception arg) { OffspringPortalPlugin.Log.LogError((object)$"Failed to register offspring_portal prefab: {arg}"); ScheduleRegisterRetry(); } } private static void ScheduleRegisterRetry() { if (!retryScheduled && !Registered) { retryScheduled = true; ((MonoBehaviour)OffspringPortalRuntime.Instance).StartCoroutine(RetryRegisterPrefab()); } } private static IEnumerator RetryRegisterPrefab() { for (int i = 0; i < 600; i++) { if (Registered) { break; } RegisterPrefab(); if (Registered) { yield break; } yield return null; } retryScheduled = false; if (!Registered) { OffspringPortalPlugin.Log.LogError((object)"Could not register offspring_portal: portal_wood was unavailable after waiting for ZNetScene."); } } internal static bool TryValidateVanillaPortalPrefab(out string message) { message = null; if (!TryResolveVanillaPortalWood(out var vanilla)) { message = "portal_wood was not found in ZNetScene at registration time. Offspring Portal cannot clone the vanilla wood portal."; return false; } if ((Object)(object)vanilla.GetComponent<TeleportWorld>() == (Object)null) { message = "portal_wood exists but has no TeleportWorld component."; return false; } return true; } internal static bool TryResolveVanillaPortalWood(out GameObject vanilla) { vanilla = null; if ((Object)(object)ZNetScene.instance != (Object)null) { vanilla = ZNetScene.instance.GetPrefab("portal_wood"); } return (Object)(object)vanilla != (Object)null; } private static void RegisterPiece() { if (pieceRegistered || !Registered || (Object)(object)Prefab == (Object)null) { return; } try { ApplyRecipe(Prefab); ApplyHammerIcon(Prefab); PieceManager.Instance.RegisterPieceInPieceTable(Prefab, "Hammer", (string)null); pieceRegistered = true; PieceManager.OnPiecesRegistered -= RegisterPiece; OffspringPortalPlugin.Log.LogInfo((object)"Registered offspring_portal in Hammer piece table."); } catch (Exception ex) { OffspringPortalPlugin.Log.LogWarning((object)("Deferring offspring_portal piece registration: " + ex.Message)); } } private static void ApplyRecipe(GameObject clone) { Piece component = clone.GetComponent<Piece>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)ObjectDB.instance == (Object)null)) { component.m_resources = (Requirement[])(object)new Requirement[3] { CreateRequirement("FineWood", 20), CreateRequirement("GreydwarfEye", 10), CreateRequirement("SurtlingCore", 2) }; } } private static void ConfigureClone(GameObject clone) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) clone.transform.localScale = Vector3.one * 0.5f; Piece component = clone.GetComponent<Piece>(); if ((Object)(object)component != (Object)null) { component.m_name = "$piece_offspring_portal"; component.m_description = "$piece_offspring_portal_description"; } } internal static OPTeleportWorld ConvertFromVanillaPortal(GameObject gameObject) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_00bf: Unknown result type (might be due to invalid IL or missing references) Transform proximityRoot = null; float exitDistance = 1f; float hoverOffset = 0f; EffectList connectedVfx = null; MeshRenderer model = null; Color colorUnconnected = Color.white; Color colorTargetfound = Color.white; TeleportWorld component = gameObject.GetComponent<TeleportWorld>(); if ((Object)(object)component != (Object)null) { proximityRoot = component.m_proximityRoot; exitDistance = component.m_exitDistance; hoverOffset = component.m_hoverOffset; connectedVfx = component.m_connected; model = component.m_model; colorUnconnected = component.m_colorUnconnected; colorTargetfound = component.m_colorTargetfound; DestroyPo