Decompiled source of TerramizerServer v1.0.6

plugins/TerramizerServer/TerramizerServer.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Unity.Jobs.LowLevel.Unsafe;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("TerramizerServer")]
[assembly: AssemblyFileVersion("1.0.6")]
[assembly: AssemblyCompany("R4V9N1")]
[assembly: AssemblyDescription("Created by R4V9N1")]
[assembly: AssemblyProduct("TerramizerServer")]
[assembly: AssemblyCopyright("Created by R4V9N1")]
[assembly: AssemblyMetadata("Creator", "Created by R4V9N1")]
[assembly: AssemblyVersion("1.0.6.0")]
namespace TerramizerServer;

internal static class BinarySearchDictionarySetValuePatch
{
	private static class Fields<TValue>
	{
		internal static readonly FieldRef<BinarySearchDictionary<int, TValue>, int[]> Keys = AccessTools.FieldRefAccess<BinarySearchDictionary<int, TValue>, int[]>("m_keys");

		internal static readonly FieldRef<BinarySearchDictionary<int, TValue>, TValue[]> Values = AccessTools.FieldRefAccess<BinarySearchDictionary<int, TValue>, TValue[]>("m_values");

		internal static readonly FieldRef<BinarySearchDictionary<int, TValue>, ushort> Length = AccessTools.FieldRefAccess<BinarySearchDictionary<int, TValue>, ushort>("m_length");
	}

	private static readonly MethodInfo PrefixMethod = AccessTools.Method(typeof(BinarySearchDictionarySetValuePatch), "SetValuePrefix", (Type[])null, (Type[])null);

	internal static void Install(Harmony harmony, Action<string> log)
	{
		try
		{
			PatchSetValue<float>(harmony);
			PatchSetValue<Vector3>(harmony);
			PatchSetValue<Quaternion>(harmony);
			PatchSetValue<int>(harmony);
			PatchSetValue<long>(harmony);
			PatchSetValue<string>(harmony);
			PatchSetValue<byte[]>(harmony);
			log?.Invoke("Installed allocation-free BinarySearchDictionary.SetValue patches.");
		}
		catch (Exception ex)
		{
			log?.Invoke("Could not install BinarySearchDictionary.SetValue patches; vanilla behavior remains active: " + ex.Message);
		}
	}

	private static void PatchSetValue<TValue>(Harmony harmony)
	{
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Expected O, but got Unknown
		Type typeFromHandle = typeof(BinarySearchDictionary<int, TValue>);
		MethodInfo methodInfo = AccessTools.Method(typeFromHandle, "SetValue", new Type[2]
		{
			typeof(int),
			typeof(TValue)
		}, (Type[])null);
		if (methodInfo == null)
		{
			throw new MissingMethodException(typeFromHandle.FullName, "SetValue");
		}
		MethodInfo methodInfo2 = PrefixMethod.MakeGenericMethod(typeof(TValue));
		harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}

	private static bool SetValuePrefix<TValue>(BinarySearchDictionary<int, TValue> __instance, int key, TValue value, ref bool __result)
	{
		if (__instance == null)
		{
			return true;
		}
		int[] array = Fields<TValue>.Keys.Invoke(__instance);
		TValue[] array2 = Fields<TValue>.Values.Invoke(__instance);
		ushort num = Fields<TValue>.Length.Invoke(__instance);
		bool exactMatch;
		int num2 = FindKeyIndex(array, num, key, out exactMatch);
		if (exactMatch)
		{
			if (EqualityComparer<TValue>.Default.Equals(array2[num2], value))
			{
				__result = false;
				return false;
			}
			array2[num2] = value;
			__result = true;
			return false;
		}
		if (array == null || array.Length <= num)
		{
			int num3 = ((array == null || array.Length == 0) ? 1 : (array.Length + 2));
			int[] array3 = new int[num3];
			TValue[] array4 = new TValue[num3];
			if (num > 0)
			{
				Array.Copy(array, array3, num);
				Array.Copy(array2, array4, num);
			}
			array = array3;
			array2 = array4;
			Fields<TValue>.Keys.Invoke(__instance) = array;
			Fields<TValue>.Values.Invoke(__instance) = array2;
		}
		if (num - num2 > 0)
		{
			Array.Copy(array, num2, array, num2 + 1, num - num2);
			Array.Copy(array2, num2, array2, num2 + 1, num - num2);
		}
		array[num2] = key;
		array2[num2] = value;
		Fields<TValue>.Length.Invoke(__instance) = (ushort)(num + 1);
		__result = true;
		return false;
	}

	private static int FindKeyIndex(int[] keys, ushort length, int key, out bool exactMatch)
	{
		if (length == 0)
		{
			exactMatch = false;
			return 0;
		}
		int num = 0;
		int num2 = length - 1;
		while (num < num2)
		{
			int num3 = (num + num2) / 2;
			if (key == keys[num3])
			{
				exactMatch = true;
				return num3;
			}
			if (key < keys[num3])
			{
				num2 = num3 - 1;
			}
			else
			{
				num = num3 + 1;
			}
		}
		int num4 = key.CompareTo(keys[num]);
		exactMatch = num4 == 0;
		if (num4 <= 0)
		{
			return num;
		}
		return num + 1;
	}
}
[HarmonyPatch(typeof(AudioMan), "Update")]
internal static class AudioManHeadlessPatch
{
	private static bool Prefix()
	{
		return !TerramizerServerPlugin.ShouldSkipHeadlessVisualSystems();
	}
}
[HarmonyPatch(typeof(ShieldDomeImageEffect), "Awake")]
internal static class ShieldDomeAwakeHeadlessPatch
{
	private static bool Prefix(ShieldDomeImageEffect __instance)
	{
		if (!TerramizerServerPlugin.ShouldSkipHeadlessVisualSystems())
		{
			return true;
		}
		if ((Object)(object)__instance != (Object)null)
		{
			((Behaviour)__instance).enabled = false;
		}
		return false;
	}
}
[HarmonyPatch(typeof(ShieldDomeImageEffect), "GetDomeColor")]
internal static class ShieldDomeColorHeadlessPatch
{
	private static bool Prefix(ref Color __result)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		if (!TerramizerServerPlugin.ShouldSkipHeadlessVisualSystems())
		{
			return true;
		}
		__result = Color.white;
		return false;
	}
}
[HarmonyPatch(typeof(EnvMan), "SkipToMorning")]
internal static class EnvManSkipToMorningPatch
{
	private static void Postfix(EnvMan __instance)
	{
		TerramizerServerPlugin.TuneSleepFastForward(__instance);
	}
}
[HarmonyPatch(typeof(Game), "SleepStop")]
internal static class GameSleepStopPatch
{
	private static void Prefix(Game __instance, out float __state)
	{
		__state = TerramizerServerPlugin.CaptureSleepSaveTimer(__instance);
	}

	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		MethodInfo worldSave = AccessTools.Method(typeof(ZNet), "Save", new Type[3]
		{
			typeof(bool),
			typeof(bool),
			typeof(bool)
		}, (Type[])null);
		MethodInfo worldReplacement = AccessTools.Method(typeof(TerramizerServerPlugin), "SaveWorldFromSleep", (Type[])null, (Type[])null);
		if (worldSave == null)
		{
			throw new InvalidOperationException("Could not resolve ZNet.Save(bool, bool, bool).");
		}
		if (worldReplacement == null)
		{
			throw new InvalidOperationException("Could not resolve TerramizerServer SaveWorldFromSleep replacement.");
		}
		int worldReplacements = 0;
		foreach (CodeInstruction instruction in instructions)
		{
			if (CodeInstructionExtensions.Calls(instruction, worldSave))
			{
				instruction.opcode = OpCodes.Call;
				instruction.operand = worldReplacement;
				worldReplacements++;
			}
			yield return instruction;
		}
		if (worldReplacements != 1)
		{
			throw new InvalidOperationException("Expected one world-save call in Game.SleepStop, found " + worldReplacements + ".");
		}
	}

	private static void Postfix(Game __instance, float __state)
	{
		TerramizerServerPlugin.RestoreSleepSaveTimer(__instance, __state);
	}
}
[BepInPlugin("r4v9n1.terramizerserver", "TerramizerServer", "1.0.6")]
public sealed class TerramizerServerPlugin : BaseUnityPlugin
{
	private struct PeerState
	{
		internal bool HasZone;

		internal Vector2s Zone;

		internal float NextTime;
	}

	private static ConfigEntry<bool> _streamingBoostEnabled;

	private static ConfigEntry<int> _streamingBoostMaxZdos;

	private static ConfigEntry<float> _streamingBoostCooldown;

	private static ConfigEntry<int> _streamingBoostMaxQueuePercent;

	private static readonly Dictionary<long, PeerState> _streamingPeerStates = new Dictionary<long, PeerState>();

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

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

	private static readonly HashSet<ZDOID> _streamingSeen = new HashSet<ZDOID>();

	private static Vector3 _streamingReferencePosition;

	private static float _nextStreamingPassTime;

	private static bool _streamingFailureLogged;

	public const string PluginGuid = "r4v9n1.terramizerserver";

	public const string PluginName = "TerramizerServer";

	public const string PluginVersion = "1.0.6";

	public const string CreatorCredit = "Created by R4V9N1";

	private const string SyncedVersionKey = "r4v9n1.terramizerserver.version";

	private const string SyncedStaticOwnershipKey = "r4v9n1.terramizerserver.staticOwnership";

	private const string SyncedOwnershipCacheKey = "r4v9n1.terramizerserver.ownershipCache";

	private const string SyncedTerrainLimitsEnabledKey = "r4v9n1.terramizerserver.extendedTerrainLimits";

	private const string SyncedTerrainRaiseLimitKey = "r4v9n1.terramizerserver.terrainRaiseLimit";

	private const string SyncedTerrainDigLimitKey = "r4v9n1.terramizerserver.terrainDigLimit";

	private const string RpcRequestCompanionMetadata = "r4v9n1.terramizerserver.RequestCompanionMetadata";

	private const string RpcCompanionMetadata = "r4v9n1.terramizerserver.CompanionMetadata";

	private const string RpcRequestCompanionMetadataV2 = "r4v9n1.terramizerserver.RequestCompanionMetadataV2";

	private const string RpcCompanionMetadataV2 = "r4v9n1.terramizerserver.CompanionMetadataV2";

	private static ConfigEntry<bool> _enabled;

	private static ConfigEntry<bool> _dedicatedOnly;

	private static ConfigEntry<bool> _disableUnityJobDebugger;

	private static ConfigEntry<bool> _reuseCollisionCallbacks;

	private static ConfigEntry<bool> _enableStaticPieceServerOwnership;

	private static ConfigEntry<bool> _dryRunStaticPieceServerOwnership;

	private static ConfigEntry<bool> _playerBuiltPiecesOnly;

	private static ConfigEntry<bool> _requireWearNTear;

	private static ConfigEntry<float> _ownershipScanIntervalSeconds;

	private static ConfigEntry<int> _maxClaimsPerScan;

	private static ConfigEntry<int> _zdoRecordsPerScan;

	private static ConfigEntry<float> _maintenanceOwnershipScanIntervalSeconds;

	private static ConfigEntry<int> _maintenanceMaxClaimsPerScan;

	private static ConfigEntry<int> _maintenanceZdoRecordsPerScan;

	private static ConfigEntry<bool> _enableBackgroundOwnershipAudit;

	private static ConfigEntry<bool> _enableOwnershipCache;

	private static ConfigEntry<float> _ownershipCacheMaxAgeHours;

	private static ConfigEntry<int> _ownershipCacheRecordsPerScan;

	private static ConfigEntry<int> _maxCacheRestoresPerScan;

	private static ConfigEntry<bool> _resumeZdoScanFromCache;

	private static ConfigEntry<bool> _logDevClaims;

	private static ConfigEntry<bool> _logWatchedClaims;

	private static ConfigEntry<bool> _logDevSkips;

	private static ConfigEntry<float> _devSummaryIntervalSeconds;

	private static ConfigEntry<bool> _speedUpSleepFastForward;

	private static ConfigEntry<float> _sleepFastForwardSeconds;

	private static ConfigEntry<bool> _skipSleepWorldSave;

	private static ConfigEntry<bool> _preserveAutosaveTimer;

	private static ConfigEntry<bool> _logSkippedSleepSaves;

	private static FieldInfo _envManSkipToTimeField;

	private static FieldInfo _envManTimeSkipSpeedField;

	private static FieldInfo _gameSaveTimerField;

	private static ManualLogSource _log;

	private static FieldInfo _objectsByIdField;

	private static int _zdoScanIndex;

	private static int _ownershipCacheScanIndex;

	private static bool _ownershipCacheWarmStartComplete;

	private static bool _ownershipCacheDirty;

	private static bool _serverMetadataAdvertised;

	private static bool _loadedZdoScanCursorPending;

	private static bool _initialBroadScanComplete;

	private static bool _initialBroadScanTraversalComplete;

	private static bool _pendingInitialBroadScanCompletion;

