Decompiled source of RunicWorldEngine v1.2.4

plugins/RunicWorldEngine/RunicWorldEngine.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.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Json;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using PartyCSharpSDK;
using PlayFab.Party;
using Runic.Localization;
using RunicWorldEngine.Contracts;
using RunicWorldEngine.Core;
using RunicWorldEngine.Integration;
using Steamworks;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Runic World Engine")]
[assembly: AssemblyDescription("Bounded Valheim world-state observability and safe save smoothing")]
[assembly: AssemblyCompany("Chazman")]
[assembly: AssemblyProduct("Runic World Engine")]
[assembly: AssemblyFileVersion("1.2.3.0")]
[assembly: AssemblyInformationalVersion("1.2.3")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("1.2.3.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 Runic.Localization
{
	internal sealed class LanguageCatalog
	{
		private readonly Dictionary<string, string> _english;

		private Dictionary<string, string> _selected = new Dictionary<string, string>();

		private readonly Func<string, string> _read;

		private string _language;

		internal LanguageCatalog(string english, Func<string, string> read)
		{
			_english = Parse(english);
			_read = read;
		}

		internal static Dictionary<string, string> Parse(string json)
		{
			if (string.IsNullOrWhiteSpace(json))
			{
				return new Dictionary<string, string>();
			}
			if (json.Length > 2097152)
			{
				throw new InvalidDataException("Language file exceeds 2 MiB.");
			}
			DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(typeof(Dictionary<string, string>), new DataContractJsonSerializerSettings
			{
				UseSimpleDictionaryFormat = true
			});
			using MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json.TrimStart('\ufeff')));
			return ((Dictionary<string, string>)dataContractJsonSerializer.ReadObject(stream)) ?? new Dictionary<string, string>();
		}

		internal void Select(string language)
		{
			language = (string.IsNullOrWhiteSpace(language) ? "English" : language);
			if (string.Equals(language, _language, StringComparison.Ordinal))
			{
				return;
			}
			_language = language;
			_selected = new Dictionary<string, string>();
			if (language.IndexOfAny(new char[4] { '/', '\\', ':', '\0' }) >= 0 || language == "." || language == "..")
			{
				return;
			}
			try
			{
				_selected = Parse(_read(language));
			}
			catch (Exception)
			{
			}
		}

		internal string Get(string key)
		{
			_english.TryGetValue(key, out var value);
			if (_selected.TryGetValue(key, out var value2) && !string.IsNullOrWhiteSpace(value2) && (value == null || SameFields(value, value2)))
			{
				return value2;
			}
			return value ?? key;
		}

		internal string English(string key)
		{
			if (!_english.TryGetValue(key, out var value))
			{
				return key;
			}
			return value;
		}

		internal string TranslateEnglish(string text)
		{
			foreach (KeyValuePair<string, string> item in _english)
			{
				if (item.Value == text)
				{
					return Get(item.Key);
				}
			}
			return text;
		}

		internal string Format(string key, params object[] args)
		{
			_english.TryGetValue(key, out var value);
			string text = Get(key);
			if (value != null && !SameFields(value, text))
			{
				text = value;
			}
			try
			{
				return string.Format(CultureInfo.CurrentCulture, text, args);
			}
			catch (FormatException)
			{
				try
				{
					return string.Format(CultureInfo.CurrentCulture, value ?? key, args);
				}
				catch (FormatException)
				{
					return value ?? key;
				}
			}
		}

		private static bool SameFields(string a, string b)
		{
			try
			{
				return Fields(a).SetEquals(Fields(b));
			}
			catch (FormatException)
			{
				return false;
			}
		}

		private static HashSet<int> Fields(string text)
		{
			HashSet<int> hashSet = new HashSet<int>();
			for (int i = 0; i < text.Length; i++)
			{
				if (text[i] == '}')
				{
					if (i + 1 >= text.Length || text[i + 1] != '}')
					{
						throw new FormatException();
					}
					i++;
				}
				else
				{
					if (text[i] != '{')
					{
						continue;
					}
					if (i + 1 < text.Length && text[i + 1] == '{')
					{
						i++;
						continue;
					}
					int num = ++i;
					for (; i < text.Length && char.IsDigit(text[i]); i++)
					{
					}
					if (num == i || !int.TryParse(text.Substring(num, i - num), out var result))
					{
						throw new FormatException();
					}
					hashSet.Add(result);
					for (; i < text.Length && text[i] != '}'; i++)
					{
						if (text[i] == '{')
						{
							throw new FormatException();
						}
					}
					if (i == text.Length)
					{
						throw new FormatException();
					}
				}
			}
			return hashSet;
		}
	}
	internal static class RunicText
	{
		private static readonly Assembly Owner = typeof(RunicText).Assembly;

		private static readonly string Module = Owner.GetName().Name;

		private static readonly LanguageCatalog Catalog = Create();

		private static LanguageCatalog Create()
		{
			using Stream stream = Owner.GetManifestResourceStream("Runic.Localization.English.json");
			using StreamReader streamReader = ((stream == null) ? null : new StreamReader(stream));
			return new LanguageCatalog(streamReader?.ReadToEnd() ?? "{}", ReadLanguage);
		}

		private static string ReadLanguage(string language)
		{
			string path = Path.Combine(Path.Combine(Path.GetDirectoryName(Owner.Location), "Translations", Module), language + ".json");
			if (!File.Exists(path))
			{
				return null;
			}
			return File.ReadAllText(path);
		}

		private static void SelectLanguage()
		{
			string language = "English";
			try
			{
				Localization instance = Localization.instance;
				language = ((instance != null) ? instance.GetSelectedLanguage() : null) ?? "English";
			}
			catch
			{
			}
			Catalog.Select(language);
		}

		internal static string Get(string key)
		{
			SelectLanguage();
			return Catalog.Get(key);
		}

		internal static string English(string key)
		{
			return Catalog.English(key);
		}

		internal static string TranslateEnglish(string text)
		{
			SelectLanguage();
			return Catalog.TranslateEnglish(text);
		}

		internal static string Format(string key, params object[] args)
		{
			SelectLanguage();
			return Catalog.Format(key, args);
		}
	}
}
namespace RunicWorldEngine
{
	internal static class WorldEngineConfig
	{
		internal static ConfigEntry<bool> OverridePlayerCap;

		internal static ConfigEntry<bool> HealthEnabled;

		internal static ConfigEntry<bool> HealthWarnings;

		internal static ConfigEntry<bool> LogPeerDetails;

		internal static ConfigEntry<int> MaximumPlayers;

		internal static ConfigEntry<int> QueueWarningMessages;

		internal static ConfigEntry<float> RttWarningMilliseconds;

		internal static ConfigEntry<float> BacklogWarningKiB;

		internal static ConfigEntry<float> StarvationSeconds;

		internal static ConfigEntry<float> HeartbeatWarningSeconds;

		internal static ConfigEntry<float> FrameWarningMilliseconds;

		internal static ConfigEntry<float> OwnershipWarningPerSecond;

		internal static ConfigEntry<float> WarningHoldSeconds;

		internal static ConfigEntry<float> WarningCooldownSeconds;

		internal static ConfigEntry<bool> Enabled { get; private set; }

		internal static ConfigEntry<bool> LogPeriodicSummary { get; private set; }

		internal static ConfigEntry<float> SummaryIntervalSeconds { get; private set; }

		internal static ConfigEntry<bool> SmoothWorldSaves { get; private set; }

		internal static ConfigEntry<float> SaveFrameBudgetMilliseconds { get; private set; }

		internal static ConfigEntry<float> MaximumSaveDeferralSeconds { get; private set; }

		internal static void Bind(ConfigFile config)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Expected O, but got Unknown
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Expected O, but got Unknown
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Expected O, but got Unknown
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Expected O, but got Unknown
			OverridePlayerCap = config.Bind<bool>("Player Capacity", "Enabled", false, RunicText.Get("text_f99a4834649c"));
			MaximumPlayers = config.Bind<int>("Player Capacity", "MaximumPlayers", 10, new ConfigDescription(RunicText.Get("text_c1c6835d0205"), (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 64), Array.Empty<object>()));
			HealthEnabled = config.Bind<bool>("Server Health", "Enabled", true, RunicText.Get("text_00308931ac1d"));
			HealthWarnings = config.Bind<bool>("Server Health", "Warnings", true, RunicText.Get("text_651d517dc40d"));
			LogPeerDetails = config.Bind<bool>("Diagnostics", "LogPeerDetails", false, RunicText.Get("text_42308444810e"));
			RttWarningMilliseconds = Threshold(config, "RttWarningMilliseconds", 500f, 50f, 10000f);
			BacklogWarningKiB = Threshold(config, "BacklogWarningKiB", 256f, 1f, 65536f);
			QueueWarningMessages = config.Bind<int>("Server Health", "QueueWarningMessages", 1000, new ConfigDescription(RunicText.Get("text_26b4a8c272de"), (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100000), Array.Empty<object>()));
			StarvationSeconds = Threshold(config, "StarvationSeconds", 10f, 2f, 120f);
			HeartbeatWarningSeconds = Threshold(config, "HeartbeatWarningSeconds", 5f, 2f, 25f);
			FrameWarningMilliseconds = Threshold(config, "FrameWarningMilliseconds", 50f, 16f, 1000f);
			OwnershipWarningPerSecond = Threshold(config, "OwnershipWarningPerSecond", 100f, 1f, 100000f);
			WarningHoldSeconds = Threshold(config, "WarningHoldSeconds", 5f, 1f, 60f);
			WarningCooldownSeconds = Threshold(config, "WarningCooldownSeconds", 60f, 10f, 600f);
			Enabled = config.Bind<bool>("General", "Enabled", true, RunicText.Get("text_9c9d086955ae"));
			LogPeriodicSummary = config.Bind<bool>("Diagnostics", "LogPeriodicSummary", false, RunicText.Get("text_4902dc8c1cb9"));
			SummaryIntervalSeconds = config.Bind<float>("Diagnostics", "SummaryIntervalSeconds", 30f, new ConfigDescription(RunicText.Get("text_5c17b1f1dcb6"), (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 600f), Array.Empty<object>()));
			SmoothWorldSaves = config.Bind<bool>("Save Smoothing", "Enabled", true, RunicText.Get("text_062cf05eea1f") + RunicText.Get("text_92cbf9361d05"));
			SaveFrameBudgetMilliseconds = config.Bind<float>("Save Smoothing", "FrameBudgetMilliseconds", 24f, new ConfigDescription(RunicText.Get("text_b7bcb46277a4"), (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 100f), Array.Empty<object>()));
			MaximumSaveDeferralSeconds = config.Bind<float>("Save Smoothing", "MaximumDeferralSeconds", 5f, new ConfigDescription(RunicText.Get("text_d2a955847a6c"), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>()));
		}

