Decompiled source of ValheimOptimizer v0.1.17

MagiCorp.ValheimOptimizer.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("MagiCorp.ValheimOptimizer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+2170dc9292f9eca3f6a5a042c19a5001720afa5c")]
[assembly: AssemblyProduct("MagiCorp.ValheimOptimizer")]
[assembly: AssemblyTitle("MagiCorp.ValheimOptimizer")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace MagiCorp.ValheimOptimizer;

[BepInPlugin("magicorp.valheim.optimizer", "MagiCorp Valheim Optimizer", "0.1.17")]
public sealed class ValheimOptimizerPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "magicorp.valheim.optimizer";

	public const string PluginName = "MagiCorp Valheim Optimizer";

	public const string PluginVersion = "0.1.17";

	internal const int ProtocolVersion = 4;

	internal static ManualLogSource Log;

	internal static ConfigEntry<bool> EnableNetworkScheduler;

	internal static ConfigEntry<int> OptimizedReplicationHz;

	internal static ConfigEntry<float> NetworkMainThreadBudgetMs;

	internal static ConfigEntry<int> ReplicationWindowKiB;

	internal static ConfigEntry<int> ReplicationMinRoomKiB;

	internal static ConfigEntry<bool> EnableZdoCompression;

	internal static ConfigEntry<int> CompressionThresholdBytes;

	internal static ConfigEntry<bool> EnableFastLoading;

	internal static ConfigEntry<int> LoadingObjectLimit;

	internal static ConfigEntry<bool> EnablePortalPrefetch;

	internal static ConfigEntry<int> PortalPrefetchMaxZdos;

	internal static ConfigEntry<int> PortalZonesPerFrame;

	internal static ConfigEntry<float> MinimumDistantTeleportSeconds;

	internal static ConfigEntry<float> InitialSpawnMinimumSeconds;

	internal static ConfigEntry<bool> EnableMinimapCache;

	internal static ConfigEntry<bool> ImmediateJoinLoadingScreen;

	internal static ConfigEntry<bool> AsyncJoinSceneLoad;

	internal static ConfigEntry<bool> MinimalMainMenu;

	internal static ConfigEntry<bool> UseCustomLoadingScreen;

	internal static ConfigEntry<bool> VerboseMetrics;

	internal static string PluginDirectory;

	private Harmony _harmony;

	private float _nextHello;

	private float _nextMetrics;

	private void Awake()
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Expected O, but got Unknown
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Expected O, but got Unknown
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Expected O, but got Unknown
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Expected O, but got Unknown
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Expected O, but got Unknown
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Expected O, but got Unknown
		//IL_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_021a: Expected O, but got Unknown
		//IL_0241: Unknown result type (might be due to invalid IL or missing references)
		//IL_024b: Expected O, but got Unknown
		//IL_027e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0288: Expected O, but got Unknown
		//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c5: Expected O, but got Unknown
		//IL_03da: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e4: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		EnableNetworkScheduler = ((BaseUnityPlugin)this).Config.Bind<bool>("Network", "AdaptiveReplicationScheduler", true, "Service all optimized peers within a bounded main-thread budget instead of one peer per frame.");
		OptimizedReplicationHz = ((BaseUnityPlugin)this).Config.Bind<int>("Network", "ReplicationHz", 30, new ConfigDescription("ZDO replication rate for negotiated optimizer peers.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 30), Array.Empty<object>()));
		NetworkMainThreadBudgetMs = ((BaseUnityPlugin)this).Config.Bind<float>("Network", "MainThreadBudgetMs", 1.75f, new ConfigDescription("Maximum scheduler CPU budget per update.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 8f), Array.Empty<object>()));
		ReplicationWindowKiB = ((BaseUnityPlugin)this).Config.Bind<int>("Network", "ReplicationWindowKiB", 128, new ConfigDescription("Maximum ZDO send window when every peer supports the optimizer.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 2048), Array.Empty<object>()));
		ReplicationMinRoomKiB = ((BaseUnityPlugin)this).Config.Bind<int>("Network", "ReplicationMinRoomKiB", 8, new ConfigDescription("Minimum free ZDO send window before building another batch.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 256), Array.Empty<object>()));
		EnableZdoCompression = ((BaseUnityPlugin)this).Config.Bind<bool>("Network", "CompressZdoData", true, "Losslessly compress large ZDOData RPC payloads between optimizer peers.");
		CompressionThresholdBytes = ((BaseUnityPlugin)this).Config.Bind<int>("Network", "CompressionThresholdBytes", 2048, new ConfigDescription("Do not compress smaller ZDO payloads.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(256, 65536), Array.Empty<object>()));
		EnableFastLoading = ((BaseUnityPlugin)this).Config.Bind<bool>("Loading", "AdaptiveObjectCreation", true, "Increase ZNet object creation throughput while the client is on a loading/teleport screen.");
		LoadingObjectLimit = ((BaseUnityPlugin)this).Config.Bind<int>("Loading", "LoadingObjectsPerPass", 300, new ConfigDescription("Maximum object creation budget while loading. Vanilla is 100.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(100, 1000), Array.Empty<object>()));
		EnablePortalPrefetch = ((BaseUnityPlugin)this).Config.Bind<bool>("Loading", "PortalPrefetch", true, "Prefetch destination terrain and ZDOs as soon as a distant teleport begins.");
		PortalPrefetchMaxZdos = ((BaseUnityPlugin)this).Config.Bind<int>("Loading", "PortalPrefetchMaxZDOs", 6000, new ConfigDescription("Maximum destination ZDOs to priority-send per teleport.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(500, 50000), Array.Empty<object>()));
		PortalZonesPerFrame = ((BaseUnityPlugin)this).Config.Bind<int>("Loading", "PortalZonesPerFrame", 2, new ConfigDescription("Destination terrain zones to poke per client frame.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 8), Array.Empty<object>()));
		MinimumDistantTeleportSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Loading", "MinimumDistantTeleportSeconds", 2.5f, new ConfigDescription("Vanilla forces 8 seconds. Area readiness is still required.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2.05f, 8f), Array.Empty<object>()));
		InitialSpawnMinimumSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Loading", "InitialSpawnMinimumSeconds", 0.25f, new ConfigDescription("Minimum initial join respawn delay on negotiated servers. Area readiness and ground checks are still required. Death respawns are unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 8f), Array.Empty<object>()));
		EnableMinimapCache = ((BaseUnityPlugin)this).Config.Bind<bool>("Loading", "PersistentMinimapCache", true, "Reuse Valheim minimap cache files on repeat joins to the same negotiated world with world-version validation.");
		ImmediateJoinLoadingScreen = ((BaseUnityPlugin)this).Config.Bind<bool>("Loading", "ImmediateJoinLoadingScreen", true, "Skip Valheim's cosmetic 1.5-second menu fade and show the loading screen immediately when starting or joining a world.");
		AsyncJoinSceneLoad = ((BaseUnityPlugin)this).Config.Bind<bool>("Loading", "AsyncJoinSceneLoad", false, "Experimental asynchronous remote scene loading. Disabled by default because some clients could remain on the loading screen. Vanilla scene loading is used when false.");
		MinimalMainMenu = ((BaseUnityPlugin)this).Config.Bind<bool>("Loading", "MinimalMainMenu", true, "Use an UI-only black main menu: no 3D world rendering and no per-frame menu camera movement.");
		UseCustomLoadingScreen = ((BaseUnityPlugin)this).Config.Bind<bool>("Loading", "UseCustomLoadingScreen", true, "Use the packaged MagiCorp loading artwork for the pre-join loading overlay. Falls back to the black/text overlay if unavailable.");
		PluginDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Paths.PluginPath;
		VerboseMetrics = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "PeriodicMetrics", true, "Log optimizer counters every 30 seconds.");
		NetworkOptimizations.Initialize();
		LoadingOptimizations.Initialize();
		PreJoinLoadingOverlay.PreloadArtwork();
		PrivateAccess.LogResolution();
		RunCompressionSelfTest();
		_harmony = new Harmony("magicorp.valheim.optimizer");
		_harmony.PatchAll(typeof(ValheimOptimizerPlugin).Assembly);
		((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded; protocol v{2}; SendZDOs window patches={3}, teleport patches={4}", "MagiCorp Valheim Optimizer", "0.1.17", 4, PatchDiagnostics.WindowConstantsPatched, PatchDiagnostics.TeleportConstantsPatched));
	}

	private void Update()
	{
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		if (realtimeSinceStartup >= _nextHello)
		{
			_nextHello = realtimeSinceStartup + 2f;
			NetworkOptimizations.SendPendingHellos();
		}
		LoadingOptimizations.UpdateClientPrefetch();
		if (VerboseMetrics.Value && realtimeSinceStartup >= _nextMetrics)
		{
			_nextMetrics = realtimeSinceStartup + 30f;
			Metrics.LogSummary();
		}
	}

	private void OnDestroy()
	{
		LoadingOptimizations.RestoreLoadingPriority();
		PreJoinLoadingOverlay.ReleaseResources();
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}

	private static void RunCompressionSelfTest()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Expected O, but got Unknown
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			ZPackage val = new ZPackage();
			for (int i = 0; i < 512; i++)
			{
				val.Write("MagiCorp-ValheimOptimizer-ZDO-ZDO-ZDO");
				val.Write(i & 7);
			}
			ZPackage val2 = new ZPackage();
			val2.WriteCompressed(val);
			ZPackage val3 = new ZPackage();
			val3.Load(val2.GetArray());
			ZPackage val4 = val3.ReadCompressedPackage();
			if (!val.GetArray().SequenceEqual(val4.GetArray()))
			{
				throw new InvalidOperationException("ZPackage compression round-trip mismatch");
			}
			Log.LogInfo((object)$"Compression self-test passed: {val.Size()} -> {val2.Size()} bytes ({100.0 * (double)val2.Size() / (double)val.Size():F1}% of original)");
		}
		catch (Exception arg)
		{
			EnableZdoCompression.Value = false;
			Log.LogError((object)$"Compression self-test failed; compressed networking disabled: {arg}");
		}
	}
}
internal static class MinimapOptimizations
{
	private const int CacheSchema = 1;

	private static readonly FieldInfo MaskPathField = AccessTools.Field(typeof(Minimap), "m_cachedMinimapMaskTexturePath");

	private static readonly FieldInfo BiomePathField = AccessTools.Field(typeof(Minimap), "m_cachedMinimapBiomeTexturePath");

	private static readonly FieldInfo HeightPathField = AccessTools.Field(typeof(Minimap), "m_cachedMinimapHeightTexturePath");

	private static readonly FieldInfo MetaPathField = AccessTools.Field(typeof(Minimap), "m_cachedMinimapMetaPath");

	private static readonly FieldInfo SaveDirectoryField = AccessTools.Field(typeof(Minimap), "m_saveDirectory");

	private static readonly FieldInfo MaskTextureField = AccessTools.Field(typeof(Minimap), "m_forestMaskTexture");

	private static readonly FieldInfo MapTextureField = AccessTools.Field(typeof(Minimap), "m_mapTexture");

	private static readonly FieldInfo HeightTextureField = AccessTools.Field(typeof(Minimap), "m_heightTexture");

	private static readonly FieldInfo RespawnAfterDeathField = AccessTools.Field(typeof(Game), "m_respawnAfterDeath");

	internal static bool IsAfterDeathRespawn(Game game)
	{
		try
		{
			return RespawnAfterDeathField != null && (bool)RespawnAfterDeathField.GetValue(game);
		}
		catch
		{
			return false;
		}
	}

	private static bool EnsurePaths(Minimap map)
	{
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Expected I4, but got Unknown
		if ((Object)(object)map == (Object)null || ZNet.World == null)
		{
			return false;
		}
		try
		{
			if (!string.IsNullOrEmpty(MetaPathField?.GetValue(map) as string))
			{
				return true;
			}
			int stableHashCode = StringExtensionMethods.GetStableHashCode(ZNet.World.m_name ?? string.Empty);
			string text = Path.Combine(Paths.ConfigPath, "MagiCorp.ValheimOptimizer", "MinimapCache", $"{ZNet.World.m_seed:X8}_{stableHashCode:X8}_{(int)ZNet.World.m_worldVersion}");
			Directory.CreateDirectory(text);
			SaveDirectoryField?.SetValue(map, text);
			MaskPathField?.SetValue(map, Path.Combine(text, "cacheMinimapMask"));
			BiomePathField?.SetValue(map, Path.Combine(text, "cacheMinimapBiome"));
			HeightPathField?.SetValue(map, Path.Combine(text, "cacheMinimapHeight"));
			MetaPathField?.SetValue(map, Path.Combine(text, "cacheMinimapMeta"));
			return true;
		}
		catch (Exception ex)
		{
			ValheimOptimizerPlugin.Log.LogWarning((object)("Optimizer minimap cache path setup failed: " + ex.Message));
			return false;
		}
	}

	private static string SidecarPath(Minimap map)
	{
		if (!EnsurePaths(map))
		{
			return null;
		}
		string text = MetaPathField?.GetValue(map) as string;
		if (!string.IsNullOrEmpty(text))
		{
			return text + ".magicorp";
		}
		return null;
	}

	internal static bool TryLoad(Minimap map, int worldSeed)
	{
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: Invalid comparison between I4 and Unknown
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		if (!ValheimOptimizerPlugin.EnableMinimapCache.Value || !NetworkOptimizations.ClientServerNegotiated() || ZNet.World == null)
		{
			return false;
		}
		try
		{
			if (!EnsurePaths(map))
			{
				return false;
			}
			string text = MaskPathField?.GetValue(map) as string;
			string text2 = BiomePathField?.GetValue(map) as string;
			string text3 = HeightPathField?.GetValue(map) as string;
			string text4 = MetaPathField?.GetValue(map) as string;
			string text5 = SidecarPath(map);
			if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(text2) || string.IsNullOrEmpty(text3) || string.IsNullOrEmpty(text4) || string.IsNullOrEmpty(text5))
			{
				return false;
			}
			if (!File.Exists(text) || !File.Exists(text2) || !File.Exists(text3) || !File.Exists(text4) || !File.Exists(text5))
			{
				return false;
			}
			byte[] array = File.ReadAllBytes(text4);
			if (array.Length < 8 || BitConverter.ToInt32(array, 0) != worldSeed || BitConverter.ToInt32(array, 4) != 1)
			{
				return false;
			}
			byte[] array2 = File.ReadAllBytes(text5);
			if (array2.Length < 20 || BitConverter.ToInt32(array2, 0) != 1 || BitConverter.ToInt32(array2, 4) != worldSeed || BitConverter.ToInt32(array2, 8) != (int)ZNet.World.m_worldVersion || BitConverter.ToInt32(array2, 12) != 2 || BitConverter.ToInt32(array2, 16) != 1)
			{
				return false;
			}
			Stopwatch stopwatch = Stopwatch.StartNew();
			object? obj = MaskTextureField?.GetValue(map);
			Texture2D val = (Texture2D)((obj is Texture2D) ? obj : null);
			object? obj2 = MapTextureField?.GetValue(map);
			Texture2D val2 = (Texture2D)((obj2 is Texture2D) ? obj2 : null);
			object? obj3 = HeightTextureField?.GetValue(map);
			Texture2D val3 = (Texture2D)((obj3 is Texture2D) ? obj3 : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null)
			{
				return false;
			}
			val.SetPixels32(Utils.CompressedBufferToColors(File.ReadAllBytes(text)));
			val.Apply();
			val2.SetPixels32(Utils.CompressedBufferToColors(File.ReadAllBytes(text2)));
			val2.Apply();
			val3.SetPixels(Utils.CompressedHalfBufferToRedChannel(File.ReadAllBytes(text3)));
			val3.Apply();
			ValheimOptimizerPlugin.Log.LogInfo((object)$"OPT BENCH minimap-cache-hit load={stopwatch.ElapsedMilliseconds}ms worldVersion={ZNet.World.m_worldVersion}");
			return true;
		}
		catch (Exception ex)
		{
			ValheimOptimizerPlugin.Log.LogWarning((object)("Optimizer minimap cache load failed; regenerating normally: " + ex.Message));
			return false;
		}
	}

	internal static void PrepareGeneration(Minimap map)
	{
		if (ValheimOptimizerPlugin.EnableMinimapCache.Value && NetworkOptimizations.ClientServerNegotiated() && ZNet.World != null)
		{
			EnsurePaths(map);
		}
	}

	internal static void MarkGenerated(Minimap map)
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Expected I4, but got Unknown
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		if (!ValheimOptimizerPlugin.EnableMinimapCache.Value || !NetworkOptimizations.ClientServerNegotiated() || ZNet.World == null)
		{
			return;
		}
		try
		{
			string text = SidecarPath(map);
			if (!string.IsNullOrEmpty(text))
			{
				List<byte> list = new List<byte>(20);
				list.AddRange(BitConverter.GetBytes(1));
				list.AddRange(BitConverter.GetBytes(ZNet.World.m_seed));
				list.AddRange(BitConverter.GetBytes((int)ZNet.World.m_worldVersion));
				list.AddRange(BitConverter.GetBytes(2));
				list.AddRange(BitConverter.GetBytes(1));
				File.WriteAllBytes(text, list.ToArray());
				ValheimOptimizerPlugin.Log.LogInfo((object)$"Optimizer minimap cache keyed for seed={ZNet.World.m_seed} worldVersion={ZNet.World.m_worldVersion}");
			}
		}
		catch (Exception ex)
		{
			ValheimOptimizerPlugin.Log.LogWarning((object)("Optimizer minimap cache metadata write failed: " + ex.Message));
		}
	}
}
internal sealed class PeerState
{
	public int RemoteProtocol;

	public bool Negotiated;

	public bool HelloSent;

	public int HelloAttempts;

	public float RegisteredAt;

	public bool CompatibilityLogged;

	public float SendAccumulator;

	public float LastPrefetchRequest;

	public bool InitialAreaRequested;

	public Vector3 InitialAreaTarget;

	public int InitialAreaStablePasses;

	public bool InitialAreaReadySent;
}
internal static class PrivateAccess
{
	private static readonly FieldInfo PeerRpc = AccessTools.Field(typeof(ZNetPeer), "m_rpc");

	private static readonly FieldInfo PeerUid = AccessTools.Field(typeof(ZNetPeer), "m_uid");

	private static readonly FieldInfo ZdoUid = AccessTools.Field(typeof(ZDO), "m_uid");

	private static readonly FieldInfo LocalPlayer = AccessTools.Field(typeof(Player), "m_localPlayer");

	private static readonly FieldInfo PlayerTeleporting = AccessTools.Field(typeof(Player), "m_teleporting");

	private static readonly FieldInfo Heightmaps = AccessTools.Field(typeof(Heightmap), "s_heightmaps");

	private static readonly MethodInfo NetGetPeer = SafeMethod(typeof(ZNet), "GetPeer", typeof(ZRpc));

	private static readonly MethodInfo HeightmapHaveQueuedRebuild = SafeMethod(typeof(Heightmap), "HaveQueuedRebuild", Type.EmptyTypes);

	private static readonly MethodInfo HeightmapRegenerate = SafeMethod(typeof(Heightmap), "Regenerate", Type.EmptyTypes);

	private static readonly MethodInfo ZdoFindPeer = SafeMethod(typeof(ZDOMan), "FindPeer", typeof(ZNetPeer));

	private static readonly MethodInfo ZdoRpcZdoData = SafeMethod(typeof(ZDOMan), "RPC_ZDOData", typeof(ZRpc), typeof(ZPackage));

	private static MethodInfo ZdoSendZdos;

	private static readonly MethodInfo SceneInLoadingScreen = SafeMethod(typeof(ZNetScene), "InLoadingScreen", Type.EmptyTypes);

	private static readonly MethodInfo SceneCreateObjectsSorted = SafeMethod(typeof(ZNetScene), "CreateObjectsSorted", typeof(List<ZDO>), typeof(int), typeof(int).MakeByRefType());

	private static readonly MethodInfo SceneCreateDistantObjects = SafeMethod(typeof(ZNetScene), "CreateDistantObjects", typeof(List<ZDO>), typeof(int), typeof(int).MakeByRefType());

	private static readonly MethodInfo ZoneCreateLocalZones = SafeMethod(typeof(ZoneSystem), "CreateLocalZones", typeof(Vector3));

	private static MethodInfo SafeMethod(Type type, string name, params Type[] parameters)
	{
		try
		{
			return AccessTools.Method(type, name, parameters, (Type[])null);
		}
		catch
		{
			return null;
		}
	}

	internal static void LogResolution()
	{
		ValheimOptimizerPlugin.Log.LogInfo((object)$"Private access: GetPeer={NetGetPeer != null}, FindPeer={ZdoFindPeer != null}, RPC_ZDOData={ZdoRpcZdoData != null}, InLoadingScreen={SceneInLoadingScreen != null}, CreateObjectsSorted={SceneCreateObjectsSorted != null}, CreateDistantObjects={SceneCreateDistantObjects != null}, CreateLocalZones={ZoneCreateLocalZones != null}, HeightmapWarm={Heightmaps != null && HeightmapHaveQueuedRebuild != null && HeightmapRegenerate != null}");
	}

	internal static ZRpc GetRpc(ZNetPeer peer)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		if (peer != null && !(PeerRpc == null))
		{
			return (ZRpc)PeerRpc.GetValue(peer);
		}
		return null;
	}

	internal static long GetUid(ZNetPeer peer)
	{
		if (peer != null && !(PeerUid == null))
		{
			return (long)PeerUid.GetValue(peer);
		}
		return 0L;
	}

	internal static ZDOID GetZdoUid(ZDO zdo)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		if (zdo != null && !(ZdoUid == null))
		{
			return (ZDOID)ZdoUid.GetValue(zdo);
		}
		return ZDOID.None;
	}

	internal static Player GetLocalPlayer()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		if (!(LocalPlayer == null))
		{
			return (Player)LocalPlayer.GetValue(null);
		}
		return null;
	}

	internal static bool IsTeleporting(Player player)
	{
		if ((Object)(object)player != (Object)null && PlayerTeleporting != null)
		{
			return (bool)PlayerTeleporting.GetValue(player);
		}
		return false;
	}

	internal static ZNetPeer GetNetPeer(ZNet net, ZRpc rpc)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Expected O, but got Unknown
		if ((Object)(object)net == (Object)null || rpc == null || NetGetPeer == null)
		{
			return null;
		}
		try
		{
			return (ZNetPeer)NetGetPeer.Invoke(net, new object[1] { rpc });
		}
		catch
		{
			return null;
		}
	}

	internal static List<Heightmap> GetHeightmaps()
	{
		if (Heightmaps == null)
		{
			return null;
		}
		try
		{
			return (List<Heightmap>)Heightmaps.GetValue(null);
		}
		catch
		{
			return null;
		}
	}

	internal static bool HeightmapNeedsRebuild(Heightmap h)
	{
		if ((Object)(object)h == (Object)null || HeightmapHaveQueuedRebuild == null)
		{
			return false;
		}
		try
		{
			return (bool)HeightmapHaveQueuedRebuild.Invoke(h, null);
		}
		catch
		{
			return false;
		}
	}

	internal static bool RegenerateHeightmap(Heightmap h)
	{
		if ((Object)(object)h == (Object)null || HeightmapRegenerate == null)
		{
			return false;
		}
		try
		{
			HeightmapRegenerate.Invoke(h, null);
			return true;
		}
		catch
		{
			return false;
		}
	}

	internal static bool IsInLoadingScreen(ZNetScene scene)
	{
		if ((Object)(object)scene == (Object)null || SceneInLoadingScreen == null)
		{
			return false;
		}
		return (bool)SceneInLoadingScreen.Invoke(scene, null);
	}

	internal static bool ReceiveZdoData(ZDOMan man, ZRpc rpc, ZPackage pkg)
	{
		if (man == null || rpc == null || pkg == null || ZdoRpcZdoData == null)
		{
			return false;
		}
		try
		{
			ZdoRpcZdoData.Invoke(man, new object[2] { rpc, pkg });
			return true;
		}
		catch
		{
			return false;
		}
	}

	internal static bool TrySendZdosToPeer(ZDOMan man, ZNetPeer peer, bool flush, out bool sentData)
	{
		sentData = false;
		if (man == null || peer == null || ZdoFindPeer == null)
		{
			return false;
		}
		try
		{
			object obj = ZdoFindPeer.Invoke(man, new object[1] { peer });
			if (obj == null)
			{
				return false;
			}
			if (ZdoSendZdos == null)
			{
				ZdoSendZdos = SafeMethod(typeof(ZDOMan), "SendZDOs", obj.GetType(), typeof(bool));
			}
			if (ZdoSendZdos == null)
			{
				return false;
			}
			sentData = (bool)ZdoSendZdos.Invoke(man, new object[2] { obj, flush });
			return true;
		}
		catch
		{
			return false;
		}
	}

	internal static void CreateObjectsFast(ZNetScene scene, List<ZDO> near, List<ZDO> distant, int maxCreated, out int created)
	{
		if (SceneCreateObjectsSorted == null || SceneCreateDistantObjects == null)
		{
			throw new MissingMethodException("ZNetScene object creation methods not found");
		}
		created = 0;
		object[] array = new object[3] { near, maxCreated, created };
		SceneCreateObjectsSorted.Invoke(scene, array);
		created = (int)array[2];
		object[] array2 = new object[3] { distant, maxCreated, created };
		SceneCreateDistantObjects.Invoke(scene, array2);
		created = (int)array2[2];
	}

	internal static bool CreateLocalZones(ZoneSystem z, Vector3 target)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)z == (Object)null || ZoneCreateLocalZones == null)
		{
			return false;
		}
		return (bool)ZoneCreateLocalZones.Invoke(z, new object[1] { target });
	}
}
internal static class NetworkOptimizations
{
	internal const string HelloRpc = "MagiOpt_Hello_v1";