	private static bool _ownershipCacheWorldValidated;

	private static long _cachedOwnershipWorldUid;

	private static bool _companionRpcReplyLogged;

	private static bool _applicationQuitting;

	private static bool _ownershipPatchFailureLogged;

	private static bool _ownershipMaintenanceFailureLogged;

	private static bool _firstBroadScanStatusStarted;

	private static bool _firstBroadScanStatusCompleted;

	private static float _nextFirstBroadScanStatusTime;

	private static string _ownershipCachePath;

	private static float _nextOwnershipScanTime;

	private static float _nextDevSummaryTime;

	private static float _nextOwnershipCacheFlushTime;

	private static ZNet _metadataAdvertisedForInstance;

	private static int _cachedZdoScanIndex;

	private static int _cachedZdoScanObjectCount;

	private static int _zdoBroadScanPassesCompleted;

	private static long _cachedZdoScanUpdatedUnixSeconds;

	private static long _claimAttempts;

	private static long _claimed;

	private static long _totalClaimed;

	private static long _watchedClaims;

	private static long _totalWatchedClaims;

	private static long _alreadyServerOwned;

	private static long _skippedNotReady;

	private static long _skippedNotPersistent;

	private static long _skippedNoCreator;

	private static long _skippedNoWearNTear;

	private static long _skippedDynamic;

	private static long _skippedNoZdo;

	private static long _skippedNoPrefab;

	private static long _skippedNotPiecePrefab;

	private static long _zdoRecordsChecked;

	private static long _cacheRecordsChecked;

	private static long _cacheRestored;

	private static long _totalCacheRestored;

	private static long _cacheRemoved;

	private static long _companionRpcReplies;

	private static readonly Dictionary<int, bool> _prefabEligibilityCache = new Dictionary<int, bool>();

	private static readonly Dictionary<string, OwnershipCacheEntry> _ownershipCache = new Dictionary<string, OwnershipCacheEntry>();

	private static readonly Queue<string> _deferredOwnershipClaims = new Queue<string>();

	private static readonly HashSet<string> _deferredOwnershipClaimSet = new HashSet<string>();

	private static ZRoutedRpc _registeredRoutedRpcInstance;

	private Harmony _harmony;

	private static ConfigEntry<bool> _enableExtendedTerrainLimits;

	private static ConfigEntry<float> _terrainRaiseLimitMeters;

	private static ConfigEntry<float> _terrainDigLimitMeters;

	internal static void TuneSleepFastForward(EnvMan envMan)
	{
		if (Application.isBatchMode && _speedUpSleepFastForward != null && _speedUpSleepFastForward.Value && !((Object)(object)envMan == (Object)null) && envMan.IsTimeSkipping() && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !(_envManSkipToTimeField == null) && !(_envManTimeSkipSpeedField == null))
		{
			double num = (double)_envManSkipToTimeField.GetValue(envMan) - ZNet.instance.GetTimeSeconds();
			if (num > 0.0)
			{
				_envManTimeSkipSpeedField.SetValue(envMan, num / (double)Mathf.Clamp(_sleepFastForwardSeconds.Value, 1f, 60f));
			}
		}
	}

	internal static float CaptureSleepSaveTimer(Game game)
	{
		if ((Object)(object)game == (Object)null || _skipSleepWorldSave == null || !_skipSleepWorldSave.Value || _preserveAutosaveTimer == null || !_preserveAutosaveTimer.Value || _gameSaveTimerField == null)
		{
			return float.NaN;
		}
		return (float)_gameSaveTimerField.GetValue(game);
	}

	internal static void RestoreSleepSaveTimer(Game game, float timer)
	{
		if (!((Object)(object)game == (Object)null) && !float.IsNaN(timer) && !(_gameSaveTimerField == null))
		{
			_gameSaveTimerField.SetValue(game, timer);
		}
	}

	internal static void SaveWorldFromSleep(ZNet znet, bool sync, bool saveOtherPlayerProfiles, bool waitForNextFrame)
	{
		if (_skipSleepWorldSave == null || !_skipSleepWorldSave.Value)
		{
			if ((Object)(object)znet != (Object)null)
			{
				znet.Save(sync, saveOtherPlayerProfiles, waitForNextFrame);
			}
		}
		else if (_logSkippedSleepSaves != null && _logSkippedSleepSaves.Value && _log != null)
		{
			_log.LogInfo((object)"Skipped sleep-triggered world save. Regular autosaves remain enabled.");
		}
	}