		private static ConfigEntry<float> Threshold(ConfigFile config, string name, float initial, float minimum, float maximum)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			return config.Bind<float>("Server Health", name, initial, new ConfigDescription(RunicText.Get("text_b5d5241509a4") + name + RunicText.Get("text_af43bb1eed0a"), (AcceptableValueBase)(object)new AcceptableValueRange<float>(minimum, maximum), Array.Empty<object>()));
		}
	}
	[BepInPlugin("chazman.RunicWorldEngine", "Runic World Engine", "1.2.3")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "chazman.RunicWorldEngine";

		public const string Name = "Runic World Engine";

		public const string Version = "1.2.3";

		private Harmony _harmony;

		private float _nextSummaryAt;

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			WorldEngineConfig.Bind(((BaseUnityPlugin)this).Config);
			ConfigEntry<bool> enabled = WorldEngineConfig.Enabled;
			if (enabled != null && !enabled.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Runic World Engine is disabled; no Harmony patches or observatory state were created.");
				return;
			}
			try
			{
				_harmony = new Harmony("chazman.RunicWorldEngine");
				ObservatoryRuntime.Verify();
				_harmony.PatchAll(typeof(Plugin).Assembly);
				CapacityRuntime.Initialize();
				HealthRuntime.Initialize();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Runic World Engine v1.2.3 ready: world/network diagnostics and save smoothing. Capacity: " + CapacityRuntime.Status + ". Unknown data is preserved; compaction and sync changes are off."));
			}
			catch (Exception ex)
			{
				Shutdown();
				((BaseUnityPlugin)this).Logger.LogError((object)("Runic World Engine failed closed; Valheim world handling remains unchanged. " + ex));
			}
		}

		private void Update()
		{
			SaveSmoothingRuntime.Tick();
			HealthRuntime.Tick();
			ConfigEntry<bool> enabled = WorldEngineConfig.Enabled;
			if (enabled == null || !enabled.Value)
			{
				return;
			}
			ConfigEntry<bool> logPeriodicSummary = WorldEngineConfig.LogPeriodicSummary;
			if (logPeriodicSummary == null || !logPeriodicSummary.Value)
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime < _nextSummaryAt)
			{
				return;
			}
			_nextSummaryAt = unscaledTime + Mathf.Clamp(WorldEngineConfig.SummaryIntervalSeconds.Value, 5f, 600f);
			ZdoObservatorySnapshot current = ObservatoryRuntime.Current;
			((BaseUnityPlugin)this).Logger.LogInfo((object)($"World sample #{current.Sequence}: objects={current.TotalObjects}, peers={current.ConnectedPeers}, " + $"created={current.CreatedSincePreviousSample}, destroyed={current.DestroyedSincePreviousSample}, " + $"sent/s={current.SentLastSecond}, received/s={current.ReceivedLastSecond}, " + $"save={current.LastSaveMilliseconds:F1}ms, load={current.LastLoadMilliseconds:F1}ms."));
			int num = 0;
			foreach (string item in HealthRuntime.Report())
			{
				if (WorldEngineConfig.LogPeerDetails.Value || num < 3)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)item);
				}
				num++;
			}
		}

		private void OnDestroy()
		{
			Shutdown();
		}

		private void Shutdown()
		{
			try
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch
			{
			}
			_harmony = null;
			CapacityRuntime.Reset();
			HealthRuntime.Reset();
			ObservatoryRuntime.Reset();
			SaveSmoothingRuntime.Reset();
		}
	}
}
namespace RunicWorldEngine.Integration
{
	internal static class CapacityRuntime
	{
		private const string Owner = "chazman.RunicWorldEngine.capacity";

		private static readonly Dictionary<MethodBase, CapacityAudit.Site> Targets = new Dictionary<MethodBase, CapacityAudit.Site>();

		private static Harmony _harmony;

		private static bool _requested;

		private static bool _valid;

		private static bool _dedicated;

		internal static int PlayerLimit { get; private set; } = 10;

		internal static bool ValidatedOverride
		{
			get
			{
				if (_requested)
				{
					return _valid;
				}
				return false;
			}
		}

		internal static string Status { get; private set; } = "vanilla capacity (override disabled)";

		internal static void Initialize()
		{
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Expected O, but got Unknown
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Expected O, but got Unknown
			_requested = WorldEngineConfig.OverridePlayerCap.Value;
			if (!_requested)
			{
				return;
			}
			try
			{
				int value = WorldEngineConfig.MaximumPlayers.Value;
				CapacityAudit.Limit(value, _dedicated, transport: true);
				AssemblyDefinition val = AssemblyDefinition.ReadAssembly(typeof(ZNet).Assembly.Location);
				try
				{
					_dedicated = CapacityAudit.IsDedicated(val);
					byte[] image = File.ReadAllBytes(typeof(ZNet).Assembly.Location);
					CapacityAudit.Site[] array = CapacityAudit.Validate(val, _dedicated);
					foreach (CapacityAudit.Site site in array)
					{
						MethodBase methodBase = typeof(ZNet).Module.ResolveMethod(site.Token);
						byte[] array2 = methodBase.GetMethodBody()?.GetILAsByteArray();
						if (array2 == null || !array2.SequenceEqual(CapacityAudit.MethodCode(image, site.Rva)))
						{
							throw new InvalidOperationException("Loaded/preloader-modified capacity body differs from audit: " + methodBase.Name);
						}
						RejectForeignPatches(methodBase);
						Targets.Add(methodBase, site);
					}
				}
				finally
				{
					((IDisposable)val)?.Dispose();
				}
				PlayerLimit = value;
				_harmony = new Harmony("chazman.RunicWorldEngine.capacity");
				foreach (MethodBase key in Targets.Keys)
				{
					_harmony.Patch(key, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(CapacityRuntime), "Transpile", (Type[])null)
					{
						priority = 0
					}, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				_valid = true;
				if (!CheckIntegrity())
				{
					throw new InvalidOperationException(Status);
				}
				Status = RunicText.Format("text_ac591cf388f4", Targets.Count, Targets.Count, PlayerLimit, CapacityAudit.Limit(PlayerLimit, _dedicated, transport: true));
				Plugin.Log.LogInfo((object)("Capacity: " + Status));
			}
			catch (Exception ex)
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				_harmony = null;
				_valid = false;
				PlayerLimit = 10;
				Status = RunicText.Get("text_b80e6b9c2dd3") + ex.Message;
				Plugin.Log.LogError((object)Status);
			}
		}

		internal static bool CheckIntegrity()
		{
			if (!_requested)
			{
				return true;
			}
			if (!_valid)
			{
				return false;
			}
			try
			{
				foreach (MethodBase key in Targets.Keys)
				{
					RejectForeignPatches(key);
					Patches patchInfo = Harmony.GetPatchInfo(key);
					if (patchInfo == null || patchInfo.Transpilers.Count((Patch p) => p.owner == "chazman.RunicWorldEngine.capacity") != 1)
					{
						throw new InvalidOperationException("Capacity patch missing: " + key.Name);
					}
				}
				return true;
			}
			catch (Exception ex)
			{
				_valid = false;
				Status = RunicText.Get("text_c175aa0f5106") + ex.Message;
				Plugin.Log.LogError((object)Status);
				return false;
			}
		}

		private static void RejectForeignPatches(MethodBase target)
		{
			Patches patchInfo = Harmony.GetPatchInfo(target);
			if (patchInfo != null && patchInfo.Transpilers.Any((Patch p) => p.owner != "chazman.RunicWorldEngine.capacity"))
			{
				throw new InvalidOperationException("Conflicting capacity/body transpiler on " + target.DeclaringType.Name + "." + target.Name);
			}
		}

		internal static IEnumerable<CodeInstruction> Transpile(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			return CapacityRewrite.Apply(instructions, Targets[original], PlayerLimit, _dedicated);
		}

