using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DundrPortalGun.Config; using DundrPortalGun.Controls; using DundrPortalGun.Items; using DundrPortalGun.Networking; using DundrPortalGun.Portals; using DundrPortalGun.Projectiles; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("DundrPortalGun")] [assembly: AssemblyDescription("A multiplayer momentum-preserving Portal Gun mod for Valheim.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("DundrPortalGun")] [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("6d0ffaa9-48fb-4eb7-bf17-4d61e6da9daa")] [assembly: AssemblyFileVersion("0.11.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyVersion("0.11.2.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DundrPortalGun { [BepInPlugin("samuel.valheim.dundrportalgun", "DundrPortalGun", "0.11.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "samuel.valheim.dundrportalgun"; public const string PluginName = "DundrPortalGun"; public const string PluginVersion = "0.11.2"; private static readonly string[] RequiredPrefabNames = new string[5] { "StaffLightning", "staff_lightning_projectile", "portal_wood", "portal", "fx_portal_connected" }; private static readonly string[] AttackFieldTerms = new string[12] { "attack", "projectile", "spawn", "animation", "stamina", "eitr", "accuracy", "burst", "charge", "draw", "recoil", "velocity" }; private static readonly string[] MovementFieldTerms = new string[11] { "body", "velocity", "move", "ground", "fall", "jump", "dodge", "teleport", "maxair", "lastground", "sliding" }; private ConfigEntry researchHarnessEnabled; private ConfigEntry relocationShortcut; private ConfigEntry relocationDistance; private ModConfig modConfig; private Harmony harmony; private bool playerMovementLogged; private Coroutine relocationRoutine; internal static ManualLogSource Log { get; private set; } internal static PortalManager Portals { get; private set; } internal static PortalNetwork Network { get; private set; } private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; harmony = new Harmony("samuel.valheim.dundrportalgun"); harmony.PatchAll(typeof(Plugin).Assembly); modConfig = new ModConfig(((BaseUnityPlugin)this).Config); Portals = new PortalManager(modConfig); Network = new PortalNetwork(modConfig, Portals); researchHarnessEnabled = ((BaseUnityPlugin)this).Config.Bind("Research Harness", "Enabled", false, "Resolve and inspect the Dundr/portal prefabs and enable the explicit relocation test shortcut."); relocationShortcut = ((BaseUnityPlugin)this).Config.Bind("Research Harness", "Direct Relocation Test", new KeyboardShortcut((KeyCode)291, Array.Empty()), "In a safe open area, move the local player directly forward without calling Player.TeleportTo and log Rigidbody velocity over the following physics ticks. Extra held keys such as sprint do not block this test."); relocationDistance = ((BaseUnityPlugin)this).Config.Bind("Research Harness", "Direct Relocation Distance", 5f, new ConfigDescription("Horizontal distance in metres used by the F10 direct-relocation test.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 15f), Array.Empty())); PrefabManager.OnVanillaPrefabsAvailable += InspectRequiredPrefabs; PrefabManager.OnVanillaPrefabsAvailable += RegisterMilestoneOneContent; Log.LogInfo((object)"DundrPortalGun 0.11.2 loaded."); Log.LogInfo((object)("Runtime inspection is enabled=" + researchHarnessEnabled.Value + ". Direct relocation test=" + ((object)relocationShortcut.Value/*cast due to .constrained prefix*/).ToString() + ".")); } private void Update() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (Network != null) { Network.Tick(localPlayer); } PortalGunInput.Tick(localPlayer); Portals.Tick(localPlayer); if (researchHarnessEnabled.Value && !((Object)(object)localPlayer == (Object)null)) { if (!playerMovementLogged) { playerMovementLogged = true; InspectPlayerMovement(localPlayer); } KeyboardShortcut value = relocationShortcut.Value; if (Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey)) { StartDirectRelocationTest(localPlayer); } } } private void FixedUpdate() { if (Portals != null) { Portals.FixedTick(Player.m_localPlayer); } } private void LateUpdate() { if (Portals != null) { Portals.LateTick(Player.m_localPlayer, Camera.main); } } private void OnDestroy() { PortalGunInput.Reset(); if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } PrefabManager.OnVanillaPrefabsAvailable -= InspectRequiredPrefabs; PrefabManager.OnVanillaPrefabsAvailable -= RegisterMilestoneOneContent; if (Portals != null) { Portals.ClearAll("plugin shutdown"); Portals = null; } if (Network != null) { Network.Shutdown(); Network = null; } } private void RegisterMilestoneOneContent() { PrefabManager.OnVanillaPrefabsAvailable -= RegisterMilestoneOneContent; try { PortalProjectilePrefabs portalProjectilePrefabs = PortalProjectileFactory.Register(); PortalGunItem.Register(modConfig, portalProjectilePrefabs.Standard, portalProjectilePrefabs.Blue); Log.LogInfo((object)"Milestone 1 content registered successfully."); } catch (Exception ex) { Log.LogError((object)("Milestone 1 content registration failed: " + ex)); } } private void InspectRequiredPrefabs() { PrefabManager.OnVanillaPrefabsAvailable -= InspectRequiredPrefabs; if (!researchHarnessEnabled.Value) { Log.LogInfo((object)"Runtime prefab inspection skipped because the research harness is disabled."); return; } Log.LogInfo((object)"=== Dundr Portal Gun required prefab inspection ==="); Dictionary dictionary = new Dictionary(); string[] requiredPrefabNames = RequiredPrefabNames; foreach (string text in requiredPrefabNames) { GameObject val = (dictionary[text] = PrefabManager.Instance.GetPrefab(text)); if ((Object)(object)val == (Object)null) { Log.LogError((object)("Required prefab did not resolve: " + text)); continue; } Log.LogInfo((object)("Resolved prefab '" + text + "': instance=" + ((Object)val).GetInstanceID() + ", activeSelf=" + val.activeSelf + ".")); } if (dictionary.TryGetValue("StaffLightning", out var value) && (Object)(object)value != (Object)null) { InspectStaff(value); } DumpPrefabHierarchy("staff_lightning_projectile", dictionary); DumpPrefabHierarchy("portal_wood", dictionary); DumpPrefabHierarchy("portal", dictionary); DumpPrefabHierarchy("fx_portal_connected", dictionary); Log.LogInfo((object)"=== End required prefab inspection ==="); } private static void InspectStaff(GameObject staff) { Log.LogInfo((object)"--- StaffLightning item and attack inspection ---"); ItemDrop component = staff.GetComponent(); if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null) { Log.LogError((object)"StaffLightning has no readable ItemDrop shared data."); DumpHierarchy(staff); return; } SharedData shared = component.m_itemData.m_shared; Log.LogInfo((object)("Shared item name=" + shared.m_name + ", itemType=" + ((object)Unsafe.As(ref shared.m_itemType)/*cast due to .constrained prefix*/).ToString() + ".")); LogFields("StaffLightning.SharedData", shared, AttackFieldTerms); LogFields("StaffLightning.PrimaryAttack", shared.m_attack, AttackFieldTerms); LogFields("StaffLightning.SecondaryAttack", shared.m_secondaryAttack, AttackFieldTerms); DumpHierarchy(staff); } private static void DumpPrefabHierarchy(string prefabName, IDictionary resolved) { if (resolved.TryGetValue(prefabName, out var value) && !((Object)(object)value == (Object)null)) { Log.LogInfo((object)("--- Hierarchy inspection: " + prefabName + " ---")); DumpHierarchy(value); } } private static void DumpHierarchy(GameObject root) { StringBuilder stringBuilder = new StringBuilder(); AppendTransform(stringBuilder, root.transform, ((Object)root.transform).name, 0); Log.LogInfo((object)stringBuilder.ToString()); } private static void AppendTransform(StringBuilder output, Transform transform, string path, int depth) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) output.Append(' ', depth * 2); output.Append(path); output.Append(" [activeSelf="); output.Append(((Component)transform).gameObject.activeSelf); output.Append(", localPosition="); output.Append(FormatVector(transform.localPosition)); output.Append(", localRotation="); output.Append(FormatVector(transform.localEulerAngles)); output.Append(", localScale="); output.Append(FormatVector(transform.localScale)); output.Append(", components="); Component[] components = ((Component)transform).GetComponents(); for (int i = 0; i < components.Length; i++) { if (i > 0) { output.Append(','); } Component val = components[i]; output.Append(((Object)(object)val == (Object)null) ? "" : ((object)val).GetType().FullName); } output.AppendLine("]"); for (int j = 0; j < transform.childCount; j++) { Transform child = transform.GetChild(j); AppendTransform(output, child, path + "/" + ((Object)child).name, depth + 1); } } private static void InspectPlayerMovement(Player player) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) Log.LogInfo((object)"=== Local Player/Character movement inspection ==="); Rigidbody component = ((Component)player).GetComponent(); if ((Object)(object)component == (Object)null) { Log.LogError((object)"Local player has no Rigidbody component."); } else { Log.LogInfo((object)("Rigidbody: instance=" + ((Object)component).GetInstanceID() + ", isKinematic=" + component.isKinematic + ", useGravity=" + component.useGravity + ", mass=" + FormatFloat(component.mass) + ", linearDamping=" + FormatFloat(component.linearDamping) + ", angularDamping=" + FormatFloat(component.angularDamping) + ", interpolation=" + ((object)component.interpolation/*cast due to .constrained prefix*/).ToString() + ", collisionDetection=" + ((object)component.collisionDetectionMode/*cast due to .constrained prefix*/).ToString() + ", constraints=" + ((object)component.constraints/*cast due to .constrained prefix*/).ToString() + ", position=" + FormatVector(component.position) + ", velocity=" + FormatVector(component.linearVelocity) + ".")); } LogDeclaredFields("Player", player, typeof(Player), MovementFieldTerms); LogDeclaredFields("Character", player, typeof(Character), MovementFieldTerms); Log.LogInfo((object)"=== End Local Player/Character movement inspection ==="); } private void StartDirectRelocationTest(Player player) { //IL_003e: 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_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) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0121: 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) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (relocationRoutine != null) { Log.LogWarning((object)"Direct relocation test ignored because a prior test is still being measured."); return; } Rigidbody component = ((Component)player).GetComponent(); if ((Object)(object)component == (Object)null) { Log.LogError((object)"Direct relocation test failed: local player has no Rigidbody."); return; } Vector3 forward = ((Component)player).transform.forward; forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.001f) { forward = Vector3.forward; } ((Vector3)(ref forward)).Normalize(); Vector3 position = component.position; Vector3 linearVelocity = component.linearVelocity; Vector3 val = position + forward * relocationDistance.Value; Log.LogInfo((object)("DIRECT_MOVE begin: position=" + FormatVector(position) + ", target=" + FormatVector(val) + ", velocity=" + FormatVector(linearVelocity) + ", speed=" + FormatFloat(((Vector3)(ref linearVelocity)).magnitude) + ". Player.TeleportTo will not be called.")); LogTeleportFields(player, "before"); component.position = val; ((Component)player).transform.position = val; Physics.SyncTransforms(); component.linearVelocity = linearVelocity; component.WakeUp(); ManualLogSource log = Log; string[] obj = new string[9] { "DIRECT_MOVE immediate: transform=", FormatVector(((Component)player).transform.position), ", body=", FormatVector(component.position), ", velocity=", FormatVector(component.linearVelocity), ", speed=", null, null }; Vector3 linearVelocity2 = component.linearVelocity; obj[7] = FormatFloat(((Vector3)(ref linearVelocity2)).magnitude); obj[8] = "."; log.LogInfo((object)string.Concat(obj)); LogTeleportFields(player, "immediate"); relocationRoutine = ((MonoBehaviour)this).StartCoroutine(MeasureRelocation(player, component, val, linearVelocity)); } private IEnumerator MeasureRelocation(Player player, Rigidbody body, Vector3 target, Vector3 velocityBefore) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) yield return (object)new WaitForFixedUpdate(); LogRelocationSample("fixed+1", player, body, target, velocityBefore); yield return (object)new WaitForFixedUpdate(); LogRelocationSample("fixed+2", player, body, target, velocityBefore); relocationRoutine = null; Log.LogInfo((object)"DIRECT_MOVE measurement complete. Report whether any black/loading screen appeared."); } private static void LogRelocationSample(string stage, Player player, Rigidbody body, Vector3 target, Vector3 velocityBefore) { //IL_002e: 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_005c: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)body == (Object)null) { Log.LogWarning((object)("DIRECT_MOVE " + stage + ": player or Rigidbody was destroyed.")); return; } Vector3 linearVelocity = body.linearVelocity; Log.LogInfo((object)("DIRECT_MOVE " + stage + ": transform=" + FormatVector(((Component)player).transform.position) + ", body=" + FormatVector(body.position) + ", targetError=" + FormatFloat(Vector3.Distance(body.position, target)) + ", velocity=" + FormatVector(linearVelocity) + ", speed=" + FormatFloat(((Vector3)(ref linearVelocity)).magnitude) + ", speedDelta=" + FormatFloat(((Vector3)(ref linearVelocity)).magnitude - ((Vector3)(ref velocityBefore)).magnitude) + ".")); LogTeleportFields(player, stage); } private static void LogTeleportFields(Player player, string stage) { List list = new List(); Type type = typeof(Player); while (type != null && type != typeof(MonoBehaviour)) { FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.Name.IndexOf("teleport", StringComparison.OrdinalIgnoreCase) >= 0) { try { list.Add(type.Name + "." + fieldInfo.Name + "=" + FormatValue(fieldInfo.GetValue(player))); } catch (Exception ex) { list.Add(type.Name + "." + fieldInfo.Name + "=<" + ex.GetType().Name + ">"); } } } type = type.BaseType; } Log.LogInfo((object)("DIRECT_MOVE " + stage + " teleport fields: " + ((list.Count == 0) ? "" : string.Join(", ", list.ToArray())) + ".")); } private static void LogFields(string label, object instance, string[] terms) { if (instance == null) { Log.LogInfo((object)(label + "=.")); return; } Type type = instance.GetType(); while (type != null && type != typeof(object)) { LogDeclaredFields(label, instance, type, terms); type = type.BaseType; } } private static void LogDeclaredFields(string label, object instance, Type declaredType, string[] terms) { FieldInfo[] fields = declaredType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Array.Sort(fields, (FieldInfo left, FieldInfo right) => string.Compare(left.Name, right.Name, StringComparison.Ordinal)); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { if (ContainsAny(fieldInfo.Name, terms)) { try { Log.LogInfo((object)(label + "." + declaredType.Name + "." + fieldInfo.Name + "=" + FormatValue(fieldInfo.GetValue(instance)) + ".")); } catch (Exception ex) { Log.LogWarning((object)(label + "." + declaredType.Name + "." + fieldInfo.Name + " could not be read: " + ex.Message)); } } } } private static bool ContainsAny(string value, string[] terms) { foreach (string value2 in terms) { if (value.IndexOf(value2, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } private static string FormatValue(object value) { //IL_006e: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) if (value == null) { return ""; } Object val = (Object)((value is Object) ? value : null); if (val != (Object)null) { return ((object)val).GetType().Name + "('" + val.name + "', instance=" + val.GetInstanceID() + ")"; } if (value is Vector3) { return FormatVector((Vector3)value); } if (value is Quaternion val2) { return FormatVector(((Quaternion)(ref val2)).eulerAngles); } if (value is ICollection collection) { return value.GetType().Name + "[count=" + collection.Count + "]"; } Type type = value.GetType(); if (type.IsPrimitive || value is decimal || value is string || type.IsEnum) { return Convert.ToString(value, CultureInfo.InvariantCulture); } return type.FullName; } private static string FormatVector(Vector3 value) { //IL_0010: 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_003c: Unknown result type (might be due to invalid IL or missing references) return "(" + FormatFloat(value.x) + "," + FormatFloat(value.y) + "," + FormatFloat(value.z) + ")"; } private static string FormatFloat(float value) { return value.ToString("0.###", CultureInfo.InvariantCulture); } } } namespace DundrPortalGun.Projectiles { internal sealed class PortalProjectilePrefabs { internal GameObject Standard { get; private set; } internal GameObject Blue { get; private set; } internal PortalProjectilePrefabs(GameObject standard, GameObject blue) { Standard = standard; Blue = blue; } } internal static class PortalProjectileFactory { internal const string StandardProjectileName = "DundrPortalGun_StandardProjectile"; internal const string BlueProjectileName = "DundrPortalGun_BlueProjectile"; private const string SourceProjectileName = "staff_lightning_projectile"; internal static PortalProjectilePrefabs Register() { //IL_001a: 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) GameObject standard = CreateProjectile("DundrPortalGun_StandardProjectile", PortalEndpointType.Standard, new Color(1f, 0.35f, 0.05f, 1f)); GameObject blue = CreateProjectile("DundrPortalGun_BlueProjectile", PortalEndpointType.Blue, new Color(0.05f, 0.35f, 1f, 1f)); Plugin.Log.LogInfo((object)"Registered harmless portal projectiles: DundrPortalGun_StandardProjectile and DundrPortalGun_BlueProjectile."); return new PortalProjectilePrefabs(standard, blue); } private static GameObject CreateProjectile(string prefabName, PortalEndpointType endpointType, Color color) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown GameObject val = PrefabManager.Instance.CreateClonedPrefab(prefabName, "staff_lightning_projectile"); if ((Object)(object)val == (Object)null) { throw new InvalidOperationException("Could not clone required projectile prefab 'staff_lightning_projectile'."); } Projectile component = val.GetComponent(); if ((Object)(object)component == (Object)null) { throw new InvalidOperationException("Cloned projectile '" + prefabName + "' has no Projectile component."); } MakeHarmless(component); TintVisuals(val, color); val.AddComponent().EndpointType = endpointType; PrefabManager.Instance.AddPrefab(new CustomPrefab(val, true)); return val; } private static void MakeHarmless(Projectile projectile) { //IL_0006: 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_0084: Expected O, but got Unknown projectile.m_damage = default(DamageTypes); projectile.m_aoe = 0f; projectile.m_attackForce = 0f; projectile.m_adrenaline = 0f; projectile.m_backstabBonus = 1f; projectile.m_statusEffect = string.Empty; projectile.m_healthReturn = 0f; projectile.m_hitNoise = 0f; projectile.m_spawnOnHit = null; projectile.m_spawnCount = 0; projectile.m_randomSpawnOnHit = new List(); projectile.m_randomSpawnOnHitCount = 0; projectile.m_spawnOnHitEffects = new EffectList(); projectile.m_respawnItemOnHit = false; projectile.m_showBreakMessage = false; projectile.m_bounce = false; projectile.m_maxBounces = 0; } private static void TintVisuals(GameObject prefab, Color color) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) ParticleSystem[] componentsInChildren = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { MainModule main = componentsInChildren[i].main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(color); } Light[] componentsInChildren2 = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].color = color; } } } internal sealed class PortalProjectileImpact : MonoBehaviour { private static readonly FieldInfo OwnerField = typeof(Projectile).GetField("m_owner", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo VelocityField = typeof(Projectile).GetField("m_vel", BindingFlags.Instance | BindingFlags.NonPublic); private Projectile projectile; private bool handledImpact; [SerializeField] internal PortalEndpointType EndpointType; private void Awake() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown projectile = ((Component)this).GetComponent(); if ((Object)(object)projectile == (Object)null) { Plugin.Log.LogError((object)(((Object)this).name + " has PortalProjectileImpact but no Projectile component.")); ((Behaviour)this).enabled = false; } else { Projectile obj = projectile; obj.m_onHit = (OnProjectileHit)Delegate.Combine((Delegate?)(object)obj.m_onHit, (Delegate?)new OnProjectileHit(HandleImpact)); } } private void OnDestroy() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown if ((Object)(object)projectile != (Object)null) { Projectile obj = projectile; obj.m_onHit = (OnProjectileHit)Delegate.Remove((Delegate?)(object)obj.m_onHit, (Delegate?)new OnProjectileHit(HandleImpact)); } } private void HandleImpact(Collider collider, Vector3 hitPoint, bool hitWater) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) if (!handledImpact) { handledImpact = true; Character val = ReadOwner(); Vector3 incomingVelocity = ReadVelocity(); Vector3 val2 = ResolveHitNormal(collider, hitPoint, incomingVelocity); GameObject val3 = (((Object)(object)collider == (Object)null) ? null : ((Component)collider).gameObject); Plugin.Log.LogInfo((object)("PORTAL_PROJECTILE_IMPACT type=" + EndpointType.ToString() + ", owner=" + DescribeOwner(val) + ", point=" + FormatVector(hitPoint) + ", normal=" + FormatVector(val2) + ", object=" + (((Object)(object)val3 == (Object)null) ? "" : ((Object)val3).name) + ", collider=" + (((Object)(object)collider == (Object)null) ? "" : ((object)collider).GetType().Name) + ", layer=" + (((Object)(object)val3 == (Object)null) ? (-1) : val3.layer) + ", water=" + hitWater + ".")); if (Plugin.Portals != null) { Plugin.Portals.TryPlace(val, EndpointType, hitPoint, val2, collider, hitWater); } } } private Character ReadOwner() { if (!(OwnerField == null) && !((Object)(object)projectile == (Object)null)) { object? value = OwnerField.GetValue(projectile); return (Character)((value is Character) ? value : null); } return null; } private Vector3 ReadVelocity() { //IL_0051: 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_003a: 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) if (VelocityField != null && (Object)(object)projectile != (Object)null && VelocityField.GetValue(projectile) is Vector3 result && ((Vector3)(ref result)).sqrMagnitude > 0.0001f) { return result; } return ((Component)this).transform.forward; } private static Vector3 ResolveHitNormal(Collider collider, Vector3 hitPoint, Vector3 incomingVelocity) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((((Vector3)(ref incomingVelocity)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref incomingVelocity)).normalized : Vector3.forward); if ((Object)(object)collider != (Object)null) { Ray val2 = default(Ray); ((Ray)(ref val2))..ctor(hitPoint - val * 0.5f, val); RaycastHit val3 = default(RaycastHit); if (collider.Raycast(val2, ref val3, 1f)) { return ((RaycastHit)(ref val3)).normal; } } return -val; } private static string DescribeOwner(Character owner) { if ((Object)(object)owner == (Object)null) { return ""; } Player val = (Player)(object)((owner is Player) ? owner : null); if ((Object)(object)val != (Object)null) { return "Player('" + val.GetPlayerName() + "')"; } return ((object)owner).GetType().Name + "('" + ((Object)owner).name + "')"; } private static string FormatVector(Vector3 value) { return "(" + value.x.ToString("0.###", CultureInfo.InvariantCulture) + "," + value.y.ToString("0.###", CultureInfo.InvariantCulture) + "," + value.z.ToString("0.###", CultureInfo.InvariantCulture) + ")"; } } internal sealed class PortalProjectileTraversal { private struct Crossing { internal PortalEndpoint Entrance; internal PortalEndpoint Exit; internal float Fraction; internal Vector3 LocalPoint; } private struct ExitSweep { internal PortalEndpoint Exit; internal float RayRadius; } private const float MinimumSpeed = 0.01f; private const float SurfaceSafety = 0.025f; private const float ExitSafety = 0.05f; private const float ExitWallRearDepth = 1.5f; private static readonly Quaternion PortalFrameTurn = Quaternion.Euler(0f, 180f, 0f); private static readonly FieldInfo VelocityField = typeof(Projectile).GetField("m_vel", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo RayRadiusField = typeof(Projectile).GetField("m_rayRadius", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo HaveStartPointField = typeof(Projectile).GetField("m_haveStartPoint", BindingFlags.Instance | BindingFlags.NonPublic); private readonly Dictionary activeExitSweeps = new Dictionary(); internal bool TryTraverse(Projectile projectile, PortalPair pair) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)projectile == (Object)null || pair == null || !pair.IsComplete || VelocityField == null || !HasNetworkAuthority(projectile)) { return false; } Vector3 velocity = projectile.GetVelocity(); if (((Vector3)(ref velocity)).sqrMagnitude < 0.0001f) { return false; } Vector3 step = velocity * Time.fixedDeltaTime; float rayRadius = ReadRayRadius(projectile); Crossing crossing; bool flag = TryFindCrossing(((Component)projectile).transform.position, step, rayRadius, pair.Standard, pair.Blue, out crossing); Crossing crossing2; bool flag2 = TryFindCrossing(((Component)projectile).transform.position, step, rayRadius, pair.Blue, pair.Standard, out crossing2); if (!flag && !flag2) { return false; } Crossing crossing3 = ((!(flag && flag2)) ? (flag ? crossing : crossing2) : ((crossing.Fraction <= crossing2.Fraction) ? crossing : crossing2)); Traverse(projectile, velocity, rayRadius, crossing3); return true; } internal bool ShouldSuppressExitWallHit(Projectile projectile, Collider collider, Vector3 hitPoint, bool water, Vector3 hitNormal) { //IL_0048: 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_004e: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)projectile == (Object)null || (Object)(object)collider == (Object)null || water || !activeExitSweeps.TryGetValue(((Object)projectile).GetInstanceID(), out var value) || (Object)(object)value.Exit == (Object)null) { return false; } Vector3 val = ((Component)value.Exit).transform.InverseTransformPoint(hitPoint); float num = Mathf.Min(value.Exit.Width, value.Exit.Height) * 0.5f - value.RayRadius; bool num2 = num > 0f && val.x * val.x + val.y * val.y <= num * num; bool flag = val.z >= -1.5f && val.z <= 0.075f; bool flag2 = (Object)(object)collider == (Object)(object)value.Exit.SourceCollider; bool flag3 = (Object)(object)collider.attachedRigidbody == (Object)null || collider.attachedRigidbody.isKinematic; if (!num2 || !flag || (!flag2 && !flag3)) { return false; } Plugin.Log.LogInfo((object)("PORTAL_PROJECTILE_EXIT_WALL_HIT_SUPPRESSED name=" + ((Object)projectile).name + ", exit=" + value.Exit.EndpointType.ToString() + ", collider=" + ((Object)collider).name + ", sourceCollider=" + flag2 + ", localHit=" + FormatVector(val) + ", hitNormal=" + FormatVector(hitNormal) + ".")); return true; } internal void FinishFixedUpdate(Projectile projectile) { if ((Object)(object)projectile != (Object)null) { activeExitSweeps.Remove(((Object)projectile).GetInstanceID()); } } private static bool TryFindCrossing(Vector3 position, Vector3 step, float rayRadius, PortalEndpoint entrance, PortalEndpoint exit, out Crossing crossing) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_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_004b: 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_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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) crossing = default(Crossing); if ((Object)(object)entrance == (Object)null || (Object)(object)exit == (Object)null) { return false; } Vector3 forward = ((Component)entrance).transform.forward; float num = rayRadius + 0.025f; float num2 = Vector3.Dot(position - ((Component)entrance).transform.position, forward) - num; float num3 = Vector3.Dot(step, forward); if (num2 < 0f || num3 >= -0.0001f) { return false; } float num4 = num2 + num3; if (num4 > 0f) { return false; } float num5 = Mathf.Clamp01(num2 / (num2 - num4)); Vector3 val = position + step * num5; Vector3 val2 = ((Component)entrance).transform.InverseTransformPoint(val - forward * num); float num6 = Mathf.Min(entrance.Width, entrance.Height) * 0.5f - rayRadius; if (num6 <= 0f || val2.x * val2.x + val2.y * val2.y > num6 * num6) { return false; } crossing.Entrance = entrance; crossing.Exit = exit; crossing.Fraction = num5; crossing.LocalPoint = new Vector3(val2.x, val2.y, 0f); return true; } private void Traverse(Projectile projectile, Vector3 velocity, float rayRadius, Crossing crossing) { //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_001d: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)projectile).transform; Quaternion val = ((Component)crossing.Exit).transform.rotation * PortalFrameTurn * Quaternion.Inverse(((Component)crossing.Entrance).transform.rotation); Vector3 val2 = PortalFrameTurn * crossing.LocalPoint; Quaternion val3 = val * transform.rotation; Vector3 val4 = val * velocity; Vector3 val5 = ((Component)crossing.Exit).transform.TransformPoint(val2) + ((Component)crossing.Exit).transform.forward * (rayRadius + 0.05f); Rigidbody component = ((Component)projectile).GetComponent(); if ((Object)(object)component != (Object)null && !component.isKinematic) { Vector3 val6 = transform.position - component.position; component.position = val5 - val * val6; component.rotation = val * component.rotation; component.linearVelocity = val * component.linearVelocity; component.angularVelocity = val * component.angularVelocity; } transform.SetPositionAndRotation(val5, val3); VelocityField.SetValue(projectile, val4); projectile.m_startPoint = val5; if (HaveStartPointField != null) { HaveStartPointField.SetValue(projectile, true); } activeExitSweeps[((Object)projectile).GetInstanceID()] = new ExitSweep { Exit = crossing.Exit, RayRadius = rayRadius }; ClearTrails(transform); Physics.SyncTransforms(); Plugin.Log.LogInfo((object)("PORTAL_PROJECTILE_TRAVERSED name=" + ((Object)projectile).name + ", entrance=" + crossing.Entrance.EndpointType.ToString() + ", exit=" + crossing.Exit.EndpointType.ToString() + ", speedBefore=" + FormatFloat(((Vector3)(ref velocity)).magnitude) + ", speedAfter=" + FormatFloat(((Vector3)(ref val4)).magnitude) + ", crossingFraction=" + FormatFloat(crossing.Fraction) + ", rayRadius=" + FormatFloat(rayRadius) + ", collisionOrigin=exactExit, rigidbody=" + (((Object)(object)component == (Object)null) ? "none" : (component.isKinematic ? "kinematic" : "dynamic")) + ".")); } private static bool HasNetworkAuthority(Projectile projectile) { ZNetView val = ((Component)projectile).GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)projectile).GetComponentInParent(); } if (!((Object)(object)val == (Object)null) && val.IsValid()) { return val.IsOwner(); } return true; } private static float ReadRayRadius(Projectile projectile) { if (RayRadiusField == null) { return 0f; } object value = RayRadiusField.GetValue(projectile); if (!(value is float)) { return 0f; } return Mathf.Max(0f, (float)value); } private static void ClearTrails(Transform root) { TrailRenderer[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (TrailRenderer val in componentsInChildren) { if ((Object)(object)val != (Object)null) { val.Clear(); } } } private static string FormatFloat(float value) { return value.ToString("0.###", CultureInfo.InvariantCulture); } private static string FormatVector(Vector3 value) { //IL_0010: 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_003c: Unknown result type (might be due to invalid IL or missing references) return "(" + FormatFloat(value.x) + "," + FormatFloat(value.y) + "," + FormatFloat(value.z) + ")"; } } } namespace DundrPortalGun.Portals { internal sealed class PortalEndpoint : MonoBehaviour { private GameObject visualRoot; internal long OwnerId { get; private set; } internal PortalEndpointType EndpointType { get; private set; } internal float Width { get; private set; } internal float Height { get; private set; } internal Collider SourceCollider { get; private set; } internal PortalViewSurface ViewSurface { get; private set; } internal Renderer[] VisualRenderers { get; private set; } internal Light[] VisualLights { get; private set; } internal void Initialize(long ownerId, PortalEndpointType endpointType, float width, float height, Collider sourceCollider, float viewDiameter, float viewEdgeFeatherFraction) { OwnerId = ownerId; EndpointType = endpointType; Width = width; Height = height; SourceCollider = sourceCollider; visualRoot = PortalVisualFactory.Create(((Component)this).transform, endpointType, width, height); VisualRenderers = (Renderer[])(((Object)(object)visualRoot == (Object)null) ? ((Array)new Renderer[0]) : ((Array)visualRoot.GetComponentsInChildren(true))); VisualLights = (Light[])(((Object)(object)visualRoot == (Object)null) ? ((Array)new Light[0]) : ((Array)visualRoot.GetComponentsInChildren(true))); ViewSurface = PortalViewSurface.Create(((Component)this).transform, Mathf.Min(viewDiameter, Mathf.Min(width, height)), viewEdgeFeatherFraction); } internal void SetLinked(bool linked) { if ((Object)(object)visualRoot != (Object)null && !visualRoot.activeSelf) { visualRoot.SetActive(true); } } internal bool TryIntersectAimRay(Ray ray, float maxDistance, out float distance) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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) distance = 0f; float num = Vector3.Dot(((Ray)(ref ray)).direction, ((Component)this).transform.forward); if (Mathf.Abs(num) < 0.0001f) { return false; } distance = Vector3.Dot(((Component)this).transform.position - ((Ray)(ref ray)).origin, ((Component)this).transform.forward) / num; if (distance < 0f || distance > maxDistance) { return false; } Vector3 val = ((Component)this).transform.InverseTransformPoint(((Ray)(ref ray)).GetPoint(distance)); float num2 = Mathf.Min(Width, Height) * 0.5f; return val.x * val.x + val.y * val.y <= num2 * num2; } } internal enum PortalEndpointType { Standard, Blue } internal sealed class PortalEntityTraversal { private enum EntityKind { None, DroppedItem, Mob } private sealed class EntityTraversalState { internal Rigidbody Body; internal PortalEndpoint BlockedExit; internal float CooldownUntil; internal int ReapplyTicks; internal Vector3 OutgoingVelocity; internal Vector3 OutgoingAngularVelocity; } private struct BodyShape { internal Vector3 Center; internal Vector3 Extents; internal Quaternion Orientation; internal Vector3 BodyToCenter; internal float GetExtent(Vector3 direction) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) Vector3 normalized = ((Vector3)(ref direction)).normalized; return Extents.x * Mathf.Abs(Vector3.Dot(Orientation * Vector3.right, normalized)) + Extents.y * Mathf.Abs(Vector3.Dot(Orientation * Vector3.up, normalized)) + Extents.z * Mathf.Abs(Vector3.Dot(Orientation * Vector3.forward, normalized)); } internal BodyShape Rotate(Quaternion rotation) { //IL_0009: 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_0015: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) BodyShape result = this; result.Orientation = rotation * Orientation; result.BodyToCenter = rotation * BodyToCenter; return result; } internal static bool TryCreate(Rigidbody body, out BodyShape shape) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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) //IL_0062: Unknown result type (might be due to invalid IL or missing references) shape = default(BodyShape); if ((Object)(object)body == (Object)null) { return false; } Collider[] componentsInChildren = ((Component)body).GetComponentsInChildren(true); bool flag = false; Bounds val = default(Bounds); Collider[] array = componentsInChildren; foreach (Collider val2 in array) { if (!((Object)(object)val2 == (Object)null) && val2.enabled && !val2.isTrigger && !((Object)(object)val2.attachedRigidbody != (Object)(object)body)) { if (!flag) { val = val2.bounds; flag = true; } else { ((Bounds)(ref val)).Encapsulate(val2.bounds); } } } if (!flag) { return false; } shape.Center = ((Bounds)(ref val)).center; shape.Extents = ((Bounds)(ref val)).extents; shape.Orientation = Quaternion.identity; shape.BodyToCenter = ((Bounds)(ref val)).center - body.position; return true; } } private const float ExitNudgeStep = 0.1f; private const float ApproachHalfDepth = 0.85f; private const float ApproachCenterDepth = 0.7f; private static readonly Quaternion PortalFrameTurn = Quaternion.Euler(0f, 180f, 0f); private static readonly Collider[] CandidateColliders = (Collider[])(object)new Collider[128]; private readonly ModConfig config; private readonly Dictionary states = new Dictionary(); private readonly List staleStateIds = new List(); private readonly HashSet examinedBodies = new HashSet(); private float nextBlockedLogTime; internal PortalEntityTraversal(ModConfig config) { this.config = config; } internal void FixedTick(IEnumerable pairs) { UpdateStates(); if (pairs == null || (!config.TransportDroppedItems.Value && !config.TransportMobs.Value)) { return; } examinedBodies.Clear(); foreach (PortalPair pair in pairs) { if (pair != null && pair.IsComplete) { ScanEndpoint(pair.Standard, pair.Blue); ScanEndpoint(pair.Blue, pair.Standard); } } } internal void Reset() { states.Clear(); staleStateIds.Clear(); examinedBodies.Clear(); nextBlockedLogTime = 0f; } private void ScanEndpoint(PortalEndpoint entrance, PortalEndpoint exit) { //IL_005f: 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_0074: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)entrance == (Object)null || (Object)(object)exit == (Object)null) { return; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(entrance.Width * 0.5f + config.EntryApertureMargin.Value, entrance.Height * 0.5f + config.EntryApertureMargin.Value, 0.85f); int num = Physics.OverlapBoxNonAlloc(((Component)entrance).transform.position + ((Component)entrance).transform.forward * 0.7f, val, CandidateColliders, ((Component)entrance).transform.rotation, -5, (QueryTriggerInteraction)1); for (int i = 0; i < num; i++) { Collider val2 = CandidateColliders[i]; CandidateColliders[i] = null; Rigidbody val3 = (((Object)(object)val2 == (Object)null) ? null : val2.attachedRigidbody); if (!((Object)(object)val3 == (Object)null) && !val3.isKinematic) { int instanceID = ((Object)val3).GetInstanceID(); if (examinedBodies.Add(instanceID) && !states.ContainsKey(instanceID) && TryClassify(val3, out var character, out var kind) && HasNetworkAuthority(val3) && BodyShape.TryCreate(val3, out var shape) && IsEntryCandidate(val3, shape, entrance)) { TryTraverse(val3, character, kind, shape, entrance, exit); } } } } private bool TryClassify(Rigidbody body, out Character character, out EntityKind kind) { character = ((Component)body).GetComponent(); if ((Object)(object)character == (Object)null) { character = ((Component)body).GetComponentInParent(); } if ((Object)(object)character != (Object)null) { if (!config.TransportMobs.Value || character is Player || character.IsDead() || character.IsTeleporting() || (Object)(object)((Component)character).GetComponent() != (Object)(object)body) { kind = EntityKind.None; return false; } kind = EntityKind.Mob; return true; } if (!config.TransportDroppedItems.Value || (Object)(object)((Component)body).GetComponent() != (Object)null || (Object)(object)((Component)body).GetComponentInParent() != (Object)null || (Object)(object)((Component)body).GetComponentInParent() != (Object)null || (Object)(object)((Component)body).GetComponentInParent() != (Object)null) { kind = EntityKind.None; return false; } ItemDrop val = ((Component)body).GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)body).GetComponentInParent(); } if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).GetComponent() != (Object)(object)body) { kind = EntityKind.None; return false; } kind = EntityKind.DroppedItem; return true; } private static bool HasNetworkAuthority(Rigidbody body) { ZNetView val = ((Component)body).GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)body).GetComponentInParent(); } if (!((Object)(object)val == (Object)null) && val.IsValid()) { return val.IsOwner(); } return true; } private bool IsEntryCandidate(Rigidbody body, BodyShape shape, PortalEndpoint entrance) { //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_000d: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) Vector3 forward = ((Component)entrance).transform.forward; float num = Vector3.Dot(shape.Center - ((Component)entrance).transform.position, forward); float num2 = 0f - Vector3.Dot(body.linearVelocity, forward); if (num2 < config.MinimumEntrySpeed.Value || num < -0.05f) { return false; } float extent = shape.GetExtent(forward); float num3 = num - num2 * Time.fixedDeltaTime; float num4 = extent + config.EntrySkin.Value; if (num > num4 && num3 > num4) { return false; } Vector3 val = ((Component)entrance).transform.InverseTransformPoint(shape.Center); float value = config.EntryApertureMargin.Value; float num5 = Mathf.Min(entrance.Width, entrance.Height) * 0.5f + value; return val.x * val.x + val.y * val.y <= num5 * num5; } private void TryTraverse(Rigidbody body, Character character, EntityKind kind, BodyShape shape, PortalEndpoint entrance, PortalEndpoint exit) { //IL_0007: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: 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) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) Quaternion val = ((Component)exit).transform.rotation * PortalFrameTurn * Quaternion.Inverse(((Component)entrance).transform.rotation); Quaternion rotation = body.rotation; Quaternion val2 = ((kind == EntityKind.Mob) ? GetUprightMobRotation(character, val, rotation) : (val * rotation)); Quaternion val3 = val2 * Quaternion.Inverse(rotation); BodyShape targetShape = shape.Rotate(val3); Vector3 val4 = ((Component)entrance).transform.InverseTransformPoint(shape.Center); Vector3 val5 = PortalFrameTurn * new Vector3(val4.x, val4.y, 0f); float num = exit.Width * 0.5f - targetShape.GetExtent(((Component)exit).transform.right); float num2 = exit.Height * 0.5f - targetShape.GetExtent(((Component)exit).transform.up); if (num < 0f || num2 < 0f) { LogRejected(body, kind, entrance, exit, "the body does not fit through the exit aperture"); return; } val5.x = Mathf.Clamp(val5.x, 0f - num, num); val5.y = Mathf.Clamp(val5.y, 0f - num2, num2); Vector3 exitPlaneCenter = ((Component)exit).transform.TransformPoint(val5); if (!TryFindClearExit(body, targetShape, exit, exitPlaneCenter, config.ExitMargin.Value, config.ExitNudgeLimit.Value, out var targetCenter, out var usedNudge, out var usedApertureScale)) { LogRejected(body, kind, entrance, exit, "no collision-free exit volume was found"); return; } Vector3 linearVelocity = body.linearVelocity; Vector3 angularVelocity = body.angularVelocity; Vector3 val6 = val * linearVelocity; Vector3 val7 = val * angularVelocity; Vector3 val8 = val3 * shape.BodyToCenter; Vector3 position = targetCenter - val8; body.position = position; body.rotation = val2; if ((Object)(object)character != (Object)null) { character.SetLookDir(val2 * Vector3.forward, 0f); } Physics.SyncTransforms(); body.linearVelocity = val6; body.angularVelocity = val7; body.WakeUp(); EntityTraversalState value = new EntityTraversalState { Body = body, BlockedExit = exit, CooldownUntil = Time.fixedTime + config.ReentryCooldown.Value, ReapplyTicks = 1, OutgoingVelocity = val6, OutgoingAngularVelocity = val7 }; states[((Object)body).GetInstanceID()] = value; Plugin.Log.LogInfo((object)("PORTAL_ENTITY_TRAVERSED kind=" + kind.ToString() + ", name=" + ((Object)body).name + ", entrance=" + entrance.EndpointType.ToString() + ", exit=" + exit.EndpointType.ToString() + ", speedBefore=" + FormatFloat(((Vector3)(ref linearVelocity)).magnitude) + ", speedAfter=" + FormatFloat(((Vector3)(ref val6)).magnitude) + ", exitNudge=" + FormatFloat(usedNudge) + ", exitApertureScale=" + FormatFloat(usedApertureScale) + ".")); } private static Quaternion GetUprightMobRotation(Character character, Quaternion frameRotation, Quaternion fallback) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (((Object)(object)character == (Object)null) ? (fallback * Vector3.forward) : character.GetLookDir()); Vector3 val2 = frameRotation * val; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f) { return fallback; } return Quaternion.LookRotation(((Vector3)(ref val2)).normalized, Vector3.up); } private static bool TryFindClearExit(Rigidbody body, BodyShape targetShape, PortalEndpoint exit, Vector3 exitPlaneCenter, float exitMargin, float nudgeLimit, out Vector3 targetCenter, out float usedNudge, out float usedApertureScale) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_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_001a: 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_004e: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = exitPlaneCenter - ((Component)exit).transform.position; float extent = targetShape.GetExtent(((Component)exit).transform.forward); float[] array = new float[5] { 1f, 0.75f, 0.5f, 0.25f, 0f }; foreach (float num in array) { Vector3 val2 = ((Component)exit).transform.position + val * num; for (float num2 = 0f; num2 <= nudgeLimit + 0.001f; num2 += 0.1f) { targetCenter = val2 + ((Component)exit).transform.forward * (extent + exitMargin + num2); if (IsVolumeClear(body, targetShape, targetCenter)) { usedNudge = num2; usedApertureScale = num; return true; } } } targetCenter = Vector3.zero; usedNudge = 0f; usedApertureScale = 0f; return false; } private static bool IsVolumeClear(Rigidbody body, BodyShape shape, Vector3 center) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0059: 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) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Mathf.Max(0.01f, shape.Extents.x - 0.02f), Mathf.Max(0.01f, shape.Extents.y - 0.02f), Mathf.Max(0.01f, shape.Extents.z - 0.02f)); Collider[] array = Physics.OverlapBox(center, val, shape.Orientation, -5, (QueryTriggerInteraction)1); foreach (Collider val2 in array) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.attachedRigidbody == (Object)(object)body) && !IsChildOf(((Component)val2).transform, ((Component)body).transform)) { return false; } } return true; } private void UpdateStates() { //IL_005e: 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) staleStateIds.Clear(); foreach (KeyValuePair state in states) { EntityTraversalState value = state.Value; if ((Object)(object)value.Body == (Object)null) { staleStateIds.Add(state.Key); continue; } if (value.ReapplyTicks > 0) { value.Body.linearVelocity = value.OutgoingVelocity; value.Body.angularVelocity = value.OutgoingAngularVelocity; value.ReapplyTicks--; } if (Time.fixedTime >= value.CooldownUntil && HasClearedExit(value.Body, value.BlockedExit)) { staleStateIds.Add(state.Key); } } foreach (int staleStateId in staleStateIds) { states.Remove(staleStateId); } } private bool HasClearedExit(Rigidbody body, PortalEndpoint exit) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)body == (Object)null || (Object)(object)exit == (Object)null) { return true; } if (!BodyShape.TryCreate(body, out var shape)) { return true; } if (Vector3.Dot(shape.Center - ((Component)exit).transform.position, ((Component)exit).transform.forward) > shape.GetExtent(((Component)exit).transform.forward) + config.RearmDistance.Value) { return true; } Vector3 val = ((Component)exit).transform.InverseTransformPoint(shape.Center); if (!(Mathf.Abs(val.x) > exit.Width * 0.5f + shape.GetExtent(((Component)exit).transform.right))) { return Mathf.Abs(val.y) > exit.Height * 0.5f + shape.GetExtent(((Component)exit).transform.up); } return true; } private static bool IsChildOf(Transform child, Transform parent) { while ((Object)(object)child != (Object)null) { if ((Object)(object)child == (Object)(object)parent) { return true; } child = child.parent; } return false; } private void LogRejected(Rigidbody body, EntityKind kind, PortalEndpoint entrance, PortalEndpoint exit, string reason) { if (!(Time.fixedTime < nextBlockedLogTime)) { nextBlockedLogTime = Time.fixedTime + 0.75f; Plugin.Log.LogInfo((object)("PORTAL_ENTITY_BLOCKED kind=" + kind.ToString() + ", name=" + (((Object)(object)body == (Object)null) ? "" : ((Object)body).name) + ", entrance=" + entrance.EndpointType.ToString() + ", exit=" + exit.EndpointType.ToString() + ", reason=" + reason + ".")); } } private static string FormatFloat(float value) { return value.ToString("0.###", CultureInfo.InvariantCulture); } } internal sealed class PortalManager { private readonly ModConfig config; private readonly PortalEntityTraversal entityTraversal; private readonly PortalProjectileTraversal projectileTraversal; private readonly PortalViewSystem viewSystem; private readonly Dictionary pairs = new Dictionary(); private bool hadLocalPlayer; private PortalEndpoint blockedExit; private bool exitRegionCleared; private float traversalCooldownUntil; private float nextBlockedLogTime; private bool hasPreviousCenter; private Vector3 previousCenter; private Player fallDamageGracePlayer; private float fallDamageGraceUntil; internal PortalManager(ModConfig config) { this.config = config; entityTraversal = new PortalEntityTraversal(config); projectileTraversal = new PortalProjectileTraversal(); viewSystem = new PortalViewSystem(config); } internal void LateTick(Player localPlayer, Camera viewer) { viewSystem.LateTick(pairs.Values, viewer); } internal void Tick(Player localPlayer) { if ((Object)(object)localPlayer == (Object)null) { if (hadLocalPlayer) { ClearAll("local player left the world"); hadLocalPlayer = false; } } else { hadLocalPlayer = true; HandleDeleteInput(localPlayer); } } internal void FixedTick(Player localPlayer) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: 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_00f9: 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_0108: 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_011a: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) if (!config.TraversalEnabled.Value) { hasPreviousCenter = false; return; } entityTraversal.FixedTick(pairs.Values); if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting()) { hasPreviousCenter = false; return; } if ((Object)(object)blockedExit != (Object)null && !exitRegionCleared) { exitRegionCleared = PortalTraversal.HasClearedExit(localPlayer, blockedExit, config); } if ((Object)(object)blockedExit == (Object)null) { exitRegionCleared = true; } if (Time.fixedTime < traversalCooldownUntil || !exitRegionCleared) { RememberCenter(localPlayer); return; } blockedExit = null; Rigidbody component = ((Component)localPlayer).GetComponent(); if ((Object)(object)component == (Object)null) { hasPreviousCenter = false; return; } Vector3 centerPoint = ((Character)localPlayer).GetCenterPoint(); Vector3 observedVelocity = component.linearVelocity; if (hasPreviousCenter && Time.fixedDeltaTime > 0f) { Vector3 val = (centerPoint - previousCenter) / Time.fixedDeltaTime; if (((Vector3)(ref val)).sqrMagnitude > ((Vector3)(ref observedVelocity)).sqrMagnitude) { observedVelocity = val; } } foreach (PortalPair value in pairs.Values) { if (value != null && value.IsComplete && (TryTraverseFrom(localPlayer, value, value.Standard, observedVelocity) || TryTraverseFrom(localPlayer, value, value.Blue, observedVelocity))) { previousCenter = ((Character)localPlayer).GetCenterPoint(); hasPreviousCenter = true; return; } } previousCenter = centerPoint; hasPreviousCenter = true; } internal void TryTraverseProjectile(Projectile projectile) { if (!config.TraversalEnabled.Value || !config.TransportProjectiles.Value || (Object)(object)projectile == (Object)null) { return; } foreach (PortalPair value in pairs.Values) { if (value != null && value.IsComplete && projectileTraversal.TryTraverse(projectile, value)) { break; } } } internal bool ShouldSuppressProjectileExitWallHit(Projectile projectile, Collider collider, Vector3 hitPoint, bool water, Vector3 hitNormal) { //IL_0008: 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) return projectileTraversal.ShouldSuppressExitWallHit(projectile, collider, hitPoint, water, hitNormal); } internal void FinishProjectileFixedUpdate(Projectile projectile) { projectileTraversal.FinishFixedUpdate(projectile); } internal bool IsFallDamageGraceActive(Player player) { if (!config.FallDamageGraceEnabled.Value || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)fallDamageGracePlayer || Time.time >= fallDamageGraceUntil) { if ((Object)(object)player == (Object)(object)fallDamageGracePlayer && Time.time >= fallDamageGraceUntil) { fallDamageGracePlayer = null; fallDamageGraceUntil = 0f; } return false; } return true; } internal void TryPlace(Character ownerCharacter, PortalEndpointType endpointType, Vector3 hitPoint, Vector3 hitNormal, Collider hitCollider, bool hitWater) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) Player val = (Player)(object)((ownerCharacter is Player) ? ownerCharacter : null); if (!PortalPlacement.TryResolve(val, hitPoint, hitNormal, hitCollider, hitWater, config, out var position, out var rotation, out var rejection)) { Plugin.Log.LogInfo((object)("PORTAL_PLACEMENT_REJECTED type=" + endpointType.ToString() + ", reason=" + rejection + ".")); } else { string targetPrefab = PortalPlacement.ResolveTargetPrefabName(hitCollider); if (Plugin.Network != null) { Plugin.Network.RequestPlacement(val, endpointType, position, rotation, targetPrefab); } else { ApplyReplicatedPlacement(val.GetPlayerID(), val.GetPlayerName(), endpointType, position, rotation, config.ApertureWidth.Value, config.ApertureHeight.Value, targetPrefab, hitCollider); } } } internal void ApplyReplicatedPlacement(long ownerId, string ownerName, PortalEndpointType endpointType, Vector3 position, Quaternion rotation, float width, float height, string targetPrefab, Collider sourceCollider = null) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) if (!pairs.TryGetValue(ownerId, out var value)) { value = new PortalPair(); pairs.Add(ownerId, value); } PortalEndpoint portalEndpoint = value.Get(endpointType); if ((Object)(object)portalEndpoint != (Object)null) { Object.Destroy((Object)(object)((Component)portalEndpoint).gameObject); } GameObject val = new GameObject("DundrPortalGun_" + endpointType.ToString() + "Endpoint"); ((Object)val).hideFlags = (HideFlags)52; val.transform.SetPositionAndRotation(position, rotation); PortalEndpoint portalEndpoint2 = val.AddComponent(); portalEndpoint2.Initialize(ownerId, endpointType, width, height, sourceCollider, config.PortalViewDiameter.Value, config.PortalViewEdgeFeatherFraction.Value); value.Set(endpointType, portalEndpoint2); value.RefreshLinkedState(); Plugin.Log.LogInfo((object)("PORTAL_PLACED type=" + endpointType.ToString() + ", owner=" + ownerName + ", ownerId=" + ownerId + ", position=" + FormatVector(position) + ", forward=" + FormatVector(val.transform.forward) + ", up=" + FormatVector(val.transform.up) + ", targetPrefab=" + targetPrefab + ", replaced=" + ((Object)(object)portalEndpoint != (Object)null) + ", pairComplete=" + value.IsComplete + ".")); } internal void ApplyReplicatedDeletion(long ownerId, PortalEndpointType endpointType, string ownerName) { if (!pairs.TryGetValue(ownerId, out var value)) { return; } PortalEndpoint portalEndpoint = value.Get(endpointType); if (!((Object)(object)portalEndpoint == (Object)null)) { value.Remove(portalEndpoint); Object.Destroy((Object)(object)((Component)portalEndpoint).gameObject); value.RefreshLinkedState(); bool isComplete = value.IsComplete; if ((Object)(object)value.Standard == (Object)null && (Object)(object)value.Blue == (Object)null) { pairs.Remove(ownerId); } Plugin.Log.LogInfo((object)("PORTAL_DELETED type=" + endpointType.ToString() + ", owner=" + ownerName + ", ownerId=" + ownerId + ", pairComplete=" + isComplete + ".")); } } internal void ClearAll(string reason) { int num = 0; foreach (PortalPair value in pairs.Values) { num += DestroyIfPresent(value.Standard); num += DestroyIfPresent(value.Blue); } pairs.Clear(); entityTraversal.Reset(); viewSystem.Reset(); ResetTraversalState(); if (num > 0) { Plugin.Log.LogInfo((object)("Removed " + num + " portal endpoint(s): " + reason + ".")); } } private bool TryTraverseFrom(Player player, PortalPair pair, PortalEndpoint entrance, Vector3 observedVelocity) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)entrance == (Object)null || !PortalTraversal.IsEntryCandidate(player, entrance, observedVelocity, config, out var planeDistance)) { return false; } PortalEndpoint other = pair.GetOther(entrance); if (!PortalTraversal.TryTraverse(player, entrance, other, config, out var rejection)) { if (Time.fixedTime >= nextBlockedLogTime) { nextBlockedLogTime = Time.fixedTime + 0.75f; Plugin.Log.LogWarning((object)("PORTAL_TRAVERSAL_BLOCKED entrance=" + entrance.EndpointType.ToString() + ", exit=" + other.EndpointType.ToString() + ", planeDistance=" + planeDistance.ToString("0.###", CultureInfo.InvariantCulture) + ", reason=" + rejection + ".")); } return false; } blockedExit = other; exitRegionCleared = false; traversalCooldownUntil = Time.fixedTime + config.ReentryCooldown.Value; BeginFallDamageGrace(player); return true; } private void BeginFallDamageGrace(Player player) { float value = config.FallDamageGraceSeconds.Value; if (config.FallDamageGraceEnabled.Value && !((Object)(object)player == (Object)null) && !(value <= 0f)) { fallDamageGracePlayer = player; fallDamageGraceUntil = Time.time + value; Plugin.Log.LogInfo((object)("PORTAL_FALL_GRACE started duration=" + value.ToString("0.###", CultureInfo.InvariantCulture) + "s.")); } } private void RememberCenter(Player player) { //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) if ((Object)(object)player == (Object)null) { hasPreviousCenter = false; return; } previousCenter = ((Character)player).GetCenterPoint(); hasPreviousCenter = true; } private void ResetTraversalState() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) blockedExit = null; exitRegionCleared = false; traversalCooldownUntil = 0f; nextBlockedLogTime = 0f; hasPreviousCenter = false; previousCenter = Vector3.zero; fallDamageGracePlayer = null; fallDamageGraceUntil = 0f; } private void HandleDeleteInput(Player player) { //IL_005f: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) if (!Input.GetMouseButtonDown(2) || !PortalGunInput.CanUsePortalGun(player)) { return; } long playerID = player.GetPlayerID(); if (!pairs.TryGetValue(playerID, out var value)) { Plugin.Log.LogInfo((object)"PORTAL_DELETE no owned endpoints exist."); return; } Camera main = Camera.main; if ((Object)(object)main == (Object)null) { Plugin.Log.LogWarning((object)"PORTAL_DELETE failed because Camera.main is null."); return; } Ray ray = default(Ray); ((Ray)(ref ray))..ctor(((Component)main).transform.position, ((Component)main).transform.forward); PortalEndpoint aimed = null; float aimedDistance = float.MaxValue; TrySelect(value.Standard, ray, ref aimed, ref aimedDistance); TrySelect(value.Blue, ray, ref aimed, ref aimedDistance); if ((Object)(object)aimed == (Object)null) { Plugin.Log.LogInfo((object)"PORTAL_DELETE no owned endpoint was under the crosshair."); return; } PortalEndpointType endpointType = aimed.EndpointType; if (Plugin.Network != null) { Plugin.Network.RequestDeletion(player, endpointType); } else { ApplyReplicatedDeletion(playerID, endpointType, player.GetPlayerName()); } } private void TrySelect(PortalEndpoint endpoint, Ray ray, ref PortalEndpoint aimed, ref float aimedDistance) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)endpoint == (Object)null) && endpoint.TryIntersectAimRay(ray, config.DeleteAimDistance.Value, out var distance) && distance < aimedDistance) { aimed = endpoint; aimedDistance = distance; } } private static int DestroyIfPresent(PortalEndpoint endpoint) { if ((Object)(object)endpoint == (Object)null) { return 0; } Object.Destroy((Object)(object)((Component)endpoint).gameObject); return 1; } private static string FormatVector(Vector3 value) { return "(" + value.x.ToString("0.###", CultureInfo.InvariantCulture) + "," + value.y.ToString("0.###", CultureInfo.InvariantCulture) + "," + value.z.ToString("0.###", CultureInfo.InvariantCulture) + ")"; } } internal sealed class PortalPair { internal PortalEndpoint Standard { get; set; } internal PortalEndpoint Blue { get; set; } internal bool IsComplete { get { if ((Object)(object)Standard != (Object)null) { return (Object)(object)Blue != (Object)null; } return false; } } internal PortalEndpoint Get(PortalEndpointType endpointType) { if (endpointType != PortalEndpointType.Standard) { return Blue; } return Standard; } internal PortalEndpoint GetOther(PortalEndpoint endpoint) { if (!((Object)(object)endpoint == (Object)(object)Standard)) { return Standard; } return Blue; } internal void Set(PortalEndpointType endpointType, PortalEndpoint endpoint) { if (endpointType == PortalEndpointType.Standard) { Standard = endpoint; } else { Blue = endpoint; } } internal void Remove(PortalEndpoint endpoint) { if ((Object)(object)Standard == (Object)(object)endpoint) { Standard = null; } if ((Object)(object)Blue == (Object)(object)endpoint) { Blue = null; } } internal void RefreshLinkedState() { bool isComplete = IsComplete; if ((Object)(object)Standard != (Object)null) { Standard.SetLinked(isComplete); } if ((Object)(object)Blue != (Object)null) { Blue.SetLinked(isComplete); } } } internal static class PortalPlacement { internal static bool TryResolve(Player owner, Vector3 hitPoint, Vector3 hitNormal, Collider hitCollider, bool hitWater, ModConfig config, out Vector3 position, out Quaternion rotation, out string rejection) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; rotation = Quaternion.identity; rejection = null; if ((Object)(object)owner == (Object)null || (Object)(object)owner != (Object)(object)Player.m_localPlayer) { rejection = "the projectile is not owned by the local player"; return false; } if (hitWater) { rejection = "water is not a valid portal surface"; return false; } if (!IsFinite(hitPoint) || !IsFinite(hitNormal) || ((Vector3)(ref hitNormal)).sqrMagnitude < 0.5f) { rejection = "the impact point or normal is invalid"; return false; } if (!IsSupportedCollider(hitCollider, out var rejection2)) { rejection = rejection2; return false; } string text = ResolveTargetPrefabName(hitCollider); if (config.EffectiveRestrictPlacementByPrefab && !IsAllowedPrefab(text, config.EffectiveAllowedPlacementPrefabs)) { rejection = "target prefab '" + text + "' is not in Portal Placement/Allowed Placement Prefabs"; return false; } Vector3 normalized = ((Vector3)(ref hitNormal)).normalized; rotation = CalculateRotation(owner, normalized); position = hitPoint + normalized * config.SurfaceOffset.Value; rejection = null; return true; } internal static bool IsAllowedTargetPrefab(string targetPrefabName, bool restrictPlacement, string configuredPrefabs) { if (restrictPlacement) { return IsAllowedPrefab(targetPrefabName, configuredPrefabs); } return true; } internal static bool TryResolveNetworkTargetPrefab(Vector3 endpointPosition, Vector3 outwardNormal, out string targetPrefabName) { //IL_0003: 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_0025: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) targetPrefabName = null; if (!IsFinite(endpointPosition) || !IsFinite(outwardNormal) || ((Vector3)(ref outwardNormal)).sqrMagnitude < 0.5f) { return false; } Vector3 normalized = ((Vector3)(ref outwardNormal)).normalized; RaycastHit[] array = Physics.RaycastAll(endpointPosition + normalized * 0.5f, -normalized, 1.25f, -5, (QueryTriggerInteraction)1); Array.Sort(array, (RaycastHit left, RaycastHit right) => ((RaycastHit)(ref left)).distance.CompareTo(((RaycastHit)(ref right)).distance)); RaycastHit[] array2 = array; for (int num = 0; num < array2.Length; num++) { RaycastHit val = array2[num]; if (IsSupportedCollider(((RaycastHit)(ref val)).collider, out var _)) { targetPrefabName = ResolveTargetPrefabName(((RaycastHit)(ref val)).collider); return true; } } return false; } internal static string ResolveTargetPrefabName(Collider collider) { if ((Object)(object)collider == (Object)null) { return ""; } Piece componentInParent = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { return NormalizePrefabName(((Object)((Component)componentInParent).gameObject).name); } ZNetView componentInParent2 = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent2 != (Object)null) { return NormalizePrefabName(((Object)((Component)componentInParent2).gameObject).name); } Character componentInParent3 = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent3 != (Object)null) { return NormalizePrefabName(((Object)((Component)componentInParent3).gameObject).name); } Rigidbody attachedRigidbody = collider.attachedRigidbody; if ((Object)(object)attachedRigidbody != (Object)null) { return NormalizePrefabName(((Object)((Component)attachedRigidbody).gameObject).name); } Transform root = ((Component)collider).transform.root; return NormalizePrefabName(((Object)(object)root == (Object)null) ? ((Object)((Component)collider).gameObject).name : ((Object)((Component)root).gameObject).name); } private static bool IsAllowedPrefab(string targetPrefabName, string configuredPrefabs) { HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); string[] array = (configuredPrefabs ?? string.Empty).Split(new char[4] { ',', ';', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = NormalizePrefabName(array[i]); if (text == "*") { return true; } if (!string.IsNullOrEmpty(text)) { hashSet.Add(text); } } return hashSet.Contains(NormalizePrefabName(targetPrefabName)); } private static string NormalizePrefabName(string name) { string text = (name ?? string.Empty).Trim(); while (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "(Clone)".Length).TrimEnd(Array.Empty()); } return text; } private static Quaternion CalculateRotation(Player owner, Vector3 forward) { //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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.ProjectOnPlane(Vector3.up, forward); if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { Camera main = Camera.main; val = Vector3.ProjectOnPlane(((Object)(object)main == (Object)null) ? ((Component)owner).transform.forward : ((Component)main).transform.up, forward); } if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Vector3.ProjectOnPlane(((Component)owner).transform.forward, forward); } if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Vector3.ProjectOnPlane(Vector3.forward, forward); } if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Vector3.ProjectOnPlane(Vector3.right, forward); } return Quaternion.LookRotation(forward, ((Vector3)(ref val)).normalized); } private static bool IsSupportedCollider(Collider collider, out string rejection) { if ((Object)(object)collider == (Object)null || !collider.enabled || collider.isTrigger) { rejection = "the hit collider is missing, disabled, or a trigger"; return false; } if ((Object)(object)((Component)collider).GetComponentInParent() != (Object)null) { rejection = "portal endpoints are not valid portal surfaces"; return false; } rejection = null; return true; } private static bool IsFinite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (IsFinite(value.x) && IsFinite(value.y)) { return IsFinite(value.z); } return false; } private static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } } internal static class PortalTraversal { private struct PlayerCapsule { internal Rigidbody Body; internal Vector3 Center; internal Vector3 Axis; internal float Radius; internal float HalfSegment; internal Vector3 BodyToCenter; internal float GetExtent(Vector3 direction) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) return Radius + HalfSegment * Mathf.Abs(Vector3.Dot(Axis, ((Vector3)(ref direction)).normalized)); } internal static bool TryCreate(Player player, out PlayerCapsule capsule) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_007b: 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_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) capsule = default(PlayerCapsule); if ((Object)(object)player == (Object)null) { return false; } CapsuleCollider collider = ((Character)player).GetCollider(); Rigidbody component = ((Component)player).GetComponent(); if ((Object)(object)collider == (Object)null || (Object)(object)component == (Object)null || !((Collider)collider).enabled) { return false; } Vector3 lossyScale = ((Component)collider).transform.lossyScale; Vector3 val; float num; float num2; switch (collider.direction) { case 0: val = Vector3.right; num = Mathf.Abs(lossyScale.x); num2 = Mathf.Max(Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z)); break; case 2: val = Vector3.forward; num = Mathf.Abs(lossyScale.z); num2 = Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y)); break; default: val = Vector3.up; num = Mathf.Abs(lossyScale.y); num2 = Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.z)); break; } float num3 = collider.radius * num2; float num4 = Mathf.Max(collider.height * num, num3 * 2f); Vector3 val2 = ((Component)collider).transform.TransformPoint(collider.center); capsule.Body = component; capsule.Center = val2; Vector3 val3 = ((Component)collider).transform.TransformDirection(val); capsule.Axis = ((Vector3)(ref val3)).normalized; capsule.Radius = num3; capsule.HalfSegment = Mathf.Max(0f, num4 * 0.5f - num3); capsule.BodyToCenter = val2 - component.position; return true; } } private const float ExitNudgeStep = 0.1f; private static readonly Quaternion PortalFrameTurn = Quaternion.Euler(0f, 180f, 0f); internal static bool IsEntryCandidate(Player player, PortalEndpoint endpoint, Vector3 observedVelocity, ModConfig config, out float planeDistance) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) planeDistance = 0f; if (!PlayerCapsule.TryCreate(player, out var capsule)) { return false; } Vector3 forward = ((Component)endpoint).transform.forward; planeDistance = Vector3.Dot(capsule.Center - ((Component)endpoint).transform.position, forward); float num = 0f - Vector3.Dot(observedVelocity, forward); if (num < config.MinimumEntrySpeed.Value || planeDistance < -0.05f) { return false; } float extent = capsule.GetExtent(forward); float num2 = planeDistance - num * Time.fixedDeltaTime; float num3 = extent + config.EntrySkin.Value; if (planeDistance > num3 && num2 > num3) { return false; } return FitsAperture(capsule, endpoint, capsule.Center, config.EntryApertureMargin.Value); } internal static bool HasClearedExit(Player player, PortalEndpoint endpoint, ModConfig config) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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) if ((Object)(object)endpoint == (Object)null) { return true; } if (!PlayerCapsule.TryCreate(player, out var capsule)) { return true; } float num = Vector3.Dot(capsule.Center - ((Component)endpoint).transform.position, ((Component)endpoint).transform.forward); float num2 = capsule.GetExtent(((Component)endpoint).transform.forward) + config.RearmDistance.Value; if (num > num2) { return true; } Vector3 val = ((Component)endpoint).transform.InverseTransformPoint(capsule.Center); float num3 = capsule.Radius + 0.2f; if (!(Mathf.Abs(val.x) > endpoint.Width * 0.5f + num3)) { return Mathf.Abs(val.y) > endpoint.Height * 0.5f + num3; } return true; } internal static bool TryTraverse(Player player, PortalEndpoint entrance, PortalEndpoint exit, ModConfig config, out string rejection) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0180: 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_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) rejection = null; if (!PlayerCapsule.TryCreate(player, out var capsule)) { rejection = "the local player capsule or Rigidbody is unavailable"; return false; } Vector3 val = ((Component)entrance).transform.InverseTransformPoint(capsule.Center); Vector3 val2 = PortalFrameTurn * new Vector3(val.x, val.y, 0f); float extent = capsule.GetExtent(((Component)exit).transform.right); float extent2 = capsule.GetExtent(((Component)exit).transform.up); float num = exit.Width * 0.5f - extent; float num2 = exit.Height * 0.5f - extent2; if (num < 0f || num2 < 0f) { rejection = "the player capsule does not fit through the exit aperture"; return false; } val2.x = Mathf.Clamp(val2.x, 0f - num, num); val2.y = Mathf.Clamp(val2.y, 0f - num2, num2); Vector3 exitPlaneCenter = ((Component)exit).transform.TransformPoint(val2); float extent3 = capsule.GetExtent(((Component)exit).transform.forward); if (!TryFindClearExit(player, capsule, exit, exitPlaneCenter, extent3, config, out var targetCenter, out var usedNudge, out var usedApertureScale)) { rejection = "no collision-free exit capsule was found within the configured nudge limit"; return false; } Rigidbody body = capsule.Body; Vector3 position = body.position; Vector3 position2 = ((Component)player).transform.position; Vector3 linearVelocity = body.linearVelocity; Vector3 lookDir = ((Character)player).GetLookDir(); Vector3 val3 = ((Component)exit).transform.TransformDirection(PortalFrameTurn * ((Component)entrance).transform.InverseTransformDirection(linearVelocity)); Vector3 val4 = ((Component)exit).transform.TransformDirection(PortalFrameTurn * ((Component)entrance).transform.InverseTransformDirection(lookDir)); Vector3 val5 = targetCenter - capsule.BodyToCenter; Vector3 val6 = val5 - position; body.position = val5; ((Component)player).transform.position = position2 + val6; ApplyMappedLook(player, val4); Physics.SyncTransforms(); body.linearVelocity = val3; body.WakeUp(); Plugin.Log.LogInfo((object)("PORTAL_TRAVERSED entrance=" + entrance.EndpointType.ToString() + ", exit=" + exit.EndpointType.ToString() + ", centerBefore=" + FormatVector(capsule.Center) + ", centerTarget=" + FormatVector(targetCenter) + ", velocityBefore=" + FormatVector(linearVelocity) + ", velocityAfter=" + FormatVector(val3) + ", lookBefore=" + FormatVector(lookDir) + ", lookTarget=" + FormatVector(val4) + ", lookAfter=" + FormatVector(((Character)player).GetLookDir()) + ", speedBefore=" + FormatFloat(((Vector3)(ref linearVelocity)).magnitude) + ", speedAfter=" + FormatFloat(((Vector3)(ref val3)).magnitude) + ", exitNudge=" + FormatFloat(usedNudge) + ", exitApertureScale=" + FormatFloat(usedApertureScale) + ". Direct Rigidbody movement used; Player.TeleportTo was not called.")); return true; } private static void ApplyMappedLook(Player player, Vector3 mappedLook) { //IL_0017: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_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_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) if (!(((Vector3)(ref mappedLook)).sqrMagnitude < 0.0001f)) { ((Vector3)(ref mappedLook)).Normalize(); Vector3 val = ((Character)player).GetLookDir(); if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = ((Component)player).transform.forward; } ((Vector3)(ref val)).Normalize(); float num = Mathf.Asin(Mathf.Clamp(0f - val.y, -1f, 1f)) * 57.29578f; float num2 = Mathf.Clamp(Mathf.Asin(Mathf.Clamp(0f - mappedLook.y, -1f, 1f)) * 57.29578f, -89f, 89f); Vector3 val2 = ((Character)player).GetLookYaw() * Vector3.forward; val2.y = 0f; Vector3 val3 = mappedLook; val3.y = 0f; float num3 = 0f; if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f && ((Vector3)(ref val3)).sqrMagnitude > 0.0001f) { num3 = Vector3.SignedAngle(val2, val3, Vector3.up); } player.SetMouseLook(new Vector2(num3, num - num2)); player.FaceLookDirection(); } } private static bool TryFindClearExit(Player player, PlayerCapsule capsule, PortalEndpoint exit, Vector3 exitPlaneCenter, float forwardExtent, ModConfig config, out Vector3 targetCenter, out float usedNudge, out float usedApertureScale) { //IL_001a: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) float value = config.ExitMargin.Value; float value2 = config.ExitNudgeLimit.Value; Vector3 val = exitPlaneCenter - ((Component)exit).transform.position; float[] array = new float[5] { 1f, 0.75f, 0.5f, 0.25f, 0f }; foreach (float num in array) { Vector3 val2 = ((Component)exit).transform.position + val * num; for (float num2 = 0f; num2 <= value2 + 0.001f; num2 += 0.1f) { usedNudge = num2; usedApertureScale = num; targetCenter = val2 + ((Component)exit).transform.forward * (forwardExtent + value + num2); if (IsCapsuleClear(player, capsule, targetCenter)) { return true; } } } targetCenter = Vector3.zero; usedNudge = 0f; usedApertureScale = 0f; return false; } private static bool IsCapsuleClear(Player player, PlayerCapsule capsule, Vector3 center) { //IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_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) Vector3 val = center + capsule.Axis * capsule.HalfSegment; Vector3 val2 = center - capsule.Axis * capsule.HalfSegment; Collider[] array = Physics.OverlapCapsule(val, val2, Mathf.Max(0.01f, capsule.Radius - 0.02f), -5, (QueryTriggerInteraction)1); foreach (Collider val3 in array) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.attachedRigidbody == (Object)(object)capsule.Body) && !IsChildOf(((Component)val3).transform, ((Component)player).transform)) { return false; } } return true; } private static bool FitsAperture(PlayerCapsule capsule, PortalEndpoint endpoint, Vector3 center, float margin) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)endpoint).transform.InverseTransformPoint(center); float num = Mathf.Min(endpoint.Width, endpoint.Height) * 0.5f + margin; return val.x * val.x + val.y * val.y <= num * num; } private static bool IsChildOf(Transform child, Transform parent) { while ((Object)(object)child != (Object)null) { if ((Object)(object)child == (Object)(object)parent) { return true; } child = child.parent; } return false; } private static string FormatVector(Vector3 value) { //IL_0010: 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_003c: Unknown result type (might be due to invalid IL or missing references) return "(" + FormatFloat(value.x) + "," + FormatFloat(value.y) + "," + FormatFloat(value.z) + ")"; } private static string FormatFloat(float value) { return value.ToString("0.###", CultureInfo.InvariantCulture); } } internal sealed class PortalViewSurface : MonoBehaviour { private const int EdgeSegments = 64; private const int ViewRenderQueue = 3990; private const int ViewSortingOrder = 100; private const float ViewSurfaceLift = 0.055f; private Mesh surfaceMesh; private MeshFilter surfaceFilter; private Material surfaceMaterial; private MeshRenderer surfaceRenderer; private RenderTexture renderTexture; private bool displaySupported; private float currentDiameter = -1f; private float currentEdgeFeatherFraction = -1f; internal Renderer Renderer => (Renderer)(object)surfaceRenderer; internal bool HasTexture { get { if ((Object)(object)renderTexture != (Object)null) { return renderTexture.IsCreated(); } return false; } } internal static PortalViewSurface Create(Transform parent, float diameter, float edgeFeatherFraction) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("PortalWindowView") { hideFlags = (HideFlags)52 }; val.transform.SetParent(parent, false); val.transform.localPosition = new Vector3(0f, 0f, 0.055f); val.transform.localRotation = Quaternion.identity; val.transform.localScale = Vector3.one; PortalViewSurface portalViewSurface = val.AddComponent(); portalViewSurface.Initialize(diameter, edgeFeatherFraction); return portalViewSurface; } internal void EnsureGeometry(float diameter, float edgeFeatherFraction) { diameter = Mathf.Max(0.01f, diameter); edgeFeatherFraction = Mathf.Clamp01(edgeFeatherFraction); if (!Mathf.Approximately(currentDiameter, diameter) || !Mathf.Approximately(currentEdgeFeatherFraction, edgeFeatherFraction)) { Mesh val = surfaceMesh; surfaceMesh = BuildCircle(diameter, edgeFeatherFraction); currentDiameter = diameter; currentEdgeFeatherFraction = edgeFeatherFraction; if ((Object)(object)surfaceFilter != (Object)null) { surfaceFilter.sharedMesh = surfaceMesh; } if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } Plugin.Log.LogInfo((object)("PORTAL_VIEW_GEOMETRY diameter=" + diameter.ToString("0.###", CultureInfo.InvariantCulture) + ", featherFraction=" + edgeFeatherFraction.ToString("0.###", CultureInfo.InvariantCulture) + ".")); } } internal RenderTexture EnsureTexture(int width, int height) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown width = Mathf.Max(64, width); height = Mathf.Max(64, height); if ((Object)(object)renderTexture != (Object)null && ((Texture)renderTexture).width == width && ((Texture)renderTexture).height == height) { return renderTexture; } ReleaseTexture(); renderTexture = new RenderTexture(width, height, 16, (RenderTextureFormat)0) { name = "DundrPortalGun_View_" + ((Object)this).GetInstanceID(), hideFlags = (HideFlags)52, filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1, useMipMap = false, autoGenerateMips = false, antiAliasing = 1 }; renderTexture.Create(); if ((Object)(object)surfaceMaterial != (Object)null) { surfaceMaterial.mainTexture = (Texture)(object)renderTexture; } return renderTexture; } internal void SetDisplayEnabled(bool enabled) { if ((Object)(object)surfaceRenderer != (Object)null) { ((Renderer)surfaceRenderer).enabled = enabled && displaySupported && HasTexture; } } internal bool IsVisibleFrom(Camera viewer, Plane[] viewerPlanes) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)viewer == (Object)null || viewerPlanes == null || (Object)(object)surfaceRenderer == (Object)null) { return false; } Vector3 val = ((Component)viewer).transform.position - ((Component)this).transform.parent.position; if (Vector3.Dot(((Component)this).transform.parent.forward, val) <= 0.01f) { return false; } return GeometryUtility.TestPlanesAABB(viewerPlanes, ((Renderer)surfaceRenderer).bounds); } private void Initialize(float diameter, float edgeFeatherFraction) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown surfaceFilter = ((Component)this).gameObject.AddComponent(); EnsureGeometry(diameter, edgeFeatherFraction); surfaceRenderer = ((Component)this).gameObject.AddComponent(); Shader val = FindDisplayShader(); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"PORTAL_VIEW_DISABLED no loaded texture-capable display shader was found."); ((Renderer)surfaceRenderer).enabled = false; ((Behaviour)this).enabled = false; return; } surfaceMaterial = new Material(val) { name = "DundrPortalGun_WindowMaterial", hideFlags = (HideFlags)52 }; surfaceMaterial.renderQueue = 3990; ((Renderer)surfaceRenderer).sharedMaterial = surfaceMaterial; ((Renderer)surfaceRenderer).sortingOrder = 100; ((Renderer)surfaceRenderer).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)surfaceRenderer).receiveShadows = false; ((Renderer)surfaceRenderer).lightProbeUsage = (LightProbeUsage)0; ((Renderer)surfaceRenderer).reflectionProbeUsage = (ReflectionProbeUsage)0; ((Renderer)surfaceRenderer).enabled = false; displaySupported = true; Plugin.Log.LogInfo((object)("PORTAL_VIEW_SHADER shader=" + ((Object)val).name + ", renderQueue=" + surfaceMaterial.renderQueue + ", sortingOrder=" + ((Renderer)surfaceRenderer).sortingOrder + ".")); } private static Shader FindDisplayShader() { //IL_004e: 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_0064: Expected O, but got Unknown string[] array = new string[6] { "Unlit/Texture", "UI/Default", "Sprites/Default", "Particles/Standard Unlit", "Unlit/Transparent", "Standard" }; for (int i = 0; i < array.Length; i++) { Shader val = Shader.Find(array[i]); if (!((Object)(object)val == (Object)null)) { Material val2 = new Material(val); bool flag = val2.HasProperty("_MainTex"); Object.Destroy((Object)val2); if (flag) { return val; } } } return null; } private static Mesh BuildCircle(float diameter, float edgeFeatherFraction) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0141: 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_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: 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_0236: 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_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Expected O, but got Unknown edgeFeatherFraction = Mathf.Clamp01(edgeFeatherFraction); int num = 1; int num2 = num + 64; Vector3[] array = (Vector3[])(object)new Vector3[129]; Vector3[] array2 = (Vector3[])(object)new Vector3[array.Length]; Vector2[] array3 = (Vector2[])(object)new Vector2[array.Length]; Color[] array4 = (Color[])(object)new Color[array.Length]; int[] array5 = new int[576]; array[0] = Vector3.zero; array2[0] = Vector3.forward; array3[0] = new Vector2(0.5f, 0.5f); array4[0] = Color.white; float num3 = diameter * 0.5f; float num4 = num3 * (1f - edgeFeatherFraction); for (int i = 0; i < 64; i++) { float num5 = (float)Math.PI * 2f * (float)i / 64f; float num6 = Mathf.Cos(num5); float num7 = Mathf.Sin(num5); int num8 = num + i; int num9 = num2 + i; array[num8] = new Vector3(num6 * num4, num7 * num4, 0f); array[num9] = new Vector3(num6 * num3, num7 * num3, 0f); array2[num8] = Vector3.forward; array2[num9] = Vector3.forward; float num10 = 0.5f * (1f - edgeFeatherFraction); array3[num8] = new Vector2(0.5f - num6 * num10, 0.5f + num7 * num10); array3[num9] = new Vector2(0.5f - num6 * 0.5f, 0.5f + num7 * 0.5f); array4[num8] = Color.white; array4[num9] = new Color(1f, 1f, 1f, 0f); int num11 = (i + 1) % 64; int num12 = num + num11; int num13 = num2 + num11; int num14 = i * 9; array5[num14] = 0; array5[num14 + 1] = num12; array5[num14 + 2] = num8; array5[num14 + 3] = num8; array5[num14 + 4] = num12; array5[num14 + 5] = num13; array5[num14 + 6] = num8; array5[num14 + 7] = num13; array5[num14 + 8] = num9; } Mesh val = new Mesh { name = "DundrPortalGun_Circle", hideFlags = (HideFlags)52, vertices = array, normals = array2, uv = array3, colors = array4, triangles = array5 }; val.RecalculateBounds(); return val; } private void OnDestroy() { ReleaseTexture(); if ((Object)(object)surfaceMaterial != (Object)null) { Object.Destroy((Object)(object)surfaceMaterial); surfaceMaterial = null; } if ((Object)(object)surfaceMesh != (Object)null) { Object.Destroy((Object)(object)surfaceMesh); surfaceMesh = null; } } private void ReleaseTexture() { if (!((Object)(object)renderTexture == (Object)null)) { if ((Object)(object)surfaceMaterial != (Object)null) { surfaceMaterial.mainTexture = null; } renderTexture.Release(); Object.Destroy((Object)(object)renderTexture); renderTexture = null; } } } internal sealed class PortalViewSystem { private struct PortalRenderCandidate { internal PortalPair Pair; internal PortalEndpoint Entrance; internal PortalEndpoint Exit; internal bool StandardLoaded; internal bool BlueLoaded; } private const float ClipPlaneLift = 0.025f; private static readonly Quaternion PortalFrameTurn = Quaternion.Euler(0f, 180f, 0f); private readonly ModConfig config; private readonly Plane[] viewerPlanes = (Plane[])(object)new Plane[6]; private readonly List hiddenEffectRenderers = new List(); private readonly List hiddenEffectRendererStates = new List(); private readonly List hiddenEffectLights = new List(); private readonly List hiddenEffectLightStates = new List(); private readonly List renderCandidates = new List(); private Camera portalCamera; private float nextRenderTime; private int renderCursor; private float nextErrorLogTime; internal PortalViewSystem(ModConfig config) { this.config = config; } internal void LateTick(IEnumerable pairs, Camera viewer) { renderCandidates.Clear(); if (pairs == null) { return; } bool flag = config.PortalViewsEnabled.Value && (Object)(object)viewer != (Object)null; if (flag) { GeometryUtility.CalculateFrustumPlanes(viewer, viewerPlanes); } foreach (PortalPair pair in pairs) { if (pair == null || !pair.IsComplete) { SetPairDisplay(pair, standardEnabled: false, blueEnabled: false); continue; } UpdatePairGeometry(pair); bool flag2 = flag && IsDestinationLoaded(pair.Blue); bool flag3 = flag && IsDestinationLoaded(pair.Standard); SetPairDisplay(pair, flag2, flag3); if (flag2 && (Object)(object)pair.Standard.ViewSurface != (Object)null && pair.Standard.ViewSurface.IsVisibleFrom(viewer, viewerPlanes)) { renderCandidates.Add(new PortalRenderCandidate { Pair = pair, Entrance = pair.Standard, Exit = pair.Blue, StandardLoaded = flag2, BlueLoaded = flag3 }); } if (flag3 && (Object)(object)pair.Blue.ViewSurface != (Object)null && pair.Blue.ViewSurface.IsVisibleFrom(viewer, viewerPlanes)) { renderCandidates.Add(new PortalRenderCandidate { Pair = pair, Entrance = pair.Blue, Exit = pair.Standard, StandardLoaded = flag2, BlueLoaded = flag3 }); } } if (renderCandidates.Count != 0 && !(Time.unscaledTime < nextRenderTime)) { float num = 1f / Mathf.Max(1f, config.PortalViewFramesPerSecond.Value); nextRenderTime = Time.unscaledTime + num; PortalRenderCandidate portalRenderCandidate = renderCandidates[renderCursor % renderCandidates.Count]; renderCursor = (renderCursor + 1) & 0x7FFFFFFF; RenderPortal(portalRenderCandidate.Pair, portalRenderCandidate.Entrance, portalRenderCandidate.Exit, viewer); SetPairDisplay(portalRenderCandidate.Pair, portalRenderCandidate.StandardLoaded, portalRenderCandidate.BlueLoaded); } } internal void Reset() { if ((Object)(object)portalCamera != (Object)null) { Object.Destroy((Object)(object)((Component)portalCamera).gameObject); portalCamera = null; } nextRenderTime = 0f; renderCursor = 0; nextErrorLogTime = 0f; } private void RenderPortal(PortalPair pair, PortalEndpoint entrance, PortalEndpoint exit, Camera viewer) { if ((Object)(object)entrance == (Object)null || (Object)(object)exit == (Object)null || (Object)(object)entrance.ViewSurface == (Object)null) { return; } try { EnsureCamera(); int num = Mathf.Clamp(config.PortalViewResolution.Value, 128, 1024); int height = num; bool num2 = !entrance.ViewSurface.HasTexture; RenderTexture texture = entrance.ViewSurface.EnsureTexture(num, height); if (num2) { Plugin.Log.LogInfo((object)("PORTAL_VIEW_READY entrance=" + entrance.EndpointType.ToString() + ", destination=" + exit.EndpointType.ToString() + ", texture=" + num + "x" + height + ", fpsBudget=" + config.PortalViewFramesPerSecond.Value + ", viewDistance=" + config.PortalViewDistance.Value + ".")); } if (!ConfigurePortalCamera(viewer, entrance, exit, texture)) { entrance.ViewSurface.SetDisplayEnabled(enabled: false); return; } pair.Standard.ViewSurface.SetDisplayEnabled(enabled: false); pair.Blue.ViewSurface.SetDisplayEnabled(enabled: false); bool value = config.HidePortalEffectsInView.Value; try { if (value) { HideEndpointEffects(exit); } portalCamera.Render(); } finally { portalCamera.targetTexture = null; if (value) { RestorePortalEffects(); } } } catch (Exception ex) { if (Time.unscaledTime >= nextErrorLogTime) { nextErrorLogTime = Time.unscaledTime + 2f; Plugin.Log.LogWarning((object)("PORTAL_VIEW_RENDER_FAILED entrance=" + entrance.EndpointType.ToString() + ", error=" + ex?.ToString() + ".")); } } } private bool ConfigurePortalCamera(Camera viewer, PortalEndpoint entrance, PortalEndpoint exit, RenderTexture texture) { //IL_0006: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_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_003d: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)exit).transform.TransformPoint(PortalFrameTurn * ((Component)entrance).transform.InverseTransformPoint(((Component)viewer).transform.position)); Vector3 val2 = ((Component)exit).transform.position + ((Component)exit).transform.forward * 0.025f; float num = ResolveViewDiameter(exit); Vector3 val3 = ((Component)exit).transform.right; Vector3 normalized = ((Vector3)(ref val3)).normalized; val3 = ((Component)exit).transform.up; Vector3 normalized2 = ((Vector3)(ref val3)).normalized; val3 = ((Component)exit).transform.forward; Vector3 val4 = -((Vector3)(ref val3)).normalized; Vector3 val5 = val2 - normalized * num * 0.5f - normalized2 * num * 0.5f; Vector3 val6 = val2 + normalized * num * 0.5f - normalized2 * num * 0.5f; Vector3 val7 = val2 - normalized * num * 0.5f + normalized2 * num * 0.5f; Vector3 val8 = val5 - val; float num2 = 0f - Vector3.Dot(val8, val4); if (num2 <= 0.01f) { return false; } float num3 = Mathf.Max(0.03f, num2); float num4 = num3 + Mathf.Max(10f, config.PortalViewDistance.Value); float num5 = Vector3.Dot(normalized, val8) * num3 / num2; float num6 = Vector3.Dot(normalized, val6 - val) * num3 / num2; float num7 = Vector3.Dot(normalized2, val8) * num3 / num2; float num8 = Vector3.Dot(normalized2, val7 - val) * num3 / num2; if (num6 - num5 <= 0.0001f || num8 - num7 <= 0.0001f) { return false; } portalCamera.CopyFrom(viewer); ((Behaviour)portalCamera).enabled = false; portalCamera.allowHDR = false; portalCamera.allowMSAA = false; portalCamera.stereoTargetEye = (StereoTargetEyeMask)0; portalCamera.nearClipPlane = num3; portalCamera.farClipPlane = num4; portalCamera.targetTexture = texture; ((Component)portalCamera).transform.SetPositionAndRotation(val, Quaternion.LookRotation(((Component)exit).transform.forward, normalized2)); Matrix4x4 identity = Matrix4x4.identity; ((Matrix4x4)(ref identity)).SetRow(0, new Vector4(normalized.x, normalized.y, normalized.z, 0f)); ((Matrix4x4)(ref identity)).SetRow(1, new Vector4(normalized2.x, normalized2.y, normalized2.z, 0f)); ((Matrix4x4)(ref identity)).SetRow(2, new Vector4(val4.x, val4.y, val4.z, 0f)); portalCamera.worldToCameraMatrix = identity * Matrix4x4.Translate(-val); portalCamera.projectionMatrix = Matrix4x4.Frustum(num5, num6, num7, num8, num3, num4); return true; } private void EnsureCamera() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown if (!((Object)(object)portalCamera != (Object)null)) { GameObject val = new GameObject("DundrPortalGun_ViewCamera"); ((Object)val).hideFlags = (HideFlags)61; portalCamera = val.AddComponent(); ((Behaviour)portalCamera).enabled = false; } } private void UpdatePairGeometry(PortalPair pair) { UpdateEndpointGeometry(pair.Standard); UpdateEndpointGeometry(pair.Blue); } private void UpdateEndpointGeometry(PortalEndpoint endpoint) { if (!((Object)(object)endpoint == (Object)null) && !((Object)(object)endpoint.ViewSurface == (Object)null)) { endpoint.ViewSurface.EnsureGeometry(ResolveViewDiameter(endpoint), config.PortalViewEdgeFeatherFraction.Value); } } private float ResolveViewDiameter(PortalEndpoint endpoint) { if ((Object)(object)endpoint == (Object)null) { return Mathf.Max(0.01f, config.PortalViewDiameter.Value); } return Mathf.Clamp(config.PortalViewDiameter.Value, 0.01f, Mathf.Min(endpoint.Width, endpoint.Height)); } private void HideEndpointEffects(PortalEndpoint endpoint) { hiddenEffectRenderers.Clear(); hiddenEffectRendererStates.Clear(); hiddenEffectLights.Clear(); hiddenEffectLightStates.Clear(); if ((Object)(object)endpoint == (Object)null) { return; } Renderer[] visualRenderers = endpoint.VisualRenderers; if (visualRenderers != null) { Renderer[] array = visualRenderers; foreach (Renderer val in array) { if (!((Object)(object)val == (Object)null)) { hiddenEffectRenderers.Add(val); hiddenEffectRendererStates.Add(val.enabled); val.enabled = false; } } } Light[] visualLights = endpoint.VisualLights; if (visualLights == null) { return; } Light[] array2 = visualLights; foreach (Light val2 in array2) { if (!((Object)(object)val2 == (Object)null)) { hiddenEffectLights.Add(val2); hiddenEffectLightStates.Add(((Behaviour)val2).enabled); ((Behaviour)val2).enabled = false; } } } private void RestorePortalEffects() { for (int i = 0; i < hiddenEffectRenderers.Count; i++) { Renderer val = hiddenEffectRenderers[i]; if ((Object)(object)val != (Object)null) { val.enabled = hiddenEffectRendererStates[i]; } } for (int j = 0; j < hiddenEffectLights.Count; j++) { Light val2 = hiddenEffectLights[j]; if ((Object)(object)val2 != (Object)null) { ((Behaviour)val2).enabled = hiddenEffectLightStates[j]; } } hiddenEffectRenderers.Clear(); hiddenEffectRendererStates.Clear(); hiddenEffectLights.Clear(); hiddenEffectLightStates.Clear(); } private static bool IsDestinationLoaded(PortalEndpoint endpoint) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)endpoint != (Object)null) { if (!((Object)(object)ZoneSystem.instance == (Object)null)) { return ZoneSystem.instance.IsZoneLoaded(((Component)endpoint).transform.position); } return true; } return false; } private static void SetPairDisplay(PortalPair pair, bool standardEnabled, bool blueEnabled) { if (pair != null) { if ((Object)(object)pair.Standard != (Object)null && (Object)(object)pair.Standard.ViewSurface != (Object)null) { pair.Standard.ViewSurface.SetDisplayEnabled(standardEnabled); } if ((Object)(object)pair.Blue != (Object)null && (Object)(object)pair.Blue.ViewSurface != (Object)null) { pair.Blue.ViewSurface.SetDisplayEnabled(blueEnabled); } } } } internal static class PortalVisualFactory { private const float SourceWidth = 1.8f; private const float StandardSourceHeight = 2.732f; private const float StandardSourceCenter = 1.366f; private const float BlueSourceHeight = 3.214f; private const float BlueSourceCenter = 1.607f; private const float BlueVisualSurfaceLift = 0.035f; private static readonly string[] UnsafeComponentNames = new string[8] { "EffectArea", "GuidePoint", "Piece", "TeleportWorld", "TeleportWorldTrigger", "TimedDestruction", "WearNTear", "ZNetView" }; internal static GameObject Create(Transform parent, PortalEndpointType endpointType, float width, float height) { //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) string text = ((endpointType == PortalEndpointType.Standard) ? "portal_wood" : "portal"); string text2 = ((endpointType == PortalEndpointType.Standard) ? "_target_found_red" : "_target_found"); float num = ((endpointType == PortalEndpointType.Standard) ? 2.732f : 3.214f); float num2 = ((endpointType == PortalEndpointType.Standard) ? 1.366f : 1.607f); GameObject prefab = PrefabManager.Instance.GetPrefab(text); Transform val = (((Object)(object)prefab == (Object)null) ? null : prefab.transform.Find(text2)); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)("PORTAL_VISUAL_FAILED type=" + endpointType.ToString() + ", missing=" + text + "/" + text2 + ".")); return null; } GameObject obj = Object.Instantiate(((Component)val).gameObject); ((Object)obj).name = "DundrPortalGun_" + endpointType.ToString() + "Glow"; obj.SetActive(false); obj.transform.SetParent(parent, false); float num3 = width / 1.8f; float num4 = height / num; obj.transform.localPosition = new Vector3(0f, (0f - num2) * num4, (endpointType == PortalEndpointType.Blue) ? 0.035f : 0f); obj.transform.localRotation = Quaternion.identity; obj.transform.localScale = new Vector3(num3, num4, 1f); Sanitize(obj); obj.SetActive(true); ActivateFadeController(obj); RestartParticles(obj); LogAudit(obj, endpointType, text + "/" + text2); return obj; } private static void Sanitize(GameObject visual) { //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) Transform val = visual.transform.Find("TELEPORT"); if ((Object)(object)val != (Object)null) { Object.DestroyImmediate((Object)(object)((Component)val).gameObject); } Component[] componentsInChildren = visual.GetComponentsInChildren(true); foreach (Component val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && !(val2 is Transform)) { bool flag = val2 is Renderer && !(val2 is ParticleSystemRenderer); if (val2 is Collider || val2 is Rigidbody || val2 is MeshFilter || flag || IsUnsafeComponentName(((object)val2).GetType().Name)) { Object.DestroyImmediate((Object)(object)val2); } } } Transform[] componentsInChildren2 = visual.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { ((Object)((Component)componentsInChildren2[i]).gameObject).hideFlags = (HideFlags)52; } ParticleSystem[] componentsInChildren3 = visual.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren3.Length; i++) { MainModule main = componentsInChildren3[i].main; ((MainModule)(ref main)).stopAction = (ParticleSystemStopAction)0; } } private static bool IsUnsafeComponentName(string componentName) { string[] unsafeComponentNames = UnsafeComponentNames; foreach (string b in unsafeComponentNames) { if (string.Equals(componentName, b, StringComparison.Ordinal)) { return true; } } return false; } private static void RestartParticles(GameObject visual) { ParticleSystem[] componentsInChildren = visual.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].Play(true); } } private static void ActivateFadeController(GameObject visual) { EffectFade component = visual.GetComponent(); if ((Object)(object)component != (Object)null) { component.SetActive(true); } } private static void LogAudit(GameObject visual, PortalEndpointType endpointType, string sourcePath) { int num = 0; Renderer[] componentsInChildren = visual.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if (!(componentsInChildren[i] is ParticleSystemRenderer)) { num++; } } Plugin.Log.LogInfo((object)("PORTAL_VISUAL_CREATED type=" + endpointType.ToString() + ", source=" + sourcePath + ", particles=" + visual.GetComponentsInChildren(true).Length + ", lights=" + visual.GetComponentsInChildren(true).Length + ", audio=" + visual.GetComponentsInChildren(true).Length + ", fadeControllers=" + visual.GetComponentsInChildren(true).Length + ", colliders=" + visual.GetComponentsInChildren(true).Length + ", rigidbodies=" + visual.GetComponentsInChildren(true).Length + ", nonParticleRenderers=" + num + ".")); } } } namespace DundrPortalGun.Patches { [HarmonyPatch(typeof(Character), "UpdateGroundContact")] internal static class PortalFallDamagePatch { [HarmonyPrefix] [HarmonyPriority(800)] private static void ResetFallAltitudeDuringPortalGrace(Character __instance, ref float ___m_maxAirAltitude) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) Player val = (Player)(object)((__instance is Player) ? __instance : null); if (!((Object)(object)val == (Object)null) && Plugin.Portals != null && Plugin.Portals.IsFallDamageGraceActive(val)) { ___m_maxAirAltitude = ((Component)val).transform.position.y; } } } [HarmonyPatch(typeof(Player), "SetControls")] internal static class PortalGunControlPatch { private static void Prefix(Player __instance, ref bool secondaryAttack, ref bool secondaryAttackHold, ref bool block, ref bool blockHold) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && PortalGunItem.IsPortalGun(((Humanoid)__instance).GetCurrentWeapon())) { bool flag = PortalGunInput.CanUsePortalGun(__instance); secondaryAttack = flag && PortalGunInput.ConsumeRightPress(); secondaryAttackHold = flag && PortalGunInput.IsRightHeld(); block = false; blockHold = false; } } } [HarmonyPatch(typeof(Projectile), "FixedUpdate")] internal static class ProjectileTraversalPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static void BeforeProjectileMovement(Projectile __instance) { if (Plugin.Portals != null) { Plugin.Portals.TryTraverseProjectile(__instance); } } [HarmonyPostfix] [HarmonyPriority(0)] private static void AfterProjectileMovement(Projectile __instance) { if (Plugin.Portals != null) { Plugin.Portals.FinishProjectileFixedUpdate(__instance); } } } [HarmonyPatch(typeof(Projectile), "OnHit")] internal static class ProjectileExitWallHitPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool BeforeProjectileHit(Projectile __instance, Collider __0, Vector3 __1, bool __2, Vector3 __3) { //IL_000e: 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) if (Plugin.Portals != null) { return !Plugin.Portals.ShouldSuppressProjectileExitWallHit(__instance, __0, __1, __2, __3); } return true; } } } namespace DundrPortalGun.Networking { internal sealed class PortalNetwork { private enum MessageType : byte { PlaceRequest = 1, DeleteRequest = 2, SnapshotRequest = 3, PlaceState = 11, DeleteState = 12, SnapshotState = 13, ConfigState = 14, Rejection = 15 } private struct PlacementRequest { internal long OwnerId; internal PortalEndpointType EndpointType; internal Vector3 Position; internal Quaternion Rotation; internal string TargetPrefab; } private sealed class EndpointState { internal long OwnerId; internal string OwnerName; internal PortalEndpointType EndpointType; internal Vector3 Position; internal Quaternion Rotation; internal float Width; internal float Height; internal string TargetPrefab; } private sealed class OwnerRecord { internal long OwnerId; internal string OwnerName; internal EndpointState Standard; internal EndpointState Blue; internal bool IsEmpty { get { if (Standard == null) { return Blue == null; } return false; } } internal EndpointState Get(PortalEndpointType type) { if (type != PortalEndpointType.Standard) { return Blue; } return Standard; } internal void Set(EndpointState state) { if (state.EndpointType == PortalEndpointType.Standard) { Standard = state; } else { Blue = state; } } internal void Remove(PortalEndpointType type) { if (type == PortalEndpointType.Standard) { Standard = null; } else { Blue = null; } } } private const string RpcName = "PortalStateV1"; private const float MaximumPlacementDistance = 1100f; private const float RequestInterval = 0.04f; private const float DisconnectedOwnerGrace = 15f; private const float OwnerAuditInterval = 2f; private readonly ModConfig config; private readonly PortalManager manager; private readonly CustomRPC stateRpc; private readonly Dictionary serverRecords = new Dictionary(); private readonly Dictionary nextRequestTimes = new Dictionary(); private readonly Dictionary ownerMissingSince = new Dictionary(); private readonly List staleOwners = new List(); private ZNet observedNetwork; private bool hadLocalPlayer; private bool snapshotRequested; private int serverRevision; private int clientRevision = -1; private bool lastServerRestrict; private string lastServerAllowed; private float nextOwnerAudit; internal PortalNetwork(ModConfig config, PortalManager manager) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_006f: Expected O, but got Unknown this.config = config; this.manager = manager; stateRpc = NetworkManager.Instance.AddRPC("PortalStateV1", new CoroutineHandler(OnServerReceive), new CoroutineHandler(OnClientReceive)); Plugin.Log.LogInfo((object)"PORTAL_NETWORK registered PortalStateV1 RPC; endpoint state and placement rules are host-authoritative."); } internal void Tick(Player localPlayer) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown ZNet instance = ZNet.instance; if ((Object)(object)instance != (Object)(object)observedNetwork) { ResetSession(instance); } if ((Object)(object)instance == (Object)null || ZRoutedRpc.instance == null) { return; } if ((Object)(object)localPlayer == (Object)null) { hadLocalPlayer = false; if (!instance.IsServer()) { snapshotRequested = false; } } else if (!hadLocalPlayer) { hadLocalPlayer = true; if (instance.IsServer()) { ApplyServerRecordsToManager(); } } if (instance.IsServer()) { BroadcastConfigIfChanged(); AuditDisconnectedOwners(); } else if ((Object)(object)localPlayer != (Object)null && !snapshotRequested) { snapshotRequested = true; ZPackage val = new ZPackage(); val.Write((byte)3); stateRpc.SendPackage(GetServerPeerId(), val); Plugin.Log.LogInfo((object)"PORTAL_NETWORK snapshot requested."); } } internal void RequestPlacement(Player owner, PortalEndpointType endpointType, Vector3 position, Quaternion rotation, string targetPrefab) { //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_0031: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown if (!((Object)(object)owner == (Object)null)) { PlacementRequest request = new PlacementRequest { OwnerId = owner.GetPlayerID(), EndpointType = endpointType, Position = position, Rotation = rotation, TargetPrefab = (targetPrefab ?? string.Empty) }; if (IsServer()) { ProcessPlacementRequest(ZNet.GetUID(), request); } else if (ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write((byte)1); WritePlacementRequest(val, request); stateRpc.SendPackage(GetServerPeerId(), val); } } } internal void RequestDeletion(Player owner, PortalEndpointType endpointType) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown if (!((Object)(object)owner == (Object)null)) { long playerID = owner.GetPlayerID(); if (IsServer()) { ProcessDeletionRequest(ZNet.GetUID(), playerID, endpointType); } else if (ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write((byte)2); val.Write(playerID); val.Write((byte)endpointType); stateRpc.SendPackage(GetServerPeerId(), val); } } } internal void Shutdown() { config.ClearServerPlacementRules(); serverRecords.Clear(); nextRequestTimes.Clear(); ownerMissingSince.Clear(); staleOwners.Clear(); observedNetwork = null; } private IEnumerator OnServerReceive(long sender, ZPackage package) { if (!IsServer() || package == null || package.Size() == 0) { yield break; } try { MessageType messageType = (MessageType)package.ReadByte(); switch (messageType) { case MessageType.PlaceRequest: ProcessPlacementRequest(sender, ReadPlacementRequest(package)); yield break; case MessageType.DeleteRequest: ProcessDeletionRequest(sender, package.ReadLong(), (PortalEndpointType)package.ReadByte()); yield break; case MessageType.SnapshotRequest: SendSnapshot(sender); yield break; } Plugin.Log.LogWarning((object)("PORTAL_NETWORK rejected unexpected server message " + messageType.ToString() + " from peer " + sender + ".")); } catch (Exception ex) { Plugin.Log.LogWarning((object)("PORTAL_NETWORK server decode failed from peer " + sender + ": " + ex.Message + ".")); } } private IEnumerator OnClientReceive(long sender, ZPackage package) { if (package == null || package.Size() == 0) { yield break; } try { MessageType messageType = (MessageType)package.ReadByte(); switch (messageType) { case MessageType.PlaceState: ReadAndApplyPlacementState(package); yield break; case MessageType.DeleteState: ReadAndApplyDeletionState(package); yield break; case MessageType.SnapshotState: ReadAndApplySnapshot(package); yield break; case MessageType.ConfigState: ReadAndApplyConfig(package); yield break; case MessageType.Rejection: Plugin.Log.LogWarning((object)("PORTAL_NETWORK request rejected by host: " + package.ReadString() + ".")); yield break; } Plugin.Log.LogWarning((object)("PORTAL_NETWORK ignored unexpected client message " + messageType.ToString() + " from peer " + sender + ".")); } catch (Exception ex) { Plugin.Log.LogWarning((object)("PORTAL_NETWORK client decode failed: " + ex.Message + ".")); } } private void ProcessPlacementRequest(long sender, PlacementRequest request) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) if (!ValidateOwnerRequest(sender, request.OwnerId, out var owner, out var rejection) || !ValidatePlacementRequest(owner, ref request, out rejection)) { Reject(sender, rejection); return; } if (!serverRecords.TryGetValue(request.OwnerId, out var value)) { value = new OwnerRecord { OwnerId = request.OwnerId, OwnerName = owner.GetPlayerName() }; serverRecords.Add(request.OwnerId, value); } value.OwnerName = owner.GetPlayerName(); EndpointState endpointState = new EndpointState { OwnerId = request.OwnerId, OwnerName = value.OwnerName, EndpointType = request.EndpointType, Position = request.Position, Rotation = request.Rotation, Width = config.ApertureWidth.Value, Height = config.ApertureHeight.Value, TargetPrefab = request.TargetPrefab }; value.Set(endpointState); serverRevision++; manager.ApplyReplicatedPlacement(endpointState.OwnerId, endpointState.OwnerName, endpointState.EndpointType, endpointState.Position, endpointState.Rotation, endpointState.Width, endpointState.Height, endpointState.TargetPrefab); BroadcastPlacement(endpointState); } private void ProcessDeletionRequest(long sender, long ownerId, PortalEndpointType endpointType) { OwnerRecord value; if (!ValidateOwnerRequest(sender, ownerId, out var owner, out var rejection) || !IsEndpointTypeValid(endpointType)) { Reject(sender, rejection ?? "invalid endpoint type"); } else if (serverRecords.TryGetValue(ownerId, out value) && value.Get(endpointType) != null) { value.Remove(endpointType); serverRevision++; manager.ApplyReplicatedDeletion(ownerId, endpointType, owner.GetPlayerName()); BroadcastDeletion(ownerId, owner.GetPlayerName(), endpointType); if (value.IsEmpty) { serverRecords.Remove(ownerId); } } } private bool ValidateOwnerRequest(long sender, long ownerId, out Player owner, out string rejection) { owner = Player.GetPlayer(ownerId); if ((Object)(object)owner == (Object)null) { rejection = "claimed player " + ownerId + " is unavailable"; return false; } ZNetView component = ((Component)owner).GetComponent(); ZDO val = (((Object)(object)component == (Object)null || !component.IsValid()) ? null : component.GetZDO()); if (((val == null) ? 0 : val.GetOwner()) != sender && (!((Object)(object)owner == (Object)(object)Player.m_localPlayer) || sender != ZNet.GetUID())) { rejection = "peer " + sender + " does not own player " + ownerId; return false; } if (nextRequestTimes.TryGetValue(sender, out var value) && Time.unscaledTime < value) { rejection = "placement/deletion rate limit exceeded"; return false; } nextRequestTimes[sender] = Time.unscaledTime + 0.04f; rejection = null; return true; } private bool ValidatePlacementRequest(Player owner, ref PlacementRequest request, out string rejection) { //IL_000e: 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_0031: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (!IsEndpointTypeValid(request.EndpointType) || !IsFinite(request.Position) || !IsFinite(request.Rotation)) { rejection = "endpoint type or transform is invalid"; return false; } if (Vector3.Distance(((Character)owner).GetCenterPoint(), request.Position) > 1100f) { rejection = "placement exceeds the host range limit"; return false; } if (request.TargetPrefab.Length > 128) { rejection = "target prefab name is too long"; return false; } if (config.RestrictPlacementByPrefab.Value) { if (!PortalPlacement.TryResolveNetworkTargetPrefab(request.Position, request.Rotation * Vector3.forward, out var targetPrefabName) || !PortalPlacement.IsAllowedTargetPrefab(targetPrefabName, restrictPlacement: true, config.AllowedPlacementPrefabs.Value)) { rejection = "the host could not verify an allowed surface at the requested endpoint"; return false; } request.TargetPrefab = targetPrefabName; } rejection = null; return true; } private void BroadcastPlacement(EndpointState state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write((byte)11); val.Write(serverRevision); WriteEndpointState(val, state); SendToClients(val); } private void BroadcastDeletion(long ownerId, string ownerName, PortalEndpointType endpointType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write((byte)12); val.Write(serverRevision); val.Write(ownerId); val.Write(ownerName ?? string.Empty); val.Write((byte)endpointType); SendToClients(val); } private void SendSnapshot(long target) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write((byte)13); val.Write(serverRevision); WriteConfig(val); int num = 0; foreach (OwnerRecord value in serverRecords.Values) { if (value.Standard != null) { num++; } if (value.Blue != null) { num++; } } val.Write(num); foreach (OwnerRecord value2 in serverRecords.Values) { if (value2.Standard != null) { WriteEndpointState(val, value2.Standard); } if (value2.Blue != null) { WriteEndpointState(val, value2.Blue); } } stateRpc.SendPackage(target, val); Plugin.Log.LogInfo((object)("PORTAL_NETWORK snapshot sent to peer " + target + " with " + num + " endpoint(s).")); } private void ReadAndApplyPlacementState(ZPackage package) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) int num = package.ReadInt(); EndpointState endpointState = ReadEndpointState(package); if (num >= clientRevision) { clientRevision = num; manager.ApplyReplicatedPlacement(endpointState.OwnerId, endpointState.OwnerName, endpointState.EndpointType, endpointState.Position, endpointState.Rotation, endpointState.Width, endpointState.Height, endpointState.TargetPrefab); } } private void ReadAndApplyDeletionState(ZPackage package) { int num = package.ReadInt(); long ownerId = package.ReadLong(); string ownerName = package.ReadString(); PortalEndpointType endpointType = (PortalEndpointType)package.ReadByte(); if (num >= clientRevision) { clientRevision = num; manager.ApplyReplicatedDeletion(ownerId, endpointType, ownerName); } } private void ReadAndApplySnapshot(ZPackage package) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) int num = package.ReadInt(); bool restrictPlacement = package.ReadBool(); string allowedPrefabs = package.ReadString(); int num2 = Mathf.Clamp(package.ReadInt(), 0, 256); if (num >= clientRevision) { clientRevision = num; config.SetServerPlacementRules(restrictPlacement, allowedPrefabs); manager.ClearAll("network snapshot replacement"); for (int i = 0; i < num2; i++) { EndpointState endpointState = ReadEndpointState(package); manager.ApplyReplicatedPlacement(endpointState.OwnerId, endpointState.OwnerName, endpointState.EndpointType, endpointState.Position, endpointState.Rotation, endpointState.Width, endpointState.Height, endpointState.TargetPrefab); } Plugin.Log.LogInfo((object)("PORTAL_NETWORK snapshot applied revision=" + num + ", endpoints=" + num2 + ", hostRestriction=" + restrictPlacement + ".")); } } private void ReadAndApplyConfig(ZPackage package) { bool restrictPlacement = package.ReadBool(); string text = package.ReadString(); config.SetServerPlacementRules(restrictPlacement, text); Plugin.Log.LogInfo((object)("PORTAL_NETWORK host placement rules updated: restrict=" + restrictPlacement + ", allowed=" + text + ".")); } private void BroadcastConfigIfChanged() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown bool value = config.RestrictPlacementByPrefab.Value; string a = config.AllowedPlacementPrefabs.Value ?? string.Empty; if (value != lastServerRestrict || !string.Equals(a, lastServerAllowed, StringComparison.Ordinal)) { lastServerRestrict = value; lastServerAllowed = a; ZPackage val = new ZPackage(); val.Write((byte)14); WriteConfig(val); SendToClients(val); } } private void AuditDisconnectedOwners() { if (Time.unscaledTime < nextOwnerAudit) { return; } nextOwnerAudit = Time.unscaledTime + 2f; staleOwners.Clear(); foreach (long key in serverRecords.Keys) { float value; if ((Object)(object)Player.GetPlayer(key) != (Object)null) { ownerMissingSince.Remove(key); } else if (!ownerMissingSince.TryGetValue(key, out value)) { ownerMissingSince[key] = Time.unscaledTime; } else if (Time.unscaledTime - value >= 15f) { staleOwners.Add(key); } } foreach (long staleOwner in staleOwners) { if (serverRecords.TryGetValue(staleOwner, out var value2)) { if (value2.Standard != null) { serverRevision++; manager.ApplyReplicatedDeletion(staleOwner, PortalEndpointType.Standard, value2.OwnerName); BroadcastDeletion(staleOwner, value2.OwnerName, PortalEndpointType.Standard); } if (value2.Blue != null) { serverRevision++; manager.ApplyReplicatedDeletion(staleOwner, PortalEndpointType.Blue, value2.OwnerName); BroadcastDeletion(staleOwner, value2.OwnerName, PortalEndpointType.Blue); } serverRecords.Remove(staleOwner); ownerMissingSince.Remove(staleOwner); Plugin.Log.LogInfo((object)("PORTAL_NETWORK removed disconnected owner " + staleOwner + ".")); } } } private void ResetSession(ZNet network) { if ((Object)(object)observedNetwork != (Object)null || (Object)(object)network != (Object)null) { manager.ClearAll("network session changed"); } observedNetwork = network; snapshotRequested = false; hadLocalPlayer = false; clientRevision = -1; serverRevision = 0; serverRecords.Clear(); nextRequestTimes.Clear(); ownerMissingSince.Clear(); config.ClearServerPlacementRules(); lastServerRestrict = !config.RestrictPlacementByPrefab.Value; lastServerAllowed = null; nextOwnerAudit = 0f; } private void ApplyServerRecordsToManager() { foreach (OwnerRecord value in serverRecords.Values) { if (value.Standard != null) { ApplyEndpointToManager(value.Standard); } if (value.Blue != null) { ApplyEndpointToManager(value.Blue); } } } private void ApplyEndpointToManager(EndpointState state) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) manager.ApplyReplicatedPlacement(state.OwnerId, state.OwnerName, state.EndpointType, state.Position, state.Rotation, state.Width, state.Height, state.TargetPrefab); } private void Reject(long target, string reason) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown Plugin.Log.LogWarning((object)("PORTAL_NETWORK rejected peer " + target + ": " + reason + ".")); if (target != ZNet.GetUID()) { ZPackage val = new ZPackage(); val.Write((byte)15); val.Write(reason ?? "request rejected"); stateRpc.SendPackage(target, val); } } private void SendToClients(ZPackage package) { if (!((Object)(object)ZNet.instance == (Object)null)) { List peers = ZNet.instance.GetPeers(); if (peers != null && peers.Count > 0) { stateRpc.SendPackage(peers, package); } } } private void WriteConfig(ZPackage package) { package.Write(config.RestrictPlacementByPrefab.Value); package.Write(config.AllowedPlacementPrefabs.Value ?? string.Empty); } private static void WritePlacementRequest(ZPackage package, PlacementRequest request) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) package.Write(request.OwnerId); package.Write((byte)request.EndpointType); package.Write(request.Position); package.Write(request.Rotation); package.Write(request.TargetPrefab ?? string.Empty); } private static PlacementRequest ReadPlacementRequest(ZPackage package) { //IL_0025: 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_0032: 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) return new PlacementRequest { OwnerId = package.ReadLong(), EndpointType = (PortalEndpointType)package.ReadByte(), Position = package.ReadVector3(), Rotation = package.ReadQuaternion(), TargetPrefab = package.ReadString() }; } private static void WriteEndpointState(ZPackage package, EndpointState state) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) package.Write(state.OwnerId); package.Write(state.OwnerName ?? string.Empty); package.Write((byte)state.EndpointType); package.Write(state.Position); package.Write(state.Rotation); package.Write(state.Width); package.Write(state.Height); package.Write(state.TargetPrefab ?? string.Empty); } private static EndpointState ReadEndpointState(ZPackage package) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) return new EndpointState { OwnerId = package.ReadLong(), OwnerName = package.ReadString(), EndpointType = (PortalEndpointType)package.ReadByte(), Position = package.ReadVector3(), Rotation = package.ReadQuaternion(), Width = package.ReadSingle(), Height = package.ReadSingle(), TargetPrefab = package.ReadString() }; } private static bool IsServer() { if ((Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.IsServer(); } return false; } private static long GetServerPeerId() { return (((Object)(object)ZNet.instance == (Object)null) ? null : ZNet.instance.GetServerPeer())?.m_uid ?? 0; } private static bool IsEndpointTypeValid(PortalEndpointType type) { if (type != PortalEndpointType.Standard) { return type == PortalEndpointType.Blue; } return true; } private static bool IsFinite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (IsFinite(value.x) && IsFinite(value.y)) { return IsFinite(value.z); } return false; } private static bool IsFinite(Quaternion value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_004f: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (IsFinite(value.x) && IsFinite(value.y) && IsFinite(value.z) && IsFinite(value.w)) { return value.x * value.x + value.y * value.y + value.z * value.z + value.w * value.w > 0.5f; } return false; } private static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } } } namespace DundrPortalGun.Controls { internal static class PortalGunInput { private static bool pendingRightPress; internal static void Tick(Player player) { if (!CanUsePortalGun(player)) { pendingRightPress = false; } else if (Input.GetMouseButtonDown(1)) { pendingRightPress = true; } } internal static bool ConsumeRightPress() { bool result = pendingRightPress; pendingRightPress = false; return result; } internal static bool IsRightHeld() { return Input.GetMouseButton(1); } internal static bool CanUsePortalGun(Player player) { if ((Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)Player.m_localPlayer && PortalGunItem.IsPortalGun(((Humanoid)player).GetCurrentWeapon()) && !InventoryGui.IsVisible() && !Menu.IsVisible() && !Console.IsVisible() && !TextInput.IsVisible()) { if (!((Object)(object)Chat.instance == (Object)null)) { return !Chat.instance.IsChatDialogWindowVisible(); } return true; } return false; } internal static void Reset() { pendingRightPress = false; } } } namespace DundrPortalGun.Items { internal static class PortalGunItem { internal const string PrefabName = "DundrPortalGun"; private const string SourceItemName = "StaffLightning"; internal static void Register(ModConfig config, GameObject standardProjectile, GameObject blueProjectile) { //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_0010: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) ItemConfig val = new ItemConfig { Name = "Dundr Portal Gun", Description = "Portal traversal test build with live linked window views. Left-click places the standard portal, right-click places the blue portal, and middle-click deletes an aimed endpoint. Players, dropped items, and fitting mobs retain portal-relative velocity.", CraftingStation = config.CraftingStation.Value, MinStationLevel = config.MinimumStationLevel.Value }; if (config.RecipeWood.Value > 0) { val.AddRequirement(new RequirementConfig("Wood", config.RecipeWood.Value, 0, true)); } CustomItem val2 = new CustomItem("DundrPortalGun", "StaffLightning", val); SharedData obj = val2.ItemDrop.m_itemData.m_shared ?? throw new InvalidOperationException("Cloned Dundr has no SharedData."); obj.m_damages = default(DamageTypes); obj.m_attackForce = 0f; obj.m_attackStatusEffect = null; obj.m_attackStatusEffectChance = 0f; Attack val3 = CloneAttack(obj.m_attack); ConfigureProjectileAttack(val3, standardProjectile, config.ProjectileVelocity.Value); obj.m_attack = val3; Attack val4 = CloneAttack(val3); ConfigureProjectileAttack(val4, blueProjectile, config.ProjectileVelocity.Value); obj.m_secondaryAttack = val4; ConfigureAlwaysLoadedVisual(((Component)val2.ItemDrop).gameObject); ItemManager.Instance.AddItem(val2); Plugin.Log.LogInfo((object)("Registered DundrPortalGun. Left-click projectile=" + ((Object)standardProjectile).name + ", right-click projectile=" + ((Object)blueProjectile).name + ", recipe=" + config.RecipeWood.Value + " Wood at " + config.CraftingStation.Value + ".")); } internal static bool IsPortalGun(ItemData itemData) { if (itemData == null) { return false; } if ((Object)(object)itemData.m_dropPrefab != (Object)null && string.Equals(((Object)itemData.m_dropPrefab).name, "DundrPortalGun", StringComparison.OrdinalIgnoreCase)) { return true; } if (itemData.m_shared != null) { return string.Equals(itemData.m_shared.m_name, "Dundr Portal Gun", StringComparison.OrdinalIgnoreCase); } return false; } private static void ConfigureProjectileAttack(Attack attack, GameObject projectile, float velocity) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) attack.m_attackType = (AttackType)2; attack.m_attackProjectile = projectile; attack.m_projectiles = 1; attack.m_projectileBursts = 1; attack.m_projectileVel = velocity; attack.m_projectileVelMin = velocity; attack.m_projectileAccuracy = 0f; attack.m_projectileAccuracyMin = 0f; attack.m_randomVelocity = false; attack.m_damageMultiplier = 0f; attack.m_attackStamina = 0f; attack.m_attackEitr = 0f; attack.m_reloadEitrDrain = 0f; attack.m_reloadStaminaDrain = 0f; attack.m_requiresReload = false; attack.m_reloadAnimation = string.Empty; attack.m_reloadTime = 0f; attack.m_recoilPushback = 0f; attack.m_spawnOnHit = null; attack.m_spawnOnTrigger = null; } private static void ConfigureAlwaysLoadedVisual(GameObject itemPrefab) { WeaponLoadState componentInChildren = itemPrefab.GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null) { Plugin.Log.LogWarning((object)"DundrPortalGun has no WeaponLoadState; loaded visual could not be forced."); return; } if ((Object)(object)componentInChildren.m_unloaded != (Object)null) { componentInChildren.m_unloaded.SetActive(false); } if ((Object)(object)componentInChildren.m_loaded != (Object)null) { componentInChildren.m_loaded.SetActive(true); } Object.DestroyImmediate((Object)(object)componentInChildren); Plugin.Log.LogInfo((object)"DundrPortalGun reload requirement removed and Loaded held model forced active."); } private static Attack CloneAttack(Attack source) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown if (source != null) { return (Attack)typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(source, null); } return new Attack(); } } } namespace DundrPortalGun.Config { internal sealed class ModConfig { private bool hasServerPlacementRules; private bool serverRestrictPlacementByPrefab; private string serverAllowedPlacementPrefabs; internal ConfigEntry CraftingStation { get; private set; } internal ConfigEntry MinimumStationLevel { get; private set; } internal ConfigEntry RecipeWood { get; private set; } internal ConfigEntry ProjectileVelocity { get; private set; } internal ConfigEntry ApertureWidth { get; private set; } internal ConfigEntry ApertureHeight { get; private set; } internal ConfigEntry SurfaceOffset { get; private set; } internal ConfigEntry DeleteAimDistance { get; private set; } internal ConfigEntry RestrictPlacementByPrefab { get; private set; } internal ConfigEntry AllowedPlacementPrefabs { get; private set; } internal ConfigEntry TraversalEnabled { get; private set; } internal ConfigEntry EntrySkin { get; private set; } internal ConfigEntry EntryApertureMargin { get; private set; } internal ConfigEntry MinimumEntrySpeed { get; private set; } internal ConfigEntry ExitMargin { get; private set; } internal ConfigEntry ExitNudgeLimit { get; private set; } internal ConfigEntry ReentryCooldown { get; private set; } internal ConfigEntry RearmDistance { get; private set; } internal ConfigEntry FallDamageGraceEnabled { get; private set; } internal ConfigEntry FallDamageGraceSeconds { get; private set; } internal ConfigEntry TransportDroppedItems { get; private set; } internal ConfigEntry TransportMobs { get; private set; } internal ConfigEntry TransportProjectiles { get; private set; } internal ConfigEntry PortalViewsEnabled { get; private set; } internal ConfigEntry PortalViewResolution { get; private set; } internal ConfigEntry PortalViewFramesPerSecond { get; private set; } internal ConfigEntry PortalViewDistance { get; private set; } internal ConfigEntry PortalViewDiameter { get; private set; } internal ConfigEntry PortalViewEdgeFeatherFraction { get; private set; } internal ConfigEntry HidePortalEffectsInView { get; private set; } internal bool EffectiveRestrictPlacementByPrefab { get { if (!hasServerPlacementRules) { return RestrictPlacementByPrefab.Value; } return serverRestrictPlacementByPrefab; } } internal string EffectiveAllowedPlacementPrefabs { get { if (!hasServerPlacementRules) { return AllowedPlacementPrefabs.Value; } return serverAllowedPlacementPrefabs; } } internal ModConfig(ConfigFile config) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Expected O, but got Unknown //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Expected O, but got Unknown //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Expected O, but got Unknown //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Expected O, but got Unknown //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Expected O, but got Unknown //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Expected O, but got Unknown //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Expected O, but got Unknown //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Expected O, but got Unknown //IL_03cb: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Expected O, but got Unknown //IL_0474: Unknown result type (might be due to invalid IL or missing references) //IL_047e: Expected O, but got Unknown //IL_04ad: Unknown result type (might be due to invalid IL or missing references) //IL_04b7: Expected O, but got Unknown //IL_04e6: Unknown result type (might be due to invalid IL or missing references) //IL_04f0: Expected O, but got Unknown //IL_051f: Unknown result type (might be due to invalid IL or missing references) //IL_0529: Expected O, but got Unknown //IL_0558: Unknown result type (might be due to invalid IL or missing references) //IL_0562: Expected O, but got Unknown CraftingStation = config.Bind("Portal Gun", "Crafting Station", "piece_workbench", "Crafting-station prefab used by the temporary test recipe. Requires a restart after changing."); MinimumStationLevel = config.Bind("Portal Gun", "Minimum Station Level", 1, new ConfigDescription("Minimum crafting-station level for the temporary test recipe.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 5), Array.Empty())); RecipeWood = config.Bind("Portal Gun", "Recipe Wood", 1, new ConfigDescription("Wood required by the temporary test recipe.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ProjectileVelocity = config.Bind("Portal Gun", "Projectile Velocity", 250f, new ConfigDescription("Launch speed shared by the standard and blue test projectiles.", (AcceptableValueBase)(object)new AcceptableValueRange(10f, 250f), Array.Empty())); ApertureWidth = config.Bind("Portal Placement", "Aperture Width", 3.347418f, new ConfigDescription("Width in metres used by endpoint fit checks and the temporary debug outline.", (AcceptableValueBase)(object)new AcceptableValueRange(0.8f, 4f), Array.Empty())); ApertureHeight = config.Bind("Portal Placement", "Aperture Height", 4.42723f, new ConfigDescription("Height in metres used by endpoint fit checks and the temporary debug outline.", (AcceptableValueBase)(object)new AcceptableValueRange(1.2f, 5f), Array.Empty())); SurfaceOffset = config.Bind("Portal Placement", "Surface Offset", 0.04f, new ConfigDescription("Distance in metres that an endpoint is offset outward from its hit surface.", (AcceptableValueBase)(object)new AcceptableValueRange(0.01f, 0.25f), Array.Empty())); DeleteAimDistance = config.Bind("Portal Placement", "Delete Aim Distance", 100f, new ConfigDescription("Maximum distance in metres for middle-click aimed endpoint deletion.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 250f), Array.Empty())); RestrictPlacementByPrefab = config.Bind("Portal Placement", "Restrict Placement By Prefab", false, "When enabled, portals can be placed only on targets whose resolved internal prefab name appears in Allowed Placement Prefabs. This setting updates live. In multiplayer, the host's setting is authoritative and is synchronized to clients."); AllowedPlacementPrefabs = config.Bind("Portal Placement", "Allowed Placement Prefabs", "stone_floor_2x2", "Comma-, semicolon-, or line-separated internal prefab names accepted when Restrict Placement By Prefab is enabled. Matching ignores capitalization, surrounding whitespace, and the runtime (Clone) suffix. Use * to allow every prefab. Successful and rejected placement logs report the resolved target prefab name."); TraversalEnabled = config.Bind("Portal Traversal", "Enabled", true, "Allow the local player and locally network-owned eligible entities to traverse complete replicated portal pairs."); EntrySkin = config.Bind("Portal Traversal", "Entry Skin", 0.18f, new ConfigDescription("Outward distance in metres at which the leading edge of the player capsule enters a portal before contacting the unchanged surface collider.", (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 0.75f), Array.Empty())); EntryApertureMargin = config.Bind("Portal Traversal", "Entry Aperture Margin", 0.4084507f, new ConfigDescription("Extra edge tolerance in metres for fitting the player capsule into a portal. This makes walking entry less exact without changing the visible portal size.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 0.5f), Array.Empty())); MinimumEntrySpeed = config.Bind("Portal Traversal", "Minimum Entry Speed", 0.1f, new ConfigDescription("Minimum speed in metres per second directed into a portal before traversal can begin.", (AcceptableValueBase)(object)new AcceptableValueRange(0.01f, 3f), Array.Empty())); ExitMargin = config.Bind("Portal Traversal", "Exit Margin", 0.18f, new ConfigDescription("Clear space kept between the exiting player capsule and the destination portal plane.", (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 1f), Array.Empty())); ExitNudgeLimit = config.Bind("Portal Traversal", "Exit Nudge Limit", 1.2f, new ConfigDescription("Maximum additional outward distance searched for a collision-free exit capsule.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 3f), Array.Empty())); ReentryCooldown = config.Bind("Portal Traversal", "Reentry Cooldown", 0.05f, new ConfigDescription("Minimum seconds after traversal before another traversal can occur.", (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 2f), Array.Empty())); RearmDistance = config.Bind("Portal Traversal", "Rearm Distance", 0.1f, new ConfigDescription("Additional outward distance the player must clear from the exit portal before it can accept entry.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 2f), Array.Empty())); FallDamageGraceEnabled = config.Bind("Portal Traversal", "Fall Damage Grace Enabled", true, "Prevent only fall damage for a short period after the local player traverses a portal. Other damage types are unaffected."); FallDamageGraceSeconds = config.Bind("Portal Traversal", "Fall Damage Grace Seconds", 3f, new ConfigDescription("Seconds of fall-damage protection granted after the local player traverses a portal. During the window, Valheim's recorded fall altitude follows the player's current height so later falls count only from where protection ended.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 30f), Array.Empty())); TransportDroppedItems = config.Bind("Portal Traversal", "Transport Dropped Items", true, "Allow dropped inventory items to traverse complete portal pairs while preserving linear and angular velocity."); TransportMobs = config.Bind("Portal Traversal", "Transport Mobs", true, "Allow locally owned non-player characters to traverse complete portal pairs while preserving velocity and upright facing."); TransportProjectiles = config.Bind("Portal Traversal", "Transport Projectiles", true, "Allow locally owned arrows, magic, and other Projectile-based attacks to traverse complete portal pairs while preserving direction and speed. Projectiles have no re-entry cooldown."); PortalViewsEnabled = config.Bind("Portal Views", "Enabled", true, "Render a non-recursive live window through each visible linked portal."); PortalViewResolution = config.Bind("Portal Views", "Horizontal Resolution", 313, new ConfigDescription("Width and height of the square render texture used by each circular portal window.", (AcceptableValueBase)(object)new AcceptableValueRange(128, 1024), Array.Empty())); PortalViewFramesPerSecond = config.Bind("Portal Views", "Render Frames Per Second", 30.51643f, new ConfigDescription("Total secondary-camera renders per second. When both portals are visible they alternate this shared budget.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 60f), Array.Empty())); PortalViewDistance = config.Bind("Portal Views", "View Distance", 80f, new ConfigDescription("Distance in metres rendered beyond the destination portal plane.", (AcceptableValueBase)(object)new AcceptableValueRange(20f, 150f), Array.Empty())); PortalViewDiameter = config.Bind("Portal Views", "Circle Diameter", 2.03662f, new ConfigDescription("Diameter in metres of the circular live-view surface. The runtime value is clamped to the smaller physical portal aperture dimension.", (AcceptableValueBase)(object)new AcceptableValueRange(0.4f, 4f), Array.Empty())); PortalViewEdgeFeatherFraction = config.Bind("Portal Views", "Border Feather Fraction", 0.3448357f, new ConfigDescription("Fraction of the circle radius faded from opaque to transparent at its edge. Zero gives a hard border; larger values create a wider, softer fade.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 0.5f), Array.Empty())); HidePortalEffectsInView = config.Bind("Portal Views", "Hide Portal Effects In View", true, "Hide only the camera-side exit portal's particle renderers and lights while the secondary portal camera renders. The nearby effect cannot obscure the view, while the other portal remains visible through it."); } internal void SetServerPlacementRules(bool restrictPlacement, string allowedPrefabs) { hasServerPlacementRules = true; serverRestrictPlacementByPrefab = restrictPlacement; serverAllowedPlacementPrefabs = allowedPrefabs ?? string.Empty; } internal void ClearServerPlacementRules() { hasServerPlacementRules = false; serverAllowedPlacementPrefabs = null; } } }