	private static bool CanRunServerStreaming()
	{
		if (_enabled != null && _enabled.Value && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
		{
			if (_dedicatedOnly.Value)
			{
				return ZNet.instance.IsDedicated();
			}
			return true;
		}
		return false;
	}

	private void InitializeStreaming()
	{
		_streamingBoostEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Streaming", "EnableServerZoneStreamingBoost", true, "Prefetches a bounded set of existing nearby ZDOs when a ready peer enters a new zone. Does not create zones or scene objects.");
		_streamingBoostMaxZdos = BindRange("Streaming", "MaxZoneStreamingBoostZdosPerPeer", 256, "Maximum existing ZDOs force-queued for one peer per zone transition.", 0, 2000);
		_streamingBoostCooldown = BindRange("Streaming", "ZoneStreamingBoostCooldownSeconds", 0.75f, "Minimum time between a peer's bounded streaming boosts.", 0.1f, 10f);
		_streamingBoostMaxQueuePercent = BindRange("Streaming", "ZoneStreamingBoostMaxQueuePercent", 35, "Do not prefetch while the peer socket queue is above this percentage of its ceiling.", 10, 90);
	}

	private static void RunStreamingBoost()
	{
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_0276: Unknown result type (might be due to invalid IL or missing references)
		//IL_0296: Unknown result type (might be due to invalid IL or missing references)
		//IL_0298: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		if (_streamingBoostEnabled == null || !_streamingBoostEnabled.Value || !CanRunServerStreaming() || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsDedicated() || ZDOMan.instance == null || (Object)(object)ZoneSystem.instance == (Object)null)
		{
			return;
		}
		try
		{
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (realtimeSinceStartup < _nextStreamingPassTime)
			{
				return;
			}
			_nextStreamingPassTime = realtimeSinceStartup + 0.1f;
			List<ZNetPeer> connectedPeers = ZNet.instance.GetConnectedPeers();
			if (connectedPeers == null)
			{
				return;
			}
			SimulationDistance val2 = default(SimulationDistance);
			for (int i = 0; i < connectedPeers.Count; i++)
			{
				ZNetPeer val = connectedPeers[i];
				if (val == null || !val.IsReady() || val.m_socket == null)
				{
					continue;
				}
				Vector3 refPos = val.GetRefPos();
				Vector2s zone = ZoneSystem.GetZone(refPos);
				if (!_streamingPeerStates.TryGetValue(val.m_uid, out var value))
				{
					value = default(PeerState);
				}
				if (realtimeSinceStartup < value.NextTime || (value.HasZone && value.Zone == zone))
				{
					continue;
				}
				if ((long)val.m_socket.GetSendQueueSize() * 100L >= 10240L * (long)_streamingBoostMaxQueuePercent.Value)
				{
					value.NextTime = realtimeSinceStartup + 0.25f;
					_streamingPeerStates[val.m_uid] = value;
					continue;
				}
				_streamingNear.Clear();
				_streamingCandidates.Clear();
				_streamingSeen.Clear();
				SimulationDistance simulationDistance = val.m_simulationDistance;
				((SimulationDistance)(ref val2))..ctor(((SimulationDistance)(ref simulationDistance)).NearSimulationDistance, 0, ((SimulationDistance)(ref simulationDistance)).IsClassic);
				ZDOMan.instance.FindSectorObjects(zone, val2, _streamingNear, (List<ZDO>)null);
				_streamingReferencePosition = refPos;
				for (int j = 0; j < _streamingNear.Count; j++)
				{
					ZDO val3 = _streamingNear[j];
					if (val3 != null && val3.IsValid() && !((ZDOID)(ref val3.m_uid)).IsNone() && _streamingSeen.Add(val3.m_uid) && (!((Object)(object)ZNetScene.instance != (Object)null) || ZNetScene.instance.HasPrefab(val3.GetPrefab())) && !ShouldDeferTerrainZdo(val3))
					{
						_streamingCandidates.Add(val3);
					}
				}
				_streamingCandidates.Sort(CompareStreamingDistance);
				int num = Math.Min(_streamingBoostMaxZdos.Value, _streamingCandidates.Count);
				for (int k = 0; k < num; k++)
				{
					ZDOMan.instance.ForceSendZDO(val.m_uid, _streamingCandidates[k].m_uid);
				}
				value.HasZone = true;
				value.Zone = zone;
				value.NextTime = realtimeSinceStartup + _streamingBoostCooldown.Value;
				_streamingPeerStates[val.m_uid] = value;
			}
			_streamingNear.Clear();
			_streamingCandidates.Clear();
			_streamingSeen.Clear();
		}
		catch (Exception ex)
		{
			if (!_streamingFailureLogged)
			{
				_streamingFailureLogged = true;
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)("Bounded zone streaming boost disabled after an unexpected runtime shape: " + ex.Message));
				}
			}
		}
	}

	private static int CompareStreamingDistance(ZDO left, ZDO right)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = left.GetPosition() - _streamingReferencePosition;
		Vector3 val2 = right.GetPosition() - _streamingReferencePosition;
		float num = val.x * val.x + val.z * val.z;
		float num2 = val2.x * val2.x + val2.z * val2.z;
		return Utils.CompareFloats(num, num2);
	}

	private static bool ShouldDeferTerrainZdo(ZDO zdo)
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)ZNetScene.instance == (Object)null)
		{
			return false;
		}
		try
		{
			GameObject prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab());
			if ((Object)(object)prefab == (Object)null || ((Object)(object)prefab.GetComponent<TerrainComp>() == (Object)null && (Object)(object)prefab.GetComponentInChildren<TerrainComp>(true) == (Object)null))
			{
				return false;
			}
			return (Object)(object)Heightmap.FindHeightmap(zdo.GetPosition()) == (Object)null;
		}
		catch
		{
			return true;
		}
	}

	private void Awake()
	{
		_log = ((BaseUnityPlugin)this).Logger;
		_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable TerramizerServer runtime features.");
		_dedicatedOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DedicatedOnly", true, "Apply runtime features only in a batch-mode dedicated-server process.");
		BindTerrainCompatibilityConfig();
		_disableUnityJobDebugger = ((BaseUnityPlugin)this).Config.Bind<bool>("Performance", "DisableUnityJobDebugger", true, "Disable Unity's development-only job debugger without changing simulation, networking, ownership, objects, or saves.");
		_reuseCollisionCallbacks = ((BaseUnityPlugin)this).Config.Bind<bool>("Performance", "ReuseCollisionCallbacks", true, "Reuse Unity collision callback objects to reduce physics GC allocations. Disable for mods that retain Collision objects after callbacks.");
		_enableStaticPieceServerOwnership = ((BaseUnityPlugin)this).Config.Bind<bool>("ExperimentalOwnership", "EnableStaticPieceServerOwnership", true, "EXPERIMENTAL: make the dedicated server claim ownership of loaded, static, player-created structure pieces while preserving their creator field.");
		_dryRunStaticPieceServerOwnership = ((BaseUnityPlugin)this).Config.Bind<bool>("ExperimentalOwnership", "DryRunStaticPieceServerOwnership", false, "Log which pieces would be claimed without changing ZDO ownership.");
		_playerBuiltPiecesOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("ExperimentalOwnership", "PlayerBuiltPiecesOnly", true, "Only claim pieces with a non-zero Valheim creator field.");
		_requireWearNTear = ((BaseUnityPlugin)this).Config.Bind<bool>("ExperimentalOwnership", "RequireWearNTear", true, "Only claim structure-style pieces that have WearNTear. This avoids crops and other non-structural placed objects.");
		_ownershipScanIntervalSeconds = BindRange("ExperimentalOwnership", "OwnershipScanIntervalSeconds", 5f, "Seconds between heavy initial ownership scan passes. Newly loaded pieces are handled immediately.", 1f, 120f);
		_maxClaimsPerScan = BindRange("ExperimentalOwnership", "MaxClaimsPerScan", 100, "Maximum ZDO ownership changes allowed per scan.", 1, 5000);
		_zdoRecordsPerScan = BindRange("ExperimentalOwnership", "ZdoRecordsPerScan", 25000, "Maximum persistent ZDO records inspected per heavy initial scan pass.", 100, 100000);
		_maintenanceOwnershipScanIntervalSeconds = BindRange("ExperimentalOwnership", "MaintenanceOwnershipScanIntervalSeconds", 15f, "Seconds between maintenance integrity audits after the verified initial world pass. New/loaded pieces are handled immediately.", 5f, 21600f);
		_maintenanceMaxClaimsPerScan = BindRange("ExperimentalOwnership", "MaintenanceMaxClaimsPerScan", 25, "Maximum ZDO ownership changes allowed per maintenance scan after the first full broad pass.", 1, 5000);
		_maintenanceZdoRecordsPerScan = BindRange("ExperimentalOwnership", "MaintenanceZdoRecordsPerScan", 5000, "Maximum persistent ZDO records inspected per maintenance scan after the verified first full broad pass.", 100, 100000);
		_enableBackgroundOwnershipAudit = ((BaseUnityPlugin)this).Config.Bind<bool>("ExperimentalOwnership", "EnableBackgroundOwnershipAudit", true, "Run the legacy whole-world ZDO ownership audit. Disabled by default because event-driven claims cover newly loaded structures without scanning the live world table.");
		_enableOwnershipCache = ((BaseUnityPlugin)this).Config.Bind<bool>("OwnershipCache", "EnableOwnershipCache", true, "Store known eligible claimed ZDOs so restart warm-start can quickly reassign them to the new server session id.");
		_ownershipCacheMaxAgeHours = BindRange("OwnershipCache", "OwnershipCacheMaxAgeHours", 168f, "Maximum age in hours for remembered ownership records. Older cache rows are ignored and removed.", 1f, 2160f);
		_ownershipCacheRecordsPerScan = BindRange("OwnershipCache", "OwnershipCacheRecordsPerScan", 200000, "Maximum cached ownership records inspected per restart warm-start pass.", 1000, 1000000);
		_maxCacheRestoresPerScan = BindRange("OwnershipCache", "MaxCacheRestoresPerScan", 5000, "Maximum cached ownership restores applied per warm-start pass.", 1, 50000);
		_resumeZdoScanFromCache = ((BaseUnityPlugin)this).Config.Bind<bool>("OwnershipCache", "ResumeZdoScanFromCache", true, "Resume the broad ZDO eligibility scan from the last persisted scan index after server restart. The cache clamps this index if the world ZDO count changed.");
		MigrateOwnershipScanBudgetsFrom104Defaults();
		_logDevClaims = ((BaseUnityPlugin)this).Config.Bind<bool>("DevLogs", "LogOwnershipClaims", false, "Log every static piece ownership claim or dry-run claim. This is very noisy on established worlds.");
		_logWatchedClaims = ((BaseUnityPlugin)this).Config.Bind<bool>("DevLogs", "LogWatchedOwnershipClaims", false, "Log ownership claims for sensitive interactive prefabs such as beds, chests, portals, fires, stations, signs, item stands, wards, doors, and gates.");
		_logDevSkips = ((BaseUnityPlugin)this).Config.Bind<bool>("DevLogs", "LogOwnershipSkips", false, "Log skipped pieces. This is noisy and should only be enabled during focused testing.");
		_devSummaryIntervalSeconds = BindRange("DevLogs", "OwnershipSummaryIntervalSeconds", 60f, "Seconds between compact ownership experiment summaries.", 5f, 600f);
		_speedUpSleepFastForward = ((BaseUnityPlugin)this).Config.Bind<bool>("Sleep", "SpeedUpSleepFastForward", true, "Tune sleep time-skip to the configured real-time duration.");
		_sleepFastForwardSeconds = BindRange("Sleep", "SleepFastForwardSeconds", 4f, "Target real seconds for sleep time-skip.", 1f, 60f);
		_skipSleepWorldSave = ((BaseUnityPlugin)this).Config.Bind<bool>("Sleep", "SkipSleepWorldSave", true, "Skip the extra world save triggered when sleep ends.");
		_preserveAutosaveTimer = ((BaseUnityPlugin)this).Config.Bind<bool>("Sleep", "PreserveAutosaveTimer", true, "Keep the regular autosave timer unchanged when the sleep save is skipped.");
		_logSkippedSleepSaves = ((BaseUnityPlugin)this).Config.Bind<bool>("Sleep", "LogSkippedSleepSaves", true, "Log when the sleep-triggered world save is skipped.");
		InitializeStreaming();
		RemoveRetiredSettings();
		_envManSkipToTimeField = AccessTools.Field(typeof(EnvMan), "m_skipToTime");
		_envManTimeSkipSpeedField = AccessTools.Field(typeof(EnvMan), "m_timeSkipSpeed");
		_gameSaveTimerField = AccessTools.Field(typeof(Game), "m_saveTimer");
		if (_enableBackgroundOwnershipAudit.Value)
		{
			LoadOwnershipCache();
		}
		ApplySafeRuntimeSetting();
		InstallExperimentalPatches();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"TerramizerServer 1.0.6 loaded.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Static piece server ownership experiment: enabled=" + _enableStaticPieceServerOwnership.Value + ", dryRun=" + _dryRunStaticPieceServerOwnership.Value + ", playerBuiltOnly=" + _playerBuiltPiecesOnly.Value + ", requireWearNTear=" + _requireWearNTear.Value + "."));
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Creator fields are preserved. WearNTear is not removed. Dynamic physics objects remain peer-owned.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Bounded zone streaming prefetch: enabled=" + _streamingBoostEnabled.Value + ", maxZdosPerPeer=" + _streamingBoostMaxZdos.Value + ", cooldown=" + _streamingBoostCooldown.Value.ToString("F2") + "s, socket backpressure=" + _streamingBoostMaxQueuePercent.Value + "%. Peer-zone scene creation remains disabled."));
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Created by R4V9N1.");
	}

	private ConfigEntry<T> BindRange<T>(string section, string key, T defaultValue, string description, T minimum, T maximum) where T : IComparable
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Expected O, but got Unknown
		return ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<T>(minimum, maximum), Array.Empty<object>()));
	}

	private void ApplySafeRuntimeSetting()
	{
		if (!_enabled.Value || (_dedicatedOnly.Value && !Application.isBatchMode))
		{
			return;
		}
		try
		{
			if (_disableUnityJobDebugger.Value && JobsUtility.JobDebuggerEnabled)
			{
				JobsUtility.JobDebuggerEnabled = false;
			}
			Physics.reuseCollisionCallbacks = _reuseCollisionCallbacks.Value;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Unity's development job debugger is disabled; all server game systems remain unmodified.");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not change Unity's optional job-debugger setting; continuing with vanilla behavior: " + ex.Message));
		}
	}

	private void InstallExperimentalPatches()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Expected O, but got Unknown
		if (_enabled.Value && (!_dedicatedOnly.Value || Application.isBatchMode))
		{
			_harmony = new Harmony("r4v9n1.terramizerserver");
			BinarySearchDictionarySetValuePatch.Install(_harmony, (Action<string>)((BaseUnityPlugin)this).Logger.LogInfo);
			TryPatch(typeof(VisEquipmentIntCachePatch), "VisEquipment ZDO integer lookup cache");
			TryPatch(typeof(ZPackageWritePackagePatch), "allocation-free ZPackage nesting");
			TryPatch(typeof(ZdoOwnershipHandoffPatch), "optimized ZDO ownership handoff scan");
			TryPatch(typeof(ZNetViewAwakeStaticOwnershipPatch), "ZNetView creation ownership observation");
			TryPatch(typeof(EnvManSkipToMorningPatch), "sleep fast-forward");
			TryPatch(typeof(GameSleepStopPatch), "sleep save policy");
			TryPatch(typeof(HeightmapAtMaxWorldLevelDepthTerrainLimitPatch), "world heightmap dig-depth terrain limit");
			TryPatch(typeof(HeightmapLevelTerrainTerrainLimitPatch), "heightmap terrain raise/dig limits");
			TryPatch(typeof(TerrainCompLevelTerrainLimitPatch), "terrain component raise/dig limits");
			TryPatch(typeof(TerrainCompRaiseTerrainLimitPatch), "terrain component direct raise limit");
			TryPatch(typeof(TerrainCompApplyToHeightmapTerrainLimitPatch), "terrain final-apply limits");
			TryPatch(typeof(AudioManHeadlessPatch), "headless audio guard");
			TryPatch(typeof(ShieldDomeAwakeHeadlessPatch), "headless shield initialization guard");
			TryPatch(typeof(ShieldDomeColorHeadlessPatch), "headless shield color guard");
		}
	}

	private void TryPatch(Type patchType, string name)
	{
		try
		{
			_harmony.CreateClassProcessor(patchType).Patch();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Installed " + name + "."));
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not install " + name + "; continuing without that patch: " + ex.Message));
		}
	}

	internal static bool ShouldSkipHeadlessVisualSystems()
	{
		return Application.isBatchMode;
	}

	private void Update()
	{
		RegisterCompanionRpcsWhenReady();
		AdvertiseServerMetadata();
		RunStreamingBoost();
		if (!ShouldRunExperiment())
		{
			return;
		}
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		if (_enableBackgroundOwnershipAudit.Value && _enableOwnershipCache.Value && !_ownershipCacheWarmStartComplete)
		{
			try
			{
				if (EnsureOwnershipCacheWorldIdentity())
				{
					ApplyOwnershipCacheWarmStart();
				}
			}
			catch (Exception ex)
			{
				LogOwnershipMaintenanceFailure(ex);
			}
		}
		if (_enableBackgroundOwnershipAudit.Value && realtimeSinceStartup >= _nextOwnershipScanTime)
		{
			try
			{
				SweepLoadedPieces();
			}
			catch (Exception ex2)
			{
				LogOwnershipMaintenanceFailure(ex2);
			}
			_nextOwnershipScanTime = realtimeSinceStartup + GetOwnershipScanIntervalSeconds();
		}
		if (_enableBackgroundOwnershipAudit.Value && realtimeSinceStartup >= _nextDevSummaryTime)
		{
			_nextDevSummaryTime = realtimeSinceStartup + _devSummaryIntervalSeconds.Value;
			LogOwnershipSummary();
		}
		if (_ownershipCacheDirty && realtimeSinceStartup >= _nextOwnershipCacheFlushTime)
		{
			FlushOwnershipCache(force: false);
		}
	}

	private void OnDestroy()
	{
		FlushOwnershipCache(force: true);
		if (_harmony != null && !_applicationQuitting)
		{
			try
			{
				_harmony.UnpatchSelf();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not unpatch TerramizerServer during teardown; process shutdown can continue safely: " + ex.Message));
			}
			_harmony = null;
		}
	}

	private void OnApplicationQuit()
	{
		_applicationQuitting = true;
		FlushOwnershipCache(force: true);
	}

	internal static void TryClaimFromZNetView(ZNetView view, string reason)
	{
		try
		{
			if (!ShouldRunExperiment() || (Object)(object)view == (Object)null)
			{
				return;
			}
			ZDO zDO = view.GetZDO();
			if (zDO == null)
			{
				return;
			}
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				int prefab = zDO.GetPrefab();
				GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab);
				if ((Object)(object)prefab2 != (Object)null && !IsEligibleStaticPiecePrefab(prefab, prefab2))
				{
					return;
				}
			}
			Piece val = ((Component)view).GetComponent<Piece>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)view).GetComponentInChildren<Piece>(true);
			}
			if (!((Object)(object)val == (Object)null))
			{
				TryClaimPiece(val, reason, allowClaimLimit: false, null);
			}
		}
		catch (Exception ex)
		{
			if (!_ownershipPatchFailureLogged && _log != null)
			{
				_ownershipPatchFailureLogged = true;
				_log.LogWarning((object)("Static ownership observation failed; the affected object remains vanilla-owned: " + ex.Message));
			}
		}
	}

	private static void SweepLoadedPieces()
	{
		Piece[] array = Object.FindObjectsByType<Piece>((FindObjectsSortMode)0);
		int claims = 0;
		int maxClaimsPerScan = GetMaxClaimsPerScan();
		for (int i = 0; i < array.Length; i++)
		{
			if (claims >= maxClaimsPerScan)
			{
				break;
			}
			int num = claims;
			TryClaimPiece(array[i], "sweep", allowClaimLimit: true, delegate
			{
				claims++;
			});
			if (claims != num && _dryRunStaticPieceServerOwnership.Value)
			{
				claims = num + 1;
			}
		}
		SweepZdoRecords(Math.Max(0, maxClaimsPerScan - claims));
	}

	private static void TryClaimPiece(Piece piece, string reason, bool allowClaimLimit, Action claimsThisScan)
	{
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		_claimAttempts++;
		if ((Object)(object)piece == (Object)null || (Object)(object)((Component)piece).gameObject == (Object)null)
		{
			_skippedNotReady++;
			return;
		}
		ZNetView val = ((Component)piece).GetComponent<ZNetView>();
		if ((Object)(object)val == (Object)null)
		{
			val = ((Component)piece).GetComponentInParent<ZNetView>();
		}
		if ((Object)(object)val == (Object)null)
		{
			val = ((Component)piece).GetComponentInChildren<ZNetView>(true);
		}
		if ((Object)(object)val == (Object)null || !val.IsValid() || val.GetZDO() == null)
		{
			_skippedNoZdo++;
			LogSkip(piece, "no valid ZDO");
			return;
		}
		ZDO zDO = val.GetZDO();
		if (!zDO.Persistent)
		{
			_skippedNotPersistent++;
			LogSkip(piece, "not persistent");
			return;
		}
		long num = zDO.GetLong(ZDOVars.s_creator, 0L);
		if (_playerBuiltPiecesOnly.Value && num == 0L)
		{
			_skippedNoCreator++;
			LogSkip(piece, "no player creator");
			return;
		}
		if (_requireWearNTear.Value && (Object)(object)((Component)piece).GetComponent<WearNTear>() == (Object)null && (Object)(object)((Component)piece).GetComponentInChildren<WearNTear>(true) == (Object)null)
		{
			_skippedNoWearNTear++;
			LogSkip(piece, "no WearNTear");
			return;
		}
		if (IsDynamicOrPhysicsObject(((Component)piece).gameObject))
		{
			_skippedDynamic++;
			LogSkip(piece, "dynamic or physics object");
			return;
		}
		string prefabName = CleanPrefabName(((Object)((Component)piece).gameObject).name);
		long sessionID = ZDOMan.GetSessionID();
		long owner = zDO.GetOwner();
		if (owner == sessionID)
		{
			_alreadyServerOwned++;
			RecordOwnershipCache(zDO, prefabName, num);
			return;
		}
		if (_dryRunStaticPieceServerOwnership.Value)
		{
			_claimed++;
			_totalClaimed++;
			claimsThisScan?.Invoke();
			LogClaim("DRY-RUN would claim", prefabName, zDO, owner, num, reason);
			return;
		}
		zDO.SetOwner(sessionID);
		if (ZDOMan.instance != null)
		{
			ZDOMan.instance.ForceSendZDO(zDO.m_uid);
		}
		_claimed++;
		_totalClaimed++;
		RecordOwnershipCache(zDO, prefabName, num);
		claimsThisScan?.Invoke();
		LogClaim("Claimed", prefabName, zDO, owner, num, reason);
	}

	private static void SweepZdoRecords(int remainingClaimBudget)
	{
		if (ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null)
		{
			return;
		}
		Dictionary<ZDOID, ZDO> objectsById = GetObjectsById();
		if (objectsById == null || objectsById.Count == 0 || !EnsureOwnershipCacheWorldIdentity())
		{
			return;
		}
		int num = Math.Max(0, remainingClaimBudget);
		int num2 = DrainDeferredOwnershipClaims(objectsById, num);
		if (_initialBroadScanTraversalComplete && !_initialBroadScanComplete)
		{
			PersistZdoScanCursor(objectsById.Count);
			if (_deferredOwnershipClaims.Count == 0)
			{
				CommitInitialBroadScanCompletion(objectsById.Count);
				LogFirstBroadScanStatus(objectsById.Count, _initialBroadScanComplete);
			}
			return;
		}
		ApplyCachedZdoScanCursor(objectsById.Count);
		ValidateCachedScanPassState(objectsById.Count);
		LogFirstBroadScanStatus(objectsById.Count, completed: false);
		if (_zdoScanIndex >= objectsById.Count)
		{
			_zdoScanIndex = 0;
		}
		int num3 = 0;
		int num4 = 0;
		int zdoRecordsPerScan = GetZdoRecordsPerScan();
		try
		{
			foreach (KeyValuePair<ZDOID, ZDO> item in objectsById)
			{
				if (num3++ >= _zdoScanIndex)
				{
					if (num4 >= zdoRecordsPerScan)
					{
						break;
					}
					num4++;
					_zdoRecordsChecked++;
					bool allowOwnershipChange = num2 < num;
					if (TryClaimZdoRecord(item.Value, "zdo-sweep", allowOwnershipChange))
					{
						num2++;
					}
				}
			}
		}
		catch (InvalidOperationException ex)
		{
			_zdoScanIndex = 0;
			if (_log != null)
			{
				_log.LogWarning((object)("[dev ownership] ZDO scan restarted because the ZDO table changed during enumeration: " + ex.Message));
			}
			return;
		}
		bool flag = _zdoScanIndex + num4 >= objectsById.Count;
		_zdoScanIndex += num4;
		if (flag || num4 == 0)
		{
			_zdoScanIndex = 0;
			if (flag && num4 > 0)
			{
				MarkBroadZdoScanPassComplete(objectsById.Count);
			}
		}
		PersistZdoScanCursor(objectsById.Count);
		if (flag && num4 > 0 && _pendingInitialBroadScanCompletion)
		{
			if (_deferredOwnershipClaims.Count == 0)
			{
				CommitInitialBroadScanCompletion(objectsById.Count);
			}
			else if (_log != null)
			{
				_log.LogInfo((object)("[ownership scan] Initial broad traversal reached 100%; waiting for " + _deferredOwnershipClaims.Count + " deferred ownership changes to drain before durable maintenance handoff."));
			}
		}
		LogFirstBroadScanStatus(objectsById.Count, flag && num4 > 0 && _initialBroadScanComplete);
	}

	private static int DrainDeferredOwnershipClaims(Dictionary<ZDOID, ZDO> objects, int claimBudget)
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		if (objects == null || claimBudget <= 0 || _deferredOwnershipClaims.Count == 0)
		{
			return 0;
		}
		int num = 0;
		int count = _deferredOwnershipClaims.Count;
		bool flag = false;
		while (num < claimBudget && count-- > 0 && _deferredOwnershipClaims.Count > 0)
		{
			string text = _deferredOwnershipClaims.Dequeue();
			_deferredOwnershipClaimSet.Remove(text);
			flag = true;
			if (TryParseZdoId(text, out var id) && objects.TryGetValue(id, out var value) && TryClaimZdoRecord(value, "zdo-deferred", allowOwnershipChange: true))
			{
				num++;
			}
		}
		if (flag)
		{
			MarkOwnershipCacheDirty();
		}
		return num;
	}

	private static void EnqueueDeferredOwnershipClaim(ZDO zdo)
	{
		if (zdo != null && zdo.IsValid())
		{
			string item = ((object)Unsafe.As<ZDOID, ZDOID>(ref zdo.m_uid)/*cast due to .constrained prefix*/).ToString();
			if (_deferredOwnershipClaimSet.Add(item))
			{
				_deferredOwnershipClaims.Enqueue(item);
				MarkOwnershipCacheDirty();
			}
		}
	}

	private static void MarkOwnershipCacheDirty()
	{
		_ownershipCacheDirty = true;
		if (_nextOwnershipCacheFlushTime <= 0f)
		{
			_nextOwnershipCacheFlushTime = Time.realtimeSinceStartup + 30f;
		}
	}

	private static void LogFirstBroadScanStatus(int objectCount, bool completed)
	{
		if (_log == null || !_enableBackgroundOwnershipAudit.Value || (_zdoBroadScanPassesCompleted > 0 && _firstBroadScanStatusCompleted))
		{
			return;
		}
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		if (completed || !_firstBroadScanStatusStarted || !(realtimeSinceStartup < _nextFirstBroadScanStatusTime))
		{
			if (!_firstBroadScanStatusStarted)
			{
				_firstBroadScanStatusStarted = true;
				float val = (float)GetZdoRecordsPerScan() / Math.Max(1f, GetOwnershipScanIntervalSeconds());
				float num = 5000f;
				float seconds = (float)objectCount / Math.Max(1f, val);
				_nextFirstBroadScanStatusTime = realtimeSinceStartup + 30f;
				_log.LogInfo((object)("[ownership scan] First broad ZDO scan started: " + objectCount + " records; estimated time " + FormatScanDuration(seconds) + " at current budget (" + val.ToString("F0") + " records/s). Prior measured warm-up reference was " + num.ToString("F0") + " records/s with a 25,000/5s budget."));
			}
			else if (completed)
			{
				_firstBroadScanStatusCompleted = true;
				_log.LogInfo((object)("[ownership scan] First broad ZDO scan completed: " + objectCount + " records inspected. Switching to maintenance mode."));
			}
			else
			{
				int num2 = Math.Min(Math.Max(_zdoScanIndex, 0), objectCount);
				int num3 = Math.Max(0, objectCount - num2);
				float val2 = (float)GetZdoRecordsPerScan() / Math.Max(1f, GetOwnershipScanIntervalSeconds());
				float seconds2 = (float)num3 / Math.Max(1f, val2);
				float num4 = ((objectCount > 0) ? ((float)num2 * 100f / (float)objectCount) : 100f);
				_nextFirstBroadScanStatusTime = realtimeSinceStartup + 30f;
				_log.LogInfo((object)("[ownership scan] First broad scan progress: " + num4.ToString("F1") + "% (" + num2 + "/" + objectCount + "); estimated remaining " + FormatScanDuration(seconds2) + "."));
			}
		}
	}

	private static string FormatScanDuration(float seconds)
	{
		if (seconds < 60f)
		{
			return Math.Max(0, (int)Math.Ceiling(seconds)) + " seconds";
		}
		int num = (int)(seconds / 60f);
		int num2 = num / 60;
		num %= 60;
		if (num2 <= 0)
		{
			return num + "m";
		}
		return num2 + "h " + num + "m";
	}

	private static bool IsMaintenanceScanMode()
	{
		if (_initialBroadScanComplete && _ownershipCacheWorldValidated)
		{
			if (!_ownershipCacheWarmStartComplete && _enableOwnershipCache != null)
			{
				return !_enableOwnershipCache.Value;
			}
			return true;
		}
		return false;
	}

	private static float GetOwnershipScanIntervalSeconds()
	{
		if (IsMaintenanceScanMode() && _maintenanceOwnershipScanIntervalSeconds != null)
		{
			return _maintenanceOwnershipScanIntervalSeconds.Value;
		}
		if (_ownershipScanIntervalSeconds == null)
		{
			return 5f;
		}
		return _ownershipScanIntervalSeconds.Value;
	}

	private static int GetMaxClaimsPerScan()
	{
		if (IsMaintenanceScanMode() && _maintenanceMaxClaimsPerScan != null)
		{
			return _maintenanceMaxClaimsPerScan.Value;
		}
		if (_maxClaimsPerScan == null)
		{
			return 250;
		}
		return _maxClaimsPerScan.Value;
	}

	private static int GetZdoRecordsPerScan()
	{
		if (IsMaintenanceScanMode() && _maintenanceZdoRecordsPerScan != null)
		{
			return _maintenanceZdoRecordsPerScan.Value;
		}
		if (_zdoRecordsPerScan == null)
		{
			return 25000;
		}
		return _zdoRecordsPerScan.Value;
	}

	private static void MarkBroadZdoScanPassComplete(int objectCount)
	{
		_zdoBroadScanPassesCompleted++;
		_cachedZdoScanObjectCount = objectCount;
		_cachedZdoScanUpdatedUnixSeconds = GetUnixSeconds();
		_ownershipCacheDirty = true;
		if (!_initialBroadScanComplete)
		{
			_initialBroadScanTraversalComplete = true;
			_pendingInitialBroadScanCompletion = true;
		}
	}

	private static void MigrateOwnershipScanBudgetsFrom104Defaults()
	{
		bool flag = false;
		if (Mathf.Approximately(_ownershipScanIntervalSeconds.Value, 15f))
		{
			_ownershipScanIntervalSeconds.Value = 5f;
			flag = true;
		}
		if (_zdoRecordsPerScan.Value == 10000)
		{
			_zdoRecordsPerScan.Value = 25000;
			flag = true;
		}
		if (Mathf.Approximately(_maintenanceOwnershipScanIntervalSeconds.Value, 1800f))
		{
			_maintenanceOwnershipScanIntervalSeconds.Value = 15f;
			flag = true;
		}
		if (_maintenanceZdoRecordsPerScan.Value == 1000)
		{
			_maintenanceZdoRecordsPerScan.Value = 5000;
			flag = true;
		}
		if (flag && _log != null)
		{
			_log.LogInfo((object)"[ownership scan] Migrated 1.0.4 default scan budgets to initial=25000/5s and maintenance=5000/15s.");
		}
	}

	private static long GetCurrentWorldUid()
	{
		try
		{
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return 0L;
			}
			MethodInfo methodInfo = AccessTools.Method(typeof(ZNet), "GetWorldUID", Type.EmptyTypes, (Type[])null);
			if (methodInfo == null)
			{
				if (_log != null)
				{
					_log.LogWarning((object)"[ownership cache] ZNet.GetWorldUID is unavailable; verified maintenance mode remains locked.");
				}
				return 0L;
			}
			object obj = methodInfo.Invoke(ZNet.instance, null);
			return (obj == null) ? 0 : Convert.ToInt64(obj);
		}
		catch (Exception ex)
		{
			if (_log != null)
			{
				_log.LogWarning((object)("[ownership cache] Could not resolve current world UID; verified maintenance mode remains locked: " + ex.Message));
			}
			return 0L;
		}
	}

	private static bool EnsureOwnershipCacheWorldIdentity()
	{
		long currentWorldUid = GetCurrentWorldUid();
		if (currentWorldUid == 0L)
		{
			_ownershipCacheWorldValidated = false;
			return false;
		}
		if (_ownershipCacheWorldValidated && _cachedOwnershipWorldUid == currentWorldUid)
		{
			return true;
		}
		if (_cachedOwnershipWorldUid != 0L && _cachedOwnershipWorldUid != currentWorldUid)
		{
			if (_log != null)
			{
				_log.LogInfo((object)"[ownership cache] Cached ownership state belongs to another world; clearing cached ownership data and restarting the heavy initial scan.");
			}
			_ownershipCache.Clear();
			_ownershipCacheScanIndex = 0;
			_cachedZdoScanIndex = 0;
			_cachedZdoScanObjectCount = 0;
			_zdoBroadScanPassesCompleted = 0;
			_cachedZdoScanUpdatedUnixSeconds = 0L;
			_initialBroadScanComplete = false;
			_initialBroadScanTraversalComplete = false;
			_pendingInitialBroadScanCompletion = false;
			_deferredOwnershipClaims.Clear();
			_deferredOwnershipClaimSet.Clear();
			_loadedZdoScanCursorPending = false;
			_ownershipCacheWarmStartComplete = false;
			_ownershipCacheDirty = true;
		}
		_cachedOwnershipWorldUid = currentWorldUid;
		_ownershipCacheWorldValidated = true;
		_ownershipCacheDirty = true;
		return true;
	}

	private static void CommitInitialBroadScanCompletion(int objectCount)
	{
		if (!_pendingInitialBroadScanCompletion || _initialBroadScanComplete || !_initialBroadScanTraversalComplete || _deferredOwnershipClaims.Count > 0 || !EnsureOwnershipCacheWorldIdentity())
		{
			return;
		}
		_cachedZdoScanIndex = 0;
		_cachedZdoScanObjectCount = objectCount;
		_cachedZdoScanUpdatedUnixSeconds = GetUnixSeconds();
		_initialBroadScanComplete = true;
		MarkOwnershipCacheDirty();
		if (!FlushOwnershipCache(force: true))
		{
			_initialBroadScanComplete = false;
			_pendingInitialBroadScanCompletion = true;
			MarkOwnershipCacheDirty();
			if (_log != null)
			{
				_log.LogWarning((object)"[ownership scan] Initial traversal and deferred claims completed, but durable cache commit failed; maintenance remains locked.");
			}
			return;
		}
		_pendingInitialBroadScanCompletion = false;
		if (_log != null)
		{
			_log.LogInfo((object)("[ownership scan] First broad ZDO scan reached 100%, deferred ownership claims are drained, and state was durably persisted for worldUid=" + _cachedOwnershipWorldUid + ". Switching to maintenance mode: interval=" + GetOwnershipScanIntervalSeconds() + "s, zdoRecordsPerScan=" + GetZdoRecordsPerScan() + "."));
		}
	}

	private static Dictionary<ZDOID, ZDO> GetObjectsById()
	{
		if (_objectsByIdField == null)
		{
			_objectsByIdField = AccessTools.Field(typeof(ZDOMan), "m_objectsByID");
			if (_objectsByIdField == null)
			{
				if (_log != null)
				{
					_log.LogWarning((object)"[dev ownership] Could not find ZDOMan.m_objectsByID; direct ZDO ownership scan is unavailable.");
				}
				return null;
			}
		}
		return _objectsByIdField.GetValue(ZDOMan.instance) as Dictionary<ZDOID, ZDO>;
	}

	private static void ApplyCachedZdoScanCursor(int currentObjectCount)
	{
		if (_loadedZdoScanCursorPending && _cachedZdoScanIndex > 0 && _resumeZdoScanFromCache != null && _resumeZdoScanFromCache.Value)
		{
			int num = _cachedZdoScanIndex;
			if (currentObjectCount > 0)
			{
				num = Mathf.Clamp(num, 0, currentObjectCount - 1);
			}
			_zdoScanIndex = num;
			if (_log != null)
			{
				_log.LogInfo((object)("[ownership cache] Resuming broad ZDO scan at index " + _zdoScanIndex + " from cached index " + _cachedZdoScanIndex + " with currentObjectCount=" + currentObjectCount + ", cachedObjectCount=" + _cachedZdoScanObjectCount + "."));
			}
			_loadedZdoScanCursorPending = false;
			_cachedZdoScanIndex = 0;
		}
	}

	private static void ValidateCachedScanPassState(int currentObjectCount)
	{
		if (_zdoBroadScanPassesCompleted <= 0 || _cachedZdoScanObjectCount <= 0 || currentObjectCount <= 0)
		{
			return;
		}
		int num = Mathf.Abs(currentObjectCount - _cachedZdoScanObjectCount);
		int num2 = Mathf.Max(10000, _cachedZdoScanObjectCount / 10);
		if (num > num2)
		{
			if (_log != null)
			{
				_log.LogInfo((object)("[ownership cache] Cached broad-scan pass count was reset because the world ZDO count changed from " + _cachedZdoScanObjectCount + " to " + currentObjectCount + "."));
			}
			_zdoBroadScanPassesCompleted = 0;
			_initialBroadScanComplete = false;
			_pendingInitialBroadScanCompletion = false;
			_cachedZdoScanObjectCount = currentObjectCount;
			_cachedZdoScanUpdatedUnixSeconds = GetUnixSeconds();
			_ownershipCacheDirty = true;
		}
	}

	private static void PersistZdoScanCursor(int objectCount)
	{
		if (_enableOwnershipCache != null && _enableOwnershipCache.Value && _resumeZdoScanFromCache != null && _resumeZdoScanFromCache.Value)
		{
			_cachedZdoScanIndex = _zdoScanIndex;
			_cachedZdoScanObjectCount = objectCount;
			_cachedZdoScanUpdatedUnixSeconds = GetUnixSeconds();
			_ownershipCacheDirty = true;
			if (_nextOwnershipCacheFlushTime <= 0f)
			{
				_nextOwnershipCacheFlushTime = Time.realtimeSinceStartup + 30f;
			}
		}
	}

	private static void ApplyOwnershipCacheWarmStart()
	{
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		if (_ownershipCacheWarmStartComplete || !_enableOwnershipCache.Value)
		{
			return;
		}
		if (_ownershipCache.Count == 0)
		{
			_ownershipCacheWarmStartComplete = true;
			return;
		}
		Dictionary<ZDOID, ZDO> objectsById = GetObjectsById();
		if (objectsById == null || objectsById.Count == 0)
		{
			return;
		}
		if (_ownershipCacheScanIndex >= _ownershipCache.Count)
		{
			_ownershipCacheScanIndex = 0;
		}
		List<OwnershipCacheEntry> list = new List<OwnershipCacheEntry>(_ownershipCache.Values);
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		int value = _ownershipCacheRecordsPerScan.Value;
		int value2 = _maxCacheRestoresPerScan.Value;
		List<string> list2 = null;
		foreach (OwnershipCacheEntry item in list)
		{
			if (num++ < _ownershipCacheScanIndex)
			{
				continue;
			}
			if (num2 >= value || num3 >= value2)
			{
				break;
			}
			num2++;
			_cacheRecordsChecked++;
			ZDO value3;
			if (!TryParseZdoId(item.Uid, out var id))
			{
				if (list2 == null)
				{
					list2 = new List<string>();
				}
				list2.Add(item.Uid);
			}
			else if (objectsById.TryGetValue(id, out value3) && TryRestoreCachedOwnership(value3))
			{
				num3++;
			}
		}
		if (list2 != null)
		{
			for (int i = 0; i < list2.Count; i++)
			{
				RemoveOwnershipCacheEntry(list2[i]);
			}
		}
		_ownershipCacheScanIndex += num2;
		if (_ownershipCacheScanIndex >= list.Count || num2 == 0)
		{
			_ownershipCacheWarmStartComplete = true;
			_ownershipCacheScanIndex = 0;
			if (_log != null)
			{
				_log.LogInfo((object)("[ownership cache] Direct warm-start complete. cacheEntries=" + _ownershipCache.Count + ", totalCacheRestored=" + _totalCacheRestored + ", removed=" + _cacheRemoved + "."));
			}
			FlushOwnershipCache(force: false);
		}
	}

	private static bool TryRestoreCachedOwnership(ZDO zdo)
	{
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		if (zdo == null || !zdo.IsValid())
		{
			return false;
		}
		string text = ((object)Unsafe.As<ZDOID, ZDOID>(ref zdo.m_uid)/*cast due to .constrained prefix*/).ToString();
		if (!_ownershipCache.TryGetValue(text, out var value))
		{
			return false;
		}
		if (!zdo.Persistent || zdo.GetPrefab() != value.PrefabHash)
		{
			RemoveOwnershipCacheEntry(text);
			return false;
		}
		long num = zdo.GetLong(ZDOVars.s_creator, 0L);
		if (_playerBuiltPiecesOnly.Value && num == 0L)
		{
			RemoveOwnershipCacheEntry(text);
			return false;
		}
		if (value.Creator != 0L && num != value.Creator)
		{
			RemoveOwnershipCacheEntry(text);
			return false;
		}
		GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(value.PrefabHash) : null);
		if ((Object)(object)val != (Object)null && !IsEligibleStaticPiecePrefab(value.PrefabHash, val))
		{
			RemoveOwnershipCacheEntry(text);
			return false;
		}
		long sessionID = ZDOMan.GetSessionID();
		long owner = zdo.GetOwner();
		if (owner == sessionID)
		{
			RecordOwnershipCache(zdo, value.PrefabName, num);
			return false;
		}
		if (_dryRunStaticPieceServerOwnership.Value)
		{
			_claimed++;
			_totalClaimed++;
			_cacheRestored++;
			_totalCacheRestored++;
			LogClaim("DRY-RUN cache would claim", value.PrefabName, zdo, owner, num, "ownership-cache");
			return true;
		}
		zdo.SetOwner(sessionID);
		ZDOMan.instance.ForceSendZDO(zdo.m_uid);
		_claimed++;
		_totalClaimed++;
		_cacheRestored++;
		_totalCacheRestored++;
		RecordOwnershipCache(zdo, value.PrefabName, num);
		LogClaim("Cache-claimed", value.PrefabName, zdo, owner, num, "ownership-cache");
		return true;
	}

	private static bool TryParseZdoId(string uid, out ZDOID id)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		id = ZDOID.None;
		if (string.IsNullOrEmpty(uid))
		{
			return false;
		}
		int num = uid.IndexOf(':');
		if (num <= 0 || num >= uid.Length - 1)
		{
			return false;
		}
		if (!long.TryParse(uid.Substring(0, num), out var result) || !uint.TryParse(uid.Substring(num + 1), out var result2))
		{
			return false;
		}
		id = new ZDOID(result, result2);
		return true;
	}

	private static void RecordOwnershipCache(ZDO zdo, string prefabName, long creator)
	{
		if (_enableBackgroundOwnershipAudit == null || !_enableBackgroundOwnershipAudit.Value || _enableOwnershipCache == null || !_enableOwnershipCache.Value || _dryRunStaticPieceServerOwnership.Value || zdo == null || !zdo.IsValid())
		{
			return;
		}
		int prefab = zdo.GetPrefab();
		if (prefab != 0)
		{
			string text = ((object)Unsafe.As<ZDOID, ZDOID>(ref zdo.m_uid)/*cast due to .constrained prefix*/).ToString();
			_ownershipCache[text] = new OwnershipCacheEntry
			{
				Uid = text,
				PrefabHash = prefab,
				Creator = creator,
				PrefabName = CleanPrefabName(prefabName),
				StoredUnixSeconds = GetUnixSeconds()
			};
			_ownershipCacheDirty = true;
			if (_nextOwnershipCacheFlushTime <= 0f)
			{
				_nextOwnershipCacheFlushTime = Time.realtimeSinceStartup + 30f;
			}
		}
	}

	private static void RemoveOwnershipCacheEntry(string uid)
	{
		if (_ownershipCache.Remove(uid))
		{
			_cacheRemoved++;
			_ownershipCacheDirty = true;
		}
	}

	private static void LoadOwnershipCache()
	{
		_ownershipCacheWarmStartComplete = true;
		if (_enableOwnershipCache == null || !_enableOwnershipCache.Value)
		{
			return;
		}
		_ownershipCachePath = Path.Combine(Paths.ConfigPath, "r4v9n1.terramizerserver.ownership-cache.tsv");
		_ownershipCacheWarmStartComplete = false;
		if (!File.Exists(_ownershipCachePath))
		{
			if (_log != null)
			{
				_log.LogInfo((object)"[ownership cache] No ownership cache found yet. It will be created as pieces are claimed.");
			}
			return;
		}
		_deferredOwnershipClaims.Clear();
		_deferredOwnershipClaimSet.Clear();
		long unixSeconds = GetUnixSeconds();
		long num = (long)(_ownershipCacheMaxAgeHours.Value * 3600f);
		int num2 = 0;
		int num3 = 0;
		try
		{
			string[] array = File.ReadAllLines(_ownershipCachePath);
			foreach (string text in array)
			{
				if (string.IsNullOrEmpty(text))
				{
					continue;
				}
				if (text[0] == '#')
				{
					ReadOwnershipCacheMetadata(text);
					continue;
				}
				string[] array2 = text.Split(new char[1] { '\t' });
				if (array2.Length >= 5 && int.TryParse(array2[1], out var result) && long.TryParse(array2[2], out var result2) && long.TryParse(array2[4], out var result3))
				{
					if (unixSeconds - result3 > num)
					{
						num3++;
						continue;
					}
					_ownershipCache[array2[0]] = new OwnershipCacheEntry
					{
						Uid = array2[0],
						PrefabHash = result,
						Creator = result2,
						PrefabName = array2[3],
						StoredUnixSeconds = result3
					};
					num2++;
				}
			}
		}
		catch (Exception ex)
		{
			_ownershipCache.Clear();
			_cachedOwnershipWorldUid = 0L;
			_initialBroadScanComplete = false;
			_initialBroadScanTraversalComplete = false;
			_pendingInitialBroadScanCompletion = false;
			_deferredOwnershipClaims.Clear();
			_deferredOwnershipClaimSet.Clear();
			_ownershipCacheWorldValidated = false;
			_ownershipCacheWarmStartComplete = true;
			if (_log != null)
			{
				_log.LogWarning((object)("[ownership cache] Could not load ownership cache; continuing with normal scan: " + ex.Message));
			}
			return;
		}
		if (num3 > 0)
		{
			_ownershipCacheDirty = true;
			_cacheRemoved += num3;
		}
		if (_cachedZdoScanUpdatedUnixSeconds > 0 && unixSeconds - _cachedZdoScanUpdatedUnixSeconds > num)
		{
			_cachedZdoScanIndex = 0;
			_cachedZdoScanObjectCount = 0;
			_zdoBroadScanPassesCompleted = 0;
			_initialBroadScanComplete = false;
			_initialBroadScanTraversalComplete = false;
			_pendingInitialBroadScanCompletion = false;
			_deferredOwnershipClaims.Clear();
			_deferredOwnershipClaimSet.Clear();
			_cachedZdoScanUpdatedUnixSeconds = 0L;
			_ownershipCacheDirty = true;
		}
		if (_zdoBroadScanPassesCompleted < 0)
		{
			_zdoBroadScanPassesCompleted = 0;
			_ownershipCacheDirty = true;
		}
		_ownershipCacheWorldValidated = false;
		_pendingInitialBroadScanCompletion = _initialBroadScanTraversalComplete && !_initialBroadScanComplete;
		_loadedZdoScanCursorPending = _cachedZdoScanIndex > 0;
		if (_log != null)
		{
			_log.LogInfo((object)("[ownership cache] Loaded " + num2 + " cached ownership records from " + _ownershipCachePath + ((num3 > 0) ? (" and expired " + num3 + ".") : ".") + " scanIndex=" + _cachedZdoScanIndex + ", scanObjectCount=" + _cachedZdoScanObjectCount + ", scanPassesCompleted=" + _zdoBroadScanPassesCompleted + ", worldUid=" + _cachedOwnershipWorldUid + ", initialBroadScanTraversalComplete=" + _initialBroadScanTraversalComplete + ", initialBroadScanComplete=" + _initialBroadScanComplete + ", deferredClaims=" + _deferredOwnershipClaims.Count + "."));
		}
	}

	private static bool FlushOwnershipCache(bool force)
	{
		if (_enableOwnershipCache == null || !_enableOwnershipCache.Value || string.IsNullOrEmpty(_ownershipCachePath) || (!_ownershipCacheDirty && !force))
		{
			return false;
		}
		try
		{
			string directoryName = Path.GetDirectoryName(_ownershipCachePath);
			if (!string.IsNullOrEmpty(directoryName))
			{
				Directory.CreateDirectory(directoryName);
			}
			string text = _ownershipCachePath + ".tmp";
			using (StreamWriter streamWriter = new StreamWriter(text, append: false, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)))
			{
				streamWriter.WriteLine("# TerramizerServer ownership cache v1");
				streamWriter.WriteLine("# scanIndex\t" + _cachedZdoScanIndex);
				streamWriter.WriteLine("# scanObjectCount\t" + _cachedZdoScanObjectCount);
				streamWriter.WriteLine("# scanPassesCompleted\t" + _zdoBroadScanPassesCompleted);
				streamWriter.WriteLine("# scanUpdatedUnixSeconds\t" + _cachedZdoScanUpdatedUnixSeconds);
				streamWriter.WriteLine("# worldUid\t" + _cachedOwnershipWorldUid);
				streamWriter.WriteLine("# initialBroadScanTraversalComplete\t" + _initialBroadScanTraversalComplete);
				streamWriter.WriteLine("# initialBroadScanComplete\t" + _initialBroadScanComplete);
				foreach (string deferredOwnershipClaim in _deferredOwnershipClaims)
				{
					streamWriter.WriteLine("# deferredClaim\t" + deferredOwnershipClaim);
				}
				streamWriter.WriteLine("# uid\tprefabHash\tcreator\tprefabName\tstoredUnixSeconds");
				foreach (OwnershipCacheEntry value in _ownershipCache.Values)
				{
					streamWriter.Write(value.Uid);
					streamWriter.Write('\t');
					streamWriter.Write(value.PrefabHash);
					streamWriter.Write('\t');
					streamWriter.Write(value.Creator);
					streamWriter.Write('\t');
					streamWriter.Write(CleanPrefabName(value.PrefabName));
					streamWriter.Write('\t');
					streamWriter.WriteLine(value.StoredUnixSeconds);
				}
			}
			if (File.Exists(_ownershipCachePath))
			{
				File.Delete(_ownershipCachePath);
			}
			File.Move(text, _ownershipCachePath);
			_ownershipCacheDirty = false;
			_nextOwnershipCacheFlushTime = Time.realtimeSinceStartup + 30f;
			return true;
		}
		catch (Exception ex)
		{
			_nextOwnershipCacheFlushTime = Time.realtimeSinceStartup + 60f;
			if (_log != null)
			{
				_log.LogWarning((object)("[ownership cache] Could not save ownership cache; will retry later: " + ex.Message));
			}
			return false;
		}
	}

	private static void ReadOwnershipCacheMetadata(string line)
	{
		if (line.StartsWith("# scanIndex\t", StringComparison.Ordinal))
		{
			int.TryParse(line.Substring("# scanIndex\t".Length), out _cachedZdoScanIndex);
		}
		else if (line.StartsWith("# scanObjectCount\t", StringComparison.Ordinal))
		{
			int.TryParse(line.Substring("# scanObjectCount\t".Length), out _cachedZdoScanObjectCount);
		}
		else if (line.StartsWith("# scanPassesCompleted\t", StringComparison.Ordinal))
		{
			int.TryParse(line.Substring("# scanPassesCompleted\t".Length), out _zdoBroadScanPassesCompleted);
		}
		else if (line.StartsWith("# scanUpdatedUnixSeconds\t", StringComparison.Ordinal))
		{
			long.TryParse(line.Substring("# scanUpdatedUnixSeconds\t".Length), out _cachedZdoScanUpdatedUnixSeconds);
		}
		else if (line.StartsWith("# worldUid\t", StringComparison.Ordinal))
		{
			long.TryParse(line.Substring("# worldUid\t".Length), out _cachedOwnershipWorldUid);
		}
		else if (line.StartsWith("# initialBroadScanTraversalComplete\t", StringComparison.Ordinal))
		{
			bool.TryParse(line.Substring("# initialBroadScanTraversalComplete\t".Length), out _initialBroadScanTraversalComplete);
		}
		else if (line.StartsWith("# initialBroadScanComplete\t", StringComparison.Ordinal))
		{
			bool.TryParse(line.Substring("# initialBroadScanComplete\t".Length), out _initialBroadScanComplete);
		}
		else if (line.StartsWith("# deferredClaim\t", StringComparison.Ordinal))
		{
			string text = line.Substring("# deferredClaim\t".Length);
			if (!string.IsNullOrEmpty(text) && _deferredOwnershipClaimSet.Add(text))
			{
				_deferredOwnershipClaims.Enqueue(text);
			}
		}
	}

	private static long GetUnixSeconds()
	{
		return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
	}

	private static string CleanPrefabName(string prefabName)
	{
		if (string.IsNullOrEmpty(prefabName))
		{
			return "unknown";
		}
		return prefabName.Replace("(Clone)", string.Empty).Replace('\t', ' ').Replace('\r', ' ')
			.Replace('\n', ' ')
			.Trim();
	}

	private static bool TryClaimZdoRecord(ZDO zdo, string reason, bool allowOwnershipChange)
	{
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		_claimAttempts++;
		if (zdo == null || !zdo.IsValid())
		{
			_skippedNoZdo++;
			return false;
		}
		if (!zdo.Persistent)
		{
			_skippedNotPersistent++;
			return false;
		}
		int prefab = zdo.GetPrefab();
		if (prefab == 0)
		{
			_skippedNoPrefab++;
			return false;
		}
		GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab);
		if ((Object)(object)prefab2 == (Object)null)
		{
			_skippedNoPrefab++;
			return false;
		}
		if (!IsEligibleStaticPiecePrefab(prefab, prefab2))
		{
			_skippedNotPiecePrefab++;
			return false;
		}
		long num = zdo.GetLong(ZDOVars.s_creator, 0L);
		if (_playerBuiltPiecesOnly.Value && num == 0L)
		{
			_skippedNoCreator++;
			return false;
		}
		long sessionID = ZDOMan.GetSessionID();
		long owner = zdo.GetOwner();
		if (owner == sessionID)
		{
			_alreadyServerOwned++;
			RecordOwnershipCache(zdo, ((Object)prefab2).name, num);
			return false;
		}
		if (!allowOwnershipChange)
		{
			EnqueueDeferredOwnershipClaim(zdo);
			return false;
		}
		if (_dryRunStaticPieceServerOwnership.Value)
		{
			_claimed++;
			_totalClaimed++;
			LogClaim("DRY-RUN would claim", ((Object)prefab2).name, zdo, owner, num, reason);
			return true;
		}
		zdo.SetOwner(sessionID);
		ZDOMan.instance.ForceSendZDO(zdo.m_uid);
		_claimed++;
		_totalClaimed++;
		RecordOwnershipCache(zdo, ((Object)prefab2).name, num);
		LogClaim("Claimed", ((Object)prefab2).name, zdo, owner, num, reason);
		return true;
	}

	private static bool IsEligibleStaticPiecePrefab(int prefabHash, GameObject prefab)
	{
		if (_prefabEligibilityCache.TryGetValue(prefabHash, out var value))
		{
			return value;
		}
		Piece val = prefab.GetComponent<Piece>();
		if ((Object)(object)val == (Object)null)
		{
			val = prefab.GetComponentInChildren<Piece>(true);
		}
		value = (Object)(object)val != (Object)null;
		if (value && _requireWearNTear.Value && (Object)(object)prefab.GetComponent<WearNTear>() == (Object)null && (Object)(object)prefab.GetComponentInChildren<WearNTear>(true) == (Object)null)
		{
			value = false;
		}
		if (value && IsDynamicOrPhysicsObject(prefab))
		{
			value = false;
		}
		_prefabEligibilityCache[prefabHash] = value;
		return value;
	}

	private static bool IsDynamicOrPhysicsObject(GameObject root)
	{
		if ((Object)(object)root.GetComponentInChildren<Rigidbody>(true) != (Object)null)
		{
			return true;
		}
		if ((Object)(object)root.GetComponentInChildren<Ship>(true) != (Object)null)
		{
			return true;
		}
		if ((Object)(object)root.GetComponentInChildren<Vagon>(true) != (Object)null)
		{
			return true;
		}
		if ((Object)(object)root.GetComponentInChildren<ItemDrop>(true) != (Object)null)
		{
			return true;
		}
		if ((Object)(object)root.GetComponentInChildren<Character>(true) != (Object)null)
		{
			return true;
		}
		if ((Object)(object)root.GetComponentInChildren<Floating>(true) != (Object)null)
		{
			return true;
		}
		return false;
	}

	private static bool ShouldRunExperiment()
	{
		if (_enabled == null || !_enabled.Value || _enableStaticPieceServerOwnership == null || !_enableStaticPieceServerOwnership.Value)
		{
			return false;
		}
		if (_dedicatedOnly != null && _dedicatedOnly.Value && !Application.isBatchMode)
		{
			return false;
		}
		if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null)
		{
			return false;
		}
		return true;
	}

	private static void AdvertiseServerMetadata()
	{
		if (_enabled != null && _enabled.Value && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && ZNet.instance.m_serverSyncedPlayerData != null && (_dedicatedOnly == null || !_dedicatedOnly.Value || Application.isBatchMode) && (!_serverMetadataAdvertised || _metadataAdvertisedForInstance != ZNet.instance))
		{
			ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.version"] = "1.0.6";
			ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.staticOwnership"] = (_enableStaticPieceServerOwnership != null && _enableStaticPieceServerOwnership.Value).ToString();
			ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.ownershipCache"] = (_enableBackgroundOwnershipAudit != null && _enableBackgroundOwnershipAudit.Value && _enableOwnershipCache != null && _enableOwnershipCache.Value).ToString();
			ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.extendedTerrainLimits"] = (_enableExtendedTerrainLimits != null && _enableExtendedTerrainLimits.Value).ToString();
			ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.terrainRaiseLimit"] = GetTerrainRaiseLimitMeters().ToString(CultureInfo.InvariantCulture);
			ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.terrainDigLimit"] = GetTerrainDigLimitMeters().ToString(CultureInfo.InvariantCulture);
			if (!_serverMetadataAdvertised && _log != null)
			{
				_log.LogInfo((object)("Advertised TerramizerServer companion metadata to connecting clients. version=1.0.6, staticOwnership=" + ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.staticOwnership"] + ", ownershipCache=" + ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.ownershipCache"] + ", extendedTerrainLimits=" + ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.extendedTerrainLimits"] + ", terrainRaiseLimit=" + ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.terrainRaiseLimit"] + ", terrainDigLimit=" + ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.terrainDigLimit"] + "."));
			}
			_serverMetadataAdvertised = true;
			_metadataAdvertisedForInstance = ZNet.instance;
		}
	}

	private static void RegisterCompanionRpcsWhenReady()
	{
		if (ZRoutedRpc.instance != null && _registeredRoutedRpcInstance != ZRoutedRpc.instance)
		{
			ZRoutedRpc.instance.Register("r4v9n1.terramizerserver.RequestCompanionMetadata", (Action<long>)OnRequestCompanionMetadata);
			ZRoutedRpc.instance.Register("r4v9n1.terramizerserver.RequestCompanionMetadataV2", (Action<long>)OnRequestCompanionMetadataV2);
			_registeredRoutedRpcInstance = ZRoutedRpc.instance;
		}
	}

	private static void OnRequestCompanionMetadata(long sender)
	{
		if (_enabled != null && _enabled.Value && ZRoutedRpc.instance != null && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && (_dedicatedOnly == null || !_dedicatedOnly.Value || Application.isBatchMode))
		{
			bool flag = _enableStaticPieceServerOwnership != null && _enableStaticPieceServerOwnership.Value;
			bool flag2 = _enableBackgroundOwnershipAudit != null && _enableBackgroundOwnershipAudit.Value && _enableOwnershipCache != null && _enableOwnershipCache.Value;
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, "r4v9n1.terramizerserver.CompanionMetadata", new object[3] { "1.0.6", flag, flag2 });
			_companionRpcReplies++;
			if (!_companionRpcReplyLogged && _log != null)
			{
				_companionRpcReplyLogged = true;
				_log.LogInfo((object)("Answered Terramizer companion metadata RPC. version=1.0.6, staticOwnership=" + flag + ", ownershipCache=" + flag2 + "."));
			}
		}
	}

	private static void OnRequestCompanionMetadataV2(long sender)
	{
		if (_enabled != null && _enabled.Value && ZRoutedRpc.instance != null && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && (_dedicatedOnly == null || !_dedicatedOnly.Value || Application.isBatchMode))
		{
			bool flag = _enableStaticPieceServerOwnership != null && _enableStaticPieceServerOwnership.Value;
			bool flag2 = _enableBackgroundOwnershipAudit != null && _enableBackgroundOwnershipAudit.Value && _enableOwnershipCache != null && _enableOwnershipCache.Value;
			bool flag3 = _enableExtendedTerrainLimits != null && _enableExtendedTerrainLimits.Value;
			float terrainRaiseLimitMeters = GetTerrainRaiseLimitMeters();
			float terrainDigLimitMeters = GetTerrainDigLimitMeters();
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, "r4v9n1.terramizerserver.CompanionMetadataV2", new object[6] { "1.0.6", flag, flag2, flag3, terrainRaiseLimitMeters, terrainDigLimitMeters });
			_companionRpcReplies++;
		}
	}

	private static void LogOwnershipMaintenanceFailure(Exception ex)
	{
		if (!_ownershipMaintenanceFailureLogged && _log != null)
		{
			_ownershipMaintenanceFailureLogged = true;
			_log.LogWarning((object)("Optional ownership maintenance hit an error; vanilla server simulation continues and the next bounded pass will retry: " + ex.Message));
		}
	}

	private unsafe static void LogClaim(string action, string prefabName, ZDO zdo, long oldOwner, long creator, string reason)
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		if (_log != null)
		{
			bool flag = IsWatchedInteractivePrefab(prefabName);
			if (flag)
			{
				_watchedClaims++;
				_totalWatchedClaims++;
			}
			if ((_logDevClaims != null && _logDevClaims.Value) || (flag && _logWatchedClaims != null && _logWatchedClaims.Value))
			{
				ManualLogSource log = _log;
				string[] obj = new string[17]
				{
					"[dev ownership] ", action, " ", prefabName, " zdo=", null, null, null, null, null,
					null, null, null, null, null, null, null
				};
				ZDOID uid = zdo.m_uid;
				obj[5] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
				obj[6] = " oldOwner=";
				obj[7] = oldOwner.ToString();
				obj[8] = " newOwner=";
				obj[9] = zdo.GetOwner().ToString();
				obj[10] = " creator=";
				obj[11] = creator.ToString();
				obj[12] = " sector=";
				obj[13] = ((object)zdo.GetSector()/*cast due to .constrained prefix*/).ToString();
				obj[14] = " reason=";
				obj[15] = reason;
				obj[16] = ".";
				log.LogInfo((object)string.Concat(obj));
			}
		}
	}

	private static bool IsWatchedInteractivePrefab(string prefabName)
	{
		if (string.IsNullOrEmpty(prefabName))
		{
			return false;
		}
		string text = prefabName.ToLowerInvariant();
		if (!text.Contains("bed") && !text.Contains("chest") && !text.Contains("portal") && !text.Contains("fire") && !text.Contains("hearth") && !text.Contains("bonfire") && !text.Contains("workbench") && !text.Contains("forge") && !text.Contains("cauldron") && !text.Contains("fermenter") && !text.Contains("smelter") && !text.Contains("kiln") && !text.Contains("windmill") && !text.Contains("spinningwheel") && !text.Contains("eitrrefinery") && !text.Contains("blackforge") && !text.Contains("magetable") && !text.Contains("artisan") && !text.Contains("obliterator") && !text.Contains("sign") && !text.Contains("itemstand") && !text.Contains("armorstand") && !text.Contains("ward") && !text.Contains("guardstone") && !text.Contains("door") && !text.Contains("gate") && !text.Contains("cartography"))
		{
			return text.Contains("sapcollector");
		}
		return true;
	}

	private static void LogSkip(Piece piece, string reason)
	{
		if (_logDevSkips != null && _logDevSkips.Value && _log != null && !((Object)(object)piece == (Object)null))
		{
			_log.LogInfo((object)("[dev ownership] skipped " + ((Object)((Component)piece).gameObject).name + ": " + reason + "."));
		}
	}

	private static void LogOwnershipSummary()
	{
		if (_log != null)
		{
			long num = Take(ref _claimed);
			long num2 = Take(ref _watchedClaims);
			long num3 = Take(ref _skippedNoZdo) + Take(ref _skippedNoPrefab) + Take(ref _skippedNotPiecePrefab) + Take(ref _skippedNotPersistent) + Take(ref _skippedNoCreator) + Take(ref _skippedNoWearNTear) + Take(ref _skippedDynamic) + Take(ref _skippedNotReady);
			_log.LogInfo((object)("[dev ownership summary] claims=" + num + ", totalClaims=" + _totalClaimed + ", watchedClaims=" + num2 + ", totalWatchedClaims=" + _totalWatchedClaims + ", scanMode=" + (IsMaintenanceScanMode() ? "maintenance" : "warmup") + ", scanPasses=" + _zdoBroadScanPassesCompleted + ", scanInterval=" + GetOwnershipScanIntervalSeconds() + ", scanRecords=" + GetZdoRecordsPerScan() + ", scanClaimLimit=" + GetMaxClaimsPerScan() + ", cacheRestored=" + Take(ref _cacheRestored) + ", totalCacheRestored=" + _totalCacheRestored + ", cacheEntries=" + _ownershipCache.Count + ", cacheChecked=" + Take(ref _cacheRecordsChecked) + ", cacheRemoved=" + _cacheRemoved + ", deferredClaims=" + _deferredOwnershipClaims.Count + ", companionRpcReplies=" + Take(ref _companionRpcReplies) + ", zdoScanIndex=" + _zdoScanIndex + ", alreadyServerOwned=" + Take(ref _alreadyServerOwned) + ", skipped=" + num3 + ", checked=" + Take(ref _zdoRecordsChecked) + ", attempts=" + Take(ref _claimAttempts) + "."));
		}
	}

	private static long Take(ref long value)
	{
		long result = value;
		value = 0L;
		return result;
	}

	private void RemoveRetiredSettings()
	{
		Remove("General", "ServerOnly", defaultValue: true);
		Remove("General", "SafetyDefaultsVersion", 0);
		Remove("Streaming", "MaxSendQueueBytes", 16384);
		Remove("Streaming", "MinFreeSendQueueBytes", 4096);
		Remove("Streaming", "PeerSendIntervalSeconds", 0.05f);
		Remove("Streaming", "ZoneStreamingBoostExtraRadius", 0);
		Remove("Streaming", "ZoneStreamingBoostIncludeDistantZdos", defaultValue: true);
		Remove("Streaming", "LogZoneStreamingBoosts", defaultValue: false);
		Remove("Streaming", "StreamingUpdateIntervalSeconds", 0.5f);
		Remove("Diagnostics", "LogDenseSyncs", defaultValue: true);
		Remove("Diagnostics", "DenseSyncThreshold", 1000);
		Remove("Diagnostics", "DenseSyncLogIntervalSeconds", 30f);
		Remove("Diagnostics", "PauseExtraStreamingDuringDenseSync", defaultValue: true);
		Remove("Diagnostics", "DenseSyncPauseSeconds", 2f);
		Remove("Diagnostics", "DiagnosticIntervalSec", 60f);
		Remove("WorldObjects", "ExtendedZoneRadius", 0);
		Remove("WorldObjects", "CreateDestroyIntervalSeconds", 0.1f);
		Remove("WorldObjects", "RemoveObjectsIntervalSeconds", 0.5f);
		Remove("WorldObjects", "EnablePredictiveZoneStreaming", defaultValue: true);
		Remove("WorldObjects", "PredictionLookaheadSec", 3f);
		Remove("WorldObjects", "PredictionMinVelocity", 2f);
		Remove("WorldObjects", "PredictionMaxLookaheadZones", 9);
		Remove("WorldObjects", "EnableZDOThrottling", defaultValue: false);
		Remove("WorldObjects", "ZDOThrottleDistance", 500f);
		Remove("WorldObjects", "EnablePlayerPriority", defaultValue: true);
		Remove("ServerSimulation", "PeerZoneUpdateIntervalSeconds", 0.5f);
		Remove("ServerSimulation", "EnableMultiPeerOutsideActiveArea", defaultValue: true);
		Remove("ServerSimulation", "EnableHeadlessVisualGuards", defaultValue: true);
		Remove("ServerSimulation", "EnablePeerZoneCreation", defaultValue: false);
		Remove("ServerSimulation", "MaxPeerZoneCreationsPerPass", 1);
		Remove("ServerSimulation", "EnableServerOwnershipForPersistentZdos", defaultValue: false);
		Remove("ServerSimulation", "AllowExperimentalServerOwnershipForPersistentZdos", defaultValue: false);
		Remove("Performance", "ActivePlayerOwnershipBudgetMs", 0.35f);
		Remove("Performance", "IdleOwnershipBudgetMs", 2f);
		Remove("Performance", "MaintenanceFullAuditIntervalSeconds", 1800f);
		Remove("Sleep", "PauseExtraZoneWorkDuringSleep", defaultValue: true);
		Remove("Sleep", "LogSleepOptimizations", defaultValue: true);
		Remove("BuildInteractions", "RepairStaleWearNTearRemoveOwnership", defaultValue: true);
		Remove("BuildInteractions", "MaxRemoveRepairDistance", 8f);
		Remove("BuildInteractions", "LogRemoveOwnershipRepairs", defaultValue: true);
		Remove("ItemInteractions", "RepairStaleItemDropOwnership", defaultValue: true);
		Remove("ItemInteractions", "LogItemDropOwnershipRepairs", defaultValue: false);
		((BaseUnityPlugin)this).Config.Save();
	}

	private void Remove<T>(string section, string key, T defaultValue)
	{
		ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, "Retired for safety.");
		((BaseUnityPlugin)this).Config.Remove(((ConfigEntryBase)val).Definition);
	}

	private void BindTerrainCompatibilityConfig()
	{
		_enableExtendedTerrainLimits = ((BaseUnityPlugin)this).Config.Bind<bool>("Terrain", "EnableExtendedTerrainLimits", true, "Enable the dedicated-server terrain limit extension for compatible clients and local server authority.");
		_terrainRaiseLimitMeters = BindRange("Terrain", "TerrainRaiseLimitMeters", 16f, "Maximum terrain raise/level delta from original terrain.", 16f, 64f);
		_terrainDigLimitMeters = BindRange("Terrain", "TerrainDigLimitMeters", 16f, "Maximum terrain dig/lower delta from original terrain.", 16f, 64f);
	}

	internal static float GetTerrainRaiseLimitMeters()
	{
		if (_enableExtendedTerrainLimits == null || !_enableExtendedTerrainLimits.Value || _terrainRaiseLimitMeters == null)
		{
			return 8f;
		}
		return Mathf.Max(16f, _terrainRaiseLimitMeters.Value);
	}

	internal static float GetTerrainDigLimitMeters()
	{
		if (_enableExtendedTerrainLimits == null || !_enableExtendedTerrainLimits.Value || _terrainDigLimitMeters == null)
		{
			return 8f;
		}
		return Mathf.Max(16f, _terrainDigLimitMeters.Value);
	}

	internal static float GetTerrainDigThresholdMeters()
	{
		return Mathf.Max(0f, GetTerrainDigLimitMeters() - 0.05f);
	}
}
internal sealed class OwnershipCacheEntry
{
	public string Uid;