		internal static void Reset()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			Targets.Clear();
			_requested = (_valid = false);
			PlayerLimit = 10;
			Status = RunicText.Get("text_29e297337e69");
		}
	}
	[HarmonyPatch(typeof(ZNet), "OpenServer")]
	internal static class CapacityHostGuard
	{
		private static bool Prefix()
		{
			return CapacityRuntime.CheckIntegrity();
		}
	}
	[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
	internal static class CapacityAdmissionGuard
	{
		private static bool Prefix(ZNet __instance, ZRpc __0)
		{
			if (!__instance.IsServer() || CapacityRuntime.CheckIntegrity())
			{
				return true;
			}
			__0.Invoke("Error", new object[1] { 9 });
			return false;
		}
	}
	[HarmonyPatch(typeof(ZDOMan), "CreateNewZDO", new Type[]
	{
		typeof(ZDOID),
		typeof(Vector3),
		typeof(int)
	})]
	internal static class ZdoCreatedPatch
	{
		private static void Postfix(ZDO __result)
		{
			ObservatoryRuntime.MarkCreated(__result);
		}
	}
	[HarmonyPatch(typeof(ZDOMan), "HandleDestroyedZDO", new Type[] { typeof(ZDOID) })]
	internal static class ZdoDestroyedPatch
	{
		private static void Prefix(ZDOMan __instance, ZDOID __0, ref bool __state)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			__state = ObservatoryRuntime.Exists(__instance, __0);
		}

		private static void Postfix(ZDOMan __instance, ZDOID __0, bool __state)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			ObservatoryRuntime.MarkDestroyed(__state, __instance, __0);
		}
	}
	[HarmonyPatch(typeof(ZDOMan), "UpdateStats", new Type[] { typeof(float) })]
	internal static class ZdoStatsPatch
	{
		private static void Postfix(ZDOMan __instance)
		{
			ObservatoryRuntime.Capture(__instance);
		}
	}
	[HarmonyPatch(typeof(ZDOMan), "SaveChunks", new Type[]
	{
		typeof(string),
		typeof(FileSource)
	})]
	internal static class ZdoChunkSaveTimingPatch
	{
		private static void Prefix(ref long __state)
		{
			__state = ObservatoryRuntime.BeginTimedOperation();
		}

		private static Exception Finalizer(long __state, Exception __exception)
		{
			ObservatoryRuntime.EndSave(__state);
			return __exception;
		}
	}
	[HarmonyPatch(typeof(ZDOMan), "LoadChunks", new Type[]
	{
		typeof(string),
		typeof(FileSource),
		typeof(World)
	})]
	internal static class ZdoChunkLoadTimingPatch
	{
		private static void Prefix(ref long __state)
		{
			__state = ObservatoryRuntime.BeginTimedOperation();
		}

		private static Exception Finalizer(long __state, Exception __exception)
		{
			ObservatoryRuntime.EndLoad(__state);
			return __exception;
		}
	}
	[HarmonyPatch(typeof(ZDOMan), "Load", new Type[]
	{
		typeof(BinaryReader),
		typeof(World)
	})]
	internal static class ZdoLegacyLoadTimingPatch
	{
		private static void Prefix(ref long __state)
		{
			__state = ObservatoryRuntime.BeginTimedOperation();
		}

		private static Exception Finalizer(long __state, Exception __exception)
		{
			ObservatoryRuntime.EndLoad(__state);
			return __exception;
		}
	}
	internal static class HealthRuntime
	{
		private sealed class PeerState
		{
			internal double LastProgress;

			internal double Joined;

			internal int Sends;
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__30_0;

			public static Func<ZNetPeer, bool> <>9__33_0;

			public static Func<char, char> <>9__38_0;

			internal void <Initialize>b__30_0(ConsoleEventArgs args)
			{
				foreach (string item in Report())
				{
					args.Context.AddString(item);
				}
			}

			internal bool <Sample>b__33_0(ZNetPeer p)
			{
				return p.IsReady();
			}

			internal char <SafeName>b__38_0(char c)
			{
				if (!char.IsControl(c) && c != '<' && c != '>')
				{
					return c;
				}
				return '_';
			}
		}

		private const int MaximumPeers = 128;

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

		private static readonly Dictionary<string, WarningLatch> Warnings = new Dictionary<string, WarningLatch>();

		private static readonly TransferCounter<ZDOID> Transfers = new TransferCounter<ZDOID>(1024);

		private static readonly FieldInfo ManagerPeers = AccessTools.Field(typeof(ZDOMan), "m_peers");

		private static readonly Type PeerType = AccessTools.Inner(typeof(ZDOMan), "ZDOPeer");

		private static readonly FieldInfo NetworkPeer = AccessTools.Field(PeerType, "m_peer");

		private static readonly FieldInfo ForceSend = AccessTools.Field(PeerType, "m_forceSend");

		private static readonly FieldInfo InvalidSector = AccessTools.Field(PeerType, "m_invalidSector");

		private static object _session;

		private static double _nextSample;

		private static double _lastSample;

		private static double _frameTotal;

		private static double _framePeak;

		private static int _frameCount;

		private static int _mainThread;

		private static bool _initialized;

		internal static bool Active { get; private set; }

		internal static bool CanObserve
		{
			get
			{
				if (Active)
				{
					return Thread.CurrentThread.ManagedThreadId == _mainThread;
				}
				return false;
			}
		}

		internal static string[] Lines { get; private set; } = new string[1] { "Health: no active session sampled." };

		private static double Now => (double)Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;

		internal static void Initialize()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			_mainThread = Thread.CurrentThread.ManagedThreadId;
			_initialized = true;
			object obj = <>c.<>9__30_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					foreach (string item in Report())
					{
						args.Context.AddString(item);
					}
				};
				<>c.<>9__30_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("runicworld_status", "Show this process's sampled player capacity and network health (read-only).", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		internal static IEnumerable<string> Report()
		{
			yield return "Runic World Engine: " + CapacityRuntime.Status;
			string[] lines = Lines;
			for (int i = 0; i < lines.Length; i++)
			{
				yield return lines[i];
			}
		}

		internal static void Tick()
		{
			if (!_initialized)
			{
				return;
			}
			ZNet instance = ZNet.instance;
			Active = WorldEngineConfig.Enabled.Value && WorldEngineConfig.HealthEnabled.Value && (Object)(object)instance != (Object)null && ZDOMan.instance != null;
			object obj = (Active ? instance : null);
			if (obj != _session)
			{
				ClearSession();
				_session = obj;
			}
			if (!Active)
			{
				return;
			}
			double now = Now;
			double num = (double)Time.unscaledDeltaTime * 1000.0;
			if (num >= 0.0 && !double.IsNaN(num) && !double.IsInfinity(num))
			{
				_frameTotal += num;
				_framePeak = Math.Max(_framePeak, num);
				_frameCount++;
			}
			if (now < _nextSample)
			{
				return;
			}
			_nextSample = now + 1.0;
			try
			{
				Sample(instance, now);
			}
			catch (Exception ex)
			{
				Lines = new string[1] { "Health sample unavailable: " + ex.GetType().Name + "; no world data changed." };
				Warn("sampling", condition: true, now, "Health sampling unavailable: " + ex.GetType().Name, instance.IsServer());
			}
		}

		private static void Sample(ZNet network, double now)
		{
			bool flag = network.IsServer();
			if (flag)
			{
				CapacityRuntime.CheckIntegrity();
			}
			double num = ((_lastSample > 0.0) ? (now - _lastSample) : 1.0);
			_lastSample = now;
			double num2 = ((_frameCount > 0) ? (_frameTotal / (double)_frameCount) : 0.0);
			double framePeak = _framePeak;
			_frameTotal = (_framePeak = 0.0);
			_frameCount = 0;
			List<ZNetPeer> peers = network.GetPeers();
			int num3 = peers.Take(128).Count((ZNetPeer p) => p.IsReady());
			int nrOfPlayers = network.GetNrOfPlayers();
			List<string> list = new List<string>(131);
			list.Add(string.Format("Health ({0}): players={1}, ready remote peers={2}, connections={3}; frame mean/peak={4:F1}/{5:F1}ms.", flag ? "server" : "local client; not remote-server telemetry", nrOfPlayers, num3, peers.Count, num2, framePeak));
			list.Add($"Ownership / {num:F1}s: assigned={Transfers.Assigned}, released={Transfers.Released}, transferred={Transfers.Transferred}, rapid repeated transfers={Transfers.RapidTransfers} (10s window; up to 1024 tracked IDs).");
			List<string> list2 = list;
			IList list3 = ManagerPeers.GetValue(ZDOMan.instance) as IList;
			Dictionary<ZNetPeer, (int, int)> dictionary = new Dictionary<ZNetPeer, (int, int)>();
			if (list3 == null)
			{
				throw new MissingFieldException("ZDOMan.m_peers");
			}
			for (int num4 = 0; num4 < Math.Min(128, list3.Count); num4++)
			{
				object obj = list3[num4];
				object? value = NetworkPeer.GetValue(obj);
				ZNetPeer val = (ZNetPeer)((value is ZNetPeer) ? value : null);
				if (val != null)
				{
					dictionary[val] = (((HashSet<ZDOID>)ForceSend.GetValue(obj)).Count, ((HashSet<ZDOID>)InvalidSector.GetValue(obj)).Count);
				}
			}
			bool flag2 = false;
			bool flag3 = false;
			bool flag4 = false;
			bool flag5 = false;
			bool flag6 = false;
			bool flag7 = false;
			HashSet<ZNetPeer> live = new HashSet<ZNetPeer>(peers.Take(128));
			ZNetPeer[] array = Peers.Keys.Where((ZNetPeer p) => !live.Contains(p)).ToArray();
			foreach (ZNetPeer key in array)
			{
				Peers.Remove(key);
			}
			for (int num6 = 0; num6 < Math.Min(128, peers.Count); num6++)
			{
				ZNetPeer val2 = peers[num6];
				if (val2.IsReady())
				{
					if (!Peers.TryGetValue(val2, out var value2))
					{
						Dictionary<ZNetPeer, PeerState> peers2 = Peers;
						PeerState obj2 = new PeerState
						{
							Joined = now,
							LastProgress = now
						};
						value2 = obj2;
						peers2[val2] = obj2;
					}
					TransportSample transportSample = TransportSampler.Read(val2.m_socket, now);
					dictionary.TryGetValue(val2, out var value3);
					double num7 = val2.m_rpc.GetTimeSinceLastPing();
					double num8 = now - value2.LastProgress;
					bool flag8 = now - value2.Joined >= 15.0;
					bool valueOrDefault = transportSample.SendWindowPressure == true;
					bool flag9 = flag8 && (value3.Item1 + value3.Item2 > 0 || valueOrDefault) && num8 >= (double)WorldEngineConfig.StarvationSeconds.Value;
					flag7 = flag7 || (flag8 && valueOrDefault);
					flag2 |= flag8 && transportSample.Rtt >= (double)WorldEngineConfig.RttWarningMilliseconds.Value;
					flag3 |= flag8 && (transportSample.PendingBytes.GetValueOrDefault() + transportSample.InFlightBytes.GetValueOrDefault() >= (double)WorldEngineConfig.BacklogWarningKiB.Value * 1024.0 || transportSample.SendMessages >= WorldEngineConfig.QueueWarningMessages.Value || transportSample.ReceiveMessages >= WorldEngineConfig.QueueWarningMessages.Value || transportSample.OutOfOrder >= WorldEngineConfig.QueueWarningMessages.Value || value3.Item1 + value3.Item2 >= WorldEngineConfig.QueueWarningMessages.Value);
					flag4 = flag4 || flag9;
					flag5 |= flag8 && num7 >= (double)WorldEngineConfig.HeartbeatWarningSeconds.Value;
					flag6 |= transportSample.Error != null || !transportSample.Rtt.HasValue;
					list2.Add(string.Format("Peer {0} '{1}' [{2}]: RTT={3}ms; send/recv={4}/{5} B/s; queued={6}B, in-flight={7}B; app send/recv queues={8}/{9} messages, out-of-order={10}; send-window pressure={11}; priority/invalid ZDOs={12}/{13}; ZDO sends={14}, last progress={15:F1}s ago; heartbeat age={16:F1}s; {17}{18}.", val2.m_uid, SafeName(val2.m_playerName), transportSample.Kind, Metric(transportSample.Rtt), Metric(transportSample.Sent), Metric(transportSample.Received), Metric(transportSample.PendingBytes), Metric(transportSample.InFlightBytes), Metric(transportSample.SendMessages), Metric(transportSample.ReceiveMessages), Metric(transportSample.OutOfOrder), (!transportSample.SendWindowPressure.HasValue) ? "n/a" : (valueOrDefault ? "yes" : "no"), value3.Item1, value3.Item2, value2.Sends, num8, num7, flag9 ? "POSSIBLE STARVATION" : "no starvation indicator", (transportSample.Error == null) ? "" : ("; sample error=" + transportSample.Error)));
					value2.Sends = 0;
				}
			}
			if (peers.Count > 128 || list3.Count > 128)
			{
				list2.Add("Peer detail and ready-peer count truncated at 128; aggregate connection count remains complete.");
			}
			Warn("capacity", flag && CapacityRuntime.ValidatedOverride && (double)nrOfPlayers >= Math.Ceiling((double)CapacityRuntime.PlayerLimit * 0.9), now, "Player count is at or above 90% of the validated cap.", flag);
			Warn("frames", num2 >= (double)WorldEngineConfig.FrameWarningMilliseconds.Value, now, $"Sustained slow server frames: mean {num2:F1}ms.", flag);
			Warn("latency", flag2, now, "One or more peers have sustained high RTT; inspect runicworld_status/peer summaries.", flag);
			Warn("backlog", flag3, now, "Sustained queued/unacknowledged traffic or priority ZDO backlog; inspect peer summaries.", flag);
			Warn("send-window", flag7, now, "Sustained pressure near Valheim's ZDO send-window limit; synchronization may be throttled.", flag);
			Warn("starvation", flag4, now, "Possible synchronization starvation: priority/invalid ZDO work or send-window pressure without successful ZDO sends.", flag);
			Warn("heartbeat", flag5, now, "One or more peer heartbeat replies are overdue; disconnect risk is rising.", flag);
			Warn("ownership", (double)Transfers.RapidTransfers / num >= (double)WorldEngineConfig.OwnershipWarningPerSecond.Value, now, "Sustained rapid ownership transfers; inspect server load and peer movement.", flag);
			Warn("sampling", condition: false, now, "Health sampling restored.", flag);
			if (flag6)
			{
				list2.Add("n/a means unavailable/uninitialized, not zero. Heartbeat age is not RTT. Priority ZDO counts are not the full unsent world backlog.");
			}
			Lines = list2.ToArray();
			Transfers.ResetInterval();
		}

		private static void Warn(string key, bool condition, double now, string message, bool server)
		{
			if (!server || !WorldEngineConfig.HealthWarnings.Value)
			{
				Warnings.Clear();
				return;
			}
			if (!Warnings.TryGetValue(key, out var value))
			{
				value = (Warnings[key] = new WarningLatch());
			}
			switch (value.Observe(condition, now, WorldEngineConfig.WarningHoldSeconds.Value, WorldEngineConfig.WarningCooldownSeconds.Value))
			{
			case 1:
				Plugin.Log.LogWarning((object)("Server health [" + key + "]: " + message));
				break;
			case -1:
				Plugin.Log.LogInfo((object)("Server health [" + key + "]: recovered below warning threshold."));
				break;
			}
		}

		internal static void RecordProgress(object zdoPeer, bool sent)
		{
			if (!sent || !Active || Thread.CurrentThread.ManagedThreadId != _mainThread)
			{
				return;
			}
			try
			{
				object? value = NetworkPeer.GetValue(zdoPeer);
				ZNetPeer val = (ZNetPeer)((value is ZNetPeer) ? value : null);
				if (val != null && Peers.TryGetValue(val, out var value2))
				{
					value2.LastProgress = Now;
					value2.Sends++;
				}
			}
			catch
			{
			}
		}

		internal static void RecordTransfer(ZDO zdo, long before)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!Active || Thread.CurrentThread.ManagedThreadId != _mainThread)
			{
				return;
			}
			try
			{
				Transfers.Record(zdo.m_uid, before, zdo.GetOwner(), Now);
			}
			catch
			{
			}
		}

		private static string Metric(double? value)
		{
			if (!value.HasValue)
			{
				return "n/a";
			}
			return value.Value.ToString("F0", CultureInfo.InvariantCulture);
		}

		private static string SafeName(string name)
		{
			return new string((from c in (name ?? "unnamed").Take(48)
				select (!char.IsControl(c) && c != '<' && c != '>') ? c : '_').ToArray());
		}

		private static void ClearSession()
		{
			Peers.Clear();
			Warnings.Clear();
			Transfers.Clear();
			PayloadObservation.Reset();
			_lastSample = (_nextSample = (_frameTotal = (_framePeak = 0.0)));
			_frameCount = 0;
			Lines = new string[1] { "Health: no active session sampled." };
		}

		internal static void Reset()
		{
			Active = (_initialized = false);
			_session = null;
			ClearSession();
		}
	}
	[HarmonyPatch(typeof(ZDO), "SetOwnerInternal", new Type[] { typeof(long) })]
	internal static class TransferObservationPatch
	{
		private static void Prefix(ZDO __instance, out long? __state)
		{
			__state = null;
			if (!HealthRuntime.CanObserve)
			{
				return;
			}
			try
			{
				__state = __instance.GetOwner();
			}
			catch
			{
			}
		}

		private static void Postfix(ZDO __instance, long? __state)
		{
			if (__state.HasValue)
			{
				HealthRuntime.RecordTransfer(__instance, __state.Value);
			}
		}
	}
	[HarmonyPatch(typeof(ZDOMan), "SendZDOs")]
	internal static class SendProgressObservationPatch
	{
		private static void Postfix(object __0, bool __result)
		{
			HealthRuntime.RecordProgress(__0, __result);
		}
	}
	internal static class ObservatoryRuntime
	{
		private static readonly FieldInfo ObjectsField = AccessTools.Field(typeof(ZDOMan), "m_objectsByID");

		private static readonly FieldInfo PeersField = AccessTools.Field(typeof(ZDOMan), "m_peers");

		private static readonly FieldInfo SentField = AccessTools.Field(typeof(ZDOMan), "m_zdosSentLastSec");

		private static readonly FieldInfo ReceivedField = AccessTools.Field(typeof(ZDOMan), "m_zdosRecvLastSec");

		private static readonly ObservatoryCounter Counter = new ObservatoryCounter();

		private static long _nextCaptureTimestamp;

		private static bool _verified;

		internal static ZdoObservatorySnapshot Current => Counter.Current;

		internal static void Verify()
		{
			bool flag = PeersField != null && !PeersField.IsStatic && PeersField.FieldType.IsGenericType && PeersField.FieldType.GetGenericTypeDefinition() == typeof(List<>) && PeersField.FieldType.GetGenericArguments().Length == 1 && PeersField.FieldType.GetGenericArguments()[0].DeclaringType == typeof(ZDOMan) && PeersField.FieldType.GetGenericArguments()[0].Name == "ZDOPeer";
			if (ObjectsField == null || ObjectsField.IsStatic || ObjectsField.FieldType != typeof(Dictionary<ZDOID, ZDO>) || !flag || SentField == null || SentField.IsStatic || SentField.FieldType != typeof(int) || ReceivedField == null || ReceivedField.IsStatic || ReceivedField.FieldType != typeof(int))
			{
				throw new MissingMemberException("ZDOMan observatory fields do not match the audited Valheim 1.0 contract.");
			}
			_verified = true;
		}

		internal static void MarkCreated(ZDO created)
		{
			if (_verified)
			{
				ConfigEntry<bool> enabled = WorldEngineConfig.Enabled;
				if (enabled != null && enabled.Value && created != null)
				{
					Counter.MarkCreated();
				}
			}
		}

		internal static bool Exists(ZDOMan manager, ZDOID id)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (_verified)
			{
				ConfigEntry<bool> enabled = WorldEngineConfig.Enabled;
				if (enabled != null && enabled.Value && manager != null)
				{
					try
					{
						return ObjectsField.GetValue(manager) is Dictionary<ZDOID, ZDO> dictionary && dictionary.ContainsKey(id);
					}
					catch
					{
						return false;
					}
				}
			}
			return false;
		}

		internal static void MarkDestroyed(bool existedBefore, ZDOMan manager, ZDOID id)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (_verified && existedBefore && !Exists(manager, id))
			{
				Counter.MarkDestroyed();
			}
		}

		internal static void Capture(ZDOMan manager)
		{
			if (!_verified || manager == null)
			{
				return;
			}
			ConfigEntry<bool> enabled = WorldEngineConfig.Enabled;
			if (enabled == null || !enabled.Value)
			{
				return;
			}
			try
			{
				long timestamp = Stopwatch.GetTimestamp();
				if (timestamp >= _nextCaptureTimestamp)
				{
					_nextCaptureTimestamp = ((timestamp > long.MaxValue - Stopwatch.Frequency) ? long.MaxValue : (timestamp + Stopwatch.Frequency));
					int totalObjects = ((ObjectsField.GetValue(manager) is Dictionary<ZDOID, ZDO> dictionary) ? dictionary.Count : 0);
					int connectedPeers = ((PeersField.GetValue(manager) is ICollection collection) ? collection.Count : 0);
					int sentLastSecond = Convert.ToInt32(SentField.GetValue(manager));
					int receivedLastSecond = Convert.ToInt32(ReceivedField.GetValue(manager));
					Counter.Capture(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), totalObjects, connectedPeers, sentLastSecond, receivedLastSecond);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("World observatory sample failed closed: " + ex.Message));
				}
			}
		}

		internal static long BeginTimedOperation()
		{
			if (_verified)
			{
				ConfigEntry<bool> enabled = WorldEngineConfig.Enabled;
				if (enabled != null && enabled.Value)
				{
					return Stopwatch.GetTimestamp();
				}
			}
			return 0L;
		}

		internal static void EndSave(long started)
		{
			Counter.RecordSaveDuration(started);
		}

		internal static void EndLoad(long started)
		{
			Counter.RecordLoadDuration(started);
			if (ZDOMan.instance != null)
			{
				Capture(ZDOMan.instance);
			}
		}

		internal static void Reset()
		{
			Counter.Reset();
			_nextCaptureTimestamp = 0L;
			_verified = false;
		}
	}
	internal static class PayloadObservation
	{
		private static ConditionalWeakTable<ZNetStats, PayloadMeter> _meters = new ConditionalWeakTable<ZNetStats, PayloadMeter>();

		internal static PayloadMeter Meter(ZNetStats socket)
		{
			return _meters.GetValue(socket, (ZNetStats _) => new PayloadMeter());
		}

		internal static void Sent(ZNetStats socket, int bytes)
		{
			if (_meters.TryGetValue(socket, out var value))
			{
				value.Sent(bytes);
			}
		}

		internal static void Received(ZNetStats socket, int bytes)
		{
			if (_meters.TryGetValue(socket, out var value))
			{
				value.Received(bytes);
			}
		}

		internal static void Reset()
		{
			_meters = new ConditionalWeakTable<ZNetStats, PayloadMeter>();
		}
	}
	[HarmonyPatch(typeof(ZNetStats), "IncSentBytes", new Type[] { typeof(int) })]
	internal static class SentPayloadObservationPatch
	{
		private static void Postfix(ZNetStats __instance, int __0)
		{
			PayloadObservation.Sent(__instance, __0);
		}
	}
	[HarmonyPatch(typeof(ZNetStats), "IncRecvBytes", new Type[] { typeof(int) })]
	internal static class ReceivedPayloadObservationPatch
	{
		private static void Postfix(ZNetStats __instance, int __0)
		{
			PayloadObservation.Received(__instance, __0);
		}
	}
	internal static class SaveSmoothingRuntime
	{
		private static readonly object Gate = new object();

		private static readonly FieldInfo SaveThreadField = AccessTools.Field(typeof(ZNet), "m_saveThread");

		private static readonly MethodInfo SaveWorldMethod = AccessTools.Method(typeof(ZNet), "SaveWorld", new Type[1] { typeof(bool) }, (Type[])null);

		private static bool _pending;

		private static bool _dispatching;

		private static float _requestedAt;

		private static float _eligibleAt;

		internal static bool BeforeSave(ZNet network, bool sync, Thread saveThread)
		{
			if (!(WorldEngineConfig.SmoothWorldSaves?.Value ?? true) || sync)
			{
				return true;
			}
			lock (Gate)
			{
				if (_dispatching)
				{
					return true;
				}
				float unscaledTime = Time.unscaledTime;
				bool flag = saveThread?.IsAlive ?? false;
				bool flag2 = Time.unscaledDeltaTime * 1000f > FrameBudget();
				if (!flag && !flag2)
				{
					return true;
				}
				if (!_pending)
				{
					_requestedAt = unscaledTime;
				}
				_pending = true;
				_eligibleAt = Math.Max(_eligibleAt, unscaledTime + (flag ? 0.25f : 0.05f));
				return false;
			}
		}

		internal static void Tick()
		{
			ConfigEntry<bool> enabled = WorldEngineConfig.Enabled;
			if (enabled == null || !enabled.Value)
			{
				return;
			}
			ConfigEntry<bool> smoothWorldSaves = WorldEngineConfig.SmoothWorldSaves;
			if (smoothWorldSaves != null && !smoothWorldSaves.Value)
			{
				return;
			}
			ZNet instance = ZNet.instance;
			if ((Object)(object)instance == (Object)null || !instance.IsServer())
			{
				return;
			}
			bool flag;
			lock (Gate)
			{
				if (!_pending || _dispatching)
				{
					return;
				}
				float unscaledTime = Time.unscaledTime;
				if (unscaledTime < _eligibleAt)
				{
					return;
				}
				if (SaveThreadField?.GetValue(instance) is Thread { IsAlive: not false })
				{
					_eligibleAt = unscaledTime + 0.25f;
					return;
				}
				bool num = Time.unscaledDeltaTime * 1000f <= FrameBudget();
				float num2 = Math.Max(0f, Math.Min(30f, WorldEngineConfig.MaximumSaveDeferralSeconds?.Value ?? 5f));
				if (!num && unscaledTime - _requestedAt < num2)
				{
					_eligibleAt = unscaledTime + 0.05f;
					return;
				}
				_pending = false;
				_dispatching = true;
				flag = true;
			}
			if (!flag)
			{
				return;
			}
			try
			{
				if (SaveWorldMethod == null)
				{
					throw new MissingMethodException("ZNet.SaveWorld(bool)");
				}
				SaveWorldMethod.Invoke(instance, new object[1] { false });
			}
			finally
			{
				lock (Gate)
				{
					_dispatching = false;
				}
			}
		}

		internal static void Reset()
		{
			lock (Gate)
			{
				_pending = false;
				_dispatching = false;
				_requestedAt = 0f;
				_eligibleAt = 0f;
			}
		}

		private static float FrameBudget()
		{
			return Math.Max(8f, Math.Min(100f, WorldEngineConfig.SaveFrameBudgetMilliseconds?.Value ?? 24f));
		}
	}
	[HarmonyPatch(typeof(ZNet), "SaveWorld", new Type[] { typeof(bool) })]
	internal static class SmoothWorldSavePatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ZNet __instance, bool sync, Thread ___m_saveThread)
		{
			return SaveSmoothingRuntime.BeforeSave(__instance, sync, ___m_saveThread);
		}
	}
	internal sealed class TransportSample
	{
		internal double? Rtt;

		internal double? Sent;

		internal double? Received;

		internal double? PendingBytes;

		internal double? InFlightBytes;

		internal int? SendMessages;

		internal int? ReceiveMessages;

		internal int? OutOfOrder;

		internal bool? SendWindowPressure;

		internal string Kind = "unavailable";

		internal string Error;
	}
	internal static class TransportSampler
	{
		private static readonly FieldInfo SteamConnection = AccessTools.Field(typeof(ZSteamSocket), "m_con");

		private static readonly FieldInfo SteamSend = AccessTools.Field(typeof(ZSteamSocket), "m_sendQueue");

		private static readonly FieldInfo SteamReceive = AccessTools.Field(typeof(ZSteamSocket), "m_pkgQueue");

		private static readonly FieldInfo PartyPeer = AccessTools.Field(typeof(ZPlayFabSocket), "m_peer");

		private static readonly FieldInfo PartyFlight = AccessTools.Field(typeof(ZPlayFabSocket), "m_inFlightQueue");

		private static readonly FieldInfo PartySend = AccessTools.Field(typeof(ZPlayFabSocket), "m_sendQueue");

		private static readonly FieldInfo PartyReceive = AccessTools.Field(typeof(ZPlayFabSocket), "m_recvQueue");

		private static readonly FieldInfo PartyOrder = AccessTools.Field(typeof(ZPlayFabSocket), "m_outOfOrderQueue");

		private static readonly FieldInfo LocalEndpoint = AccessTools.Field(typeof(PlayFabMultiplayerManager), "_localEndPointHandle");

		private static readonly FieldInfo RemoteEndpoint = AccessTools.Field(typeof(PlayFabPlayer), "_endPointHandle");

		private static readonly PARTY_ENDPOINT_STATISTIC[] Statistics = (PARTY_ENDPOINT_STATISTIC[])(object)new PARTY_ENDPOINT_STATISTIC[2]
		{
			(PARTY_ENDPOINT_STATISTIC)8,
			(PARTY_ENDPOINT_STATISTIC)1
		};

		internal static TransportSample Read(ISocket socket, double now)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			//IL_0081: 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_00a5: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Expected O, but got Unknown
			TransportSample transportSample = new TransportSample();
			try
			{
				if (socket == null || !socket.IsConnected())
				{
					return transportSample;
				}
				if (socket is ZSteamSocket)
				{
					transportSample.Kind = "Steam/native bytes";
					transportSample.SendMessages = Count(SteamSend, socket);
					transportSample.ReceiveMessages = Count(SteamReceive, socket);
					HSteamNetConnection val = (HSteamNetConnection)SteamConnection.GetValue(socket);
					SteamNetConnectionRealTimeStatus_t val2 = default(SteamNetConnectionRealTimeStatus_t);
					SteamNetConnectionRealTimeLaneStatus_t val3 = default(SteamNetConnectionRealTimeLaneStatus_t);
					if ((int)SteamNetworkingSockets.GetConnectionRealTimeStatus(val, ref val2, 0, ref val3) == 1)
					{
						transportSample.Rtt = Nonnegative(val2.m_nPing);
						transportSample.Sent = Nonnegative(val2.m_flOutBytesPerSec);
						transportSample.Received = Nonnegative(val2.m_flInBytesPerSec);
						transportSample.PendingBytes = (double)val2.m_cbPendingReliable + (double)val2.m_cbPendingUnreliable;
						transportSample.InFlightBytes = val2.m_cbSentUnackedReliable;
					}
				}
				else if (socket is ZPlayFabSocket)
				{
					transportSample.Kind = "PlayFab/socket payload bytes";
					transportSample.SendMessages = Count(PartySend, socket);
					transportSample.ReceiveMessages = Count(PartyReceive, socket);
					transportSample.OutOfOrder = Count(PartyOrder, socket);
					object? value = PartyFlight.GetValue(socket);
					InFlightQueue val4 = (InFlightQueue)((value is InFlightQueue) ? value : null);
					if (val4 != null)
					{
						transportSample.InFlightBytes = val4.Bytes;
					}
					(double?, double?) tuple = PayloadObservation.Meter((ZNetStats)socket).Sample(now);
					transportSample.Sent = tuple.Item1;
					transportSample.Received = tuple.Item2;
					PlayFabPlayer[] array = PartyPeer.GetValue(socket) as PlayFabPlayer[];
					PlayFabMultiplayerManager val5 = PlayFabMultiplayerManager.Get();
					PARTY_ENDPOINT_HANDLE val6 = (PARTY_ENDPOINT_HANDLE)(((Object)(object)val5 == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/);
					PARTY_ENDPOINT_HANDLE val7 = (PARTY_ENDPOINT_HANDLE)((array != null && array.Length == 1) ? /*isinst with value type is only supported in some contexts*/: null);
					ulong[] array2 = default(ulong[]);
					if (val6 != null && val7 != null && SDK.PartyEndpointGetEndpointStatistics(val6, (PARTY_ENDPOINT_HANDLE[])(object)new PARTY_ENDPOINT_HANDLE[1] { val7 }, Statistics, ref array2) == 0 && array2 != null && array2.Length == 2)
					{
						transportSample.Rtt = ((array2[0] != 0) ? new double?(array2[0]) : ((double?)null));
						transportSample.PendingBytes = array2[1];
					}
				}
				else
				{
					transportSample.Kind = ((object)socket).GetType().Name + "/unsupported metrics";
				}
			}
			catch (Exception ex)
			{
				transportSample.Error = ex.GetType().Name;
			}
			if (socket is ZSteamSocket || socket is ZPlayFabSocket)
			{
				transportSample.SendWindowPressure = SendWindowPressure.Estimate(socket is ZPlayFabSocket, transportSample.PendingBytes, transportSample.InFlightBytes, transportSample.SendMessages);
			}
			return transportSample;
		}

		private static double? Nonnegative(double value)
		{
			if (!(value >= 0.0) || double.IsNaN(value) || double.IsInfinity(value))
			{
				return null;
			}
			return value;
		}

		private static int? Count(FieldInfo field, object instance)
		{
			if (!(field?.GetValue(instance) is ICollection collection))
			{
				return null;
			}
			return collection.Count;
		}
	}
}
namespace RunicWorldEngine.Core
{
	internal static class CapacityAudit
	{
		internal sealed class Site
		{
			internal string Type;

