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 BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; 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("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+7c1d2c20f20282a1313ac0e61abf2255741dfadf")] [assembly: AssemblyProduct("OffspringPortal")] [assembly: AssemblyTitle("OffspringPortal")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.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(TeleportWorld 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(); 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(TeleportWorld portal, Character character, Dictionary cooldowns, ref float lastNoDestinationMessageTime) { //IL_0058: 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_0148: 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; } if (!ZNet.instance.IsServer()) { return false; } ZNetView component = ((Component)portal).GetComponent(); 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; } SpeciesType adultSpecies = SpeciesHelper.GetAdultSpecies(character); if (!SpeciesHelper.SpeciesMatches(adultSpecies, portalRecord.DeclaredSpecies)) { return false; } PortalRecord destination; switch (portalRecord.AdultDestination) { case AdultDestination.Farm: if (!DestinationRegistry.TryResolveFarmDestination(adultSpecies, out destination)) { string message = "No Farm portal exists."; return WarnMissingDestination(time, ref lastNoDestinationMessageTime, message); } break; case AdultDestination.Cull: if (!DestinationRegistry.TryResolveCullDestination(out destination)) { string message = "No Cull portal exists."; return WarnMissingDestination(time, ref lastNoDestinationMessageTime, message); } break; default: return false; } if (!JuvenileTeleporter.TryTeleport(character, destination, portal)) { OffspringPortalPlugin.Log.LogWarning((object)("Failed to teleport " + SpeciesCatalog.GetDisplayName(adultSpecies) + " adult.")); return false; } OffspringPortalPlugin.Log.LogInfo((object)$"Teleported {SpeciesCatalog.GetDisplayName(adultSpecies)} adult to {portalRecord.AdultDestination} portal at {destination.Position}."); cooldowns[instanceID] = time + ModConfig.TeleportCooldownSec.Value; PlayPortalActivation(portal); return true; } 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); } return false; } private static void PlayPortalActivation(TeleportWorld portal) { //IL_001b: 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 (portal?.m_connected != null) { portal.m_connected.Create(((Component)portal).transform.position, ((Component)portal).transform.rotation, ((Component)portal).transform, 1f, -1); } } } 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, _ => 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: return 20f; default: return 0f; } } } public sealed class PortalRecord { public ZDOID Id; public Vector3 Position; public PortalRole Role; public SpeciesType DeclaredSpecies; public AdultDestination AdultDestination; } public static class DestinationRegistry { private static readonly Dictionary Portals = new Dictionary(); private static readonly Dictionary MaturingRoundRobinIndex = new Dictionary(); private static readonly Dictionary FarmRoundRobinIndex = new Dictionary(); private static int cullRoundRobinIndex; public static void Clear() { Portals.Clear(); } public static void RegisterOrUpdate(ZDOID id, Vector3 position, PortalRole role, SpeciesType declaredSpecies, 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.DeclaredSpecies = declaredSpecies; 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_000a: 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) if (record != 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 TryResolveDestination(juvenileSpecies, PortalRole.Maturing, MaturingRoundRobinIndex, out destination); } public static bool TryResolveFarmDestination(SpeciesType adultSpecies, out PortalRecord destination) { return TryResolveDestination(adultSpecies, PortalRole.Farm, FarmRoundRobinIndex, out destination); } public static bool TryResolveCullDestination(out PortalRecord destination) { destination = null; List list = (from p in Portals.Values where p.Role == PortalRole.Cull orderby ((object)Unsafe.As(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 HasCullReceiver() { return Portals.Values.Any((PortalRecord p) => p.Role == PortalRole.Cull); } public static bool HasFarmReceiver(SpeciesType maturingReceives) { if (maturingReceives != SpeciesType.None && maturingReceives != SpeciesType.All && TryResolveFarmDestination(maturingReceives, out var destination)) { return true; } if (TryResolveFarmDestination(SpeciesType.All, out destination)) { return true; } if (maturingReceives == SpeciesType.All) { return Portals.Values.Any((PortalRecord p) => p.Role == PortalRole.Farm); } return false; } public static IEnumerable GetBreederPortals() { return Portals.Values.Where((PortalRecord p) => p.Role == PortalRole.Breeder); } public static IEnumerable GetAll() { return Portals.Values; } public static void RefreshCapWarnings() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.EnableCapWarning.Value) { return; } foreach (PortalRecord destination in Portals.Values.Where((PortalRecord p) => p.Role == PortalRole.Maturing && p.DeclaredSpecies != SpeciesType.All)) { bool flag = GetBreederPortals().Any((PortalRecord source) => Vector3.Distance(source.Position, destination.Position) <= BreedingCapData.GetCapRadius(destination.DeclaredSpecies)); ZDO zDO = ZDOMan.instance.GetZDO(destination.Id); if (zDO != null) { zDO.Set("op_cap_warning", flag); } } } private static bool TryResolveDestination(SpeciesType species, PortalRole requiredRole, Dictionary roundRobinIndex, out PortalRecord destination) { destination = null; if (species == SpeciesType.None) { return false; } List list = (from p in Portals.Values where p.Role == requiredRole && p.DeclaredSpecies == species orderby ((object)Unsafe.As(ref p.Id)/*cast due to .constrained prefix*/).ToString() select p).ToList(); if (list.Count > 0) { destination = PickRoundRobin(species, list, roundRobinIndex); RefreshPortalPosition(destination); return destination != null; } List list2 = (from p in Portals.Values where p.Role == requiredRole && p.DeclaredSpecies == SpeciesType.All orderby ((object)Unsafe.As(ref p.Id)/*cast due to .constrained prefix*/).ToString() select p).ToList(); if (list2.Count > 0) { destination = PickRoundRobin(SpeciesType.All, list2, roundRobinIndex); RefreshPortalPosition(destination); return destination != null; } return false; } private static PortalRecord PickRoundRobin(SpeciesType key, List candidates, Dictionary 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 JuvenileFollow { public static bool TryCommand(Character character, Player player, bool showMessage) { if ((Object)(object)character == (Object)null || (Object)(object)player == (Object)null) { return false; } if (!SpeciesHelper.IsEligibleJuvenile(character) || !character.IsTamed()) { return false; } ZNetView nview = character.GetNview(); if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return false; } MonsterAI component = ((Component)character).GetComponent(); Tameable component2 = ((Component)character).GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component != (Object)null) { component2.m_commandable = true; if (ZNet.instance.IsServer()) { ApplyMonsterFollowToggle(component2, component, player, showMessage); return true; } component2.Command((Humanoid)(object)player, showMessage); return true; } if ((Object)(object)((Component)character).GetComponent() == (Object)null) { return false; } JuvenileFollowController.EnsureAttached(character); JuvenileFollowRpcHandler.EnsureAttached(character); if (ZNet.instance.IsServer()) { return ApplyAnimalFollowToggle(character, player, showMessage); } ((Component)character).GetComponent()?.RequestToggle(player, showMessage); return true; } 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(); 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(Tameable tameable, MonsterAI monsterAi, Player player, bool showMessage) { ZNetView component = ((Component)tameable).GetComponent(); if ((Object)(object)component != (Object)null && !component.IsOwner()) { component.ClaimOwnership(); } 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, tameable.GetHoverName() + " " + Localization.instance.Localize("$hud_tamestay"), 0, (Sprite)null); } 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, tameable.GetHoverName() + " " + Localization.instance.Localize("$hud_tamefollow"), 0, (Sprite)null); } } 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_0093: 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); } } else { zdo.Set("op_follow_target", zDOID); if (showMessage) { ((Character)player).Message((MessageType)2, hoverName + " " + Localization.instance.Localize("$hud_tamefollow"), 0, (Sprite)null); } } return true; } } public sealed class JuvenileFollowController : MonoBehaviour { public static bool TryApplyAnimalFollow(AnimalAI animalAi, float dt) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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_0090: 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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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(); ZNetView component2 = ((Component)animalAi).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || !component2.IsValid()) { return false; } if (!ZNet.instance.IsServer() || !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() == (Object)null) && (Object)(object)((Component)character).GetComponent() == (Object)null) { ((Component)character).gameObject.AddComponent(); } } 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() : 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 && !((Object)(object)character == (Object)null) && SpeciesHelper.IsEligibleJuvenile(character) && character.IsTamed() && (!((Object)(object)((Component)character).GetComponent() == (Object)null) || !((Object)(object)((Component)character).GetComponent() == (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[$KEY_Use] " + text); } else { hoverText = Localization.instance.Localize(character.GetHoverName() + "\n[$KEY_Use] " + text); } } } } public sealed class JuvenileFollowRpcHandler : MonoBehaviour { private const string ToggleFollowRpc = "op_toggle_follow"; private ZNetView nview; private bool registered; private void Awake() { nview = ((Component)this).GetComponent(); } private void Start() { TryRegister(); } private void TryRegister() { if (!registered && !((Object)(object)nview == (Object)null) && nview.IsValid()) { nview.Register("op_toggle_follow", (Action)RPC_ToggleFollow); registered = true; } } public void RequestToggle(Player player, bool showMessage) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) TryRegister(); if (!((Object)(object)nview == (Object)null) && nview.IsValid() && !((Object)(object)player == (Object)null)) { nview.InvokeRPC("op_toggle_follow", new object[2] { ((Character)player).GetZDOID(), showMessage }); } } private void RPC_ToggleFollow(long sender, ZDOID playerId, bool showMessage) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (ZNet.instance.IsServer()) { Character component = ((Component)this).GetComponent(); object obj = Player.GetPlayer(sender); if (obj == null) { GameObject obj2 = ZNetScene.instance.FindInstance(playerId); obj = ((obj2 != null) ? obj2.GetComponent() : null); } Player val = (Player)obj; if (!((Object)(object)component == (Object)null) && !((Object)(object)val == (Object)null)) { JuvenileFollow.ApplyAnimalFollowToggle(component, val, showMessage); } } } public static void EnsureAttached(Character character) { if (!((Object)(object)character == (Object)null) && !((Object)(object)((Component)character).GetComponent() == (Object)null) && (Object)(object)((Component)character).GetComponent() == (Object)null) { ((Component)character).gameObject.AddComponent(); } } } public sealed class JuvenileGroundSnapper : MonoBehaviour { private Character character; private ZNetView nview; private float nextCheckTime; private void Awake() { character = ((Component)this).GetComponent(); nview = ((Component)this).GetComponent(); } 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(); if ((Object)(object)juvenileGroundSnapper == (Object)null) { juvenileGroundSnapper = ((Component)character).gameObject.AddComponent(); } 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() : ((Component)((RaycastHit)(ref current)).collider).GetComponentInParent()); if (!((Object)(object)val == (Object)null) && !val.IsPlayer() && val.IsTamed() && (!juvenilesOnly || SpeciesHelper.IsEligibleJuvenile(val)) && (juvenilesOnly || !((Object)(object)((Component)val).GetComponent() == (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(); 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(TeleportWorld 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(); 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(TeleportWorld portal, Character character, Dictionary cooldowns, ref float lastNoDestinationMessageTime) { //IL_0136: 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; } if (!ZNet.instance.IsServer()) { 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; } SpeciesType juvenileSpecies = SpeciesHelper.GetJuvenileSpecies(character); if (!DestinationRegistry.TryResolveMaturingDestination(juvenileSpecies, out var destination)) { if (time - lastNoDestinationMessageTime > 5f) { lastNoDestinationMessageTime = time; OffspringPortalPlugin.Log.LogWarning((object)("No maturing portal registered for " + SpeciesCatalog.GetDisplayName(juvenileSpecies) + ".")); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)2, "No maturing portal registered for " + SpeciesCatalog.GetDisplayName(juvenileSpecies) + ".", 0, (Sprite)null); } } return false; } if (!JuvenileTeleporter.TryTeleport(character, destination, portal)) { OffspringPortalPlugin.Log.LogWarning((object)("Failed to teleport " + SpeciesCatalog.GetDisplayName(juvenileSpecies) + " juvenile.")); return false; } OffspringPortalPlugin.Log.LogInfo((object)$"Teleported {SpeciesCatalog.GetDisplayName(juvenileSpecies)} juvenile to maturing portal at {destination.Position}."); cooldowns[instanceID] = time + ModConfig.TeleportCooldownSec.Value; PlayPortalActivation(portal); return true; } private static void PlayPortalActivation(TeleportWorld portal) { //IL_001b: 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 (portal?.m_connected != null) { portal.m_connected.Create(((Component)portal).transform.position, ((Component)portal).transform.rotation, ((Component)portal).transform, 1f, -1); } } } public static class JuvenileTeleporter { public static bool TryTeleport(Character juvenile, PortalRecord destination, TeleportWorld sourcePortal) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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 || !ZNet.instance.IsServer()) { return false; } DestinationRegistry.RefreshPortalPosition(destination); Vector3 exitPosition = PortalPlacement.GetExitPosition(destination.Id, sourcePortal); if ((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.IsAreaReady(exitPosition)) { return TryTeleportNow(juvenile, destination, sourcePortal); } if (TryTeleportNow(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.")); return OffspringPortalRuntime.Instance.TryQueueDistantTeleport(juvenile, destination, sourcePortal); } public static bool TryTeleportNow(Character juvenile, PortalRecord destination, TeleportWorld sourcePortal, bool allowStoredHeight = false) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_0081: 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)juvenile == (Object)null || destination == null || (Object)(object)sourcePortal == (Object)null) { return false; } if (!ZNet.instance.IsServer()) { return false; } ZNetView nview = juvenile.GetNview(); if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return false; } nview.ClaimOwnership(); Tameable component = ((Component)juvenile).GetComponent(); 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); } return false; } JuvenileGroundSnapper.EnsureAttached(juvenile); JuvenileFollowController.EnsureAttached(juvenile); JuvenileFollowRpcHandler.EnsureAttached(juvenile); ZDO zDO = nview.GetZDO(); if (zDO != null) { zDO.Set("op_transported", true); } return true; } public static Vector3 ResolveDestinationPosition(PortalRecord destination, TeleportWorld 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, TeleportWorld 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 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 ModConfig { public static ConfigEntry TeleportCooldownSec; public static ConfigEntry BreederScanRange; public static ConfigEntry BreederScanIntervalSec; public static ConfigEntry DistantTeleportTimeoutSec; public static ConfigEntry AllowRetransport; public static ConfigEntry EnableFollowCommand; public static ConfigEntry EnableCapWarning; public static ConfigEntry MaturingAdultScanIntervalSec; public static void Bind(ConfigFile config) { TeleportCooldownSec = config.Bind("General", "TeleportCooldownSec", 2f, "Seconds between successive teleports at the same source portal."); BreederScanRange = config.Bind("General", "BreederScanRange", 10f, "Breeder portals automatically teleport tamed juveniles within this radius (meters)."); BreederScanIntervalSec = config.Bind("General", "BreederScanIntervalSec", 0.5f, "How often breeder portals scan for nearby juveniles."); DistantTeleportTimeoutSec = config.Bind("General", "DistantTeleportTimeoutSec", 15f, "How long to wait for a distant pen zone to load before giving up."); AllowRetransport = config.Bind("General", "AllowRetransport", false, "If true, a juvenile can use the portal more than once."); EnableFollowCommand = config.Bind("General", "EnableFollowCommand", true, "Press E on tamed juveniles to toggle follow/stay (Boar, Wolf, Lox, Hen, Asksvin)."); EnableCapWarning = config.Bind("General", "EnableCapWarning", true, "Show warning when a maturing portal is within species cap radius of a breeder portal."); MaturingAdultScanIntervalSec = config.Bind("General", "MaturingAdultScanIntervalSec", 30f, "How often maturing portals scan for nearby adults to forward to cull pens."); } } public class OffspringPortalMarker : MonoBehaviour { private TeleportWorld teleportWorld; private void Awake() { teleportWorld = ((Component)this).GetComponent(); } private void Start() { if ((Object)(object)teleportWorld != (Object)null && !((Behaviour)teleportWorld).enabled) { ((MonoBehaviour)this).StartCoroutine(InitializeTeleportWorldWhenReady()); } } private IEnumerator InitializeTeleportWorldWhenReady() { ZNetView nview = ((Component)this).GetComponent(); for (int i = 0; i < 30; i++) { if ((Object)(object)nview != (Object)null && nview.GetZDO() != null) { break; } yield return null; } if (!((Object)(object)teleportWorld == (Object)null) && !((Object)(object)nview == (Object)null) && nview.GetZDO() != null && !((Behaviour)teleportWorld).enabled) { OffspringPortalInitializer.CompleteTeleportWorldAwake(teleportWorld, nview); } } } internal static class OffspringPortalInitializer { internal static void CompleteTeleportWorldAwake(TeleportWorld portal, ZNetView nview) { if (!((Behaviour)portal).enabled) { Traverse.Create((object)portal).Field("m_nview").Value = nview; Traverse.Create((object)portal).Field("m_hadTarget").Value = (bool)AccessTools.Method(typeof(TeleportWorld), "HaveTarget", (Type[])null, (Type[])null).Invoke(portal, null); nview.Register("RPC_SetTag", (Action)delegate(long sender, string tag, string target) { AccessTools.Method(typeof(TeleportWorld), "RPC_SetTag", (Type[])null, (Type[])null).Invoke(portal, new object[3] { sender, tag, target }); }); nview.Register("RPC_SetConnected", (Action)delegate(long sender, ZDOID targetId) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) AccessTools.Method(typeof(TeleportWorld), "RPC_SetConnected", (Type[])null, (Type[])null).Invoke(portal, new object[2] { sender, targetId }); }); ((Behaviour)portal).enabled = true; ((MonoBehaviour)portal).InvokeRepeating("UpdatePortal", 0.5f, 0.5f); } } } public static class OffspringPortalPrefabs { private static bool pieceRegistered; public static GameObject Prefab { get; private set; } public static bool Registered { get; private set; } public static void Initialize() { PrefabManager.OnVanillaPrefabsAvailable += RegisterPrefab; PieceManager.OnPiecesRegistered += RegisterPiece; PrefabManager.OnPrefabsRegistered += RegisterPiece; } public static void EnsurePieceRegistered() { RegisterPiece(); } private static void RegisterPrefab() { if (!Registered) { GameObject val = PrefabManager.Instance.CreateClonedPrefab("offspring_portal", "portal_wood"); if ((Object)(object)val == (Object)null) { OffspringPortalPlugin.Log.LogError((object)"Failed to clone portal_wood via Jotunn."); return; } ConfigureClone(val); EnsureRuntimeTriggers(val.GetComponent()); PrefabManager.Instance.AddPrefab(val); Prefab = val; Registered = true; PrefabManager.OnVanillaPrefabsAvailable -= RegisterPrefab; OffspringPortalPlugin.Log.LogInfo((object)"Registered offspring_portal prefab."); RegisterPiece(); } } private static void RegisterPiece() { if (pieceRegistered || !Registered || (Object)(object)Prefab == (Object)null) { return; } try { ApplyRecipe(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(); 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; TeleportWorld component = clone.GetComponent(); if ((Object)(object)component != (Object)null) { component.m_exitDistance = 1f; } EnsureRuntimeTriggers(component); if ((Object)(object)clone.GetComponent() == (Object)null) { clone.AddComponent(); } Piece component2 = clone.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.m_name = "$piece_offspring_portal"; component2.m_description = "$piece_offspring_portal_description"; } } public static void EnsureRuntimeTriggers(TeleportWorld teleportWorld) { if ((Object)(object)teleportWorld == (Object)null) { return; } TeleportWorldTrigger[] componentsInChildren = ((Component)teleportWorld).GetComponentsInChildren(true); foreach (TeleportWorldTrigger obj in componentsInChildren) { GameObject gameObject = ((Component)obj).gameObject; ((Behaviour)obj).enabled = false; if ((Object)(object)gameObject.GetComponent() == (Object)null) { gameObject.AddComponent(); } } if ((Object)(object)teleportWorld.m_proximityRoot == (Object)null) { return; } Collider[] componentsInChildren2 = ((Component)teleportWorld.m_proximityRoot).GetComponentsInChildren(true); foreach (Collider val in componentsInChildren2) { if (val.isTrigger && !((Object)(object)((Component)val).GetComponent() != (Object)null)) { ((Component)val).gameObject.AddComponent(); } } if ((Object)(object)((Component)teleportWorld).GetComponent() == (Object)null) { ((Component)teleportWorld).gameObject.AddComponent(); } } private static Requirement CreateRequirement(string itemName, int amount) { //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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown ObjectDB instance = ObjectDB.instance; GameObject val = ((instance != null) ? instance.GetItemPrefab(itemName) : null); return new Requirement { m_resItem = (((Object)(object)val != (Object)null) ? val.GetComponent() : null), m_amount = amount, m_amountPerLevel = 0, m_recover = true }; } public static bool IsOffspringPortal(TeleportWorld portal) { if ((Object)(object)portal == (Object)null) { return false; } if ((Object)(object)((Component)portal).GetComponent() != (Object)null) { return true; } if (IsOffspringPiece(((Component)portal).gameObject)) { return true; } ZNetView component = ((Component)portal).GetComponent(); if ((Object)(object)component == (Object)null || component.GetZDO() == null) { return false; } ZDO zDO = component.GetZDO(); if (zDO.GetPrefab() == StringExtensionMethods.GetStableHashCode("offspring_portal")) { return true; } return !string.IsNullOrEmpty(zDO.GetString("op_portal_role", string.Empty)); } public static bool IsOffspringPortal(GameObject gameObject) { if ((Object)(object)gameObject == (Object)null) { return false; } if ((Object)(object)gameObject.GetComponent() != (Object)null) { return true; } if (IsOffspringPiece(gameObject)) { return true; } return IsOffspringPortal(gameObject.GetComponent()); } public static void EnsureIdentity(TeleportWorld portal) { if (!((Object)(object)portal == (Object)null) && IsOffspringPiece(((Component)portal).gameObject) && (Object)(object)((Component)portal).GetComponent() == (Object)null) { ((Component)portal).gameObject.AddComponent(); } } private static bool IsOffspringPiece(GameObject gameObject) { Piece component = gameObject.GetComponent(); if ((Object)(object)component != (Object)null) { return component.m_name == "$piece_offspring_portal"; } return false; } } public sealed class OffspringPortalRuntime : MonoBehaviour { private static OffspringPortalRuntime instance; private readonly HashSet pendingTeleports = new HashSet(); public static OffspringPortalRuntime Instance { get { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if ((Object)(object)instance == (Object)null) { GameObject val = new GameObject("OffspringPortal_Runtime"); Object.DontDestroyOnLoad((Object)val); instance = val.AddComponent(); } return instance; } } public bool TryQueueDistantTeleport(Character juvenile, PortalRecord destination, TeleportWorld sourcePortal) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_004e: Unknown result type (might be due to invalid IL or missing references) ZNetView val = juvenile?.GetNview(); if ((Object)(object)val == (Object)null || !val.IsValid()) { return false; } ZDOID uid = val.GetZDO().m_uid; if (pendingTeleports.Contains(uid)) { return false; } pendingTeleports.Add(uid); ((MonoBehaviour)this).StartCoroutine(DeferredTeleport(juvenile, destination, sourcePortal, uid)); return true; } private IEnumerator DeferredTeleport(Character juvenile, PortalRecord destination, TeleportWorld sourcePortal, ZDOID juvenileId) { //IL_0023: 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) float timeout = ModConfig.DistantTeleportTimeoutSec.Value; float elapsed = 0f; Vector3 targetPos = JuvenileTeleporter.ResolveDestinationPosition(destination, sourcePortal); while (elapsed < timeout) { if ((Object)(object)juvenile == (Object)null) { pendingTeleports.Remove(juvenileId); yield break; } if ((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.IsAreaReady(targetPos) && JuvenileTeleporter.TryTeleportNow(juvenile, destination, sourcePortal)) { pendingTeleports.Remove(juvenileId); yield break; } elapsed += 0.25f; yield return (object)new WaitForSeconds(0.25f); } if ((Object)(object)juvenile != (Object)null && JuvenileTeleporter.TryTeleportNow(juvenile, destination, sourcePortal, allowStoredHeight: true)) { pendingTeleports.Remove(juvenileId); yield break; } pendingTeleports.Remove(juvenileId); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)2, "Could not reach distant pen for " + SpeciesCatalog.GetDisplayName(SpeciesHelper.GetJuvenileSpecies(juvenile)) + ".", 0, (Sprite)null); } } } public class OffspringPortalScanner : MonoBehaviour { private TeleportWorld portal; private readonly Dictionary juvenileCooldowns = new Dictionary(); private readonly Dictionary adultCooldowns = new Dictionary(); private float lastNoJuvenileDestinationMessageTime; private float lastNoAdultDestinationMessageTime; private void Start() { portal = ((Component)this).GetComponent(); float value = ModConfig.BreederScanIntervalSec.Value; ((MonoBehaviour)this).InvokeRepeating("ScanForJuveniles", value, value); float value2 = ModConfig.MaturingAdultScanIntervalSec.Value; ((MonoBehaviour)this).InvokeRepeating("ScanForAdults", value2, value2); } private void ScanForJuveniles() { if (ZNet.instance.IsServer() && !((Object)(object)portal == (Object)null) && OffspringPortalPrefabs.IsOffspringPortal(portal) && JuvenilePortalRouter.IsBreederPortal(portal)) { ScanNearbyCharacters((Character character, Dictionary cooldowns) => JuvenilePortalRouter.TryRoute(portal, character, cooldowns, ref lastNoJuvenileDestinationMessageTime), juvenileCooldowns); } } private void ScanForAdults() { if (ZNet.instance.IsServer() && !((Object)(object)portal == (Object)null) && OffspringPortalPrefabs.IsOffspringPortal(portal) && AdultPortalRouter.IsAdultRoutingMaturingPortal(portal)) { ScanNearbyCharacters((Character character, Dictionary cooldowns) => AdultPortalRouter.TryRoute(portal, character, cooldowns, ref lastNoAdultDestinationMessageTime), adultCooldowns); } } private void ScanNearbyCharacters(Func, bool> tryRoute, Dictionary cooldowns) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_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_007a: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (((Object)(object)portal.m_proximityRoot != (Object)null) ? portal.m_proximityRoot.position : ((Component)portal).transform.position); float value = ModConfig.BreederScanRange.Value; float num = value * value; foreach (Character allCharacter in Character.GetAllCharacters()) { if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsPlayer()) { Vector3 val2 = ((Component)allCharacter).transform.position - val; if (!(((Vector3)(ref val2)).sqrMagnitude > num)) { tryRoute(allCharacter, cooldowns); } } } } } public class OffspringPortalTrigger : MonoBehaviour { private TeleportWorld portal; private readonly Dictionary cooldowns = new Dictionary(); private float lastNoDestinationMessageTime; private void Awake() { portal = ((Component)this).GetComponentInParent(); } private void OnTriggerEnter(Collider other) { if ((Object)(object)portal == (Object)null || !OffspringPortalPrefabs.IsOffspringPortal(portal)) { return; } Character character = GetCharacter(other); Player val = (Player)(object)((character is Player) ? character : null); if (val != null) { if ((Object)(object)val == (Object)(object)Player.m_localPlayer) { ((Character)val).Message((MessageType)2, "Offspring portals route juveniles only. Use a standard portal to travel.", 0, (Sprite)null); } } else { TryRouteJuvenile(other); } } private void OnTriggerStay(Collider other) { if (!(GetCharacter(other) is Player)) { TryRouteJuvenile(other); } } private void TryRouteJuvenile(Collider other) { if (!((Object)(object)portal == (Object)null) && OffspringPortalPrefabs.IsOffspringPortal(portal)) { Character character = GetCharacter(other); if (!((Object)(object)character == (Object)null)) { JuvenilePortalRouter.TryRoute(portal, character, cooldowns, ref lastNoDestinationMessageTime); } } } private static Character GetCharacter(Collider other) { Character component = ((Component)other).GetComponent(); if ((Object)(object)component != (Object)null) { return component; } if ((Object)(object)other.attachedRigidbody != (Object)null) { component = ((Component)other.attachedRigidbody).GetComponent(); if ((Object)(object)component != (Object)null) { return component; } } return ((Component)other).GetComponentInParent(); } } [BepInPlugin("offspringportal.mod", "Offspring Portal", "0.2.9")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class OffspringPortalPlugin : BaseUnityPlugin { public const string PluginGuid = "offspringportal.mod"; public const string PluginName = "Offspring Portal"; public const string PluginVersion = "0.2.9"; internal static ManualLogSource Log; private Harmony harmony; private void Awake() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ModConfig.Bind(((BaseUnityPlugin)this).Config); OffspringPortalPrefabs.Initialize(); _ = OffspringPortalRuntime.Instance; harmony = new Harmony("offspringportal.mod"); harmony.PatchAll(typeof(OffspringPortalPlugin).Assembly); XPortalCompat.TryApply(harmony); Log.LogInfo((object)"Offspring Portal 0.2.9 loaded."); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } public static class PortalDisplayHelper { public const string UnnamedDisplay = "(No Name)"; public const int MaxNameLength = 32; public static string SanitizeName(string name) { if (string.IsNullOrWhiteSpace(name)) { return string.Empty; } name = name.Trim(); if (name.Length > 32) { return name.Substring(0, 32); } return name; } public static string GetDisplayName(ZDO zdo) { if (zdo == null) { return "(No Name)"; } string text = SanitizeName(zdo.GetString("op_portal_name", string.Empty)); if (!string.IsNullOrEmpty(text)) { return text; } return "(No Name)"; } public static string GetDetailLine(PortalRole role, SpeciesType species, AdultDestination adultDestination) { switch (role) { case PortalRole.Maturing: { string text = "Receives: " + SpeciesCatalog.GetDisplayName(species) + " juveniles"; if (adultDestination != AdultDestination.None) { text = text + "\nDestination: " + PortalRoleCatalog.GetDisplayName(adultDestination); } return text; } case PortalRole.Farm: return "Receives: " + SpeciesCatalog.GetDisplayName(species) + " adults"; case PortalRole.Cull: return "Role: Cull yard"; default: return "Role: Breeder"; } } public static string GetHoverText(ZDO zdo, PortalRole role, SpeciesType species, AdultDestination adultDestination, bool capWarning) { string displayName = GetDisplayName(zdo); string detailLine = GetDetailLine(role, species, adultDestination); string text = BuildWarnings(role, species, adultDestination, capWarning); return Localization.instance.Localize("Name: " + displayName + "\n" + detailLine + text + "\n[$KEY_Use] Configure"); } private static string BuildWarnings(PortalRole role, SpeciesType species, AdultDestination adultDestination, bool capWarning) { string text = string.Empty; if (capWarning) { text += "\nWarning: maturing pen is within breeding cap radius of a breeder portal."; } if (role == PortalRole.Maturing && adultDestination != AdultDestination.None && ((adultDestination == AdultDestination.Cull) ? (!DestinationRegistry.HasCullReceiver()) : (!DestinationRegistry.HasFarmReceiver(species)))) { string displayName = PortalRoleCatalog.GetDisplayName(adultDestination); text = text + "\nWarning: No " + displayName + " portal exists. Adults will not be teleported."; } return text; } } public static class PortalHelper { public static bool TryGetPortal(TeleportWorld portal, out ZDOID id, out Vector3 position, out SpeciesType species) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) id = ZDOID.None; position = Vector3.zero; species = SpeciesType.None; if ((Object)(object)portal == (Object)null || !OffspringPortalPrefabs.IsOffspringPortal(portal)) { return false; } ZNetView component = ((Component)portal).GetComponent(); ZDO val = ((component != null) ? component.GetZDO() : null); if (val == null) { return false; } id = val.m_uid; position = val.GetPosition(); species = SpeciesCatalog.FromStorageValue(val.GetString("op_declared_species", string.Empty)); return true; } public static void SyncRegistryFromPortal(TeleportWorld portal) { ZNetView obj = ((portal != null) ? ((Component)portal).GetComponent() : null); ZDO val = ((obj != null) ? obj.GetZDO() : null); if (val != null && OffspringPortalPrefabs.IsOffspringPortal(portal)) { SyncRegistryFromZdo(val); PortalTravelGuard.ClearTravelBindings(val); DestinationRegistry.RefreshCapWarnings(); } } public static void SyncRegistryFromZdo(ZDO zdo) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (zdo != null && zdo.GetPrefab() == StringExtensionMethods.GetStableHashCode("offspring_portal")) { PortalRole role = PortalRoleCatalog.FromZdo(zdo); SpeciesType declaredSpecies = SpeciesCatalog.FromStorageValue(zdo.GetString("op_declared_species", string.Empty)); AdultDestination adultDestination = PortalRoleCatalog.GetAdultDestination(zdo); DestinationRegistry.RegisterOrUpdate(zdo.m_uid, zdo.GetPosition(), role, declaredSpecies, adultDestination); } } public static void RebuildRegistryFromWorld() { DestinationRegistry.Clear(); RebuildRegistryFromLoadedPortals(); RebuildRegistryFromAllPortalZdos(); DestinationRegistry.RefreshCapWarnings(); LogRegistryState("rebuilt"); } private static void LogRegistryState(string reason) { int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; using (IEnumerator enumerator = DestinationRegistry.GetAll().GetEnumerator()) { while (enumerator.MoveNext()) { switch (enumerator.Current.Role) { case PortalRole.Maturing: num2++; break; case PortalRole.Farm: num3++; break; case PortalRole.Cull: num4++; break; default: num++; break; } } } OffspringPortalPlugin.Log.LogInfo((object)$"Portal registry {reason}: {num} breeder(s), {num2} maturing, {num3} farm, {num4} cull."); } private static void RebuildRegistryFromLoadedPortals() { if ((Object)(object)ZNetScene.instance == (Object)null) { return; } TeleportWorld[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (TeleportWorld portal in array) { if (OffspringPortalPrefabs.IsOffspringPortal(portal)) { SyncRegistryFromPortal(portal); } } } private static void RebuildRegistryFromAllPortalZdos() { if (ZDOMan.instance == null) { return; } List list = new List(); int num = 0; while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative("offspring_portal", list, ref num)) { } foreach (ZDO item in list) { SyncRegistryFromZdo(item); } } } public static class PortalPlacement { public const float PortalScale = 0.5f; public const float ScaledExitDistance = 1f; public static Vector3 GetExitPosition(ZDOID portalId, TeleportWorld fallbackPortal = null) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_001e: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_00b6: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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) Vector3 val = Vector3.zero; Quaternion val2 = Quaternion.identity; float num = 1f; ZDOMan instance = ZDOMan.instance; ZDO val3 = ((instance != null) ? instance.GetZDO(portalId) : null); if (val3 != null) { val = val3.GetPosition(); val2 = val3.GetRotation(); } else if ((Object)(object)fallbackPortal != (Object)null) { val = ((Component)fallbackPortal).transform.position; val2 = ((Component)fallbackPortal).transform.rotation; num = fallbackPortal.m_exitDistance; } ZNetScene instance2 = ZNetScene.instance; GameObject val4 = ((instance2 != null) ? instance2.FindInstance(portalId) : null); TeleportWorld val5 = (((Object)(object)val4 != (Object)null) ? val4.GetComponent() : null); if ((Object)(object)val5 != (Object)null) { val = ((Component)val5).transform.position; val2 = ((Component)val5).transform.rotation; num = val5.m_exitDistance; } return val + val2 * Vector3.forward * num; } public static Quaternion GetExitRotation(ZDOID portalId, TeleportWorld fallbackPortal = null) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) ZDOMan instance = ZDOMan.instance; ZDO val = ((instance != null) ? instance.GetZDO(portalId) : null); if (val != null) { return val.GetRotation(); } ZNetScene instance2 = ZNetScene.instance; GameObject val2 = ((instance2 != null) ? instance2.FindInstance(portalId) : null); TeleportWorld val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent() : null); if ((Object)(object)val3 != (Object)null) { return ((Component)val3).transform.rotation; } if (!((Object)(object)fallbackPortal != (Object)null)) { return Quaternion.identity; } return ((Component)fallbackPortal).transform.rotation; } } public enum PortalRole { Breeder, Maturing, Farm, Cull } public enum AdultDestination { None, Farm, Cull } public static class PortalRoleCatalog { public static PortalRole FromZdo(ZDO zdo) { if (zdo == null) { return PortalRole.Breeder; } string value = zdo.GetString("op_portal_role", string.Empty); if (!string.IsNullOrWhiteSpace(value) && Enum.TryParse(value, ignoreCase: true, out var result)) { return result; } if (SpeciesCatalog.FromStorageValue(zdo.GetString("op_declared_species", string.Empty)) != SpeciesType.None) { return PortalRole.Maturing; } return PortalRole.Breeder; } public static AdultDestination GetAdultDestination(ZDO zdo) { if (zdo == null) { return AdultDestination.None; } string value = zdo.GetString("op_adult_destination", string.Empty); if (!string.IsNullOrWhiteSpace(value) && Enum.TryParse(value, ignoreCase: true, out var result)) { return result; } if (!zdo.GetBool("op_forward_adults", false)) { return AdultDestination.None; } return AdultDestination.Cull; } public static string ToStorageValue(PortalRole role) { return role.ToString(); } public static string ToStorageValue(AdultDestination destination) { return destination.ToString(); } public static string GetDisplayName(PortalRole role) { return role switch { PortalRole.Maturing => "Maturing", PortalRole.Farm => "Farm", PortalRole.Cull => "Cull", _ => "Breeder", }; } public static string GetDisplayName(AdultDestination destination) { return destination.ToString(); } public static SpeciesType ResolveSpecies(PortalRole role, SpeciesType selectedSpecies) { if (role != PortalRole.Breeder && role != PortalRole.Cull) { return selectedSpecies; } return SpeciesType.None; } public static AdultDestination ResolveAdultDestination(PortalRole role, AdultDestination selectedDestination) { if (role != PortalRole.Maturing) { return AdultDestination.None; } return selectedDestination; } public static string GetConfiguredMessage(PortalRole role, SpeciesType species, AdultDestination adultDestination) { switch (role) { case PortalRole.Maturing: { string text = "Maturing (receives " + SpeciesCatalog.GetDisplayName(species) + ")"; if (adultDestination != AdultDestination.None) { return text + ", destination " + GetDisplayName(adultDestination); } return text; } case PortalRole.Farm: return "Farm (receives " + SpeciesCatalog.GetDisplayName(species) + " adults)"; case PortalRole.Cull: return "Cull yard"; default: return "Breeder"; } } } public static class PortalRpc { private const string RpcSetConfig = "OffspringPortal_SetConfigV3"; public static void Register() { ZRoutedRpc.instance.Register("OffspringPortal_SetConfigV3", (Method)OnSetConfigRpc); } public static void SetPortalConfig(ZDOID portalId, PortalRole role, SpeciesType species, string name, AdultDestination adultDestination) { //IL_0039: 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) string text = PortalDisplayHelper.SanitizeName(name); AdultDestination adultDestination2 = PortalRoleCatalog.ResolveAdultDestination(role, adultDestination); if (ZNet.instance.IsServer()) { ApplyPortalConfig(portalId, role, species, text, adultDestination2); return; } ZRoutedRpc.instance.InvokeRoutedRPC("OffspringPortal_SetConfigV3", new object[5] { portalId, PortalRoleCatalog.ToStorageValue(role), SpeciesCatalog.ToStorageValue(species), text, PortalRoleCatalog.ToStorageValue(adultDestination2) }); } private static void OnSetConfigRpc(long sender, ZDOID portalId, string roleValue, string speciesValue, string name, string adultDestinationValue) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (ZNet.instance.IsServer()) { PortalRole result; PortalRole role = (Enum.TryParse(roleValue, ignoreCase: true, out result) ? result : PortalRole.Breeder); AdultDestination result2; AdultDestination adultDestination = (Enum.TryParse(adultDestinationValue, ignoreCase: true, out result2) ? result2 : AdultDestination.None); ApplyPortalConfig(portalId, role, SpeciesCatalog.FromStorageValue(speciesValue), PortalDisplayHelper.SanitizeName(name), adultDestination); } } private static void ApplyPortalConfig(ZDOID portalId, PortalRole role, SpeciesType species, string name, AdultDestination adultDestination) { //IL_0005: 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_0077: 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) ZDO zDO = ZDOMan.instance.GetZDO(portalId); if (zDO != null) { SpeciesType speciesType = PortalRoleCatalog.ResolveSpecies(role, species); AdultDestination adultDestination2 = PortalRoleCatalog.ResolveAdultDestination(role, adultDestination); zDO.Set("op_portal_role", PortalRoleCatalog.ToStorageValue(role)); zDO.Set("op_declared_species", SpeciesCatalog.ToStorageValue(speciesType)); zDO.Set("op_portal_name", name); zDO.Set("op_adult_destination", PortalRoleCatalog.ToStorageValue(adultDestination2)); zDO.Set("op_forward_adults", adultDestination2 == AdultDestination.Cull); PortalTravelGuard.ClearTravelBindings(zDO); DestinationRegistry.RegisterOrUpdate(portalId, zDO.GetPosition(), role, speciesType, adultDestination2); DestinationRegistry.RefreshCapWarnings(); if ((Object)(object)FindPortal(portalId) != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null) { string text = (string.IsNullOrEmpty(name) ? "(No Name)" : name); string configuredMessage = PortalRoleCatalog.GetConfiguredMessage(role, speciesType, adultDestination2); ((Character)Player.m_localPlayer).Message((MessageType)1, "Portal \"" + text + "\" configured as " + configuredMessage + ".", 0, (Sprite)null); } } } private static TeleportWorld FindPortal(ZDOID portalId) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = ZDOMan.instance.GetZDO(portalId); if (zDO == null) { return null; } ZNetView val = ZNetScene.instance.FindInstance(zDO); if (!((Object)(object)val != (Object)null)) { return null; } return ((Component)val).GetComponent(); } } public static class PortalTravelGuard { public const string PlayerTravelBlockedMessage = "Offspring portals route juveniles only. Use a standard portal to travel."; private const string XPortalTargetField = "XPortal_TargetId"; private const string XPortalPreviousField = "XPortal_PreviousId"; public static bool IsOffspringPortalZdo(ZDO zdo) { if (zdo == null) { return false; } if (zdo.GetPrefab() == StringExtensionMethods.GetStableHashCode("offspring_portal")) { return true; } return !string.IsNullOrEmpty(zdo.GetString("op_portal_role", string.Empty)); } public static bool TryGetConnectedPortal(TeleportWorld portal, out TeleportWorld connected) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0049: Unknown result type (might be due to invalid IL or missing references) connected = null; if ((Object)(object)portal == (Object)null) { return false; } ZNetView component = ((Component)portal).GetComponent(); ZDO val = ((component != null) ? component.GetZDO() : null); if (val == null) { return false; } ZDOID connectionZDOID = val.GetConnectionZDOID((ConnectionType)1); if (connectionZDOID == ZDOID.None) { return false; } ZNetScene instance = ZNetScene.instance; GameObject val2 = ((instance != null) ? instance.FindInstance(connectionZDOID) : null); connected = (((Object)(object)val2 != (Object)null) ? val2.GetComponent() : null); return (Object)(object)connected != (Object)null; } public static bool BlocksPlayerTravel(TeleportWorld source, Player player, out string message) { message = null; if ((Object)(object)source == (Object)null || (Object)(object)player == (Object)null) { return false; } if (OffspringPortalPrefabs.IsOffspringPortal(source)) { message = "Offspring portals route juveniles only. Use a standard portal to travel."; return true; } if (TryGetConnectedPortal(source, out var connected) && OffspringPortalPrefabs.IsOffspringPortal(connected)) { message = "Offspring portals route juveniles only. Use a standard portal to travel."; return true; } return false; } public static void ClearTravelBindings(ZDO zdo) { //IL_0006: 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_0026: Unknown result type (might be due to invalid IL or missing references) if (zdo != null) { zdo.UpdateConnection((ConnectionType)1, ZDOID.None); zdo.Set("XPortal_TargetId", ZDOID.None); zdo.Set("XPortal_PreviousId", ZDOID.None); } } public static void ClearTravelBindings(TeleportWorld portal) { if (!((Object)(object)portal == (Object)null) && ZNet.instance.IsServer()) { ZNetView component = ((Component)portal).GetComponent(); ZDO val = ((component != null) ? component.GetZDO() : null); if (val != null && component.IsOwner()) { ClearTravelBindings(val); } } } public static void ClearAllOffspringTravelBindings() { if (!ZNet.instance.IsServer()) { return; } TeleportWorld[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (TeleportWorld portal in array) { if (OffspringPortalPrefabs.IsOffspringPortal(portal)) { ClearTravelBindings(portal); } } } } public static class SpeciesHelper { private static readonly Dictionary AdultPrefabMap = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "Boar", SpeciesType.Boar }, { "Wolf", SpeciesType.Wolf }, { "WolfCub", SpeciesType.Wolf }, { "Lox", SpeciesType.Lox }, { "Hen", SpeciesType.Chicken }, { "Chicken", SpeciesType.Chicken }, { "Asksvin", SpeciesType.Asksvin } }; public static bool IsEligibleJuvenile(Character character) { if ((Object)(object)character == (Object)null || !character.IsTamed()) { return false; } if ((Object)(object)((Component)character).GetComponent() != (Object)null) { return true; } return (((Object)character).name ?? string.Empty).IndexOf("wolfcub", StringComparison.OrdinalIgnoreCase) >= 0; } public static bool IsEligibleAdult(Character character) { if ((Object)(object)character != (Object)null && character.IsTamed() && (Object)(object)((Component)character).GetComponent() == (Object)null) { return GetAdultSpecies(character) != SpeciesType.None; } return false; } public static SpeciesType GetAdultSpecies(Character character) { return MapAdultPrefab((character != null) ? ((Object)character).name : null); } public static SpeciesType GetJuvenileSpecies(Character character) { Growup component = ((Component)character).GetComponent(); if ((Object)(object)component == (Object)null) { return SpeciesType.None; } if ((Object)(object)component.m_grownPrefab != (Object)null) { SpeciesType speciesType = MapAdultPrefab(((Object)component.m_grownPrefab).name); if (speciesType != SpeciesType.None) { return speciesType; } } if (component.m_altGrownPrefabs != null) { foreach (GrownEntry altGrownPrefab in component.m_altGrownPrefabs) { if (!((Object)(object)altGrownPrefab?.m_prefab == (Object)null)) { SpeciesType speciesType2 = MapAdultPrefab(((Object)altGrownPrefab.m_prefab).name); if (speciesType2 != SpeciesType.None) { return speciesType2; } } } } return MapAdultPrefab(((Object)character).name); } public static bool SpeciesMatches(SpeciesType juvenile, SpeciesType destination) { return destination switch { SpeciesType.None => false, SpeciesType.All => true, _ => juvenile == destination, }; } private static SpeciesType MapAdultPrefab(string prefabName) { if (string.IsNullOrWhiteSpace(prefabName)) { return SpeciesType.None; } foreach (KeyValuePair item in AdultPrefabMap) { if (prefabName.IndexOf(item.Key, StringComparison.OrdinalIgnoreCase) >= 0) { return item.Value; } } return SpeciesType.None; } } public enum SpeciesType { None, All, Boar, Wolf, Lox, Chicken, Asksvin } public static class SpeciesCatalog { public static readonly IReadOnlyList DestinationOptions = new SpeciesType[6] { SpeciesType.Boar, SpeciesType.Wolf, SpeciesType.Lox, SpeciesType.Chicken, SpeciesType.Asksvin, SpeciesType.All }; public static string ToStorageValue(SpeciesType species) { if (species != SpeciesType.None) { return species.ToString(); } return string.Empty; } public static SpeciesType FromStorageValue(string value) { if (string.IsNullOrWhiteSpace(value)) { return SpeciesType.None; } if (!Enum.TryParse(value, ignoreCase: true, out var result)) { return SpeciesType.None; } return result; } public static string GetDisplayName(SpeciesType species) { return species switch { SpeciesType.All => "All", SpeciesType.Boar => "Boar", SpeciesType.Wolf => "Wolf", SpeciesType.Lox => "Lox", SpeciesType.Chicken => "Hen", SpeciesType.Asksvin => "Asksvin", _ => "Breeder", }; } } internal static class ValheimExtensions { public static ZNetView GetNview(this Character character) { if (!((Object)(object)character != (Object)null)) { return null; } return ((Component)character).GetComponent(); } public static ZDO GetZdo(this Character character) { ZNetView nview = character.GetNview(); if (!((Object)(object)nview != (Object)null)) { return null; } return nview.GetZDO(); } } internal static class XPortalCompat { public static void TryApply(Harmony harmony) { Type type = AccessTools.TypeByName("XPortal.XPortal"); if (!(type == null)) { Patch(harmony, type, "OnPrePortalHover", "OnPrePortalHoverPrefix"); Patch(harmony, type, "OnPortalPlaced", "OnPortalPlacedPrefix"); Patch(harmony, type, "OnPortalRequestText", "OnPortalRequestTextPrefix"); OffspringPortalPlugin.Log.LogInfo((object)"XPortal compatibility enabled: offspring portals excluded from travel network."); } } private static void Patch(Harmony harmony, Type targetType, string methodName, string handlerName) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(targetType, methodName, (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(XPortalCompat), handlerName, (Type[])null, (Type[])null); if (!(methodInfo == null) && !(methodInfo2 == null)) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static bool ShouldBlock(ZDOID portalId) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) ZDOMan instance = ZDOMan.instance; return PortalTravelGuard.IsOffspringPortalZdo((instance != null) ? instance.GetZDO(portalId) : null); } private static bool OnPrePortalHoverPrefix(ZDOID portalId) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return !ShouldBlock(portalId); } private static bool OnPortalPlacedPrefix(ZDOID portalId) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (!ShouldBlock(portalId)) { return true; } PortalTravelGuard.ClearTravelBindings(FindPortal(portalId)); return false; } private static bool OnPortalRequestTextPrefix(ZDOID portalId) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return !ShouldBlock(portalId); } private static TeleportWorld FindPortal(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(); } } public static class ZdoFields { public const string DeclaredSpecies = "op_declared_species"; public const string PortalName = "op_portal_name"; public const string PortalRole = "op_portal_role"; public const string ForwardAdults = "op_forward_adults"; public const string AdultDestination = "op_adult_destination"; public const string Transported = "op_transported"; public const string FollowTarget = "op_follow_target"; public const string CapWarning = "op_cap_warning"; } public static class PrefabNames { public const string OffspringPortal = "offspring_portal"; public const string VanillaPortalWood = "portal_wood"; } } namespace OffspringPortal.UI { public sealed class SpeciesConfigPanel { private static SpeciesConfigPanel instance; private const float Padding = 24f; private const float LabelWidth = 160f; private const float InputWidth = 460f; private const float RowHeight = 32f; private const float ButtonWidth = 110f; private const float ButtonHeight = 48f; private const float FirstColumnLeft = 24f; private const float SecondColumnLeft = 208f; private const float NameRowTop = -84f; private const float TypeRowTop = -140f; private const float ReceivesRowTop = -196f; private const float DestinationRowTop = -252f; private const float ButtonRowHeight = 72f; private GameObject mainPanel; private GameObject receivesLabelObject; private GameObject destinationLabelObject; private InputField nameInputField; private Dropdown typeDropdown; private Dropdown speciesDropdown; private Dropdown destinationDropdown; private readonly Dictionary indexToRole = new Dictionary(); private readonly Dictionary indexToSpecies = new Dictionary(); private readonly Dictionary indexToDestination = new Dictionary(); private ZDOID portalId; private SpeciesType savedSpecies = SpeciesType.Boar; private AdultDestination savedDestination; private bool initialized; public static SpeciesConfigPanel Instance => instance ?? (instance = new SpeciesConfigPanel()); public void Open(ZDOID id, PortalRole currentRole, SpeciesType currentSpecies, string currentName, AdultDestination adultDestination) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) EnsureInitialized(); if (!((Object)(object)mainPanel == (Object)null)) { portalId = id; savedSpecies = ((currentSpecies == SpeciesType.None) ? SpeciesType.Boar : currentSpecies); savedDestination = adultDestination; nameInputField.text = currentName ?? string.Empty; PopulateTypeDropdown(currentRole); PopulateSpeciesDropdown(savedSpecies); PopulateDestinationDropdown(savedDestination); UpdatePanelState(); mainPanel.SetActive(true); GUIManager.BlockInput(true); } } public void Close() { if ((Object)(object)mainPanel != (Object)null) { mainPanel.SetActive(false); } GUIManager.BlockInput(false); } private void EnsureInitialized() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_014f: 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) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_0398: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03d0: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_0446: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Unknown result type (might be due to invalid IL or missing references) //IL_0494: Unknown result type (might be due to invalid IL or missing references) //IL_049e: Expected O, but got Unknown //IL_04c7: Unknown result type (might be due to invalid IL or missing references) //IL_04d6: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_0509: Unknown result type (might be due to invalid IL or missing references) //IL_0524: Unknown result type (might be due to invalid IL or missing references) //IL_052e: Expected O, but got Unknown if (initialized) { return; } GameObject val = GameObject.Find("_GameMain/LoadingGUI/CustomGUIFront"); if ((Object)(object)val == (Object)null) { OffspringPortalPlugin.Log.LogError((object)"Could not find Valheim custom GUI root."); return; } float num = 692f; float num2 = 308f + 72f + 24f; mainPanel = GUIManager.Instance.CreateWoodpanel(val.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), num, num2, false); ((Object)mainPanel).name = "OffspringPortal_ConfigPanel"; mainPanel.AddComponent(); if ((Object)(object)mainPanel.GetComponentInParent() == (Object)null) { mainPanel.AddComponent(); } GameObject obj = GUIManager.Instance.CreateText("Configure Portal", mainPanel.transform, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(20f, -15f), GUIManager.Instance.AveriaSerifBold, 32, GUIManager.Instance.ValheimOrange, true, Color.black, 250f, 50f, false); obj.GetComponent().alignment = (TextAnchor)1; obj.GetComponent().pivot = new Vector2(0.5f, 1f); CreateLabel("Name", -84f, out var labelObject); GameObject val2 = GUIManager.Instance.CreateInputField(mainPanel.transform, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(208f, -84f), (ContentType)0, "e.g. Boar Farm", 18, 460f, 32f); val2.GetComponent().pivot = new Vector2(0f, 1f); nameInputField = val2.GetComponent(); nameInputField.characterLimit = 32; CreateLabel("Type", -140f, out labelObject); GameObject val3 = GUIManager.Instance.CreateDropDown(mainPanel.transform, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(208f, -140f), 18, 460f, 32f); val3.GetComponent().pivot = new Vector2(0f, 1f); typeDropdown = val3.GetComponent(); ((UnityEvent)(object)typeDropdown.onValueChanged).AddListener((UnityAction)OnTypeChanged); ApplyDropdownStyle(typeDropdown); CreateLabel("Receives", -196f, out receivesLabelObject); GameObject val4 = GUIManager.Instance.CreateDropDown(mainPanel.transform, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(208f, -196f), 18, 460f, 32f); val4.GetComponent().pivot = new Vector2(0f, 1f); speciesDropdown = val4.GetComponent(); ((UnityEvent)(object)speciesDropdown.onValueChanged).AddListener((UnityAction)OnSpeciesChanged); ApplyDropdownStyle(speciesDropdown); CreateLabel("Destination", -252f, out destinationLabelObject); GameObject val5 = GUIManager.Instance.CreateDropDown(mainPanel.transform, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(208f, -252f), 18, 460f, 32f); val5.GetComponent().pivot = new Vector2(0f, 1f); destinationDropdown = val5.GetComponent(); ((UnityEvent)(object)destinationDropdown.onValueChanged).AddListener((UnityAction)OnDestinationChanged); ApplyDropdownStyle(destinationDropdown); GameObject obj2 = GUIManager.Instance.CreateButton(Localization.instance.Localize("$menu_ok"), mainPanel.transform, new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(-24f, 24f), 110f, 48f); obj2.GetComponent().pivot = new Vector2(1f, 0f); ((UnityEvent)obj2.GetComponent