	internal const string CompressedZdoRpc = "MagiOpt_ZDO_v1";

	internal const string PortalPrefetchRpc = "MagiOpt_PortalPrefetch_v1";

	internal const string InitialAreaRequestRpc = "MagiOpt_InitialAreaReq_v1";

	internal const string InitialAreaReadyRpc = "MagiOpt_InitialAreaReady_v1";

	private static readonly Dictionary<ZRpc, PeerState> Peers = new Dictionary<ZRpc, PeerState>();

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

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

	private static int _roundRobin;

	private static bool _clientInitialAreaReady;

	private static Vector3 _clientInitialAreaTarget;

	private static Vector3 _lastInitialAreaRequestTarget;

	private static float _lastInitialAreaRequestAt;

	internal static void Initialize()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		Peers.Clear();
		_roundRobin = 0;
		_clientInitialAreaReady = false;
		_clientInitialAreaTarget = Vector3.zero;
		_lastInitialAreaRequestTarget = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
		_lastInitialAreaRequestAt = -100f;
	}

	internal static void RegisterPeer(ZNetPeer peer)
	{
		ZRpc rpc = PrivateAccess.GetRpc(peer);
		if (rpc == null)
		{
			return;
		}
		if (!Peers.ContainsKey(rpc))
		{
			Peers[rpc] = new PeerState
			{
				RegisteredAt = Time.realtimeSinceStartup
			};
		}
		if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer())
		{
			_clientInitialAreaReady = false;
		}
		try
		{
			rpc.Register<int>("MagiOpt_Hello_v1", (Action<ZRpc, int>)OnHello);
			rpc.Register<ZPackage>("MagiOpt_ZDO_v1", (Action<ZRpc, ZPackage>)OnCompressedZdo);
			rpc.Register<ZPackage>("MagiOpt_PortalPrefetch_v1", (Action<ZRpc, ZPackage>)OnPortalPrefetch);
			rpc.Register<ZPackage>("MagiOpt_InitialAreaReq_v1", (Action<ZRpc, ZPackage>)OnInitialAreaRequest);
			rpc.Register<ZPackage>("MagiOpt_InitialAreaReady_v1", (Action<ZRpc, ZPackage>)OnInitialAreaReady);
		}
		catch (Exception ex)
		{
			ValheimOptimizerPlugin.Log.LogWarning((object)("Peer optimizer RPC registration failed: " + ex.Message));
		}
	}

	internal static void RemovePeer(ZNetPeer peer)
	{
		ZRpc rpc = PrivateAccess.GetRpc(peer);
		if (rpc != null)
		{
			Peers.Remove(rpc);
		}
		if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer())
		{
			_clientInitialAreaReady = false;
		}
	}

	internal static bool IsNegotiated(ZRpc rpc)
	{
		if (rpc != null && Peers.TryGetValue(rpc, out var value))
		{
			return value.Negotiated;
		}
		return false;
	}

	private static void OnHello(ZRpc rpc, int protocol)
	{
		if (!Peers.TryGetValue(rpc, out var value))
		{
			value = new PeerState
			{
				RegisteredAt = Time.realtimeSinceStartup
			};
			Peers[rpc] = value;
		}
		value.RemoteProtocol = protocol;
		bool negotiated = value.Negotiated;
		value.Negotiated = protocol == 4;
		if (value.Negotiated && !value.HelloSent)
		{
			try
			{
				rpc.Invoke("MagiOpt_Hello_v1", new object[1] { 4 });
				value.HelloSent = true;
				value.HelloAttempts++;
			}
			catch
			{
			}
		}
		if (value.Negotiated && !negotiated)
		{
			Metrics.Handshakes++;
			ValheimOptimizerPlugin.Log.LogInfo((object)"Optimizer network protocol negotiated with peer");
			Benchmarking.OnNegotiated();
		}
	}

	internal static void SendPendingHellos()
	{
		try
		{
			if (ZDOMan.instance == null || (Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			List<ZNetPeer> peers = ZNet.instance.GetPeers();
			bool flag = ZNet.instance.IsServer();
			for (int i = 0; i < peers.Count; i++)
			{
				ZNetPeer peer = peers[i];
				ZRpc rpc = PrivateAccess.GetRpc(peer);
				if (rpc == null)
				{
					continue;
				}
				if (!Peers.TryGetValue(rpc, out var value))
				{
					RegisterPeer(peer);
					if (!Peers.TryGetValue(rpc, out value))
					{
						continue;
					}
				}
				if (!flag)
				{
					if (!value.Negotiated && !value.CompatibilityLogged && Time.realtimeSinceStartup - value.RegisteredAt >= 6f)
					{
						value.CompatibilityLogged = true;
						ValheimOptimizerPlugin.Log.LogInfo((object)"Remote server did not advertise Valheim Optimizer; vanilla compatibility mode active");
					}
				}
				else if (!value.Negotiated && value.HelloAttempts < 3)
				{
					rpc.Invoke("MagiOpt_Hello_v1", new object[1] { 4 });
					value.HelloSent = true;
					value.HelloAttempts++;
				}
			}
		}
		catch (Exception ex)
		{
			ValheimOptimizerPlugin.Log.LogDebug((object)("Hello pass skipped: " + ex.Message));
		}
	}

	internal static bool ClientServerNegotiated()
	{
		try
		{
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			if (ZNet.instance.IsServer())
			{
				return true;
			}
			return IsNegotiated(ZNet.instance.GetServerRPC());
		}
		catch
		{
			return false;
		}
	}

	internal static bool AllPeersNegotiated()
	{
		if (ZDOMan.instance == null || (Object)(object)ZNet.instance == (Object)null)
		{
			return false;
		}
		List<ZNetPeer> peers = ZNet.instance.GetPeers();
		if (peers == null || peers.Count == 0)
		{
			return false;
		}
		for (int i = 0; i < peers.Count; i++)
		{
			if (!IsNegotiated(PrivateAccess.GetRpc(peers[i])))
			{
				return false;
			}
		}
		return true;
	}

	internal static int GetWindowBytes()
	{
		if (!AllPeersNegotiated())
		{
			return 10240;
		}
		return ValheimOptimizerPlugin.ReplicationWindowKiB.Value * 1024;
	}

	internal static int GetMinRoomBytes()
	{
		if (!AllPeersNegotiated())
		{
			return 2048;
		}
		return Math.Min(GetWindowBytes() / 2, ValheimOptimizerPlugin.ReplicationMinRoomKiB.Value * 1024);
	}

	internal static bool TryRunScheduler(ZDOMan man, float dt)
	{
		if (!ValheimOptimizerPlugin.EnableNetworkScheduler.Value || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || !AllPeersNegotiated())
		{
			return false;
		}
		List<ZNetPeer> peers = ZNet.instance.GetPeers();
		int count = peers.Count;
		if (count == 0)
		{
			return true;
		}
		float num = 1f / (float)Math.Max(1, ValheimOptimizerPlugin.OptimizedReplicationHz.Value);
		for (int i = 0; i < count; i++)
		{
			ZRpc rpc = PrivateAccess.GetRpc(peers[i]);
			if (Peers.TryGetValue(rpc, out var value))
			{
				value.SendAccumulator = Math.Min(0.5f, value.SendAccumulator + dt);
			}
		}
		long timestamp = Stopwatch.GetTimestamp();
		double num2 = ValheimOptimizerPlugin.NetworkMainThreadBudgetMs.Value;
		int num3 = 0;
		for (int j = 0; j < count; j++)
		{
			int index = (_roundRobin + j) % count;
			ZNetPeer val = peers[index];
			ZRpc rpc2 = PrivateAccess.GetRpc(val);
			if (Peers.TryGetValue(rpc2, out var value2) && !(value2.SendAccumulator + 0.0001f < num))
			{
				if (!PrivateAccess.TrySendZdosToPeer(man, val, flush: false, out var sentData))
				{
					return false;
				}
				UpdateInitialAreaReady(value2, rpc2, val, sentData);
				double num4 = (double)(Stopwatch.GetTimestamp() - timestamp) * 1000.0 / (double)Stopwatch.Frequency;
				if (num3 > 0 && num4 >= num2)
				{
					Metrics.SchedulerBudgetHits++;
					break;
				}
				value2.SendAccumulator = Math.Max(0f, value2.SendAccumulator - num);
				num3++;
				Metrics.SchedulerPeerServices++;
			}
		}
		_roundRobin = (_roundRobin + Math.Max(1, num3)) % Math.Max(1, count);
		Metrics.SchedulerPasses++;
		return true;
	}

	internal static void MarkUrgent(ZRpc rpc)
	{
		if (rpc != null && Peers.TryGetValue(rpc, out var value))
		{
			value.SendAccumulator = 1f;
		}
	}

	internal static bool TryCompressZdoRpc(ZRpc rpc, ref string method, ref object[] parameters)
	{
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Expected O, but got Unknown
		if (!ValheimOptimizerPlugin.EnableZdoCompression.Value || method != "ZDOData" || !IsNegotiated(rpc))
		{
			return false;
		}
		if (parameters != null && parameters.Length == 1)
		{
			object obj = parameters[0];
			ZPackage val = (ZPackage)((obj is ZPackage) ? obj : null);
			if (val != null)
			{
				int num = val.Size();
				if (num < ValheimOptimizerPlugin.CompressionThresholdBytes.Value)
				{
					return false;
				}
				long timestamp = Stopwatch.GetTimestamp();
				try
				{
					ZPackage val2 = new ZPackage();
					val2.WriteCompressed(val);
					int num2 = val2.Size();
					if (num2 + 16 >= num)
					{
						return false;
					}
					method = "MagiOpt_ZDO_v1";
					parameters = new object[1] { val2 };
					Interlocked.Increment(ref Metrics.CompressedPackets);
					Interlocked.Add(ref Metrics.ZdoBytesBeforeCompression, num);
					Interlocked.Add(ref Metrics.ZdoBytesAfterCompression, num2);
					return true;
				}
				catch (Exception ex)
				{
					ValheimOptimizerPlugin.Log.LogWarning((object)("ZDO compression failed; sending vanilla packet: " + ex.Message));
					return false;
				}
				finally
				{
					Interlocked.Add(ref Metrics.CompressionStopwatchTicks, Stopwatch.GetTimestamp() - timestamp);
				}
			}
		}
		return false;
	}

	private static void OnCompressedZdo(ZRpc rpc, ZPackage packed)
	{
		try
		{
			ZPackage pkg = packed.ReadCompressedPackage();
			Interlocked.Increment(ref Metrics.DecompressedPackets);
			if (!PrivateAccess.ReceiveZdoData(ZDOMan.instance, rpc, pkg))
			{
				throw new MissingMethodException("RPC_ZDOData(ZRpc,ZPackage) unavailable");
			}
		}
		catch (Exception arg)
		{
			ValheimOptimizerPlugin.Log.LogError((object)$"Compressed ZDO receive failed: {arg}");
		}
	}

	internal static void RequestInitialArea(Vector3 target)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Expected O, but got Unknown
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer() || !ClientServerNegotiated() || float.IsNaN(target.x) || float.IsNaN(target.y) || float.IsNaN(target.z))
		{
			return;
		}
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		bool flag = Vector3.SqrMagnitude(target - _lastInitialAreaRequestTarget) > 16f;
		if ((!flag && _clientInitialAreaReady) || (!flag && realtimeSinceStartup - _lastInitialAreaRequestAt < 1f))
		{
			return;
		}
		_lastInitialAreaRequestTarget = target;
		_lastInitialAreaRequestAt = realtimeSinceStartup;
		if (flag)
		{
			_clientInitialAreaReady = false;
		}
		_clientInitialAreaTarget = target;
		ZRpc serverRPC = ZNet.instance.GetServerRPC();
		if (IsNegotiated(serverRPC))
		{
			ZPackage val = new ZPackage();
			val.Write(target);
			serverRPC.Invoke("MagiOpt_InitialAreaReq_v1", new object[1] { val });
			ISocket socket = serverRPC.GetSocket();
			if (socket != null)
			{
				socket.Flush();
			}
			ValheimOptimizerPlugin.Log.LogInfo((object)$"OPT BENCH initial-area-request target={target}");
		}
	}

	internal static bool ClientInitialAreaReadyFor(Vector3 target)
	{
		//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_000d: Unknown result type (might be due to invalid IL or missing references)
		if (_clientInitialAreaReady)
		{
			return Vector3.SqrMagnitude(target - _clientInitialAreaTarget) <= 64f;
		}
		return false;
	}

	private static void OnInitialAreaRequest(ZRpc rpc, ZPackage pkg)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: 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_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || !IsNegotiated(rpc) || !Peers.TryGetValue(rpc, out var value))
		{
			return;
		}
		try
		{
			Vector3 val = pkg.ReadVector3();
			if (float.IsNaN(val.x) || float.IsNaN(val.y) || float.IsNaN(val.z) || float.IsInfinity(val.x) || float.IsInfinity(val.y) || float.IsInfinity(val.z) || (value.InitialAreaRequested && Vector3.SqrMagnitude(value.InitialAreaTarget - val) <= 16f))
			{
				return;
			}
			value.InitialAreaRequested = true;
			value.InitialAreaTarget = val;
			value.InitialAreaStablePasses = 0;
			value.InitialAreaReadySent = false;
			ZNetPeer netPeer = PrivateAccess.GetNetPeer(ZNet.instance, rpc);
			if (netPeer != null)
			{
				PrefetchNear.Clear();
				Vector2s zone = ZoneSystem.GetZone(val);
				ZDOMan.instance.FindSectorObjects(zone, new SimulationDistance(1, 0, false), PrefetchNear, (List<ZDO>)null);
				long uid = PrivateAccess.GetUid(netPeer);
				for (int i = 0; i < PrefetchNear.Count; i++)
				{
					ZDOMan.instance.ForceSendZDO(uid, PrivateAccess.GetZdoUid(PrefetchNear[i]));
				}
				MarkUrgent(rpc);
				ValheimOptimizerPlugin.Log.LogInfo((object)$"Initial area requested at {val}; prioritized {PrefetchNear.Count} near ZDOs");
			}
		}
		catch (Exception ex)
		{
			ValheimOptimizerPlugin.Log.LogWarning((object)("Initial area request failed: " + ex.Message));
		}
	}

	private static void OnInitialAreaReady(ZRpc rpc, ZPackage pkg)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer() || !IsNegotiated(rpc))
		{
			return;
		}
		try
		{
			Vector3 val = pkg.ReadVector3();
			if (!(Vector3.SqrMagnitude(val - _clientInitialAreaTarget) > 64f))
			{
				_clientInitialAreaReady = true;
				ValheimOptimizerPlugin.Log.LogInfo((object)$"OPT BENCH initial-area-server-ready target={val}");
			}
		}
		catch
		{
		}
	}

	private static void UpdateInitialAreaReady(PeerState state, ZRpc rpc, ZNetPeer netPeer, bool sentData)
	{
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Expected O, but got Unknown
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		if (state == null || !state.InitialAreaRequested || state.InitialAreaReadySent || rpc == null || netPeer == null)
		{
			return;
		}
		if (sentData)
		{
			state.InitialAreaStablePasses = 0;
			return;
		}
		int num = ((netPeer.m_socket != null) ? netPeer.m_socket.GetSendQueueSize() : int.MaxValue);
		if (num > 4096)
		{
			state.InitialAreaStablePasses = 0;
			return;
		}
		state.InitialAreaStablePasses++;
		if (state.InitialAreaStablePasses >= 3)
		{
			ZPackage val = new ZPackage();
			val.Write(state.InitialAreaTarget);
			rpc.Invoke("MagiOpt_InitialAreaReady_v1", new object[1] { val });
			ISocket socket = rpc.GetSocket();
			if (socket != null)
			{
				socket.Flush();
			}
			state.InitialAreaReadySent = true;
			ValheimOptimizerPlugin.Log.LogInfo((object)$"Initial area replication complete target={state.InitialAreaTarget} queue={num}");
		}
	}

	internal static void RequestPortalPrefetch(Vector3 target)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		if (!ValheimOptimizerPlugin.EnablePortalPrefetch.Value || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer())
		{
			return;
		}
		ZRpc serverRPC = ZNet.instance.GetServerRPC();
		if (IsNegotiated(serverRPC))
		{
			ZPackage val = new ZPackage();
			val.Write(target);
			ISocket socket = serverRPC.GetSocket();
			int num = ((socket != null) ? socket.GetSendQueueSize() : 0);
			serverRPC.Invoke("MagiOpt_PortalPrefetch_v1", new object[1] { val });
			if (socket != null)
			{
				socket.Flush();
			}
			ValheimOptimizerPlugin.Log.LogDebug((object)$"Portal prefetch request sent target={target} queueBefore={num} queueAfter={((socket != null) ? socket.GetSendQueueSize() : 0)}");
		}
	}

	private static void OnPortalPrefetch(ZRpc rpc, ZPackage pkg)
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: 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_0146: 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)
		if (!ValheimOptimizerPlugin.EnablePortalPrefetch.Value || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || !IsNegotiated(rpc))
		{
			return;
		}
		try
		{
			if (!Peers.TryGetValue(rpc, out var value))
			{
				return;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (realtimeSinceStartup - value.LastPrefetchRequest < 1.5f)
			{
				return;
			}
			value.LastPrefetchRequest = realtimeSinceStartup;
			Vector3 val = pkg.ReadVector3();
			if (float.IsNaN(val.x) || float.IsNaN(val.y) || float.IsNaN(val.z) || float.IsInfinity(val.x) || float.IsInfinity(val.y) || float.IsInfinity(val.z))
			{
				return;
			}
			ZNetPeer netPeer = PrivateAccess.GetNetPeer(ZNet.instance, rpc);
			if (netPeer == null)
			{
				return;
			}
			long uid = PrivateAccess.GetUid(netPeer);
			if (uid != 0L)
			{
				PrefetchNear.Clear();
				PrefetchDistant.Clear();
				Vector2s zone = ZoneSystem.GetZone(val);
				ZDOMan.instance.FindSectorObjects(zone, ZNet.instance.GetSyncedSimulationDistance(), PrefetchNear, PrefetchDistant);
				int value2 = ValheimOptimizerPlugin.PortalPrefetchMaxZdos.Value;
				int num = 0;
				int num2 = 0;
				while (num2 < PrefetchNear.Count && num < value2)
				{
					ZDOMan.instance.ForceSendZDO(uid, PrivateAccess.GetZdoUid(PrefetchNear[num2]));
					num2++;
					num++;
				}
				int num3 = 0;
				while (num3 < PrefetchDistant.Count && num < value2)
				{
					ZDOMan.instance.ForceSendZDO(uid, PrivateAccess.GetZdoUid(PrefetchDistant[num3]));
					num3++;
					num++;
				}
				MarkUrgent(rpc);
				Metrics.PortalPrefetchRequests++;
				Metrics.PortalZdosQueued += num;
				ValheimOptimizerPlugin.Log.LogInfo((object)$"Portal prefetch queued {num} destination ZDOs ({PrefetchNear.Count} near, {PrefetchDistant.Count} distant candidates)");
			}
		}
		catch (Exception ex)
		{
			ValheimOptimizerPlugin.Log.LogWarning((object)("Portal prefetch request failed: " + ex.Message));
		}
	}
}
internal static class LoadingOptimizations
{
	private static bool _clientPrefetch;