			internal string Method;

			internal string MemberType;

			internal string Member;

			internal bool Previous;

			internal bool Transport;

			internal int Baseline;

			internal int Token;

			internal int Rva;
		}

		internal static readonly HashSet<string> Fingerprints = new HashSet<string>(StringComparer.Ordinal) { "EC5CA7EC57BA5C5A2EFF1C41FA3C7F6B2D75A497FC990D58F8ADDC3CD54BC7E0", "459DD8DBAB089DF496991274244B62297AD68764D988D78475D8251A20343E63", "F54B5B813E98AD518E07CF56E69A4864C4515FC3184472D31A4FFC3036D3D2A3", "F66F7EDC4D1A499F505B65F7924BF175A5383F7EC6EEC4C11FD6869DDD900DCE", "490240F2759B3EDF43BE848F6ACBC4DB524913E72514C6051C434062DFC77434", "3AFFCFECC1E54E67D24BCA4783D924B027F8858F2CF9DAEC11EE49E3B2ACE6FE", "DD13270F59DB84CCCDBB943803EE216854704FDCED7612443D7CDB6222AF1117", "4C2CF929012527CCDCE74F530E008B34A250C8A4006A16C2EFD65AFA374A95A4", "C25809B87CB42B4553CF5EB3E6AB3FF058CD0F7575C22E83D30179A769A68DAE", "CD68B17D73F15C90C439F2E0A2622188140C0767BEAAEE4DB1AF6807898A674C" };