	public int PrefabHash;

	public long Creator;

	public string PrefabName;

	public long StoredUnixSeconds;
}
[HarmonyPatch(typeof(ZNetView), "Awake")]
internal static class ZNetViewAwakeStaticOwnershipPatch
{
	private static void Postfix(ZNetView __instance)
	{
		TerramizerServerPlugin.TryClaimFromZNetView(__instance, "znetview-awake");
	}
}
[HarmonyPatch(typeof(Heightmap), "AtMaxWorldLevelDepth")]
internal static class HeightmapAtMaxWorldLevelDepthTerrainLimitPatch
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		int replaced = 0;
		foreach (CodeInstruction instruction in instructions)
		{
			if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num && Math.Abs(num - 7.95f) < 0.0001f)
			{
				replaced++;
				yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), "GetTerrainDigThresholdMeters", (Type[])null, (Type[])null));
			}
			else
			{
				yield return instruction;
			}
		}
		if (replaced != 1)
		{
			throw new InvalidOperationException("Expected one Heightmap.AtMaxWorldLevelDepth terrain-limit constant, found " + replaced + ".");
		}
	}
}
[HarmonyPatch(typeof(Heightmap), "LevelTerrain")]
internal static class HeightmapLevelTerrainTerrainLimitPatch
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		int replaced = 0;
		foreach (CodeInstruction instruction in instructions)
		{
			if (instruction.opcode == OpCodes.Ldc_R8 && instruction.operand is double num && Math.Abs(num - 8.0) < 0.0001)
			{
				int num2 = replaced + 1;
				replaced = num2;
				if (num2 <= 2)
				{
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), (replaced == 1) ? "GetTerrainDigLimitMeters" : "GetTerrainRaiseLimitMeters", (Type[])null, (Type[])null));
					yield return new CodeInstruction(OpCodes.Conv_R8, (object)null);
					continue;
				}
			}
			yield return instruction;
		}
		if (replaced != 2)
		{
			throw new InvalidOperationException("Expected two Heightmap.LevelTerrain terrain-limit constants, found " + replaced + ".");
		}
	}
}
[HarmonyPatch(typeof(TerrainComp), "LevelTerrain")]
internal static class TerrainCompLevelTerrainLimitPatch
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		int replaced = 0;
		foreach (CodeInstruction instruction in instructions)
		{
			if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num && Math.Abs(num + 8f) < 0.0001f)
			{
				replaced++;
				yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), "GetTerrainDigLimitMeters", (Type[])null, (Type[])null));
				yield return new CodeInstruction(OpCodes.Neg, (object)null);
			}
			else if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num2 && Math.Abs(num2 - 8f) < 0.0001f)
			{
				replaced++;
				yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), "GetTerrainRaiseLimitMeters", (Type[])null, (Type[])null));
			}
			else
			{
				yield return instruction;
			}
		}
		if (replaced != 2)
		{
			throw new InvalidOperationException("Expected signed TerrainComp.LevelTerrain terrain-limit constants, found " + replaced + ".");
		}
	}
}
[HarmonyPatch(typeof(TerrainComp), "RaiseTerrain")]
internal static class TerrainCompRaiseTerrainLimitPatch
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		int replaced = 0;
		foreach (CodeInstruction instruction in instructions)
		{
			if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num && Math.Abs(num + 8f) < 0.0001f)
			{
				replaced++;
				yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), "GetTerrainDigLimitMeters", (Type[])null, (Type[])null));
				yield return new CodeInstruction(OpCodes.Neg, (object)null);
			}
			else if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num2 && Math.Abs(num2 - 8f) < 0.0001f)
			{
				replaced++;
				yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), "GetTerrainRaiseLimitMeters", (Type[])null, (Type[])null));
			}
			else
			{
				yield return instruction;
			}
		}
		if (replaced != 2)
		{
			throw new InvalidOperationException("Expected signed TerrainComp.RaiseTerrain terrain-limit constants, found " + replaced + ".");
		}
	}
}
[HarmonyPatch(typeof(TerrainComp), "ApplyToHeightmap")]
internal static class TerrainCompApplyToHeightmapTerrainLimitPatch
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		int replaced = 0;
		foreach (CodeInstruction instruction in instructions)
		{
			if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num && Math.Abs(num + 8f) < 0.0001f)
			{
				replaced++;
				yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), "GetTerrainDigLimitMeters", (Type[])null, (Type[])null));
				yield return new CodeInstruction(OpCodes.Neg, (object)null);
			}
			else if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num2 && Math.Abs(num2 - 8f) < 0.0001f)
			{
				replaced++;
				yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), "GetTerrainRaiseLimitMeters", (Type[])null, (Type[])null));
			}
			else
			{
				yield return instruction;
			}
		}
		if (replaced != 2)
		{
			throw new InvalidOperationException("Expected signed TerrainComp.ApplyToHeightmap terrain-limit constants, found " + replaced + ".");
		}
	}
}
[HarmonyPatch(typeof(VisEquipment), "UpdateEquipmentVisuals")]
internal static class VisEquipmentIntCachePatch
{
	private static readonly MethodInfo ZdoGetInt = AccessTools.Method(typeof(ZDO), "GetInt", new Type[2]
	{
		typeof(int),
		typeof(int)
	}, (Type[])null);