	private static Vector3 _prefetchTarget;

	private static float _prefetchStarted;

	private static int _terrainStableFrames;

	private static bool _baseTerrainLogged;

	private static bool _heightmapWarmLogged;

	private static bool _priorityChanged;

	private static ThreadPriority _oldPriority;

	internal static void Initialize()
	{
		_clientPrefetch = false;
		_terrainStableFrames = 0;
		_baseTerrainLogged = false;
		_heightmapWarmLogged = false;
		_priorityChanged = false;
	}

	internal static int GetAdaptiveLoadingObjectLimit()
	{
		int value = ValheimOptimizerPlugin.LoadingObjectLimit.Value;
		float unscaledDeltaTime = Time.unscaledDeltaTime;
		if (unscaledDeltaTime > 0.09f)
		{
			return 100;
		}
		if (unscaledDeltaTime > 0.06f)
		{
			return Math.Min(value, 140);
		}
		if (unscaledDeltaTime > 0.04f)
		{
			return Math.Min(value, 200);
		}
		return value;
	}

	internal static float GetMinimumDistantTeleportSeconds()
	{
		if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer() && !NetworkOptimizations.ClientServerNegotiated())
		{
			return 8f;
		}
		return ValheimOptimizerPlugin.MinimumDistantTeleportSeconds.Value;
	}

	internal static void BeginPortalPrefetch(Vector3 target)
	{
		//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_003c: Unknown result type (might be due to invalid IL or missing references)
		if (ValheimOptimizerPlugin.EnablePortalPrefetch.Value && NetworkOptimizations.ClientServerNegotiated())
		{
			_prefetchTarget = target;
			_prefetchStarted = Time.realtimeSinceStartup;
			_clientPrefetch = true;
			_terrainStableFrames = 0;
			_baseTerrainLogged = false;
			_heightmapWarmLogged = false;
			NetworkOptimizations.RequestPortalPrefetch(target);
			SetHighLoadingPriority();
		}
	}

	internal static void EndPortalPrefetch()
	{
		_clientPrefetch = false;
		RestoreLoadingPriority();
	}

	internal static void UpdateClientPrefetch()
	{
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsDedicated())
			{
				return;
			}
			if (!NetworkOptimizations.ClientServerNegotiated())
			{
				_clientPrefetch = false;
				RestoreLoadingPriority();
				return;
			}
			if (PrivateAccess.IsInLoadingScreen(ZNetScene.instance))
			{
				SetHighLoadingPriority();
			}
			else if (!_clientPrefetch)
			{
				RestoreLoadingPriority();
			}
			if (!_clientPrefetch || (Object)(object)ZoneSystem.instance == (Object)null || WorldGenerator.instance == null || HeightmapBuilder.instance == null)
			{
				return;
			}
			if (Time.realtimeSinceStartup - _prefetchStarted > 12f)
			{
				EndPortalPrefetch();
				ValheimOptimizerPlugin.Log.LogWarning((object)"Client portal terrain prefetch timed out after 12s");
				return;
			}
			Vector2s zone = ZoneSystem.GetZone(_prefetchTarget);
			Vector3 zonePos = ZoneSystem.GetZonePos(zone);
			Heightmap val = (((Object)(object)ZoneSystem.instance.m_zonePrefab != (Object)null) ? ZoneSystem.instance.m_zonePrefab.GetComponentInChildren<Heightmap>() : null);
			if ((Object)(object)val == (Object)null || !HeightmapBuilder.instance.IsTerrainReady(zonePos, val.m_width, val.m_scale, val.IsDistantLod, WorldGenerator.instance))
			{
				return;
			}
			if (!_baseTerrainLogged)
			{
				_baseTerrainLogged = true;
				Benchmarking.OnBaseTerrainReady();
			}
			int value = ValheimOptimizerPlugin.PortalZonesPerFrame.Value;
			for (int i = 0; i < value; i++)
			{
				if (PrivateAccess.CreateLocalZones(ZoneSystem.instance, _prefetchTarget))
				{
					Metrics.PortalZonesPoked++;
				}
			}
			if (!ZoneSystem.instance.IsZoneLoaded(_prefetchTarget))
			{
				_terrainStableFrames = 0;
				return;
			}
			List<Heightmap> heightmaps = PrivateAccess.GetHeightmaps();
			if (heightmaps == null || heightmaps.Count == 0)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			for (int j = 0; j < heightmaps.Count; j++)
			{
				Heightmap val2 = heightmaps[j];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Vector2s zone2 = ZoneSystem.GetZone(((Component)val2).transform.position);
				if (Math.Abs(zone2.x - zone.x) > 2 || Math.Abs(zone2.y - zone.y) > 2)
				{
					continue;
				}
				num++;
				if (num2 < 2 && PrivateAccess.HeightmapNeedsRebuild(val2) && PrivateAccess.RegenerateHeightmap(val2))
				{
					num2++;
					Metrics.PortalHeightmapsWarmed++;
					if (!_heightmapWarmLogged)
					{
						_heightmapWarmLogged = true;
						Benchmarking.OnHeightmapWarm();
					}
				}
			}
			if (num > 0)
			{
				_terrainStableFrames++;
			}
		}
		catch (Exception ex)
		{
			EndPortalPrefetch();
			ValheimOptimizerPlugin.Log.LogWarning((object)("Client portal terrain prefetch stopped: " + ex.Message));
		}
	}

	internal static void SetHighLoadingPriority()
	{
		//IL_0008: 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)
		if (!_priorityChanged)
		{
			_oldPriority = Application.backgroundLoadingPriority;
			Application.backgroundLoadingPriority = (ThreadPriority)4;
			_priorityChanged = true;
		}
	}

	internal static void RestoreLoadingPriority()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		if (_priorityChanged)
		{
			Application.backgroundLoadingPriority = _oldPriority;
			_priorityChanged = false;
		}
	}
}
internal static class Benchmarking
{
	private static float _joinStart = -1f;

