Decompiled source of TerramizerServer v0.4.7

plugins/TerramizerServer/TerramizerServer.dll

Decompiled 12 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("TerramizerServer")]
[assembly: AssemblyFileVersion("0.4.7")]
[assembly: AssemblyCompany("R4V9N1")]
[assembly: AssemblyDescription("Created by R4V9N1")]
[assembly: AssemblyProduct("TerramizerServer")]
[assembly: AssemblyCopyright("Created by R4V9N1")]
[assembly: AssemblyMetadata("Creator", "Created by R4V9N1")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.4.7.0")]
namespace TerramizerServer;

[BepInPlugin("r4v9n1.terramizerserver", "TerramizerServer", "0.4.7")]
public sealed class TerramizerServerPlugin : BaseUnityPlugin
{
	private struct PeerMotionSample
	{
		public Vector3 Position;

		public Vector3 Velocity;

		public float Time;

		public PeerMotionSample(Vector3 position, Vector3 velocity, float time)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			Position = position;
			Velocity = velocity;
			Time = time;
		}
	}

	private struct PeerStreamingState
	{
		public bool HasZone;

		public Vector2i CurrentZone;

		public Vector2i PredictedZone;

		public float NextBoostTime;
	}

	private delegate void CreateObjectsDelegate(ZNetScene scene, List<ZDO> currentObjects, List<ZDO> distantObjects);

	private delegate void RemoveObjectsDelegate(ZNetScene scene, List<ZDO> currentObjects, List<ZDO> distantObjects);

	private delegate bool CreateLocalZonesDelegate(ZoneSystem zoneSystem, Vector3 refPoint);

	private delegate void WearNTearRemoveRpcDelegate(WearNTear instance, long sender, bool blockDrop);

	public const string PluginGuid = "r4v9n1.terramizerserver";

	public const string PluginName = "TerramizerServer";

	public const string PluginVersion = "0.4.7";

	public const string CreatorCredit = "Created by R4V9N1";

	internal const int VanillaMaxSendQueueBytes = 10240;

	internal const int VanillaMinFreeSendQueueBytes = 2048;

	internal const float VanillaPeerSendIntervalSeconds = 0.05f;

	private static ConfigEntry<bool> _enabled;

	private static ConfigEntry<bool> _serverOnly;

	private static ConfigEntry<bool> _dedicatedOnly;

	private static ConfigEntry<int> _safetyDefaultsVersion;

	private static ConfigEntry<int> _maxSendQueueBytes;

	private static ConfigEntry<int> _minFreeSendQueueBytes;

	private static ConfigEntry<float> _peerSendIntervalSeconds;

	private static ConfigEntry<bool> _enableServerZoneStreamingBoost;

	private static ConfigEntry<int> _zoneStreamingBoostExtraRadius;

	private static ConfigEntry<int> _maxZoneStreamingBoostZdosPerPeer;

	private static ConfigEntry<float> _zoneStreamingBoostCooldownSeconds;

	private static ConfigEntry<int> _zoneStreamingBoostMaxQueuePercent;

	private static ConfigEntry<bool> _zoneStreamingBoostIncludeDistantZdos;

	private static ConfigEntry<bool> _logZoneStreamingBoosts;

	private static ConfigEntry<bool> _logDenseSyncs;

	private static ConfigEntry<int> _denseSyncThreshold;

	private static ConfigEntry<float> _denseSyncLogIntervalSeconds;

	private static ConfigEntry<bool> _pauseExtraStreamingDuringDenseSync;

	private static ConfigEntry<float> _denseSyncPauseSeconds;

	private static ConfigEntry<int> _extendedZoneRadius;

	private static ConfigEntry<float> _createDestroyIntervalSeconds;

	private static ConfigEntry<float> _removeObjectsIntervalSeconds;

	private static ConfigEntry<bool> _enablePredictiveZoneStreaming;

	private static ConfigEntry<float> _predictionLookaheadSec;

	private static ConfigEntry<float> _predictionMinVelocity;

	private static ConfigEntry<int> _predictionMaxLookaheadZones;

	private static ConfigEntry<bool> _enableZDOThrottling;

	private static ConfigEntry<float> _zdoThrottleDistance;

	private static ConfigEntry<bool> _enablePlayerPriority;

	private static ConfigEntry<bool> _enablePeerZoneCreation;

	private static ConfigEntry<float> _peerZoneUpdateIntervalSeconds;

	private static ConfigEntry<int> _maxPeerZoneCreationsPerPass;

	private static ConfigEntry<bool> _enableMultiPeerOutsideActiveArea;

	private static ConfigEntry<bool> _enableServerOwnershipForPersistentZdos;

	private static ConfigEntry<bool> _allowExperimentalServerOwnershipForPersistentZdos;

	private static ConfigEntry<bool> _enableHeadlessVisualGuards;

	private static ConfigEntry<bool> _pauseExtraZoneWorkDuringSleep;

	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 ConfigEntry<bool> _logSleepOptimizations;

	private static ConfigEntry<bool> _repairStaleWearNTearRemoveOwnership;

	private static ConfigEntry<float> _maxRemoveRepairDistance;

	private static ConfigEntry<bool> _logRemoveOwnershipRepairs;

	private static ConfigEntry<bool> _repairStaleItemDropOwnership;

	private static ConfigEntry<bool> _logItemDropOwnershipRepairs;

	private static ConfigEntry<float> _diagnosticIntervalSec;

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

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

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

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

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

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

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

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

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

	private static readonly List<long> _stalePeerIds = new List<long>();

	private static readonly HashSet<ZDO> _seenZdos = new HashSet<ZDO>();

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

	private static readonly HashSet<Vector2i> _coverageZones = new HashSet<Vector2i>();

	private static readonly HashSet<Vector2i> _ttlRefreshZones = new HashSet<Vector2i>();

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

	private static readonly Dictionary<long, float> _lastDenseSyncLogTimes = new Dictionary<long, float>();

	private static readonly Dictionary<Type, FieldInfo> _netPeerFields = new Dictionary<Type, FieldInfo>();

	private static readonly Dictionary<long, PeerMotionSample> _peerMotion = new Dictionary<long, PeerMotionSample>();

	private static readonly Dictionary<long, PeerStreamingState> _peerStreamingStates = new Dictionary<long, PeerStreamingState>();

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

	private static readonly Dictionary<Type, FieldInfo> _forceSendFields = new Dictionary<Type, FieldInfo>();

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

	private static readonly List<KeyValuePair<int, int>> _densePrefabCountsSorted = new List<KeyValuePair<int, int>>();

	private static readonly int PlayerPrefabHash = StringExtensionMethods.GetStableHashCode("Player");

	private static ManualLogSource _log;

	private static CreateObjectsDelegate _createObjects;

	private static RemoveObjectsDelegate _removeObjects;

	private static CreateLocalZonesDelegate _createLocalZones;

	private static FieldInfo _routedRpcTargetPeerIdField;

	private static FieldInfo _routedRpcSenderPeerIdField;

	private static FieldInfo _routedRpcTargetZdoField;

	private static FieldInfo _routedRpcMethodHashField;

	private static FieldInfo _routedRpcParametersField;

	private static FieldInfo _envManSkipToTimeField;

	private static FieldInfo _envManTimeSkipSpeedField;

	private static FieldInfo _gameSaveTimerField;

	private static FieldInfo _zoneSystemZonesField;

	private static FieldInfo _zoneDataTtlField;

	private static FieldInfo _zNetSceneInstancesField;

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

	private static long _diagnosticStaleSceneInstancesRemoved;

	private static WearNTearRemoveRpcDelegate _wearNTearRemoveRpc;

	private Harmony _harmony;

	private static float _nextDiagnosticLogTime;

	private static float _nextPeerZoneCreateTime;

	private static float _nextCreateDestroyTime;

	private static float _nextRemoveObjectsTime;

	private static float _nextWarningLogTime;

	private static float _nextRemoveRepairWarningTime;

	private static float _nextSleepPauseLogTime;

	private static float _nextSleepBedCheckTime;

	private static float _denseSyncPauseUntil;

	private static bool _sleepBedPauseActive;

	private static int _nextZoneCreationCenter;

	private static long _diagnosticCreateDestroyPasses;

	private static long _diagnosticZoneCreateAttempts;

	private static long _diagnosticZoneCreateSuccesses;

	private static long _diagnosticBoostQueued;

	private static long _diagnosticBoostBackpressureSkips;

	private static long _diagnosticSyncDuplicatesRemoved;

	private static long _diagnosticItemDropOwnershipRepairs;

	private static long _diagnosticItemDropOwnershipRefreshes;

	private static long _diagnosticDensePressurePauses;

	private static long _diagnosticZoneTtlRefreshes;

	private static int _diagnosticMaxSyncList;

	private static int _diagnosticPeakSendQueue;

	private static HashSet<ZDOID> _syncForceSend;

	private static long _syncReceiverUid;

	private static Vector3 _syncReceiverRefPos;

	private static bool _syncPlayerPriority;

	private void Awake()
	{
		//IL_076f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0779: Expected O, but got Unknown
		_log = ((BaseUnityPlugin)this).Logger;
		_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable TerramizerServer.");
		_serverOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ServerOnly", true, "Only run this plugin when this game instance is acting as a Valheim server.");
		_dedicatedOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DedicatedOnly", true, "Only run on the dedicated server process. Keep true for local/single-player testing.");
		_safetyDefaultsVersion = BindRange("General", "SafetyDefaultsVersion", 0, "Internal migration marker used when safer compatibility defaults change between releases.", 0, 4);
		_maxSendQueueBytes = BindRange("Streaming", "MaxSendQueueBytes", 16384, "Socket send queue ceiling used by ZDO streaming. Vanilla is 10240. This moderate increase avoids the long interactive-update delays seen with a 24576-byte ceiling in dense areas.", 2048, 262144);
		_minFreeSendQueueBytes = BindRange("Streaming", "MinFreeSendQueueBytes", 4096, "Minimum free socket queue space required before sending another ZDO packet. Vanilla is 2048.", 512, 131072);
		_peerSendIntervalSeconds = BindRange("Streaming", "PeerSendIntervalSeconds", 0.05f, "Seconds between ZDO send passes. The default preserves Valheim's cadence while allowing a moderately larger packet budget.", 0.01f, 0.25f);
		_enableServerZoneStreamingBoost = ((BaseUnityPlugin)this).Config.Bind<bool>("Streaming", "EnableServerZoneStreamingBoost", true, "When a player enters or approaches a new zone, queue nearby server-known ZDOs to that peer first. This improves area load-in without changing ZDO ownership.");
		_zoneStreamingBoostExtraRadius = BindRange("Streaming", "ZoneStreamingBoostExtraRadius", 0, "Extra zone rings around the player's current and predicted zone to force-send on zone entry. 0 keeps the boost inside vanilla active-area coverage.", 0, 3);
		_maxZoneStreamingBoostZdosPerPeer = BindRange("Streaming", "MaxZoneStreamingBoostZdosPerPeer", 128, "Maximum ZDOs to force-queue for one peer on a zone-entry streaming boost. A conservative cap prevents bulk objects from delaying ownership and interaction updates.", 0, 5000);
		_zoneStreamingBoostCooldownSeconds = BindRange("Streaming", "ZoneStreamingBoostCooldownSeconds", 1.5f, "Minimum seconds between zone-entry streaming boosts for the same peer.", 0.1f, 10f);
		_zoneStreamingBoostMaxQueuePercent = BindRange("Streaming", "ZoneStreamingBoostMaxQueuePercent", 35, "Do not add a zone-entry boost while the peer socket queue is above this percentage of MaxSendQueueBytes. The zone change is retried after the queue drains.", 10, 90);
		_zoneStreamingBoostIncludeDistantZdos = ((BaseUnityPlugin)this).Config.Bind<bool>("Streaming", "ZoneStreamingBoostIncludeDistantZdos", true, "Also force-queue distant ZDOs if the near-object boost has remaining room.");
		_logZoneStreamingBoosts = ((BaseUnityPlugin)this).Config.Bind<bool>("Streaming", "LogZoneStreamingBoosts", false, "Log each zone-entry streaming boost with peer name, zone, and queued ZDO count.");
		_logDenseSyncs = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "LogDenseSyncs", true, "Log when a peer has a large pending ZDO sync list.");
		_denseSyncThreshold = BindRange("Diagnostics", "DenseSyncThreshold", 1000, "Pending ZDO count that triggers a dense-area log line.", 100, 100000);
		_denseSyncLogIntervalSeconds = BindRange("Diagnostics", "DenseSyncLogIntervalSeconds", 30f, "Minimum seconds between dense-area log lines per peer.", 5f, 600f);
		_pauseExtraStreamingDuringDenseSync = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "PauseExtraStreamingDuringDenseSync", true, "Pause TerramizerServer's extra zone generation and zone-entry boosts while any peer already has at least DenseSyncThreshold pending objects.");
		_denseSyncPauseSeconds = BindRange("Diagnostics", "DenseSyncPauseSeconds", 2f, "How long to keep extra streaming paused after observing a dense pending sync list. Repeated dense lists extend the pause.", 0.5f, 30f);
		_extendedZoneRadius = BindRange("WorldObjects", "ExtendedZoneRadius", 0, "Additional zone layers the server preloads around each peer. 0 keeps vanilla radius while still combining all ready peers.", 0, 3);
		_createDestroyIntervalSeconds = BindRange("WorldObjects", "CreateDestroyIntervalSeconds", 0.1f, "Minimum time between combined multi-peer object create passes. This bounds repeated scans in object-dense bases.", 0.03f, 1f);
		_removeObjectsIntervalSeconds = BindRange("WorldObjects", "RemoveObjectsIntervalSeconds", 0.5f, "Minimum time between server instance removal scans. Object creation still runs at CreateDestroyIntervalSeconds.", 0.05f, 2f);
		_enablePredictiveZoneStreaming = ((BaseUnityPlugin)this).Config.Bind<bool>("WorldObjects", "EnablePredictiveZoneStreaming", true, "Bias each peer's active-area center forward along their velocity so the server loads ahead of movement.");
		_predictionLookaheadSec = BindRange("WorldObjects", "PredictionLookaheadSec", 3f, "Seconds ahead to project each peer before zone checks.", 0.5f, 10f);
		_predictionMinVelocity = BindRange("WorldObjects", "PredictionMinVelocity", 2f, "Minimum smoothed speed before prediction engages.", 0.5f, 20f);
		_predictionMaxLookaheadZones = BindRange("WorldObjects", "PredictionMaxLookaheadZones", 9, "Hard cap on prediction distance, in zones.", 1, 25);
		_enableZDOThrottling = ((BaseUnityPlugin)this).Config.Bind<bool>("WorldObjects", "EnableZDOThrottling", false, "Reduce send priority for far-away default-type ZDOs while preserving Valheim's terrain, solid, prioritized, and player ordering. Disabled by default because distant objects normally fall outside the near sync list.");
		_zdoThrottleDistance = BindRange("WorldObjects", "ZDOThrottleDistance", 500f, "Distance beyond which ordinary ZDOs are deprioritized during send sorting.", 0f, 1000f);
		_enablePlayerPriority = ((BaseUnityPlugin)this).Config.Bind<bool>("WorldObjects", "EnablePlayerPriority", true, "Boost player ZDOs ahead of bulk world objects during server send sorting.");
		_enablePeerZoneCreation = ((BaseUnityPlugin)this).Config.Bind<bool>("ServerSimulation", "EnablePeerZoneCreation", false, "Experimental: instantiate full local zones around every ready peer. Disabled by default because moving around a multi-zone base can repeatedly unload/reload dungeon-bearing edge zones; Valheim still performs its normal peer ghost-zone generation.");
		_peerZoneUpdateIntervalSeconds = BindRange("ServerSimulation", "PeerZoneUpdateIntervalSeconds", 0.5f, "Seconds between server-side peer zone creation passes. This avoids hundreds of no-op checks per minute after zones are warm.", 0.05f, 2f);
		_maxPeerZoneCreationsPerPass = BindRange("ServerSimulation", "MaxPeerZoneCreationsPerPass", 1, "Maximum current/predicted peer centers allowed to generate a new zone in one server update pass.", 1, 16);
		_enableMultiPeerOutsideActiveArea = ((BaseUnityPlugin)this).Config.Bind<bool>("ServerSimulation", "EnableMultiPeerOutsideActiveArea", true, "Treat a point as active when it is inside any ready peer's active area. This helps server-side systems work for split-up players.");
		_enableServerOwnershipForPersistentZdos = ((BaseUnityPlugin)this).Config.Bind<bool>("ServerSimulation", "EnableServerOwnershipForPersistentZdos", false, "Legacy dangerous option kept only for config migration. TerramizerServer no longer mass-transfers persistent ZDO ownership; use Streaming.EnableServerZoneStreamingBoost instead.");
		_allowExperimentalServerOwnershipForPersistentZdos = ((BaseUnityPlugin)this).Config.Bind<bool>("ServerSimulation", "AllowExperimentalServerOwnershipForPersistentZdos", false, "Legacy dangerous option kept only for config migration. It is ignored by this build.");
		_enableHeadlessVisualGuards = ((BaseUnityPlugin)this).Config.Bind<bool>("ServerSimulation", "EnableHeadlessVisualGuards", true, "Skip a few visual/audio-only systems on dedicated servers to avoid pointless headless work and log spam.");
		_pauseExtraZoneWorkDuringSleep = ((BaseUnityPlugin)this).Config.Bind<bool>("Sleep", "PauseExtraZoneWorkDuringSleep", true, "Temporarily disable TerramizerServer's extra peer-zone warming and zone-entry streaming boost while all connected characters are in bed or the server is skipping time.");
		_speedUpSleepFastForward = ((BaseUnityPlugin)this).Config.Bind<bool>("Sleep", "SpeedUpSleepFastForward", true, "Tune Valheim's sleep time-skip so the night passes in the configured number of real seconds.");
		_sleepFastForwardSeconds = BindRange("Sleep", "SleepFastForwardSeconds", 4f, "Target real seconds for the sleep time-skip. Lower is faster, but very low values can make time-based object catch-up spike after waking.", 1f, 60f);
		_skipSleepWorldSave = ((BaseUnityPlugin)this).Config.Bind<bool>("Sleep", "SkipSleepWorldSave", false, "Skip the extra world save Valheim runs when sleep ends. This is off by default to preserve vanilla durability and save-system compatibility.");
		_preserveAutosaveTimer = ((BaseUnityPlugin)this).Config.Bind<bool>("Sleep", "PreserveAutosaveTimer", true, "Keep Valheim's regular autosave timer unchanged while skipping the sleep-triggered world save.");
		_logSkippedSleepSaves = ((BaseUnityPlugin)this).Config.Bind<bool>("Sleep", "LogSkippedSleepSaves", true, "Log when TerramizerServer skips a sleep-triggered world save.");
		_logSleepOptimizations = ((BaseUnityPlugin)this).Config.Bind<bool>("Sleep", "LogSleepOptimizations", true, "Log when TerramizerServer speeds up sleep or pauses extra zone work for sleep.");
		_repairStaleWearNTearRemoveOwnership = ((BaseUnityPlugin)this).Config.Bind<bool>("BuildInteractions", "RepairStaleWearNTearRemoveOwnership", true, "Recover legitimate hammer deconstruct RPCs when a build piece is routed to a different, stale, disconnected, or inactive ZDO owner. The requester must be nearby, the piece must be removable, and no-build locations are rejected.");
		_maxRemoveRepairDistance = BindRange("BuildInteractions", "MaxRemoveRepairDistance", 8f, "Maximum 3D distance from the requesting player's reference position to a build piece before stale-remove ownership repair is refused.", 5f, 16f);
		_logRemoveOwnershipRepairs = ((BaseUnityPlugin)this).Config.Bind<bool>("BuildInteractions", "LogRemoveOwnershipRepairs", true, "Log when TerramizerServer repairs stale ownership for a build-piece remove RPC.");
		_repairStaleItemDropOwnership = ((BaseUnityPlugin)this).Config.Bind<bool>("ItemInteractions", "RepairStaleItemDropOwnership", true, "Let the server complete a nearby ItemDrop ownership request when food, pickup, or tame consumption is stuck on another owner route.");
		_logItemDropOwnershipRepairs = ((BaseUnityPlugin)this).Config.Bind<bool>("ItemInteractions", "LogItemDropOwnershipRepairs", false, "Log each server-assisted ItemDrop ownership transfer. Leave off normally because feeding and pickup can produce many requests.");
		_diagnosticIntervalSec = BindRange("Diagnostics", "DiagnosticIntervalSec", 60f, "Seconds between optional server status log lines.", 10f, 3600f);
		ClampConfig();
		ApplySafetyMigrations();
		_nextDiagnosticLogTime = Time.realtimeSinceStartup + Mathf.Clamp(_diagnosticIntervalSec.Value, 10f, 3600f);
		_createObjects = AccessTools.MethodDelegate<CreateObjectsDelegate>(AccessTools.Method(typeof(ZNetScene), "CreateObjects", (Type[])null, (Type[])null), (object)null, true);
		_removeObjects = AccessTools.MethodDelegate<RemoveObjectsDelegate>(AccessTools.Method(typeof(ZNetScene), "RemoveObjects", (Type[])null, (Type[])null), (object)null, true);
		_createLocalZones = CreateDelegateSafely<CreateLocalZonesDelegate>(typeof(ZoneSystem), "CreateLocalZones");
		_wearNTearRemoveRpc = CreateDelegateSafely<WearNTearRemoveRpcDelegate>(typeof(WearNTear), "RPC_Remove");
		InitializeRoutedRpcReflection();
		InitializeSleepReflection();
		InitializeZoneTtlReflection();
		InitializeZNetSceneReflection();
		_harmony = new Harmony("r4v9n1.terramizerserver");
		InstallPatches();
		((BaseUnityPlugin)this).Logger.LogInfo((object)("TerramizerServer 0.4.7 loaded. MaxQueue=" + _maxSendQueueBytes.Value + ", MinFree=" + _minFreeSendQueueBytes.Value + ", PeerInterval=" + _peerSendIntervalSeconds.Value + "s."));
		((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 Update()
	{
		if (CanRunOnServer())
		{
			MaybeLogDiagnostics();
		}
	}

	private void OnDestroy()
	{
		if (_harmony != null)
		{
			_harmony.UnpatchSelf();
			_harmony = null;
		}
	}

	private void InstallPatches()
	{
		bool num = HasPlugin("CW_Jesse.BetterNetworking") || HasPlugin("com.Fire.FiresGhettoNetworkMod") || HasPlugin("is.codex.valheim.zdostreamtuner");
		bool flag = HasPlugin("MVP.Valheim_Serverside_Simulations");
		if (num)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Detected another ZDO networking tuner. TerramizerServer will not replace send-queue constants or the send interval; its correctness and diagnostic patches remain active.");
		}
		else
		{
			PatchFeature(typeof(ZdoManSendZdosPatch), "ZDO queue limits");
			PatchFeature(typeof(ZdoManSendZdoToPeersPatch), "ZDO send interval");
		}
		if (!PatchFeature(typeof(ZdoManCreateSyncListPatch), "ZDO sync-list deduplication and priority") && _enableServerZoneStreamingBoost != null)
		{
			_enableServerZoneStreamingBoost.Value = false;
			((BaseUnityPlugin)this).Logger.LogError((object)"Disabled server zone streaming boost because sync-list deduplication could not be installed safely.");
		}
		PatchFeature(typeof(ZDOManServerSortSendZdosPatch), "server ZDO distance adjustment");
		PatchFeature(typeof(EnvManSkipToMorningPatch), "sleep fast-forward");
		PatchFeature(typeof(GameSleepStopPatch), "sleep save policy");
		PatchFeature(typeof(ZRoutedRpcHandleRoutedRpcPatch), "locally routed ownership recovery");
		PatchFeature(typeof(ZRoutedRpcRouteRpcPatch), "forwarded ownership recovery");
		PatchFeature(typeof(AudioManUpdateHeadlessPatch), "headless audio guard");
		PatchFeature(typeof(ShieldDomeImageEffectAwakeHeadlessPatch), "headless shield initialization guard");
		PatchFeature(typeof(ShieldDomeImageEffectGetDomeColorHeadlessPatch), "headless shield guard");
		if (flag)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Detected Valheim Serverside Simulations. TerramizerServer's overlapping multi-peer object/zone simulation patches are disabled to avoid double work and ownership conflicts.");
			return;
		}
		PatchFeature(typeof(ZNetSceneRemoveObjectsSafetyPatch), "stale ZNetScene instance sanitation");
		PatchFeature(typeof(ZNetSceneCreateDestroyObjectsPatch), "multi-peer object coverage");
		PatchFeature(typeof(ZoneSystemUpdatePeerZoneCreationPatch), "bounded peer zone creation");
		PatchFeature(typeof(ZNetSceneOutsideActiveAreaPeerPatch), "multi-peer active area");
		PatchFeature(typeof(ZdoManReleaseNearbyZdosServerOwnershipPatch), "legacy ownership migration");
	}

	private bool PatchFeature(Type patchType, string featureName)
	{
		try
		{
			_harmony.CreateClassProcessor(patchType).Patch();
			return true;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Disabled " + featureName + " because its Valheim patch no longer matched: " + ex.Message));
			return false;
		}
	}

	private static bool HasPlugin(string guid)
	{
		if (Chainloader.PluginInfos != null)
		{
			return Chainloader.PluginInfos.ContainsKey(guid);
		}
		return false;
	}

	internal static bool CanRunOnServer()
	{
		if (_enabled == null || !_enabled.Value)
		{
			return false;
		}
		try
		{
			ZNet instance = ZNet.instance;
			if (_dedicatedOnly != null && _dedicatedOnly.Value)
			{
				return (Object)(object)instance != (Object)null && instance.IsDedicated();
			}
			if (_serverOnly == null || !_serverOnly.Value)
			{
				return true;
			}
			return (Object)(object)instance != (Object)null && (instance.IsServer() || instance.IsDedicated());
		}
		catch
		{
			return false;
		}
	}

	internal static bool ShouldRunCreateDestroyObjects()
	{
		return CanRunOnServer();
	}

	internal static int GetMaxSendQueueBytes()
	{
		if (!CanRunOnServer())
		{
			return 10240;
		}
		if (_maxSendQueueBytes != null)
		{
			return _maxSendQueueBytes.Value;
		}
		return 10240;
	}

	internal static int GetMinFreeSendQueueBytes()
	{
		if (!CanRunOnServer())
		{
			return 2048;
		}
		if (_minFreeSendQueueBytes != null)
		{
			return _minFreeSendQueueBytes.Value;
		}
		return 2048;
	}

	internal static float GetPeerSendIntervalSeconds()
	{
		if (!CanRunOnServer())
		{
			return 0.05f;
		}
		if (_peerSendIntervalSeconds != null)
		{
			return _peerSendIntervalSeconds.Value;
		}
		return 0.05f;
	}

	internal static bool RunCreateDestroyObjects(ZNetScene scene)
	{
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		if (!ShouldRunCreateDestroyObjects())
		{
			return true;
		}
		bool flag = false;
		try
		{
			ZNet instance = ZNet.instance;
			ZoneSystem instance2 = ZoneSystem.instance;
			ZDOMan instance3 = ZDOMan.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || instance3 == null)
			{
				return true;
			}
			if (ShouldPauseExtraZoneWorkForSleep())
			{
				return true;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			float num = ((_createDestroyIntervalSeconds == null) ? 0.1f : Mathf.Clamp(_createDestroyIntervalSeconds.Value, 0.03f, 1f));
			if (realtimeSinceStartup < _nextCreateDestroyTime)
			{
				return false;
			}
			_nextCreateDestroyTime = realtimeSinceStartup + num;
			List<ZNetPeer> connectedPeers = instance.GetConnectedPeers();
			if (connectedPeers == null || connectedPeers.Count == 0)
			{
				return true;
			}
			int num2 = Mathf.Clamp(_extendedZoneRadius.Value, 0, 3);
			int num3 = Math.Max(1, instance2.m_activeArea + num2);
			int num4 = Math.Max(num3, instance2.m_activeDistantArea + num2);
			_nearScratch.Clear();
			_distantScratch.Clear();
			_coverageZones.Clear();
			bool flag2 = false;
			for (int i = 0; i < connectedPeers.Count; i++)
			{
				ZNetPeer val = connectedPeers[i];
				if (val != null && val.IsReady())
				{
					flag2 = true;
					Vector2i zone = ZoneSystem.GetZone(val.GetRefPos());
					Vector2i zone2 = ZoneSystem.GetZone(GetPredictedRefPos(val));
					if (_coverageZones.Add(zone))
					{
						instance3.FindSectorObjects(zone, num3, num4, _nearScratch, _distantScratch);
					}
					if (_coverageZones.Add(zone2))
					{
						instance3.FindSectorObjects(zone2, num3, num4, _nearScratch, _distantScratch);
					}
				}
			}
			if (!flag2)
			{
				return true;
			}
			_seenZdos.Clear();
			FilterAndDedupeZdos(_nearScratch, _nearFiltered);
			FilterAndDedupeZdos(_distantScratch, _distantFiltered);
			if (_createObjects != null)
			{
				_createObjects(scene, _nearFiltered, _distantFiltered);
			}
			float num5 = ((_removeObjectsIntervalSeconds == null) ? 0.5f : Mathf.Clamp(_removeObjectsIntervalSeconds.Value, num, 2f));
			if (_removeObjects != null && realtimeSinceStartup >= _nextRemoveObjectsTime)
			{
				_nextRemoveObjectsTime = realtimeSinceStartup + num5;
				flag = true;
				RepairStaleSceneInstances(scene);
				_removeObjects(scene, _nearFiltered, _distantFiltered);
				flag = false;
			}
			_diagnosticCreateDestroyPasses++;
			return false;
		}
		catch (Exception ex)
		{
			if (_log != null)
			{
				if (flag)
				{
					_log.LogWarning((object)("TerramizerServer RemoveObjects pass failed; suppressing vanilla retry for this frame: " + ex.Message));
				}
				else
				{
					_log.LogWarning((object)("TerramizerServer CreateDestroyObjects fell back to vanilla: " + ex.Message));
				}
			}
			return !flag;
		}
	}

	internal static void SortZdosForServer(List<ZDO> toSync, Vector3 refPos)
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		if (!CanRunOnServer() || toSync == null || toSync.Count == 0)
		{
			return;
		}
		float num = ((_enableZDOThrottling != null && _enableZDOThrottling.Value) ? Mathf.Max(0f, _zdoThrottleDistance.Value) : 0f);
		float num2 = num * num;
		for (int i = 0; i < toSync.Count; i++)
		{
			ZDO val = toSync[i];
			if (val != null && val.IsValid() && !(num2 <= 0f) && (int)val.Type == 0)
			{
				Vector3 position = val.GetPosition();
				float num3 = position.x - refPos.x;
				float num4 = position.z - refPos.z;
				if (num3 * num3 + num4 * num4 > num2)
				{
					val.m_tempSortValue += 500f;
				}
			}
		}
	}

	internal static void PostProcessSyncList(object zdoPeer, List<ZDO> toSync)
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		if (!CanRunOnServer() || zdoPeer == null || toSync == null)
		{
			return;
		}
		ZNetPeer netPeer = GetNetPeer(zdoPeer);
		HashSet<ZDOID> forceSendSet = GetForceSendSet(zdoPeer);
		_syncSeenZdos.Clear();
		int num = 0;
		int count = toSync.Count;
		for (int i = 0; i < count; i++)
		{
			ZDO val = toSync[i];
			if (val != null && val.IsValid() && !((ZDOID)(ref val.m_uid)).IsNone() && _syncSeenZdos.Add(val.m_uid))
			{
				toSync[num++] = val;
			}
		}
		if (num < count)
		{
			toSync.RemoveRange(num, count - num);
			_diagnosticSyncDuplicatesRemoved += count - num;
		}
		_syncForceSend = forceSendSet;
		_syncReceiverUid = netPeer?.m_uid ?? 0;
		_syncReceiverRefPos = ((netPeer == null) ? Vector3.zero : netPeer.GetRefPos());
		_syncPlayerPriority = _enablePlayerPriority != null && _enablePlayerPriority.Value;
		try
		{
			toSync.Sort(CompareFinalSyncZdos);
		}
		finally
		{
			_syncForceSend = null;
		}
		_diagnosticMaxSyncList = Math.Max(_diagnosticMaxSyncList, toSync.Count);
		if (netPeer != null && netPeer.m_socket != null)
		{
			_diagnosticPeakSendQueue = Math.Max(_diagnosticPeakSendQueue, netPeer.m_socket.GetSendQueueSize());
		}
		if (_pauseExtraStreamingDuringDenseSync != null && _pauseExtraStreamingDuringDenseSync.Value && _denseSyncThreshold != null && toSync.Count >= _denseSyncThreshold.Value)
		{
			float num2 = ((_denseSyncPauseSeconds == null) ? 2f : Mathf.Clamp(_denseSyncPauseSeconds.Value, 0.5f, 30f));
			_denseSyncPauseUntil = Math.Max(_denseSyncPauseUntil, Time.realtimeSinceStartup + num2);
		}
		MaybeLogDenseSync(zdoPeer, toSync);
	}

	private static int CompareFinalSyncZdos(ZDO left, ZDO right)
	{
		//IL_000d: 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_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Invalid comparison between Unknown and I4
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Invalid comparison between Unknown and I4
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Expected I4, but got Unknown
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Expected I4, but got Unknown
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		bool flag = _syncForceSend != null && _syncForceSend.Contains(left.m_uid);
		bool flag2 = _syncForceSend != null && _syncForceSend.Contains(right.m_uid);
		if (flag != flag2)
		{
			if (!flag)
			{
				return 1;
			}
			return -1;
		}
		if (_syncPlayerPriority)
		{
			int playerPrefabHash = GetPlayerPrefabHash();
			bool flag3 = left.GetPrefab() == playerPrefabHash;
			bool flag4 = right.GetPrefab() == playerPrefabHash;
			if (flag3 != flag4)
			{
				if (!flag3)
				{
					return 1;
				}
				return -1;
			}
		}
		bool flag5 = (int)left.Type == 1 && left.HasOwner() && left.GetOwner() != _syncReceiverUid;
		bool flag6 = (int)right.Type == 1 && right.HasOwner() && right.GetOwner() != _syncReceiverUid;
		if (flag5 != flag6)
		{
			if (!flag5)
			{
				return 1;
			}
			return -1;
		}
		if (left.Type != right.Type)
		{
			return ((int)right.Type).CompareTo((int)left.Type);
		}
		if (flag)
		{
			Vector3 val = left.GetPosition() - _syncReceiverRefPos;
			float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
			val = right.GetPosition() - _syncReceiverRefPos;
			float sqrMagnitude2 = ((Vector3)(ref val)).sqrMagnitude;
			return Utils.CompareFloats(sqrMagnitude, sqrMagnitude2);
		}
		return Utils.CompareFloats(left.m_tempSortValue, right.m_tempSortValue);
	}

	internal static void RunPeerZoneCreation(ZoneSystem zoneSystem)
	{
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0232: Unknown result type (might be due to invalid IL or missing references)
		if (!CanRunOnServer() || (Object)(object)zoneSystem == (Object)null)
		{
			return;
		}
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		float num = ((_peerZoneUpdateIntervalSeconds == null) ? 0.5f : Mathf.Clamp(_peerZoneUpdateIntervalSeconds.Value, 0.05f, 2f));
		if (realtimeSinceStartup < _nextPeerZoneCreateTime)
		{
			return;
		}
		_nextPeerZoneCreateTime = realtimeSinceStartup + num;
		RefreshLoadedPeerZoneTtls(zoneSystem);
		if (ShouldPauseExtraZoneWorkForSleep())
		{
			return;
		}
		if (_pauseExtraStreamingDuringDenseSync != null && _pauseExtraStreamingDuringDenseSync.Value && realtimeSinceStartup < _denseSyncPauseUntil)
		{
			_diagnosticDensePressurePauses++;
			return;
		}
		bool flag = _enablePeerZoneCreation != null && _enablePeerZoneCreation.Value && _createLocalZones != null;
		bool flag2 = IsZoneStreamingBoostEnabled();
		if (!flag && !flag2)
		{
			return;
		}
		try
		{
			ZNet instance = ZNet.instance;
			if ((Object)(object)instance == (Object)null || !instance.IsServer())
			{
				return;
			}
			ZDOMan instance2 = ZDOMan.instance;
			if (instance2 == null)
			{
				flag2 = false;
			}
			List<ZNetPeer> connectedPeers = instance.GetConnectedPeers();
			if (connectedPeers == null)
			{
				return;
			}
			_readyPeerIds.Clear();
			_coverageZones.Clear();
			_zoneCreationCenters.Clear();
			for (int i = 0; i < connectedPeers.Count; i++)
			{
				ZNetPeer val = connectedPeers[i];
				if (val == null || !val.IsReady())
				{
					continue;
				}
				_readyPeerIds.Add(val.m_uid);
				Vector3 refPos = val.GetRefPos();
				Vector3 predictedRefPos = GetPredictedRefPos(val);
				if (flag)
				{
					if (_coverageZones.Add(ZoneSystem.GetZone(refPos)))
					{
						_zoneCreationCenters.Add(refPos);
					}
					if (_coverageZones.Add(ZoneSystem.GetZone(predictedRefPos)))
					{
						_zoneCreationCenters.Add(predictedRefPos);
					}
				}
				if (flag2)
				{
					MaybeBoostPeerZoneStreaming(instance2, zoneSystem, val, predictedRefPos);
				}
			}
			if (flag && _zoneCreationCenters.Count > 0)
			{
				int num2 = ((_maxPeerZoneCreationsPerPass == null) ? 1 : Mathf.Clamp(_maxPeerZoneCreationsPerPass.Value, 1, 16));
				int num3 = _nextZoneCreationCenter % _zoneCreationCenters.Count;
				int num4 = 0;
				for (int j = 0; j < _zoneCreationCenters.Count; j++)
				{
					if (num4 >= num2)
					{
						break;
					}
					int index = (num3 + j) % _zoneCreationCenters.Count;
					_diagnosticZoneCreateAttempts++;
					if (_createLocalZones(zoneSystem, _zoneCreationCenters[index]))
					{
						num4++;
						_diagnosticZoneCreateSuccesses++;
					}
				}
				_nextZoneCreationCenter = (num3 + 1) % _zoneCreationCenters.Count;
			}
			PrunePeerTracking(_readyPeerIds);
		}
		catch (Exception ex)
		{
			LogWarningThrottled("Peer zone creation skipped after an error: " + ex.Message);
		}
	}

	internal static bool TryMultiPeerOutsideActiveArea(Vector3 point, ref bool result)
	{
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		if (!CanRunOnServer() || _enableMultiPeerOutsideActiveArea == null || !_enableMultiPeerOutsideActiveArea.Value)
		{
			return true;
		}
		if (ShouldPauseExtraZoneWorkForSleep())
		{
			return true;
		}
		try
		{
			ZNet instance = ZNet.instance;
			if ((Object)(object)instance == (Object)null || !instance.IsServer())
			{
				return true;
			}
			List<ZNetPeer> connectedPeers = instance.GetConnectedPeers();
			if (connectedPeers == null || connectedPeers.Count == 0)
			{
				return true;
			}
			ZoneSystem instance2 = ZoneSystem.instance;
			if ((Object)(object)instance2 == (Object)null)
			{
				return true;
			}
			bool flag = false;
			for (int i = 0; i < connectedPeers.Count; i++)
			{
				ZNetPeer val = connectedPeers[i];
				if (val != null && val.IsReady())
				{
					flag = true;
					int num = Math.Max(1, instance2.m_activeArea);
					Vector2i zone = ZoneSystem.GetZone(val.GetRefPos());
					if (!ZNetScene.OutsideActiveArea(point, zone, num))
					{
						result = false;
						return false;
					}
					Vector2i zone2 = ZoneSystem.GetZone(GetPredictedRefPos(val));
					if (!(zone2 == zone) && !ZNetScene.OutsideActiveArea(point, zone2, num))
					{
						result = false;
						return false;
					}
				}
			}
			if (!flag)
			{
				return true;
			}
			result = true;
			return false;
		}
		catch (Exception ex)
		{
			LogWarningThrottled("Multi-peer active-area check fell back to vanilla: " + ex.Message);
			return true;
		}
	}

	internal static void RunServerOwnershipForPersistentZdos(ZDOMan zdoMan, Vector3 refPosition)
	{
		if (_enableServerOwnershipForPersistentZdos != null && _enableServerOwnershipForPersistentZdos.Value)
		{
			_enableServerOwnershipForPersistentZdos.Value = false;
			if (_log != null)
			{
				_log.LogWarning((object)"Disabled legacy persistent-ZDO server ownership. TerramizerServer now uses server-side streaming boosts instead of mass ownership transfer.");
			}
		}
	}

	private static bool IsZoneStreamingBoostEnabled()
	{
		if (_enableServerZoneStreamingBoost != null && _enableServerZoneStreamingBoost.Value)
		{
			return !ShouldPauseExtraZoneWorkForSleep();
		}
		return false;
	}

	internal static void TuneSleepFastForward(EnvMan envMan)
	{
		if (!CanRunOnServer() || _speedUpSleepFastForward == null || !_speedUpSleepFastForward.Value || (Object)(object)envMan == (Object)null || !envMan.IsTimeSkipping())
		{
			return;
		}
		try
		{
			ZNet instance = ZNet.instance;
			if ((Object)(object)instance == (Object)null || !instance.IsServer())
			{
				return;
			}
			if (_envManSkipToTimeField == null || _envManTimeSkipSpeedField == null)
			{
				LogWarningThrottled("Sleep fast-forward tuning is unavailable because EnvMan sleep fields could not be found.");
				return;
			}
			double num = (double)_envManSkipToTimeField.GetValue(envMan) - instance.GetTimeSeconds();
			if (!(num <= 0.0))
			{
				float num2 = ((_sleepFastForwardSeconds == null) ? 4f : Mathf.Clamp(_sleepFastForwardSeconds.Value, 1f, 60f));
				double num3 = num / (double)num2;
				_envManTimeSkipSpeedField.SetValue(envMan, num3);
				if (_logSleepOptimizations != null && _logSleepOptimizations.Value && _log != null)
				{
					_log.LogInfo((object)("Sleep fast-forward tuned to about " + num2.ToString("0.##") + " real second(s)."));
				}
			}
		}
		catch (Exception ex)
		{
			LogWarningThrottled("Sleep fast-forward tuning failed: " + ex.Message);
		}
	}

	internal static void SavePlayerProfileFromSleep(Game game, bool setLogoutPoint)
	{
		if ((Object)(object)game == (Object)null)
		{
			return;
		}
		bool flag = ShouldSkipSleepWorldSave() && _preserveAutosaveTimer != null && _preserveAutosaveTimer.Value && _gameSaveTimerField != null;
		float num = 0f;
		if (flag)
		{
			try
			{
				num = (float)_gameSaveTimerField.GetValue(game);
			}
			catch (Exception ex)
			{
				flag = false;
				LogWarningThrottled("Could not read Game.m_saveTimer before sleep save: " + ex.Message);
			}
		}
		game.SavePlayerProfile(setLogoutPoint);
		if (!flag)
		{
			return;
		}
		try
		{
			_gameSaveTimerField.SetValue(game, num);
		}
		catch (Exception ex2)
		{
			LogWarningThrottled("Could not restore Game.m_saveTimer after sleep save: " + ex2.Message);
		}
	}

	internal static void SaveWorldFromSleep(ZNet znet, bool sync, bool saveOtherPlayerProfiles, bool waitForNextFrame)
	{
		if (!ShouldSkipSleepWorldSave())
		{
			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. The regular autosave schedule is unchanged.");
		}
	}

	private static bool ShouldSkipSleepWorldSave()
	{
		if (CanRunOnServer() && _skipSleepWorldSave != null)
		{
			return _skipSleepWorldSave.Value;
		}
		return false;
	}

	private unsafe static void MaybeBoostPeerZoneStreaming(ZDOMan zdoMan, ZoneSystem zoneSystem, ZNetPeer peer, Vector3 predictedRefPos)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_0202: Unknown result type (might be due to invalid IL or missing references)
		if (zdoMan == null || (Object)(object)zoneSystem == (Object)null || peer == null || !peer.IsReady())
		{
			return;
		}
		long uid = peer.m_uid;
		Vector3 refPos = peer.GetRefPos();
		Vector2i zone = ZoneSystem.GetZone(refPos);
		Vector2i zone2 = ZoneSystem.GetZone(predictedRefPos);
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		PeerStreamingState value;
		bool flag = _peerStreamingStates.TryGetValue(uid, out value) && value.HasZone;
		if (realtimeSinceStartup < value.NextBoostTime || (flag && value.CurrentZone == zone && value.PredictedZone == zone2))
		{
			return;
		}
		int num = Math.Max(1, GetMaxSendQueueBytes());
		int num2 = ((_zoneStreamingBoostMaxQueuePercent == null) ? 35 : Mathf.Clamp(_zoneStreamingBoostMaxQueuePercent.Value, 10, 90));
		int num3 = ((peer.m_socket != null) ? peer.m_socket.GetSendQueueSize() : 0);
		_diagnosticPeakSendQueue = Math.Max(_diagnosticPeakSendQueue, num3);
		if ((long)num3 * 100L >= (long)num * (long)num2)
		{
			value.NextBoostTime = realtimeSinceStartup + 0.25f;
			_peerStreamingStates[uid] = value;
			_diagnosticBoostBackpressureSkips++;
			return;
		}
		int num4 = QueueZoneStreamingBoost(zdoMan, zoneSystem, peer, zone, zone2, refPos);
		value.HasZone = true;
		value.CurrentZone = zone;
		value.PredictedZone = zone2;
		value.NextBoostTime = realtimeSinceStartup + ((_zoneStreamingBoostCooldownSeconds == null) ? 1.5f : Mathf.Clamp(_zoneStreamingBoostCooldownSeconds.Value, 0.1f, 10f));
		_peerStreamingStates[uid] = value;
		_diagnosticBoostQueued += num4;
		if (num4 > 0 && _logZoneStreamingBoosts != null && _logZoneStreamingBoosts.Value && _log != null)
		{
			string text = (string.IsNullOrEmpty(peer.m_playerName) ? "unknown peer" : peer.m_playerName);
			ManualLogSource log = _log;
			string[] obj = new string[7]
			{
				"Queued ",
				num4.ToString(),
				" server-side ZDO streaming boost object(s) for ",
				text,
				" at zone ",
				null,
				null
			};
			Vector2i val = zone;
			obj[5] = ((object)(*(Vector2i*)(&val))/*cast due to .constrained prefix*/).ToString();
			obj[6] = ".";
			log.LogInfo((object)string.Concat(obj));
		}
	}

	private static int QueueZoneStreamingBoost(ZDOMan zdoMan, ZoneSystem zoneSystem, ZNetPeer peer, Vector2i currentZone, Vector2i predictedZone, Vector3 refPos)
	{
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		int num = ((_maxZoneStreamingBoostZdosPerPeer == null) ? 128 : Mathf.Clamp(_maxZoneStreamingBoostZdosPerPeer.Value, 0, 5000));
		if (num <= 0)
		{
			return 0;
		}
		int num2 = ((_zoneStreamingBoostExtraRadius != null) ? Mathf.Clamp(_zoneStreamingBoostExtraRadius.Value, 0, 3) : 0);
		int num3 = Math.Max(1, zoneSystem.m_activeArea + num2);
		int num4 = ((_zoneStreamingBoostIncludeDistantZdos != null && _zoneStreamingBoostIncludeDistantZdos.Value) ? Math.Max(0, zoneSystem.m_activeDistantArea) : 0);
		_streamBoostNearScratch.Clear();
		_streamBoostDistantScratch.Clear();
		_streamBoostCandidates.Clear();
		_streamBoostSeenZdos.Clear();
		zdoMan.FindSectorObjects(currentZone, num3, num4, _streamBoostNearScratch, _streamBoostDistantScratch);
		if (!(predictedZone == currentZone))
		{
			zdoMan.FindSectorObjects(predictedZone, num3, num4, _streamBoostNearScratch, _streamBoostDistantScratch);
		}
		AddStreamingBoostCandidates(_streamBoostNearScratch, refPos, near: true);
		if (_zoneStreamingBoostIncludeDistantZdos != null && _zoneStreamingBoostIncludeDistantZdos.Value && _streamBoostCandidates.Count < num)
		{
			AddStreamingBoostCandidates(_streamBoostDistantScratch, refPos, near: false);
		}
		_streamBoostCandidates.Sort(CompareStreamingBoostZdos);
		int num5 = 0;
		for (int i = 0; i < _streamBoostCandidates.Count; i++)
		{
			if (num5 >= num)
			{
				break;
			}
			ZDO val = _streamBoostCandidates[i];
			if (val != null && val.IsValid() && !((ZDOID)(ref val.m_uid)).IsNone())
			{
				zdoMan.ForceSendZDO(peer.m_uid, val.m_uid);
				num5++;
			}
		}
		_streamBoostNearScratch.Clear();
		_streamBoostDistantScratch.Clear();
		_streamBoostCandidates.Clear();
		_streamBoostSeenZdos.Clear();
		return num5;
	}

	private static void AddStreamingBoostCandidates(List<ZDO> source, Vector3 refPos, bool near)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		if (source == null)
		{
			return;
		}
		ZNetScene instance = ZNetScene.instance;
		for (int i = 0; i < source.Count; i++)
		{
			ZDO val = source[i];
			if (val != null && val.IsValid() && !((ZDOID)(ref val.m_uid)).IsNone() && _streamBoostSeenZdos.Add(val.m_uid) && (!((Object)(object)instance != (Object)null) || instance.HasPrefab(val.GetPrefab())) && !ShouldDelayTerrainCompilerZdo(val, instance))
			{
				val.m_tempSortValue = GetStreamingBoostSortValue(val, refPos, near);
				_streamBoostCandidates.Add(val);
			}
		}
	}

	private static float GetStreamingBoostSortValue(ZDO zdo, Vector3 refPos, bool near)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		Vector3 position = zdo.GetPosition();
		float num = position.x - refPos.x;
		float num2 = position.z - refPos.z;
		float num3 = num * num + num2 * num2;
		if (!near)
		{
			num3 += 1000000f;
		}
		return num3;
	}

	private static int CompareStreamingBoostZdos(ZDO left, ZDO right)
	{
		int num = GetStreamingBoostTypeRank(left).CompareTo(GetStreamingBoostTypeRank(right));
		if (num != 0)
		{
			return num;
		}
		return Utils.CompareFloats(left.m_tempSortValue, right.m_tempSortValue);
	}

	private static int GetStreamingBoostTypeRank(ZDO zdo)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Invalid comparison between Unknown and I4
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Invalid comparison between Unknown and I4
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Invalid comparison between Unknown and I4
		if (_enablePlayerPriority != null && _enablePlayerPriority.Value && zdo.GetPrefab() == GetPlayerPrefabHash())
		{
			return 0;
		}
		if ((int)zdo.Type == 3)
		{
			return 1;
		}
		if ((int)zdo.Type == 2)
		{
			return 2;
		}
		if ((int)zdo.Type == 1)
		{
			return 3;
		}
		return 4;
	}

	internal static bool TryHandleRoutedOwnershipRpc(object routedRpcData)
	{
		if (!CanRunOnServer() || routedRpcData == null || !HasRoutedRpcReflection())
		{
			return false;
		}
		try
		{
			int num = (int)_routedRpcMethodHashField.GetValue(routedRpcData);
			if (num == StringExtensionMethods.GetStableHashCode("RPC_Remove"))
			{
				return TryHandleStaleWearNTearRemoveRpc(routedRpcData);
			}
			if (num == StringExtensionMethods.GetStableHashCode("RPC_RequestOwn"))
			{
				return TryHandleItemDropOwnershipRequest(routedRpcData);
			}
		}
		catch (Exception ex)
		{
			LogRemoveRepairWarning("Routed ownership repair inspection failed: " + ex.Message);
		}
		return false;
	}

	private unsafe static bool TryHandleItemDropOwnershipRequest(object routedRpcData)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_024b: Unknown result type (might be due to invalid IL or missing references)
		//IL_024c: Unknown result type (might be due to invalid IL or missing references)
		if (_repairStaleItemDropOwnership == null || !_repairStaleItemDropOwnership.Value)
		{
			return false;
		}
		ZDOID val = (ZDOID)_routedRpcTargetZdoField.GetValue(routedRpcData);
		long num = (long)_routedRpcSenderPeerIdField.GetValue(routedRpcData);
		if (((ZDOID)(ref val)).IsNone() || num == 0L)
		{
			return false;
		}
		ZNet instance = ZNet.instance;
		ZDOMan instance2 = ZDOMan.instance;
		ZNetScene instance3 = ZNetScene.instance;
		if ((Object)(object)instance == (Object)null || instance2 == null || (Object)(object)instance3 == (Object)null || !instance.IsServer())
		{
			return false;
		}
		ZDO zDO = instance2.GetZDO(val);
		if (zDO == null || !zDO.IsValid())
		{
			return false;
		}
		bool flag = num == ZNet.GetUID();
		ZNetPeer val2 = (flag ? null : instance.GetPeer(num));
		if (!flag && (val2 == null || !val2.IsReady() || !IsPeerActiveNearZdo(val2, zDO)))
		{
			return false;
		}
		GameObject prefab = instance3.GetPrefab(zDO.GetPrefab());
		if ((Object)(object)prefab == (Object)null || (Object)(object)prefab.GetComponentInChildren<ItemDrop>(true) == (Object)null)
		{
			return false;
		}
		if (flag)
		{
			ZNetView val3 = instance3.FindInstance(zDO);
			if ((Object)(object)val3 == (Object)null || (Object)(object)((Component)val3).GetComponent<ItemDrop>() == (Object)null)
			{
				return false;
			}
		}
		long owner = zDO.GetOwner();
		if (owner == num)
		{
			if (flag)
			{
				return false;
			}
			instance2.ForceSendZDO(num, val);
			_routedRpcTargetPeerIdField.SetValue(routedRpcData, ZNet.GetUID());
			_diagnosticItemDropOwnershipRefreshes++;
			if (_logItemDropOwnershipRepairs != null && _logItemDropOwnershipRepairs.Value && _log != null)
			{
				ManualLogSource log = _log;
				string[] obj = new string[5] { "Re-sent authoritative ItemDrop ownership for ZDO ", null, null, null, null };
				ZDOID val4 = val;
				obj[1] = ((object)(*(ZDOID*)(&val4))/*cast due to .constrained prefix*/).ToString();
				obj[2] = " to recorded owner ";
				obj[3] = num.ToString();
				obj[4] = ".";
				log.LogInfo((object)string.Concat(obj));
			}
			return true;
		}
		zDO.SetOwner(num);
		if (!flag)
		{
			instance2.ForceSendZDO(num, val);
		}
		_routedRpcTargetPeerIdField.SetValue(routedRpcData, ZNet.GetUID());
		_diagnosticItemDropOwnershipRepairs++;
		if (_logItemDropOwnershipRepairs != null && _logItemDropOwnershipRepairs.Value && _log != null)
		{
			string text = (flag ? "server simulation" : ("nearby peer " + num));
			ManualLogSource log2 = _log;
			string[] obj2 = new string[7] { "Transferred ItemDrop ZDO ", null, null, null, null, null, null };
			ZDOID val4 = val;
			obj2[1] = ((object)(*(ZDOID*)(&val4))/*cast due to .constrained prefix*/).ToString();
			obj2[2] = " from owner ";
			obj2[3] = owner.ToString();
			obj2[4] = " to ";
			obj2[5] = text;
			obj2[6] = ".";
			log2.LogInfo((object)string.Concat(obj2));
		}
		return true;
	}

	internal unsafe static bool TryHandleStaleWearNTearRemoveRpc(object routedRpcData)
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
		if (!CanRunOnServer() || _repairStaleWearNTearRemoveOwnership == null || !_repairStaleWearNTearRemoveOwnership.Value || routedRpcData == null)
		{
			return false;
		}
		if (!HasRoutedRpcReflection())
		{
			LogRemoveRepairWarning("Stale remove ownership repair is unavailable because Valheim's routed-RPC fields could not be found.");
			return false;
		}
		if (_routedRpcParametersField == null || _wearNTearRemoveRpc == null)
		{
			LogRemoveRepairWarning("Stale remove ownership repair is unavailable because Valheim's WearNTear remove handler could not be bound safely.");
			return false;
		}
		try
		{
			if ((int)_routedRpcMethodHashField.GetValue(routedRpcData) != StringExtensionMethods.GetStableHashCode("RPC_Remove"))
			{
				return false;
			}
			ZDOID val = (ZDOID)_routedRpcTargetZdoField.GetValue(routedRpcData);
			if (((ZDOID)(ref val)).IsNone())
			{
				return false;
			}
			ZDOMan instance = ZDOMan.instance;
			ZNetScene instance2 = ZNetScene.instance;
			ZNet instance3 = ZNet.instance;
			if (instance == null || (Object)(object)instance2 == (Object)null || (Object)(object)instance3 == (Object)null || !instance3.IsServer())
			{
				return false;
			}
			ZDO zDO = instance.GetZDO(val);
			if (zDO == null || !zDO.IsValid())
			{
				return false;
			}
			long num = (long)_routedRpcSenderPeerIdField.GetValue(routedRpcData);
			if (!IsRemoveRequesterCloseEnough(instance3, num, zDO.GetPosition()))
			{
				return false;
			}
			if (Location.IsInsideNoBuildLocation(zDO.GetPosition()))
			{
				return false;
			}
			ZNetView val2 = instance2.FindInstance(zDO);
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = TryCreateServerInstanceForRemove(instance2, zDO);
				if ((Object)(object)val2 == (Object)null)
				{
					ZDOID val3 = val;
					LogRemoveRepairWarning("Could not handle build-piece remove on the server because there is no active instance for ZDO " + ((object)(*(ZDOID*)(&val3))/*cast due to .constrained prefix*/).ToString() + ".");
					return false;
				}
			}
			WearNTear component = ((Component)val2).GetComponent<WearNTear>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			Piece component2 = ((Component)val2).GetComponent<Piece>();
			if ((Object)(object)component2 != (Object)null && !component2.CanBeRemoved())
			{
				return false;
			}
			long targetPeerId = (long)_routedRpcTargetPeerIdField.GetValue(routedRpcData);
			long owner = zDO.GetOwner();
			long uID = ZNet.GetUID();
			if (!ShouldServerHandleRemoveRpc(instance3, zDO, owner, targetPeerId, uID, num))
			{
				return false;
			}
			zDO.SetOwner(uID);
			object? value = _routedRpcParametersField.GetValue(routedRpcData);
			ZPackage val4 = (ZPackage)((value is ZPackage) ? value : null);
			if (val4 == null || _wearNTearRemoveRpc == null)
			{
				zDO.SetOwner(owner);
				return false;
			}
			int pos = val4.GetPos();
			bool blockDrop;
			try
			{
				val4.SetPos(0);
				blockDrop = val4.ReadBool();
			}
			finally
			{
				val4.SetPos(pos);
			}
			try
			{
				_wearNTearRemoveRpc(component, num, blockDrop);
			}
			catch
			{
				if (zDO.IsValid())
				{
					zDO.SetOwner(owner);
				}
				throw;
			}
			if (zDO.IsValid())
			{
				zDO.SetOwner(owner);
				return false;
			}
			if (_logRemoveOwnershipRepairs != null && _logRemoveOwnershipRepairs.Value && _log != null)
			{
				ManualLogSource log = _log;
				string[] obj2 = new string[5] { "Handled build-piece remove on server for ZDO ", null, null, null, null };
				ZDOID val3 = val;
				obj2[1] = ((object)(*(ZDOID*)(&val3))/*cast due to .constrained prefix*/).ToString();
				obj2[2] = " after temporarily moving ownership from ";
				obj2[3] = owner.ToString();
				obj2[4] = " to server.";
				log.LogInfo((object)string.Concat(obj2));
			}
			_routedRpcTargetPeerIdField.SetValue(routedRpcData, uID);
			return true;
		}
		catch (Exception innerException)
		{
			while (innerException.InnerException != null)
			{
				innerException = innerException.InnerException;
			}
			LogRemoveRepairWarning("Stale build-piece remove ownership repair failed in " + innerException.GetType().Name + ": " + innerException.Message);
			return false;
		}
	}

	private static void ApplySafetyMigrations()
	{
		if (_enablePeerZoneCreation != null && _enablePeerZoneCreation.Value)
		{
			_enablePeerZoneCreation.Value = false;
			if (_log != null)
			{
				_log.LogWarning((object)"Disabled experimental peer zone creation because it can repeatedly reload dungeon-bearing zones. Normal Valheim ghost-zone generation remains active.");
			}
		}
		if (_enableServerOwnershipForPersistentZdos != null && _enableServerOwnershipForPersistentZdos.Value)
		{
			_enableServerOwnershipForPersistentZdos.Value = false;
			if (_log != null)
			{
				_log.LogWarning((object)"Disabled legacy persistent-ZDO server ownership. Use Streaming.EnableServerZoneStreamingBoost for faster area data without server ownership transfer.");
			}
		}
		if (_safetyDefaultsVersion != null && _safetyDefaultsVersion.Value < 1)
		{
			if (_enableZDOThrottling != null)
			{
				_enableZDOThrottling.Value = false;
			}
			if (_skipSleepWorldSave != null)
			{
				_skipSleepWorldSave.Value = false;
			}
			_safetyDefaultsVersion.Value = 1;
			if (_log != null)
			{
				_log.LogWarning((object)"Applied 0.4 safety migration: disabled ZDO throttling and sleep-save skipping.");
			}
		}
		if (_safetyDefaultsVersion != null && _safetyDefaultsVersion.Value < 2)
		{
			if (_repairStaleWearNTearRemoveOwnership != null)
			{
				_repairStaleWearNTearRemoveOwnership.Value = true;
			}
			_safetyDefaultsVersion.Value = 2;
			if (_log != null)
			{
				_log.LogWarning((object)"Applied 0.4.2 ownership-route migration: enabled narrow build-piece remove recovery so non-owner players are not dependent on another client's ownership route.");
			}
		}
		if (_safetyDefaultsVersion != null && _safetyDefaultsVersion.Value < 3)
		{
			_maxSendQueueBytes.Value = 16384;
			_peerSendIntervalSeconds.Value = 0.05f;
			_zoneStreamingBoostExtraRadius.Value = 0;
			_maxZoneStreamingBoostZdosPerPeer.Value = 128;
			_zoneStreamingBoostCooldownSeconds.Value = 1.5f;
			_extendedZoneRadius.Value = 0;
			_createDestroyIntervalSeconds.Value = 0.1f;
			_removeObjectsIntervalSeconds.Value = 0.5f;
			_peerZoneUpdateIntervalSeconds.Value = 0.5f;
			_maxPeerZoneCreationsPerPass.Value = 1;
			if (_repairStaleItemDropOwnership != null)
			{
				_repairStaleItemDropOwnership.Value = true;
			}
			_safetyDefaultsVersion.Value = 3;
			if (_log != null)
			{
				_log.LogWarning((object)"Applied 0.4.3 dense-world migration: reduced bulk streaming and zone-scan pressure, and enabled nearby ItemDrop ownership-request recovery.");
			}
		}
		if (_safetyDefaultsVersion != null && _safetyDefaultsVersion.Value < 4)
		{
			if (_enablePeerZoneCreation != null)
			{
				_enablePeerZoneCreation.Value = false;
			}
			_safetyDefaultsVersion.Value = 4;
			if (_log != null)
			{
				_log.LogWarning((object)"Applied 0.4.6 zone-loading migration: disabled experimental full local peer-zone instantiation. Valheim's normal peer ghost-zone generation remains enabled.");
			}
		}
	}

	internal static bool ShouldSkipHeadlessVisualSystems()
	{
		if (_enabled == null || !_enabled.Value || _enableHeadlessVisualGuards == null || !_enableHeadlessVisualGuards.Value)
		{
			return false;
		}
		try
		{
			if (Application.isBatchMode)
			{
				return true;
			}
			if (!CanRunOnServer())
			{
				return false;
			}
			ZNet instance = ZNet.instance;
			return (Object)(object)instance != (Object)null && instance.IsDedicated();
		}
		catch
		{
			return false;
		}
	}

	private static bool ShouldPauseExtraZoneWorkForSleep()
	{
		if (_pauseExtraZoneWorkDuringSleep == null || !_pauseExtraZoneWorkDuringSleep.Value)
		{
			return false;
		}
		try
		{
			EnvMan instance = EnvMan.instance;
			if ((Object)(object)instance != (Object)null && instance.IsTimeSkipping())
			{
				LogSleepPause();
				return true;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (realtimeSinceStartup >= _nextSleepBedCheckTime)
			{
				_nextSleepBedCheckTime = realtimeSinceStartup + 0.2f;
				_sleepBedPauseActive = AreAllCharactersInBed();
			}
			if (_sleepBedPauseActive)
			{
				LogSleepPause();
				return true;
			}
		}
		catch
		{
			return false;
		}
		return false;
	}

	private static bool AreAllCharactersInBed()
	{
		ZNet instance = ZNet.instance;
		if ((Object)(object)instance == (Object)null || !instance.IsServer())
		{
			return false;
		}
		List<ZDO> allCharacterZDOS = instance.GetAllCharacterZDOS();
		if (allCharacterZDOS == null || allCharacterZDOS.Count == 0)
		{
			return false;
		}
		bool result = false;
		for (int i = 0; i < allCharacterZDOS.Count; i++)
		{
			ZDO val = allCharacterZDOS[i];
			if (val != null && val.IsValid())
			{
				result = true;
				if (!val.GetBool(ZDOVars.s_inBed, false))
				{
					return false;
				}
			}
		}
		return result;
	}

	private static void LogSleepPause()
	{
		if (_log != null && _logSleepOptimizations != null && _logSleepOptimizations.Value)
		{
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (!(realtimeSinceStartup < _nextSleepPauseLogTime))
			{
				_nextSleepPauseLogTime = realtimeSinceStartup + 30f;
				_log.LogInfo((object)"Paused extra zone warming while players are sleeping.");
			}
		}
	}

	private static bool ShouldServerHandleRemoveRpc(ZNet znet, ZDO zdo, long owner, long targetPeerId, long serverUid, long senderPeerId)
	{
		if ((Object)(object)znet == (Object)null || zdo == null)
		{
			return false;
		}
		if (owner == 0L || owner == serverUid || targetPeerId == 0L || targetPeerId == serverUid)
		{
			return true;
		}
		if (senderPeerId != 0L && senderPeerId != owner)
		{
			return true;
		}
		ZNetPeer peer = znet.GetPeer(targetPeerId);
		if (peer == null || !peer.IsReady())
		{
			return true;
		}
		return !IsPeerActiveNearZdo(peer, zdo);
	}

	private unsafe static ZNetView TryCreateServerInstanceForRemove(ZNetScene scene, ZDO zdo)
	{
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)scene == (Object)null || zdo == null || _createObjects == null)
		{
			return null;
		}
		try
		{
			List<ZDO> list = new List<ZDO>(1);
			List<ZDO> distantObjects = new List<ZDO>(0);
			list.Add(zdo);
			_createObjects(scene, list, distantObjects);
			ZNetView obj = scene.FindInstance(zdo);
			if ((Object)(object)obj != (Object)null && _logRemoveOwnershipRepairs != null && _logRemoveOwnershipRepairs.Value && _log != null)
			{
				ManualLogSource log = _log;
				ZDOID uid = zdo.m_uid;
				log.LogInfo((object)("Created missing server instance for build-piece remove ZDO " + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString() + "."));
			}
			return obj;
		}
		catch (Exception ex)
		{
			LogRemoveRepairWarning("Could not create missing server instance for build-piece remove: " + ex.Message);
			return null;
		}
	}

	private static bool IsRemoveRequesterCloseEnough(ZNet znet, long senderPeerId, Vector3 zdoPosition)
	{
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)znet == (Object)null)
		{
			return false;
		}
		long uID = ZNet.GetUID();
		if (senderPeerId == uID)
		{
			return true;
		}
		ZNetPeer peer = znet.GetPeer(senderPeerId);
		if (peer == null || !peer.IsReady())
		{
			return false;
		}
		float num = ((_maxRemoveRepairDistance == null) ? 8f : Mathf.Clamp(_maxRemoveRepairDistance.Value, 5f, 16f));
		Vector3 val = peer.GetRefPos() - zdoPosition;
		return ((Vector3)(ref val)).sqrMagnitude <= num * num;
	}

	private static bool IsPeerActiveNearZdo(ZNetPeer peer, ZDO zdo)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		if (peer == null || zdo == null)
		{
			return false;
		}
		ZoneSystem instance = ZoneSystem.instance;
		int num = (((Object)(object)instance == (Object)null) ? 2 : Math.Max(1, instance.m_activeArea));
		return ZNetScene.InActiveArea(zdo.GetSector(), ZoneSystem.GetZone(peer.GetRefPos()), num);
	}

	private static void InitializeZNetSceneReflection()
	{
		_zNetSceneInstancesField = AccessTools.Field(typeof(ZNetScene), "m_instances");
		if (_zNetSceneInstancesField == null && _log != null)
		{
			_log.LogWarning((object)"Could not bind ZNetScene.m_instances; stale scene-instance sanitation will be unavailable.");
		}
	}

	internal static int RepairStaleSceneInstances(ZNetScene scene)
	{
		if ((Object)(object)scene == (Object)null || _zNetSceneInstancesField == null)
		{
			return 0;
		}
		if (!(_zNetSceneInstancesField.GetValue(scene) is Dictionary<ZDO, ZNetView> { Count: not 0 } dictionary))
		{
			return 0;
		}
		_staleSceneInstanceKeys.Clear();
		foreach (KeyValuePair<ZDO, ZNetView> item in dictionary)
		{
			ZDO key = item.Key;
			ZNetView value = item.Value;
			ZDO val = null;
			if ((Object)(object)value != (Object)null)
			{
				try
				{
					val = value.GetZDO();
				}
				catch
				{
				}
			}
			if (key == null || !key.IsValid() || (Object)(object)value == (Object)null || val == null || val != key)
			{
				_staleSceneInstanceKeys.Add(key);
			}
		}
		int num = 0;
		for (int i = 0; i < _staleSceneInstanceKeys.Count; i++)
		{
			ZDO val2 = _staleSceneInstanceKeys[i];
			if (val2 == null || !dictionary.TryGetValue(val2, out var value2) || !dictionary.Remove(val2))
			{
				continue;
			}
			num++;
			if (!((Object)(object)value2 != (Object)null))
			{
				continue;
			}
			try
			{
				if (value2.GetZDO() == null)
				{
					Object.Destroy((Object)(object)((Component)value2).gameObject);
				}
			}
			catch
			{
			}
		}
		if (num > 0)
		{
			_diagnosticStaleSceneInstancesRemoved += num;
			if (_log != null)
			{
				_log.LogWarning((object)("Removed " + num + " stale ZNetScene instance registration(s) before RemoveObjects."));
			}
		}
		_staleSceneInstanceKeys.Clear();
		return num;
	}

	private static void InitializeRoutedRpcReflection()
	{
		MethodInfo methodInfo = AccessTools.Method(typeof(ZRoutedRpc), "RouteRPC", (Type[])null, (Type[])null);
		Type type = null;
		if (methodInfo != null)
		{
			ParameterInfo[] parameters = methodInfo.GetParameters();
			if (parameters.Length == 1)
			{
				type = parameters[0].ParameterType;
			}
		}
		if (!(type == null))
		{
			_routedRpcTargetPeerIdField = AccessTools.Field(type, "m_targetPeerID");
			_routedRpcSenderPeerIdField = AccessTools.Field(type, "m_senderPeerID");
			_routedRpcTargetZdoField = AccessTools.Field(type, "m_targetZDO");
			_routedRpcMethodHashField = AccessTools.Field(type, "m_methodHash");
			_routedRpcParametersField = AccessTools.Field(type, "m_parameters");
		}
	}

	private static void InitializeSleepReflection()
	{
		_envManSkipToTimeField = AccessTools.Field(typeof(EnvMan), "m_skipToTime");
		_envManTimeSkipSpeedField = AccessTools.Field(typeof(EnvMan), "m_timeSkipSpeed");
		_gameSaveTimerField = AccessTools.Field(typeof(Game), "m_saveTimer");
	}

	private static void InitializeZoneTtlReflection()
	{
		_zoneSystemZonesField = AccessTools.Field(typeof(ZoneSystem), "m_zones");
		if (_zoneSystemZonesField != null)
		{
			Type[] genericArguments = _zoneSystemZonesField.FieldType.GetGenericArguments();
			if (genericArguments.Length == 2)
			{
				_zoneDataTtlField = AccessTools.Field(genericArguments[1], "m_ttl");
			}
		}
		if ((_zoneSystemZonesField == null || _zoneDataTtlField == null) && _enablePeerZoneCreation != null && _enablePeerZoneCreation.Value)
		{
			_enablePeerZoneCreation.Value = false;
			if (_log != null)
			{
				_log.LogError((object)"Disabled peer zone creation because Valheim's zone TTL fields could not be found safely.");
			}
		}
	}

	private static void RefreshLoadedPeerZoneTtls(ZoneSystem zoneSystem)
	{
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)zoneSystem == (Object)null || _enablePeerZoneCreation == null || !_enablePeerZoneCreation.Value || _zoneSystemZonesField == null || _zoneDataTtlField == null)
		{
			return;
		}
		IDictionary dictionary = _zoneSystemZonesField.GetValue(zoneSystem) as IDictionary;
		ZNet instance = ZNet.instance;
		if (dictionary == null || (Object)(object)instance == (Object)null || !instance.IsServer())
		{
			return;
		}
		List<ZNetPeer> connectedPeers = instance.GetConnectedPeers();
		if (connectedPeers == null)
		{
			return;
		}
		_ttlRefreshZones.Clear();
		int radius = Math.Max(1, zoneSystem.m_activeArea);
		for (int i = 0; i < connectedPeers.Count; i++)
		{
			ZNetPeer val = connectedPeers[i];
			if (val != null && val.IsReady())
			{
				Vector2i zone = ZoneSystem.GetZone(val.GetRefPos());
				AddZoneSquare(_ttlRefreshZones, zone, radius);
				Vector2i zone2 = ZoneSystem.GetZone(GetPredictedRefPos(val));
				if (!(zone2 == zone))
				{
					AddZoneSquare(_ttlRefreshZones, zone2, radius);
				}
			}
		}
		foreach (Vector2i ttlRefreshZone in _ttlRefreshZones)
		{
			if (dictionary.Contains(ttlRefreshZone))
			{
				object obj = dictionary[ttlRefreshZone];
				if (obj != null)
				{
					_zoneDataTtlField.SetValue(obj, 0f);
					_diagnosticZoneTtlRefreshes++;
				}
			}
		}
	}

	private static void AddZoneSquare(HashSet<Vector2i> zones, Vector2i center, int radius)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: 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_0019: Unknown result type (might be due to invalid IL or missing references)
		for (int i = center.y - radius; i <= center.y + radius; i++)
		{
			for (int j = center.x - radius; j <= center.x + radius; j++)
			{
				zones.Add(new Vector2i(j, i));
			}
		}
	}

	private static bool HasRoutedRpcReflection()
	{
		if (_routedRpcTargetPeerIdField != null && _routedRpcSenderPeerIdField != null && _routedRpcTargetZdoField != null)
		{
			return _routedRpcMethodHashField != null;
		}
		return false;
	}

	private static void LogRemoveRepairWarning(string message)
	{
		if (_log != null && !(Time.realtimeSinceStartup < _nextRemoveRepairWarningTime))
		{
			_nextRemoveRepairWarningTime = Time.realtimeSinceStartup + 30f;
			_log.LogWarning((object)message);
		}
	}

	private static void ClampConfig()
	{
		ClampInt(_maxSendQueueBytes, 2048, 262144);
		ClampInt(_minFreeSendQueueBytes, 512, 131072);
		ClampFloat(_peerSendIntervalSeconds, 0.01f, 0.25f);
		ClampInt(_zoneStreamingBoostExtraRadius, 0, 3);
		ClampInt(_maxZoneStreamingBoostZdosPerPeer, 0, 5000);
		ClampFloat(_zoneStreamingBoostCooldownSeconds, 0.1f, 10f);
		ClampInt(_zoneStreamingBoostMaxQueuePercent, 10, 90);
		ClampInt(_denseSyncThreshold, 100, 100000);
		ClampFloat(_denseSyncLogIntervalSeconds, 5f, 600f);
		ClampFloat(_denseSyncPauseSeconds, 0.5f, 30f);
		ClampInt(_extendedZoneRadius, 0, 3);
		ClampFloat(_createDestroyIntervalSeconds, 0.03f, 1f);
		ClampFloat(_removeObjectsIntervalSeconds, 0.05f, 2f);
		ClampFloat(_predictionLookaheadSec, 0.5f, 10f);
		ClampFloat(_predictionMinVelocity, 0.5f, 20f);
		ClampInt(_predictionMaxLookaheadZones, 1, 25);
		ClampFloat(_zdoThrottleDistance, 0f, 1000f);
		ClampFloat(_peerZoneUpdateIntervalSeconds, 0.05f, 2f);
		ClampInt(_maxPeerZoneCreationsPerPass, 1, 16);
		ClampFloat(_sleepFastForwardSeconds, 1f, 60f);
		ClampFloat(_maxRemoveRepairDistance, 5f, 16f);
		ClampFloat(_diagnosticIntervalSec, 10f, 3600f);
		if (_minFreeSendQueueBytes != null && _maxSendQueueBytes != null && _minFreeSendQueueBytes.Value > _maxSendQueueBytes.Value)
		{
			_minFreeSendQueueBytes.Value = _maxSendQueueBytes.Value;
		}
	}

	private static bool ClampInt(ConfigEntry<int> entry, int min, int max)
	{
		if (entry.Value < min)
		{
			entry.Value = min;
			return true;
		}
		if (entry.Value > max)
		{
			entry.Value = max;
			return true;
		}
		return false;
	}

	private static bool ClampFloat(ConfigEntry<float> entry, float min, float max)
	{
		if (entry.Value < min)
		{
			entry.Value = min;
			return true;
		}
		if (entry.Value > max)
		{
			entry.Value = max;
			return true;
		}
		return false;
	}

	private static int GetPlayerPrefabHash()
	{
		return PlayerPrefabHash;
	}

	internal static void MaybeLogDenseSync(object zdoPeer, List<ZDO> toSync)
	{
		if (CanRunOnServer() && _log != null && _logDenseSyncs != null && _logDenseSyncs.Value && zdoPeer != null && toSync != null && toSync.Count >= _denseSyncThreshold.Value)
		{
			ZNetPeer netPeer = GetNetPeer(zdoPeer);
			long key = netPeer?.m_uid ?? 0;
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (!_lastDenseSyncLogTimes.TryGetValue(key, out var value) || !(realtimeSinceStartup - value < _denseSyncLogIntervalSeconds.Value))
			{
				_lastDenseSyncLogTimes[key] = realtimeSinceStartup;
				string text = ((netPeer == null || string.IsNullOrEmpty(netPeer.m_playerName)) ? "unknown peer" : netPeer.m_playerName);
				string text2 = DescribeDenseSyncPrefabs(toSync);
				_log.LogInfo((object)("Dense ZDO sync for " + text + ": " + toSync.Count + " pending object(s)" + text2 + ". If this stays high, the area itself is probably too object-heavy for smooth client loading."));
			}
		}
	}

	private static string DescribeDenseSyncPrefabs(List<ZDO> toSync)
	{
		_densePrefabCounts.Clear();
		_densePrefabCountsSorted.Clear();
		for (int i = 0; i < toSync.Count; i++)
		{
			ZDO val = toSync[i];
			if (val != null && val.IsValid())
			{
				int prefab = val.GetPrefab();
				_densePrefabCounts.TryGetValue(prefab, out var value);
				_densePrefabCounts[prefab] = value + 1;
			}
		}
		foreach (KeyValuePair<int, int> densePrefabCount in _densePrefabCounts)
		{
			_densePrefabCountsSorted.Add(densePrefabCount);
		}
		_densePrefabCountsSorted.Sort((KeyValuePair<int, int> left, KeyValuePair<int, int> right) => right.Value.CompareTo(left.Value));
		int num = Math.Min(5, _densePrefabCountsSorted.Count);
		if (num == 0)
		{
			return string.Empty;
		}
		ZNetScene instance = ZNetScene.instance;
		StringBuilder stringBuilder = new StringBuilder("; top pending prefabs: ");
		for (int num2 = 0; num2 < num; num2++)
		{
			if (num2 > 0)
			{
				stringBuilder.Append(", ");
			}
			KeyValuePair<int, int> keyValuePair = _densePrefabCountsSorted[num2];
			GameObject val2 = (((Object)(object)instance == (Object)null) ? null : instance.GetPrefab(keyValuePair.Key));
			stringBuilder.Append(((Object)(object)val2 == (Object)null) ? ("hash:" + keyValuePair.Key) : ((Object)val2).name);
			stringBuilder.Append('=');
			stringBuilder.Append(keyValuePair.Value);
		}
		return stringBuilder.ToString();
	}

	private static Vector3 GetPredictedRefPos(ZNetPeer peer)
	{
		//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_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		Vector3 refPos = peer.GetRefPos();
		if (_enablePredictiveZoneStreaming == null || !_enablePredictiveZoneStreaming.Value)
		{
			return refPos;
		}
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		long uid = peer.m_uid;
		if (!_peerMotion.TryGetValue(uid, out var value))
		{
			value = new PeerMotionSample(refPos, Vector3.zero, realtimeSinceStartup);
			_peerMotion[uid] = value;
			return refPos;
		}
		float num = realtimeSinceStartup - value.Time;
		if (num >= 0.25f)
		{
			Vector3 val = refPos - value.Position;
			val.y = 0f;
			if (num > 2f || ((Vector3)(ref val)).sqrMagnitude > 16384f)
			{
				value.Velocity = Vector3.zero;
			}
			else if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				value.Velocity = Vector3.zero;
			}
			else
			{
				Vector3 val2 = val / Mathf.Max(num, 0.05f);
				value.Velocity = Vector3.Lerp(value.Velocity, val2, 0.5f);
			}
			value.Position = refPos;
			value.Time = realtimeSinceStartup;
			_peerMotion[uid] = value;
		}
		float num2 = Mathf.Max(0f, _predictionMinVelocity.Value);
		if (((Vector3)(ref value.Velocity)).magnitude < num2)
		{
			return refPos;
		}
		Vector3 predicted = refPos + value.Velocity * Mathf.Max(0.5f, _predictionLookaheadSec.Value);
		return ClampForwardOffsetToMaxZones(refPos, predicted, Mathf.Max(1, _predictionMaxLookaheadZones.Value));
	}

	private static void PrunePeerTracking(HashSet<long> readyPeerIds)
	{
		if (readyPeerIds == null)
		{
			return;
		}
		_stalePeerIds.Clear();
		foreach (long key in _peerStreamingStates.Keys)
		{
			if (!readyPeerIds.Contains(key))
			{
				_stalePeerIds.Add(key);
			}
		}
		for (int i = 0; i < _stalePeerIds.Count; i++)
		{
			_peerStreamingStates.Remove(_stalePeerIds[i]);
		}
		_stalePeerIds.Clear();
		foreach (long key2 in _peerMotion.Keys)
		{
			if (!readyPeerIds.Contains(key2))
			{
				_stalePeerIds.Add(key2);
			}
		}
		for (int j = 0; j < _stalePeerIds.Count; j++)
		{
			_peerMotion.Remove(_stalePeerIds[j]);
		}
		_stalePeerIds.Clear();
		foreach (long key3 in _lastDenseSyncLogTimes.Keys)
		{
			if (!readyPeerIds.Contains(key3))
			{
				_stalePeerIds.Add(key3);
			}
		}
		for (int k = 0; k < _stalePeerIds.Count; k++)
		{
			_lastDenseSyncLogTimes.Remove(_stalePeerIds[k]);
		}
		_stalePeerIds.Clear();
	}

	private static Vector3 ClampForwardOffsetToMaxZones(Vector3 origin, Vector3 predicted, int maxZones)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = predicted - origin;
		val.y = 0f;
		float num = (float)maxZones * 64f;
		if (((Vector3)(ref val)).magnitude <= num)
		{
			return new Vector3(origin.x + val.x, predicted.y, origin.z + val.z);
		}
		Vector3 val2 = ((Vector3)(ref val)).normalized * num;
		return new Vector3(origin.x + val2.x, predicted.y, origin.z + val2.z);
	}

	private static ZNetPeer GetNetPeer(object zdoPeer)
	{
		Type type = zdoPeer.GetType();
		if (!_netPeerFields.TryGetValue(type, out var value))
		{
			value = AccessTools.Field(type, "m_peer");
			_netPeerFields[type] = value;
		}
		if (!(value == null))
		{
			object? value2 = value.GetValue(zdoPeer);
			return (ZNetPeer)((value2 is ZNetPeer) ? value2 : null);
		}
		return null;
	}

	private static HashSet<ZDOID> GetForceSendSet(object zdoPeer)
	{
		Type type = zdoPeer.GetType();
		if (!_forceSendFields.TryGetValue(type, out var value))
		{
			value = AccessTools.Field(type, "m_forceSend");
			_forceSendFields[type] = value;
		}
		if (!(value == null))
		{
			return value.GetValue(zdoPeer) as HashSet<ZDOID>;
		}
		return null;
	}

	private static void FilterAndDedupeZdos(List<ZDO> source, List<ZDO> destination)
	{
		destination.Clear();
		ZNetScene instance = ZNetScene.instance;
		for (int i = 0; i < source.Count; i++)
		{
			ZDO val = source[i];
			if (val != null && val.IsValid() && !((ZDOID)(ref val.m_uid)).IsNone() && (!((Object)(object)instance != (Object)null) || instance.HasPrefab(val.GetPrefab())) && !ShouldDelayTerrainCompilerZdo(val, instance) && _seenZdos.Add(val))
			{
				destination.Add(val);
			}
		}
	}

	private static bool ShouldDelayTerrainCompilerZdo(ZDO zdo, ZNetScene scene)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		if (zdo == null || (Object)(object)scene == (Object)null || !IsTerrainCompilerPrefab(scene, zdo.GetPrefab()))
		{
			return false;
		}
		try
		{
			return (Object)(object)Heightmap.FindHeightmap(zdo.GetPosition()) == (Object)null;
		}
		catch
		{
			return true;
		}
	}

	private static bool IsTerrainCompilerPrefab(ZNetScene scene, int prefabHash)
	{
		if (_terrainCompilerPrefabCache.TryGetValue(prefabHash, out var value))
		{
			return value;
		}
		bool flag = false;
		try
		{
			GameObject val = (((Object)(object)scene == (Object)null) ? null : scene.GetPrefab(prefabHash));
			if ((Object)(object)val != (Object)null)
			{
				flag = (Object)(object)val.GetComponent<TerrainComp>() != (Object)null || (Object)(object)val.GetComponentInChildren<TerrainComp>(true) != (Object)null;
			}
		}
		catch
		{
			flag = false;
		}
		_terrainCompilerPrefabCache[prefabHash] = flag;
		return flag;
	}

	private static void MaybeLogDiagnostics()
	{
		if (_log != null && !(Time.realtimeSinceStartup < _nextDiagnosticLogTime))
		{
			_nextDiagnosticLogTime = Time.realtimeSinceStartup + Mathf.Clamp(_diagnosticIntervalSec.Value, 10f, 3600f);
			_log.LogInfo((object)("TerramizerServer status: create/destroy passes=" + _diagnosticCreateDestroyPasses + ", last candidates=" + _nearFiltered.Count + " near/" + _distantFiltered.Count + " distant, zone creates=" + _diagnosticZoneCreateSuccesses + "/" + _diagnosticZoneCreateAttempts + ", boost queued=" + _diagnosticBoostQueued + ", boost backpressure skips=" + _diagnosticBoostBackpressureSkips + ", item ownership transfers=" + _diagnosticItemDropOwnershipRepairs + ", item ownership refreshes=" + _diagnosticItemDropOwnershipRefreshes + ", stale scene registrations removed=" + _diagnosticStaleSceneInstancesRemoved + ", dense-pressure pauses=" + _diagnosticDensePressurePauses + ", zone TTL refreshes=" + _diagnosticZoneTtlRefreshes + ", sync duplicates removed=" + _diagnosticSyncDuplicatesRemoved + ", max sync list=" + _diagnosticMaxSyncList + ", peak socket queue=" + _diagnosticPeakSendQueue + " bytes."));
			_diagnosticCreateDestroyPasses = 0L;
			_diagnosticZoneCreateAttempts = 0L;
			_diagnosticZoneCreateSuccesses = 0L;
			_diagnosticBoostQueued = 0L;
			_diagnosticBoostBackpressureSkips = 0L;
			_diagnosticItemDropOwnershipRepairs = 0L;
			_diagnosticItemDropOwnershipRefreshes = 0L;
			_diagnosticStaleSceneInstancesRemoved = 0L;
			_diagnosticDensePressurePauses = 0L;
			_diagnosticZoneTtlRefreshes = 0L;
			_diagnosticSyncDuplicatesRemoved = 0L;
			_diagnosticMaxSyncList = 0;
			_diagnosticPeakSendQueue = 0;
		}
	}

	private static T CreateDelegateSafely<T>(Type type, string methodName) where T : Delegate
	{
		try
		{
			MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				LogWarningThrottled("Could not find " + type.Name + "." + methodName + "; related server-simulation feature will stay inactive.");
				return null;
			}
			return AccessTools.MethodDelegate<T>(methodInfo, (object)null, true);
		}
		catch (Exception ex)
		{
			LogWarningThrottled("Could not bind " + type.Name + "." + methodName + ": " + ex.Message);
			return null;
		}
	}

	private static void LogWarningThrottled(string message)
	{
		if (_log != null)
		{
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (!(realtimeSinceStartup < _nextWarningLogTime))
			{
				_nextWarningLogTime = realtimeSinceStartup + 30f;
				_log.LogWarning((object)message);
			}
		}
	}

	internal static void LogPatchMismatch(string feature, string details)
	{
		if (_log != null)
		{
			_log.LogError((object)("Left " + feature + " at vanilla behavior because the expected IL pattern was not found (" + details + "). This usually means Valheim changed; update TerramizerServer before forcing the feature."));
		}
	}
}
[HarmonyPatch(typeof(ZDOMan), "SendZDOs")]
internal static class ZdoManSendZdosPatch
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Expected O, but got Unknown
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Expected O, but got Unknown
		List<CodeInstruction> list = new List<CodeInstruction>(instructions);
		MethodInfo methodInfo = AccessTools.Method(typeof(TerramizerServerPlugin), "GetMaxSendQueueBytes", (Type[])null, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(typeof(TerramizerServerPlugin), "GetMinFreeSendQueueBytes", (Type[])null, (Type[])null);
		int num = 0;
		int num2 = 0;
		for (int i = 0; i < list.Count; i++)
		{
			CodeInstruction val = list[i];
			if (val.opcode == OpCodes.Ldc_I4 && val.operand is int)
			{
				int num3 = (int)val.operand;
				num += ((num3 == 10240) ? 1 : 0);
				num2 += ((num3 == 2048) ? 1 : 0);
			}
		}
		if (methodInfo == null || methodInfo2 == null || num != 2 || num2 != 1)
		{
			TerramizerServerPlugin.LogPatchMismatch("ZDO queue limits", "max=" + num + ", min=" + num2);
			return list;
		}
		List<CodeInstruction> list2 = new List<CodeInstruction>(list.Count);
		foreach (CodeInstruction item in list)
		{
			if (item.opcode == OpCodes.Ldc_I4 && item.operand is int)
			{
				switch ((int)item.operand)
				{
				case 10240:
					list2.Add(CopyLabelsAndBlocks(item, new CodeInstruction(OpCodes.Call, (object)methodInfo)));
					continue;
				case 2048:
					list2.Add(CopyLabelsAndBlocks(item, new CodeInstruction(OpCodes.Call, (object)methodInfo2)));
					continue;
				}
			}
			list2.Add(item);
		}
		return list2;
	}

	private static CodeInstruction CopyLabelsAndBlocks(CodeInstruction source, CodeInstruction target)
	{
		target.labels.AddRange(source.labels);
		target.blocks.AddRange(source.blocks);
		return target;
	}
}
[HarmonyPatch(typeof(ZDOMan), "SendZDOToPeers2")]
internal static class ZdoManSendZdoToPeersPatch
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Expected O, but got Unknown
		List<CodeInstruction> list = new List<CodeInstruction>(instructions);
		MethodInfo methodInfo = AccessTools.Method(typeof(TerramizerServerPlugin), "GetPeerSendIntervalSeconds", (Type[])null, (Type[])null);
		int num = 0;
		for (int i = 0; i < list.Count; i++)
		{
			CodeInstruction val = list[i];
			if (val.opcode == OpCodes.Ldc_R4 && val.operand is float && Math.Abs((float)val.operand - 0.05f) < 0.0001f)
			{
				num++;
			}
		}
		if (methodInfo == null || num != 1)
		{
			TerramizerServerPlugin.LogPatchMismatch("ZDO send interval", "matches=" + num);
			return list;
		}
		List<CodeInstruction> list2 = new List<CodeInstruction>(list.Count);
		foreach (CodeInstruction item in list)
		{
			if (item.opcode == OpCodes.Ldc_R4 && item.operand is float && Math.Abs((float)item.operand - 0.05f) < 0.0001f)
			{
				list2.Add(CopyLabelsAndBlocks(item, new CodeInstruction(OpCodes.Call, (object)methodInfo)));
			}
			else
			{
				list2.Add(item);
			}
		}
		return list2;
	}

	private static CodeInstruction CopyLabelsAndBlocks(CodeInstruction source, CodeInstruction target)
	{
		target.labels.AddRange(source.labels);
		target.blocks.AddRange(source.blocks);
		return target;
	}
}
[HarmonyPatch(typeof(ZDOMan), "CreateSyncList")]
internal static class ZdoManCreateSyncListPatch
{
	private static void Postfix(object __0, List<ZDO> __1)
	{
		TerramizerServerPlugin.PostProcessSyncList(__0, __1);
	}
}
[HarmonyPatch(typeof(EnvMan), "SkipToMorning")]
internal static class EnvManSkipToMorningPatch
{
	[HarmonyPriority(0)]
	private static void Postfix(EnvMan __instance)
	{
		TerramizerServerPlugin.TuneSleepFastForward(__instance);
	}
}
[HarmonyPatch(typeof(Game), "SleepStop")]
internal static class GameSleepStopPatch
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Exp