Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TerramizerServer v1.0.6
plugins/TerramizerServer/TerramizerServer.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Unity.Jobs.LowLevel.Unsafe; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("TerramizerServer")] [assembly: AssemblyFileVersion("1.0.6")] [assembly: AssemblyCompany("R4V9N1")] [assembly: AssemblyDescription("Created by R4V9N1")] [assembly: AssemblyProduct("TerramizerServer")] [assembly: AssemblyCopyright("Created by R4V9N1")] [assembly: AssemblyMetadata("Creator", "Created by R4V9N1")] [assembly: AssemblyVersion("1.0.6.0")] namespace TerramizerServer; internal static class BinarySearchDictionarySetValuePatch { private static class Fields<TValue> { internal static readonly FieldRef<BinarySearchDictionary<int, TValue>, int[]> Keys = AccessTools.FieldRefAccess<BinarySearchDictionary<int, TValue>, int[]>("m_keys"); internal static readonly FieldRef<BinarySearchDictionary<int, TValue>, TValue[]> Values = AccessTools.FieldRefAccess<BinarySearchDictionary<int, TValue>, TValue[]>("m_values"); internal static readonly FieldRef<BinarySearchDictionary<int, TValue>, ushort> Length = AccessTools.FieldRefAccess<BinarySearchDictionary<int, TValue>, ushort>("m_length"); } private static readonly MethodInfo PrefixMethod = AccessTools.Method(typeof(BinarySearchDictionarySetValuePatch), "SetValuePrefix", (Type[])null, (Type[])null); internal static void Install(Harmony harmony, Action<string> log) { try { PatchSetValue<float>(harmony); PatchSetValue<Vector3>(harmony); PatchSetValue<Quaternion>(harmony); PatchSetValue<int>(harmony); PatchSetValue<long>(harmony); PatchSetValue<string>(harmony); PatchSetValue<byte[]>(harmony); log?.Invoke("Installed allocation-free BinarySearchDictionary.SetValue patches."); } catch (Exception ex) { log?.Invoke("Could not install BinarySearchDictionary.SetValue patches; vanilla behavior remains active: " + ex.Message); } } private static void PatchSetValue<TValue>(Harmony harmony) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown Type typeFromHandle = typeof(BinarySearchDictionary<int, TValue>); MethodInfo methodInfo = AccessTools.Method(typeFromHandle, "SetValue", new Type[2] { typeof(int), typeof(TValue) }, (Type[])null); if (methodInfo == null) { throw new MissingMethodException(typeFromHandle.FullName, "SetValue"); } MethodInfo methodInfo2 = PrefixMethod.MakeGenericMethod(typeof(TValue)); harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static bool SetValuePrefix<TValue>(BinarySearchDictionary<int, TValue> __instance, int key, TValue value, ref bool __result) { if (__instance == null) { return true; } int[] array = Fields<TValue>.Keys.Invoke(__instance); TValue[] array2 = Fields<TValue>.Values.Invoke(__instance); ushort num = Fields<TValue>.Length.Invoke(__instance); bool exactMatch; int num2 = FindKeyIndex(array, num, key, out exactMatch); if (exactMatch) { if (EqualityComparer<TValue>.Default.Equals(array2[num2], value)) { __result = false; return false; } array2[num2] = value; __result = true; return false; } if (array == null || array.Length <= num) { int num3 = ((array == null || array.Length == 0) ? 1 : (array.Length + 2)); int[] array3 = new int[num3]; TValue[] array4 = new TValue[num3]; if (num > 0) { Array.Copy(array, array3, num); Array.Copy(array2, array4, num); } array = array3; array2 = array4; Fields<TValue>.Keys.Invoke(__instance) = array; Fields<TValue>.Values.Invoke(__instance) = array2; } if (num - num2 > 0) { Array.Copy(array, num2, array, num2 + 1, num - num2); Array.Copy(array2, num2, array2, num2 + 1, num - num2); } array[num2] = key; array2[num2] = value; Fields<TValue>.Length.Invoke(__instance) = (ushort)(num + 1); __result = true; return false; } private static int FindKeyIndex(int[] keys, ushort length, int key, out bool exactMatch) { if (length == 0) { exactMatch = false; return 0; } int num = 0; int num2 = length - 1; while (num < num2) { int num3 = (num + num2) / 2; if (key == keys[num3]) { exactMatch = true; return num3; } if (key < keys[num3]) { num2 = num3 - 1; } else { num = num3 + 1; } } int num4 = key.CompareTo(keys[num]); exactMatch = num4 == 0; if (num4 <= 0) { return num; } return num + 1; } } [HarmonyPatch(typeof(AudioMan), "Update")] internal static class AudioManHeadlessPatch { private static bool Prefix() { return !TerramizerServerPlugin.ShouldSkipHeadlessVisualSystems(); } } [HarmonyPatch(typeof(ShieldDomeImageEffect), "Awake")] internal static class ShieldDomeAwakeHeadlessPatch { private static bool Prefix(ShieldDomeImageEffect __instance) { if (!TerramizerServerPlugin.ShouldSkipHeadlessVisualSystems()) { return true; } if ((Object)(object)__instance != (Object)null) { ((Behaviour)__instance).enabled = false; } return false; } } [HarmonyPatch(typeof(ShieldDomeImageEffect), "GetDomeColor")] internal static class ShieldDomeColorHeadlessPatch { private static bool Prefix(ref Color __result) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!TerramizerServerPlugin.ShouldSkipHeadlessVisualSystems()) { return true; } __result = Color.white; return false; } } [HarmonyPatch(typeof(EnvMan), "SkipToMorning")] internal static class EnvManSkipToMorningPatch { private static void Postfix(EnvMan __instance) { TerramizerServerPlugin.TuneSleepFastForward(__instance); } } [HarmonyPatch(typeof(Game), "SleepStop")] internal static class GameSleepStopPatch { private static void Prefix(Game __instance, out float __state) { __state = TerramizerServerPlugin.CaptureSleepSaveTimer(__instance); } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { MethodInfo worldSave = AccessTools.Method(typeof(ZNet), "Save", new Type[3] { typeof(bool), typeof(bool), typeof(bool) }, (Type[])null); MethodInfo worldReplacement = AccessTools.Method(typeof(TerramizerServerPlugin), "SaveWorldFromSleep", (Type[])null, (Type[])null); if (worldSave == null) { throw new InvalidOperationException("Could not resolve ZNet.Save(bool, bool, bool)."); } if (worldReplacement == null) { throw new InvalidOperationException("Could not resolve TerramizerServer SaveWorldFromSleep replacement."); } int worldReplacements = 0; foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, worldSave)) { instruction.opcode = OpCodes.Call; instruction.operand = worldReplacement; worldReplacements++; } yield return instruction; } if (worldReplacements != 1) { throw new InvalidOperationException("Expected one world-save call in Game.SleepStop, found " + worldReplacements + "."); } } private static void Postfix(Game __instance, float __state) { TerramizerServerPlugin.RestoreSleepSaveTimer(__instance, __state); } } [BepInPlugin("r4v9n1.terramizerserver", "TerramizerServer", "1.0.6")] public sealed class TerramizerServerPlugin : BaseUnityPlugin { private struct PeerState { internal bool HasZone; internal Vector2s Zone; internal float NextTime; } private static ConfigEntry<bool> _streamingBoostEnabled; private static ConfigEntry<int> _streamingBoostMaxZdos; private static ConfigEntry<float> _streamingBoostCooldown; private static ConfigEntry<int> _streamingBoostMaxQueuePercent; private static readonly Dictionary<long, PeerState> _streamingPeerStates = new Dictionary<long, PeerState>(); private static readonly List<ZDO> _streamingNear = new List<ZDO>(512); private static readonly List<ZDO> _streamingCandidates = new List<ZDO>(512); private static readonly HashSet<ZDOID> _streamingSeen = new HashSet<ZDOID>(); private static Vector3 _streamingReferencePosition; private static float _nextStreamingPassTime; private static bool _streamingFailureLogged; public const string PluginGuid = "r4v9n1.terramizerserver"; public const string PluginName = "TerramizerServer"; public const string PluginVersion = "1.0.6"; public const string CreatorCredit = "Created by R4V9N1"; private const string SyncedVersionKey = "r4v9n1.terramizerserver.version"; private const string SyncedStaticOwnershipKey = "r4v9n1.terramizerserver.staticOwnership"; private const string SyncedOwnershipCacheKey = "r4v9n1.terramizerserver.ownershipCache"; private const string SyncedTerrainLimitsEnabledKey = "r4v9n1.terramizerserver.extendedTerrainLimits"; private const string SyncedTerrainRaiseLimitKey = "r4v9n1.terramizerserver.terrainRaiseLimit"; private const string SyncedTerrainDigLimitKey = "r4v9n1.terramizerserver.terrainDigLimit"; private const string RpcRequestCompanionMetadata = "r4v9n1.terramizerserver.RequestCompanionMetadata"; private const string RpcCompanionMetadata = "r4v9n1.terramizerserver.CompanionMetadata"; private const string RpcRequestCompanionMetadataV2 = "r4v9n1.terramizerserver.RequestCompanionMetadataV2"; private const string RpcCompanionMetadataV2 = "r4v9n1.terramizerserver.CompanionMetadataV2"; private static ConfigEntry<bool> _enabled; private static ConfigEntry<bool> _dedicatedOnly; private static ConfigEntry<bool> _disableUnityJobDebugger; private static ConfigEntry<bool> _reuseCollisionCallbacks; private static ConfigEntry<bool> _enableStaticPieceServerOwnership; private static ConfigEntry<bool> _dryRunStaticPieceServerOwnership; private static ConfigEntry<bool> _playerBuiltPiecesOnly; private static ConfigEntry<bool> _requireWearNTear; private static ConfigEntry<float> _ownershipScanIntervalSeconds; private static ConfigEntry<int> _maxClaimsPerScan; private static ConfigEntry<int> _zdoRecordsPerScan; private static ConfigEntry<float> _maintenanceOwnershipScanIntervalSeconds; private static ConfigEntry<int> _maintenanceMaxClaimsPerScan; private static ConfigEntry<int> _maintenanceZdoRecordsPerScan; private static ConfigEntry<bool> _enableBackgroundOwnershipAudit; private static ConfigEntry<bool> _enableOwnershipCache; private static ConfigEntry<float> _ownershipCacheMaxAgeHours; private static ConfigEntry<int> _ownershipCacheRecordsPerScan; private static ConfigEntry<int> _maxCacheRestoresPerScan; private static ConfigEntry<bool> _resumeZdoScanFromCache; private static ConfigEntry<bool> _logDevClaims; private static ConfigEntry<bool> _logWatchedClaims; private static ConfigEntry<bool> _logDevSkips; private static ConfigEntry<float> _devSummaryIntervalSeconds; private static ConfigEntry<bool> _speedUpSleepFastForward; private static ConfigEntry<float> _sleepFastForwardSeconds; private static ConfigEntry<bool> _skipSleepWorldSave; private static ConfigEntry<bool> _preserveAutosaveTimer; private static ConfigEntry<bool> _logSkippedSleepSaves; private static FieldInfo _envManSkipToTimeField; private static FieldInfo _envManTimeSkipSpeedField; private static FieldInfo _gameSaveTimerField; private static ManualLogSource _log; private static FieldInfo _objectsByIdField; private static int _zdoScanIndex; private static int _ownershipCacheScanIndex; private static bool _ownershipCacheWarmStartComplete; private static bool _ownershipCacheDirty; private static bool _serverMetadataAdvertised; private static bool _loadedZdoScanCursorPending; private static bool _initialBroadScanComplete; private static bool _initialBroadScanTraversalComplete; private static bool _pendingInitialBroadScanCompletion; private static bool _ownershipCacheWorldValidated; private static long _cachedOwnershipWorldUid; private static bool _companionRpcReplyLogged; private static bool _applicationQuitting; private static bool _ownershipPatchFailureLogged; private static bool _ownershipMaintenanceFailureLogged; private static bool _firstBroadScanStatusStarted; private static bool _firstBroadScanStatusCompleted; private static float _nextFirstBroadScanStatusTime; private static string _ownershipCachePath; private static float _nextOwnershipScanTime; private static float _nextDevSummaryTime; private static float _nextOwnershipCacheFlushTime; private static ZNet _metadataAdvertisedForInstance; private static int _cachedZdoScanIndex; private static int _cachedZdoScanObjectCount; private static int _zdoBroadScanPassesCompleted; private static long _cachedZdoScanUpdatedUnixSeconds; private static long _claimAttempts; private static long _claimed; private static long _totalClaimed; private static long _watchedClaims; private static long _totalWatchedClaims; private static long _alreadyServerOwned; private static long _skippedNotReady; private static long _skippedNotPersistent; private static long _skippedNoCreator; private static long _skippedNoWearNTear; private static long _skippedDynamic; private static long _skippedNoZdo; private static long _skippedNoPrefab; private static long _skippedNotPiecePrefab; private static long _zdoRecordsChecked; private static long _cacheRecordsChecked; private static long _cacheRestored; private static long _totalCacheRestored; private static long _cacheRemoved; private static long _companionRpcReplies; private static readonly Dictionary<int, bool> _prefabEligibilityCache = new Dictionary<int, bool>(); private static readonly Dictionary<string, OwnershipCacheEntry> _ownershipCache = new Dictionary<string, OwnershipCacheEntry>(); private static readonly Queue<string> _deferredOwnershipClaims = new Queue<string>(); private static readonly HashSet<string> _deferredOwnershipClaimSet = new HashSet<string>(); private static ZRoutedRpc _registeredRoutedRpcInstance; private Harmony _harmony; private static ConfigEntry<bool> _enableExtendedTerrainLimits; private static ConfigEntry<float> _terrainRaiseLimitMeters; private static ConfigEntry<float> _terrainDigLimitMeters; internal static void TuneSleepFastForward(EnvMan envMan) { if (Application.isBatchMode && _speedUpSleepFastForward != null && _speedUpSleepFastForward.Value && !((Object)(object)envMan == (Object)null) && envMan.IsTimeSkipping() && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !(_envManSkipToTimeField == null) && !(_envManTimeSkipSpeedField == null)) { double num = (double)_envManSkipToTimeField.GetValue(envMan) - ZNet.instance.GetTimeSeconds(); if (num > 0.0) { _envManTimeSkipSpeedField.SetValue(envMan, num / (double)Mathf.Clamp(_sleepFastForwardSeconds.Value, 1f, 60f)); } } } internal static float CaptureSleepSaveTimer(Game game) { if ((Object)(object)game == (Object)null || _skipSleepWorldSave == null || !_skipSleepWorldSave.Value || _preserveAutosaveTimer == null || !_preserveAutosaveTimer.Value || _gameSaveTimerField == null) { return float.NaN; } return (float)_gameSaveTimerField.GetValue(game); } internal static void RestoreSleepSaveTimer(Game game, float timer) { if (!((Object)(object)game == (Object)null) && !float.IsNaN(timer) && !(_gameSaveTimerField == null)) { _gameSaveTimerField.SetValue(game, timer); } } internal static void SaveWorldFromSleep(ZNet znet, bool sync, bool saveOtherPlayerProfiles, bool waitForNextFrame) { if (_skipSleepWorldSave == null || !_skipSleepWorldSave.Value) { if ((Object)(object)znet != (Object)null) { znet.Save(sync, saveOtherPlayerProfiles, waitForNextFrame); } } else if (_logSkippedSleepSaves != null && _logSkippedSleepSaves.Value && _log != null) { _log.LogInfo((object)"Skipped sleep-triggered world save. Regular autosaves remain enabled."); } } private static bool CanRunServerStreaming() { if (_enabled != null && _enabled.Value && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { if (_dedicatedOnly.Value) { return ZNet.instance.IsDedicated(); } return true; } return false; } private void InitializeStreaming() { _streamingBoostEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Streaming", "EnableServerZoneStreamingBoost", true, "Prefetches a bounded set of existing nearby ZDOs when a ready peer enters a new zone. Does not create zones or scene objects."); _streamingBoostMaxZdos = BindRange("Streaming", "MaxZoneStreamingBoostZdosPerPeer", 256, "Maximum existing ZDOs force-queued for one peer per zone transition.", 0, 2000); _streamingBoostCooldown = BindRange("Streaming", "ZoneStreamingBoostCooldownSeconds", 0.75f, "Minimum time between a peer's bounded streaming boosts.", 0.1f, 10f); _streamingBoostMaxQueuePercent = BindRange("Streaming", "ZoneStreamingBoostMaxQueuePercent", 35, "Do not prefetch while the peer socket queue is above this percentage of its ceiling.", 10, 90); } private static void RunStreamingBoost() { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) if (_streamingBoostEnabled == null || !_streamingBoostEnabled.Value || !CanRunServerStreaming() || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsDedicated() || ZDOMan.instance == null || (Object)(object)ZoneSystem.instance == (Object)null) { return; } try { float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < _nextStreamingPassTime) { return; } _nextStreamingPassTime = realtimeSinceStartup + 0.1f; List<ZNetPeer> connectedPeers = ZNet.instance.GetConnectedPeers(); if (connectedPeers == null) { return; } SimulationDistance val2 = default(SimulationDistance); for (int i = 0; i < connectedPeers.Count; i++) { ZNetPeer val = connectedPeers[i]; if (val == null || !val.IsReady() || val.m_socket == null) { continue; } Vector3 refPos = val.GetRefPos(); Vector2s zone = ZoneSystem.GetZone(refPos); if (!_streamingPeerStates.TryGetValue(val.m_uid, out var value)) { value = default(PeerState); } if (realtimeSinceStartup < value.NextTime || (value.HasZone && value.Zone == zone)) { continue; } if ((long)val.m_socket.GetSendQueueSize() * 100L >= 10240L * (long)_streamingBoostMaxQueuePercent.Value) { value.NextTime = realtimeSinceStartup + 0.25f; _streamingPeerStates[val.m_uid] = value; continue; } _streamingNear.Clear(); _streamingCandidates.Clear(); _streamingSeen.Clear(); SimulationDistance simulationDistance = val.m_simulationDistance; ((SimulationDistance)(ref val2))..ctor(((SimulationDistance)(ref simulationDistance)).NearSimulationDistance, 0, ((SimulationDistance)(ref simulationDistance)).IsClassic); ZDOMan.instance.FindSectorObjects(zone, val2, _streamingNear, (List<ZDO>)null); _streamingReferencePosition = refPos; for (int j = 0; j < _streamingNear.Count; j++) { ZDO val3 = _streamingNear[j]; if (val3 != null && val3.IsValid() && !((ZDOID)(ref val3.m_uid)).IsNone() && _streamingSeen.Add(val3.m_uid) && (!((Object)(object)ZNetScene.instance != (Object)null) || ZNetScene.instance.HasPrefab(val3.GetPrefab())) && !ShouldDeferTerrainZdo(val3)) { _streamingCandidates.Add(val3); } } _streamingCandidates.Sort(CompareStreamingDistance); int num = Math.Min(_streamingBoostMaxZdos.Value, _streamingCandidates.Count); for (int k = 0; k < num; k++) { ZDOMan.instance.ForceSendZDO(val.m_uid, _streamingCandidates[k].m_uid); } value.HasZone = true; value.Zone = zone; value.NextTime = realtimeSinceStartup + _streamingBoostCooldown.Value; _streamingPeerStates[val.m_uid] = value; } _streamingNear.Clear(); _streamingCandidates.Clear(); _streamingSeen.Clear(); } catch (Exception ex) { if (!_streamingFailureLogged) { _streamingFailureLogged = true; ManualLogSource log = _log; if (log != null) { log.LogWarning((object)("Bounded zone streaming boost disabled after an unexpected runtime shape: " + ex.Message)); } } } } private static int CompareStreamingDistance(ZDO left, ZDO right) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) Vector3 val = left.GetPosition() - _streamingReferencePosition; Vector3 val2 = right.GetPosition() - _streamingReferencePosition; float num = val.x * val.x + val.z * val.z; float num2 = val2.x * val2.x + val2.z * val2.z; return Utils.CompareFloats(num, num2); } private static bool ShouldDeferTerrainZdo(ZDO zdo) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNetScene.instance == (Object)null) { return false; } try { GameObject prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab()); if ((Object)(object)prefab == (Object)null || ((Object)(object)prefab.GetComponent<TerrainComp>() == (Object)null && (Object)(object)prefab.GetComponentInChildren<TerrainComp>(true) == (Object)null)) { return false; } return (Object)(object)Heightmap.FindHeightmap(zdo.GetPosition()) == (Object)null; } catch { return true; } } private void Awake() { _log = ((BaseUnityPlugin)this).Logger; _enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable TerramizerServer runtime features."); _dedicatedOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DedicatedOnly", true, "Apply runtime features only in a batch-mode dedicated-server process."); BindTerrainCompatibilityConfig(); _disableUnityJobDebugger = ((BaseUnityPlugin)this).Config.Bind<bool>("Performance", "DisableUnityJobDebugger", true, "Disable Unity's development-only job debugger without changing simulation, networking, ownership, objects, or saves."); _reuseCollisionCallbacks = ((BaseUnityPlugin)this).Config.Bind<bool>("Performance", "ReuseCollisionCallbacks", true, "Reuse Unity collision callback objects to reduce physics GC allocations. Disable for mods that retain Collision objects after callbacks."); _enableStaticPieceServerOwnership = ((BaseUnityPlugin)this).Config.Bind<bool>("ExperimentalOwnership", "EnableStaticPieceServerOwnership", true, "EXPERIMENTAL: make the dedicated server claim ownership of loaded, static, player-created structure pieces while preserving their creator field."); _dryRunStaticPieceServerOwnership = ((BaseUnityPlugin)this).Config.Bind<bool>("ExperimentalOwnership", "DryRunStaticPieceServerOwnership", false, "Log which pieces would be claimed without changing ZDO ownership."); _playerBuiltPiecesOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("ExperimentalOwnership", "PlayerBuiltPiecesOnly", true, "Only claim pieces with a non-zero Valheim creator field."); _requireWearNTear = ((BaseUnityPlugin)this).Config.Bind<bool>("ExperimentalOwnership", "RequireWearNTear", true, "Only claim structure-style pieces that have WearNTear. This avoids crops and other non-structural placed objects."); _ownershipScanIntervalSeconds = BindRange("ExperimentalOwnership", "OwnershipScanIntervalSeconds", 5f, "Seconds between heavy initial ownership scan passes. Newly loaded pieces are handled immediately.", 1f, 120f); _maxClaimsPerScan = BindRange("ExperimentalOwnership", "MaxClaimsPerScan", 100, "Maximum ZDO ownership changes allowed per scan.", 1, 5000); _zdoRecordsPerScan = BindRange("ExperimentalOwnership", "ZdoRecordsPerScan", 25000, "Maximum persistent ZDO records inspected per heavy initial scan pass.", 100, 100000); _maintenanceOwnershipScanIntervalSeconds = BindRange("ExperimentalOwnership", "MaintenanceOwnershipScanIntervalSeconds", 15f, "Seconds between maintenance integrity audits after the verified initial world pass. New/loaded pieces are handled immediately.", 5f, 21600f); _maintenanceMaxClaimsPerScan = BindRange("ExperimentalOwnership", "MaintenanceMaxClaimsPerScan", 25, "Maximum ZDO ownership changes allowed per maintenance scan after the first full broad pass.", 1, 5000); _maintenanceZdoRecordsPerScan = BindRange("ExperimentalOwnership", "MaintenanceZdoRecordsPerScan", 5000, "Maximum persistent ZDO records inspected per maintenance scan after the verified first full broad pass.", 100, 100000); _enableBackgroundOwnershipAudit = ((BaseUnityPlugin)this).Config.Bind<bool>("ExperimentalOwnership", "EnableBackgroundOwnershipAudit", true, "Run the legacy whole-world ZDO ownership audit. Disabled by default because event-driven claims cover newly loaded structures without scanning the live world table."); _enableOwnershipCache = ((BaseUnityPlugin)this).Config.Bind<bool>("OwnershipCache", "EnableOwnershipCache", true, "Store known eligible claimed ZDOs so restart warm-start can quickly reassign them to the new server session id."); _ownershipCacheMaxAgeHours = BindRange("OwnershipCache", "OwnershipCacheMaxAgeHours", 168f, "Maximum age in hours for remembered ownership records. Older cache rows are ignored and removed.", 1f, 2160f); _ownershipCacheRecordsPerScan = BindRange("OwnershipCache", "OwnershipCacheRecordsPerScan", 200000, "Maximum cached ownership records inspected per restart warm-start pass.", 1000, 1000000); _maxCacheRestoresPerScan = BindRange("OwnershipCache", "MaxCacheRestoresPerScan", 5000, "Maximum cached ownership restores applied per warm-start pass.", 1, 50000); _resumeZdoScanFromCache = ((BaseUnityPlugin)this).Config.Bind<bool>("OwnershipCache", "ResumeZdoScanFromCache", true, "Resume the broad ZDO eligibility scan from the last persisted scan index after server restart. The cache clamps this index if the world ZDO count changed."); MigrateOwnershipScanBudgetsFrom104Defaults(); _logDevClaims = ((BaseUnityPlugin)this).Config.Bind<bool>("DevLogs", "LogOwnershipClaims", false, "Log every static piece ownership claim or dry-run claim. This is very noisy on established worlds."); _logWatchedClaims = ((BaseUnityPlugin)this).Config.Bind<bool>("DevLogs", "LogWatchedOwnershipClaims", false, "Log ownership claims for sensitive interactive prefabs such as beds, chests, portals, fires, stations, signs, item stands, wards, doors, and gates."); _logDevSkips = ((BaseUnityPlugin)this).Config.Bind<bool>("DevLogs", "LogOwnershipSkips", false, "Log skipped pieces. This is noisy and should only be enabled during focused testing."); _devSummaryIntervalSeconds = BindRange("DevLogs", "OwnershipSummaryIntervalSeconds", 60f, "Seconds between compact ownership experiment summaries.", 5f, 600f); _speedUpSleepFastForward = ((BaseUnityPlugin)this).Config.Bind<bool>("Sleep", "SpeedUpSleepFastForward", true, "Tune sleep time-skip to the configured real-time duration."); _sleepFastForwardSeconds = BindRange("Sleep", "SleepFastForwardSeconds", 4f, "Target real seconds for sleep time-skip.", 1f, 60f); _skipSleepWorldSave = ((BaseUnityPlugin)this).Config.Bind<bool>("Sleep", "SkipSleepWorldSave", true, "Skip the extra world save triggered when sleep ends."); _preserveAutosaveTimer = ((BaseUnityPlugin)this).Config.Bind<bool>("Sleep", "PreserveAutosaveTimer", true, "Keep the regular autosave timer unchanged when the sleep save is skipped."); _logSkippedSleepSaves = ((BaseUnityPlugin)this).Config.Bind<bool>("Sleep", "LogSkippedSleepSaves", true, "Log when the sleep-triggered world save is skipped."); InitializeStreaming(); RemoveRetiredSettings(); _envManSkipToTimeField = AccessTools.Field(typeof(EnvMan), "m_skipToTime"); _envManTimeSkipSpeedField = AccessTools.Field(typeof(EnvMan), "m_timeSkipSpeed"); _gameSaveTimerField = AccessTools.Field(typeof(Game), "m_saveTimer"); if (_enableBackgroundOwnershipAudit.Value) { LoadOwnershipCache(); } ApplySafeRuntimeSetting(); InstallExperimentalPatches(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"TerramizerServer 1.0.6 loaded."); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Static piece server ownership experiment: enabled=" + _enableStaticPieceServerOwnership.Value + ", dryRun=" + _dryRunStaticPieceServerOwnership.Value + ", playerBuiltOnly=" + _playerBuiltPiecesOnly.Value + ", requireWearNTear=" + _requireWearNTear.Value + ".")); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Creator fields are preserved. WearNTear is not removed. Dynamic physics objects remain peer-owned."); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Bounded zone streaming prefetch: enabled=" + _streamingBoostEnabled.Value + ", maxZdosPerPeer=" + _streamingBoostMaxZdos.Value + ", cooldown=" + _streamingBoostCooldown.Value.ToString("F2") + "s, socket backpressure=" + _streamingBoostMaxQueuePercent.Value + "%. Peer-zone scene creation remains disabled.")); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Created by R4V9N1."); } private ConfigEntry<T> BindRange<T>(string section, string key, T defaultValue, string description, T minimum, T maximum) where T : IComparable { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown return ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<T>(minimum, maximum), Array.Empty<object>())); } private void ApplySafeRuntimeSetting() { if (!_enabled.Value || (_dedicatedOnly.Value && !Application.isBatchMode)) { return; } try { if (_disableUnityJobDebugger.Value && JobsUtility.JobDebuggerEnabled) { JobsUtility.JobDebuggerEnabled = false; } Physics.reuseCollisionCallbacks = _reuseCollisionCallbacks.Value; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Unity's development job debugger is disabled; all server game systems remain unmodified."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not change Unity's optional job-debugger setting; continuing with vanilla behavior: " + ex.Message)); } } private void InstallExperimentalPatches() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (_enabled.Value && (!_dedicatedOnly.Value || Application.isBatchMode)) { _harmony = new Harmony("r4v9n1.terramizerserver"); BinarySearchDictionarySetValuePatch.Install(_harmony, (Action<string>)((BaseUnityPlugin)this).Logger.LogInfo); TryPatch(typeof(VisEquipmentIntCachePatch), "VisEquipment ZDO integer lookup cache"); TryPatch(typeof(ZPackageWritePackagePatch), "allocation-free ZPackage nesting"); TryPatch(typeof(ZdoOwnershipHandoffPatch), "optimized ZDO ownership handoff scan"); TryPatch(typeof(ZNetViewAwakeStaticOwnershipPatch), "ZNetView creation ownership observation"); TryPatch(typeof(EnvManSkipToMorningPatch), "sleep fast-forward"); TryPatch(typeof(GameSleepStopPatch), "sleep save policy"); TryPatch(typeof(HeightmapAtMaxWorldLevelDepthTerrainLimitPatch), "world heightmap dig-depth terrain limit"); TryPatch(typeof(HeightmapLevelTerrainTerrainLimitPatch), "heightmap terrain raise/dig limits"); TryPatch(typeof(TerrainCompLevelTerrainLimitPatch), "terrain component raise/dig limits"); TryPatch(typeof(TerrainCompRaiseTerrainLimitPatch), "terrain component direct raise limit"); TryPatch(typeof(TerrainCompApplyToHeightmapTerrainLimitPatch), "terrain final-apply limits"); TryPatch(typeof(AudioManHeadlessPatch), "headless audio guard"); TryPatch(typeof(ShieldDomeAwakeHeadlessPatch), "headless shield initialization guard"); TryPatch(typeof(ShieldDomeColorHeadlessPatch), "headless shield color guard"); } } private void TryPatch(Type patchType, string name) { try { _harmony.CreateClassProcessor(patchType).Patch(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Installed " + name + ".")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not install " + name + "; continuing without that patch: " + ex.Message)); } } internal static bool ShouldSkipHeadlessVisualSystems() { return Application.isBatchMode; } private void Update() { RegisterCompanionRpcsWhenReady(); AdvertiseServerMetadata(); RunStreamingBoost(); if (!ShouldRunExperiment()) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (_enableBackgroundOwnershipAudit.Value && _enableOwnershipCache.Value && !_ownershipCacheWarmStartComplete) { try { if (EnsureOwnershipCacheWorldIdentity()) { ApplyOwnershipCacheWarmStart(); } } catch (Exception ex) { LogOwnershipMaintenanceFailure(ex); } } if (_enableBackgroundOwnershipAudit.Value && realtimeSinceStartup >= _nextOwnershipScanTime) { try { SweepLoadedPieces(); } catch (Exception ex2) { LogOwnershipMaintenanceFailure(ex2); } _nextOwnershipScanTime = realtimeSinceStartup + GetOwnershipScanIntervalSeconds(); } if (_enableBackgroundOwnershipAudit.Value && realtimeSinceStartup >= _nextDevSummaryTime) { _nextDevSummaryTime = realtimeSinceStartup + _devSummaryIntervalSeconds.Value; LogOwnershipSummary(); } if (_ownershipCacheDirty && realtimeSinceStartup >= _nextOwnershipCacheFlushTime) { FlushOwnershipCache(force: false); } } private void OnDestroy() { FlushOwnershipCache(force: true); if (_harmony != null && !_applicationQuitting) { try { _harmony.UnpatchSelf(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not unpatch TerramizerServer during teardown; process shutdown can continue safely: " + ex.Message)); } _harmony = null; } } private void OnApplicationQuit() { _applicationQuitting = true; FlushOwnershipCache(force: true); } internal static void TryClaimFromZNetView(ZNetView view, string reason) { try { if (!ShouldRunExperiment() || (Object)(object)view == (Object)null) { return; } ZDO zDO = view.GetZDO(); if (zDO == null) { return; } if ((Object)(object)ZNetScene.instance != (Object)null) { int prefab = zDO.GetPrefab(); GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab); if ((Object)(object)prefab2 != (Object)null && !IsEligibleStaticPiecePrefab(prefab, prefab2)) { return; } } Piece val = ((Component)view).GetComponent<Piece>(); if ((Object)(object)val == (Object)null) { val = ((Component)view).GetComponentInChildren<Piece>(true); } if (!((Object)(object)val == (Object)null)) { TryClaimPiece(val, reason, allowClaimLimit: false, null); } } catch (Exception ex) { if (!_ownershipPatchFailureLogged && _log != null) { _ownershipPatchFailureLogged = true; _log.LogWarning((object)("Static ownership observation failed; the affected object remains vanilla-owned: " + ex.Message)); } } } private static void SweepLoadedPieces() { Piece[] array = Object.FindObjectsByType<Piece>((FindObjectsSortMode)0); int claims = 0; int maxClaimsPerScan = GetMaxClaimsPerScan(); for (int i = 0; i < array.Length; i++) { if (claims >= maxClaimsPerScan) { break; } int num = claims; TryClaimPiece(array[i], "sweep", allowClaimLimit: true, delegate { claims++; }); if (claims != num && _dryRunStaticPieceServerOwnership.Value) { claims = num + 1; } } SweepZdoRecords(Math.Max(0, maxClaimsPerScan - claims)); } private static void TryClaimPiece(Piece piece, string reason, bool allowClaimLimit, Action claimsThisScan) { //IL_01e3: Unknown result type (might be due to invalid IL or missing references) _claimAttempts++; if ((Object)(object)piece == (Object)null || (Object)(object)((Component)piece).gameObject == (Object)null) { _skippedNotReady++; return; } ZNetView val = ((Component)piece).GetComponent<ZNetView>(); if ((Object)(object)val == (Object)null) { val = ((Component)piece).GetComponentInParent<ZNetView>(); } if ((Object)(object)val == (Object)null) { val = ((Component)piece).GetComponentInChildren<ZNetView>(true); } if ((Object)(object)val == (Object)null || !val.IsValid() || val.GetZDO() == null) { _skippedNoZdo++; LogSkip(piece, "no valid ZDO"); return; } ZDO zDO = val.GetZDO(); if (!zDO.Persistent) { _skippedNotPersistent++; LogSkip(piece, "not persistent"); return; } long num = zDO.GetLong(ZDOVars.s_creator, 0L); if (_playerBuiltPiecesOnly.Value && num == 0L) { _skippedNoCreator++; LogSkip(piece, "no player creator"); return; } if (_requireWearNTear.Value && (Object)(object)((Component)piece).GetComponent<WearNTear>() == (Object)null && (Object)(object)((Component)piece).GetComponentInChildren<WearNTear>(true) == (Object)null) { _skippedNoWearNTear++; LogSkip(piece, "no WearNTear"); return; } if (IsDynamicOrPhysicsObject(((Component)piece).gameObject)) { _skippedDynamic++; LogSkip(piece, "dynamic or physics object"); return; } string prefabName = CleanPrefabName(((Object)((Component)piece).gameObject).name); long sessionID = ZDOMan.GetSessionID(); long owner = zDO.GetOwner(); if (owner == sessionID) { _alreadyServerOwned++; RecordOwnershipCache(zDO, prefabName, num); return; } if (_dryRunStaticPieceServerOwnership.Value) { _claimed++; _totalClaimed++; claimsThisScan?.Invoke(); LogClaim("DRY-RUN would claim", prefabName, zDO, owner, num, reason); return; } zDO.SetOwner(sessionID); if (ZDOMan.instance != null) { ZDOMan.instance.ForceSendZDO(zDO.m_uid); } _claimed++; _totalClaimed++; RecordOwnershipCache(zDO, prefabName, num); claimsThisScan?.Invoke(); LogClaim("Claimed", prefabName, zDO, owner, num, reason); } private static void SweepZdoRecords(int remainingClaimBudget) { if (ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { return; } Dictionary<ZDOID, ZDO> objectsById = GetObjectsById(); if (objectsById == null || objectsById.Count == 0 || !EnsureOwnershipCacheWorldIdentity()) { return; } int num = Math.Max(0, remainingClaimBudget); int num2 = DrainDeferredOwnershipClaims(objectsById, num); if (_initialBroadScanTraversalComplete && !_initialBroadScanComplete) { PersistZdoScanCursor(objectsById.Count); if (_deferredOwnershipClaims.Count == 0) { CommitInitialBroadScanCompletion(objectsById.Count); LogFirstBroadScanStatus(objectsById.Count, _initialBroadScanComplete); } return; } ApplyCachedZdoScanCursor(objectsById.Count); ValidateCachedScanPassState(objectsById.Count); LogFirstBroadScanStatus(objectsById.Count, completed: false); if (_zdoScanIndex >= objectsById.Count) { _zdoScanIndex = 0; } int num3 = 0; int num4 = 0; int zdoRecordsPerScan = GetZdoRecordsPerScan(); try { foreach (KeyValuePair<ZDOID, ZDO> item in objectsById) { if (num3++ >= _zdoScanIndex) { if (num4 >= zdoRecordsPerScan) { break; } num4++; _zdoRecordsChecked++; bool allowOwnershipChange = num2 < num; if (TryClaimZdoRecord(item.Value, "zdo-sweep", allowOwnershipChange)) { num2++; } } } } catch (InvalidOperationException ex) { _zdoScanIndex = 0; if (_log != null) { _log.LogWarning((object)("[dev ownership] ZDO scan restarted because the ZDO table changed during enumeration: " + ex.Message)); } return; } bool flag = _zdoScanIndex + num4 >= objectsById.Count; _zdoScanIndex += num4; if (flag || num4 == 0) { _zdoScanIndex = 0; if (flag && num4 > 0) { MarkBroadZdoScanPassComplete(objectsById.Count); } } PersistZdoScanCursor(objectsById.Count); if (flag && num4 > 0 && _pendingInitialBroadScanCompletion) { if (_deferredOwnershipClaims.Count == 0) { CommitInitialBroadScanCompletion(objectsById.Count); } else if (_log != null) { _log.LogInfo((object)("[ownership scan] Initial broad traversal reached 100%; waiting for " + _deferredOwnershipClaims.Count + " deferred ownership changes to drain before durable maintenance handoff.")); } } LogFirstBroadScanStatus(objectsById.Count, flag && num4 > 0 && _initialBroadScanComplete); } private static int DrainDeferredOwnershipClaims(Dictionary<ZDOID, ZDO> objects, int claimBudget) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (objects == null || claimBudget <= 0 || _deferredOwnershipClaims.Count == 0) { return 0; } int num = 0; int count = _deferredOwnershipClaims.Count; bool flag = false; while (num < claimBudget && count-- > 0 && _deferredOwnershipClaims.Count > 0) { string text = _deferredOwnershipClaims.Dequeue(); _deferredOwnershipClaimSet.Remove(text); flag = true; if (TryParseZdoId(text, out var id) && objects.TryGetValue(id, out var value) && TryClaimZdoRecord(value, "zdo-deferred", allowOwnershipChange: true)) { num++; } } if (flag) { MarkOwnershipCacheDirty(); } return num; } private static void EnqueueDeferredOwnershipClaim(ZDO zdo) { if (zdo != null && zdo.IsValid()) { string item = ((object)Unsafe.As<ZDOID, ZDOID>(ref zdo.m_uid)/*cast due to .constrained prefix*/).ToString(); if (_deferredOwnershipClaimSet.Add(item)) { _deferredOwnershipClaims.Enqueue(item); MarkOwnershipCacheDirty(); } } } private static void MarkOwnershipCacheDirty() { _ownershipCacheDirty = true; if (_nextOwnershipCacheFlushTime <= 0f) { _nextOwnershipCacheFlushTime = Time.realtimeSinceStartup + 30f; } } private static void LogFirstBroadScanStatus(int objectCount, bool completed) { if (_log == null || !_enableBackgroundOwnershipAudit.Value || (_zdoBroadScanPassesCompleted > 0 && _firstBroadScanStatusCompleted)) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (completed || !_firstBroadScanStatusStarted || !(realtimeSinceStartup < _nextFirstBroadScanStatusTime)) { if (!_firstBroadScanStatusStarted) { _firstBroadScanStatusStarted = true; float val = (float)GetZdoRecordsPerScan() / Math.Max(1f, GetOwnershipScanIntervalSeconds()); float num = 5000f; float seconds = (float)objectCount / Math.Max(1f, val); _nextFirstBroadScanStatusTime = realtimeSinceStartup + 30f; _log.LogInfo((object)("[ownership scan] First broad ZDO scan started: " + objectCount + " records; estimated time " + FormatScanDuration(seconds) + " at current budget (" + val.ToString("F0") + " records/s). Prior measured warm-up reference was " + num.ToString("F0") + " records/s with a 25,000/5s budget.")); } else if (completed) { _firstBroadScanStatusCompleted = true; _log.LogInfo((object)("[ownership scan] First broad ZDO scan completed: " + objectCount + " records inspected. Switching to maintenance mode.")); } else { int num2 = Math.Min(Math.Max(_zdoScanIndex, 0), objectCount); int num3 = Math.Max(0, objectCount - num2); float val2 = (float)GetZdoRecordsPerScan() / Math.Max(1f, GetOwnershipScanIntervalSeconds()); float seconds2 = (float)num3 / Math.Max(1f, val2); float num4 = ((objectCount > 0) ? ((float)num2 * 100f / (float)objectCount) : 100f); _nextFirstBroadScanStatusTime = realtimeSinceStartup + 30f; _log.LogInfo((object)("[ownership scan] First broad scan progress: " + num4.ToString("F1") + "% (" + num2 + "/" + objectCount + "); estimated remaining " + FormatScanDuration(seconds2) + ".")); } } } private static string FormatScanDuration(float seconds) { if (seconds < 60f) { return Math.Max(0, (int)Math.Ceiling(seconds)) + " seconds"; } int num = (int)(seconds / 60f); int num2 = num / 60; num %= 60; if (num2 <= 0) { return num + "m"; } return num2 + "h " + num + "m"; } private static bool IsMaintenanceScanMode() { if (_initialBroadScanComplete && _ownershipCacheWorldValidated) { if (!_ownershipCacheWarmStartComplete && _enableOwnershipCache != null) { return !_enableOwnershipCache.Value; } return true; } return false; } private static float GetOwnershipScanIntervalSeconds() { if (IsMaintenanceScanMode() && _maintenanceOwnershipScanIntervalSeconds != null) { return _maintenanceOwnershipScanIntervalSeconds.Value; } if (_ownershipScanIntervalSeconds == null) { return 5f; } return _ownershipScanIntervalSeconds.Value; } private static int GetMaxClaimsPerScan() { if (IsMaintenanceScanMode() && _maintenanceMaxClaimsPerScan != null) { return _maintenanceMaxClaimsPerScan.Value; } if (_maxClaimsPerScan == null) { return 250; } return _maxClaimsPerScan.Value; } private static int GetZdoRecordsPerScan() { if (IsMaintenanceScanMode() && _maintenanceZdoRecordsPerScan != null) { return _maintenanceZdoRecordsPerScan.Value; } if (_zdoRecordsPerScan == null) { return 25000; } return _zdoRecordsPerScan.Value; } private static void MarkBroadZdoScanPassComplete(int objectCount) { _zdoBroadScanPassesCompleted++; _cachedZdoScanObjectCount = objectCount; _cachedZdoScanUpdatedUnixSeconds = GetUnixSeconds(); _ownershipCacheDirty = true; if (!_initialBroadScanComplete) { _initialBroadScanTraversalComplete = true; _pendingInitialBroadScanCompletion = true; } } private static void MigrateOwnershipScanBudgetsFrom104Defaults() { bool flag = false; if (Mathf.Approximately(_ownershipScanIntervalSeconds.Value, 15f)) { _ownershipScanIntervalSeconds.Value = 5f; flag = true; } if (_zdoRecordsPerScan.Value == 10000) { _zdoRecordsPerScan.Value = 25000; flag = true; } if (Mathf.Approximately(_maintenanceOwnershipScanIntervalSeconds.Value, 1800f)) { _maintenanceOwnershipScanIntervalSeconds.Value = 15f; flag = true; } if (_maintenanceZdoRecordsPerScan.Value == 1000) { _maintenanceZdoRecordsPerScan.Value = 5000; flag = true; } if (flag && _log != null) { _log.LogInfo((object)"[ownership scan] Migrated 1.0.4 default scan budgets to initial=25000/5s and maintenance=5000/15s."); } } private static long GetCurrentWorldUid() { try { if ((Object)(object)ZNet.instance == (Object)null) { return 0L; } MethodInfo methodInfo = AccessTools.Method(typeof(ZNet), "GetWorldUID", Type.EmptyTypes, (Type[])null); if (methodInfo == null) { if (_log != null) { _log.LogWarning((object)"[ownership cache] ZNet.GetWorldUID is unavailable; verified maintenance mode remains locked."); } return 0L; } object obj = methodInfo.Invoke(ZNet.instance, null); return (obj == null) ? 0 : Convert.ToInt64(obj); } catch (Exception ex) { if (_log != null) { _log.LogWarning((object)("[ownership cache] Could not resolve current world UID; verified maintenance mode remains locked: " + ex.Message)); } return 0L; } } private static bool EnsureOwnershipCacheWorldIdentity() { long currentWorldUid = GetCurrentWorldUid(); if (currentWorldUid == 0L) { _ownershipCacheWorldValidated = false; return false; } if (_ownershipCacheWorldValidated && _cachedOwnershipWorldUid == currentWorldUid) { return true; } if (_cachedOwnershipWorldUid != 0L && _cachedOwnershipWorldUid != currentWorldUid) { if (_log != null) { _log.LogInfo((object)"[ownership cache] Cached ownership state belongs to another world; clearing cached ownership data and restarting the heavy initial scan."); } _ownershipCache.Clear(); _ownershipCacheScanIndex = 0; _cachedZdoScanIndex = 0; _cachedZdoScanObjectCount = 0; _zdoBroadScanPassesCompleted = 0; _cachedZdoScanUpdatedUnixSeconds = 0L; _initialBroadScanComplete = false; _initialBroadScanTraversalComplete = false; _pendingInitialBroadScanCompletion = false; _deferredOwnershipClaims.Clear(); _deferredOwnershipClaimSet.Clear(); _loadedZdoScanCursorPending = false; _ownershipCacheWarmStartComplete = false; _ownershipCacheDirty = true; } _cachedOwnershipWorldUid = currentWorldUid; _ownershipCacheWorldValidated = true; _ownershipCacheDirty = true; return true; } private static void CommitInitialBroadScanCompletion(int objectCount) { if (!_pendingInitialBroadScanCompletion || _initialBroadScanComplete || !_initialBroadScanTraversalComplete || _deferredOwnershipClaims.Count > 0 || !EnsureOwnershipCacheWorldIdentity()) { return; } _cachedZdoScanIndex = 0; _cachedZdoScanObjectCount = objectCount; _cachedZdoScanUpdatedUnixSeconds = GetUnixSeconds(); _initialBroadScanComplete = true; MarkOwnershipCacheDirty(); if (!FlushOwnershipCache(force: true)) { _initialBroadScanComplete = false; _pendingInitialBroadScanCompletion = true; MarkOwnershipCacheDirty(); if (_log != null) { _log.LogWarning((object)"[ownership scan] Initial traversal and deferred claims completed, but durable cache commit failed; maintenance remains locked."); } return; } _pendingInitialBroadScanCompletion = false; if (_log != null) { _log.LogInfo((object)("[ownership scan] First broad ZDO scan reached 100%, deferred ownership claims are drained, and state was durably persisted for worldUid=" + _cachedOwnershipWorldUid + ". Switching to maintenance mode: interval=" + GetOwnershipScanIntervalSeconds() + "s, zdoRecordsPerScan=" + GetZdoRecordsPerScan() + ".")); } } private static Dictionary<ZDOID, ZDO> GetObjectsById() { if (_objectsByIdField == null) { _objectsByIdField = AccessTools.Field(typeof(ZDOMan), "m_objectsByID"); if (_objectsByIdField == null) { if (_log != null) { _log.LogWarning((object)"[dev ownership] Could not find ZDOMan.m_objectsByID; direct ZDO ownership scan is unavailable."); } return null; } } return _objectsByIdField.GetValue(ZDOMan.instance) as Dictionary<ZDOID, ZDO>; } private static void ApplyCachedZdoScanCursor(int currentObjectCount) { if (_loadedZdoScanCursorPending && _cachedZdoScanIndex > 0 && _resumeZdoScanFromCache != null && _resumeZdoScanFromCache.Value) { int num = _cachedZdoScanIndex; if (currentObjectCount > 0) { num = Mathf.Clamp(num, 0, currentObjectCount - 1); } _zdoScanIndex = num; if (_log != null) { _log.LogInfo((object)("[ownership cache] Resuming broad ZDO scan at index " + _zdoScanIndex + " from cached index " + _cachedZdoScanIndex + " with currentObjectCount=" + currentObjectCount + ", cachedObjectCount=" + _cachedZdoScanObjectCount + ".")); } _loadedZdoScanCursorPending = false; _cachedZdoScanIndex = 0; } } private static void ValidateCachedScanPassState(int currentObjectCount) { if (_zdoBroadScanPassesCompleted <= 0 || _cachedZdoScanObjectCount <= 0 || currentObjectCount <= 0) { return; } int num = Mathf.Abs(currentObjectCount - _cachedZdoScanObjectCount); int num2 = Mathf.Max(10000, _cachedZdoScanObjectCount / 10); if (num > num2) { if (_log != null) { _log.LogInfo((object)("[ownership cache] Cached broad-scan pass count was reset because the world ZDO count changed from " + _cachedZdoScanObjectCount + " to " + currentObjectCount + ".")); } _zdoBroadScanPassesCompleted = 0; _initialBroadScanComplete = false; _pendingInitialBroadScanCompletion = false; _cachedZdoScanObjectCount = currentObjectCount; _cachedZdoScanUpdatedUnixSeconds = GetUnixSeconds(); _ownershipCacheDirty = true; } } private static void PersistZdoScanCursor(int objectCount) { if (_enableOwnershipCache != null && _enableOwnershipCache.Value && _resumeZdoScanFromCache != null && _resumeZdoScanFromCache.Value) { _cachedZdoScanIndex = _zdoScanIndex; _cachedZdoScanObjectCount = objectCount; _cachedZdoScanUpdatedUnixSeconds = GetUnixSeconds(); _ownershipCacheDirty = true; if (_nextOwnershipCacheFlushTime <= 0f) { _nextOwnershipCacheFlushTime = Time.realtimeSinceStartup + 30f; } } } private static void ApplyOwnershipCacheWarmStart() { //IL_00eb: Unknown result type (might be due to invalid IL or missing references) if (_ownershipCacheWarmStartComplete || !_enableOwnershipCache.Value) { return; } if (_ownershipCache.Count == 0) { _ownershipCacheWarmStartComplete = true; return; } Dictionary<ZDOID, ZDO> objectsById = GetObjectsById(); if (objectsById == null || objectsById.Count == 0) { return; } if (_ownershipCacheScanIndex >= _ownershipCache.Count) { _ownershipCacheScanIndex = 0; } List<OwnershipCacheEntry> list = new List<OwnershipCacheEntry>(_ownershipCache.Values); int num = 0; int num2 = 0; int num3 = 0; int value = _ownershipCacheRecordsPerScan.Value; int value2 = _maxCacheRestoresPerScan.Value; List<string> list2 = null; foreach (OwnershipCacheEntry item in list) { if (num++ < _ownershipCacheScanIndex) { continue; } if (num2 >= value || num3 >= value2) { break; } num2++; _cacheRecordsChecked++; ZDO value3; if (!TryParseZdoId(item.Uid, out var id)) { if (list2 == null) { list2 = new List<string>(); } list2.Add(item.Uid); } else if (objectsById.TryGetValue(id, out value3) && TryRestoreCachedOwnership(value3)) { num3++; } } if (list2 != null) { for (int i = 0; i < list2.Count; i++) { RemoveOwnershipCacheEntry(list2[i]); } } _ownershipCacheScanIndex += num2; if (_ownershipCacheScanIndex >= list.Count || num2 == 0) { _ownershipCacheWarmStartComplete = true; _ownershipCacheScanIndex = 0; if (_log != null) { _log.LogInfo((object)("[ownership cache] Direct warm-start complete. cacheEntries=" + _ownershipCache.Count + ", totalCacheRestored=" + _totalCacheRestored + ", removed=" + _cacheRemoved + ".")); } FlushOwnershipCache(force: false); } } private static bool TryRestoreCachedOwnership(ZDO zdo) { //IL_0159: Unknown result type (might be due to invalid IL or missing references) if (zdo == null || !zdo.IsValid()) { return false; } string text = ((object)Unsafe.As<ZDOID, ZDOID>(ref zdo.m_uid)/*cast due to .constrained prefix*/).ToString(); if (!_ownershipCache.TryGetValue(text, out var value)) { return false; } if (!zdo.Persistent || zdo.GetPrefab() != value.PrefabHash) { RemoveOwnershipCacheEntry(text); return false; } long num = zdo.GetLong(ZDOVars.s_creator, 0L); if (_playerBuiltPiecesOnly.Value && num == 0L) { RemoveOwnershipCacheEntry(text); return false; } if (value.Creator != 0L && num != value.Creator) { RemoveOwnershipCacheEntry(text); return false; } GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(value.PrefabHash) : null); if ((Object)(object)val != (Object)null && !IsEligibleStaticPiecePrefab(value.PrefabHash, val)) { RemoveOwnershipCacheEntry(text); return false; } long sessionID = ZDOMan.GetSessionID(); long owner = zdo.GetOwner(); if (owner == sessionID) { RecordOwnershipCache(zdo, value.PrefabName, num); return false; } if (_dryRunStaticPieceServerOwnership.Value) { _claimed++; _totalClaimed++; _cacheRestored++; _totalCacheRestored++; LogClaim("DRY-RUN cache would claim", value.PrefabName, zdo, owner, num, "ownership-cache"); return true; } zdo.SetOwner(sessionID); ZDOMan.instance.ForceSendZDO(zdo.m_uid); _claimed++; _totalClaimed++; _cacheRestored++; _totalCacheRestored++; RecordOwnershipCache(zdo, value.PrefabName, num); LogClaim("Cache-claimed", value.PrefabName, zdo, owner, num, "ownership-cache"); return true; } private static bool TryParseZdoId(string uid, out ZDOID id) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) id = ZDOID.None; if (string.IsNullOrEmpty(uid)) { return false; } int num = uid.IndexOf(':'); if (num <= 0 || num >= uid.Length - 1) { return false; } if (!long.TryParse(uid.Substring(0, num), out var result) || !uint.TryParse(uid.Substring(num + 1), out var result2)) { return false; } id = new ZDOID(result, result2); return true; } private static void RecordOwnershipCache(ZDO zdo, string prefabName, long creator) { if (_enableBackgroundOwnershipAudit == null || !_enableBackgroundOwnershipAudit.Value || _enableOwnershipCache == null || !_enableOwnershipCache.Value || _dryRunStaticPieceServerOwnership.Value || zdo == null || !zdo.IsValid()) { return; } int prefab = zdo.GetPrefab(); if (prefab != 0) { string text = ((object)Unsafe.As<ZDOID, ZDOID>(ref zdo.m_uid)/*cast due to .constrained prefix*/).ToString(); _ownershipCache[text] = new OwnershipCacheEntry { Uid = text, PrefabHash = prefab, Creator = creator, PrefabName = CleanPrefabName(prefabName), StoredUnixSeconds = GetUnixSeconds() }; _ownershipCacheDirty = true; if (_nextOwnershipCacheFlushTime <= 0f) { _nextOwnershipCacheFlushTime = Time.realtimeSinceStartup + 30f; } } } private static void RemoveOwnershipCacheEntry(string uid) { if (_ownershipCache.Remove(uid)) { _cacheRemoved++; _ownershipCacheDirty = true; } } private static void LoadOwnershipCache() { _ownershipCacheWarmStartComplete = true; if (_enableOwnershipCache == null || !_enableOwnershipCache.Value) { return; } _ownershipCachePath = Path.Combine(Paths.ConfigPath, "r4v9n1.terramizerserver.ownership-cache.tsv"); _ownershipCacheWarmStartComplete = false; if (!File.Exists(_ownershipCachePath)) { if (_log != null) { _log.LogInfo((object)"[ownership cache] No ownership cache found yet. It will be created as pieces are claimed."); } return; } _deferredOwnershipClaims.Clear(); _deferredOwnershipClaimSet.Clear(); long unixSeconds = GetUnixSeconds(); long num = (long)(_ownershipCacheMaxAgeHours.Value * 3600f); int num2 = 0; int num3 = 0; try { string[] array = File.ReadAllLines(_ownershipCachePath); foreach (string text in array) { if (string.IsNullOrEmpty(text)) { continue; } if (text[0] == '#') { ReadOwnershipCacheMetadata(text); continue; } string[] array2 = text.Split(new char[1] { '\t' }); if (array2.Length >= 5 && int.TryParse(array2[1], out var result) && long.TryParse(array2[2], out var result2) && long.TryParse(array2[4], out var result3)) { if (unixSeconds - result3 > num) { num3++; continue; } _ownershipCache[array2[0]] = new OwnershipCacheEntry { Uid = array2[0], PrefabHash = result, Creator = result2, PrefabName = array2[3], StoredUnixSeconds = result3 }; num2++; } } } catch (Exception ex) { _ownershipCache.Clear(); _cachedOwnershipWorldUid = 0L; _initialBroadScanComplete = false; _initialBroadScanTraversalComplete = false; _pendingInitialBroadScanCompletion = false; _deferredOwnershipClaims.Clear(); _deferredOwnershipClaimSet.Clear(); _ownershipCacheWorldValidated = false; _ownershipCacheWarmStartComplete = true; if (_log != null) { _log.LogWarning((object)("[ownership cache] Could not load ownership cache; continuing with normal scan: " + ex.Message)); } return; } if (num3 > 0) { _ownershipCacheDirty = true; _cacheRemoved += num3; } if (_cachedZdoScanUpdatedUnixSeconds > 0 && unixSeconds - _cachedZdoScanUpdatedUnixSeconds > num) { _cachedZdoScanIndex = 0; _cachedZdoScanObjectCount = 0; _zdoBroadScanPassesCompleted = 0; _initialBroadScanComplete = false; _initialBroadScanTraversalComplete = false; _pendingInitialBroadScanCompletion = false; _deferredOwnershipClaims.Clear(); _deferredOwnershipClaimSet.Clear(); _cachedZdoScanUpdatedUnixSeconds = 0L; _ownershipCacheDirty = true; } if (_zdoBroadScanPassesCompleted < 0) { _zdoBroadScanPassesCompleted = 0; _ownershipCacheDirty = true; } _ownershipCacheWorldValidated = false; _pendingInitialBroadScanCompletion = _initialBroadScanTraversalComplete && !_initialBroadScanComplete; _loadedZdoScanCursorPending = _cachedZdoScanIndex > 0; if (_log != null) { _log.LogInfo((object)("[ownership cache] Loaded " + num2 + " cached ownership records from " + _ownershipCachePath + ((num3 > 0) ? (" and expired " + num3 + ".") : ".") + " scanIndex=" + _cachedZdoScanIndex + ", scanObjectCount=" + _cachedZdoScanObjectCount + ", scanPassesCompleted=" + _zdoBroadScanPassesCompleted + ", worldUid=" + _cachedOwnershipWorldUid + ", initialBroadScanTraversalComplete=" + _initialBroadScanTraversalComplete + ", initialBroadScanComplete=" + _initialBroadScanComplete + ", deferredClaims=" + _deferredOwnershipClaims.Count + ".")); } } private static bool FlushOwnershipCache(bool force) { if (_enableOwnershipCache == null || !_enableOwnershipCache.Value || string.IsNullOrEmpty(_ownershipCachePath) || (!_ownershipCacheDirty && !force)) { return false; } try { string directoryName = Path.GetDirectoryName(_ownershipCachePath); if (!string.IsNullOrEmpty(directoryName)) { Directory.CreateDirectory(directoryName); } string text = _ownershipCachePath + ".tmp"; using (StreamWriter streamWriter = new StreamWriter(text, append: false, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false))) { streamWriter.WriteLine("# TerramizerServer ownership cache v1"); streamWriter.WriteLine("# scanIndex\t" + _cachedZdoScanIndex); streamWriter.WriteLine("# scanObjectCount\t" + _cachedZdoScanObjectCount); streamWriter.WriteLine("# scanPassesCompleted\t" + _zdoBroadScanPassesCompleted); streamWriter.WriteLine("# scanUpdatedUnixSeconds\t" + _cachedZdoScanUpdatedUnixSeconds); streamWriter.WriteLine("# worldUid\t" + _cachedOwnershipWorldUid); streamWriter.WriteLine("# initialBroadScanTraversalComplete\t" + _initialBroadScanTraversalComplete); streamWriter.WriteLine("# initialBroadScanComplete\t" + _initialBroadScanComplete); foreach (string deferredOwnershipClaim in _deferredOwnershipClaims) { streamWriter.WriteLine("# deferredClaim\t" + deferredOwnershipClaim); } streamWriter.WriteLine("# uid\tprefabHash\tcreator\tprefabName\tstoredUnixSeconds"); foreach (OwnershipCacheEntry value in _ownershipCache.Values) { streamWriter.Write(value.Uid); streamWriter.Write('\t'); streamWriter.Write(value.PrefabHash); streamWriter.Write('\t'); streamWriter.Write(value.Creator); streamWriter.Write('\t'); streamWriter.Write(CleanPrefabName(value.PrefabName)); streamWriter.Write('\t'); streamWriter.WriteLine(value.StoredUnixSeconds); } } if (File.Exists(_ownershipCachePath)) { File.Delete(_ownershipCachePath); } File.Move(text, _ownershipCachePath); _ownershipCacheDirty = false; _nextOwnershipCacheFlushTime = Time.realtimeSinceStartup + 30f; return true; } catch (Exception ex) { _nextOwnershipCacheFlushTime = Time.realtimeSinceStartup + 60f; if (_log != null) { _log.LogWarning((object)("[ownership cache] Could not save ownership cache; will retry later: " + ex.Message)); } return false; } } private static void ReadOwnershipCacheMetadata(string line) { if (line.StartsWith("# scanIndex\t", StringComparison.Ordinal)) { int.TryParse(line.Substring("# scanIndex\t".Length), out _cachedZdoScanIndex); } else if (line.StartsWith("# scanObjectCount\t", StringComparison.Ordinal)) { int.TryParse(line.Substring("# scanObjectCount\t".Length), out _cachedZdoScanObjectCount); } else if (line.StartsWith("# scanPassesCompleted\t", StringComparison.Ordinal)) { int.TryParse(line.Substring("# scanPassesCompleted\t".Length), out _zdoBroadScanPassesCompleted); } else if (line.StartsWith("# scanUpdatedUnixSeconds\t", StringComparison.Ordinal)) { long.TryParse(line.Substring("# scanUpdatedUnixSeconds\t".Length), out _cachedZdoScanUpdatedUnixSeconds); } else if (line.StartsWith("# worldUid\t", StringComparison.Ordinal)) { long.TryParse(line.Substring("# worldUid\t".Length), out _cachedOwnershipWorldUid); } else if (line.StartsWith("# initialBroadScanTraversalComplete\t", StringComparison.Ordinal)) { bool.TryParse(line.Substring("# initialBroadScanTraversalComplete\t".Length), out _initialBroadScanTraversalComplete); } else if (line.StartsWith("# initialBroadScanComplete\t", StringComparison.Ordinal)) { bool.TryParse(line.Substring("# initialBroadScanComplete\t".Length), out _initialBroadScanComplete); } else if (line.StartsWith("# deferredClaim\t", StringComparison.Ordinal)) { string text = line.Substring("# deferredClaim\t".Length); if (!string.IsNullOrEmpty(text) && _deferredOwnershipClaimSet.Add(text)) { _deferredOwnershipClaims.Enqueue(text); } } } private static long GetUnixSeconds() { return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; } private static string CleanPrefabName(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return "unknown"; } return prefabName.Replace("(Clone)", string.Empty).Replace('\t', ' ').Replace('\r', ' ') .Replace('\n', ' ') .Trim(); } private static bool TryClaimZdoRecord(ZDO zdo, string reason, bool allowOwnershipChange) { //IL_0143: Unknown result type (might be due to invalid IL or missing references) _claimAttempts++; if (zdo == null || !zdo.IsValid()) { _skippedNoZdo++; return false; } if (!zdo.Persistent) { _skippedNotPersistent++; return false; } int prefab = zdo.GetPrefab(); if (prefab == 0) { _skippedNoPrefab++; return false; } GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab); if ((Object)(object)prefab2 == (Object)null) { _skippedNoPrefab++; return false; } if (!IsEligibleStaticPiecePrefab(prefab, prefab2)) { _skippedNotPiecePrefab++; return false; } long num = zdo.GetLong(ZDOVars.s_creator, 0L); if (_playerBuiltPiecesOnly.Value && num == 0L) { _skippedNoCreator++; return false; } long sessionID = ZDOMan.GetSessionID(); long owner = zdo.GetOwner(); if (owner == sessionID) { _alreadyServerOwned++; RecordOwnershipCache(zdo, ((Object)prefab2).name, num); return false; } if (!allowOwnershipChange) { EnqueueDeferredOwnershipClaim(zdo); return false; } if (_dryRunStaticPieceServerOwnership.Value) { _claimed++; _totalClaimed++; LogClaim("DRY-RUN would claim", ((Object)prefab2).name, zdo, owner, num, reason); return true; } zdo.SetOwner(sessionID); ZDOMan.instance.ForceSendZDO(zdo.m_uid); _claimed++; _totalClaimed++; RecordOwnershipCache(zdo, ((Object)prefab2).name, num); LogClaim("Claimed", ((Object)prefab2).name, zdo, owner, num, reason); return true; } private static bool IsEligibleStaticPiecePrefab(int prefabHash, GameObject prefab) { if (_prefabEligibilityCache.TryGetValue(prefabHash, out var value)) { return value; } Piece val = prefab.GetComponent<Piece>(); if ((Object)(object)val == (Object)null) { val = prefab.GetComponentInChildren<Piece>(true); } value = (Object)(object)val != (Object)null; if (value && _requireWearNTear.Value && (Object)(object)prefab.GetComponent<WearNTear>() == (Object)null && (Object)(object)prefab.GetComponentInChildren<WearNTear>(true) == (Object)null) { value = false; } if (value && IsDynamicOrPhysicsObject(prefab)) { value = false; } _prefabEligibilityCache[prefabHash] = value; return value; } private static bool IsDynamicOrPhysicsObject(GameObject root) { if ((Object)(object)root.GetComponentInChildren<Rigidbody>(true) != (Object)null) { return true; } if ((Object)(object)root.GetComponentInChildren<Ship>(true) != (Object)null) { return true; } if ((Object)(object)root.GetComponentInChildren<Vagon>(true) != (Object)null) { return true; } if ((Object)(object)root.GetComponentInChildren<ItemDrop>(true) != (Object)null) { return true; } if ((Object)(object)root.GetComponentInChildren<Character>(true) != (Object)null) { return true; } if ((Object)(object)root.GetComponentInChildren<Floating>(true) != (Object)null) { return true; } return false; } private static bool ShouldRunExperiment() { if (_enabled == null || !_enabled.Value || _enableStaticPieceServerOwnership == null || !_enableStaticPieceServerOwnership.Value) { return false; } if (_dedicatedOnly != null && _dedicatedOnly.Value && !Application.isBatchMode) { return false; } if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null) { return false; } return true; } private static void AdvertiseServerMetadata() { if (_enabled != null && _enabled.Value && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && ZNet.instance.m_serverSyncedPlayerData != null && (_dedicatedOnly == null || !_dedicatedOnly.Value || Application.isBatchMode) && (!_serverMetadataAdvertised || _metadataAdvertisedForInstance != ZNet.instance)) { ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.version"] = "1.0.6"; ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.staticOwnership"] = (_enableStaticPieceServerOwnership != null && _enableStaticPieceServerOwnership.Value).ToString(); ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.ownershipCache"] = (_enableBackgroundOwnershipAudit != null && _enableBackgroundOwnershipAudit.Value && _enableOwnershipCache != null && _enableOwnershipCache.Value).ToString(); ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.extendedTerrainLimits"] = (_enableExtendedTerrainLimits != null && _enableExtendedTerrainLimits.Value).ToString(); ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.terrainRaiseLimit"] = GetTerrainRaiseLimitMeters().ToString(CultureInfo.InvariantCulture); ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.terrainDigLimit"] = GetTerrainDigLimitMeters().ToString(CultureInfo.InvariantCulture); if (!_serverMetadataAdvertised && _log != null) { _log.LogInfo((object)("Advertised TerramizerServer companion metadata to connecting clients. version=1.0.6, staticOwnership=" + ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.staticOwnership"] + ", ownershipCache=" + ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.ownershipCache"] + ", extendedTerrainLimits=" + ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.extendedTerrainLimits"] + ", terrainRaiseLimit=" + ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.terrainRaiseLimit"] + ", terrainDigLimit=" + ZNet.instance.m_serverSyncedPlayerData["r4v9n1.terramizerserver.terrainDigLimit"] + ".")); } _serverMetadataAdvertised = true; _metadataAdvertisedForInstance = ZNet.instance; } } private static void RegisterCompanionRpcsWhenReady() { if (ZRoutedRpc.instance != null && _registeredRoutedRpcInstance != ZRoutedRpc.instance) { ZRoutedRpc.instance.Register("r4v9n1.terramizerserver.RequestCompanionMetadata", (Action<long>)OnRequestCompanionMetadata); ZRoutedRpc.instance.Register("r4v9n1.terramizerserver.RequestCompanionMetadataV2", (Action<long>)OnRequestCompanionMetadataV2); _registeredRoutedRpcInstance = ZRoutedRpc.instance; } } private static void OnRequestCompanionMetadata(long sender) { if (_enabled != null && _enabled.Value && ZRoutedRpc.instance != null && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && (_dedicatedOnly == null || !_dedicatedOnly.Value || Application.isBatchMode)) { bool flag = _enableStaticPieceServerOwnership != null && _enableStaticPieceServerOwnership.Value; bool flag2 = _enableBackgroundOwnershipAudit != null && _enableBackgroundOwnershipAudit.Value && _enableOwnershipCache != null && _enableOwnershipCache.Value; ZRoutedRpc.instance.InvokeRoutedRPC(sender, "r4v9n1.terramizerserver.CompanionMetadata", new object[3] { "1.0.6", flag, flag2 }); _companionRpcReplies++; if (!_companionRpcReplyLogged && _log != null) { _companionRpcReplyLogged = true; _log.LogInfo((object)("Answered Terramizer companion metadata RPC. version=1.0.6, staticOwnership=" + flag + ", ownershipCache=" + flag2 + ".")); } } } private static void OnRequestCompanionMetadataV2(long sender) { if (_enabled != null && _enabled.Value && ZRoutedRpc.instance != null && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && (_dedicatedOnly == null || !_dedicatedOnly.Value || Application.isBatchMode)) { bool flag = _enableStaticPieceServerOwnership != null && _enableStaticPieceServerOwnership.Value; bool flag2 = _enableBackgroundOwnershipAudit != null && _enableBackgroundOwnershipAudit.Value && _enableOwnershipCache != null && _enableOwnershipCache.Value; bool flag3 = _enableExtendedTerrainLimits != null && _enableExtendedTerrainLimits.Value; float terrainRaiseLimitMeters = GetTerrainRaiseLimitMeters(); float terrainDigLimitMeters = GetTerrainDigLimitMeters(); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "r4v9n1.terramizerserver.CompanionMetadataV2", new object[6] { "1.0.6", flag, flag2, flag3, terrainRaiseLimitMeters, terrainDigLimitMeters }); _companionRpcReplies++; } } private static void LogOwnershipMaintenanceFailure(Exception ex) { if (!_ownershipMaintenanceFailureLogged && _log != null) { _ownershipMaintenanceFailureLogged = true; _log.LogWarning((object)("Optional ownership maintenance hit an error; vanilla server simulation continues and the next bounded pass will retry: " + ex.Message)); } } private unsafe static void LogClaim(string action, string prefabName, ZDO zdo, long oldOwner, long creator, string reason) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) if (_log != null) { bool flag = IsWatchedInteractivePrefab(prefabName); if (flag) { _watchedClaims++; _totalWatchedClaims++; } if ((_logDevClaims != null && _logDevClaims.Value) || (flag && _logWatchedClaims != null && _logWatchedClaims.Value)) { ManualLogSource log = _log; string[] obj = new string[17] { "[dev ownership] ", action, " ", prefabName, " zdo=", null, null, null, null, null, null, null, null, null, null, null, null }; ZDOID uid = zdo.m_uid; obj[5] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString(); obj[6] = " oldOwner="; obj[7] = oldOwner.ToString(); obj[8] = " newOwner="; obj[9] = zdo.GetOwner().ToString(); obj[10] = " creator="; obj[11] = creator.ToString(); obj[12] = " sector="; obj[13] = ((object)zdo.GetSector()/*cast due to .constrained prefix*/).ToString(); obj[14] = " reason="; obj[15] = reason; obj[16] = "."; log.LogInfo((object)string.Concat(obj)); } } } private static bool IsWatchedInteractivePrefab(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return false; } string text = prefabName.ToLowerInvariant(); if (!text.Contains("bed") && !text.Contains("chest") && !text.Contains("portal") && !text.Contains("fire") && !text.Contains("hearth") && !text.Contains("bonfire") && !text.Contains("workbench") && !text.Contains("forge") && !text.Contains("cauldron") && !text.Contains("fermenter") && !text.Contains("smelter") && !text.Contains("kiln") && !text.Contains("windmill") && !text.Contains("spinningwheel") && !text.Contains("eitrrefinery") && !text.Contains("blackforge") && !text.Contains("magetable") && !text.Contains("artisan") && !text.Contains("obliterator") && !text.Contains("sign") && !text.Contains("itemstand") && !text.Contains("armorstand") && !text.Contains("ward") && !text.Contains("guardstone") && !text.Contains("door") && !text.Contains("gate") && !text.Contains("cartography")) { return text.Contains("sapcollector"); } return true; } private static void LogSkip(Piece piece, string reason) { if (_logDevSkips != null && _logDevSkips.Value && _log != null && !((Object)(object)piece == (Object)null)) { _log.LogInfo((object)("[dev ownership] skipped " + ((Object)((Component)piece).gameObject).name + ": " + reason + ".")); } } private static void LogOwnershipSummary() { if (_log != null) { long num = Take(ref _claimed); long num2 = Take(ref _watchedClaims); long num3 = Take(ref _skippedNoZdo) + Take(ref _skippedNoPrefab) + Take(ref _skippedNotPiecePrefab) + Take(ref _skippedNotPersistent) + Take(ref _skippedNoCreator) + Take(ref _skippedNoWearNTear) + Take(ref _skippedDynamic) + Take(ref _skippedNotReady); _log.LogInfo((object)("[dev ownership summary] claims=" + num + ", totalClaims=" + _totalClaimed + ", watchedClaims=" + num2 + ", totalWatchedClaims=" + _totalWatchedClaims + ", scanMode=" + (IsMaintenanceScanMode() ? "maintenance" : "warmup") + ", scanPasses=" + _zdoBroadScanPassesCompleted + ", scanInterval=" + GetOwnershipScanIntervalSeconds() + ", scanRecords=" + GetZdoRecordsPerScan() + ", scanClaimLimit=" + GetMaxClaimsPerScan() + ", cacheRestored=" + Take(ref _cacheRestored) + ", totalCacheRestored=" + _totalCacheRestored + ", cacheEntries=" + _ownershipCache.Count + ", cacheChecked=" + Take(ref _cacheRecordsChecked) + ", cacheRemoved=" + _cacheRemoved + ", deferredClaims=" + _deferredOwnershipClaims.Count + ", companionRpcReplies=" + Take(ref _companionRpcReplies) + ", zdoScanIndex=" + _zdoScanIndex + ", alreadyServerOwned=" + Take(ref _alreadyServerOwned) + ", skipped=" + num3 + ", checked=" + Take(ref _zdoRecordsChecked) + ", attempts=" + Take(ref _claimAttempts) + ".")); } } private static long Take(ref long value) { long result = value; value = 0L; return result; } private void RemoveRetiredSettings() { Remove("General", "ServerOnly", defaultValue: true); Remove("General", "SafetyDefaultsVersion", 0); Remove("Streaming", "MaxSendQueueBytes", 16384); Remove("Streaming", "MinFreeSendQueueBytes", 4096); Remove("Streaming", "PeerSendIntervalSeconds", 0.05f); Remove("Streaming", "ZoneStreamingBoostExtraRadius", 0); Remove("Streaming", "ZoneStreamingBoostIncludeDistantZdos", defaultValue: true); Remove("Streaming", "LogZoneStreamingBoosts", defaultValue: false); Remove("Streaming", "StreamingUpdateIntervalSeconds", 0.5f); Remove("Diagnostics", "LogDenseSyncs", defaultValue: true); Remove("Diagnostics", "DenseSyncThreshold", 1000); Remove("Diagnostics", "DenseSyncLogIntervalSeconds", 30f); Remove("Diagnostics", "PauseExtraStreamingDuringDenseSync", defaultValue: true); Remove("Diagnostics", "DenseSyncPauseSeconds", 2f); Remove("Diagnostics", "DiagnosticIntervalSec", 60f); Remove("WorldObjects", "ExtendedZoneRadius", 0); Remove("WorldObjects", "CreateDestroyIntervalSeconds", 0.1f); Remove("WorldObjects", "RemoveObjectsIntervalSeconds", 0.5f); Remove("WorldObjects", "EnablePredictiveZoneStreaming", defaultValue: true); Remove("WorldObjects", "PredictionLookaheadSec", 3f); Remove("WorldObjects", "PredictionMinVelocity", 2f); Remove("WorldObjects", "PredictionMaxLookaheadZones", 9); Remove("WorldObjects", "EnableZDOThrottling", defaultValue: false); Remove("WorldObjects", "ZDOThrottleDistance", 500f); Remove("WorldObjects", "EnablePlayerPriority", defaultValue: true); Remove("ServerSimulation", "PeerZoneUpdateIntervalSeconds", 0.5f); Remove("ServerSimulation", "EnableMultiPeerOutsideActiveArea", defaultValue: true); Remove("ServerSimulation", "EnableHeadlessVisualGuards", defaultValue: true); Remove("ServerSimulation", "EnablePeerZoneCreation", defaultValue: false); Remove("ServerSimulation", "MaxPeerZoneCreationsPerPass", 1); Remove("ServerSimulation", "EnableServerOwnershipForPersistentZdos", defaultValue: false); Remove("ServerSimulation", "AllowExperimentalServerOwnershipForPersistentZdos", defaultValue: false); Remove("Performance", "ActivePlayerOwnershipBudgetMs", 0.35f); Remove("Performance", "IdleOwnershipBudgetMs", 2f); Remove("Performance", "MaintenanceFullAuditIntervalSeconds", 1800f); Remove("Sleep", "PauseExtraZoneWorkDuringSleep", defaultValue: true); Remove("Sleep", "LogSleepOptimizations", defaultValue: true); Remove("BuildInteractions", "RepairStaleWearNTearRemoveOwnership", defaultValue: true); Remove("BuildInteractions", "MaxRemoveRepairDistance", 8f); Remove("BuildInteractions", "LogRemoveOwnershipRepairs", defaultValue: true); Remove("ItemInteractions", "RepairStaleItemDropOwnership", defaultValue: true); Remove("ItemInteractions", "LogItemDropOwnershipRepairs", defaultValue: false); ((BaseUnityPlugin)this).Config.Save(); } private void Remove<T>(string section, string key, T defaultValue) { ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, "Retired for safety."); ((BaseUnityPlugin)this).Config.Remove(((ConfigEntryBase)val).Definition); } private void BindTerrainCompatibilityConfig() { _enableExtendedTerrainLimits = ((BaseUnityPlugin)this).Config.Bind<bool>("Terrain", "EnableExtendedTerrainLimits", true, "Enable the dedicated-server terrain limit extension for compatible clients and local server authority."); _terrainRaiseLimitMeters = BindRange("Terrain", "TerrainRaiseLimitMeters", 16f, "Maximum terrain raise/level delta from original terrain.", 16f, 64f); _terrainDigLimitMeters = BindRange("Terrain", "TerrainDigLimitMeters", 16f, "Maximum terrain dig/lower delta from original terrain.", 16f, 64f); } internal static float GetTerrainRaiseLimitMeters() { if (_enableExtendedTerrainLimits == null || !_enableExtendedTerrainLimits.Value || _terrainRaiseLimitMeters == null) { return 8f; } return Mathf.Max(16f, _terrainRaiseLimitMeters.Value); } internal static float GetTerrainDigLimitMeters() { if (_enableExtendedTerrainLimits == null || !_enableExtendedTerrainLimits.Value || _terrainDigLimitMeters == null) { return 8f; } return Mathf.Max(16f, _terrainDigLimitMeters.Value); } internal static float GetTerrainDigThresholdMeters() { return Mathf.Max(0f, GetTerrainDigLimitMeters() - 0.05f); } } internal sealed class OwnershipCacheEntry { public string Uid; public int PrefabHash; public long Creator; public string PrefabName; public long StoredUnixSeconds; } [HarmonyPatch(typeof(ZNetView), "Awake")] internal static class ZNetViewAwakeStaticOwnershipPatch { private static void Postfix(ZNetView __instance) { TerramizerServerPlugin.TryClaimFromZNetView(__instance, "znetview-awake"); } } [HarmonyPatch(typeof(Heightmap), "AtMaxWorldLevelDepth")] internal static class HeightmapAtMaxWorldLevelDepthTerrainLimitPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replaced = 0; foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num && Math.Abs(num - 7.95f) < 0.0001f) { replaced++; yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), "GetTerrainDigThresholdMeters", (Type[])null, (Type[])null)); } else { yield return instruction; } } if (replaced != 1) { throw new InvalidOperationException("Expected one Heightmap.AtMaxWorldLevelDepth terrain-limit constant, found " + replaced + "."); } } } [HarmonyPatch(typeof(Heightmap), "LevelTerrain")] internal static class HeightmapLevelTerrainTerrainLimitPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replaced = 0; foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldc_R8 && instruction.operand is double num && Math.Abs(num - 8.0) < 0.0001) { int num2 = replaced + 1; replaced = num2; if (num2 <= 2) { yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), (replaced == 1) ? "GetTerrainDigLimitMeters" : "GetTerrainRaiseLimitMeters", (Type[])null, (Type[])null)); yield return new CodeInstruction(OpCodes.Conv_R8, (object)null); continue; } } yield return instruction; } if (replaced != 2) { throw new InvalidOperationException("Expected two Heightmap.LevelTerrain terrain-limit constants, found " + replaced + "."); } } } [HarmonyPatch(typeof(TerrainComp), "LevelTerrain")] internal static class TerrainCompLevelTerrainLimitPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replaced = 0; foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num && Math.Abs(num + 8f) < 0.0001f) { replaced++; yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), "GetTerrainDigLimitMeters", (Type[])null, (Type[])null)); yield return new CodeInstruction(OpCodes.Neg, (object)null); } else if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num2 && Math.Abs(num2 - 8f) < 0.0001f) { replaced++; yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), "GetTerrainRaiseLimitMeters", (Type[])null, (Type[])null)); } else { yield return instruction; } } if (replaced != 2) { throw new InvalidOperationException("Expected signed TerrainComp.LevelTerrain terrain-limit constants, found " + replaced + "."); } } } [HarmonyPatch(typeof(TerrainComp), "RaiseTerrain")] internal static class TerrainCompRaiseTerrainLimitPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replaced = 0; foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num && Math.Abs(num + 8f) < 0.0001f) { replaced++; yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), "GetTerrainDigLimitMeters", (Type[])null, (Type[])null)); yield return new CodeInstruction(OpCodes.Neg, (object)null); } else if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num2 && Math.Abs(num2 - 8f) < 0.0001f) { replaced++; yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), "GetTerrainRaiseLimitMeters", (Type[])null, (Type[])null)); } else { yield return instruction; } } if (replaced != 2) { throw new InvalidOperationException("Expected signed TerrainComp.RaiseTerrain terrain-limit constants, found " + replaced + "."); } } } [HarmonyPatch(typeof(TerrainComp), "ApplyToHeightmap")] internal static class TerrainCompApplyToHeightmapTerrainLimitPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replaced = 0; foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num && Math.Abs(num + 8f) < 0.0001f) { replaced++; yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), "GetTerrainDigLimitMeters", (Type[])null, (Type[])null)); yield return new CodeInstruction(OpCodes.Neg, (object)null); } else if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num2 && Math.Abs(num2 - 8f) < 0.0001f) { replaced++; yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TerramizerServerPlugin), "GetTerrainRaiseLimitMeters", (Type[])null, (Type[])null)); } else { yield return instruction; } } if (replaced != 2) { throw new InvalidOperationException("Expected signed TerrainComp.ApplyToHeightmap terrain-limit constants, found " + replaced + "."); } } } [HarmonyPatch(typeof(VisEquipment), "UpdateEquipmentVisuals")] internal static class VisEquipmentIntCachePatch { private static readonly MethodInfo ZdoGetInt = AccessTools.Method(typeof(ZDO), "GetInt", new Type[2] { typeof(int), typeof(int) }, (Type[])null); private static readonly MethodInfo GetCachedIntMethod = AccessTools.Method(typeof(VisEquipmentIntCachePatch), "GetCachedInt", (Type[])null, (Type[])null); private static readonly FieldRef<Dictionary<ZDOID, BinarySearchDictionary<int, int>>> IntTables = AccessTools.StaticFieldRefAccess<Dictionary<ZDOID, BinarySearchDictionary<int, int>>>(AccessTools.Field(typeof(ZDOExtraData), "s_ints")); private static bool _transpilerFoundCall; [ThreadStatic] private static BinarySearchDictionary<int, int> _currentTable; private static BinarySearchDictionary<int, int> CurrentTable => _currentTable; private static void Prefix(VisEquipment __instance, out BinarySearchDictionary<int, int> __state) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) __state = _currentTable; _currentTable = null; if ((Object)(object)__instance == (Object)null) { return; } ZNetView val = (((Object)(object)__instance.m_nViewOverride != (Object)null) ? __instance.m_nViewOverride : ((Component)__instance).GetComponent<ZNetView>()); if (!((Object)(object)val == (Object)null)) { ZDO zDO = val.GetZDO(); if (zDO != null) { IntTables.Invoke()?.TryGetValue(zDO.m_uid, out _currentTable); } } } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { if (ZdoGetInt == null || GetCachedIntMethod == null) { throw new MissingMethodException("VisEquipmentIntCachePatch could not resolve ZDO.GetInt(int, int)."); } foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, ZdoGetInt)) { instruction.opcode = OpCodes.Call; instruction.operand = GetCachedIntMethod; _transpilerFoundCall = true; } yield return instruction; } if (!_transpilerFoundCall) { throw new InvalidOperationException("VisEquipment.UpdateEquipmentVisuals contained no ZDO.GetInt(int, int) calls."); } } private static Exception Finalizer(Exception __exception, BinarySearchDictionary<int, int> __state) { _currentTable = __state; return __exception; } private static int GetCachedInt(ZDO zdo, int hash, int defaultValue) { BinarySearchDictionary<int, int> currentTable = CurrentTable; if (currentTable != null) { return currentTable.GetValueOrDefault(hash, defaultValue); } if (zdo == null) { return defaultValue; } return zdo.GetInt(hash, defaultValue); } } [HarmonyPatch(typeof(ZDOMan), "ReleaseNearbyZDOS")] internal static class ZdoOwnershipHandoffPatch { private delegate bool IsInPeerActiveAreaDelegate(ZDOMan instance, Vector3 position, long uid); private static readonly List<ZDO> NearbyObjects = new List<ZDO>(512); private static readonly IsInPeerActiveAreaDelegate IsInPeerActiveArea = CreateIsInPeerActiveAreaDelegate(); private static IsInPeerActiveAreaDelegate CreateIsInPeerActiveAreaDelegate() { try { MethodInfo methodInfo = AccessTools.Method(typeof(ZDOMan), "IsInPeerActiveArea", (Type[])null, (Type[])null); if (methodInfo == null) { return null; } return (IsInPeerActiveAreaDelegate)methodInfo.CreateDelegate(typeof(IsInPeerActiveAreaDelegate)); } catch { return null; } } private static bool OwnerIsInActiveArea(ZDOMan instance, Vector3 position, long owner) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (IsInPeerActiveArea == null) { return true; } return IsInPeerActiveArea(instance, position, owner); } private static bool Prefix(ZDOMan __instance, Vector3 refPosition, long uid) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) try { if (__instance == null || (Object)(object)ZNet.instance == (Object)null) { return true; } Vector2s zone = ZoneSystem.GetZone(refPosition); SimulationDistance syncedSimulationDistance = ZNet.instance.GetSyncedSimulationDistance(); SimulationDistance val = default(SimulationDistance); ((SimulationDistance)(ref val))..ctor(((SimulationDistance)(ref syncedSimulationDistance)).NearSimulationDistance, 0, ((SimulationDistance)(ref syncedSimulationDistance)).IsClassic); NearbyObjects.Clear(); __instance.FindSectorObjects(zone, val, NearbyObjects, (List<ZDO>)null); bool flag = uid == ZDOMan.GetSessionID(); for (int i = 0; i < NearbyObjects.Count; i++) { ZDO val2 = NearbyObjects[i]; if (val2 == null || !val2.Persistent) { continue; } Vector3 position = val2.GetPosition(); bool flag2 = val2.HasOwner(); bool flag3; long num; if (flag) { flag3 = val2.IsOwner(); num = ((flag3 || !flag2) ? 0 : val2.GetOwner()); } else { num = (flag2 ? val2.GetOwner() : 0); flag3 = num == uid; } if (flag3) { if (!ZNetScene.InActiveArea(position, zone)) { val2.SetOwner(0L); } } else if ((!flag2 || !OwnerIsInActiveArea(__instance, position, num)) && ZNetScene.InActiveArea(position, zone)) { val2.SetOwner(uid); } } NearbyObjects.Clear(); return false; } catch { NearbyObjects.Clear(); return true; } } } [HarmonyPatch(typeof(ZPackage), "Write", new Type[] { typeof(ZPackage) })] internal static class ZPackageWritePackagePatch { private static readonly FieldRef<ZPackage, MemoryStream> Stream = AccessTools.FieldRefAccess<ZPackage, MemoryStream>("m_stream"); private static readonly FieldRef<ZPackage, BinaryWriter> Writer = AccessTools.FieldRefAccess<ZPackage, BinaryWriter>("m_writer"); private static bool Prefix(ZPackage __instance, ZPackage pkg) { if (__instance == null || pkg == null) { return true; } MemoryStream memoryStream = Stream.Invoke(pkg); BinaryWriter binaryWriter = Writer.Invoke(pkg); BinaryWriter binaryWriter2 = Writer.Invoke(__instance); if (memoryStream == null || binaryWriter == null || binaryWriter2 == null) { return true; } binaryWriter.Flush(); memoryStream.Flush(); if (!memoryStream.TryGetBuffer(out var buffer)) { return true; } binaryWriter2.Write((int)memoryStream.Length); binaryWriter2.Write(buffer.Array, buffer.Offset, (int)memoryStream.Length); return false; } }