	private static float _negotiatedAt = -1f;

	private static float _teleportStart = -1f;

	private static bool _teleportActiveSeen;

	internal static void OnJoinStart()
	{
		if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer())
		{
			_joinStart = Time.realtimeSinceStartup;
			_negotiatedAt = -1f;
			ValheimOptimizerPlugin.Log.LogInfo((object)"OPT BENCH join-start");
		}
	}

	internal static void OnPeerAdded()
	{
		if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer() && !(_joinStart >= 0f))
		{
			_joinStart = Time.realtimeSinceStartup;
			ValheimOptimizerPlugin.Log.LogInfo((object)"OPT BENCH join-start");
		}
	}

	internal static void OnNegotiated()
	{
		if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer())
		{
			if (_joinStart < 0f)
			{
				_joinStart = Time.realtimeSinceStartup;
			}
			_negotiatedAt = Time.realtimeSinceStartup;
			ValheimOptimizerPlugin.Log.LogInfo((object)$"OPT BENCH negotiated +{_negotiatedAt - _joinStart:F3}s");
		}
	}

	internal static void OnSpawned(Player player)
	{
		if (!((Object)(object)player == (Object)null) && !((Object)(object)PrivateAccess.GetLocalPlayer() != (Object)(object)player) && !(_joinStart < 0f))
		{
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			string arg = ((_negotiatedAt >= 0f) ? $" negotiated={_negotiatedAt - _joinStart:F3}s" : "");
			ValheimOptimizerPlugin.Log.LogInfo((object)$"OPT BENCH join-spawned total={realtimeSinceStartup - _joinStart:F3}s{arg} loadCreated={Metrics.LoadingObjectsCreated}");
			_joinStart = -1f;
			_negotiatedAt = -1f;
		}
	}

	internal static void BeginTeleport(Vector3 target, float distance, bool distantFlag)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		_teleportStart = Time.realtimeSinceStartup;
		_teleportActiveSeen = true;
		ValheimOptimizerPlugin.Log.LogInfo((object)$"OPT BENCH teleport-start distance={distance:F1}m distantFlag={distantFlag} target={target}");
	}

	internal static void OnBaseTerrainReady()
	{
		if (!(_teleportStart < 0f))
		{
			ValheimOptimizerPlugin.Log.LogInfo((object)$"OPT BENCH teleport-base-terrain-ready +{Time.realtimeSinceStartup - _teleportStart:F3}s");
		}
	}

	internal static void OnHeightmapWarm()
	{
		if (!(_teleportStart < 0f))
		{
			ValheimOptimizerPlugin.Log.LogInfo((object)$"OPT BENCH teleport-heightmap-warm +{Time.realtimeSinceStartup - _teleportStart:F3}s");
		}
	}

	internal static void OnTeleportUpdate(Player player)
	{
		if (!(_teleportStart < 0f) && !((Object)(object)player == (Object)null) && !((Object)(object)PrivateAccess.GetLocalPlayer() != (Object)(object)player))
		{
			if (PrivateAccess.IsTeleporting(player))
			{
				_teleportActiveSeen = true;
			}
			else if (_teleportActiveSeen)
			{
				LoadingOptimizations.EndPortalPrefetch();
				Metrics.PortalTerrainPrefetchCompleted++;
				ValheimOptimizerPlugin.Log.LogInfo((object)$"OPT BENCH teleport-complete total={Time.realtimeSinceStartup - _teleportStart:F3}s");
				_teleportStart = -1f;
				_teleportActiveSeen = false;
			}
		}
	}
}
internal static class Metrics
{
	internal static long Handshakes;

