Decompiled source of NoodlesMcDoodles v1.0.12

plugins/NoodlesMcDoodles.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Sockets;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using NoodlesMcDoodles.Core;
using NoodlesMcDoodles.Gameplay;
using NoodlesMcDoodles.Ownership;
using NoodlesMcDoodles.Transport;
using Steamworks;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: AssemblyCompany("NoodlesMcDoodles")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.12.0")]
[assembly: AssemblyInformationalVersion("1.0.12")]
[assembly: AssemblyProduct("NoodlesMcDoodles")]
[assembly: AssemblyTitle("NoodlesMcDoodles")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.12.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace NoodlesMcDoodles.ZoneSim
{
	internal static class CreateNearFirstOrder
	{
		[HarmonyPatch(typeof(ZNetScene), "CreateObjectsSorted")]
		internal static class Patch_ZNetScene_CreateObjectsSorted_NearFirst
		{
			private static readonly MethodInfo s_distanceSqr = AccessTools.Method(typeof(Utils), "DistanceSqr", (Type[])null, (Type[])null);

			private static readonly MethodInfo s_effectiveDistanceSqr = AccessTools.Method(typeof(CreateNearFirstOrder), "EffectiveDistanceSqr", (Type[])null, (Type[])null);

			[HarmonyTranspiler]
			internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Expected O, but got Unknown
				if (s_distanceSqr == null || s_effectiveDistanceSqr == null)
				{
					NoodlesLog.Error("NoodlesMcDoodles Z-near-first anchor: Utils.DistanceSqr or its own replacement helper did not resolve via reflection -- leaving CreateObjectsSorted's sort key completely unpatched (vanilla's own distance-to-reference-position order).");
					return instructions;
				}
				try
				{
					CodeMatcher obj = new CodeMatcher(instructions, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
					{
						new CodeMatch((OpCode?)OpCodes.Call, (object)s_distanceSqr, (string)null)
					}).ThrowIfInvalid("NoodlesMcDoodles Z-near-first anchor: call Utils.DistanceSqr(Vector3,Vector3) not found in ZNetScene.CreateObjectsSorted");
					obj.SetOperandAndAdvance((object)s_effectiveDistanceSqr);
					return obj.InstructionEnumeration();
				}
				catch (Exception arg)
				{
					NoodlesLog.Error("NoodlesMcDoodles Z-near-first transpiler (CreateObjectsSorted) anchor not found -- leaving this method completely unpatched (vanilla's own sort key, pre-round-4 " + $"behaviour) rather than risk a partial/unsafe patch: {arg}");
					return instructions;
				}
			}
		}

		private static int s_cachedFrame = -1;

		private static readonly List<Vector3> s_peerPositions = new List<Vector3>();

		private static float EffectiveDistanceSqr(Vector3 referencePosition, Vector3 position)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (!ZoneSimConfig.ServerZoneSimFlag.Active || !ZoneSimConfig.IsAuthoritativeProcess())
			{
				return Utils.DistanceSqr(referencePosition, position);
			}
			RefreshPeerPositionsIfNeeded();
			if (s_peerPositions.Count == 0)
			{
				return Utils.DistanceSqr(referencePosition, position);
			}
			float num = float.MaxValue;
			for (int i = 0; i < s_peerPositions.Count; i++)
			{
				float num2 = Utils.DistanceSqr(s_peerPositions[i], position);
				if (num2 < num)
				{
					num = num2;
				}
			}
			return num;
		}

		private static void RefreshPeerPositionsIfNeeded()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			int frameCount = Time.frameCount;
			if (frameCount == s_cachedFrame)
			{
				return;
			}
			s_cachedFrame = frameCount;
			s_peerPositions.Clear();
			ZNet instance = ZNet.instance;
			List<ZNetPeer> list = ((instance != null) ? instance.GetPeers() : null);
			if (list == null)
			{
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				ZNetPeer val = list[i];
				if (PeerReadyState.HasFirstRealPosition(val))
				{
					s_peerPositions.Add(val.GetRefPos());
				}
			}
		}
	}
	internal static class CreateObjectsBudget
	{
		[HarmonyPatch(typeof(ZNetScene), "CreateObjects")]
		internal static class Patch_ZNetScene_CreateObjects_FrameBudget
		{
			[HarmonyTranspiler]
			internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Expected O, but got Unknown
				CodeMatcher obj = new CodeMatcher(instructions, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
				{
					new CodeMatch((OpCode?)OpCodes.Ldc_I4_S, (object)(sbyte)100, (string)null)
				}).ThrowIfInvalid("NoodlesMcDoodles Z6 anchor: ldc.i4.s 100 (InLoadingScreen()==true branch) not found in ZNetScene.CreateObjects");
				obj.SetInstructionAndAdvance(CodeInstruction.Call(typeof(ZoneSimConfig), "EffectiveMaxCreatedPerFrame", (Type[])null, (Type[])null));
				return obj.InstructionEnumeration();
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Update")]
		internal static class Patch_ZNetScene_Update_CreateDestroyCadence
		{
			[HarmonyTranspiler]
			internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_0002: 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_002a: Expected O, but got Unknown
				CodeMatcher obj = new CodeMatcher(instructions, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
				{
					new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)(1f / 30f), (string)null)
				}).ThrowIfInvalid("NoodlesMcDoodles Z6 anchor: 1f/30f (create/destroy cadence gate) not found in ZNetScene.Update");
				obj.SetInstructionAndAdvance(CodeInstruction.Call(typeof(ZoneSimConfig), "EffectiveCreateDestroyIntervalSeconds", (Type[])null, (Type[])null));
				return obj.InstructionEnumeration();
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "CreateObjects")]
		internal static class Patch_ZNetScene_CreateObjects_TimeBudgetTick
		{
			[HarmonyPrefix]
			internal static void Prefix()
			{
				s_tickStopwatch.Restart();
				s_createdThisTick = 0;
				s_budgetAppliedThisTick = false;
			}

			[HarmonyPostfix]
			internal static void Postfix(List<ZDO> currentNearObjects, List<ZDO> currentDistantObjects)
			{
				if (!ZoneSimConfig.ServerZoneSimFlag.Active || !ZoneSimConfig.IsAuthoritativeProcess())
				{
					return;
				}
				try
				{
					int num = 0;
					foreach (ZDO currentNearObject in currentNearObjects)
					{
						if (!currentNearObject.Created)
						{
							num++;
						}
					}
					foreach (ZDO currentDistantObject in currentDistantObjects)
					{
						if (!currentDistantObject.Created)
						{
							num++;
						}
					}
					Telemetry_ZoneSim.SetCreateBacklog(num);
					Telemetry_ZoneSim.SetCreatedThisTick(s_createdThisTick);
					if (s_budgetAppliedThisTick)
					{
						Telemetry_ZoneSim.CreateBudgetLimitedTicksTotal.Increment();
					}
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_ZNetScene_CreateObjects_TimeBudgetTick.Postfix", e);
				}
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "CreateObjectsSorted")]
		internal static class Patch_ZNetScene_CreateObjectsSorted_TimeBudget
		{
			[HarmonyTranspiler]
			internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_0002: 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_0021: Expected O, but got Unknown
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Expected O, but got Unknown
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Expected O, but got Unknown
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Expected O, but got Unknown
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Expected O, but got Unknown
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				//IL_009e: Expected O, but got Unknown
				//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ac: Expected O, but got Unknown
				try
				{
					CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[5]
					{
						new CodeMatch((OpCode?)OpCodes.Ldarg_3, (object)null, (string)null),
						new CodeMatch((OpCode?)OpCodes.Ldind_I4, (object)null, (string)null),
						new CodeMatch((OpCode?)OpCodes.Ldloc_1, (object)null, (string)null),
						new CodeMatch((OpCode?)OpCodes.Blt, (object)null, (string)null),
						new CodeMatch((OpCode?)OpCodes.Leave, (object)null, (string)null)
					}).ThrowIfInvalid("NoodlesMcDoodles Z6 time-budget anchor: `if (created >= num) break;` (SERVER:82178-82181) not found in ZNetScene.CreateObjectsSorted");
					val.Advance(3);
					val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[3]
					{
						new CodeInstruction(OpCodes.Ldarg_3, (object)null),
						new CodeInstruction(OpCodes.Ldind_I4, (object)null),
						CodeInstruction.Call(typeof(CreateObjectsBudget), "EffectiveCreateCap", (Type[])null, (Type[])null)
					});
					return val.InstructionEnumeration();
				}
				catch (Exception arg)
				{
					NoodlesLog.Error("NoodlesMcDoodles Z6 time-budget transpiler (CreateObjectsSorted) anchor not found -- leaving this method completely unpatched (vanilla's own count-only cap, " + $"pre-1.0.9 behaviour) rather than risk a partial/unsafe patch: {arg}");
					return instructions;
				}
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "CreateDistantObjects")]
		internal static class Patch_ZNetScene_CreateDistantObjects_TimeBudget
		{
			[HarmonyTranspiler]
			internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_0002: 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_0021: Expected O, but got Unknown
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Expected O, but got Unknown
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Expected O, but got Unknown
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Expected O, but got Unknown
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Expected O, but got Unknown
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				//IL_009e: Expected O, but got Unknown
				//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ac: Expected O, but got Unknown
				try
				{
					CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null).MatchStartForward((CodeMatch[])(object)new CodeMatch[5]
					{
						new CodeMatch((OpCode?)OpCodes.Ldarg_3, (object)null, (string)null),
						new CodeMatch((OpCode?)OpCodes.Ldind_I4, (object)null, (string)null),
						new CodeMatch((OpCode?)OpCodes.Ldarg_2, (object)null, (string)null),
						new CodeMatch((OpCode?)OpCodes.Ble, (object)null, (string)null),
						new CodeMatch((OpCode?)OpCodes.Leave, (object)null, (string)null)
					}).ThrowIfInvalid("NoodlesMcDoodles Z6 time-budget anchor: `if (created > maxCreatedPerFrame) break;` (SERVER:82217-82220) not found in ZNetScene.CreateDistantObjects");
					val.Advance(3);
					val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[3]
					{
						new CodeInstruction(OpCodes.Ldarg_3, (object)null),
						new CodeInstruction(OpCodes.Ldind_I4, (object)null),
						CodeInstruction.Call(typeof(CreateObjectsBudget), "EffectiveCreateCap", (Type[])null, (Type[])null)
					});
					return val.InstructionEnumeration();
				}
				catch (Exception arg)
				{
					NoodlesLog.Error("NoodlesMcDoodles Z6 time-budget transpiler (CreateDistantObjects) anchor not found -- leaving this method completely unpatched (vanilla's own count-only cap, " + $"pre-1.0.9 behaviour) rather than risk a partial/unsafe patch: {arg}");
					return instructions;
				}
			}
		}

		private static readonly Stopwatch s_tickStopwatch = new Stopwatch();

		private static int s_createdThisTick;

		private static bool s_budgetAppliedThisTick;

		private const double RecentFrameHotMs = 20.0;

		internal static void LogActiveBranchOnce()
		{
			NoodlesLog.Info("ZoneSim Z6: ZNetScene.CreateObjects's InLoadingScreen()==true branch (the '100' literal) is ALWAYS the one a real dedicated server takes (Player.m_localPlayer is permanently null server-side) — MaxCreatedPerFrame tunes that branch; the '10' literal is a dead branch here and is left untouched.");
		}

		private static int EffectiveCreateCap(int originalCap, int createdSoFar)
		{
			if (!ZoneSimConfig.ServerZoneSimFlag.Active || !ZoneSimConfig.IsAuthoritativeProcess())
			{
				return originalCap;
			}
			s_createdThisTick = createdSoFar;
			if (createdSoFar < ZoneSimConfig.MinCreatedPerTick.Value)
			{
				return originalCap;
			}
			if (!(FrameTiming.RecentMeanMs > 20.0) && s_tickStopwatch.Elapsed.TotalMilliseconds < (double)ZoneSimConfig.CreateBudgetMs.Value)
			{
				return originalCap;
			}
			s_budgetAppliedThisTick = true;
			return createdSoFar - 1;
		}
	}
	internal static class GraceHold
	{
		private readonly struct Entry
		{
			public readonly int TicksRemaining;

			public readonly bool IsNear;

			public Entry(int ticksRemaining, bool isNear)
			{
				TicksRemaining = ticksRemaining;
				IsNear = isNear;
			}
		}

		private static readonly Dictionary<ZDO, Entry> s_held = new Dictionary<ZDO, Entry>();

		internal static int HeldCount => s_held.Count;

		public static void Refresh(ZDO zdo, bool isNear)
		{
			s_held[zdo] = new Entry(ZoneSimConfig.ObjectUnfeedGraceTicks.Value, isNear);
		}

		public static void TickAndReappend(HashSet<ZDO> fedThisTick, List<ZDO> near, List<ZDO> distant)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			if (s_held.Count == 0)
			{
				return;
			}
			foreach (ZDO item in s_held.Keys.ToList())
			{
				if (fedThisTick.Contains(item))
				{
					s_held.Remove(item);
					continue;
				}
				Entry entry = s_held[item];
				if (entry.TicksRemaining <= 0 || !item.IsValid())
				{
					s_held.Remove(item);
					continue;
				}
				if (ZoneHealth.IsPoisoned(item.GetPrefab()) || ZoneHealth.IsQuarantined(item.GetSector()))
				{
					s_held.Remove(item);
					continue;
				}
				(entry.IsNear ? near : distant).Add(item);
				Telemetry_ZoneSim.ObjectsAppendedTotal.Increment();
				s_held[item] = new Entry(entry.TicksRemaining - 1, entry.IsNear);
			}
		}
	}
	internal static class HeldBandPreservationGuard
	{
		[HarmonyPatch(typeof(WearNTear), "UpdateWear")]
		internal static class Patch_WearNTear_UpdateWear_HeldBandFreeze
		{
			private static bool Prefix(WearNTear __instance)
			{
				//IL_005e: 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)
				if (!s_flag.Active)
				{
					return true;
				}
				try
				{
					if (!TryGetHeldBandZone(((Component)__instance).gameObject, out var position, out var zone))
					{
						return true;
					}
					s_wearDamageSuppressed.Increment();
					RecordBlock("heldband.wearntear.wear", "WearNTear.UpdateWear damage/wear accumulation skipped for '" + ((Object)((Component)__instance).gameObject).name + "' " + $"at {position} (zone {zone}) -- unattended in the held band (Finding 1); resumes the instant a " + "real peer's active area reaches it.", mainLog: false);
					return false;
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_WearNTear_UpdateWear_HeldBandFreeze", e);
					return true;
				}
			}
		}

		[HarmonyPatch(typeof(Ship), "TakeAshlandsDamage")]
		internal static class Patch_Ship_TakeAshlandsDamage_HeldBandFreeze
		{
			private static bool Prefix(Ship __instance)
			{
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				if (!s_flag.Active)
				{
					return true;
				}
				try
				{
					if (!TryGetHeldBandZone(((Component)__instance).gameObject, out var position, out var zone))
					{
						return true;
					}
					s_shipAshlandsDamageSuppressed.Increment();
					RecordBlock("heldband.ship.ashlands", $"Ship.TakeAshlandsDamage skipped for '{((Object)((Component)__instance).gameObject).name}' at {position} (zone {zone}) " + "-- unattended in the held band (Finding 1); resumes the instant a real peer's active area reaches it.");
					return false;
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_Ship_TakeAshlandsDamage_HeldBandFreeze", e);
					return true;
				}
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "TimedDestruction")]
		internal static class Patch_ItemDrop_TimedDestruction_HeldBandFreeze
		{
			private static bool Prefix(ItemDrop __instance)
			{
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				if (!s_flag.Active)
				{
					return true;
				}
				try
				{
					if (!TryGetHeldBandZone(((Component)__instance).gameObject, out var position, out var zone))
					{
						return true;
					}
					s_itemDespawnSuppressed.Increment();
					RecordBlock("heldband.itemdrop.despawn", $"ItemDrop.TimedDestruction skipped for '{((Object)((Component)__instance).gameObject).name}' at {position} (zone {zone}) " + "-- unattended in the held band (Finding 2); item is preserved until a real peer's active area reaches it.");
					return false;
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_ItemDrop_TimedDestruction_HeldBandFreeze", e);
					return true;
				}
			}
		}

		[HarmonyPatch(typeof(Character), "RPC_Damage")]
		internal static class Patch_Character_RPC_Damage_TameFreeze
		{
			private static bool Prefix(Character __instance, HitData hit)
			{
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0080: Unknown result type (might be due to invalid IL or missing references)
				if (!s_flag.Active)
				{
					return true;
				}
				try
				{
					if ((Object)(object)((Component)__instance).GetComponent<Tameable>() == (Object)null)
					{
						return true;
					}
					Character val = ((hit != null) ? hit.GetAttacker() : null);
					if ((Object)(object)val != (Object)null && val.IsPlayer())
					{
						return true;
					}
					if (!TryGetHeldBandZone(((Component)__instance).gameObject, out var position, out var zone))
					{
						return true;
					}
					s_tameCombatSuppressed.Increment();
					RecordBlock("heldband.tame.combat", $"Character.RPC_Damage skipped for tame '{((Object)((Component)__instance).gameObject).name}' at {position} (zone {zone}) " + "-- non-player attacker, unattended in the held band (Finding 3); a player can still damage this tame normally.");
					return false;
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_Character_RPC_Damage_TameFreeze", e);
					return true;
				}
			}
		}

		[HarmonyPatch(typeof(WearNTear), "ApplyDamage")]
		internal static class Patch_WearNTear_ApplyDamage_HeldBandFreeze
		{
			private static bool Prefix(WearNTear __instance, float damage, HitData hitData, ref bool __result)
			{
				//IL_0075: 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)
				if (!s_flag.Active)
				{
					return true;
				}
				try
				{
					Character val = ((hitData != null) ? hitData.GetAttacker() : null);
					if ((Object)(object)val != (Object)null && val.IsPlayer())
					{
						return true;
					}
					if (!TryGetHeldBandZone(((Component)__instance).gameObject, out var position, out var zone))
					{
						return true;
					}
					s_pieceCombatSuppressed.Increment();
					RecordBlock("heldband.wearntear.combat", $"WearNTear.ApplyDamage skipped ({damage:F1} dmg) for '{((Object)((Component)__instance).gameObject).name}' at " + $"{position} (zone {zone}) -- non-player attacker, unattended in the held band (Finding 4); " + "resumes the instant a real peer's active area reaches it.");
					__result = false;
					return false;
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_WearNTear_ApplyDamage_HeldBandFreeze", e);
					return true;
				}
			}
		}

		[HarmonyPatch(typeof(WearNTear), "RPC_Remove")]
		internal static class Patch_WearNTear_RPCRemove_MarkPlayerInitiated
		{
			private static void Prefix(WearNTear __instance)
			{
				if (!s_flag.Active)
				{
					return;
				}
				try
				{
					s_pendingRemoveInstance = __instance;
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_WearNTear_RPCRemove_MarkPlayerInitiated", e);
				}
			}

			private static void Postfix(WearNTear __instance)
			{
				try
				{
					if (s_pendingRemoveInstance == __instance)
					{
						s_pendingRemoveInstance = null;
					}
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_WearNTear_RPCRemove_MarkPlayerInitiated", e);
				}
			}
		}

		[HarmonyPatch(typeof(WearNTear), "Destroy")]
		internal static class Patch_WearNTear_Destroy_NoAttackerLossWatch
		{
			private static void Prefix(WearNTear __instance, HitData hitData)
			{
				//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_0114: Unknown result type (might be due to invalid IL or missing references)
				//IL_011b: Unknown result type (might be due to invalid IL or missing references)
				if (!s_flag.Active)
				{
					return;
				}
				try
				{
					if (!IsServerRuntime())
					{
						return;
					}
					bool flag = s_pendingRemoveInstance == __instance;
					s_pendingRemoveInstance = null;
					ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
					if (!((Object)(object)component == (Object)null) && component.IsValid())
					{
						ZDO zDO = component.GetZDO();
						Character val = ((hitData != null) ? hitData.GetAttacker() : null);
						if ((!((Object)(object)val != (Object)null) || !val.IsPlayer()) && !flag && zDO.GetLong(ZDOVars.s_creator, 0L) != 0L && TryGetHeldBandZone(((Component)__instance).gameObject, out var position, out var zone))
						{
							bool num = hitData == null;
							string kind = (num ? "heldBandWearNTearDestroyedNoAttacker" : "heldBandWearNTearDestroyedNonPlayerAttacker");
							string arg = (num ? "no attacker (hitData==null), unattended decay (Finding 1)" : ("non-player attacker '" + (((val != null) ? ((Object)((Component)val).gameObject).name : null) ?? "unknown") + "', combat (Finding 4)"));
							LossSignals.Report(kind, $"{zDO.m_uid} ('{((Object)((Component)__instance).gameObject).name}') is about to be destroyed on the server with " + $"{arg} while player-built and unattended in held-band zone {zone} at {position} " + "-- this should be provably unreachable once the preservation guards above are correct; this catcher firing means one of them has a hole. Standing the mod down for a human to look, per the user's own 'no player built object destroyed' instruction.");
						}
					}
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_WearNTear_Destroy_NoAttackerLossWatch", e);
				}
			}
		}

		private static FeatureFlag s_flag;

		private const int Tier1FirstN = 3;

		private const int Tier2FirstN = 20;

		private const float RateLimitWindowSeconds = 60f;

		private static readonly Counter s_wearDamageSuppressed = Telemetry.GetCounter("zonesim.wearDamageSuppressedHeldBand");

		private static readonly Counter s_shipAshlandsDamageSuppressed = Telemetry.GetCounter("zonesim.shipAshlandsDamageSuppressedHeldBand");

		private static readonly Counter s_itemDespawnSuppressed = Telemetry.GetCounter("zonesim.itemDespawnSuppressedHeldBand");

		private static readonly Counter s_tameCombatSuppressed = Telemetry.GetCounter("gameplay.tameCombatSuppressedHeldBand");

		private static readonly Counter s_pieceCombatSuppressed = Telemetry.GetCounter("zonesim.pieceCombatSuppressedHeldBand");

		private static WearNTear s_pendingRemoveInstance;

		internal static void Init()
		{
			ConfigEntry<bool> config = NoodlesConfig.File.Bind<bool>("Features", "HeldBandPreservationGuard.Active", true, "WP2 (spec.json) — freezes exactly the destructive/despawn vanilla code paths (WearNTear weather/ash/lava/support-loss damage, Ship Ashlands damage, ItemDrop's 1-hour despawn, wildlife-vs-tame combat, wildlife-vs-piece combat) that only fire at all because ServerZoneSim+OwnershipAuthority instantiate and claim the empty held ring nobody is near -- vanilla itself never simulates that ring, so it never runs these paths there either (Findings 1-4: 1-3 Audit A, 4 a fixer pass). SCOPE: ServerZoneMembership (O6/held-band) ONLY, never SharedAreaZoneHold (O10) -- an O10-held object is, by construction, within a real player's own near-ring, so this guard structurally cannot suppress gameplay in front of an actual player. DEFAULT ON (new safety-net feature this spec adds, closes Findings 1-2, adds the tame-protection half of Finding 3, and closes Finding 4's piece-combat gap): unlike most flags in this mod, turning this OFF is NOT the safe fallback while OwnershipAuthority/ServerZoneSim stay on -- it reopens exactly the four findings above (a held-band base decays/despawns/loses tames/loses pieces to wildlife in ways vanilla, which never simulates that ring, would never do). A player can always damage their own or any tame/piece normally regardless of this flag (the Player-attacker bypass in both combat guards is unconditional).");
			s_flag = Features.Register("HeldBandPreservationGuard", config);
			RegisterPatches();
		}

		private static void RegisterPatches()
		{
			PatchRegistry.Register("HeldBandPreservationGuard", typeof(Patch_WearNTear_UpdateWear_HeldBandFreeze));
			PatchRegistry.Register("HeldBandPreservationGuard", typeof(Patch_Ship_TakeAshlandsDamage_HeldBandFreeze));
			PatchRegistry.Register("HeldBandPreservationGuard", typeof(Patch_ItemDrop_TimedDestruction_HeldBandFreeze));
			PatchRegistry.Register("HeldBandPreservationGuard", typeof(Patch_Character_RPC_Damage_TameFreeze));
			PatchRegistry.Register("HeldBandPreservationGuard", typeof(Patch_WearNTear_ApplyDamage_HeldBandFreeze));
			PatchRegistry.Register("HeldBandPreservationGuard", typeof(Patch_WearNTear_RPCRemove_MarkPlayerInitiated));
			PatchRegistry.Register("HeldBandPreservationGuard", typeof(Patch_WearNTear_Destroy_NoAttackerLossWatch));
		}

		private static bool IsServerRuntime()
		{
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				return ZNet.instance.IsServer();
			}
			return false;
		}

		private static bool TryGetHeldBandZone(GameObject go, out Vector3 position, out Vector2s zone)
		{
			//IL_0001: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			position = default(Vector3);
			zone = default(Vector2s);
			if (!IsServerRuntime())
			{
				return false;
			}
			ZNetView component = go.GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return false;
			}
			position = component.GetZDO().GetPosition();
			zone = ZoneSystem.GetZone(position);
			if (!ServerZoneMembership.IsServerHeld(zone))
			{
				return false;
			}
			List<ZNetPeer> peers = ZNet.instance.GetPeers();
			if (peers != null)
			{
				return !AnyPeerSimulatesHere(position, peers);
			}
			return true;
		}

		private static bool AnyPeerSimulatesHere(Vector3 position, List<ZNetPeer> peers)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			foreach (ZNetPeer peer in peers)
			{
				if (peer == null)
				{
					continue;
				}
				if (ZNetScene.InActiveArea(position, peer.GetRefPos()))
				{
					return true;
				}
				if (peer.m_characterID != ZDOID.None && ZDOMan.instance != null)
				{
					ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID);
					if (zDO != null && ZNetScene.InActiveArea(position, zDO.GetPosition()))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static void RecordBlock(string key, string message, bool mainLog = true)
		{
			string message2 = "held-band preservation: " + message;
			if (mainLog)
			{
				NoodlesLog.WarningRateLimited(key, message2, 3, 60f);
			}
			NoodlesLog.DetailRateLimited(key, message2, 20, 60f);
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "CreateObject")]
	internal static class Patch_ZNetScene_CreateObject_Containment
	{
		[HarmonyFinalizer]
		internal static Exception Finalizer(ZDO zdo, Exception __exception)
		{
			//IL_0074: 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_005e: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (__exception == null)
			{
				return null;
			}
			try
			{
				ZNetView.m_useInitZDO = false;
				ZNetView.m_initZDO = null;
			}
			catch (Exception e)
			{
				NoodlesLog.PatchException("Patch_ZNetScene_CreateObject_Containment.StaticFieldCleanup", e);
			}
			if (!ZoneSimConfig.ServerZoneSimFlag.Active || !ZoneSimConfig.IsAuthoritativeProcess())
			{
				return __exception;
			}
			try
			{
				int prefabHash = 0;
				Vector2s zone = default(Vector2s);
				try
				{
					prefabHash = ((zdo != null) ? zdo.GetPrefab() : 0);
					zone = (Vector2s)((zdo != null) ? zdo.GetSector() : default(Vector2s));
				}
				catch
				{
				}
				Telemetry_ZoneSim.InstantiateExceptionsCaught.Increment();
				ZoneHealth.RecordFailure(prefabHash, zone, __exception);
			}
			catch (Exception e2)
			{
				NoodlesLog.PatchException("Patch_ZNetScene_CreateObject_Containment", e2);
			}
			return __exception;
		}
	}
	internal static class ZoneHealth
	{
		private static readonly HashSet<int> s_poisonedPrefabs = new HashSet<int>();

		private static readonly HashSet<Vector2s> s_quarantinedZones = new HashSet<Vector2s>();

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

		private static readonly object s_lock = new object();

		public static int PoisonedCount
		{
			get
			{
				lock (s_lock)
				{
					return s_poisonedPrefabs.Count;
				}
			}
		}

		public static int QuarantinedCount
		{
			get
			{
				lock (s_lock)
				{
					return s_quarantinedZones.Count;
				}
			}
		}

		public static void RecordFailure(int prefabHash, Vector2s zone, Exception cause)
		{
			//IL_0021: 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)
			bool flag;
			lock (s_lock)
			{
				flag = s_poisonedPrefabs.Add(prefabHash);
				s_quarantinedZones.Add(zone);
			}
			if (flag || s_loggedPrefabs.Add(prefabHash))
			{
				NoodlesLog.Warning("instantiate exception from prefab " + StringUtils.StringFromHash(prefabHash) + " in zone " + $"{zone} — poisoning this prefab and quarantining this zone from server-side simulation " + $"(logged once per prefab; see zonesim.instantiateExceptionsCaught for the running count): {cause}");
			}
			Telemetry_ZoneSim.SetPrefabsPoisoned(PoisonedCount);
			Telemetry_ZoneSim.SetZonesQuarantined(QuarantinedCount);
		}

		public static bool IsPoisoned(int prefabHash)
		{
			lock (s_lock)
			{
				return s_poisonedPrefabs.Contains(prefabHash);
			}
		}

		public static bool IsQuarantined(Vector2s zone)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			lock (s_lock)
			{
				return s_quarantinedZones.Contains(zone);
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "CreateObjects")]
	internal static class Patch_ZNetScene_CreateObjects_ObjectFeed
	{
		private static readonly HashSet<ZDO> s_seen = new HashSet<ZDO>();

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

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

		private static readonly SimulationDistance s_singleZoneDistance = new SimulationDistance(0, 0, false);

		[HarmonyPrefix]
		internal static void Prefix(List<ZDO> currentNearObjects, List<ZDO> currentDistantObjects)
		{
			if (!ZoneSimConfig.ServerZoneSimFlag.Active || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return;
			}
			try
			{
				RunFeed(currentNearObjects, currentDistantObjects);
			}
			catch (Exception e)
			{
				NoodlesLog.PatchException("Patch_ZNetScene_CreateObjects_ObjectFeed", e);
			}
		}

		private static void RunFeed(List<ZDO> currentNearObjects, List<ZDO> currentDistantObjects)
		{
			Stopwatch stopwatch = Stopwatch.StartNew();
			try
			{
				RunFeedTimed(currentNearObjects, currentDistantObjects);
			}
			finally
			{
				Telemetry_ZoneSim.SetObjectFeedMs(stopwatch.Elapsed.TotalMilliseconds);
			}
		}

		private static void RunFeedTimed(List<ZDO> currentNearObjects, List<ZDO> currentDistantObjects)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			s_seen.Clear();
			foreach (ZDO currentNearObject in currentNearObjects)
			{
				s_seen.Add(currentNearObject);
			}
			foreach (ZDO currentDistantObject in currentDistantObjects)
			{
				s_seen.Add(currentDistantObject);
			}
			ZoneCap.BeginTick();
			foreach (Vector2s item in PokeRingDriver.ActiveZones())
			{
				if (!ZoneHealth.IsQuarantined(item))
				{
					s_tempNear.Clear();
					s_tempDistant.Clear();
					ZDOMan.instance.FindSectorObjects(item, s_singleZoneDistance, s_tempNear, s_tempDistant);
					int zoneObjectEstimate = s_tempNear.Count + s_tempDistant.Count;
					if (ZoneCap.CanInclude(item, zoneObjectEstimate))
					{
						AppendFiltered(currentNearObjects, s_tempNear, isNear: true);
						AppendFiltered(currentDistantObjects, s_tempDistant, isNear: false);
					}
				}
			}
			GraceHold.TickAndReappend(s_seen, currentNearObjects, currentDistantObjects);
		}

		private static void AppendFiltered(List<ZDO> target, List<ZDO> candidates, bool isNear)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			foreach (ZDO candidate in candidates)
			{
				if (!s_seen.Add(candidate))
				{
					continue;
				}
				int prefab = candidate.GetPrefab();
				if (ZoneHealth.IsPoisoned(prefab))
				{
					continue;
				}
				if ((Object)(object)ZNetScene.instance.GetPrefab(prefab) == (Object)null)
				{
					Telemetry_ZoneSim.ObjectsSkippedMissingPrefab.Increment();
					MissingPrefabLog.WarnOnce(prefab, candidate.GetPosition());
					continue;
				}
				target.Add(candidate);
				Telemetry_ZoneSim.ObjectsAppendedTotal.Increment();
				if (!candidate.Persistent && candidate.IsOwner())
				{
					GraceHold.Refresh(candidate, isNear);
				}
			}
		}
	}
	internal static class MissingPrefabLog
	{
		private static readonly HashSet<int> s_logged = new HashSet<int>();

		public static void WarnOnce(int prefabHash, Vector3 position)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			lock (s_logged)
			{
				if (!s_logged.Add(prefabHash))
				{
					return;
				}
			}
			NoodlesLog.Warning($"skipping unresolved prefab {StringUtils.StringFromHash(prefabHash)} near {position} — this " + "server is likely missing a content mod a client near it has (operational alert, not data loss: the ZDO is simply never fed to this module's own instantiation, so vanilla's destructive invalid-prefab branch is never reached for it).");
		}
	}
	internal sealed class PokeRingDriver : MonoBehaviour
	{
		private readonly struct RingCacheKey : IEquatable<RingCacheKey>
		{
			public readonly Vector2s Center;

			public readonly int Ring;

			public RingCacheKey(Vector2s center, int ring)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				Center = center;
				Ring = ring;
			}

			public bool Equals(RingCacheKey other)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				if (Ring == other.Ring)
				{
					Vector2s center = Center;
					return ((Vector2s)(ref center)).Equals(other.Center);
				}
				return false;
			}

			public override bool Equals(object obj)
			{
				if (obj is RingCacheKey other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				return (((object)Center/*cast due to .constrained prefix*/).GetHashCode() * 397) ^ Ring;
			}
		}

		private static bool s_started;

		private float m_updateTimer;

		private readonly HashSet<Vector2s> m_pokedThisTick = new HashSet<Vector2s>();

		private static readonly Dictionary<RingCacheKey, List<Vector2s>> s_ringZoneCache = new Dictionary<RingCacheKey, List<Vector2s>>();

		private double m_zoneBuildMsThisTick;

		private const double RecentFrameHotMs = 20.0;

		internal static void EnsureStarted()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!s_started)
			{
				s_started = true;
				GameObject val = new GameObject("NoodlesMcDoodles.ZoneSim.PokeRingDriver");
				Object.DontDestroyOnLoad((Object)val);
				val.AddComponent<PokeRingDriver>();
			}
		}

		private static List<Vector2s> RingZonesCached(Vector2s center, int ring)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			RingCacheKey key = new RingCacheKey(center, ring);
			if (!s_ringZoneCache.TryGetValue(key, out var value))
			{
				value = RingZones(center, ring);
				s_ringZoneCache[key] = value;
			}
			return value;
		}

		private void FixedUpdate()
		{
			try
			{
				Tick();
			}
			catch (Exception e)
			{
				NoodlesLog.PatchException("PokeRingDriver", e);
			}
		}

		private void Tick()
		{
			if (ZoneSimConfig.ServerZoneSimFlag.Active && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !((Object)(object)ZoneSystem.instance == (Object)null) && ZoneSystemAccess.IsReady)
			{
				m_updateTimer += Time.fixedDeltaTime;
				if (!(m_updateTimer < ZoneSimConfig.UpdateTickSeconds.Value))
				{
					m_updateTimer = 0f;
					Stopwatch stopwatch = Stopwatch.StartNew();
					RunTick();
					Telemetry_ZoneSim.SetPokeRingTickMs(stopwatch.Elapsed.TotalMilliseconds);
				}
			}
		}

		private void RunTick()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			m_pokedThisTick.Clear();
			s_ringZoneCache.Clear();
			int num = 0;
			int num2 = 0;
			m_zoneBuildMsThisTick = 0.0;
			bool flag = FrameTiming.RecentMeanMs > 20.0;
			int ring = EffectiveRingRadius();
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				if (!PeerReadyState.HasFirstRealPosition(peer))
				{
					continue;
				}
				foreach (Vector2s item in RingZonesCached(ZoneSystem.GetZone(peer.GetRefPos()), ring))
				{
					if (m_pokedThisTick.Add(item) && ZoneSystemAccess.IsZoneGenerated(ZoneSystem.instance, item))
					{
						if (ZoneSystem.instance.IsZoneLoaded(item))
						{
							ZoneSystemAccess.PokeLocalZone(ZoneSystem.instance, item);
							continue;
						}
						if (num >= ZoneSimConfig.MaxZoneBuildsPerTick.Value || (num > 0 && (m_zoneBuildMsThisTick >= (double)ZoneSimConfig.ZoneBuildBudgetMs.Value || flag)))
						{
							num2++;
							continue;
						}
						Stopwatch stopwatch = Stopwatch.StartNew();
						ZoneSystemAccess.PokeLocalZone(ZoneSystem.instance, item);
						stopwatch.Stop();
						m_zoneBuildMsThisTick += stopwatch.Elapsed.TotalMilliseconds;
						num++;
						Telemetry_ZoneSim.ZonesPokedTotal.Increment();
						Telemetry_ZoneSim.SetLastZoneBuildMs(stopwatch.Elapsed.TotalMilliseconds);
					}
				}
			}
			Telemetry_ZoneSim.SetZoneBuildsThisTick(num);
			Telemetry_ZoneSim.SetZoneBuildsDeferredThisTick(num2);
			if (num2 > 0)
			{
				Telemetry_ZoneSim.ZoneBuildsDeferredTotal.Add(num2);
			}
			Telemetry_ZoneSim.SetZonesRealActive(ZoneSystemAccess.ZoneCount(ZoneSystem.instance));
			Telemetry_ZoneSim.SetHeldBandRingBonus(Mathf.Clamp(ZoneSimConfig.HeldBandRingBonus.Value, 0, 2));
		}

		private static int EffectiveRingRadius()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			int value = ZoneSimConfig.PokeRingRadius.Value;
			SimulationDistance syncedSimulationDistance = ZNet.instance.GetSyncedSimulationDistance();
			int nearSimulationDistance = ((SimulationDistance)(ref syncedSimulationDistance)).NearSimulationDistance;
			int num = Mathf.Clamp(ZoneSimConfig.HeldBandRingBonus.Value, 0, 2);
			return Mathf.Min(value, nearSimulationDistance) + num;
		}

		private static List<Vector2s> RingZones(Vector2s center, int ring)
		{
			//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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			ZoneSystem instance = ZoneSystem.instance;
			List<Vector2s> list = new List<Vector2s>();
			Vector2s val = default(Vector2s);
			for (int i = -ring; i <= ring; i++)
			{
				for (int j = -ring; j <= ring; j++)
				{
					((Vector2s)(ref val))..ctor(center.x + j, center.y + i);
					if (instance.ZonesWithinRadius(center, val, ring, false))
					{
						list.Add(val);
					}
				}
			}
			list.Sort((Vector2s a, Vector2s b) => SquaredDistance(center, a).CompareTo(SquaredDistance(center, b)));
			return list;
		}

		private static int SquaredDistance(Vector2s a, Vector2s b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			int num = a.x - b.x;
			int num2 = a.y - b.y;
			return num * num + num2 * num2;
		}

		internal static IEnumerable<Vector2s> ActiveZones()
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)ZoneSystem.instance == (Object)null || !ZoneSystemAccess.IsReady)
			{
				yield break;
			}
			HashSet<Vector2s> seen = new HashSet<Vector2s>();
			int ringRadius = EffectiveRingRadius();
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				if (!PeerReadyState.HasFirstRealPosition(peer))
				{
					continue;
				}
				Vector2s zone = ZoneSystem.GetZone(peer.GetRefPos());
				foreach (Vector2s item in RingZonesCached(zone, ringRadius))
				{
					if (seen.Add(item) && ZoneSystemAccess.ContainsZone(ZoneSystem.instance, item))
					{
						yield return item;
					}
				}
			}
		}
	}
	internal static class PeerReadyState
	{
		public static bool HasFirstRealPosition(ZNetPeer peer)
		{
			//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)
			if (peer != null)
			{
				return peer.GetRefPos() != Vector3.zero;
			}
			return false;
		}
	}
	internal static class SnapGuard
	{
		[HarmonyPatch(typeof(SnapToGround), "SnappAll")]
		internal static class Patch_SnapToGround_SnappAll_Defer
		{
			[HarmonyPrefix]
			internal static bool Prefix()
			{
				if (!ZoneSimConfig.ServerZoneSimFlag.Active || !ZoneSimConfig.IsAuthoritativeProcess())
				{
					return true;
				}
				try
				{
					return !RunDeferredSnap();
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_SnapToGround_SnappAll_Defer", e);
					return true;
				}
			}
		}

		private static readonly FieldInfo s_allSnappersField = AccessTools.Field(typeof(SnapToGround), "m_allSnappers");

		private static bool RunDeferredSnap()
		{
			if (s_allSnappersField == null)
			{
				return false;
			}
			List<SnapToGround> list = (List<SnapToGround>)s_allSnappersField.GetValue(null);
			if (list == null)
			{
				return false;
			}
			if (list.Count == 0)
			{
				return true;
			}
			Heightmap.ForceGenerateAll();
			for (int num = list.Count - 1; num >= 0; num--)
			{
				SnapToGround val = list[num];
				if ((Object)(object)val == (Object)null)
				{
					list.RemoveAt(num);
				}
				else if (IsZoneReady(val))
				{
					val.Snap();
					SetInList(val, value: false);
					list.RemoveAt(num);
					Telemetry_ZoneSim.SnapRetriedCount.Increment();
				}
			}
			Telemetry_ZoneSim.SetSnapDeferredCount(list.Count);
			return true;
		}

		private static bool IsZoneReady(SnapToGround snapper)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZoneSystem.instance == (Object)null || !ZoneSystemAccess.IsReady)
			{
				return false;
			}
			Vector2s zone = ZoneSystem.GetZone(((Component)snapper).transform.position);
			return ZoneSystemAccess.ContainsZone(ZoneSystem.instance, zone);
		}

		private static void SetInList(SnapToGround snapper, bool value)
		{
			AccessTools.FieldRefAccess<SnapToGround, bool>(snapper, "m_inList") = value;
		}

		internal static void RetryDeferred()
		{
			if (!ZoneSimConfig.ServerZoneSimFlag.Active || !ZoneSimConfig.IsAuthoritativeProcess())
			{
				return;
			}
			try
			{
				SnapToGround.SnappAll();
			}
			catch (Exception e)
			{
				NoodlesLog.PatchException("RetryDeferred", e);
			}
		}
	}
	internal static class TerrainReadinessGate
	{
		[HarmonyPatch(typeof(TerrainComp), "TryCleanInvalidTCs")]
		internal static class Patch_TerrainComp_TryCleanInvalidTCs_Canary
		{
			[HarmonyPrefix]
			internal static void Prefix(TerrainComp __instance)
			{
				try
				{
					HashSet<TerrainComp> s_duplicateInstances = TerrainComp.s_duplicateInstances;
					if (s_duplicateInstances.Count > 1 && s_duplicateInstances.Contains(__instance))
					{
						Telemetry_ZoneSim.TerrainCompDuplicatesObserved.Add(s_duplicateInstances.Count - 1);
					}
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_TerrainComp_TryCleanInvalidTCs_Canary", e);
				}
			}
		}

		public static bool IsReady(Vector2s zone)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZoneSystem.instance == (Object)null || !ZoneSystemAccess.IsReady)
			{
				return false;
			}
			return ZoneSystemAccess.ContainsZone(ZoneSystem.instance, zone);
		}
	}
	internal static class UpdateCadence
	{
		[HarmonyPatch(typeof(ZoneSystem), "Update")]
		internal static class Patch_ZoneSystem_Update_Cadence
		{
			[HarmonyTranspiler]
			internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Expected O, but got Unknown
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Expected O, but got Unknown
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0085: Expected O, but got Unknown
				//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d6: Expected O, but got Unknown
				//IL_017b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0181: Expected O, but got Unknown
				//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c3: Expected O, but got Unknown
				//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f8: Expected O, but got Unknown
				CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
				FieldInfo updateTimerField = AccessTools.Field(typeof(ZoneSystem), "m_updateTimer");
				val.Start().MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
				{
					new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction instr) => CodeInstructionExtensions.LoadsField(instr, updateTimerField, false) || CodeInstructionExtensions.StoresField(instr, updateTimerField)), (string)null)
				}).ThrowIfInvalid("NoodlesMcDoodles Z5 anchor 0/3: m_updateTimer field reference not found in ZoneSystem.Update");
				val.Advance(1);
				val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
				{
					new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)0.1f, (string)null)
				}).ThrowIfInvalid("NoodlesMcDoodles Z5 anchor 1/3: cadence-gate 0.1f not found in ZoneSystem.Update");
				val.SetInstructionAndAdvance(CodeInstruction.Call(typeof(ZoneSimConfig), "EffectiveUpdateTickSeconds", (Type[])null, (Type[])null));
				val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
				{
					new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)0.1f, (string)null)
				}).ThrowIfInvalid("NoodlesMcDoodles Z5 anchor 2/3: UpdateTTL(0.1f) argument not found in ZoneSystem.Update");
				val.SetInstructionAndAdvance(CodeInstruction.Call(typeof(ZoneSimConfig), "EffectiveUpdateTickSeconds", (Type[])null, (Type[])null));
				int num = val.InstructionEnumeration().Count((CodeInstruction i) => i.opcode == OpCodes.Ldc_R4 && CodeInstructionExtensions.OperandIs(i, (object)0.1f));
				if (num != 1)
				{
					throw new InvalidOperationException("NoodlesMcDoodles Z5: expected exactly 1 deliberately-untouched 0.1f literal (m_timeSlicedGenerationTimeBudget) remaining in ZoneSystem.Update after replacing the " + $"2 real targets, found {num} — method shape changed, refusing a partial patch.");
				}
				val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
				{
					new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction instr) => CodeInstructionExtensions.Calls(instr, AccessTools.Method(typeof(ZoneSystem), "UpdateTTL", new Type[1] { typeof(float) }, (Type[])null))), (string)null)
				}).ThrowIfInvalid("NoodlesMcDoodles Z5 anchor: UpdateTTL(float) call not found in ZoneSystem.Update");
				val.Advance(1);
				val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ZoneSimConfig), "OnRealZoneTick", (Type[])null, (Type[])null))
				});
				val.MatchStartForward((CodeMatch[])(object)new CodeMatch[1]
				{
					new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction instr) => CodeInstructionExtensions.Calls(instr, AccessTools.Method(typeof(ZNet), "GetPeers", (Type[])null, (Type[])null))), (string)null)
				}).ThrowIfInvalid("NoodlesMcDoodles Z5 anchor 3/3: ZNet.GetPeers() call not found in ZoneSystem.Update");
				val.SetInstructionAndAdvance(CodeInstruction.Call(typeof(UpdateCadence), "RotatedPeersForGhostZones", (Type[])null, (Type[])null));
				return val.InstructionEnumeration();
			}
		}

		[HarmonyPatch(typeof(ZoneSystem), "CreateGhostZones")]
		internal static class Patch_ZoneSystem_CreateGhostZones_RoundRobinCap
		{
			private static int s_ghostSpawnsThisTick;

			[HarmonyPrefix]
			internal static bool Prefix(ref bool __result)
			{
				if (!ZoneSimConfig.ServerZoneSimFlag.Active || !ZoneSimConfig.IsAuthoritativeProcess())
				{
					return true;
				}
				try
				{
					if (s_ghostSpawnsThisTick >= ZoneSimConfig.MaxGhostSpawnsPerTick.Value)
					{
						__result = false;
						return false;
					}
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_ZoneSystem_CreateGhostZones_RoundRobinCap", e);
				}
				return true;
			}

			[HarmonyPostfix]
			internal static void Postfix(bool __result)
			{
				if (!ZoneSimConfig.ServerZoneSimFlag.Active || !ZoneSimConfig.IsAuthoritativeProcess())
				{
					return;
				}
				try
				{
					if (__result)
					{
						s_ghostSpawnsThisTick++;
					}
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_ZoneSystem_CreateGhostZones_RoundRobinCap.Postfix", e);
				}
			}

			internal static void ResetTickCounter()
			{
				Telemetry_ZoneSim.SetGhostSpawnsThisTick(s_ghostSpawnsThisTick);
				s_ghostSpawnsThisTick = 0;
			}
		}

		private static int s_rotationOffset;

		private static readonly List<ZNetPeer> s_rotatedBuffer = new List<ZNetPeer>();

		internal static List<ZNetPeer> RotatedPeersForGhostZones(ZNet znet)
		{
			List<ZNetPeer> peers = znet.GetPeers();
			if (!ZoneSimConfig.ServerZoneSimFlag.Active || !ZoneSimConfig.IsAuthoritativeProcess() || peers.Count <= 1)
			{
				return peers;
			}
			try
			{
				s_rotatedBuffer.Clear();
				int num = s_rotationOffset % peers.Count;
				for (int i = 0; i < peers.Count; i++)
				{
					s_rotatedBuffer.Add(peers[(num + i) % peers.Count]);
				}
				s_rotationOffset = (s_rotationOffset + 1) % peers.Count;
				return s_rotatedBuffer;
			}
			catch (Exception e)
			{
				NoodlesLog.PatchException("RotatedPeersForGhostZones", e);
				return peers;
			}
		}
	}
	internal static class ZoneCap
	{
		private static readonly HashSet<Vector2s> s_includedThisTick = new HashSet<Vector2s>();

		private static int s_globalObjectEstimate;

		public static void BeginTick()
		{
			s_includedThisTick.Clear();
			s_globalObjectEstimate = 0;
			Telemetry_ZoneSim.SetCapCurrentlyOverBudget(over: false);
		}

		public static bool CanInclude(Vector2s zone, int zoneObjectEstimate)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			int value = ZoneSimConfig.MaxObjectsPerPeer.Value;
			int value2 = ZoneSimConfig.MaxObjectsGlobal.Value;
			float value3 = ZoneSimConfig.CapIncludeThresholdPct.Value;
			float num = Math.Max(ZoneSimConfig.CapExcludeThresholdPct.Value, value3);
			bool num2 = s_includedThisTick.Contains(zone);
			long num3 = (long)s_globalObjectEstimate + (long)zoneObjectEstimate;
			bool flag = (float)num3 < (float)value2 * value3;
			bool flag2 = (float)num3 < (float)value2 * num;
			bool flag3 = (num2 ? flag2 : flag);
			if (zoneObjectEstimate > value)
			{
				flag3 = false;
			}
			if (flag3)
			{
				s_includedThisTick.Add(zone);
				s_globalObjectEstimate += zoneObjectEstimate;
			}
			else
			{
				Telemetry_ZoneSim.CapHitCount.Increment();
				Telemetry_ZoneSim.SetCapCurrentlyOverBudget(over: true);
			}
			Telemetry_ZoneSim.SetGlobalObjectEstimate(s_globalObjectEstimate);
			return flag3;
		}

		public static bool WasIncludedThisTick(Vector2s zone)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return s_includedThisTick.Contains(zone);
		}
	}
	internal static class ZoneSimConfig
	{
		public static ConfigEntry<int> PokeRingRadius;

		public static ConfigEntry<int> MaxZoneBuildsPerTick;

		public static ConfigEntry<float> ZoneTTLSeconds;

		public static ConfigEntry<float> UpdateTickSeconds;

		public static ConfigEntry<int> MaxGhostSpawnsPerTick;

		public static ConfigEntry<int> MaxCreatedPerFrame;

		public static ConfigEntry<int> CreateDestroyHz;

		public static ConfigEntry<float> CreateBudgetMs;

		public static ConfigEntry<int> MinCreatedPerTick;

		public static ConfigEntry<float> ZoneBuildBudgetMs;

		public static ConfigEntry<int> ObjectUnfeedGraceTicks;

		public static ConfigEntry<int> MaxObjectsPerPeer;

		public static ConfigEntry<int> MaxObjectsGlobal;

		public static ConfigEntry<float> CapIncludeThresholdPct;

		public static ConfigEntry<float> CapExcludeThresholdPct;

		public static ConfigEntry<int> HeldBandRingBonus;

		internal const float VanillaZoneUpdateTickSeconds = 0.1f;

		internal const float VanillaZoneTTLSeconds = 4f;

		internal const int VanillaMaxCreatedPerFrame = 100;

		internal const float VanillaCreateDestroyIntervalSeconds = 1f / 30f;

		internal const int VanillaGhostSpawnsPerTick = 1;

		public static FeatureFlag ServerZoneSimFlag { get; private set; }

		[NoodlesModuleInit(100)]
		internal static void Init()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Expected O, but got Unknown
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Expected O, but got Unknown
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Expected O, but got Unknown
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Expected O, but got Unknown
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: 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_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Expected O, but got Unknown
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Expected O, but got Unknown
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Expected O, but got Unknown
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Expected O, but got Unknown
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Expected O, but got Unknown
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Expected O, but got Unknown
			ConfigFile file = NoodlesConfig.File;
			ConfigEntry<bool> val = file.Bind<bool>("Features", "ServerZoneSim.Active", true, "Master switch for server zone simulation (docs/design/04): gives the server real terrain and objects around every connected peer, instead of only its one permanently-void-ocean reference position. No vanilla equivalent (vanilla simulates nothing away from that dead point). Does NOT move ownership or change what any peer receives by itself (docs/design/04, 'What this fixes ... and what it does not') — it only gives the Ownership module something real to hold. DEFAULT ON (user decision, ownership redesign, 2026-09-28: 'Fix and do all, default to on, Proxima is our real testing ground') — turned on TOGETHER with OwnershipAuthority.Active (also default on now) and ZoneSim.HeldBandRingBonus=1, the combination this flag alone used to warn was missing (see the cross-flag warning below): on its own, with OwnershipAuthority off, this still only makes the server build every player's surroundings without taking any of them over, which costs server CPU and memory for no gain — that misconfiguration now gets its own loud warning instead of shipping silently. RUNTIME AUTHORITY: every actual patch body this flag gates also requires ZoneSimConfig.IsAuthoritativeProcess() (ZNet.instance.IsServer()), never this flag alone — a listen host IS the server and must get this; a plain remote client, whose own copy of this config is also true now, must not (docs/impl/CORE-API.md 'Runtime authority, not the flag alone').");
			ServerZoneSimFlag = Features.Register("ServerZoneSim", val);
			val.SettingChanged += delegate
			{
				CrossFlagWarnings.CheckServerZoneSimWithoutOwnershipAuthority();
			};
			PokeRingRadius = file.Bind<int>("ZoneSim", "PokeRingRadius", 2, new ConfigDescription("Z2 — how many zones out from each peer's own position the server keeps real (Heightmap+MeshCollider), clamped at read time to the negotiated NearSimulationDistance. Vanilla value: 2 (ZNet's own dead reference position already uses SimulationDistance.OriginalDistance, Near=2 — a 5x5 block) — this default gives every peer the SAME ring size vanilla's one unreachable point already gets, not a multiple of it. Safe max: 5 (matches vanilla's top simulation-distance slider level) — raising it scales zone count, and therefore cost, roughly as (2n+1)^2, so treat values above 2 as deliberate opt-in headroom for a server that has confirmed spare CPU/RAM.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 5), Array.Empty<object>()));
			HeldBandRingBonus = file.Bind<int>("ZoneSim", "HeldBandRingBonus", 1, new ConfigDescription("Widens the SAME ring value Hook 1's terrain build AND Hook 2's object feed AND O6's claim test all read (PokeRingDriver.EffectiveRingRadius = min(PokeRingRadius, negotiated near) + this value) — never a second, independently-tuned radius; that single-ring property is what makes a wider held band safe (no zone can ever be claimed without having been fed). No vanilla equivalent. 0 = today's exact ring/cost/behaviour, byte-for-byte. 1 (default, user decision 2026-09-28) reaches the real held band (~160-224m at default PokeRingRadius=2/PeerRefPosPadding=64) that O6 could never actually hold before this key existed — only matters once OwnershipAuthority.Active is also on (also default on now). 2 is opt-in headroom (~288m) for a server with confirmed spare CPU/RAM. Pair a nonzero value with MaxObjectsPerPeer/MaxObjectsGlobal (see those keys) — ZoneCap's own hysteresis fails safe but silently under-delivers the benefit if the budget wasn't sized for the wider ring.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2), Array.Empty<object>()));
			MaxZoneBuildsPerTick = file.Bind<int>("ZoneSim", "MaxZoneBuildsPerTick", 1, new ConfigDescription("New cap (Hook 1's own per-tick cost bound, RED-TEAM FIX) on real zone CONSTRUCTIONS (Instantiate+Heightmap+MeshCollider) per UpdateTickSeconds tick, across every peer combined. No vanilla equivalent (vanilla never builds more than its one static zone, once). DEFAULT LOWERED 4 -> 1 (1.0.9 frame-stall fix, knee-of-curve): measured evidence (SP/harness108) attributed 15.6-21.8% of slow-frame time to Heightmap.CustomLateUpdate's deferred terrain rebuild for newly built zones, consistent with several builds from one tick stacking their deferred rebuild into the same LateUpdate; 1 per tick at UpdateTickSeconds=0.05s (20Hz) still activates a held zone well ahead of a player walking at run speed (~7 m/s) -- see ZoneBuildBudgetMs's own description for the measured activation-lead-time margin. Safe max: 16 — raise only if telemetry (zonesim.zoneBuildsThisTick / zonesim.zoneBuildsDeferredThisTick pinned at the cap with peers still waiting on terrain) shows real, sustained demand, and raise ZoneBuildBudgetMs alongside it.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 16), Array.Empty<object>()));
			ZoneBuildBudgetMs = file.Bind<float>("ZoneSim", "ZoneBuildBudgetMs", 6f, new ConfigDescription("1.0.9 (frame-stall fix) — Hook 1's own per-tick WALL-CLOCK budget on a SECOND-OR-LATER NEW zone construction competing for the same tick (PokeRingDriver's own PokeLocalZone(Full) calls; never the free TTL-refresh poke of an already-loaded zone, which stays O(1) and uncapped), on top of MaxZoneBuildsPerTick's existing count cap. No vanilla equivalent. ROUND 2 finding (SP/harness108, first 1.0.9 run): this alone barely moved MonoUpdaters.LateUpdate's slow-frame share (1053ms/336ms slow vs 1.0.7's 958ms/315ms) because zonesim.zoneBuildsDeferredTotal showed a build wanted almost every tick already -- MaxZoneBuildsPerTick=1 was already isolating builds to one/tick in practice, so this budget was rarely the thing doing the limiting; the remaining cost is ONE Ashlands zone's own Heightmap+MeshCollider build, ~16-26ms, which no cap on ADDITIONAL builds can shrink. PokeRingDriver.cs's own RunTick remarks cover the companion fix (a recent-frame-health check, reusing Core/FrameTiming.RecentMeanMs, that ALSO defers a second-or-later build once recent frames are already running hot -- ROUND 3 safety fix: round 2's first cut applied that check to the tick's FIRST build too and produced a real ARMED_WAIT FAIL (zero held zones for 300s) on a busy mod stack whose own background hitches alone could keep recent frames looking hot indefinitely; a lone newly-entered zone now always gets its one build attempt this tick regardless, exactly as before round 2 -- this key's own 6ms value still governs the second-or-later-build case unchanged). Safe max 20ms — raise only alongside MaxZoneBuildsPerTick.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 20f), Array.Empty<object>()));
			ZoneTTLSeconds = file.Bind<float>("ZoneSim", "ZoneTTLSeconds", 15f, new ConfigDescription("Z4 — how long an empty, unpoked zone's terrain root survives before being torn down. Vanilla value: 4s. This default is the user's own explicit numeric target (DESIGN.md Lead decisions/Configuration reference), kept as-is: it buys slack for Hook 1's ring driver to miss a tick without a full terrain re-bake, and only ever protects EMPTY zones (vanilla's own HaveInstanceInSector gate — a zone with any live instance is never touched regardless of TTL). ~3.75x vanilla, not an unbounded increase. Hard-clamped 4-20s.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 20f), Array.Empty<object>()));
			UpdateTickSeconds = file.Bind<float>("ZoneSim", "UpdateTickSeconds", 0.05f, new ConfigDescription("Z5 — ZoneSystem's own update cadence (terrain/ghost-zone tick), and Hook 1's poke-ring driver's cadence. Vanilla value: 0.1s. This default is the user's own explicit numeric target, kept as-is: a moderate 2x vanilla's rate, made safe specifically by the mandatory MaxGhostSpawnsPerTick cap and the UpdateTTL dt-accuracy fix this doc ships alongside it (without both, 0.05s alone would be a foot-gun — see docs/design/04 Hook 3). Range keeps it at or faster than vanilla only; there is no headroom above vanilla's own 0.1s offered here.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 0.1f), Array.Empty<object>()));
			MaxGhostSpawnsPerTick = file.Bind<int>("ZoneSim", "MaxGhostSpawnsPerTick", 1, new ConfigDescription("Hook 3's mandatory companion cap on first-time zone GENERATION (SpawnZone Ghost, full PlaceLocations/PlaceVegetation cost) per tick, across every peer, serviced round-robin so no single peer is starved. Vanilla value: 1 (implicitly — vanilla only ever has one reference position generating at a time). Default matches vanilla's own existing discipline exactly, not a multiple. Safe max: 4 — trades a bigger worst-case per-tick hitch for faster cold-world population; raise only for a fresh-world/large-group-expedition server.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 4), Array.Empty<object>()));
			MaxCreatedPerFrame = file.Bind<int>("ZoneSim", "MaxCreatedPerFrame", 100, new ConfigDescription("Z6 — GameObject instantiation budget per ZNetScene create/destroy tick. Vanilla value: 100 — a dedicated server ALREADY always takes this branch (Player.m_localPlayer is permanently null server-side, so InLoadingScreen() is permanently true; the '10' literal a client can hit is a dead branch on a real dedicated server). This default therefore changes NOTHING versus an unmodded server; it exists so an admin can opt into more if telemetry shows the budget is the bottleneck. Safe max: 400 (4x) — CreateObjectsSorted already self-scales past ~100x the configured value for a large backlog, so values much above 400 buy little extra.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(100, 400), Array.Empty<object>()));
			CreateDestroyHz = file.Bind<int>("ZoneSim", "CreateDestroyHz", 30, new ConfigDescription("Hook 6's companion cadence knob for the create/destroy pass itself (ZNetScene.Update's own 1/30s gate). Vanilla value: 30 (Hz). Default matches vanilla exactly — 60 is a straightforward 2x CPU cost for that one pass and is left as explicit opt-in only, not the default, since it was not one of the user's selected numeric targets.", (AcceptableValueBase)(object)new AcceptableValueList<int>(new int[2] { 30, 60 }), Array.Empty<object>()));
			CreateBudgetMs = file.Bind<float>("ZoneSim", "CreateBudgetMs", 8f, new ConfigDescription("1.0.9 (frame-stall fix) — Z6's own per-tick WALL-CLOCK budget on ZNetScene's create loop (CreateObjectsSorted + CreateDistantObjects combined), on top of MaxCreatedPerFrame's existing COUNT cap — whichever is reached first stops this tick's object creation (never below MinCreatedPerTick, see that key; also short-circuited to an immediate cut once Core.FrameTiming.RecentMeanMs is already running hot — see CreateObjectsBudget.cs's own EffectiveCreateCap remarks). No vanilla equivalent (vanilla's cap is count-only, sized for a dedicated server's one permanently-void reference position, which never presents the multi-thousand-object backlog a freshly-ring-entered ZoneSim zone can). ROUND 2 default 7ms -> 3ms (measured on the first harness108 1.0.9 run): 7ms barely moved Phase B's CreateObject call count because several remaining slow frames showed 1.4-7.4ms/object average — cost concentrated in occasional expensive INDIVIDUAL objects, not a steady rate a small window could reliably cap at a handful of objects. ROUND 4 default 3ms -> 8ms: round 3 cut walking stalls ~80% but left the create backlog draining at only ~60/s (~10,900 objects measured, several minutes to drain) — the server's own measured baseline (this mod's ZoneSim work aside) is ~30fps / ~5ms mean frame, so a 3ms create budget was tighter than the frame's own steady-state margin and too timid against the round-4 priority (drain the backlog several times faster while keeping walking stalls close to round 3's result) — see round 4's own harness108 A/B/C/D measurements for the knee actually picked from this range. HARD RULE (never violated by this budget): ZNetScene.CreateObject is always called for every item the loop reaches — this only makes the loop's own existing break condition trip earlier, exactly where vanilla's own count cap already knows how to stop, so 'Destroyed invalid prefab ZDO' can never fire because of this budget. Raise further toward 16ms only if zonesim.createBudgetLimitedTicksTotal stays pinned with zonesim.createBacklog not draining.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 16f), Array.Empty<object>()));
			MinCreatedPerTick = file.Bind<int>("ZoneSim", "MinCreatedPerTick", 2, new ConfigDescription("1.0.9 (frame-stall fix) — the floor CreateBudgetMs (and the recent-frame-health gate) can never cut below: this many objects (near+distant combined) always get created in a tick's create loop even if the budget is already spent (or recent frames are already hot) when the tick starts, so a held zone's backlog always makes forward progress every tick — never a permanent stall. No vanilla equivalent. ROUND 2 default 4 -> 2 (same harness108 1.0.9 run noted on CreateBudgetMs): an UNCONDITIONAL floor is, by construction, exposed to whatever the single most expensive object among its N slots costs (a per-iteration budget check can only stop MORE objects from being attempted, never shrink one already in flight) — halving the floor halves how many chances per tick an occasional expensive individual object has to land in the unconditionally-allowed slots, while 2 still guarantees real progress every tick (never a permanent stall) exactly as 4 did. Safe max 20 — raise only alongside CreateBudgetMs.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>()));
			ObjectUnfeedGraceTicks = file.Bind<int>("ZoneSim", "ObjectUnfeedGraceTicks", 3, new ConfigDescription("Hook 2's grace-hold: extra ticks a fed, non-Persistent, server-owned ZDO stays earmarked after its zone drops from the feed, before RemoveObjects's ordinary sweep may reach it. No vanilla equivalent (new mod-owned bookkeeping). Default (~150ms at the 0.05s tick default) absorbs ordinary ring-boundary churn without materially delaying real cleanup. 0 restores immediate-sweep (pre-fix) behaviour; safe max 20 (~1s) — raise only if zonesim.objectsDestroyedOnUnfeed shows real churn in play.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
			MaxObjectsPerPeer = file.Bind<int>("ZoneSim", "MaxObjectsPerPeer", 4000, new ConfigDescription("Z9 — per-peer object-count budget (Hook 5's ZoneCap), enforced with 90%/100% hysteresis, 'stop appending, never destroy' on hit. No direct vanilla equivalent (the server simulates 0 real objects per peer today); the nearest comparison is what a vanilla CLIENT already instantiates for itself — research/04's cost model: ~2,500 for a full default-radius (5x5, ring=2) ring in ordinary terrain; this project's own live probe (baseline/2026-09-28-probe-solo/FINDINGS.md) measured ~1,500 mean / 2,184 max objects around one real player on Proxima Maxi, also at ring=2. RESIZED (2026-09-28, held-band redesign) for ZoneSim.HeldBandRingBonus's new default of 1: the real zone count in the ring scales 21 -> 37 (+76%, redesign/redesign-result.json), so that same measured baseline scales to ~2,640 mean / ~3,850 max — default 4,000 sits just above the SCALED max, the same margin the original 2,500 default kept above its own (ring=2) baseline max of 2,184, so an isolated/far peer's own held band is fully covered without hitting the cap. A player parked at a large base (probe/design notes observed up to ~7,800 near a dense base) will hit the cap for the excess only — fails safe (that excess simply isn't server-simulated), never destructive. Raise toward the safe max of 10,000 (kept below research/04's own 'clearly too large' line of 10,000-20,000 for a single dense area) only after confirming spare RAM on the host via zonesim.globalObjectEstimateThisTick.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(500, 10000), Array.Empty<object>()));
			MaxObjectsGlobal = file.Bind<int>("ZoneSim", "MaxObjectsGlobal", 24000, new ConfigDescription("Z9 — server-wide object-count budget across every peer combined, same hysteresis/fail-safe behaviour as MaxObjectsPerPeer. No vanilla equivalent. Default = MaxObjectsPerPeer x 6 (24,000, following MaxObjectsPerPeer's own 2026-09-28 resize for HeldBandRingBonus=1): 6 is a deliberately modest 'typically online together' planning figure for the target 2-10 player ordinary server (not the theoretical 10-player join ceiling), so most sessions never approach this cap even before any single peer hits their own per-peer cap. Safe max 60,000 (10,000 hard-clamped per-peer x 6) — raise together with MaxObjectsPerPeer, and only after live RSS/CPU headroom is confirmed on the host (archserver: 31GB RAM / 12 cores shared with 2 other Valheim servers; baseline vanilla Proxima usage: 3.6GB RSS / 13% of one core at ~1.13M ZDOs with one player, per baseline/2026-09-28-lan/BASELINE.md).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2000, 100000), Array.Empty<object>()));
			CapIncludeThresholdPct = file.Bind<float>("ZoneSim", "CapIncludeThresholdPct", 0.9f, new ConfigDescription("Z9 hysteresis: a zone not already included this tick's pass only joins the feed below this fraction of the global budget. No vanilla equivalent. Fixed at 0.90 per docs/design/04.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 0.99f), Array.Empty<object>()));
			CapExcludeThresholdPct = file.Bind<float>("ZoneSim", "CapExcludeThresholdPct", 1f, new ConfigDescription("Z9 hysteresis: a zone already included this tick's pass stays included up to this fraction of the global budget (must be >= CapIncludeThresholdPct; clamped up to it if configured lower). No vanilla equivalent. Fixed at 1.00 per docs/design/04.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 1f), Array.Empty<object>()));
			RegisterPatches();
			CreateObjectsBudget.LogActiveBranchOnce();
			HeldBandPreservationGuard.Init();
			PokeRingDriver.EnsureStarted();
			ZoneSimGate.CanHoldProvider = CanHoldZone;
			HeldBandGate.RingBonusProvider = () => Mathf.Clamp(HeldBandRingBonus.Value, 0, 2);
			CrossFlagWarnings.CheckServerZoneSimWithoutOwnershipAuthority();
			NoodlesLog.Info($"ZoneSim: configured PokeRingRadius={PokeRingRadius.Value} " + $"HeldBandRingBonus={HeldBandRingBonus.Value} MaxObjectsPerPeer={MaxObjectsPerPeer.Value} " + $"MaxObjectsGlobal={MaxObjectsGlobal.Value} UpdateTickSeconds={UpdateTickSeconds.Value} " + $"ZoneTTLSeconds={ZoneTTLSeconds.Value} MaxZoneBuildsPerTick={MaxZoneBuildsPerTick.Value} " + $"ZoneBuildBudgetMs={ZoneBuildBudgetMs.Value} MaxCreatedPerFrame={MaxCreatedPerFrame.Value} " + $"CreateBudgetMs={CreateBudgetMs.Value} MinCreatedPerTick={MinCreatedPerTick.Value}.");
		}

		private static void RegisterPatches()
		{
			PatchRegistry.Register("ServerZoneSim", typeof(Patch_ZNetScene_CreateObject_Containment));
			PatchRegistry.Register("ServerZoneSim", typeof(Patch_ZNetScene_CreateObjects_ObjectFeed));
			PatchRegistry.Register("ServerZoneSim", typeof(UpdateCadence.Patch_ZoneSystem_Update_Cadence));
			PatchRegistry.Register("ServerZoneSim", typeof(UpdateCadence.Patch_ZoneSystem_CreateGhostZones_RoundRobinCap));
			PatchRegistry.Register("ServerZoneSim", typeof(ZoneTtl.Patch_ZNet_Awake_ApplyZoneTtl));
			PatchRegistry.Register("ServerZoneSim", typeof(ZoneTtl.Patch_ZoneSystem_UpdateTTL_BacklogDrain));
			PatchRegistry.Register("ServerZoneSim", typeof(CreateObjectsBudget.Patch_ZNetScene_CreateObjects_FrameBudget));
			PatchRegistry.Register("ServerZoneSim", typeof(CreateObjectsBudget.Patch_ZNetScene_Update_CreateDestroyCadence));
			PatchRegistry.Register("ServerZoneSim", typeof(CreateObjectsBudget.Patch_ZNetScene_CreateObjects_TimeBudgetTick));
			PatchRegistry.Register("ServerZoneSim", typeof(CreateObjectsBudget.Patch_ZNetScene_CreateObjectsSorted_TimeBudget));
			PatchRegistry.Register("ServerZoneSim", typeof(CreateObjectsBudget.Patch_ZNetScene_CreateDistantObjects_TimeBudget));
			PatchRegistry.Register("ServerZoneSim", typeof(CreateNearFirstOrder.Patch_ZNetScene_CreateObjectsSorted_NearFirst));
			PatchRegistry.Register("ServerZoneSim", typeof(SnapGuard.Patch_SnapToGround_SnappAll_Defer));
			PatchRegistry.Register("ServerZoneSim", typeof(TerrainReadinessGate.Patch_TerrainComp_TryCleanInvalidTCs_Canary));
		}

		internal static bool IsAuthoritativeProcess()
		{
			if ((Object)(object)ZNet.instance != (Object)null)
			{
				return ZNet.instance.IsServer();
			}
			return false;
		}

		internal static float EffectiveUpdateTickSeconds()
		{
			if (!ServerZoneSimFlag.Active || !IsAuthoritativeProcess())
			{
				return 0.1f;
			}
			return Mathf.Clamp(UpdateTickSeconds.Value, 0.05f, 0.1f);
		}

		internal static void OnRealZoneTick()
		{
			if (!ServerZoneSimFlag.Active || !IsAuthoritativeProcess())
			{
				return;
			}
			try
			{
				UpdateCadence.Patch_ZoneSystem_CreateGhostZones_RoundRobinCap.ResetTickCounter();
			}
			catch (Exception e)
			{
				NoodlesLog.PatchException("OnRealZoneTick.GhostSpawnReset", e);
			}
			try
			{
				SnapGuard.RetryDeferred();
			}
			catch (Exception e2)
			{
				NoodlesLog.PatchException("OnRealZoneTick.SnapRetry", e2);
			}
		}

		internal static int EffectiveMaxCreatedPerFrame()
		{
			if (!ServerZoneSimFlag.Active || !IsAuthoritativeProcess())
			{
				return 100;
			}
			return Mathf.Clamp(MaxCreatedPerFrame.Value, 100, 400);
		}

		internal static float EffectiveCreateDestroyIntervalSeconds()
		{
			if (!ServerZoneSimFlag.Active || !IsAuthoritativeProcess())
			{
				return 1f / 30f;
			}
			int num = ((CreateDestroyHz.Value == 60) ? 60 : 30);
			return 1f / (float)num;
		}

		private static bool CanHoldZone(Vector2s zone)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (!ServerZoneSimFlag.Active || !IsAuthoritativeProcess())
			{
				return false;
			}
			return ZoneCap.WasIncludedThisTick(zone);
		}
	}
	internal static class Telemetry_ZoneSim
	{
		public static Counter ZonesPokedTotal => Telemetry.GetCounter("zonesim.zonesPokedTotal");

		public static Counter ObjectsAppendedTotal => Telemetry.GetCounter("zonesim.objectsAppendedTotal");

		public static Counter ObjectsSkippedMissingPrefab => Telemetry.GetCounter("zonesim.objectsSkippedMissingPrefab");

		public static Counter ObjectsDestroyedOnUnfeed => Telemetry.GetCounter("zonesim.objectsDestroyedOnUnfeed");

		public static Counter InstantiateExceptionsCaught => Telemetry.GetCounter("zonesim.instantiateExceptionsCaught");

		public static Counter CapHitCount => Telemetry.GetCounter("zonesim.capHitCount");

		public static Counter SnapRetriedCount => Telemetry.GetCounter("zonesim.snapRetriedCount");

		public static Counter TerrainCompDuplicatesObserved => Telemetry.GetCounter("zonesim.terrainCompDuplicatesObserved");

		public static Counter CreateBudgetLimitedTicksTotal => Telemetry.GetCounter("zonesim.createBudgetLimitedTicksTotal");

		public static Counter ZoneBuildsDeferredTotal => Telemetry.GetCounter("zonesim.zoneBuildsDeferredTotal");

		public static void SetZonesRealActive(int count)
		{
			Telemetry.SetGauge("zonesim.zonesRealActive", count);
		}

		public static void SetZoneBuildsThisTick(int count)
		{
			Telemetry.SetGauge("zonesim.zoneBuildsThisTick", count);
		}

		public static void SetHeldBandRingBonus(int bonus)
		{
			Telemetry.SetGauge("zonesim.heldBandRingBonus", bonus);
		}

		public static void SetPrefabsPoisoned(int count)
		{
			Telemetry.SetGauge("zonesim.prefabsPoisoned", count);
		}

		public static void SetZonesQuarantined(int count)
		{
			Telemetry.SetGauge("zonesim.zonesQuarantined", count);
		}

		public static void SetGhostSpawnsThisTick(int count)
		{
			Telemetry.SetGauge("zonesim.ghostSpawnsThisTick", count);
		}

		public static void SetZonesTtlDestroyedThisTick(int count)
		{
			Telemetry.SetGauge("zonesim.zonesTtlDestroyedThisTick", count);
		}

		public static void SetCapCurrentlyOverBudget(bool over)
		{
			Telemetry.SetGauge("zonesim.capCurrentlyOverBudget", over ? 1 : 0);
		}

		public static void SetGlobalObjectEstimate(int count)
		{
			Telemetry.SetGauge("zonesim.globalObjectEstimateThisTick", count);
		}

		public static void SetSnapDeferredCount(int count)
		{
			Telemetry.SetGauge("zonesim.snapDeferredCount", count);
		}

		public static void SetCreateBacklog(int count)
		{
			Telemetry.SetGauge("zonesim.createBacklog", count);
		}

		public static void SetCreatedThisTick(int count)
		{
			Telemetry.SetGauge("zonesim.createdThisTick", count);
		}

		public static void SetZoneBuildsDeferredThisTick(int count)
		{
			Telemetry.SetGauge("zonesim.zoneBuildsDeferredThisTick", count);
		}

		public static void SetLastZoneBuildMs(double ms)
		{
			Telemetry.SetGauge("zonesim.lastZoneBuildMs", ms);
		}

		public static void SetPokeRingTickMs(double ms)
		{
			Telemetry.SetGauge("zonesim.pokeRingTickMs", ms);
		}

		public static void SetObjectFeedMs(double ms)
		{
			Telemetry.SetGauge("zonesim.objectFeedMs", ms);
		}
	}
	internal static class ZoneSystemAccess
	{
		private static readonly FieldInfo s_zonesField = AccessTools.Field(typeof(ZoneSystem), "m_zones");

		private static readonly Type s_zoneDataType = AccessTools.Inner(typeof(ZoneSystem), "ZoneData");

		private static readonly FieldInfo s_zoneDataRoot = ((s_zoneDataType != null) ? AccessTools.Field(s_zoneDataType, "m_root") : null);

		private static readonly FieldInfo s_zoneDataTtl = ((s_zoneDataType != null) ? AccessTools.Field(s_zoneDataType, "m_ttl") : null);

		private static readonly MethodInfo s_pokeLocalZone = AccessTools.Method(typeof(ZoneSystem), "PokeLocalZone", (Type[])null, (Type[])null);

		private static readonly MethodInfo s_isZoneGenerated = AccessTools.Method(typeof(ZoneSystem), "IsZoneGenerated", new Type[1] { typeof(Vector2s) }, (Type[])null);

		public static bool IsReady
		{
			get
			{
				if (s_zonesField != null && s_zoneDataType != null && s_zoneDataRoot != null && s_zoneDataTtl != null && s_pokeLocalZone != null)
				{
					return s_isZoneGenerated != null;
				}
				return false;
			}
		}

		private static IDictionary Zones(ZoneSystem instance)
		{
			return (IDictionary)s_zonesField.GetValue(instance);
		}

		public static bool ContainsZone(ZoneSystem instance, Vector2s zone)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Zones(instance).Contains(zone);
		}

		public static int ZoneCount(ZoneSystem instance)
		{
			return Zones(instance).Count;
		}

		public static List<(Vector2s zone, object data)> SnapshotZoneEntries(ZoneSystem instance)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			List<(Vector2s, object)> list = new List<(Vector2s, object)>();
			foreach (DictionaryEntry item in Zones(instance))
			{
				list.Add(((Vector2s)item.Key, item.Value));
			}
			return list;
		}

		public static void RemoveZone(ZoneSystem instance, Vector2s zone)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Zones(instance).Remove(zone);
		}

		public static GameObject ZoneRoot(object zoneData)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			return (GameObject)s_zoneDataRoot.GetValue(zoneData);
		}

		public static float ZoneTtl(object zoneData)
		{
			return (float)s_zoneDataTtl.GetValue(zoneData);
		}

		public static void AddZoneTtl(object zoneData, float dt)
		{
			s_zoneDataTtl.SetValue(zoneData, ZoneTtl(zoneData) + dt);
		}

		public static bool PokeLocalZone(ZoneSystem instance, Vector2s zone)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			return (bool)s_pokeLocalZone.Invoke(instance, new object[1] { zone });
		}

		public static bool IsZoneGenerated(ZoneSystem instance, Vector2s zone)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			return (bool)s_isZoneGenerated.Invoke(instance, new object[1] { zone });
		}
	}
	internal static class ZoneTtl
	{
		[HarmonyPatch(typeof(ZNet), "Awake")]
		internal static class Patch_ZNet_Awake_ApplyZoneTtl
		{
			[HarmonyPostfix]
			internal static void Postfix()
			{
				try
				{
					ApplyZoneTtl();
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_ZNet_Awake_ApplyZoneTtl", e);
				}
			}
		}

		[HarmonyPatch(typeof(ZoneSystem), "UpdateTTL")]
		internal static class Patch_ZoneSystem_UpdateTTL_BacklogDrain
		{
			private static readonly List<(Vector2s zone, object data)> s_expiredBuffer = new List<(Vector2s, object)>();

			[HarmonyPrefix]
			internal static bool Prefix(ZoneSystem __instance, float dt)
			{
				if (!ZoneSimConfig.ServerZoneSimFlag.Active || !ZoneSimConfig.IsAuthoritativeProcess())
				{
					return true;
				}
				if (!ZoneSystemAccess.IsReady)
				{
					return true;
				}
				try
				{
					RunBacklogDrain(__instance, dt);
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_ZoneSystem_UpdateTTL_BacklogDrain", e);
					return true;
				}
				return false;
			}

			private static void RunBacklogDrain(ZoneSystem instance, float dt)
			{
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0079: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
				List<(Vector2s, object)> list = ZoneSystemAccess.SnapshotZoneEntries(instance);
				foreach (var item in list)
				{
					ZoneSystemAccess.AddZoneTtl(item.Item2, dt);
				}
				s_expiredBuffer.Clear();
				float zoneTTL = instance.m_zoneTTL;
				foreach (var (val, obj) in list)
				{
					if (ZoneSystemAccess.ZoneTtl(obj) > zoneTTL && !ZNetScene.instance.HaveInstanceInSector(val))
					{
						s_expiredBuffer.Add((val, obj));
					}
				}
				foreach (var item2 in s_expiredBuffer)
				{
					var (zone, _) = item2;
					Object.Destroy((Object)(object)ZoneSystemAccess.ZoneRoot(item2.data));
					ZoneSystemAccess.RemoveZone(instance, zone);
				}
				Telemetry_ZoneSim.SetZonesTtlDestroyedThisTick(s_expiredBuffer.Count);
			}
		}

		internal static void ApplyZoneTtl()
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !((Object)(object)ZoneSystem.instance == (Object)null))
			{
				ZoneSystem.instance.m_zoneTTL = (ZoneSimConfig.ServerZoneSimFlag.Active ? Mathf.Clamp(ZoneSimConfig.ZoneTTLSeconds.Value, 4f, 20f) : 4f);
			}
		}
	}
}
namespace NoodlesMcDoodles.Transport
{
	internal static class AdaptiveRate
	{
		[HarmonyPatch(typeof(ZNet), "Update")]
		internal static class Patch_ZNet_Update_AdaptiveRateTick
		{
			private static void Postfix(ZNet __instance)
			{
				try
				{
					float realtimeSinceStartup = Time.realtimeSinceStartup;
					if (!(realtimeSinceStartup - s_lastTick < 1f))
					{
						s_lastTick = realtimeSinceStartup;
						Tick(__instance, realtimeSinceStartup);
					}
				}
				catch (Exception e)
				{
					NoodlesLog.PatchException("Patch_ZNet_Update_AdaptiveRateTick", e);
				}
			}
		}

		public static ConfigEntry<int> FloorBps;

		public static ConfigEntry<int> ServerTotalBps;

		public static ConfigEntry<int> PingInflationMs;

		public static ConfigEntry<float> LossThreshold;

		public static FeatureFlag T9;

		private const float TickSeconds = 1f;

		private static readonly ConditionalWeakTable<ZNetPeer, RateState> s_state = new ConditionalWeakTable<ZNetPeer, RateState>();

		private static readonly FieldRef<ZSteamSocket, HSteamNetConnection> s_con = AccessTools.FieldRefAccess<ZSteamSocket, HSteamNetConnection>("m_con");

		private static bool s_anyManaged;

		private static float s_lastTick;

		[NoodlesModuleInit(100)]
		internal static void Init()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			ConfigFile file = NoodlesConfig.File;
			FloorBps = file.Bind<int>("Transport", "T9_FloorBps", 153600, new ConfigDescription("T9: the rate every connection starts at and never drops below. Vanilla's fixed rate is 153600, so the default means no player ever gets less than vanilla gives them.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(153600, 1048576), Array.Empty<object>()));
			ServerTotalBps = file.Bind<int>("Transport", "T9_ServerTotalBps", 10485760, new ConfigDescription("T9: raises stop while the server is already sending this much to all players together (bytes/s, measured). Default 10 MiB/s (about 84 Mbit/s) = ~40 players at T1's default 256 KiB/s, so it is a safety net; each connection's own loss and ping checks are what protect a home uplink. Raise it for a big server on a fast line. Server only.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1048576, 104857600), Array.Empty<object>()));
			PingInflationMs = file.Bind<int>("Transport", "T9_PingInflationMs", 30, new ConfigDescription("T9: how far a player's ping may rise above their recent minimum (ms) before the rate backs off. The margin used is the larger of this and half the minimum ping.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 200), Array.Empty<object>()));
			LossThreshold = file.Bind<float>("Transport", "T9_LossThreshold", 0.98f, new ConfigDescription("T9: Steam's delivery ratio to the player below which the rate backs off (1.0 = every packet arrives). Below 0.95 it backs off immediately.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.9f, 0.999f), Array.Empty<object>()));
			ConfigEntry<bool> val = file.Bind<bool>("Features", "Transport.T9.Active", true, "T9: adaptive per-connection send rate. On: each connection starts at T9_FloorBps and rises toward T1 (T2 while joining) only while Steam reports clean delivery and a steady ping. Off: every connection gets T1's fixed rate, as before.");
			T9 = Features.Register("Transport.T9", val);
			PatchRegistry.Register("Transport.T9", typeof(Patch_ZNet_Update_AdaptiveRateTick));
			KillSwitch.RegisterFlushCallback("Transport.T9", ReleaseAll);
			val.SettingChanged += delegate
			{
				MainThreadDispatcher.Enqueue(delegate
				{
					if (!T9.Active)
					{
						ReleaseAll();
					}
					SteamRateController.Resync();
				});
			};
			T9.OnForcedOff = ReleaseAll;
		}

		private static bool EligibleHere(ZNet znet)
		{
			if (!znet.IsServer())
			{
				return TransportLeverConfig.Q10Active;
			}
			return true;
		}

		private static int Ceiling()
		{
			if (!TransportLeverConfig.T1.Active)
			{
				return 153600;
			}
			return TransportLeverConfig.T1_GlobalRateBps.Value;
		}

		private static int JoinCeiling(int ceiling)
		{
			if (!TransportLeverConfig.T2.Active)
			{
				return ceiling;
			}
			return Math.Max(ceiling, Math.Min(TransportLeverConfig.T2_JoinBurstBps.Value, ceiling * 8));
		}

		private static void Tick(ZNet znet, float now)
		{
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Invalid comparison between Unknown and I4
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_0584: Unknown result type (might be due to invalid IL or missing references)
			int value = FloorBps.Value;
			int num = Ceiling();
			if (T9 == null || !T9.Active || !EligibleHere(znet) || num <= value)
			{
				if (s_anyManaged)
				{
					ReleaseAll();
				}
				return;
			}
			bool dedicated = znet.IsDedicated();
			bool flag = znet.IsServer();
			int num2 = JoinCeiling(num);
			float num3 = TransportLeverConfig.T2_MaxBurstSeconds.Value;
			long num4 = 0L;
			long num5 = 0L;
			foreach (ZNetPeer connectedPeer in znet.GetConnectedPeers())
			{
				if (connectedPeer != null && s_state.TryGetValue(connectedPeer, out var value2))
				{
					if (value2.RateBps > 0)
					{
						num4 += value2.RateBps;
					}
					num5 += (long)value2.LastOutBps;
				}
			}
			int num6 = 0;
			foreach (ZNetPeer connectedPeer2 in znet.GetConnectedPeers())
			{
				if (connectedPeer2 == null || !connectedPeer2.IsReady())
				{
					continue;
				}
				if (!SteamSockets.TryGet(connectedPeer2.m_socket, out var steam, out var layers))
				{
					NoodlesLog.DetailRateLimited($"t9_nosteam_{connectedPeer2.m_uid}", "T9: " + PeerLabel(connectedPeer2) + " is on a " + (((object)connectedPeer2.m_socket)?.GetType().Name ?? "missing") + " socket, not Steam: left at vanilla rates.", 1, 300f);
					continue;
				}
				if (layers > 0)
				{
					NoodlesLog.DetailRateLimited($"t9_wrapped_{connectedPeer2.m_uid}", "T9: " + PeerLabel(connectedPeer2) + "'s socket is wrapped " + $"by {layers} ServerSync layer(s); managing the Steam connecti