		internal static Site[] Sites(bool dedicated)
		{
			return new Site[5]
			{
				new Site
				{
					Type = "ZNet",
					Method = "RPC_PeerInfo",
					MemberType = "ZNet",
					Member = "GetNrOfPlayers",
					Previous = true,
					Baseline = 10
				},
				new Site
				{
					Type = "ZSteamMatchmaking",
					Method = "RegisterServer",
					MemberType = (dedicated ? "Steamworks.SteamGameServer" : "Steamworks.SteamMatchmaking"),
					Member = (dedicated ? "SetMaxPlayerCount" : "CreateLobby"),
					Baseline = 10
				},
				new Site
				{
					Type = "ZPlayFabMatchmaking",
					Method = "SetPlatformMatchmakingData",
					MemberType = "Splatform.MultiplayerSessionData",
					Member = "m_maxPlayers",
					Baseline = 10
				},
				new Site
				{
					Type = "ZPlayFabMatchmaking",
					Method = "CreateLobby",
					MemberType = "PlayFab.MultiplayerModels.CreateLobbyRequest",
					Member = "MaxPlayers",
					Baseline = (dedicated ? 11 : 10),
					Transport = true
				},
				new Site
				{
					Type = "ZPlayFabMatchmaking",
					Method = "CreateAndJoinNetwork",
					MemberType = "PlayFab.Party.PlayFabNetworkConfiguration",
					Member = "set_MaxPlayerCount",
					Baseline = (dedicated ? 11 : 10),
					Transport = true
				}
			}.Concat((!dedicated) ? ((IEnumerable<Site>)Array.Empty<Site>()) : ((IEnumerable<Site>)new Site[1]
			{
				new Site
				{
					Type = "SteamManager",
					Method = "Awake",
					MemberType = "Steamworks.SteamGameServer",
					Member = "SetMaxPlayerCount",
					Baseline = 64
				}
			})).ToArray();
		}