	internal static long CompressedPackets;

	internal static long DecompressedPackets;

	internal static long ZdoBytesBeforeCompression;

	internal static long ZdoBytesAfterCompression;

	internal static long CompressionStopwatchTicks;

	internal static long SchedulerPasses;

	internal static long SchedulerPeerServices;

	internal static long SchedulerBudgetHits;

	internal static long LoadingObjectsCreated;

	internal static long LoadingCreatePasses;

	internal static long PortalPrefetchRequests;

	internal static long PortalZdosQueued;

	internal static long PortalZonesPoked;

	internal static long PortalHeightmapsWarmed;

	internal static long PortalTerrainPrefetchCompleted;

	internal static void LogSummary()
	{
		long num = Interlocked.Read(in ZdoBytesBeforeCompression);
		long num2 = Interlocked.Read(in ZdoBytesAfterCompression);
		double num3 = ((num > 0) ? (100.0 * (double)(num - num2) / (double)num) : 0.0);
		double num4 = (double)Interlocked.Read(in CompressionStopwatchTicks) * 1000.0 / (double)Stopwatch.Frequency;
		ValheimOptimizerPlugin.Log.LogInfo((object)$"OPT METRICS peers={CountNegotiatedPeers()} zdoCompressed={CompressedPackets} rx={DecompressedPackets} bytes={num}->{num2} saved={num3:F1}% compCPU={num4:F1}ms schedulerServices={SchedulerPeerServices} budgetHits={SchedulerBudgetHits} loadCreated={LoadingObjectsCreated} portalReq={PortalPrefetchRequests} portalZDOs={PortalZdosQueued} zones={PortalZonesPoked} hmaps={PortalHeightmapsWarmed} terrainDone={PortalTerrainPrefetchCompleted}");
	}