	private static readonly MethodInfo GetCachedIntMethod = AccessTools.Method(typeof(VisEquipmentIntCachePatch), "GetCachedInt", (Type[])null, (Type[])null);

	private static readonly FieldRef<Dictionary<ZDOID, BinarySearchDictionary<int, int>>> IntTables = AccessTools.StaticFieldRefAccess<Dictionary<ZDOID, BinarySearchDictionary<int, int>>>(AccessTools.Field(typeof(ZDOExtraData), "s_ints"));

	private static bool _transpilerFoundCall;

	[ThreadStatic]
	private static BinarySearchDictionary<int, int> _currentTable;

	private static BinarySearchDictionary<int, int> CurrentTable => _currentTable;

	private static void Prefix(VisEquipment __instance, out BinarySearchDictionary<int, int> __state)
	{
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		__state = _currentTable;
		_currentTable = null;
		if ((Object)(object)__instance == (Object)null)
		{
			return;
		}
		ZNetView val = (((Object)(object)__instance.m_nViewOverride != (Object)null) ? __instance.m_nViewOverride : ((Component)__instance).GetComponent<ZNetView>());
		if (!((Object)(object)val == (Object)null))
		{
			ZDO zDO = val.GetZDO();
			if (zDO != null)
			{
				IntTables.Invoke()?.TryGetValue(zDO.m_uid, out _currentTable);
			}
		}
	}

	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		if (ZdoGetInt == null || GetCachedIntMethod == null)
		{
			throw new MissingMethodException("VisEquipmentIntCachePatch could not resolve ZDO.GetInt(int, int).");
		}
		foreach (CodeInstruction instruction in instructions)
		{
			if (CodeInstructionExtensions.Calls(instruction, ZdoGetInt))
			{
				instruction.opcode = OpCodes.Call;
				instruction.operand = GetCachedIntMethod;
				_transpilerFoundCall = true;
			}
			yield return instruction;
		}
		if (!_transpilerFoundCall)
		{
			throw new InvalidOperationException("VisEquipment.UpdateEquipmentVisuals contained no ZDO.GetInt(int, int) calls.");
		}
	}

	private static Exception Finalizer(Exception __exception, BinarySearchDictionary<int, int> __state)
	{
		_currentTable = __state;
		return __exception;
	}

	private static int GetCachedInt(ZDO zdo, int hash, int defaultValue)
	{
		BinarySearchDictionary<int, int> currentTable = CurrentTable;
		if (currentTable != null)
		{
			return currentTable.GetValueOrDefault(hash, defaultValue);
		}
		if (zdo == null)
		{
			return defaultValue;
		}
		return zdo.GetInt(hash, defaultValue);
	}
}
[HarmonyPatch(typeof(ZDOMan), "ReleaseNearbyZDOS")]
internal static class ZdoOwnershipHandoffPatch
{
	private delegate bool IsInPeerActiveAreaDelegate(ZDOMan instance, Vector3 position, long uid);

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