		internal static int Limit(int players, bool dedicated, bool transport)
		{
			if (players < 2 || players > 64)
			{
				throw new ArgumentOutOfRangeException("players");
			}
			checked
			{
				return players + (unchecked(dedicated && transport) ? 1 : 0);
			}
		}

		internal static string Fingerprint(MethodDefinition method)
		{
			string s = string.Join("\n", ((IEnumerable<Instruction>)method.Body.Instructions).Select((Instruction i) => ((object)i).ToString())) + "\n" + string.Join("\n", ((IEnumerable<ExceptionHandler>)method.Body.ExceptionHandlers).Select(delegate(ExceptionHandler e)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				object[] obj = new object[7] { e.HandlerType, null, null, null, null, null, null };
				Instruction tryStart = e.TryStart;
				obj[1] = ((tryStart != null) ? new int?(tryStart.Offset) : ((int?)null));
				Instruction tryEnd = e.TryEnd;
				obj[2] = ((tryEnd != null) ? new int?(tryEnd.Offset) : ((int?)null));
				Instruction handlerStart = e.HandlerStart;
				obj[3] = ((handlerStart != null) ? new int?(handlerStart.Offset) : ((int?)null));
				Instruction handlerEnd = e.HandlerEnd;
				obj[4] = ((handlerEnd != null) ? new int?(handlerEnd.Offset) : ((int?)null));
				Instruction filterStart = e.FilterStart;
				obj[5] = ((filterStart != null) ? new int?(filterStart.Offset) : ((int?)null));
				TypeReference catchType = e.CatchType;
				obj[6] = ((catchType != null) ? ((MemberReference)catchType).FullName : null);
				return string.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}", obj);
			}));
			using SHA256 sHA = SHA256.Create();
			return BitConverter.ToString(sHA.ComputeHash(Encoding.UTF8.GetBytes(s))).Replace("-", "");
		}

		internal static Site[] Validate(AssemblyDefinition assembly, bool dedicated)
		{
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			Site[] array = Sites(dedicated);
			HashSet<Instruction> hashSet = new HashSet<Instruction>();
			Site[] array2 = array;
			foreach (Site site in array2)
			{
				MethodDefinition val = ((IEnumerable<MethodDefinition>)((IEnumerable<TypeDefinition>)assembly.MainModule.Types).Single((TypeDefinition t) => ((MemberReference)t).FullName == site.Type).Methods).Single((MethodDefinition m) => ((MemberReference)m).Name == site.Method);
				if (!val.HasBody || !Fingerprints.Contains(Fingerprint(val)))
				{
					throw new InvalidOperationException("Unaudited player-cap method: " + site.Type + "." + site.Method);
				}
				Collection<Instruction> instructions = val.Body.Instructions;
				int num = 0;
				for (int num2 = 0; num2 < instructions.Count; num2++)
				{
					int num3 = num2 + ((!site.Previous) ? 1 : (-1));
					if (!TryConstant(instructions[num2], out var value) || num3 < 0 || num3 >= instructions.Count)
					{
						continue;
					}
					object operand = instructions[num3].Operand;
					MemberReference val2 = (MemberReference)((operand is MemberReference) ? operand : null);
					if (val2 != null && !(val2.Name != site.Member) && !(((MemberReference)val2.DeclaringType).FullName != site.MemberType))
					{
						if (value != site.Baseline)
						{
							throw new InvalidOperationException("Changed capacity literal in " + ((MemberReference)val).FullName);
						}
						num++;
						hashSet.Add(instructions[num2]);
					}
				}
				if (num != 1)
				{
					throw new InvalidOperationException("Expected exactly one cap site: " + ((MemberReference)val).FullName);
				}
				Site site2 = site;
				MetadataToken metadataToken = ((MemberReference)val).MetadataToken;
				site2.Token = ((MetadataToken)(ref metadataToken)).ToInt32();
				site.Rva = val.RVA;
			}
			foreach (TypeDefinition item in AllTypes((IEnumerable<TypeDefinition>)assembly.MainModule.Types))
			{
				foreach (MethodDefinition item2 in ((IEnumerable<MethodDefinition>)item.Methods).Where((MethodDefinition m) => m.HasBody))
				{
					Collection<Instruction> instructions2 = item2.Body.Instructions;
					for (int num4 = 0; num4 < instructions2.Count; num4++)
					{
						if (TryConstant(instructions2[num4], out var value2) && !hashSet.Contains(instructions2[num4]))
						{
							MemberReference val3 = (MemberReference)((num4 + 1 < instructions2.Count) ? /*isinst with value type is only supported in some contexts*/: null);
							MemberReference val4 = (MemberReference)((num4 > 0) ? /*isinst with value type is only supported in some contexts*/: null);
							if ((!(((MemberReference)item).FullName == "ServerListEntryData") || !(((MemberReference)item2).Name == ".ctor") || !(((val3 != null) ? val3.Name : null) == "m_playerLimit")) && (!(((MemberReference)item).FullName == "ServerMatchmakingData") || !(((MemberReference)item2).Name == ".ctor") || !(((val3 != null) ? val3.Name : null) == "m_playerLimit") || value2 != 0) && (!(((MemberReference)item).FullName == "ZNet") || !(((MemberReference)item2).Name == "UpdateNetTime") || !(((val4 != null) ? val4.Name : null) == "GetNrOfPlayers") || value2 != 0) && (((val4 != null) ? val4.Name : null) == "GetNrOfPlayers" || (val3 != null && new string[7] { "SetMaxPlayerCount", "set_MaxPlayerCount", "MaxPlayers", "m_maxPlayers", "m_playerLimit", "CreateLobby", "SetLobbyMemberLimit" }.Contains(val3.Name))))
							{
								throw new InvalidOperationException("Unaccounted literal limit: " + ((MemberReference)item2).FullName + " / " + (object)instructions2[num4]);
							}
						}
					}
				}
			}
			return array;
		}

		internal static bool IsDedicated(AssemblyDefinition assembly)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Invalid comparison between Unknown and I4
			Collection<Instruction> instructions = ((IEnumerable<MethodDefinition>)((IEnumerable<TypeDefinition>)assembly.MainModule.Types).Single((TypeDefinition t) => ((MemberReference)t).Name == "ZNet").Methods).Single((MethodDefinition m) => ((MemberReference)m).Name == "IsDedicated").Body.Instructions;
			if (instructions.Count == 2)
			{
				OpCode opCode = instructions[1].OpCode;
				if ((int)((OpCode)(ref opCode)).Code == 41 && TryConstant(instructions[0], out var value) && (value == 0 || value == 1))
				{
					return value == 1;
				}
			}
			throw new InvalidOperationException("Unknown dedicated-server build marker.");
		}

		internal static byte[] MethodCode(byte[] image, int rva)
		{
			if (image == null || image.Length < 64 || image[0] != 77 || image[1] != 90)
			{
				throw new InvalidOperationException("Invalid game PE image.");
			}
			int num = BitConverter.ToInt32(image, 60);
			if (BitConverter.ToInt32(image, num) != 17744)
			{
				throw new InvalidOperationException("Invalid PE signature.");
			}
			int num2 = BitConverter.ToUInt16(image, num + 6);
			int num3 = num + 24 + BitConverter.ToUInt16(image, num + 20);
			for (int i = 0; i < num2; i++)
			{
				int num4 = checked(num3 + i * 40);
				int num5 = BitConverter.ToInt32(image, num4 + 12);
				int num6 = BitConverter.ToInt32(image, num4 + 16);
				if (rva < num5 || (long)rva - (long)num5 >= num6)
				{
					continue;
				}
				int num7 = checked(BitConverter.ToInt32(image, num4 + 20) + rva - num5);
				int num8;
				int num9;
				if ((image[num7] & 3) == 2)
				{
					num8 = 1;
					num9 = image[num7] >> 2;
				}
				else
				{
					if ((image[num7] & 3) != 3)
					{
						throw new InvalidOperationException("Unknown method header.");
					}
					num8 = (BitConverter.ToUInt16(image, num7) >> 12) * 4;
					num9 = BitConverter.ToInt32(image, num7 + 4);
				}
				if (num8 < 1 || num9 < 0 || (long)num7 + (long)num8 + num9 > image.Length)
				{
					throw new InvalidOperationException("Truncated method body.");
				}
				byte[] array = new byte[num9];
				Buffer.BlockCopy(image, num7 + num8, array, 0, num9);
				return array;
			}
			throw new InvalidOperationException("Method RVA outside game PE sections.");
		}

		internal static IEnumerable<TypeDefinition> AllTypes(IEnumerable<TypeDefinition> types)
		{
			foreach (TypeDefinition type in types)
			{
				yield return type;
				foreach (TypeDefinition item in AllTypes((IEnumerable<TypeDefinition>)type.NestedTypes))
				{
					yield return item;
				}
			}
		}

		internal static bool TryConstant(Instruction instruction, out int value)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Invalid comparison between Unknown and I4
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Invalid comparison between Unknown and I4
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected I4, but got Unknown
			value = 0;
			OpCode opCode = instruction.OpCode;
			if ((int)((OpCode)(ref opCode)).Code != 32)
			{
				opCode = instruction.OpCode;
				if ((int)((OpCode)(ref opCode)).Code != 31)
				{
					opCode = instruction.OpCode;
					if ((int)((OpCode)(ref opCode)).Code >= 22)
					{
						opCode = instruction.OpCode;
						if ((int)((OpCode)(ref opCode)).Code <= 30)
						{
							opCode = instruction.OpCode;
							value = ((OpCode)(ref opCode)).Code - 22;
							return true;
						}
					}
					return false;
				}
			}
			value = Convert.ToInt32(instruction.Operand);
			return true;
		}
	}
	internal static class CapacityRewrite
	{
		internal static List<CodeInstruction> Apply(IEnumerable<CodeInstruction> instructions, CapacityAudit.Site site, int players, bool dedicated)
		{
			List<CodeInstruction> list = instructions.ToList();
			List<int> list2 = new List<int>();
			for (int i = 0; i < list.Count; i++)
			{
				int num = i + ((!site.Previous) ? 1 : (-1));
				if (CodeInstructionExtensions.LoadsConstant(list[i], (long)site.Baseline) && num >= 0 && num < list.Count && list[num].operand is MemberInfo memberInfo && memberInfo.Name == site.Member && memberInfo.DeclaringType.FullName == site.MemberType)
				{
					list2.Add(i);
				}
			}
			if (list2.Count != 1)
			{
				throw new InvalidOperationException("Capacity transpiler expected one replacement: " + site.Type + "." + site.Method);
			}
			int num2 = CapacityAudit.Limit(players, dedicated, site.Transport);
			list[list2[0]].opcode = OpCodes.Ldc_I4;
			list[list2[0]].operand = num2;
			return list;
		}
	}
	internal static class SendWindowPressure
	{
		internal static bool? Estimate(bool playFab, double? queuedBytes, double? inFlightBytes, int? appMessages)
		{
			if (appMessages > 0)
			{
				return true;
			}
			if (playFab)
			{
				if (!inFlightBytes.HasValue)
				{
					return null;
				}
				return inFlightBytes.Value * 0.25 >= 8192.0;
			}
			if (!queuedBytes.HasValue || !inFlightBytes.HasValue)
			{
				return null;
			}
			return queuedBytes.Value + inFlightBytes.Value >= 8192.0;
		}
	}
	internal sealed class ByteRate
	{
		private int _previous;

		private double _time;

		private bool _seeded;

		internal double? Sample(int value, double now)
		{
			uint num = (uint)(value - _previous);
			double num2 = now - _time;
			double? result = ((_seeded && num2 > 0.0 && num <= int.MaxValue) ? new double?((double)num / num2) : ((double?)null));
			_seeded = true;
			_previous = value;
			_time = now;
			return result;
		}
	}
	internal sealed class WarningLatch
	{
		private bool _condition;

		private bool _active;

		private bool _seeded;

		private double _changedAt;

		private double _lastWarning = double.NegativeInfinity;

		internal int Observe(bool condition, double now, double hold, double cooldown)
		{
			if (!_seeded || condition != _condition)
			{
				_seeded = true;
				_condition = condition;
				_changedAt = now;
			}
			if (now - _changedAt < hold)
			{
				return 0;
			}
			if (condition && now - _lastWarning >= cooldown)
			{
				_active = true;
				_lastWarning = now;
				return 1;
			}
			if (!condition && _active)
			{
				_active = false;
				return -1;
			}
			return 0;
		}
	}
	internal sealed class PayloadMeter
	{
		private int _sent;

		private int _received;

		private readonly ByteRate _sentRate = new ByteRate();

		private readonly ByteRate _receivedRate = new ByteRate();

		internal void Sent(int bytes)
		{
			if (bytes > 0)
			{
				Interlocked.Add(ref _sent, bytes);
			}
		}

		internal void Received(int bytes)
		{
			if (bytes > 0)
			{
				Interlocked.Add(ref _received, bytes);
			}
		}

		internal (double? Sent, double? Received) Sample(double now)
		{
			return (Sent: _sentRate.Sample(Volatile.Read(in _sent), now), Received: _receivedRate.Sample(Volatile.Read(in _received), now));
		}
	}
	internal sealed class TransferCounter<TKey>
	{
		private readonly int _maximum;

		private readonly Dictionary<TKey, double> _recent = new Dictionary<TKey, double>();

		private readonly Queue<TKey> _order = new Queue<TKey>();

		internal long Assigned;

		internal long Released;

		internal long Transferred;

		internal long RapidTransfers;

		internal int Tracked => _recent.Count;

		internal TransferCounter(int maximum)
		{
			_maximum = Math.Max(1, maximum);
		}

		internal void Record(TKey id, long before, long after, double now)
		{
			if (before == after)
			{
				return;
			}
			if (before == 0L)
			{
				Assigned++;
				return;
			}
			if (after == 0L)
			{
				Released++;
				return;
			}
			Transferred++;
			if (_recent.TryGetValue(id, out var value) && now - value <= 10.0)
			{
				RapidTransfers++;
			}
			if (!_recent.ContainsKey(id))
			{
				if (_recent.Count >= _maximum)
				{
					_recent.Remove(_order.Dequeue());
				}
				_order.Enqueue(id);
			}
			_recent[id] = now;
		}

		internal void ResetInterval()
		{
			Assigned = (Released = (Transferred = (RapidTransfers = 0L)));
		}

		internal void Clear()
		{
			ResetInterval();
			_recent.Clear();
			_order.Clear();
		}
	}
	internal sealed class ObservatoryCounter
	{
		private readonly object _gate = new object();

		private int _created;

		private int _destroyed;

		private long _sequence;

		private double _lastSaveMilliseconds;

		private double _lastLoadMilliseconds;

		private ZdoObservatorySnapshot _current = ZdoObservatorySnapshot.Empty;

		internal ZdoObservatorySnapshot Current
		{
			get
			{
				lock (_gate)
				{
					return _current;
				}
			}
		}

		internal void MarkCreated()
		{
			lock (_gate)
			{
				_created = SaturatingIncrement(_created);
			}
		}

		internal void MarkDestroyed()
		{
			lock (_gate)
			{
				_destroyed = SaturatingIncrement(_destroyed);
			}
		}

		internal void RecordSaveDuration(long startedTimestamp)
		{
			RecordDuration(startedTimestamp, save: true);
		}

		internal void RecordLoadDuration(long startedTimestamp)
		{
			RecordDuration(startedTimestamp, save: false);
		}

		internal ZdoObservatorySnapshot Capture(long unixMilliseconds, int totalObjects, int connectedPeers, int sentLastSecond, int receivedLastSecond)
		{
			lock (_gate)
			{
				_sequence = ((_sequence == long.MaxValue) ? long.MaxValue : (_sequence + 1));
				_current = new ZdoObservatorySnapshot(_sequence, Math.Max(0L, unixMilliseconds), Math.Max(0, totalObjects), Math.Max(0, connectedPeers), _created, _destroyed, Math.Max(0, sentLastSecond), Math.Max(0, receivedLastSecond), _lastSaveMilliseconds, _lastLoadMilliseconds);
				_created = 0;
				_destroyed = 0;
				return _current;
			}
		}

		internal void Reset()
		{
			lock (_gate)
			{
				_created = 0;
				_destroyed = 0;
				_sequence = 0L;
				_lastSaveMilliseconds = 0.0;
				_lastLoadMilliseconds = 0.0;
				_current = ZdoObservatorySnapshot.Empty;
			}
		}

		private void RecordDuration(long startedTimestamp, bool save)
		{
			if (startedTimestamp <= 0)
			{
				return;
			}
			long num = Stopwatch.GetTimestamp() - startedTimestamp;
			if (num < 0)
			{
				return;
			}
			double num2 = (double)num * 1000.0 / (double)Stopwatch.Frequency;
			lock (_gate)
			{
				if (save)
				{
					_lastSaveMilliseconds = num2;
				}
				else
				{
					_lastLoadMilliseconds = num2;
				}
			}
		}

		private static int SaturatingIncrement(int value)
		{
			if (value != int.MaxValue)
			{
				return value + 1;
			}
			return value;
		}
	}
}
namespace RunicWorldEngine.Contracts
{
	internal sealed class ZdoObservatorySnapshot
	{
		internal long Sequence { get; }