	private static int CountNegotiatedPeers()
	{
		try
		{
			if (ZDOMan.instance == null || (Object)(object)ZNet.instance == (Object)null)
			{
				return 0;
			}
			int num = 0;
			List<ZNetPeer> peers = ZNet.instance.GetPeers();
			for (int i = 0; i < peers.Count; i++)
			{
				if (NetworkOptimizations.IsNegotiated(PrivateAccess.GetRpc(peers[i])))
				{
					num++;
				}
			}
			return num;
		}
		catch
		{
			return 0;
		}
	}
}
internal static class PatchDiagnostics
{
	internal static int WindowConstantsPatched;

	internal static int TeleportConstantsPatched;
}
[HarmonyPatch(typeof(ZNet), "Start")]
internal static class ZNetStartBenchmarkPatch
{
	private static void Postfix()
	{
		Benchmarking.OnJoinStart();
	}
}
[HarmonyPatch(typeof(ZDOMan), "AddPeer")]
internal static class AddPeerPatch
{
	private static void Postfix(ZNetPeer __0)
	{
		NetworkOptimizations.RegisterPeer(__0);
		Benchmarking.OnPeerAdded();
	}
}
[HarmonyPatch(typeof(ZDOMan), "RemovePeer")]
internal static class RemovePeerPatch
{
	private static void Prefix(ZNetPeer __0)
	{
		NetworkOptimizations.RemovePeer(__0);
	}
}
[HarmonyPatch(typeof(ZRpc), "Invoke", new Type[]
{
	typeof(string),
	typeof(object[])
})]
internal static class ZRpcInvokePatch
{
	private static void Prefix(ZRpc __instance, ref string __0, ref object[] __1)
	{
		NetworkOptimizations.TryCompressZdoRpc(__instance, ref __0, ref __1);
	}
}
[HarmonyPatch(typeof(ZDOMan), "SendZDOToPeers2")]
internal static class ZdoSchedulerPatch
{
	private static bool _failedOpen;