	private static readonly IsInPeerActiveAreaDelegate IsInPeerActiveArea = CreateIsInPeerActiveAreaDelegate();

	private static IsInPeerActiveAreaDelegate CreateIsInPeerActiveAreaDelegate()
	{
		try
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(ZDOMan), "IsInPeerActiveArea", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				return null;
			}
			return (IsInPeerActiveAreaDelegate)methodInfo.CreateDelegate(typeof(IsInPeerActiveAreaDelegate));
		}
		catch
		{
			return null;
		}
	}

	private static bool OwnerIsInActiveArea(ZDOMan instance, Vector3 position, long owner)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		if (IsInPeerActiveArea == null)
		{
			return true;
		}
		return IsInPeerActiveArea(instance, position, owner);
	}

	private static bool Prefix(ZDOMan __instance, Vector3 refPosition, long uid)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (__instance == null || (Object)(object)ZNet.instance == (Object)null)
			{
				return true;
			}
			Vector2s zone = ZoneSystem.GetZone(refPosition);
			SimulationDistance syncedSimulationDistance = ZNet.instance.GetSyncedSimulationDistance();
			SimulationDistance val = default(SimulationDistance);
			((SimulationDistance)(ref val))..ctor(((SimulationDistance)(ref syncedSimulationDistance)).NearSimulationDistance, 0, ((SimulationDistance)(ref syncedSimulationDistance)).IsClassic);
			NearbyObjects.Clear();
			__instance.FindSectorObjects(zone, val, NearbyObjects, (List<ZDO>)null);
			bool flag = uid == ZDOMan.GetSessionID();
			for (int i = 0; i < NearbyObjects.Count; i++)
			{
				ZDO val2 = NearbyObjects[i];
				if (val2 == null || !val2.Persistent)
				{
					continue;
				}
				Vector3 position = val2.GetPosition();
				bool flag2 = val2.HasOwner();
				bool flag3;
				long num;
				if (flag)
				{
					flag3 = val2.IsOwner();
					num = ((flag3 || !flag2) ? 0 : val2.GetOwner());
				}
				else
				{
					num = (flag2 ? val2.GetOwner() : 0);
					flag3 = num == uid;
				}
				if (flag3)
				{
					if (!ZNetScene.InActiveArea(position, zone))
					{
						val2.SetOwner(0L);
					}
				}
				else if ((!flag2 || !OwnerIsInActiveArea(__instance, position, num)) && ZNetScene.InActiveArea(position, zone))
				{
					val2.SetOwner(uid);
				}
			}
			NearbyObjects.Clear();
			return false;
		}
		catch
		{
			NearbyObjects.Clear();
			return true;
		}
	}
}
[HarmonyPatch(typeof(ZPackage), "Write", new Type[] { typeof(ZPackage) })]
internal static class ZPackageWritePackagePatch
{
	private static readonly FieldRef<ZPackage, MemoryStream> Stream = AccessTools.FieldRefAccess<ZPackage, MemoryStream>("m_stream");

	private static readonly FieldRef<ZPackage, BinaryWriter> Writer = AccessTools.FieldRefAccess<ZPackage, BinaryWriter>("m_writer");

	private static bool Prefix(ZPackage __instance, ZPackage pkg)
	{
		if (__instance == null || pkg == null)
		{
			return true;
		}
		MemoryStream memoryStream = Stream.Invoke(pkg);
		BinaryWriter binaryWriter = Writer.Invoke(pkg);
		BinaryWriter binaryWriter2 = Writer.Invoke(__instance);
		if (memoryStream == null || binaryWriter == null || binaryWriter2 == null)
		{
			return true;
		}
		binaryWriter.Flush();
		memoryStream.Flush();
		if (!memoryStream.TryGetBuffer(out var buffer))
		{
			return true;
		}
		binaryWriter2.Write((int)memoryStream.Length);
		binaryWriter2.Write(buffer.Array, buffer.Offset, (int)memoryStream.Length);
		return false;
	}
}