		internal long CapturedUnixMilliseconds { get; }

		internal int TotalObjects { get; }

		internal int ConnectedPeers { get; }

		internal int CreatedSincePreviousSample { get; }

		internal int DestroyedSincePreviousSample { get; }

		internal int SentLastSecond { get; }

		internal int ReceivedLastSecond { get; }

		internal double LastSaveMilliseconds { get; }

		internal double LastLoadMilliseconds { get; }

		internal static ZdoObservatorySnapshot Empty { get; } = new ZdoObservatorySnapshot(0L, 0L, 0, 0, 0, 0, 0, 0, 0.0, 0.0);

		internal ZdoObservatorySnapshot(long sequence, long capturedUnixMilliseconds, int totalObjects, int connectedPeers, int createdSincePreviousSample, int destroyedSincePreviousSample, int sentLastSecond, int receivedLastSecond, double lastSaveMilliseconds, double lastLoadMilliseconds)
		{
			Sequence = Math.Max(0L, sequence);
			CapturedUnixMilliseconds = Math.Max(0L, capturedUnixMilliseconds);
			TotalObjects = Math.Max(0, totalObjects);
			ConnectedPeers = Math.Max(0, connectedPeers);
			CreatedSincePreviousSample = Math.Max(0, createdSincePreviousSample);
			DestroyedSincePreviousSample = Math.Max(0, destroyedSincePreviousSample);
			SentLastSecond = Math.Max(0, sentLastSecond);
			ReceivedLastSecond = Math.Max(0, receivedLastSecond);
			LastSaveMilliseconds = Math.Max(0.0, lastSaveMilliseconds);
			LastLoadMilliseconds = Math.Max(0.0, lastLoadMilliseconds);
		}
	}
}