	private static bool Prefix(ZDOMan __instance, float __0)
	{
		if (_failedOpen)
		{
			return true;
		}
		try
		{
			return !NetworkOptimizations.TryRunScheduler(__instance, __0);
		}
		catch (Exception arg)
		{
			_failedOpen = true;
			ValheimOptimizerPlugin.Log.LogError((object)$"Replication scheduler failed; falling back to vanilla for this session: {arg}");
			return true;
		}
	}
}
[HarmonyPatch(typeof(ZDOMan), "SendZDOs")]
internal static class SendWindowPatch
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		MethodInfo window = AccessTools.Method(typeof(NetworkOptimizations), "GetWindowBytes", (Type[])null, (Type[])null);
		MethodInfo minRoom = AccessTools.Method(typeof(NetworkOptimizations), "GetMinRoomBytes", (Type[])null, (Type[])null);
		foreach (CodeInstruction instruction in instructions)
		{
			if (instruction.opcode == OpCodes.Ldc_I4 && instruction.operand is int num && num == 10240)
			{
				CodeInstruction val = new CodeInstruction(instruction)
				{
					opcode = OpCodes.Call,
					operand = window
				};
				PatchDiagnostics.WindowConstantsPatched++;
				yield return val;
			}
			else if (instruction.opcode == OpCodes.Ldc_I4 && instruction.operand is int num2 && num2 == 2048)
			{
				CodeInstruction val2 = new CodeInstruction(instruction)
				{
					opcode = OpCodes.Call,
					operand = minRoom
				};
				PatchDiagnostics.WindowConstantsPatched++;
				yield return val2;
			}
			else
			{
				yield return instruction;
			}
		}
	}
}
[HarmonyPatch(typeof(ZNetScene), "CreateObjects")]
internal static class FastObjectCreationPatch
{
	private static bool _failedOpen;

	private static bool Prefix(ZNetScene __instance, List<ZDO> __0, List<ZDO> __1)
	{
		if (_failedOpen || !ValheimOptimizerPlugin.EnableFastLoading.Value || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsDedicated() || !NetworkOptimizations.ClientServerNegotiated())
		{
			return true;
		}
		try
		{
			if (!PrivateAccess.IsInLoadingScreen(__instance))
			{
				return true;
			}
			int adaptiveLoadingObjectLimit = LoadingOptimizations.GetAdaptiveLoadingObjectLimit();
			PrivateAccess.CreateObjectsFast(__instance, __0, __1, adaptiveLoadingObjectLimit, out var created);
			Metrics.LoadingCreatePasses++;
			Metrics.LoadingObjectsCreated += created;
			return false;
		}
		catch (Exception arg)
		{
			_failedOpen = true;
			ValheimOptimizerPlugin.Log.LogError((object)$"Adaptive object creation failed; falling back to vanilla for this session: {arg}");
			return true;
		}
	}
}
[HarmonyPatch(typeof(Player), "TeleportTo")]
internal static class PlayerTeleportPatch
{
	private static void Postfix(Player __instance, Vector3 __0, Quaternion __1, bool __2, bool __result)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: 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)
		if (__result && !((Object)(object)PrivateAccess.GetLocalPlayer() != (Object)(object)__instance))
		{
			float num = Vector3.Distance(((Component)__instance).transform.position, __0);
			if (__2 || !(num < 32f))
			{
				Benchmarking.BeginTeleport(__0, num, __2);
				LoadingOptimizations.BeginPortalPrefetch(__0);
			}
		}
	}
}
[HarmonyPatch(typeof(ZNet), "SetReferencePosition")]
internal static class InitialAreaRequestPatch
{
	private static void Postfix(Vector3 __0)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer() && !((Object)(object)PrivateAccess.GetLocalPlayer() != (Object)null))
		{
			NetworkOptimizations.RequestInitialArea(__0);
		}
	}
}
[HarmonyPatch(typeof(Game), "FindSpawnPoint")]
internal static class InitialSpawnDelayPatch
{
	private static void Prefix(Game __instance)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer())
		{
			Vector3 referencePosition = ZNet.instance.GetReferencePosition();
			bool flag = NetworkOptimizations.ClientServerNegotiated() && !MinimapOptimizations.IsAfterDeathRespawn(__instance) && NetworkOptimizations.ClientInitialAreaReadyFor(referencePosition);
			__instance.m_respawnLoadDuration = (flag ? ValheimOptimizerPlugin.InitialSpawnMinimumSeconds.Value : 8f);
		}
	}
}
[HarmonyPatch(typeof(Minimap), "TryLoadMinimapTextureData")]
internal static class MinimapCacheLoadPatch
{
	private static bool Prefix(Minimap __instance, int worldSeed, ref bool __result)
	{
		if (!MinimapOptimizations.TryLoad(__instance, worldSeed))
		{
			return true;
		}
		__result = true;
		return false;
	}
}
[HarmonyPatch(typeof(Minimap), "GenerateWorldMap")]
internal static class MinimapCacheGeneratePatch
{
	private static void Prefix(Minimap __instance)
	{
		MinimapOptimizations.PrepareGeneration(__instance);
	}

	private static void Postfix(Minimap __instance)
	{
		MinimapOptimizations.MarkGenerated(__instance);
	}
}
[HarmonyPatch(typeof(Player), "OnSpawned")]
internal static class PlayerSpawnBenchmarkPatch
{
	private static void Postfix(Player __instance)
	{
		PreJoinLoadingOverlay.Hide();
		Benchmarking.OnSpawned(__instance);
	}
}
[HarmonyPatch(typeof(Player), "UpdateTeleport")]
internal static class TeleportBenchmarkPatch
{
	private static void Postfix(Player __instance)
	{
		Benchmarking.OnTeleportUpdate(__instance);
	}
}
[HarmonyPatch(typeof(Player), "UpdateTeleport")]
internal static class TeleportMinimumPatch
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		MethodInfo getter = AccessTools.Method(typeof(LoadingOptimizations), "GetMinimumDistantTeleportSeconds", (Type[])null, (Type[])null);
		foreach (CodeInstruction instruction in instructions)
		{
			if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num && Math.Abs(num - 8f) < 0.0001f)
			{
				CodeInstruction val = new CodeInstruction(instruction)
				{
					opcode = OpCodes.Call,
					operand = getter
				};
				PatchDiagnostics.TeleportConstantsPatched++;
				yield return val;
			}
			else
			{
				yield return instruction;
			}
		}
	}
}
internal sealed class PreJoinLoadingOverlay : MonoBehaviour
{
	private static PreJoinLoadingOverlay _instance;

	private static Texture2D _artworkTexture;

	private static bool _artworkLoadAttempted;

	private static bool _artworkAvailable;

	private static readonly MethodInfo LoadImageMethod = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule")?.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[3]
	{
		typeof(Texture2D),
		typeof(byte[]),
		typeof(bool)
	}, null);

	private string _tipKey;

	private GUIStyle _titleStyle;

	private GUIStyle _tipStyle;

	internal static void PreloadArtwork()
	{
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Expected O, but got Unknown
		if (_artworkLoadAttempted || !ValheimOptimizerPlugin.UseCustomLoadingScreen.Value)
		{
			return;
		}
		_artworkLoadAttempted = true;
		Texture2D val = null;
		try
		{
			string text = ValheimOptimizerPlugin.PluginDirectory;
			if (string.IsNullOrEmpty(text))
			{
				text = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			}
			string text2 = Path.Combine(text ?? Paths.PluginPath, "loading_screen.png");
			if (!File.Exists(text2))
			{
				ValheimOptimizerPlugin.Log.LogWarning((object)("Custom loading artwork not found at " + text2 + "; using black/text fallback"));
				return;
			}
			byte[] array = File.ReadAllBytes(text2);
			val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (LoadImageMethod == null)
			{
				throw new MissingMethodException("UnityEngine.ImageConversion.LoadImage was not found");
			}
			if (!(bool)LoadImageMethod.Invoke(null, new object[3] { val, array, false }) || ((Texture)val).width < 2 || ((Texture)val).height < 2)
			{
				throw new InvalidDataException("Loading-screen image decode returned an invalid texture");
			}
			((Object)val).name = "MagiCorp.ValheimOptimizer.LoadingScreen";
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			_artworkTexture = val;
			_artworkAvailable = true;
			ValheimOptimizerPlugin.Log.LogInfo((object)$"Custom loading artwork loaded once: {((Texture)val).width}x{((Texture)val).height} ({array.Length / 1024} KiB)");
		}
		catch (Exception ex)
		{
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)val);
			}
			_artworkTexture = null;
			_artworkAvailable = false;
			ValheimOptimizerPlugin.Log.LogWarning((object)("Custom loading artwork failed to load; using black/text fallback: " + ex.Message));
		}
	}

	internal static void Show()
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Expected O, but got Unknown
		try
		{
			if (ValheimOptimizerPlugin.UseCustomLoadingScreen.Value)
			{
				PreloadArtwork();
			}
			if ((Object)(object)_instance == (Object)null)
			{
				GameObject val = new GameObject("MagiCorp.PreJoinLoadingOverlay");
				Object.DontDestroyOnLoad((Object)val);
				_instance = val.AddComponent<PreJoinLoadingOverlay>();
			}
			string[] array = new string[3] { "$loadscreen_tip06", "$loadscreen_tip17", "$loadscreen_tip24" };
			_instance._tipKey = array[Random.Range(0, array.Length)];
			((Behaviour)_instance).enabled = true;
			ValheimOptimizerPlugin.Log.LogInfo((object)("Pre-join loading overlay shown artwork=" + (_artworkAvailable ? "custom" : "fallback") + " tip=" + _instance._tipKey));
		}
		catch (Exception ex)
		{
			ValheimOptimizerPlugin.Log.LogWarning((object)("Pre-join loading overlay failed: " + ex.Message));
		}
	}

	internal static void Hide()
	{
		if ((Object)(object)_instance != (Object)null)
		{
			((Behaviour)_instance).enabled = false;
		}
	}

	internal static void ReleaseResources()
	{
		if ((Object)(object)_artworkTexture != (Object)null)
		{
			Object.Destroy((Object)(object)_artworkTexture);
			_artworkTexture = null;
		}
		_artworkAvailable = false;
		_artworkLoadAttempted = false;
		if ((Object)(object)_instance != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)_instance).gameObject);
			_instance = null;
		}
	}

	private string Localize(string key)
	{
		try
		{
			return (Localization.instance != null) ? Localization.instance.Localize(key) : key;
		}
		catch
		{
			return key;
		}
	}

	private void EnsureStyles()
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Expected O, but got Unknown
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Expected O, but got Unknown
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		int fontSize = Math.Max(24, Screen.height / 32);
		int fontSize2 = Math.Max(16, Screen.height / 54);
		if (_titleStyle == null)
		{
			_titleStyle = new GUIStyle(GUI.skin.label);
			_titleStyle.alignment = (TextAnchor)4;
			_titleStyle.fontStyle = (FontStyle)1;
			_titleStyle.normal.textColor = Color.white;
		}
		if (_tipStyle == null)
		{
			_tipStyle = new GUIStyle(GUI.skin.label);
			_tipStyle.alignment = (TextAnchor)4;
			_tipStyle.wordWrap = true;
			_tipStyle.normal.textColor = Color.white;
		}
		_titleStyle.fontSize = fontSize;
		_tipStyle.fontSize = fontSize2;
	}

	private void OnGUI()
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		GUI.depth = -10000;
		GUI.color = Color.black;
		GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture);
		GUI.color = Color.white;
		EnsureStyles();
		if (ValheimOptimizerPlugin.UseCustomLoadingScreen.Value && _artworkAvailable && (Object)(object)_artworkTexture != (Object)null)
		{
			GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)_artworkTexture, (ScaleMode)1, true);
			return;
		}
		float num = (float)Screen.height * 0.43f;
		GUI.Label(new Rect((float)Screen.width * 0.15f, num, (float)Screen.width * 0.7f, 60f), "Loading...", _titleStyle);
		GUI.Label(new Rect((float)Screen.width * 0.18f, num + 72f, (float)Screen.width * 0.64f, 120f), Localize(_tipKey ?? "$loadscreen_tip06"), _tipStyle);
	}
}
[HarmonyPatch(typeof(Hud), "UpdateBlackScreen")]
internal static class PreJoinLoadingOverlayHandoffPatch
{
	private static void Postfix()
	{
		if ((Object)(object)Game.instance != (Object)null && Game.instance.WaitingForRespawn())
		{
			PreJoinLoadingOverlay.Hide();
		}
	}
}
[HarmonyPatch(typeof(FejdStartup), "ShowConnectError")]
internal static class PreJoinLoadingOverlayErrorPatch
{
	private static void Prefix()
	{
		PreJoinLoadingOverlay.Hide();
	}
}
[HarmonyPatch(typeof(FejdStartup), "TransitionToMainScene")]
internal static class ImmediateLoadingScreenPatch
{
	private static readonly MethodInfo BackendCheck = AccessTools.Method(typeof(FejdStartup), "LoadMainSceneIfBackendSelected", (Type[])null, (Type[])null);

