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 ValheimTune v0.7.0
plugins/ValheimTune.dll
Decompiled 7 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Steamworks; using UnityEngine; using ValheimTune.Patches; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ValheimTune")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.7.0.0")] [assembly: AssemblyInformationalVersion("0.7.0+4d181ca723f884dfd05a2c443aacc630925d1ce3")] [assembly: AssemblyProduct("ValheimTune")] [assembly: AssemblyTitle("ValheimTune")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.7.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ValheimTune { public static class AssetUnload { public enum Decision { Run, Defer } public static Decision Decide(int peers, double deferredFor, double maxDeferSecs) { if (peers <= 0) { return Decision.Run; } if (deferredFor >= maxDeferSecs) { return Decision.Run; } return Decision.Defer; } } public static class Cfg { public static ConfigEntry<int> LogIntervalSeconds; public static ConfigEntry<int> SendWindowBytes; public static ConfigEntry<int> MinHeadroomBytes; public static ConfigEntry<bool> AllPeersPerRound; public static ConfigEntry<float> RoundSeconds; public static ConfigEntry<int> SendRateMax; public static ConfigEntry<int> SendRateMin; public static ConfigEntry<int> MaxPacketsPerPeerPerFrame; public static ConfigEntry<int> TargetFrameRate; public static ConfigEntry<int> ConfigReloadSeconds; public static ConfigEntry<bool> FloatingDropsRun; public static ConfigEntry<bool> FloatingDropsDelete; public static ConfigEntry<string> HotObjectsIgnore; public static ConfigEntry<bool> DirtySets; public static ConfigEntry<float> ReconcileSeconds; public static ConfigEntry<int> RelayMinIntervalMs; public static ConfigEntry<string> KnownGoodBuilds; public static ConfigEntry<bool> DisableOnUnknownBuild; public static ConfigEntry<bool> TopKSort; public static ConfigEntry<int> TopK; public static ConfigEntry<bool> ServerSkipRenderMesh; public static ConfigEntry<bool> DeferAssetUnload; public static ConfigEntry<int> AssetUnloadMaxDeferMinutes; public static void Bind(ConfigFile c) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Expected O, but got Unknown //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Expected O, but got Unknown LogIntervalSeconds = c.Bind<int>("Measure", "LogIntervalSeconds", 10, "How often to print the stats line. 0 disables."); ConfigReloadSeconds = c.Bind<int>("Measure", "ConfigReloadSeconds", 5, "Re-read the cfg file this often so knobs that are read at runtime change without a restart. 0 disables. Patch-time settings (SendZDOs window, Steam send rate) still need a restart."); SendWindowBytes = c.Bind<int>("Sync", "SendWindowBytes", 10240, new ConfigDescription("Per-peer bytes in flight before the server stops queueing ZDO data. Vanilla 10240. Try 32768. Also sizes each iteration of the disconnect flush.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(4096, 1048576), Array.Empty<object>())); MinHeadroomBytes = c.Bind<int>("Sync", "MinHeadroomBytes", 2048, new ConfigDescription("Below this much free window the peer is skipped this round. Vanilla 2048. Scale with the window; must stay below SendWindowBytes.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(256, 262144), Array.Empty<object>())); AllPeersPerRound = c.Bind<bool>("Sync", "AllPeersPerRound", false, "Serve every peer each round instead of one peer per frame. Turn on after B1 is verified with several players; otherwise it concentrates the scan cost into one frame (6 peers x 4.1 ms full scans per 0.05 s if the DirtySets watchdog ever disables dirty sets)."); RoundSeconds = c.Bind<float>("Sync", "RoundSeconds", 0.05f, new ConfigDescription("Round period when AllPeersPerRound is on. Vanilla 0.05.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>())); SendRateMax = c.Bind<int>("Steam", "SendRateMaxBytesPerSec", 153600, "Steam per-connection send rate cap. Vanilla 153600 (150 KB/s). Try 1048576. Bounded by your upload / player count."); SendRateMin = c.Bind<int>("Steam", "SendRateMinBytesPerSec", 153600, "Leave at vanilla so the estimator can back off on loss."); MaxPacketsPerPeerPerFrame = c.Bind<int>("Receive", "MaxPacketsPerPeerPerFrame", 0, "Stop draining one peer's socket after this many packets in a frame; the rest wait in Steam's queue. 0 = vanilla (unlimited). Try 64."); TargetFrameRate = c.Bind<int>("Server", "TargetFrameRate", 0, "Application.targetFrameRate for the headless server. 0 = do not touch. Round period is 0.05 + players/fps, so 30 -> 60 doubles the sync rate at 6 players. Costs CPU."); FloatingDropsRun = c.Bind<bool>("Cleanup", "FloatingDropsRun", false, "One-shot trigger: set true to scan for item drops floating in water. The plugin runs it on the next config reload and sets this back to false. Measured ~50 ms of main-thread stall on a 698k-ZDO world (one 67 ms frame, 2026-09-07)."); FloatingDropsDelete = c.Bind<bool>("Cleanup", "FloatingDropsDelete", false, "When a scan runs with this true, the found items are DELETED (server takes ownership and destroys them; clients see them vanish). Leave false for a dry run that only logs counts."); HotObjectsIgnore = c.Bind<string>("Measure", "HotObjectsIgnore", "Player,Fish1,Fish2,Fish3", "Comma-separated prefab names left out of the hot-objects line (things that are expected to move)."); DirtySets = c.Bind<bool>("Sync", "DirtySets", true, "B1: only consider changed ZDOs each round instead of rescanning the whole active area. Full scan on join, zone change, and every ReconcileSeconds."); ReconcileSeconds = c.Bind<float>("Sync", "ReconcileSeconds", 30f, "Safety-net full scan interval per peer when DirtySets is on."); RelayMinIntervalMs = c.Bind<int>("Sync", "RelayMinIntervalMs", 0, "Do not re-send a non-prioritized object (fish, items, pieces) to the same peer more often than this, in ms. 0 = vanilla. 200 = 5 Hz; fish and drifting items are the bulk of idle traffic at a big base."); KnownGoodBuilds = c.Bind<string>("Compat", "KnownGoodBuilds", "1.0.7", "Game versions (Version.CurrentVersion) this build of the plugin was verified against. Comma-separated."); DisableOnUnknownBuild = c.Bind<bool>("Compat", "DisableOnUnknownBuild", true, "On a version not in KnownGoodBuilds, keep only measurement, the send-rate postfix and the constant swap; every replacement patch runs vanilla."); TopKSort = c.Bind<bool>("Sync", "TopKSort", true, "B2: bounded-heap selection of the objects that fit the send window instead of a full sort of every candidate. Only matters during joins, zone changes and the reconcile scan."); ServerSkipRenderMesh = c.Bind<bool>("Server", "SkipRenderMesh", false, "B4a: skip Heightmap.RebuildRenderMesh on a dedicated server. The render mesh is rebuilt for every ghost zone a player explores and every terrain edit that loads with one, and never drawn on a -nographics process. Collision mesh untouched. Watch meshSkips on the stats line."); DeferAssetUnload = c.Bind<bool>("Server", "DeferAssetUnload", false, "G1: hold the hourly Resources.UnloadUnusedAssets() until no players are connected. Vanilla runs it every hour regardless (Game.cs:239); measured 443-607 ms of main-thread stall on a 698k-ZDO world, landing with players online. Deferred, not skipped: it still runs the moment the server empties, or after AssetUnloadMaxDeferMinutes whichever comes first."); AssetUnloadMaxDeferMinutes = c.Bind<int>("Server", "AssetUnloadMaxDeferMinutes", 240, new ConfigDescription("Backstop for DeferAssetUnload: run the collection even with players online once it has been held this long. Stops a server that never empties from never collecting.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 1440), Array.Empty<object>())); TopK = c.Bind<int>("Sync", "TopK", 0, new ConfigDescription("How many candidates to order per round. 0 = SendWindowBytes / 64 (512 at 32 KB), never below 64.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 8192), Array.Empty<object>())); } } public sealed class ChurnTally { private readonly Dictionary<int, int> _counts = new Dictionary<int, int>(); public int Total { get; private set; } public void Add(int key) { _counts.TryGetValue(key, out var value); _counts[key] = value + 1; Total++; } public List<KeyValuePair<int, int>> Top(int n) { return _counts.OrderByDescending((KeyValuePair<int, int> kv) => kv.Value).Take(n).ToList(); } public void Reset() { _counts.Clear(); Total = 0; } } public static class Compat { public static bool ReplacementsAllowed = true; public static string GameVersion = "?"; public static bool IsKnown(string version, string knownList) { if (string.IsNullOrEmpty(knownList)) { return false; } return knownList.Split(',').Any((string s) => s.Trim() == version); } } public static class ConstSwap { public static int LastReplaced; public static IEnumerable<CodeInstruction> Replace(IEnumerable<CodeInstruction> code, IReadOnlyDictionary<int, int> map) { LastReplaced = 0; foreach (CodeInstruction item in code) { if (item.opcode == OpCodes.Ldc_I4 && item.operand is int key && map.TryGetValue(key, out var value)) { LastReplaced++; yield return new CodeInstruction(OpCodes.Ldc_I4, (object)value) { labels = item.labels, blocks = item.blocks }; } else { yield return item; } } } } public sealed class DirtyPeerState<TId> { private (int x, int y) _lastZone = (x: int.MinValue, y: int.MinValue); private float _lastFullScan = float.NegativeInfinity; private bool _wasActive; private readonly List<TId> _prune = new List<TId>(); public HashSet<TId> Pending { get; } = new HashSet<TId>(); public int FullScans { get; private set; } public bool NeedsFullScan((int x, int y) zone, float now, float reconcileSeconds, bool active) { int num; if (_wasActive) { (int, int) tuple = zone; (int, int) lastZone = _lastZone; if (tuple.Item1 == lastZone.Item1 && tuple.Item2 == lastZone.Item2) { num = ((now - _lastFullScan > reconcileSeconds) ? 1 : 0); goto IL_003b; } } num = 1; goto IL_003b; IL_003b: _wasActive = active; if (num != 0) { _lastZone = zone; _lastFullScan = now; FullScans++; } return (byte)num != 0; } public void Drain(List<TId> into, Func<TId, bool> exists, Func<TId, bool> inArea, Func<TId, bool> shouldSend, Func<TId, bool> deferSend = null) { _prune.Clear(); foreach (TId item in Pending) { if (!exists(item) || !inArea(item) || !shouldSend(item)) { _prune.Add(item); } else if (deferSend == null || !deferSend(item)) { into.Add(item); } } foreach (TId item2 in _prune) { Pending.Remove(item2); } } } public static class FloatingDrops { private static readonly Dictionary<int, bool> s_isCandidate = new Dictionary<int, bool>(); private static bool IsFloatingCandidate(int hash) { if (s_isCandidate.TryGetValue(hash, out var value)) { return value; } GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(hash) : null); value = (Object)(object)val != (Object)null && ((Object)(object)val.GetComponent<ItemDrop>() != (Object)null || (Object)(object)val.GetComponent<TreeLog>() != (Object)null) && (Object)(object)val.GetComponent<Fish>() == (Object)null; s_isCandidate[hash] = value; return value; } public static (int found, int deleted) Run(bool delete, ManualLogSource log) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) ZDOMan instance = ZDOMan.instance; if (instance == null || (Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null || WorldGenerator.instance == null) { log.LogWarning((object)"[ValheimTune] floating drops: world not ready"); return (found: 0, deleted: 0); } float waterLevel = ZoneSystem.instance.m_waterLevel; List<ZDOID> list = new List<ZDOID>(); ChurnTally churnTally = new ChurnTally(); List<(string, Vector3)> list2 = new List<(string, Vector3)>(); foreach (KeyValuePair<ZDOID, ZDO> item in instance.m_objectsByID) { ZDO value = item.Value; if (!IsFloatingCandidate(value.GetPrefab())) { continue; } Vector3 position = value.GetPosition(); if (!(position.y > waterLevel + 0.25f) && !(WorldGenerator.instance.GetHeight(position.x, position.z) >= waterLevel)) { list.Add(item.Key); churnTally.Add(value.GetPrefab()); if (list2.Count < 10) { GameObject prefab = ZNetScene.instance.GetPrefab(value.GetPrefab()); list2.Add((((Object)(object)prefab != (Object)null) ? ((Object)prefab).name : value.GetPrefab().ToString(), position)); } } } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("[ValheimTune] floating drops: ").Append(list.Count).Append(delete ? " found, deleting:" : " found (dry run):"); foreach (KeyValuePair<int, int> item2 in churnTally.Top(10)) { GameObject prefab2 = ZNetScene.instance.GetPrefab(item2.Key); stringBuilder.Append(' ').Append(((Object)(object)prefab2 != (Object)null) ? ((Object)prefab2).name : item2.Key.ToString()).Append('=') .Append(item2.Value); } log.LogInfo((object)stringBuilder.ToString()); if (list2.Count > 0) { StringBuilder stringBuilder2 = new StringBuilder("[ValheimTune] floating drops sample:"); foreach (var item3 in list2) { stringBuilder2.Append(' ').Append(item3.Item1).Append('@') .Append('(') .Append((int)item3.Item2.x) .Append(',') .Append((int)item3.Item2.y) .Append(',') .Append((int)item3.Item2.z) .Append(')'); } log.LogInfo((object)stringBuilder2.ToString()); } int num = 0; if (delete) { long sessionID = ZDOMan.GetSessionID(); foreach (ZDOID item4 in list) { ZDO zDO = instance.GetZDO(item4); if (zDO != null) { zDO.SetOwner(sessionID); instance.DestroyZDO(zDO); num++; } } log.LogInfo((object)$"[ValheimTune] floating drops: {num} queued for destruction"); } return (found: list.Count, deleted: num); } } [BepInPlugin("akoozie.valheimtune", "ValheimTune", "0.7.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "akoozie.valheimtune"; public const string Version = "0.7.0"; private const float WatchdogWindowSeconds = 10f; public static ManualLogSource Log; public static Plugin Instance; private Harmony _harmony; private float _logTimer; private float _reloadTimer; private float _wdTimer; private void Awake() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Cfg.Bind(((BaseUnityPlugin)this).Config); if (Cfg.MinHeadroomBytes.Value >= Cfg.SendWindowBytes.Value) { Log.LogError((object)"[ValheimTune] MinHeadroomBytes >= SendWindowBytes: no ZDO will ever be sent. Fix the config."); } Compat.GameVersion = ((object)Version.CurrentVersion/*cast due to .constrained prefix*/).ToString(); Compat.ReplacementsAllowed = !Cfg.DisableOnUnknownBuild.Value || Compat.IsKnown(Compat.GameVersion, Cfg.KnownGoodBuilds.Value); if (!Compat.ReplacementsAllowed) { Log.LogWarning((object)("[ValheimTune] game " + Compat.GameVersion + " not in KnownGoodBuilds (" + Cfg.KnownGoodBuilds.Value + "): replacement patches inactive, running vanilla + measurement")); } _harmony = new Harmony("akoozie.valheimtune"); _harmony.PatchAll(typeof(Plugin).Assembly); uint num = 39u; Log.LogInfo((object)string.Format("[ValheimTune] {0} loaded on game {1} (net {2}), {3} methods patched, replacements {4}", "0.7.0", Compat.GameVersion, num, _harmony.GetPatchedMethods().Count(), Compat.ReplacementsAllowed ? "on" : "OFF")); } private void Update() { //IL_04ff: Unknown result type (might be due to invalid IL or missing references) //IL_0513: Unknown result type (might be due to invalid IL or missing references) ReloadConfig(); RunFloatingDropsIfRequested(); AssetUnloadPatch.RunIfDue(); MeasurePatches.FrameMs.Add(Time.unscaledDeltaTime * 1000f); int value = Cfg.TargetFrameRate.Value; if (value > 0 && Application.targetFrameRate != value) { Application.targetFrameRate = value; Log.LogInfo((object)$"[ValheimTune] targetFrameRate set to {value}"); } ZDOMan instance = ZDOMan.instance; int num = ((instance != null) ? instance.GetRecvZDOs() : 0); _wdTimer += Time.unscaledDeltaTime; if (_wdTimer >= 10f) { long watchdogRecv = DirtyPatches.WatchdogRecv; long watchdogMarks = DirtyPatches.WatchdogMarks; if (DirtyPatches.WatchdogShouldTrip(Cfg.DirtySets.Value, DirtyPatches.Disabled, watchdogRecv > 0, watchdogMarks)) { DirtyPatches.Disabled = true; Log.LogError((object)$"[ValheimTune] DirtySets: {watchdogRecv} ZDOs deserialized in {10f:F0} s but the revision hook fired 0 times; falling back to vanilla scanning. The ZDO revision setters are probably inlined on this Mono build."); } else if (DirtyPatches.WatchdogShouldRearm(DirtyPatches.Disabled, watchdogMarks)) { DirtyPatches.Disabled = false; Log.LogWarning((object)$"[ValheimTune] DirtySets: revision hook fired {watchdogMarks} times while disabled; re-armed (full scan per peer on the next round)."); } DirtyPatches.WatchdogMarks = 0L; DirtyPatches.WatchdogRecv = 0L; _wdTimer = 0f; } int value2 = Cfg.LogIntervalSeconds.Value; if (value2 <= 0) { MeasurePatches.ResetAll(); DirtyPatches.ResetCounters(); RenderMeshPatch.Skipped = 0L; return; } _logTimer += Time.unscaledDeltaTime; if (_logTimer < (float)value2) { return; } _logTimer = 0f; int num2 = instance?.m_peers.Count ?? 0; int num3 = ((instance != null) ? instance.GetSentZDOs() : 0); int num4 = num; Log.LogInfo((object)($"[ValheimTune] frame avg {MeasurePatches.FrameMs.Avg:F1} max {MeasurePatches.FrameMs.Max:F1} ms " + $"({1000.0 / Math.Max(0.01, MeasurePatches.FrameMs.Avg):F0} fps) | " + $"syncList avg {MeasurePatches.SyncListMs.Avg:F2} max {MeasurePatches.SyncListMs.Max:F2} ms | " + $"send avg {MeasurePatches.SendMs.Avg:F2} ms | Z max {MeasurePatches.MaxZ} | peer-sends {MeasurePatches.Rounds} | " + $"zdos/s sent {num3} recv {num4} | peers {num2}" + string.Format(" | marks {0} full {1} dirtyRounds {2} deferred {3} drained {4}{5}", DirtyPatches.Marks, DirtyPatches.FullScans, DirtyPatches.DirtyRounds, DirtyPatches.Deferred, DirtyPatches.LastDrained, DirtyPatches.Disabled ? " DISABLED" : "") + $" | meshSkips {RenderMeshPatch.Skipped}")); if (MeasurePatches.Recv.Total > 0) { StringBuilder stringBuilder = new StringBuilder("[ValheimTune] recv by prefab ("); stringBuilder.Append(MeasurePatches.Recv.Total).Append(" in window):"); ZNetScene scene = ZNetScene.instance; foreach (KeyValuePair<int, int> item2 in MeasurePatches.Recv.Top(8)) { string text = null; if ((Object)(object)scene != (Object)null) { GameObject prefab = scene.GetPrefab(item2.Key); if ((Object)(object)prefab != (Object)null) { text = ((Object)prefab).name; } } stringBuilder.Append(' ').Append(text ?? item2.Key.ToString()).Append('=') .Append(item2.Value); } Log.LogInfo((object)stringBuilder.ToString()); HashSet<string> ignoreSet = new HashSet<string>(from s in Cfg.HotObjectsIgnore.Value.Split(',') select s.Trim()); List<KeyValuePair<ZDOID, (int, int, Vector3)>> list = MeasurePatches.HotTop(12).Where(delegate(KeyValuePair<ZDOID, (int count, int prefab, Vector3 pos)> x) { ZNetScene obj3 = scene; object obj4; if (obj3 == null) { obj4 = null; } else { GameObject prefab3 = obj3.GetPrefab(x.Value.prefab); obj4 = ((prefab3 != null) ? ((Object)prefab3).name : null); } if (obj4 == null) { obj4 = x.Value.prefab.ToString(); } string item = (string)obj4; return !ignoreSet.Contains(item); }).Take(6) .ToList(); if (list.Count > 0) { StringBuilder stringBuilder2 = new StringBuilder("[ValheimTune] hot objects:"); foreach (KeyValuePair<ZDOID, (int, int, Vector3)> item3 in list) { ZNetScene obj = scene; object obj2; if (obj == null) { obj2 = null; } else { GameObject prefab2 = obj.GetPrefab(item3.Value.Item2); obj2 = ((prefab2 != null) ? ((Object)prefab2).name : null); } if (obj2 == null) { obj2 = item3.Value.Item2.ToString(); } string value3 = (string)obj2; int value4 = (int)item3.Value.Item3.x; int value5 = (int)item3.Value.Item3.z; stringBuilder2.Append(' ').Append(value3).Append('=') .Append(item3.Value.Item1) .Append('@') .Append('(') .Append(value4) .Append(',') .Append(value5) .Append(')'); } Log.LogInfo((object)stringBuilder2.ToString()); } } RenderMeshPatch.Skipped = 0L; DirtyPatches.ResetCounters(); MeasurePatches.ResetAll(); } private void ReloadConfig() { int value = Cfg.ConfigReloadSeconds.Value; if (value <= 0) { return; } _reloadTimer += Time.unscaledDeltaTime; if (_reloadTimer < (float)value) { return; } _reloadTimer = 0f; try { ((BaseUnityPlugin)this).Config.Reload(); } catch (Exception arg) { Log.LogError((object)$"[ValheimTune] config reload failed: {arg}"); } } private void RunFloatingDropsIfRequested() { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null || !Cfg.FloatingDropsRun.Value) { return; } try { FloatingDrops.Run(Cfg.FloatingDropsDelete.Value, Log); } catch (Exception arg) { Log.LogError((object)$"[ValheimTune] floating drops run failed: {arg}"); } finally { Cfg.FloatingDropsRun.Value = false; ((BaseUnityPlugin)this).Config.Save(); } } } public sealed class RollingStats { private double _sum; public int Count { get; private set; } public double Max { get; private set; } public double Avg { get { if (Count != 0) { return _sum / (double)Count; } return 0.0; } } public void Add(double v) { _sum += v; Count++; if (v > Max) { Max = v; } } public void Reset() { _sum = 0.0; Count = 0; Max = 0.0; } } public static class TopK { private static class Buf<T> { public static T[] Items; } private static double[] s_rank; private static int[] s_heap; private static bool[] s_taken; public static void Select<T>(List<T> items, Func<T, double> rank, int k) { int count = items.Count; if (count == 0 || k <= 0) { return; } if (k > count) { k = count; } if (s_rank == null || s_rank.Length < count) { s_rank = new double[count]; s_heap = new int[count]; s_taken = new bool[count]; } if (Buf<T>.Items == null || Buf<T>.Items.Length < count) { Buf<T>.Items = new T[count]; } double[] array = s_rank; int[] array2 = s_heap; bool[] array3 = s_taken; T[] items2 = Buf<T>.Items; for (int i = 0; i < count; i++) { items2[i] = items[i]; array[i] = rank(items[i]); array3[i] = false; } int num = 0; for (int j = 0; j < count; j++) { if (num < k) { array2[num] = j; num++; SiftUp(array2, array, num - 1); } else if (array[j] < array[array2[0]]) { array2[0] = j; SiftDown(array2, array, 0, num); } } int num2 = num; for (int num3 = num2 - 1; num3 >= 0; num3--) { int num4 = array2[0]; array3[num4] = true; items[num3] = items2[num4]; num--; array2[0] = array2[num]; SiftDown(array2, array, 0, num); } int num5 = num2; for (int l = 0; l < count; l++) { if (!array3[l]) { items[num5++] = items2[l]; } } } private static void SiftUp(int[] heap, double[] rankArr, int i) { while (i > 0) { int num = (i - 1) / 2; if (!(rankArr[heap[num]] >= rankArr[heap[i]])) { ref int reference = ref heap[num]; ref int reference2 = ref heap[i]; int num2 = heap[i]; int num3 = heap[num]; reference = num2; reference2 = num3; i = num; continue; } break; } } private static void SiftDown(int[] heap, double[] rankArr, int i, int count) { while (true) { int num = 2 * i + 1; int num2 = 2 * i + 2; int num3 = i; if (num < count && rankArr[heap[num]] > rankArr[heap[num3]]) { num3 = num; } if (num2 < count && rankArr[heap[num2]] > rankArr[heap[num3]]) { num3 = num2; } if (num3 != i) { ref int reference = ref heap[i]; ref int reference2 = ref heap[num3]; int num4 = heap[num3]; int num5 = heap[i]; reference = num4; reference2 = num5; i = num3; continue; } break; } } } } namespace ValheimTune.Patches { [HarmonyPatch(typeof(Game), "CollectResources")] public static class AssetUnloadPatch { private static float s_deferredSince = -1f; public static bool Pending => s_deferredSince >= 0f; [HarmonyPrefix] private static bool Prefix() { if (!Compat.ReplacementsAllowed || !Cfg.DeferAssetUnload.Value) { return true; } if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsDedicated()) { return true; } int peerConnections = ZNet.instance.GetPeerConnections(); float realtimeSinceStartup = Time.realtimeSinceStartup; double num = ((s_deferredSince < 0f) ? 0.0 : ((double)(realtimeSinceStartup - s_deferredSince))); double maxDeferSecs = (double)Cfg.AssetUnloadMaxDeferMinutes.Value * 60.0; if (AssetUnload.Decide(peerConnections, num, maxDeferSecs) == AssetUnload.Decision.Defer) { if (s_deferredSince < 0f) { s_deferredSince = realtimeSinceStartup; Plugin.Log.LogInfo((object)$"[ValheimTune] asset unload deferred: {peerConnections} player(s) online, will run when the server empties (backstop {Cfg.AssetUnloadMaxDeferMinutes.Value} min)"); } return false; } if (s_deferredSince >= 0f) { Plugin.Log.LogInfo((object)$"[ValheimTune] asset unload running after {num:F0} s deferred ({peerConnections} player(s) online)"); s_deferredSince = -1f; } return true; } public static void RunIfDue() { if (!Pending || !Cfg.DeferAssetUnload.Value) { return; } ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null) { return; } double deferredFor = Time.realtimeSinceStartup - s_deferredSince; if (AssetUnload.Decide(instance.GetPeerConnections(), deferredFor, (double)Cfg.AssetUnloadMaxDeferMinutes.Value * 60.0) == AssetUnload.Decision.Run) { Game instance2 = Game.instance; if (instance2 != null) { instance2.CollectResources(false); } } } } [HarmonyPatch] public static class ConstPatches { private static bool s_allPeersDisabledLogged; private static bool s_rateLogged; [HarmonyPatch(typeof(ZDOMan), "SendZDOs")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> SendZDOsWindow(IEnumerable<CodeInstruction> code) { Dictionary<int, int> map = new Dictionary<int, int> { { 10240, Cfg.SendWindowBytes.Value }, { 2048, Cfg.MinHeadroomBytes.Value } }; List<CodeInstruction> list = new List<CodeInstruction>(code); List<CodeInstruction> result = new List<CodeInstruction>(ConstSwap.Replace(list, map)); if (ConstSwap.LastReplaced != 3) { Plugin.Log.LogError((object)$"[ValheimTune] SendZDOs: {ConstSwap.LastReplaced} constants replaced, expected 3; leaving the method untouched"); return list; } Plugin.Log.LogInfo((object)$"[ValheimTune] SendZDOs window {Cfg.SendWindowBytes.Value}/{Cfg.MinHeadroomBytes.Value}, {ConstSwap.LastReplaced} constants replaced (expected 3)"); return result; } [HarmonyPatch(typeof(ZDOMan), "SendZDOToPeers2")] [HarmonyPrefix] private static bool AllPeersPerRound(ZDOMan __instance, float dt) { if (!Compat.ReplacementsAllowed || !Cfg.AllPeersPerRound.Value || DirtyPatches.Disabled) { if (DirtyPatches.Disabled && !s_allPeersDisabledLogged) { s_allPeersDisabledLogged = true; Plugin.Log.LogWarning((object)"[ValheimTune] AllPeersPerRound skipped: DirtySets watchdog disabled dirty sets, falling back to vanilla one-peer-per-frame to avoid stacking full scans in one frame."); } return true; } if (__instance.m_peers.Count == 0) { return false; } __instance.m_sendTimer += dt; if (__instance.m_sendTimer < Cfg.RoundSeconds.Value) { return false; } __instance.m_sendTimer = 0f; for (int i = 0; i < __instance.m_peers.Count; i++) { try { __instance.SendZDOs(__instance.m_peers[i], false); } catch (Exception arg) { Plugin.Log.LogError((object)$"[ValheimTune] SendZDOs threw for peer {i}: {arg}"); } } return false; } [HarmonyPatch(typeof(ZSteamSocket), "RegisterGlobalCallbacks")] [HarmonyPostfix] private static void SendRate() { SetGlobalInt((ESteamNetworkingConfigValue)10, Cfg.SendRateMin.Value); SetGlobalInt((ESteamNetworkingConfigValue)11, Cfg.SendRateMax.Value); if (!s_rateLogged) { s_rateLogged = true; Plugin.Log.LogInfo((object)$"[ValheimTune] Steam send rate min {Cfg.SendRateMin.Value} max {Cfg.SendRateMax.Value} B/s"); } } private static void SetGlobalInt(ESteamNetworkingConfigValue key, int value) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) GCHandle gCHandle = GCHandle.Alloc(value, GCHandleType.Pinned); try { if (!SteamGameServerNetworkingUtils.SetConfigValue(key, (ESteamNetworkingConfigScope)1, IntPtr.Zero, (ESteamNetworkingConfigDataType)1, gCHandle.AddrOfPinnedObject())) { Plugin.Log.LogError((object)$"[ValheimTune] Steam rejected {key} = {value}"); } } finally { gCHandle.Free(); } } } [HarmonyPatch] public static class DirtyPatches { public static long MarksData; public static long MarksOwner; public static int FullScans; public static int DirtyRounds; public static int Deferred; public static int LastDrained; public static bool Disabled; public static long WatchdogMarks; public static long WatchdogRecv; private static readonly ConditionalWeakTable<ZDOPeer, DirtyPeerState<ZDOID>> s_state = new ConditionalWeakTable<ZDOPeer, DirtyPeerState<ZDOID>>(); private static readonly List<ZDOID> s_ids = new List<ZDOID>(256); private static int s_relayMinMs; public static long Marks => MarksData + MarksOwner; private static bool Active { get { if (Compat.ReplacementsAllowed && Cfg.DirtySets.Value && !Disabled && (Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.IsServer(); } return false; } } internal static int ZoneChebyshev(Vector2s a, Vector2s b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) int num = a.x - b.x; if (num < 0) { num = -num; } int num2 = a.y - b.y; if (num2 < 0) { num2 = -num2; } if (num <= num2) { return num2; } return num; } internal static bool InNear(Vector2s centre, Vector2s candidate, SimulationDistance sd) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) if (ZoneChebyshev(centre, candidate) > ((SimulationDistance)(ref sd)).NearSimulationDistance) { return false; } if (!((SimulationDistance)(ref sd)).IsClassic) { return ZoneSystem.instance.ZonesWithinRadius(centre, candidate, ((SimulationDistance)(ref sd)).NearSimulationDistance, false); } return true; } internal static bool InDistant(Vector2s centre, Vector2s candidate, SimulationDistance sd) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) if (ZoneChebyshev(centre, candidate) > ((SimulationDistance)(ref sd)).TotalSimulationDistance) { return false; } if (!((SimulationDistance)(ref sd)).IsClassic) { return ZoneSystem.instance.ZonesWithinRadius(centre, candidate, ((SimulationDistance)(ref sd)).TotalSimulationDistance, true); } return true; } public static DirtyPeerState<ZDOID> StateFor(ZDOPeer peer) { return s_state.GetValue(peer, (ZDOPeer _) => new DirtyPeerState<ZDOID>()); } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPostfix] private static void DataRevisionSet(ZDO __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Mark(__instance.m_uid, isOwner: false); } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPostfix] private static void OwnerRevisionSet(ZDO __instance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Mark(__instance.m_uid, isOwner: true); } private static void Mark(ZDOID id, bool isOwner) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (id == ZDOID.None) { return; } if (isOwner) { MarksOwner++; } else { MarksData++; WatchdogMarks++; } if (!Active) { return; } ZDOMan instance = ZDOMan.instance; if (instance != null) { List<ZDOPeer> peers = instance.m_peers; for (int i = 0; i < peers.Count; i++) { StateFor(peers[i]).Pending.Add(id); } } } public static void ResetCounters() { MarksData = 0L; MarksOwner = 0L; FullScans = 0; DirtyRounds = 0; Deferred = 0; LastDrained = 0; } public static bool WatchdogShouldTrip(bool dirtySetsOn, bool disabled, bool recvSeen, long marksInWindow) { if (dirtySetsOn && !disabled && recvSeen) { return marksInWindow == 0; } return false; } public static bool WatchdogShouldRearm(bool disabled, long marksInWindow) { if (disabled) { return marksInWindow > 0; } return false; } [HarmonyPatch(typeof(ZDOMan), "CreateSyncList")] [HarmonyPrefix] private static bool CreateSyncListPrefix(ZDOMan __instance, ZDOPeer peer, List<ZDO> toSync, out bool __state) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) __state = false; ZDOID lastId = ZDOID.None; ZDO lastZdo = null; bool active = Active; Vector3 refPos = peer.m_peer.GetRefPos(); Vector2s zone = ZoneSystem.GetZone(refPos); DirtyPeerState<ZDOID> dirtyPeerState = StateFor(peer); bool flag = dirtyPeerState.NeedsFullScan((x: zone.x, y: zone.y), Time.time, Cfg.ReconcileSeconds.Value, active); if (!active) { return true; } if (flag) { FullScans++; __state = true; return true; } DirtyRounds++; SimulationDistance sd = peer.m_peer.m_simulationDistance; s_relayMinMs = Cfg.RelayMinIntervalMs.Value; s_ids.Clear(); dirtyPeerState.Drain(s_ids, (ZDOID id) => Z(id) != null, delegate(ZDOID id) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_0015: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) ZDO val = Z(id); Vector2s sector = val.GetSector(); return InNear(zone, sector, sd) || (val.Distant && InDistant(zone, sector, sd)); }, (ZDOID id) => peer.ShouldSend(Z(id)), (ZDOID id) => RelayThrottled(peer, Z(id))); LastDrained = s_ids.Count; int num = 0; for (int num2 = 0; num2 < s_ids.Count; num2++) { ZDO zDO = __instance.GetZDO(s_ids[num2]); if (InNear(zone, zDO.GetSector(), sd)) { toSync.Add(zDO); num++; } } if (num < 10) { for (int num3 = 0; num3 < s_ids.Count; num3++) { ZDO zDO2 = __instance.GetZDO(s_ids[num3]); if (!InNear(zone, zDO2.GetSector(), sd)) { toSync.Add(zDO2); } } } __instance.ServerSortSendZDOS(toSync, refPos, peer); __instance.AddForceSendZdos(peer, toSync); return false; ZDO Z(ZDOID id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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) if (id != lastId) { lastZdo = __instance.GetZDO(id); lastId = id; } return lastZdo; } } [HarmonyPatch(typeof(ZDOMan), "CreateSyncList")] [HarmonyPostfix] private static void CreateSyncListPostfix(ZDOPeer peer, List<ZDO> toSync, bool __state) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (__state) { DirtyPeerState<ZDOID> dirtyPeerState = StateFor(peer); for (int i = 0; i < toSync.Count; i++) { dirtyPeerState.Pending.Add(toSync[i].m_uid); } } } private static bool RelayThrottled(ZDOPeer peer, ZDO z) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) int num = s_relayMinMs; if (num <= 0) { return false; } if ((int)z.Type == 1) { return false; } if (z.GetOwner() == peer.m_peer.m_uid) { return false; } if (!peer.m_zdos.TryGetValue(z.m_uid, out var value)) { return false; } bool num2 = (Time.time - value.m_syncTime) * 1000f < (float)num; if (num2) { Deferred++; } return num2; } } [HarmonyPatch] public static class MeasurePatches { public static readonly RollingStats FrameMs = new RollingStats(); public static readonly RollingStats SyncListMs = new RollingStats(); public static readonly RollingStats SendMs = new RollingStats(); public static readonly ChurnTally Recv = new ChurnTally(); public static int MaxZ; public static int Rounds; private static readonly Stopwatch s_sync = new Stopwatch(); private static readonly Stopwatch s_send = new Stopwatch(); private static readonly Dictionary<ZDOID, (int count, int prefab, Vector3 pos)> s_hot = new Dictionary<ZDOID, (int, int, Vector3)>(); [HarmonyPatch(typeof(ZDOMan), "CreateSyncList")] [HarmonyPrefix] [HarmonyPriority(800)] private static void SyncListPrefix() { s_sync.Restart(); } [HarmonyPatch(typeof(ZDOMan), "CreateSyncList")] [HarmonyPostfix] private static void SyncListPostfix(ZDOMan __instance) { SyncListMs.Add(s_sync.Elapsed.TotalMilliseconds); int count = __instance.m_tempSectorObjects.Count; if (count > MaxZ) { MaxZ = count; } } [HarmonyPatch(typeof(ZDOMan), "SendZDOs")] [HarmonyPrefix] [HarmonyPriority(800)] private static void SendPrefix() { s_send.Restart(); } [HarmonyPatch(typeof(ZDOMan), "SendZDOs")] [HarmonyPostfix] private static void SendPostfix() { SendMs.Add(s_send.Elapsed.TotalMilliseconds); Rounds++; } [HarmonyPatch(typeof(ZDO), "Deserialize")] [HarmonyPostfix] private static void DeserializePostfix(ZDO __instance) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) Recv.Add(__instance.GetPrefab()); DirtyPatches.WatchdogRecv++; ZDOID uid = __instance.m_uid; s_hot.TryGetValue(uid, out (int, int, Vector3) value); s_hot[uid] = (value.Item1 + 1, __instance.GetPrefab(), __instance.GetPosition()); } public static List<KeyValuePair<ZDOID, (int count, int prefab, Vector3 pos)>> HotTop(int n) { return s_hot.OrderByDescending((KeyValuePair<ZDOID, (int count, int prefab, Vector3 pos)> x) => x.Value.count).Take(n).ToList(); } public static void ResetAll() { FrameMs.Reset(); SyncListMs.Reset(); SendMs.Reset(); MaxZ = 0; Rounds = 0; Recv.Reset(); s_hot.Clear(); } } [HarmonyPatch(typeof(ZRpc), "Update")] public static class ReceiveCapPatch { [HarmonyPrefix] private static bool Prefix(ZRpc __instance, float dt, ref ErrorCode __result) { int value = Cfg.MaxPacketsPerPeerPerFrame.Value; if (!Compat.ReplacementsAllowed || value <= 0) { return true; } if (!__instance.m_socket.IsConnected()) { __result = (ErrorCode)1; return false; } for (int i = 0; i < value; i++) { ZPackage val = __instance.m_socket.Recv(); if (val == null) { break; } __instance.m_recvPackages++; __instance.m_recvData += val.Size(); try { __instance.HandlePackage(val); } catch (EndOfStreamException ex) { ZLog.LogError((object)("EndOfStreamException in ZRpc::HandlePackage: Assume incompatible version: " + ex.Message)); __result = (ErrorCode)2; return false; } catch (Exception ex2) { ZLog.Log((object)("Exception in ZRpc::HandlePackage: " + ex2)); } } __instance.UpdatePing(dt); __result = (ErrorCode)0; return false; } } [HarmonyPatch(typeof(Heightmap), "RebuildRenderMesh")] public static class RenderMeshPatch { public static long Skipped; [HarmonyPrefix] private static bool Prefix() { if (!Compat.ReplacementsAllowed || !Cfg.ServerSkipRenderMesh.Value) { return true; } if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsDedicated()) { return true; } Skipped++; return false; } } [HarmonyPatch] public static class SortPatches { private static bool Active { get { if (Compat.ReplacementsAllowed && Cfg.TopKSort.Value && (Object)(object)ZNet.instance != (Object)null) { return ZNet.instance.IsServer(); } return false; } } [HarmonyPatch(typeof(ZDOMan), "ServerSortSendZDOS")] [HarmonyPrefix] private static bool Prefix(List<ZDO> objects, Vector3 refPos, ZDOPeer peer) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (!Active) { return true; } float time = Time.time; long receiver = peer.m_peer.m_uid; Dictionary<ZDOID, PeerZDOInfo> zdos = peer.m_zdos; int k = ((Cfg.TopK.Value > 0) ? Cfg.TopK.Value : Math.Max(64, Cfg.SendWindowBytes.Value / 64)); TopK.Select(objects, delegate(ZDO z) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_002a: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) int num = (((int)z.Type != 1 || !z.HasOwner() || z.GetOwner() == receiver) ? (1 + (3 - z.Type)) : 0); float num2 = 100f; if (zdos.TryGetValue(z.m_uid, out var value)) { num2 = Mathf.Clamp(time - value.m_syncTime, 0f, 100f); } double num3 = Vector3.Distance(z.GetPosition(), refPos) - num2 * 1.5f; return (double)num * 100000.0 + num3; }, k); return false; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }