Decompiled source of ChallengeHubDreamBridge v0.5.0

BepInEx\plugins\ChallengeHubDreamBridge\ChallengeHubDreamBridge.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Video;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ChallengeHub Dream Bridge")]
[assembly: AssemblyDescription("A protected dream passage between ChallengeHub Server2 and Server4.")]
[assembly: AssemblyCompany("ChallengeHub")]
[assembly: AssemblyProduct("ChallengeHub Dream Bridge")]
[assembly: AssemblyFileVersion("0.5.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.5.0.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 ChallengeHubDreamBridge
{
	internal static class DreamBridgeInputHints
	{
		internal static string UseKey()
		{
			try
			{
				ZInput instance = ZInput.instance;
				string text = ((instance != null) ? instance.GetBoundKeyString("Use", true) : null);
				if (!string.IsNullOrWhiteSpace(text))
				{
					return text;
				}
			}
			catch
			{
			}
			return "E";
		}
	}
	[HarmonyPatch(typeof(WearNTear), "Damage")]
	internal static class DreamEventStructureDamagePatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(WearNTear __instance, HitData hit)
		{
			if (DreamCataclysmFeature.IsSequenceActive && (Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponentInParent<TeleportWorld>() != (Object)null)
			{
				return false;
			}
			DreamCataclysmFeature.ModifyEventStructureDamage(__instance, hit);
			return true;
		}
	}
	[HarmonyPatch]
	internal static class DreamEventCollapseSupportPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(WearNTear), "GetSupport", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(WearNTear __instance, ref float __result)
		{
			if (DreamCataclysmFeature.IsActiveCollapseTarget(__instance))
			{
				__result = 0f;
			}
		}
	}
	[HarmonyPatch(typeof(Character), "Damage")]
	internal static class DreamEventBossCharacterDamagePatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static void Prefix(HitData hit)
		{
			DreamCataclysmFeature.ModifyEventBossCharacterDamage(hit);
		}
	}
	[HarmonyPatch]
	internal static class DreamEventPlayerDeathPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(Player), "OnDeath", (Type[])null, (Type[])null);
		}

		[HarmonyPostfix]
		private static void Postfix(Player __instance)
		{
			DreamCataclysmFeature.ReportLocalPlayerDeath(__instance);
		}
	}
	[HarmonyPatch]
	internal static class DreamPortalInteractPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from method in AccessTools.GetDeclaredMethods(typeof(TeleportWorld))
				where method.Name == "Interact"
				select method;
		}

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(TeleportWorld __instance, object[] __args, ref bool __result)
		{
			if (!DreamBridgeRuntime.IsDreamPortal(__instance))
			{
				return true;
			}
			Player val = __args?.OfType<Player>().FirstOrDefault();
			if ((Object)(object)val == (Object)null)
			{
				Humanoid? obj = __args?.OfType<Humanoid>().FirstOrDefault();
				val = (Player)(object)((obj is Player) ? obj : null);
			}
			if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			DreamBridgeRuntime.UsePortal(__instance, val);
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(TeleportWorld), "GetHoverText")]
	internal static class DreamPortalHoverPatch
	{
		private static void Postfix(TeleportWorld __instance, ref string __result)
		{
			if (DreamBridgeRuntime.IsDreamPortal(__instance))
			{
				if (DreamBridgeRuntime.CurrentRole == DreamWorldRole.Server3Finale && DreamCataclysmFeature.CurrentPhase != DreamCataclysmPhase.AwaitingAdmin)
				{
					__result = "<color=#b9dfff><size=22>Traumportal</size></color>\n<color=#c8a8ff>Versiegelt bis zum vollstaendigen Ende der alten Welt</color>";
					return;
				}
				string text = ((DreamBridgeRuntime.CurrentRole == DreamWorldRole.Server3Dream) ? DreamBridgeRuntime.ReturnDestinationLabel() : "die alte Traumwelt");
				__result = "<color=#b9dfff><size=22>Traumportal</size></color>\n<color=#c8a8ff>Eine Bruecke zwischen Erinnerung und Gegenwart</color>\n[<color=#ffff00><b>" + DreamBridgeInputHints.UseKey() + "</b></color>] Nach " + text;
			}
		}
	}
	[HarmonyPatch]
	internal static class DreamArchiveInteractPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			HashSet<MethodBase> hashSet = new HashSet<MethodBase>();
			Type[] array = new Type[2]
			{
				typeof(Humanoid),
				typeof(Player)
			};
			foreach (Type type in array)
			{
				MethodInfo[] methods;
				try
				{
					methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
					continue;
				}
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					if (!(methodInfo == null) && (string.Equals(methodInfo.Name, "Interact", StringComparison.Ordinal) || methodInfo.Name.EndsWith(".Interact", StringComparison.Ordinal)))
					{
						ParameterInfo[] parameters;
						try
						{
							parameters = methodInfo.GetParameters();
						}
						catch
						{
							continue;
						}
						if (parameters.Any((ParameterInfo parameter) => parameter.ParameterType == typeof(GameObject)))
						{
							hashSet.Add(methodInfo);
						}
					}
				}
			}
			return hashSet;
		}

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(Humanoid __instance, object[] __args)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val == null || !DreamBridgeRuntime.ShouldBlockPlayer(val))
			{
				return true;
			}
			GameObject val2 = __args?.OfType<GameObject>().FirstOrDefault();
			if (DreamBridgeRuntime.IsDreamPortal(((Object)(object)val2 != (Object)null) ? val2.GetComponentInParent<TeleportWorld>() : null))
			{
				return true;
			}
			DreamBridgeRuntime.ShowReadOnlyMessage();
			return false;
		}
	}
	[HarmonyPatch]
	internal static class DreamArchivePlayerActionPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			List<MethodBase> list = new List<MethodBase>();
			Add(list, typeof(Player), "PlacePiece", "RemovePiece", "AutoPickup");
			Add(list, typeof(Humanoid), "StartAttack", "UseItem", "DropItem", "Pickup");
			Type type = AccessTools.TypeByName("InventoryGui");
			Add(list, type, "DoCrafting", "OnDropOutside");
			return list.Distinct();
		}

		private static void Add(List<MethodBase> result, Type type, params string[] names)
		{
			if (type == null)
			{
				return;
			}
			foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type))
			{
				if (names.Contains(declaredMethod.Name))
				{
					result.Add(declaredMethod);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(object __instance)
		{
			Humanoid val = (Humanoid)((__instance is Humanoid) ? __instance : null);
			bool flag;
			if (val != null)
			{
				Player val2 = (Player)(object)((val is Player) ? val : null);
				if (val2 != null)
				{
					flag = DreamBridgeRuntime.ShouldBlockPlayer(val2);
					goto IL_0023;
				}
			}
			flag = DreamBridgeRuntime.IsArchiveProtected;
			goto IL_0023;
			IL_0023:
			if (!flag)
			{
				return true;
			}
			DreamBridgeRuntime.ShowReadOnlyMessage();
			return false;
		}
	}
	[HarmonyPatch]
	internal static class DreamArchiveKnowledgePatch
	{
		private static readonly HashSet<string> BlockedKnowledgeMethods = new HashSet<string>(StringComparer.Ordinal) { "AddKnownItem", "AddKnownMaterial", "AddKnownRecipe", "AddKnownStation", "AddKnownBiome", "AddKnownText", "UpdateKnownRecipesList" };

		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from method in typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where BlockedKnowledgeMethods.Contains(method.Name)
				select method;
		}

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(Player __instance)
		{
			return !DreamBridgeRuntime.ShouldBlockPlayer(__instance);
		}
	}
	[HarmonyPatch]
	internal static class DreamArchiveDamagePatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			string[] array = new string[7] { "Character", "WearNTear", "Destructible", "MineRock", "MineRock5", "TreeBase", "TreeLog" };
			string[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				Type type = AccessTools.TypeByName(array2[i]);
				if (type == null)
				{
					continue;
				}
				foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type))
				{
					if (declaredMethod.Name == "Damage" || declaredMethod.Name == "RPC_Damage" || declaredMethod.Name == "ApplyDamage")
					{
						yield return declaredMethod;
					}
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(object __instance, object[] __args)
		{
			return !DreamBridgeRuntime.ShouldBlockDamage(__instance, __args);
		}
	}
	[HarmonyPatch]
	internal static class DreamArchiveMutationRpcPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			HashSet<string> names = new HashSet<string>(StringComparer.Ordinal)
			{
				"RPC_Pick", "RPC_PickArea", "RPC_RequestOpen", "RPC_TakeAll", "RPC_UseDoor", "RPC_AddItem", "RPC_AddFuel", "RPC_AddOre", "RPC_EmptyProcessed", "RPC_RemoveDoneItem",
				"RPC_SetText", "RPC_SetTag", "RPC_Attach", "RPC_Detach", "RPC_Pickup"
			};
			string[] array = new string[11]
			{
				"Pickable", "PickableItem", "Container", "Door", "ItemDrop", "CookingStation", "Smelter", "Fermenter", "Bed", "Sign",
				"ItemStand"
			};
			string[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				Type type = AccessTools.TypeByName(array2[i]);
				if (type == null)
				{
					continue;
				}
				foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type))
				{
					if (names.Contains(declaredMethod.Name))
					{
						yield return declaredMethod;
					}
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(object[] __args)
		{
			return !DreamBridgeRuntime.ShouldBlockSender(__args);
		}
	}
	internal enum DreamWorldRole
	{
		None,
		Server2,
		Server3Dream,
		Server3Finale
	}
	internal sealed class DreamBridgeBehaviour : MonoBehaviour
	{
		private float _nextPortalCheck;

		private float _nextDreamEnforcement;

		private float _nextDreamPositionCheckpoint;

		private float _nextHint;

		private float _nextDreamAnnouncement;

		private bool _travelling;

		private bool _arrivalHandled;

		private bool _returnArrivalHandled;

		private DreamWorldRole _travelTarget;

		private float _transitionAlpha;

		private float _transitionStartedAt;

		private float _transitionFadeStartedAt = -1f;

		private Texture2D _dreamOverlay;

		private Texture2D _transitionImage;

		private bool _transitionImageLoadAttempted;

		private bool _transitionAudioMuted;

		private float _previousAudioVolume = 1f;

		private GUIStyle _dreamStyle;

		private GUIStyle _transitionTitleStyle;

		private GUIStyle _transitionHintStyle;

		private void Awake()
		{
			DreamBridgeRuntime.LoadSession();
		}

		private void Update()
		{
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Enabled == null || !Plugin.Enabled.Value)
			{
				return;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			UpdateTransition(realtimeSinceStartup);
			if (DreamBridgeRuntime.IsServerAuthority())
			{
				DreamBridgeRuntime.AdvancePortalCatalog();
			}
			if (realtimeSinceStartup >= _nextPortalCheck)
			{
				_nextPortalCheck = realtimeSinceStartup + 2f;
				DreamBridgeRuntime.RegisterNetworkRpc();
				DreamBridgeRuntime.DecorateLoadedDreamPortals();
				if (DreamBridgeRuntime.IsServerAuthority())
				{
					DreamBridgeRuntime.EnsureStoneCirclePortal();
				}
			}
			if ((Object)(object)Player.m_localPlayer != (Object)null && DreamBridgeRuntime.ShouldPlaceReturnAtDreamPortal())
			{
				if (!_returnArrivalHandled)
				{
					_returnArrivalHandled = true;
					((MonoBehaviour)this).StartCoroutine(PlaceReturnBehindDreamPortal());
				}
				return;
			}
			if (DreamBridgeRuntime.CurrentRole != DreamWorldRole.Server2)
			{
				_returnArrivalHandled = false;
			}
			if (!DreamBridgeRuntime.IsLocalDreamVisitor)
			{
				_arrivalHandled = false;
				return;
			}
			if (realtimeSinceStartup >= _nextDreamAnnouncement)
			{
				_nextDreamAnnouncement = realtimeSinceStartup + 2f;
				DreamBridgeRuntime.AnnounceLocalDreamVisitor();
			}
			if (realtimeSinceStartup >= _nextDreamEnforcement)
			{
				_nextDreamEnforcement = realtimeSinceStartup + 0.1f;
				DreamBridgeRuntime.EnforceGroundedDreamState(Player.m_localPlayer);
			}
			if (realtimeSinceStartup >= _nextDreamPositionCheckpoint && DreamBridgeRuntime.CanSaveDreamPoint())
			{
				_nextDreamPositionCheckpoint = realtimeSinceStartup + 10f;
				DreamBridgeRuntime.SaveLastDreamPoint(Player.m_localPlayer, writeLog: false);
			}
			if (!_travelling && !DreamCataclysmFeature.IsSequenceActive && (Object)(object)Player.m_localPlayer != (Object)null && Plugin.WakeUpShortcut != null)
			{
				KeyboardShortcut value = Plugin.WakeUpShortcut.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "Du wachst in der Gegenwart auf ...", 0, (Sprite)null);
					BeginTravel(Player.m_localPlayer);
					return;
				}
			}
			if (!_arrivalHandled && (Object)(object)Player.m_localPlayer != (Object)null && DreamBridgeRuntime.ShouldPlaceDreamArrival())
			{
				_arrivalHandled = true;
				((MonoBehaviour)this).StartCoroutine(PlaceDreamArrival());
			}
			if ((Object)(object)Player.m_localPlayer != (Object)null && realtimeSinceStartup >= _nextHint)
			{
				_nextHint = realtimeSinceStartup + 12f;
				((Character)Player.m_localPlayer).Message((MessageType)1, "Du wandelst passiv durch die Traumwelt. " + WakeUpKeyLabel() + " weckt dich auf " + DreamBridgeRuntime.ReturnDestinationLabel() + ".", 0, (Sprite)null);
			}
		}

		private static string WakeUpKeyLabel()
		{
			//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)
			if (Plugin.WakeUpShortcut == null)
			{
				return "Z";
			}
			return ((object)Plugin.WakeUpShortcut.Value/*cast due to .constrained prefix*/).ToString();
		}

		internal void BeginTravel(Player player, bool forceSiegreicheIntro = false)
		{
			if (_travelling || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			DreamWorldRole currentRole = DreamBridgeRuntime.CurrentRole;
			if (currentRole != DreamWorldRole.Server2 && currentRole != DreamWorldRole.Server3Dream && currentRole != DreamWorldRole.Server3Finale)
			{
				return;
			}
			if (currentRole == DreamWorldRole.Server3Finale && DreamCataclysmFeature.CurrentPhase != DreamCataclysmPhase.AwaitingAdmin)
			{
				((Character)player).Message((MessageType)2, "Das Traumportal bleibt versiegelt, bis das Ende der alten Welt vollstaendig eingetreten ist.", 0, (Sprite)null);
				return;
			}
			if (currentRole == DreamWorldRole.Server3Dream)
			{
				DreamBridgeRuntime.SaveLastDreamPoint(player);
			}
			DreamWorldRole returnTarget = DreamWorldRole.None;
			if (currentRole == DreamWorldRole.Server3Dream)
			{
				_travelTarget = DreamBridgeRuntime.ResolveDreamReturnTarget();
			}
			else
			{
				_travelTarget = DreamWorldRole.Server3Dream;
				returnTarget = currentRole;
			}
			_travelling = true;
			_transitionAlpha = 1f;
			_transitionStartedAt = Time.realtimeSinceStartup;
			_transitionFadeStartedAt = -1f;
			MuteTransitionAudio();
			((MonoBehaviour)this).StartCoroutine(Travel(_travelTarget, forceSiegreicheIntro, returnTarget));
		}

		private void UpdateTransition(float now)
		{
			if (!_travelling)
			{
				return;
			}
			if (_transitionFadeStartedAt >= 0f)
			{
				_transitionAlpha = 1f - Mathf.Clamp01((now - _transitionFadeStartedAt) / 1.35f);
				if (_transitionAlpha <= 0.001f)
				{
					CancelTransition();
				}
			}
			else if (now - _transitionStartedAt > 180f)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"Traum-Ladebild nach Zeitlimit freigegeben.");
				}
				CancelTransition();
			}
		}

		private void BeginTransitionReveal()
		{
			if (_transitionFadeStartedAt < 0f)
			{
				_transitionFadeStartedAt = Time.realtimeSinceStartup;
			}
		}

		private void CancelTransition()
		{
			_travelling = false;
			_travelTarget = DreamWorldRole.None;
			_transitionAlpha = 0f;
			_transitionFadeStartedAt = -1f;
			RestoreTransitionAudio();
		}

		private void MuteTransitionAudio()
		{
			if (_transitionAudioMuted)
			{
				return;
			}
			try
			{
				Type type = AccessTools.TypeByName("UnityEngine.AudioListener");
				PropertyInfo propertyInfo = ((type != null) ? AccessTools.Property(type, "volume") : null);
				if (!(propertyInfo == null))
				{
					_previousAudioVolume = Convert.ToSingle(propertyInfo.GetValue(null, null), CultureInfo.InvariantCulture);
					propertyInfo.SetValue(null, 0f, null);
					_transitionAudioMuted = true;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Traumreise konnte Audio nicht stummschalten: " + ex.Message));
				}
			}
		}

		private void RestoreTransitionAudio()
		{
			if (_transitionAudioMuted)
			{
				try
				{
					Type type = AccessTools.TypeByName("UnityEngine.AudioListener");
					((type != null) ? AccessTools.Property(type, "volume") : null)?.SetValue(null, _previousAudioVolume, null);
				}
				catch
				{
				}
				_transitionAudioMuted = false;
			}
		}

		private unsafe IEnumerator PlaceDreamArrival()
		{
			yield return (object)new WaitForSeconds(2f);
			Player player = Player.m_localPlayer;
			if ((Object)(object)player == (Object)null)
			{
				CancelTransition();
				yield break;
			}
			DreamBridgeRuntime.EnforceGroundedDreamState(player);
			string arrivalDescription;
			if (DreamBridgeRuntime.TryGetLastDreamPoint(player, out var target, out var rotation))
			{
				arrivalDescription = "an deinem zuletzt besuchten Ort";
			}
			else
			{
				target = DreamBridgeRuntime.StoneCirclePosition() + new Vector3(0f, 0.2f, 4f);
				rotation = Quaternion.identity;
				arrivalDescription = "am Start-Steinkreis";
			}
			if (TryStartArrivalTeleport(player, target, rotation))
			{
				float settleDeadline = Time.realtimeSinceStartup + 25f;
				yield return null;
				while ((Object)(object)player != (Object)null && ((Character)player).IsTeleporting() && Time.realtimeSinceStartup < settleDeadline)
				{
					yield return null;
				}
				yield return (object)new WaitForSeconds(0.35f);
				DreamBridgeRuntime.MarkArrivalPlaced();
				DreamBridgeRuntime.SaveLastDreamPoint(player, writeLog: false);
				BeginTransitionReveal();
				((Character)player).Message((MessageType)2, "Du betrittst den Traum " + arrivalDescription + ".\nNur schauen. Nichts beruehren.", 0, (Sprite)null);
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					string text = arrivalDescription;
					Vector3 val = target;
					log.LogInfo((object)("Traumankunft " + text + " @ " + ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString()));
				}
			}
		}

		private bool TryStartArrivalTeleport(Player player, Vector3 target, Quaternion rotation)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				((Character)player).TeleportTo(target, rotation, true);
				return true;
			}
			catch (Exception ex)
			{
				CancelTransition();
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Traumankunft konnte nicht versetzt werden: " + ex.Message));
				}
				return false;
			}
		}

		private unsafe IEnumerator PlaceReturnBehindDreamPortal()
		{
			yield return (object)new WaitForSeconds(2f);
			Player player = Player.m_localPlayer;
			if ((Object)(object)player == (Object)null)
			{
				CancelTransition();
				yield break;
			}
			Vector3 stoneCircle = DreamBridgeRuntime.StoneCirclePosition();
			Vector3 target = stoneCircle + new Vector3(0f, 0.2f, 4f);
			if (!TryStartArrivalTeleport(player, target, Quaternion.identity))
			{
				yield break;
			}
			float loadingDeadline = Time.realtimeSinceStartup + 25f;
			yield return null;
			while ((Object)(object)player != (Object)null && ((Character)player).IsTeleporting() && Time.realtimeSinceStartup < loadingDeadline)
			{
				yield return null;
			}
			TeleportWorld dreamPortal = null;
			float portalDeadline = Time.realtimeSinceStartup + 30f;
			while ((Object)(object)player != (Object)null && Time.realtimeSinceStartup < portalDeadline)
			{
				dreamPortal = DreamBridgeRuntime.FindVisibleDreamPortalNear(stoneCircle, 18f);
				if ((Object)(object)dreamPortal != (Object)null)
				{
					break;
				}
				yield return null;
			}
			if ((Object)(object)dreamPortal == (Object)null)
			{
				CancelTransition();
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Aufwachen abgebrochen: sichtbares Traumportal am Steinkreis von " + DreamBridgeRuntime.ReturnDestinationLabel() + " nicht gefunden."));
				}
				((Character)player).Message((MessageType)2, "Das Traumportal ist noch verborgen. Versuche die Rueckkehr erneut.", 0, (Sprite)null);
				yield break;
			}
			Quaternion rotation = ((Component)dreamPortal).transform.rotation;
			Vector3 target2 = DreamBridgeRuntime.PortalExitPosition(dreamPortal);
			if (TryStartArrivalTeleport(player, target2, rotation))
			{
				float settleDeadline = Time.realtimeSinceStartup + 12f;
				yield return null;
				while ((Object)(object)player != (Object)null && ((Character)player).IsTeleporting() && Time.realtimeSinceStartup < settleDeadline)
				{
					yield return null;
				}
				DreamBridgeRuntime.MarkReturnPlaced();
				BeginTransitionReveal();
				((Character)player).Message((MessageType)2, "Du erwachst am Ausgang des Traumportals in der Gegenwart.", 0, (Sprite)null);
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					string text = DreamBridgeRuntime.ReturnDestinationLabel();
					Vector3 val = target2;
					log2.LogInfo((object)("Aufwachen am regulaeren Ausgang des sichtbaren Traumportals auf " + text + " @ " + ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString()));
				}
			}
		}

		private IEnumerator Travel(DreamWorldRole targetRole, bool forceSiegreicheIntro, DreamWorldRole returnTarget)
		{
			Player player = Player.m_localPlayer;
			string text = ((targetRole == DreamWorldRole.Server3Dream) ? "die alte Welt" : DreamBridgeRuntime.RoleLabel(targetRole));
			if (player != null)
			{
				((Character)player).Message((MessageType)2, "Der Traum zieht dich nach " + text + " ...", 0, (Sprite)null);
			}
			DreamBridgeRuntime.AuthorizeTravel(targetRole, returnTarget, forceSiegreicheIntro);
			yield return (object)new WaitForSeconds(1.5f);
			try
			{
				if ((Object)(object)Game.instance == (Object)null)
				{
					throw new InvalidOperationException("Game ist nicht bereit.");
				}
				Game.instance.SavePlayerProfile(true);
				Game.instance.Logout(true, true);
			}
			catch (Exception ex)
			{
				CancelTransition();
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("Traumreise konnte die aktuelle Welt nicht verlassen: " + ex));
				}
				if (player != null)
				{
					((Character)player).Message((MessageType)2, "Die Traumreise ist abgebrochen.", 0, (Sprite)null);
				}
				yield break;
			}
			float deadline = Time.realtimeSinceStartup + 45f;
			FejdStartup startup = null;
			while (Time.realtimeSinceStartup < deadline)
			{
				try
				{
					Scene activeScene = SceneManager.GetActiveScene();
					if (string.Equals(((Scene)(ref activeScene)).name, "start", StringComparison.OrdinalIgnoreCase))
					{
						startup = Object.FindFirstObjectByType<FejdStartup>();
					}
				}
				catch
				{
				}
				if ((Object)(object)startup != (Object)null)
				{
					break;
				}
				yield return null;
			}
			if ((Object)(object)startup == (Object)null)
			{
				CancelTransition();
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)"Traumreise: Hauptmenue wurde nicht rechtzeitig bereit.");
				}
				yield break;
			}
			yield return (object)new WaitForSeconds(0.75f);
			try
			{
				DreamBridgeRuntime.JoinTarget(startup, targetRole);
			}
			catch (Exception ex2)
			{
				CancelTransition();
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogError((object)("Traumreise-Direktbeitritt fehlgeschlagen: " + ex2));
				}
			}
		}

		private void OnGUI()
		{
			//IL_0047: 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_00ac: 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_014a: 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_00da: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			if (_transitionAlpha > 0.001f)
			{
				DrawTransitionOverlay();
			}
			else if (Plugin.DreamVisuals != null && Plugin.DreamVisuals.Value && DreamBridgeRuntime.IsLocalDreamVisitor && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				EnsureDreamOverlayTextures();
				int depth = GUI.depth;
				Color color = GUI.color;
				GUI.depth = -30000;
				float realtimeSinceStartup = Time.realtimeSinceStartup;
				float num = 0.82f + Mathf.Sin(realtimeSinceStartup * 0.55f) * 0.18f;
				Rect val = new Rect(0f, 0f, (float)Screen.width, (float)Screen.height);
				GUI.color = new Color(1f, 1f, 1f, 0.88f + num * 0.12f);
				GUI.DrawTexture(val, (Texture)(object)_dreamOverlay, (ScaleMode)0);
				if (_dreamStyle == null)
				{
					_dreamStyle = new GUIStyle(GUI.skin.label)
					{
						alignment = (TextAnchor)1,
						fontSize = 19,
						fontStyle = (FontStyle)2
					};
					_dreamStyle.normal.textColor = new Color(0.78f, 0.88f, 1f, 0.84f);
				}
				GUI.color = Color.white;
				GUI.Label(new Rect((float)Screen.width * 0.2f, 14f, (float)Screen.width * 0.6f, 34f), "TRAUMWELT  •  nur betrachten  •  " + WakeUpKeyLabel() + " zum Aufwachen", _dreamStyle);
				GUI.color = color;
				GUI.depth = depth;
			}
		}

		private void EnsureDreamOverlayTextures()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: 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_017f: 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_018d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_dreamOverlay == (Object)null))
			{
				return;
			}
			_dreamOverlay = new Texture2D(256, 144, (TextureFormat)4, false);
			Color[] array = (Color[])(object)new Color[36864];
			for (int i = 0; i < 144; i++)
			{
				float num = Mathf.Abs((float)i / 143f * 2f - 1f);
				float num2 = Mathf.Sin((float)i / 143f * (float)Math.PI);
				for (int j = 0; j < 256; j++)
				{
					float num3 = Mathf.Abs((float)j / 255f * 2f - 1f);
					float num4 = Mathf.PerlinNoise((float)j * 0.032f, (float)i * 0.055f);
					float num5 = 0.5f + 0.5f * Mathf.Sin((float)j * 0.045f + (float)i * 0.075f);
					float num6 = Mathf.Clamp01((num4 * 0.72f + num5 * 0.28f - 0.48f) * 1.35f) * num2;
					float num7 = Mathf.Pow(Mathf.Clamp01((Mathf.Sqrt(num3 * num3 + num * num) - 0.38f) / 0.8f), 1.55f);
					float num8 = Mathf.Clamp01(0.075f + num6 * 0.14f + num7 * 0.62f);
					Color val = Color.Lerp(new Color(0.42f, 0.58f, 0.96f), new Color(0.035f, 0.012f, 0.1f), num7 * 0.9f);
					array[i * 256 + j] = new Color(val.r, val.g, val.b, num8);
				}
			}
			_dreamOverlay.SetPixels(array);
			((Texture)_dreamOverlay).wrapMode = (TextureWrapMode)1;
			_dreamOverlay.Apply(false, true);
		}

		private void DrawTransitionOverlay()
		{
			//IL_000b: 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_0089: 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_0064: 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_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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_00ed: Expected O, but got Unknown
			//IL_010c: 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_0126: 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_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Expected O, but got Unknown
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			EnsureTransitionImage();
			int depth = GUI.depth;
			Color color = GUI.color;
			GUI.depth = -32000;
			GUI.color = new Color(1f, 1f, 1f, _transitionAlpha);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(0f, 0f, (float)Screen.width, (float)Screen.height);
			if ((Object)(object)_transitionImage != (Object)null)
			{
				GUI.DrawTexture(val, (Texture)(object)_transitionImage, (ScaleMode)1, false);
			}
			else
			{
				GUI.color = new Color(0.025f, 0.035f, 0.09f, _transitionAlpha);
				GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture, (ScaleMode)0);
			}
			if (_transitionTitleStyle == null)
			{
				_transitionTitleStyle = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					fontSize = Mathf.Clamp(Mathf.RoundToInt((float)Screen.height * 0.034f), 22, 44),
					fontStyle = (FontStyle)1
				};
				_transitionTitleStyle.normal.textColor = new Color(0.88f, 0.95f, 1f, 0.96f);
				_transitionHintStyle = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					fontSize = Mathf.Clamp(Mathf.RoundToInt((float)Screen.height * 0.021f), 15, 28),
					fontStyle = (FontStyle)2
				};
				_transitionHintStyle.normal.textColor = new Color(0.73f, 0.85f, 1f, 0.9f);
			}
			float num = 0.72f + Mathf.Sin(Time.realtimeSinceStartup * 2.2f) * 0.18f;
			GUI.color = new Color(1f, 1f, 1f, _transitionAlpha * num);
			GUI.Label(new Rect(0f, (float)Screen.height - 128f, (float)Screen.width, 50f), "DER TRAUM TRAEGT DICH", _transitionTitleStyle);
			int count = 1 + Mathf.FloorToInt(Time.realtimeSinceStartup * 1.5f) % 3;
			GUI.Label(new Rect(0f, (float)Screen.height - 82f, (float)Screen.width, 34f), "Die Welten gleiten ineinander" + new string('.', count), _transitionHintStyle);
			GUI.color = color;
			GUI.depth = depth;
		}

		private void EnsureTransitionImage()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			if ((Object)(object)_transitionImage != (Object)null || _transitionImageLoadAttempted)
			{
				return;
			}
			_transitionImageLoadAttempted = true;
			try
			{
				using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ChallengeHubDreamBridge.Assets.dream-transition.png");
				if (stream == null)
				{
					throw new InvalidOperationException("Eingebettetes Traum-Ladebild fehlt.");
				}
				byte[] array = new byte[checked((int)stream.Length)];
				int num;
				for (int i = 0; i < array.Length; i += num)
				{
					num = stream.Read(array, i, array.Length - i);
					if (num <= 0)
					{
						break;
					}
				}
				_transitionImage = new Texture2D(2, 2, (TextureFormat)4, false);
				Type type = AccessTools.TypeByName("UnityEngine.ImageConversion");
				MethodInfo methodInfo = ((type != null) ? AccessTools.GetDeclaredMethods(type).FirstOrDefault(delegate(MethodInfo method)
				{
					ParameterInfo[] parameters = method.GetParameters();
					return method.Name == "LoadImage" && parameters.Length == 3 && parameters[0].ParameterType == typeof(Texture2D) && parameters[1].ParameterType == typeof(byte[]) && parameters[2].ParameterType == typeof(bool);
				}) : null);
				object obj = ((methodInfo != null) ? methodInfo.Invoke(null, new object[3] { _transitionImage, array, true }) : null);
				if (!(obj is bool) || !(bool)obj)
				{
					throw new InvalidOperationException("Traum-Ladebild konnte nicht dekodiert werden.");
				}
				((Texture)_transitionImage).wrapMode = (TextureWrapMode)1;
			}
			catch (Exception ex)
			{
				if ((Object)(object)_transitionImage != (Object)null)
				{
					Object.Destroy((Object)(object)_transitionImage);
				}
				_transitionImage = null;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Traum-Ladebild nicht verfuegbar: " + ex.Message));
				}
			}
		}

		private void OnDestroy()
		{
			RestoreTransitionAudio();
			if ((Object)(object)_dreamOverlay != (Object)null)
			{
				Object.Destroy((Object)(object)_dreamOverlay);
			}
			if ((Object)(object)_transitionImage != (Object)null)
			{
				Object.Destroy((Object)(object)_transitionImage);
			}
		}
	}
	internal static class DreamBridgeRuntime
	{
		internal const string PortalMarkerField = "ChallengeHub.DreamBridge.Portal";

		internal const string PortalSchemaField = "ChallengeHub.DreamBridge.Schema";

		internal const string PortalSchema = "1";

		private const string LastDreamPointCustomDataKey = "ChallengeHub.DreamBridge.LastPoint.EventRun2Dream.v1";

		private const string SessionFileName = "ChallengeHubDreamBridge.session";

		private const string DreamVisitorRpc = "ChallengeHub_DreamBridge_VisitorState_v1";

		private static readonly HashSet<int> Decorated = new HashSet<int>();

		private static readonly List<ZDO> PortalCatalog = new List<ZDO>();

		private static readonly HashSet<long> DreamVisitorPeers = new HashSet<long>();

		private static readonly HashSet<long> DreamVisitorPlayerIds = new HashSet<long>();

		private static ZRoutedRpc _registeredRpc;

		private static float _nextSpawnAttempt;

		private static bool _spawning;

		private static bool _portalCatalogReady;

		private static int _portalCatalogIndex;

		private static string _portalCatalogWorld = string.Empty;

		private static bool _stoneCirclePortalReady;

		private static DreamWorldRole _sessionTarget = DreamWorldRole.None;

		private static DreamWorldRole _sessionReturnTarget = DreamWorldRole.None;

		private static DateTime _sessionExpiresUtc = DateTime.MinValue;

		private static bool _arrivalPending;

		private static bool _sessionLoaded;

		private static bool _dreamConnectionLatched;

		private static bool _finaleConnectionLatched;

		private static bool _forceSiegreicheIntro;

		private static float _lastReadOnlyMessage;

		internal static DreamWorldRole CurrentRole
		{
			get
			{
				string a = RuntimeWorldName();
				if (string.Equals(a, Plugin.MainWorldName?.Value, StringComparison.OrdinalIgnoreCase))
				{
					return DreamWorldRole.Server2;
				}
				if (string.Equals(a, Plugin.FinaleWorldName?.Value, StringComparison.OrdinalIgnoreCase))
				{
					return DreamWorldRole.Server3Finale;
				}
				if (string.Equals(a, Plugin.DreamWorldName?.Value, StringComparison.OrdinalIgnoreCase))
				{
					return DreamWorldRole.Server3Dream;
				}
				if (_dreamConnectionLatched)
				{
					return DreamWorldRole.Server3Dream;
				}
				if (_finaleConnectionLatched)
				{
					return DreamWorldRole.Server3Finale;
				}
				return DreamWorldRole.None;
			}
		}

		internal static bool IsLocalDreamVisitor
		{
			get
			{
				if (Plugin.Enabled != null && Plugin.Enabled.Value && CurrentRole == DreamWorldRole.Server3Dream)
				{
					return IsAuthorizedDreamArrival();
				}
				return false;
			}
		}

		internal static bool IsArchiveProtected
		{
			get
			{
				if (!DreamCataclysmFeature.CombatEnabled && Plugin.ArchiveReadOnly != null && Plugin.ArchiveReadOnly.Value)
				{
					return IsLocalDreamVisitor;
				}
				return false;
			}
		}

		internal static bool IsServerAuthority()
		{
			try
			{
				return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer();
			}
			catch
			{
				return false;
			}
		}

		internal static void RegisterNetworkRpc()
		{
			try
			{
				if (ZRoutedRpc.instance != null && _registeredRpc != ZRoutedRpc.instance)
				{
					_registeredRpc = ZRoutedRpc.instance;
					_registeredRpc.Register<ZPackage>("ChallengeHub_DreamBridge_VisitorState_v1", (Action<long, ZPackage>)RpcDreamVisitorState);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Traumportal-Netzwerk konnte noch nicht registriert werden: " + ex.Message));
				}
			}
		}

		internal static void AnnounceLocalDreamVisitor()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			if (!IsLocalDreamVisitor || (Object)(object)Player.m_localPlayer == (Object)null || ZRoutedRpc.instance == null)
			{
				return;
			}
			try
			{
				ZPackage val = new ZPackage();
				val.Write(Player.m_localPlayer.GetPlayerID());
				if (IsServerAuthority())
				{
					RpcDreamVisitorState(0L, val);
					return;
				}
				long num = ResolveServerPeerId();
				if (num != 0L)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(num, "ChallengeHub_DreamBridge_VisitorState_v1", new object[1] { val });
				}
			}
			catch
			{
			}
		}

		private static void RpcDreamVisitorState(long sender, ZPackage package)
		{
			if (!IsServerAuthority() || CurrentRole != DreamWorldRole.Server3Dream || package == null)
			{
				return;
			}
			try
			{
				long playerId = package.ReadLong();
				Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player candidate) => (Object)(object)candidate != (Object)null && candidate.GetPlayerID() == playerId));
				if (!((Object)(object)val == (Object)null))
				{
					ZNetView component = ((Component)val).GetComponent<ZNetView>();
					ZDO val2 = ((component != null) ? component.GetZDO() : null);
					if (sender == 0L || (val2 != null && val2.GetOwner() == sender))
					{
						DreamVisitorPeers.Add(sender);
						DreamVisitorPlayerIds.Add(playerId);
					}
				}
			}
			catch
			{
			}
		}

		internal static bool ShouldBlockPlayer(Player player)
		{
			if (DreamCataclysmFeature.CombatEnabled)
			{
				return false;
			}
			if (Plugin.ArchiveReadOnly == null || !Plugin.ArchiveReadOnly.Value || CurrentRole != DreamWorldRole.Server3Dream || (Object)(object)player == (Object)null)
			{
				return false;
			}
			if (!IsServerAuthority())
			{
				if ((Object)(object)player == (Object)(object)Player.m_localPlayer)
				{
					return IsLocalDreamVisitor;
				}
				return false;
			}
			try
			{
				if (DreamVisitorPlayerIds.Contains(player.GetPlayerID()))
				{
					return true;
				}
				ZNetView component = ((Component)player).GetComponent<ZNetView>();
				long? obj;
				if (component == null)
				{
					obj = null;
				}
				else
				{
					ZDO zDO = component.GetZDO();
					obj = ((zDO != null) ? new long?(zDO.GetOwner()) : ((long?)null));
				}
				long? num = obj;
				long valueOrDefault = num.GetValueOrDefault();
				return valueOrDefault != 0L && DreamVisitorPeers.Contains(valueOrDefault);
			}
			catch
			{
				return false;
			}
		}

		internal static bool ShouldBlockSender(object[] arguments)
		{
			if (DreamCataclysmFeature.CombatEnabled)
			{
				return false;
			}
			if (!IsServerAuthority() || CurrentRole != DreamWorldRole.Server3Dream || arguments == null)
			{
				return false;
			}
			for (int i = 0; i < arguments.Length; i++)
			{
				if (arguments[i] is long item && DreamVisitorPeers.Contains(item))
				{
					return true;
				}
			}
			return false;
		}

		internal static bool ShouldBlockDamage(object target, object[] arguments)
		{
			if (DreamCataclysmFeature.CombatEnabled)
			{
				return false;
			}
			if (Plugin.ArchiveReadOnly == null || !Plugin.ArchiveReadOnly.Value || CurrentRole != DreamWorldRole.Server3Dream)
			{
				return false;
			}
			Player val = (Player)((target is Player) ? target : null);
			if (val != null && ShouldBlockPlayer(val))
			{
				return true;
			}
			HitData val2 = arguments?.OfType<HitData>().FirstOrDefault();
			if (val2 == null)
			{
				return false;
			}
			try
			{
				Character attacker = val2.GetAttacker();
				Player val3 = (Player)(object)((attacker is Player) ? attacker : null);
				return (Object)(object)val3 != (Object)null && ShouldBlockPlayer(val3);
			}
			catch
			{
				return false;
			}
		}

		internal static void AdvancePortalCatalog()
		{
			if (!IsServerAuthority() || ZDOMan.instance == null || CurrentRole == DreamWorldRole.None)
			{
				return;
			}
			string text = RuntimeWorldName();
			if (!string.Equals(_portalCatalogWorld, text, StringComparison.Ordinal))
			{
				_portalCatalogWorld = text;
				_portalCatalogReady = false;
				_portalCatalogIndex = 0;
				_stoneCirclePortalReady = false;
				PortalCatalog.Clear();
			}
			if (_portalCatalogReady)
			{
				return;
			}
			try
			{
				if (ZDOMan.instance.GetAllZDOsWithPrefabIterative("portal_wood", PortalCatalog, ref _portalCatalogIndex))
				{
					_portalCatalogReady = true;
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)("Traumportal-Katalog bereit: " + PortalCatalog.Count + " Holzportale in " + text + "."));
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Traumportal-Katalogisierung fehlgeschlagen und wird neu begonnen: " + ex.Message));
				}
				_portalCatalogIndex = 0;
				PortalCatalog.Clear();
			}
		}

		internal static List<DreamTourStop> BuildBaseTour(Vector3 origin, float hubRadius, int expectedCount)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (!IsServerAuthority() || CurrentRole != DreamWorldRole.Server3Finale || !_portalCatalogReady || ZDOMan.instance == null || expectedCount != 6)
			{
				return new List<DreamTourStop>();
			}
			return BuildBaseTourNear(origin, hubRadius, expectedCount);
		}

		private static List<DreamTourStop> BuildBaseTourNear(Vector3 origin, float hubRadius, int expectedCount)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: 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)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<int, DreamTourStop> selected = new Dictionary<int, DreamTourStop>();
			string[] array = new string[6] { "Wiesen", "Schwarzwald", "Sumpf", "Berge", "Ebenen", "Ashlands" };
			string[] array2 = new string[6] { "Eikthyr", "Der Uralte", "Knochenwanst", "Moder", "Yagluth", "Fader" };
			string[] array3 = new string[6] { "Eikthyr", "gd_king", "Bonemass", "Dragon", "GoblinKing", "Fader" };
			selected[0] = new DreamTourStop
			{
				Label = "Graslandbasis",
				BiomeLabel = array[0],
				BossLabel = array2[0],
				BossPrefab = array3[0],
				SecondBossLabel = string.Empty,
				SecondBossPrefab = string.Empty,
				Position = origin,
				Rotation = Quaternion.identity
			};
			List<string> list = new List<string>();
			foreach (IGrouping<string, ZDO> item in PortalCatalog.Where((ZDO zdo) => zdo != null && zdo.IsValid() && !IsDreamPortalZdo(zdo) && !string.IsNullOrWhiteSpace(zdo.GetString("tag", string.Empty))).GroupBy<ZDO, string>((ZDO zdo) => zdo.GetString("tag", string.Empty).Trim(), StringComparer.OrdinalIgnoreCase).ToList())
			{
				string key = item.Key;
				int num = PortalBiomeOrder(key);
				if (num < 1 || num >= expectedCount)
				{
					continue;
				}
				list.Add(key);
				ZDO hub = item.OrderBy((ZDO zdo) => HorizontalDistanceSquared(zdo.GetPosition(), origin)).FirstOrDefault();
				if (hub == null)
				{
					continue;
				}
				ZDO val = null;
				try
				{
					ZDOID connectionZDOID = hub.GetConnectionZDOID((ConnectionType)1);
					if (!((ZDOID)(ref connectionZDOID)).IsNone())
					{
						val = ZDOMan.instance.GetZDO(connectionZDOID);
					}
				}
				catch
				{
				}
				if (val == null || !val.IsValid() || val.m_uid == hub.m_uid)
				{
					val = (from zdo in item
						where zdo != null && zdo.IsValid() && zdo.m_uid != hub.m_uid
						orderby HorizontalDistanceSquared(zdo.GetPosition(), origin) descending
						select zdo).FirstOrDefault();
				}
				if (val != null && val.IsValid())
				{
					Quaternion rotation = val.GetRotation();
					Vector3 position = val.GetPosition() + rotation * Vector3.forward * 7f + Vector3.up;
					DreamTourStop value = new DreamTourStop
					{
						Label = key,
						BiomeLabel = array[num],
						BossLabel = array2[num],
						BossPrefab = array3[num],
						SecondBossLabel = ((num == 5) ? "Die Koenigin" : string.Empty),
						SecondBossPrefab = ((num == 5) ? "SeekerQueen" : string.Empty),
						Position = position,
						Rotation = rotation
					};
					float num2 = HorizontalDistanceSquared(hub.GetPosition(), origin);
					if (!selected.TryGetValue(num, out var value2) || num2 < HorizontalDistanceSquared(value2.Position, origin))
					{
						selected[num] = value;
					}
				}
			}
			if (selected.Count != expectedCount)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Dreamquake-Basisportale unvollstaendig. Erkannte Zielnamen: " + ((list.Count == 0) ? "keine" : string.Join(", ", list.Distinct<string>(StringComparer.OrdinalIgnoreCase))) + "."));
				}
				return new List<DreamTourStop>();
			}
			List<DreamTourStop> list2 = (from order in Enumerable.Range(0, expectedCount)
				select selected[order]).ToList();
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("Dreamquake-Basisportale erkannt: " + string.Join(", ", list2.Select((DreamTourStop stop) => stop.BiomeLabel + "=" + stop.Label)) + "."));
			}
			return list2;
		}

		private unsafe static string PortalConnectionKey(ZDO portal)
		{
			//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_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_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)
			if (portal == null)
			{
				return "ungueltig";
			}
			try
			{
				ZDOID connectionZDOID = portal.GetConnectionZDOID((ConnectionType)1);
				if (!((ZDOID)(ref connectionZDOID)).IsNone())
				{
					ZDOID val = connectionZDOID;
					return "ziel:" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString();
				}
			}
			catch
			{
			}
			string text = portal.GetString("tag", string.Empty);
			if (string.IsNullOrWhiteSpace(text))
			{
				ZDOID val = portal.m_uid;
				return "portal:" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString();
			}
			return "tag:" + text;
		}

		internal static int WorldBiomeOrder(Vector3 position)
		{
			//IL_0014: 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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0024: Invalid comparison between Unknown and I4
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Invalid comparison between Unknown and I4
			//IL_0026: 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_003e: Expected I4, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Invalid comparison between Unknown and I4
			Biome val;
			try
			{
				val = ((WorldGenerator.instance != null) ? WorldGenerator.instance.GetBiome(position) : Heightmap.FindBiome(position));
			}
			catch
			{
				return -1;
			}
			if ((int)val <= 8)
			{
				switch (val - 1)
				{
				default:
					if ((int)val != 8)
					{
						break;
					}
					return 1;
				case 0:
					return 0;
				case 1:
					return 2;
				case 3:
					return 3;
				case 2:
					break;
				}
			}
			else
			{
				if ((int)val == 16)
				{
					return 4;
				}
				if ((int)val == 32)
				{
					return 5;
				}
			}
			return -1;
		}

		private static int PortalBiomeOrder(string value)
		{
			string text = (value ?? string.Empty).ToLowerInvariant();
			if (text.Contains("wies") || text.Contains("meadow") || text.Contains("gras"))
			{
				return 0;
			}
			if (text.Contains("dunkel") || text.Contains("schwarz") || text.Contains("black") || text.Contains("wald"))
			{
				return 1;
			}
			if (text.Contains("sumpf") || text.Contains("swamp"))
			{
				return 2;
			}
			if (text.Contains("berg") || text.Contains("mountain"))
			{
				return 3;
			}
			if (text.Contains("ebene") || text.Contains("plain"))
			{
				return 4;
			}
			if (text.Contains("ash") || text.Contains("asche"))
			{
				return 5;
			}
			return 99;
		}

		private static float HorizontalDistanceSquared(Vector3 left, Vector3 right)
		{
			//IL_0000: 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_000d: 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)
			float num = left.x - right.x;
			float num2 = left.z - right.z;
			return num * num + num2 * num2;
		}

		internal static long ResolveServerPeerId()
		{
			try
			{
				MethodInfo methodInfo = AccessTools.Method(((object)ZRoutedRpc.instance)?.GetType(), "GetServerPeerID", (Type[])null, (Type[])null) ?? AccessTools.Method(((object)ZRoutedRpc.instance)?.GetType(), "GetServerPeerId", (Type[])null, (Type[])null);
				return (methodInfo != null) ? Convert.ToInt64(methodInfo.Invoke(ZRoutedRpc.instance, null), CultureInfo.InvariantCulture) : 0;
			}
			catch
			{
				return 0L;
			}
		}

		internal static string RuntimeWorldName()
		{
			try
			{
				object obj = AccessTools.Property(typeof(ZNet), "World")?.GetValue(null, null);
				if (obj == null)
				{
					return string.Empty;
				}
				FieldInfo fieldInfo = AccessTools.Field(obj.GetType(), "m_fileName");
				string text = ((fieldInfo != null) ? Convert.ToString(fieldInfo.GetValue(obj), CultureInfo.InvariantCulture) : string.Empty);
				if (!string.IsNullOrWhiteSpace(text))
				{
					return text;
				}
				FieldInfo fieldInfo2 = AccessTools.Field(obj.GetType(), "m_name");
				return (fieldInfo2 != null) ? Convert.ToString(fieldInfo2.GetValue(obj), CultureInfo.InvariantCulture) : string.Empty;
			}
			catch
			{
				return string.Empty;
			}
		}

		internal unsafe static void EnsureStoneCirclePortal()
		{
			//IL_0106: 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_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.SpawnAtStoneCircle == null || !Plugin.SpawnAtStoneCircle.Value || (CurrentRole != DreamWorldRole.Server2 && CurrentRole != DreamWorldRole.Server3Dream && CurrentRole != DreamWorldRole.Server3Finale) || _spawning || Time.realtimeSinceStartup < _nextSpawnAttempt || (Object)(object)ZNetScene.instance == (Object)null || ZDOMan.instance == null || (Object)(object)ZoneSystem.instance == (Object)null)
			{
				return;
			}
			_nextSpawnAttempt = Time.realtimeSinceStartup + 10f;
			if (_stoneCirclePortalReady || !_portalCatalogReady)
			{
				return;
			}
			if (((IEnumerable<ZDO>)PortalCatalog).FirstOrDefault((Func<ZDO, bool>)IsDreamPortalZdo) != null)
			{
				_stoneCirclePortalReady = true;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("Persistentes Traumportal im Start-Steinkreis bestaetigt: Welt=" + RuntimeWorldName()));
				}
				return;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab("portal_wood");
			if ((Object)(object)prefab == (Object)null)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)"Traumportal: Vanilla-Prefab portal_wood ist noch nicht verfuegbar.");
				}
				return;
			}
			_spawning = true;
			try
			{
				Vector3 position = StoneCirclePosition();
				position.y += ((Plugin.PortalGroundOffset != null) ? Plugin.PortalGroundOffset.Value : 0.08f);
				ZNetScene.instance.SpawnObject(position, Quaternion.Euler(0f, 180f, 0f), prefab);
				TeleportWorld val = Object.FindObjectsByType<TeleportWorld>((FindObjectsSortMode)0).Where(delegate(TeleportWorld item)
				{
					//IL_000f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0015: Unknown result type (might be due to invalid IL or missing references)
					//IL_001a: Unknown result type (might be due to invalid IL or missing references)
					//IL_001f: Unknown result type (might be due to invalid IL or missing references)
					if ((Object)(object)item != (Object)null)
					{
						Vector3 val4 = ((Component)item).transform.position - position;
						return ((Vector3)(ref val4)).sqrMagnitude <= 9f;
					}
					return false;
				}).OrderBy(delegate(TeleportWorld item)
				{
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					//IL_000c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Unknown result type (might be due to invalid IL or missing references)
					//IL_0016: Unknown result type (might be due to invalid IL or missing references)
					Vector3 val4 = ((Component)item).transform.position - position;
					return ((Vector3)(ref val4)).sqrMagnitude;
				})
					.FirstOrDefault();
				if ((Object)(object)val != (Object)null)
				{
					ConfigureDreamPortal(val);
				}
				object obj;
				if (!((Object)(object)val != (Object)null))
				{
					obj = null;
				}
				else
				{
					ZNetView component = ((Component)val).GetComponent<ZNetView>();
					obj = ((component != null) ? component.GetZDO() : null);
				}
				ZDO val2 = (ZDO)obj;
				if (val2 != null && !PortalCatalog.Contains(val2))
				{
					PortalCatalog.Add(val2);
				}
				_stoneCirclePortalReady = (Object)(object)val != (Object)null;
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					Vector3 val3 = position;
					log3.LogInfo((object)("Traumportal im Mittelpunkt des Start-Steinkreises erzeugt: " + ((object)(*(Vector3*)(&val3))/*cast due to .constrained prefix*/).ToString() + " | Welt=" + RuntimeWorldName()));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogError((object)("Traumportal konnte nicht im Steinkreis erzeugt werden: " + ex));
				}
			}
			finally
			{
				_spawning = false;
			}
		}

		internal static Vector3 StoneCirclePosition()
		{
			//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_0044: 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_0026: 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)
			Vector3 val = Vector3.zero;
			try
			{
				if ((Object)(object)ZoneSystem.instance != (Object)null)
				{
					Vector3 val2 = default(Vector3);
					if (ZoneSystem.instance.GetLocationIcon("StartTemple", ref val2))
					{
						val = val2;
					}
					float y = default(float);
					if (ZoneSystem.instance.GetGroundHeight(val, ref y))
					{
						val.y = y;
					}
				}
			}
			catch
			{
			}
			return val;
		}

		internal static bool IsDreamPortalZdo(ZDO zdo)
		{
			try
			{
				return zdo != null && zdo.IsValid() && zdo.GetBool("ChallengeHub.DreamBridge.Portal", false);
			}
			catch
			{
				return false;
			}
		}

		internal static bool IsDreamPortal(TeleportWorld portal)
		{
			if ((Object)(object)portal == (Object)null)
			{
				return false;
			}
			try
			{
				ZNetView component = ((Component)portal).GetComponent<ZNetView>();
				if (IsDreamPortalZdo((component != null) ? component.GetZDO() : null))
				{
					return true;
				}
				return false;
			}
			catch
			{
				return false;
			}
		}

		internal static TeleportWorld FindVisibleDreamPortalNear(Vector3 expectedPosition, float radius)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				float radiusSquared = radius * radius;
				return Object.FindObjectsByType<TeleportWorld>((FindObjectsSortMode)0).Where(delegate(TeleportWorld portal)
				{
					//IL_0024: Unknown result type (might be due to invalid IL or missing references)
					//IL_002f: Unknown result type (might be due to invalid IL or missing references)
					//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)
					if ((Object)(object)portal != (Object)null && ((Component)portal).gameObject.activeInHierarchy && IsDreamPortal(portal))
					{
						Vector3 val = ((Component)portal).transform.position - expectedPosition;
						return ((Vector3)(ref val)).sqrMagnitude <= radiusSquared;
					}
					return false;
				}).OrderBy(delegate(TeleportWorld portal)
				{
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					//IL_000c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0011: Unknown result type (might be due to invalid IL or missing references)
					//IL_0016: Unknown result type (might be due to invalid IL or missing references)
					Vector3 val = ((Component)portal).transform.position - expectedPosition;
					return ((Vector3)(ref val)).sqrMagnitude;
				})
					.FirstOrDefault();
			}
			catch
			{
				return null;
			}
		}

		internal static Vector3 PortalExitPosition(TeleportWorld portal)
		{
			//IL_0009: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if ((Object)(object)portal == (Object)null)
			{
				return Vector3.zero;
			}
			float num = 2f;
			try
			{
				FieldInfo field = ((object)portal).GetType().GetField("m_exitDistance", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					num = Convert.ToSingle(field.GetValue(portal), CultureInfo.InvariantCulture);
				}
			}
			catch
			{
			}
			return ((Component)portal).transform.position + ((Component)portal).transform.rotation * Vector3.forward * num + Vector3.up;
		}

		private static void ConfigureDreamPortal(TeleportWorld portal)
		{
			if ((Object)(object)portal == (Object)null)
			{
				return;
			}
			try
			{
				ZNetView component = ((Component)portal).GetComponent<ZNetView>();
				ZDO val = ((component != null) ? component.GetZDO() : null);
				if (val == null)
				{
					return;
				}
				val.Set("ChallengeHub.DreamBridge.Portal", true);
				val.Set("ChallengeHub.DreamBridge.Schema", "1");
				val.Set("tag", (Plugin.PortalTag != null) ? Plugin.PortalTag.Value : "TRAUM");
				if (!Application.isBatchMode)
				{
					try
					{
						portal.SetText((Plugin.PortalTag != null) ? Plugin.PortalTag.Value : "TRAUM");
					}
					catch
					{
					}
					EnsureVisual(portal);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Traumportal-Markierung fehlgeschlagen: " + ex.Message));
				}
			}
		}

		internal static void DecorateLoadedDreamPortals()
		{
			if (Plugin.DreamVisuals == null || !Plugin.DreamVisuals.Value)
			{
				return;
			}
			try
			{
				TeleportWorld[] array = Object.FindObjectsByType<TeleportWorld>((FindObjectsSortMode)0);
				foreach (TeleportWorld portal in array)
				{
					if (IsDreamPortal(portal))
					{
						EnsureVisual(portal);
					}
				}
			}
			catch
			{
			}
		}

		private static void EnsureVisual(TeleportWorld portal)
		{
			if ((Object)(object)portal == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)portal).GetInstanceID();
			if (!Decorated.Contains(instanceID) || !((Object)(object)((Component)portal).GetComponent<DreamPortalAura>() != (Object)null))
			{
				Decorated.Add(instanceID);
				if ((Object)(object)((Component)portal).GetComponent<DreamPortalAura>() == (Object)null)
				{
					((Component)portal).gameObject.AddComponent<DreamPortalAura>();
				}
			}
		}

		internal static void EnforceGroundedDreamState(Player player)
		{
			if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer) && IsLocalDreamVisitor)
			{
				SetBool(player, "m_debugFly", value: false);
				if (DreamCataclysmFeature.CombatEnabled)
				{
					SetBool(player, "m_ghostMode", value: false);
					SetBool(player, "m_godMode", value: false);
					SetBool(player, "m_noPlacementCost", value: false);
					SetBool(player, "m_autoPickup", value: true);
				}
				else
				{
					SetBool(player, "m_ghostMode", value: true);
					SetBool(player, "m_godMode", value: true);
					SetBool(player, "m_noPlacementCost", value: false);
					SetBool(player, "m_autoPickup", value: false);
				}
			}
		}

		private static void SetBool(object target, string fieldName, bool value)
		{
			try
			{
				FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null && field.FieldType == typeof(bool))
				{
					field.SetValue(target, value);
				}
			}
			catch
			{
			}
		}

		internal static void ShowReadOnlyMessage()
		{
			if (!(Time.realtimeSinceStartup - _lastReadOnlyMessage < 1.5f))
			{
				_lastReadOnlyMessage = Time.realtimeSinceStartup;
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)2, "Dies ist nur ein Traum. Du kannst die alte Welt nicht veraendern.", 0, (Sprite)null);
				}
			}
		}

		internal static void UsePortal(TeleportWorld portal, Player player)
		{
			if (IsDreamPortal(portal) && !((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer))
			{
				(((Object)(object)Plugin.Instance != (Object)null) ? ((Component)Plugin.Instance).GetComponent<DreamBridgeBehaviour>() : null)?.BeginTravel(player);
			}
		}

		internal static DreamWorldRole ResolveDreamReturnTarget()
		{
			LoadSession();
			if (_sessionReturnTarget == DreamWorldRole.Server2 || _sessionReturnTarget == DreamWorldRole.Server3Finale)
			{
				return _sessionReturnTarget;
			}
			return DreamWorldRole.Server3Finale;
		}

		internal static string RoleLabel(DreamWorldRole role)
		{
			return role switch
			{
				DreamWorldRole.Server2 => "Server2", 
				DreamWorldRole.Server3Finale => "Server3", 
				DreamWorldRole.Server3Dream => "Server4", 
				_ => "die Gegenwart", 
			};
		}

		internal static string ReturnDestinationLabel()
		{
			return RoleLabel(ResolveDreamReturnTarget());
		}

		internal static void AuthorizeTravel(DreamWorldRole target, DreamWorldRole returnTarget = DreamWorldRole.None, bool forceSiegreicheIntro = false)
		{
			_sessionTarget = target;
			if (target == DreamWorldRole.Server3Dream && (returnTarget == DreamWorldRole.Server2 || returnTarget == DreamWorldRole.Server3Finale))
			{
				_sessionReturnTarget = returnTarget;
			}
			_sessionExpiresUtc = DateTime.UtcNow.AddMinutes((target == DreamWorldRole.Server3Dream) ? 20 : 5);
			_arrivalPending = target == DreamWorldRole.Server3Dream || target == DreamWorldRole.Server2 || target == DreamWorldRole.Server3Finale;
			_dreamConnectionLatched = target == DreamWorldRole.Server3Dream;
			if (target == DreamWorldRole.Server3Dream)
			{
				_finaleConnectionLatched = false;
			}
			_forceSiegreicheIntro = target == DreamWorldRole.Server2 && forceSiegreicheIntro;
			SaveSession();
		}

		internal static void LoadSession()
		{
			if (_sessionLoaded)
			{
				return;
			}
			_sessionLoaded = true;
			try
			{
				string path = SessionPath();
				if (File.Exists(path))
				{
					Dictionary<string, string> dictionary = (from line in File.ReadAllLines(path)
						select line.Split(new char[1] { '=' }, 2) into parts
						where parts.Length == 2
						select parts).ToDictionary<string[], string, string>((string[] parts) => parts[0].Trim(), (string[] parts) => parts[1].Trim(), StringComparer.OrdinalIgnoreCase);
					if (dictionary.TryGetValue("Target", out var value))
					{
						Enum.TryParse<DreamWorldRole>(value, ignoreCase: true, out _sessionTarget);
					}
					if (dictionary.TryGetValue("ReturnTarget", out var value2))
					{
						Enum.TryParse<DreamWorldRole>(value2, ignoreCase: true, out _sessionReturnTarget);
					}
					if (dictionary.TryGetValue("ExpiresUtc", out var value3))
					{
						DateTime.TryParse(value3, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out _sessionExpiresUtc);
					}
					if (dictionary.TryGetValue("ArrivalPending", out var value4))
					{
						bool.TryParse(value4, out _arrivalPending);
					}
					if (dictionary.TryGetValue("ForceSiegreicheIntro", out var value5))
					{
						bool.TryParse(value5, out _forceSiegreicheIntro);
					}
					if (_sessionExpiresUtc <= DateTime.UtcNow)
					{
						ClearSession();
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Traumsitzung konnte nicht gelesen werden: " + ex.Message));
				}
			}
		}

		internal static bool IsAuthorizedDreamArrival()
		{
			LoadSession();
			if (_sessionTarget == DreamWorldRole.Server3Dream && _sessionExpiresUtc > DateTime.UtcNow)
			{
				if (!_dreamConnectionLatched)
				{
					return string.Equals(RuntimeWorldName(), Plugin.DreamWorldName?.Value, StringComparison.OrdinalIgnoreCase);
				}
				return true;
			}
			return false;
		}

		internal static bool IsDreamWorldSession()
		{
			if (Plugin.Enabled != null && Plugin.Enabled.Value && !string.IsNullOrWhiteSpace(RuntimeWorldName()))
			{
				return string.Equals(RuntimeWorldName(), Plugin.DreamWorldName?.Value, StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}

		internal static bool ShouldBypassChallengeHubGate()
		{
			if (IsExactDreamEndpoint())
			{
				return true;
			}
			if (IsExactFinaleEndpoint())
			{
				return true;
			}
			if (Plugin.Enabled == null || !Plugin.Enabled.Value)
			{
				return false;
			}
			if (IsDreamWorldSession())
			{
				return true;
			}
			if (_dreamConnectionLatched)
			{
				return true;
			}
			LoadSession();
			if (_sessionTarget == DreamWorldRole.Server3Dream && _arrivalPending && _sessionExpiresUtc > DateTime.UtcNow)
			{
				return true;
			}
			return IsExactDreamEndpoint();
		}

		private static bool IsExactFinaleEndpoint()
		{
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(ZNet), "m_serverHost");
				FieldInfo fieldInfo2 = AccessTools.Field(typeof(ZNet), "m_serverHostPort");
				object obj = ((fieldInfo != null && !fieldInfo.IsStatic) ? ZNet.instance : null);
				object obj2 = ((fieldInfo2 != null && !fieldInfo2.IsStatic) ? ZNet.instance : null);
				string a = ((fieldInfo != null) ? Convert.ToString(fieldInfo.GetValue(obj), CultureInfo.InvariantCulture) : string.Empty);
				int num = ((fieldInfo2 != null) ? Convert.ToInt32(fieldInfo2.GetValue(obj2), CultureInfo.InvariantCulture) : 0);
				int num2;
				if (string.Equals(a, Plugin.FinaleHost?.Value, StringComparison.OrdinalIgnoreCase))
				{
					num2 = ((num == Plugin.FinalePort?.Value) ? 1 : 0);
					if (num2 != 0)
					{
						_finaleConnectionLatched = true;
						_dreamConnectionLatched = false;
					}
				}
				else
				{
					num2 = 0;
				}
				return (byte)num2 != 0;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsExactDreamEndpoint()
		{
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(ZNet), "m_serverHost");
				FieldInfo fieldInfo2 = AccessTools.Field(typeof(ZNet), "m_serverHostPort");
				object obj = ((fieldInfo != null && !fieldInfo.IsStatic) ? ZNet.instance : null);
				object obj2 = ((fieldInfo2 != null && !fieldInfo2.IsStatic) ? ZNet.instance : null);
				string text = ((fieldInfo != null) ? Convert.ToString(fieldInfo.GetValue(obj), CultureInfo.InvariantCulture) : string.Empty);
				int num = ((fieldInfo2 != null) ? Convert.ToInt32(fieldInfo2.GetValue(obj2), CultureInfo.InvariantCulture) : 0);
				int num2;
				if (string.Equals(text, Plugin.DreamHost?.Value, StringComparison.OrdinalIgnoreCase))
				{
					num2 = ((num == Plugin.DreamPort?.Value) ? 1 : 0);
					if (num2 != 0)
					{
						_dreamConnectionLatched = true;
						_finaleConnectionLatched = false;
						goto IL_0117;
					}
				}
				else
				{
					num2 = 0;
				}
				if (!string.IsNullOrWhiteSpace(text) && num > 0)
				{
					_dreamConnectionLatched = false;
				}
				goto IL_0117;
				IL_0117:
				return (byte)num2 != 0;
			}
			catch
			{
				return false;
			}
		}

		internal static bool ShouldPlaceDreamArrival()
		{
			LoadSession();
			if (IsAuthorizedDreamArrival())
			{
				return _arrivalPending;
			}
			return false;
		}

		internal static bool ShouldPlaceReturnAtDreamPortal()
		{
			LoadSession();
			if ((_sessionTarget == DreamWorldRole.Server2 || _sessionTarget == DreamWorldRole.Server3Finale) && _arrivalPending && _sessionExpiresUtc > DateTime.UtcNow)
			{
				return CurrentRole == _sessionTarget;
			}
			return false;
		}

		internal static void MarkReturnPlaced()
		{
			_arrivalPending = false;
			_sessionExpiresUtc = DateTime.UtcNow.AddMinutes(5.0);
			SaveSession();
		}

		internal static void MarkArrivalPlaced()
		{
			_arrivalPending = false;
			_sessionExpiresUtc = DateTime.UtcNow.AddHours(12.0);
			SaveSession();
		}

		internal static bool TryGetLastDreamPoint(Player player, out Vector3 position, out Quaternion rotation)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00a3: 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)
			position = Vector3.zero;
			rotation = Quaternion.identity;
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			try
			{
				string[] array = ReadPlayerCustomData(player, "ChallengeHub.DreamBridge.LastPoint.EventRun2Dream.v1").Split(new char[1] { '|' });
				if (array.Length != 7)
				{
					return false;
				}
				float[] array2 = new float[7];
				for (int i = 0; i < array2.Length; i++)
				{
					if (!float.TryParse(array[i], NumberStyles.Float, CultureInfo.InvariantCulture, out array2[i]))
					{
						return false;
					}
				}
				position = new Vector3(array2[0], array2[1], array2[2]);
				rotation = new Quaternion(array2[3], array2[4], array2[5], array2[6]);
				return IsFinite(position.x) && IsFinite(position.y) && IsFinite(position.z) && IsFinite(rotation.x) && IsFinite(rotation.y) && IsFinite(rotation.z) && IsFinite(rotation.w);
			}
			catch
			{
				return false;
			}
		}

		internal static bool CanSaveDreamPoint()
		{
			LoadSession();
			if (IsAuthorizedDreamArrival())
			{
				return !_arrivalPending;
			}
			return false;
		}

		internal unsafe static void SaveLastDreamPoint(Player player, bool writeLog = true)
		{
			//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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0145: 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)
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || CurrentRole != DreamWorldRole.Server3Dream)
			{
				return;
			}
			try
			{
				Vector3 position = ((Component)player).transform.position;
				Quaternion rotation = ((Component)player).transform.rotation;
				if (!IsFinite(position.x) || !IsFinite(position.y) || !IsFinite(position.z))
				{
					return;
				}
				string value = string.Join("|", position.x.ToString("R", CultureInfo.InvariantCulture), position.y.ToString("R", CultureInfo.InvariantCulture), position.z.ToString("R", CultureInfo.InvariantCulture), rotation.x.ToString("R", CultureInfo.InvariantCulture), rotation.y.ToString("R", CultureInfo.InvariantCulture), rotation.z.ToString("R", CultureInfo.InvariantCulture), rotation.w.ToString("R", CultureInfo.InvariantCulture));
				if (writeLog && WritePlayerCustomData(player, "ChallengeHub.DreamBridge.LastPoint.EventRun2Dream.v1", value))
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						Vector3 val = position;
						log.LogInfo((object)("Letzten Traumpunkt im Charakterprofil gespeichert: " + ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString()));
					}
				}
				else if (!writeLog)
				{
					WritePlayerCustomData(player, "ChallengeHub.DreamBridge.LastPoint.EventRun2Dream.v1", value);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Letzter Traumpunkt konnte nicht gespeichert werden: " + ex.Message));
				}
			}
		}

		internal static bool ShouldSuspendClientGameplay()
		{
			if (Application.isBatchMode || IsServerAuthority())
			{
				return false;
			}
			if (CurrentRole == DreamWorldRole.Server3Dream)
			{
				return IsAuthorizedDreamArrival();
			}
			return false;
		}

		private static bool IsFinite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}

		private static string ReadPlayerCustomData(Player player, string key)
		{
			try
			{
				MethodInfo method = ((object)player).GetType().GetMethod("GetCustomData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);
				if (method != null)
				{
					return Convert.ToString(method.Invoke(player, new object[1] { key })) ?? string.Empty;
				}
			}
			catch
			{
			}
			try
			{
				if (((object)player).GetType().GetField("m_customData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(player) is IDictionary<string, string> dictionary && dictionary.TryGetValue(key, out var value))
				{
					return value ?? string.Empty;
				}
			}
			catch
			{
			}
			return string.Empty;
		}

		private static bool WritePlayerCustomData(Player player, string key, string value)
		{
			try
			{
				MethodInfo method = ((object)player).GetType().GetMethod("SetCustomData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2]
				{
					typeof(string),
					typeof(string)
				}, null);
				if (method != null)
				{
					method.Invoke(player, new object[2]
					{
						key,
						value ?? string.Empty
					});
					return true;
				}
			}
			catch
			{
			}
			try
			{
				if (((object)player).GetType().GetField("m_customData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(player) is IDictionary<string, string> dictionary)
				{
					dictionary[key] = value ?? string.Empty;
					return true;
				}
			}
			catch
			{
			}
			return false;
		}

		internal static void JoinTarget(FejdStartup startup, DreamWorldRole target)
		{
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)startup == (Object)null)
			{
				throw new ArgumentNullException("startup");
			}
			bool flag = target == DreamWorldRole.Server3Dream;
			string value;
			int value2;
			string value3;
			if (flag)
			{
				value = Plugin.DreamHost.Value;
				value2 = Plugin.DreamPort.Value;
				value3 = Plugin.DreamPassword.Value;
			}
			else
			{
				switch (target)
				{
				case DreamWorldRole.Server3Finale:
					value = Plugin.FinaleHost.Value;
					value2 = Plugin.FinalePort.Value;
					value3 = Plugin.FinalePassword.Value;
					break;
				case DreamWorldRole.Server2:
					value = Plugin.MainHost.Value;
					value2 = Plugin.MainPort.Value;
					value3 = Plugin.MainPassword.Value;
					break;
				default:
					throw new InvalidOperationException("Unbekanntes Traumbruecken-Ziel: " + target);
				}
			}
			if (value2 <= 0 || value2 > 65535)
			{
				throw new InvalidOperationException("Ungueltiger Zielport: " + value2);
			}
			ushort num = (ushort)value2;
			if (string.IsNullOrWhiteSpace(value3))
			{
				throw new InvalidOperationException("Direktes Zielpasswort ist nicht konfiguriert.");
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(FejdStartup), "<ServerPassword>k__BackingField");
			if (fieldInfo != null)
			{
				fieldInfo.SetValue(null, value3 ?? string.Empty);
			}
			ServerJoinData val = default(ServerJoinData);
			((ServerJoinData)(ref val))..ctor(new ServerJoinDataDedicated(value, num));
			FieldInfo fieldInfo2 = AccessTools.Field(typeof(FejdStartup), "m_queuedJoinServer");
			if (fieldInfo2 == null)
			{
				throw new MissingFieldException("FejdStartup.m_queuedJoinServer");
			}
			fieldInfo2.SetValue(startup, val);
			ZNet.SetServerHost(value, (int)num, (OnlineBackendType)0);
			PlayerProfile val2 = SelectedProfile(startup);
			if (val2 == null)
			{
				AccessTools.Method(typeof(FejdStartup), "ShowCharacterSelection", (Type[])null, (Type[])null)?.Invoke(startup, null);
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(typeof(FejdStartup), "SetSelectedProfile", new Type[1] { typeof(string) }, (Type[])null);
			if (methodInfo == null)
			{
				throw new MissingMethodException("FejdStartup.SetSelectedProfile");
			}
			methodInfo.Invoke(startup, new object[1] { val2.GetFilename() });
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("Traumreise verbindet " + val2.GetName() + " mit " + value + ":" + num + "."));
			}
			if (!flag && _forceSiegreicheIntro)
			{
				ForceSiegreicheIntro(startup);
				_forceSiegreicheIntro = false;
				SaveSession();
			}
			startup.OnCharacterStart();
		}

		private static void ForceSiegreicheIntro(FejdStartup startup)
		{
			try
			{
				Type type = AccessTools.TypeByName("ChallengeHubValheim.WorldIntroVideoFeature");
				string? text = Convert.ToString(((type != null) ? AccessTools.Method(type, "BuildSeenKey", (Type[])null, (Type[])null) : null)?.Invoke(null, new object[1] { startup }), CultureInfo.InvariantCulture);
				if (string.IsNullOrWhiteSpace(text))
				{
					throw new InvalidOperationException("Intro-Schluessel ist nicht verfuegbar.");
				}
				PlayerPrefs.SetInt(text, 0);
				PlayerPrefs.Save();
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"Siegreiche-Valheimer-Intro fuer den Cataclysm-Uebergang freigegeben.");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Intro konnte nicht erzwungen werden: " + ex.Message));
				}
			}
		}

		private static PlayerProfile SelectedProfile(FejdStartup startup)
		{
			try
			{
				List<PlayerProfile> list = AccessTools.Field(typeof(FejdStartup), "m_profiles")?.GetValue(startup) as List<PlayerProfile>;
				object obj = AccessTools.Field(typeof(FejdStartup), "m_profileIndex")?.GetValue(startup);
				int num = ((obj != null) ? Convert.ToInt32(obj, CultureInfo.InvariantCulture) : (-1));
				return (list != null && num >= 0 && num < list.Count) ? list[num] : null;
			}
			catch
			{
				return null;
			}
		}

		private static void SaveSession()
		{
			try
			{
				File.WriteAllLines(SessionPath(), new string[5]
				{
					"Target=" + _sessionTarget,
					"ReturnTarget=" + _sessionReturnTarget,
					"ExpiresUtc=" + _sessionExpiresUtc.ToString("O", CultureInfo.InvariantCulture),
					"ArrivalPending=" + _arrivalPending,
					"ForceSiegreicheIntro=" + _forceSiegreicheIntro
				});
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Traumsitzung konnte nicht gespeichert werden: " + ex.Message));
				}
			}
		}

		private static void ClearSession()
		{
			_sessionTarget = DreamWorldRole.None;
			_sessionReturnTarget = DreamWorldRole.None;
			_sessionExpiresUtc = DateTime.MinValue;
			_arrivalPending = false;
			_forceSiegreicheIntro = false;
			try
			{
				if (File.Exists(SessionPath()))
				{
					File.Delete(SessionPath());
				}
			}
			catch
			{
			}
		}

		private static string SessionPath()
		{
			return Path.Combine(Paths.ConfigPath, "ChallengeHubDreamBridge.session");
		}
	}
	internal sealed class DreamPortalAura : MonoBehaviour
	{
		private Light _light;

		private ParticleSystem _particles;

		private void Awake()
		{
			//IL_0052: 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_0067: Expected O, but got Unknown
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: 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_00e1: 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_011a: 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_0138: 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_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			_light = ((Component)this).gameObject.AddComponent<Light>();
			_light.type = (LightType)2;
			_light.range = 11f;
			_light.intensity = 2.2f;
			_light.color = new Color(0.42f, 0.68f, 1f);
			GameObject val = new GameObject("ChallengeHub_DreamMist");
			val.transform.SetParent(((Component)this).transform, false);
			val.transform.localPosition = new Vector3(0f, 1.7f, 0f);
			_particles = val.AddComponent<ParticleSystem>();
			MainModule main = _particles.main;
			((MainModule)(ref main)).loop = true;
			((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(3.5f);
			((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.35f);
			((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.18f);
			((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(0.35f, 0.65f, 1f, 0.65f), new Color(0.78f, 0.42f, 1f, 0.55f));
			((MainModule)(ref main)).maxParticles = 90;
			EmissionModule emission = _particles.emission;
			((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(18f);
			ShapeModule shape = _particles.shape;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)10;
			((ShapeModule)(ref shape)).radius = 2.15f;
		}

		private void Update()
		{
			//IL_0059: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_light == (Object)null))
			{
				float num = 0.5f + 0.5f * Mathf.Sin(Time.time * 1.35f);
				_light.intensity = 1.7f + num * 1.25f;
				_light.color = Color.Lerp(new Color(0.3f, 0.72f, 1f), new Color(0.72f, 0.3f, 1f), num);
			}
		}
	}
	internal enum DreamBridgeVideoSelection
	{
		Stop,
		Part1,
		Part2,
		Both
	}
	internal static class DreamBridgeVideoFeature
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static ConsoleEvent <0>__Command;

			public static Action<long, ZPackage> <1>__RpcRequest;

			public static Action<long, ZPackage> <2>__RpcPlayback;
		}

		internal const string Part1FileName = "die-siegreichen-valheimer-intro-teil1.mp4";

		internal const string Part2FileName = "die-siegreichen-valheimer-intro-teil2.mp4";

		private const string RequestRpc = "ChallengeHub_DreamBridge_VideoRequest_v1";

		private const string PlaybackRpc = "ChallengeHub_DreamBridge_VideoPlayback_v1";

		private static DreamBridgeVideoBehaviour _behaviour;

		private static ZRoutedRpc _registeredRpc;

		private static bool _commandRegistered;

		internal static bool IsPlaying
		{
			get
			{
				if ((Object)(object)_behaviour != (Object)null)
				{
					return _behaviour.IsPlaying;
				}
				return false;
			}
		}

		internal static void Initialize(Plugin plugin)
		{
			if (!((Object)(object)plugin == (Object)null))
			{
				_behaviour = ((Component)plugin).GetComponent<DreamBridgeVideoBehaviour>() ?? ((Component)plugin).gameObject.AddComponent<DreamBridgeVideoBehaviour>();
				if (!Application.isBatchMode)
				{
					_behaviour.Initialize(new string[2] { "die-siegreichen-valheimer-intro-teil1.mp4", "die-siegreichen-valheimer-intro-teil2.mp4" });
				}
			}
		}

		internal static void Tick()
		{
			RegisterCommand();
			RegisterRpcs();
		}

		private static void RegisterCommand()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			if (!_commandRegistered)
			{
				_commandRegistered = true;
				object obj = <>O.<0>__Command;
				if (obj == null)
				{
					ConsoleEvent val = Command;
					<>O.<0>__Command = val;
					obj = (object)val;
				}
				new ConsoleCommand("dreamvideo", "Admin: dreamvideo 1 | 2 | beide | stop. Lokal: dreamvideo lokal 1 | 2 | beide.", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			}
		}

		private static void Command(ConsoleEventArgs args)
		{
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Expected O, but got Unknown
			string text = Argument(args, 1);
			int num;
			switch (text)
			{
			default:
				num = ((text == "vorschau") ? 1 : 0);
				break;
			case "lokal":
			case "local":
			case "preview":
				num = 1;
				break;
			}
			bool flag = (byte)num != 0;
			string text2 = (flag ? Argument(args, 2) : text);
			if (string.IsNullOrWhiteSpace(text2) || text2 == "help" || text2 == "hilfe")
			{
				args.Context.AddString("dreamvideo 1: Teil 1 synchron fuer alle anwesenden Spieler.");
				args.Context.AddString("dreamvideo 2: Teil 2 synchron fuer alle anwesenden Spieler.");
				args.Context.AddString("dreamvideo beide: Teil 1 und danach Teil 2 synchron abspielen.");
				args.Context.AddString("dreamvideo stop: laufende Wiedergabe bei allen beenden.");
				args.Context.AddString("dreamvideo lokal 1|2|beide: nur auf diesem Client als Vorschau.");
				return;
			}
			DreamBridgeVideoSelection dreamBridgeVideoSelection = ParseSelection(text2);
			if (dreamBridgeVideoSelection == (DreamBridgeVideoSelection)(-1))
			{
				args.Context.AddString("Unbekannte Auswahl. Erlaubt: 1, 2, beide, stop.");
				return;
			}
			if (flag)
			{
				if (Application.isBatchMode || (Object)(object)_behaviour == (Object)null)
				{
					args.Context.AddString("Eine lokale Vorschau ist auf dem Dedicated Server nicht moeglich.");
				}
				else if (dreamBridgeVideoSelection == DreamBridgeVideoSelection.Stop)
				{
					_behaviour.StopPlayback("lokale Vorschau beendet");
				}
				else if (!_behaviour.Play(dreamBridgeVideoSelection, DateTime.UtcNow.Ticks))
				{
					args.Context.AddString("Video fehlt oder eine Wiedergabe konnte nicht gestartet werden.");
				}
				else
				{
					args.Context.AddString("Lokale DreamBridge-Vorschau gestartet: " + SelectionLabel(dreamBridgeVideoSelection) + ".");
				}
				return;
			}
			ZPackage val = new ZPackage();
			val.Write((int)dreamBridgeVideoSelection);
			if (DreamBridgeRuntime.IsServerAuthority())
			{
				RpcRequest(0L, val);
			}
			else
			{
				long num2 = DreamBridgeRuntime.ResolveServerPeerId();
				if (num2 == 0L || ZRoutedRpc.instance == null)
				{
					args.Context.AddString("Kein Server fuer die synchrone Videowiedergabe verbunden.");
					return;
				}
				ZRoutedRpc.instance.InvokeRoutedRPC(num2, "ChallengeHub_DreamBridge_VideoRequest_v1", new object[1] { val });
			}
			args.Context.AddString("DreamBridge-Videoanfrage gesendet: " + SelectionLabel(dreamBridgeVideoSelection) + ".");
		}

		private static string Argument(ConsoleEventArgs args, int index)
		{
			if (args?.Args == null || args.Args.Length <= index)
			{
				return string.Empty;
			}
			return Convert.ToString(args.Args[index], CultureInfo.InvariantCulture)?.Trim().ToLowerInvariant() ?? string.Empty;
		}

		private static DreamBridgeVideoSelection ParseSelection(string action)
		{
			switch (action)
			{
			case "1":
			case "teil1":
			case "part1":
				return DreamBridgeVideoSelection.Part1;
			case "2":
			case "teil2":
			case "part2":
				return DreamBridgeVideoSelection.Part2;
			case "beide":
			case "all":
			case "both":
				return DreamBridgeVideoSelection.Both;
			case "stop":
			case "ende":
			case "abort":
				return DreamBridgeVideoSelection.Stop;
			default:
				return (DreamBridgeVideoSelection)(-1);
			}
		}

		private static string SelectionLabel(DreamBridgeVideoSelection selection)
		{
			return selection switch
			{
				DreamBridgeVideoSelection.Part1 => "Teil 1", 
				DreamBridgeVideoSelection.Part2 => "Teil 2", 
				DreamBridgeVideoSelection.Both => "beide Teile", 
				_ => "Stop", 
			};
		}

		private static void RegisterRpcs()
		{
			if (ZRoutedRpc.instance != null && _registeredRpc != ZRoutedRpc.instance)
			{
				_registeredRpc = ZRoutedRpc.instance;
				_registeredRpc.Register<ZPackage>("ChallengeHub_DreamBridge_VideoRequest_v1", (Action<long, ZPackage>)RpcRequest);
				_registeredRpc.Register<ZPackage>("ChallengeHub_DreamBridge_VideoPlayback_v1", (Action<long, ZPackage>)RpcPlayback);
			}
		}

		private static void RpcRequest(long sender, ZPackage package)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			if (!DreamBridgeRuntime.IsServerAuthority() || package == null)
			{
				return;
			}
			if (!DreamCataclysmFeature.IsAdminSender(sender))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("DreamBridge-Videoanfrage eines Nicht-Admins verworfen: " + sender));
				}
				return;
			}
			DreamBridgeVideoSelection dreamBridgeVideoSelection = (DreamBridgeVideoSelection)package.ReadInt();
			long ticks;
			switch (dreamBridgeVideoSelection)
			{
			default:
				return;
			case DreamBridgeVideoSelection.Part1:
			case DreamBridgeVideoSelection.Part2:
			case DreamBridgeVideoSelection.Both:
				ticks = DateTime.UtcNow.AddSeconds(2.5).Ticks;
				break;
			case DreamBridgeVideoSelection.Stop:
				ticks = DateTime.UtcNow.Ticks;
				break;
			}
			long num = ticks;
			ZPackage val = new ZPackage();
			val.Write((int)dreamBridgeVideoSelection);
			val.Write(num);
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null)
			{
				instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "ChallengeHub_DreamBridge_VideoPlayback_v1", new object[1] { val });
			}
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("DreamBridge-Video serverweit angeordnet: " + SelectionLabel(dreamBridgeVideoSelection) + "."));
			}
		}

		private static void RpcPlayback(long sender, ZPackage package)
		{
			if (package == null || Application.isBatchMode || (Object)(object)_behaviour == (Object)null)
			{
				return;
			}
			long num = DreamBridgeRuntime.ResolveServerPeerId();
			if (!DreamBridgeRuntime.IsServerAuthority() && (num == 0L || sender != num))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("DreamBridge-Videowiedergabe von einer Nicht-Serverquelle verworfen: " + sender));
				}
				return;
			}
			DreamBridgeVideoSelection dreamBridgeVideoSelection = (DreamBridgeVideoSelection)package.ReadInt();
			long synchronizedStartTicks = package.ReadLong();
			if (dreamBridgeVideoSelection == DreamBridgeVideoSelection.Stop)
			{
				_behaviour.StopPlayback("serverweit beendet");
			}
			else
			{
				_behaviour.Play(dreamBridgeVideoSelection, synchronizedStartTicks);
			}
		}

		internal static string ResolveVideoPath(string fileName)
		{
			try
			{
				string text = Path.Combine(Path.GetDirectoryName(typeof(DreamBridgeVideoFeature).Assembly.Location) ?? Paths.PluginPath, "Media", fileName);
				if (File.Exists(text))
				{
					return text;
				}
				string text2 = Path.Combine(Paths.PluginPath, "ChallengeHubDreamBridge", "Media", fileName);
				if (!string.Equals(text, text2, StringComparison.OrdinalIgnoreCase) && File.Exists(text2))
				{
					return text2;
				}
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("DreamBridge-Video fehlt: " + text));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)("DreamBridge-Videopfad konnte nicht geprueft werden: " + ex.Message));
				}
			}
			return null;
		}
	}
	internal sealed class DreamBridgeVideoBehaviour : MonoBehaviour
	{
		private const float PrepareTimeoutSeconds = 25f;

		private const float BetweenPartsBlackSeconds = 0.45f;

		private readonly VideoPlayer[] _videos = (VideoPlayer[])(object)new VideoPlayer[2];

		private readonly AudioSource[] _audios = (AudioSource[])(object)new AudioSource[2];

		private readonly bool[] _prepared = new bool[2];

		private string[] _paths;

		private DreamBridgeVideoSelection _selection;

		pri