	private static IEnumerator ContinueAfterPresentedFrame(FejdStartup startup)
	{
		yield return null;
		try
		{
			BackendCheck?.Invoke(startup, null);
		}
		catch (Exception ex)
		{
			ValheimOptimizerPlugin.Log.LogWarning((object)("Deferred backend check failed: " + ex.Message));
		}
	}

	private static bool Prefix(FejdStartup __instance)
	{
		if (!ValheimOptimizerPlugin.ImmediateJoinLoadingScreen.Value || (Object)(object)__instance == (Object)null || (Object)(object)__instance.m_loading == (Object)null || BackendCheck == null)
		{
			return true;
		}
		try
		{
			PreJoinLoadingOverlay.Show();
			__instance.m_loading.SetActive(true);
			ZCursor.Hide();
			((MonoBehaviour)__instance).StartCoroutine(ContinueAfterPresentedFrame(__instance));
			ValheimOptimizerPlugin.Log.LogInfo((object)"Immediate loading screen activated; presenting a frame before scene load");
			return false;
		}
		catch (Exception ex)
		{
			ValheimOptimizerPlugin.Log.LogWarning((object)("Immediate loading transition failed; using vanilla fade: " + ex.Message));
			return true;
		}
	}
}
[HarmonyPatch(typeof(FejdStartup), "LoadMainScene")]
internal static class AsyncJoinScenePatch
{
	private static readonly FieldInfo StartingWorldField = AccessTools.Field(typeof(FejdStartup), "m_startingWorld");

	private static bool Prefix(FejdStartup __instance)
	{
		if (ValheimOptimizerPlugin.AsyncJoinSceneLoad.Value)
		{
			ValheimOptimizerPlugin.Log.LogWarning((object)"AsyncJoinSceneLoad is temporarily safety-disabled in 0.1.17; using Valheim's normal scene loader");
		}
		return true;
	}
}
internal static class MinimalMainMenuOptimizations
{
	internal static void InitializeMenuWorldIfNeeded(World world)
	{
		if (Application.isBatchMode)
		{
			WorldGenerator.Initialize(world);
		}
		else if (ValheimOptimizerPlugin.MinimalMainMenu.Value)
		{
			ValheimOptimizerPlugin.Log.LogInfo((object)"Minimal main menu: skipped WorldGenerator.Initialize(menu world); gameplay world initialization remains handled by ZNet");
		}
		else
		{
			WorldGenerator.Initialize(world);
		}
	}

	private static bool IsUnderUiRoot(Transform transform, FejdStartup startup)
	{
		if ((Object)(object)transform == (Object)null || (Object)(object)startup == (Object)null)
		{
			return false;
		}
		GameObject[] array = (GameObject[])(object)new GameObject[6] { startup.m_mainMenu, startup.m_menuList, startup.m_loading, startup.m_characterSelectScreen, startup.m_startGamePanel, startup.m_creditsPanel };
		foreach (GameObject val in array)
		{
			if ((Object)(object)val != (Object)null && transform.IsChildOf(val.transform))
			{
				return true;
			}
		}
		return false;
	}

	internal static void Apply(FejdStartup startup)
	{
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		if (Application.isBatchMode || !ValheimOptimizerPlugin.MinimalMainMenu.Value || (Object)(object)startup == (Object)null || (Object)(object)startup.m_mainCamera == (Object)null)
		{
			return;
		}
		try
		{
			Camera component = startup.m_mainCamera.GetComponent<Camera>();
			int num = 0;
			if ((Object)(object)startup.m_mainMenu != (Object)null)
			{
				num |= 1 << startup.m_mainMenu.layer;
			}
			if ((Object)(object)startup.m_menuList != (Object)null)
			{
				num |= 1 << startup.m_menuList.layer;
			}
			if ((Object)(object)startup.m_loading != (Object)null)
			{
				num |= 1 << startup.m_loading.layer;
			}
			if ((Object)(object)startup.m_characterSelectScreen != (Object)null)
			{
				num |= 1 << startup.m_characterSelectScreen.layer;
			}
			if ((Object)(object)startup.m_startGamePanel != (Object)null)
			{
				num |= 1 << startup.m_startGamePanel.layer;
			}
			if ((Object)(object)startup.m_creditsPanel != (Object)null)
			{
				num |= 1 << startup.m_creditsPanel.layer;
			}
			if ((Object)(object)component != (Object)null)
			{
				component.clearFlags = (CameraClearFlags)2;
				component.backgroundColor = Color.black;
				component.cullingMask = num;
			}
			int num2 = 0;
			Camera[] array = Object.FindObjectsByType<Camera>((FindObjectsSortMode)0);
			foreach (Camera val in array)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)component) && ((Behaviour)val).enabled && !((Object)(object)val.targetTexture != (Object)null) && (val.cullingMask & num) == 0)
				{
					((Behaviour)val).enabled = false;
					num2++;
				}
			}
			int num3 = 0;
			ParticleSystem[] array2 = Object.FindObjectsByType<ParticleSystem>((FindObjectsSortMode)0);
			foreach (ParticleSystem val2 in array2)
			{
				if (!((Object)(object)val2 == (Object)null) && !IsUnderUiRoot(((Component)val2).transform, startup))
				{
					val2.Stop(true, (ParticleSystemStopBehavior)0);
					num3++;
				}
			}
			ValheimOptimizerPlugin.Log.LogInfo((object)$"Minimal main menu active: black UI-only main camera; disabled background cameras={num2}, stopped background particles={num3}");
		}
		catch (Exception ex)
		{
			ValheimOptimizerPlugin.Log.LogWarning((object)("Minimal main menu setup failed: " + ex.Message));
		}
	}
}
[HarmonyPatch(typeof(FejdStartup), "Awake")]
internal static class MinimalMainMenuWorldGeneratorPatch
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		MethodInfo original = AccessTools.Method(typeof(WorldGenerator), "Initialize", new Type[1] { typeof(World) }, (Type[])null);
		MethodInfo replacement = AccessTools.Method(typeof(MinimalMainMenuOptimizations), "InitializeMenuWorldIfNeeded", (Type[])null, (Type[])null);
		foreach (CodeInstruction instruction in instructions)
		{
			if (original != null && replacement != null && CodeInstructionExtensions.Calls(instruction, original))
			{
				yield return new CodeInstruction(instruction)
				{
					opcode = OpCodes.Call,
					operand = replacement
				};
			}
			else
			{
				yield return instruction;
			}
		}
	}
}
[HarmonyPatch(typeof(FejdStartup), "Start")]
internal static class MinimalMainMenuSetupPatch
{
	private static void Postfix(FejdStartup __instance)
	{
		MinimalMainMenuOptimizations.Apply(__instance);
	}
}
[HarmonyPatch(typeof(FejdStartup), "UpdateCamera")]
internal static class MinimalMainMenuCameraPatch
{
	private static bool Prefix()
	{
		return !ValheimOptimizerPlugin.MinimalMainMenu.Value;
	}
}