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 ValheimScalability v1.0.0
plugins\ValheimScalability.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Profiling; using UnityEngine.Rendering; using ValheimScalability.BepInExConfig; using ValheimScalability.Patches; using ValheimScalability.Rendering.Clustering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ValheimScalability")] [assembly: AssemblyDescription("Valheim Mod for rapid world startup and server joining without UI interaction")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("zolantris")] [assembly: AssemblyProduct("ValheimScalability")] [assembly: AssemblyCopyright("Copyright © 2026, GNU-v3 licensed")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 ValheimVehicles.SharedScripts { internal static class BuildInfo { public const string Version = "1.0.0"; public const string AssemblyVersion = "1.0.0.0"; public const string FileVersion = "1.0.0.0"; public const string PackageVersion = "1.0.0"; } } namespace ValheimScalability { [BepInPlugin("zolantris.ValheimScalability", "ValheimScalability", "1.0.0")] public class ValheimScalabilityPlugin : BaseUnityPlugin { public const string Author = "zolantris"; public const string Version = "1.0.0"; public const string ModName = "ValheimScalability"; public const string BepInGuid = "zolantris.ValheimScalability"; private static Harmony _harmony; public const string ModDescription = "Valheim Mod meant to unlock performance and scalability of your machine"; public const string CopyRight = "Copyright © 2026, GNU-v3 licensed"; public static string HarmonyGuid => "zolantris.ValheimScalability"; public void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown ValheimScalabilityConfig.Bind(((BaseUnityPlugin)this).Config); _harmony = new Harmony(HarmonyGuid); _harmony.PatchAll(typeof(SectorMeshClusterPatches)); _harmony.PatchAll(typeof(SectorMeshClusterDamagePatch)); } } } namespace ValheimScalability.Rendering.Clustering { public static class ClusterBatchFilter { private static readonly object Sync = new object(); private static bool _dirty = true; private static HashSet<int> _includedLayers = new HashSet<int>(); private static HashSet<int> _excludedLayers = new HashSet<int>(); private static string[] _includedObjectNames = Array.Empty<string>(); private static string[] _excludedObjectNames = Array.Empty<string>(); private static Regex[] _includedObjectRegex = Array.Empty<Regex>(); private static Regex[] _excludedObjectRegex = Array.Empty<Regex>(); private static string[] _excludedMaterialNames = Array.Empty<string>(); private static Regex[] _excludedMaterialRegex = Array.Empty<Regex>(); private static string[] _excludedShaderNames = Array.Empty<string>(); private static Regex[] _excludedShaderRegex = Array.Empty<Regex>(); private static string[] _instancedObjectHints = Array.Empty<string>(); private static string[] _instancedMaterialHints = Array.Empty<string>(); private static string[] _instancedShaderHints = Array.Empty<string>(); private static Regex[] _instancedCandidateRegex = Array.Empty<Regex>(); private static string[] _windPropertyNames = Array.Empty<string>(); private static bool _hasObjectIncludeFilter; public static void Invalidate() { lock (Sync) { _dirty = true; } } public static bool IsLayerAllowed(int layer) { EnsureParsed(); if (_excludedLayers.Contains(layer)) { return false; } if (_includedLayers.Count != 0) { return _includedLayers.Contains(layer); } return true; } public static bool IsObjectAllowed(string rootName, string rendererName) { EnsureParsed(); if (MatchesSubstring(rootName, _excludedObjectNames) || MatchesSubstring(rendererName, _excludedObjectNames) || MatchesRegex(rootName, _excludedObjectRegex) || MatchesRegex(rendererName, _excludedObjectRegex)) { return false; } if (!_hasObjectIncludeFilter) { return true; } if (!MatchesSubstring(rootName, _includedObjectNames) && !MatchesSubstring(rendererName, _includedObjectNames) && !MatchesRegex(rootName, _includedObjectRegex)) { return MatchesRegex(rendererName, _includedObjectRegex); } return true; } public static bool IsMaterialAllowed(Material material) { EnsureParsed(); if (!Object.op_Implicit((Object)(object)material)) { return false; } if (!MatchesSubstring(((Object)material).name, _excludedMaterialNames)) { return !MatchesRegex(((Object)material).name, _excludedMaterialRegex); } return false; } public static bool IsShaderAllowed(Shader shader) { EnsureParsed(); if (!Object.op_Implicit((Object)(object)shader)) { return false; } if (!MatchesSubstring(((Object)shader).name, _excludedShaderNames)) { return !MatchesRegex(((Object)shader).name, _excludedShaderRegex); } return false; } public static bool IsInstancingCandidate(string rootName, string rendererName, Material[] materials) { EnsureParsed(); if (MatchesSubstring(rootName, _instancedObjectHints) || MatchesSubstring(rendererName, _instancedObjectHints)) { return true; } string text = rootName + "|" + rendererName; foreach (Material val in materials) { if (!Object.op_Implicit((Object)(object)val)) { continue; } text = text + "|" + ((Object)val).name; if (MatchesSubstring(((Object)val).name, _instancedMaterialHints)) { return true; } if (Object.op_Implicit((Object)(object)val.shader)) { text = text + "|" + ((Object)val.shader).name; if (MatchesSubstring(((Object)val.shader).name, _instancedShaderHints)) { return true; } } string[] windPropertyNames = _windPropertyNames; foreach (string text2 in windPropertyNames) { if (!string.IsNullOrWhiteSpace(text2) && val.HasProperty(text2)) { return true; } } } return MatchesRegex(text, _instancedCandidateRegex); } private static void EnsureParsed() { if (!_dirty) { return; } lock (Sync) { if (_dirty) { _includedLayers = ParseLayers(ValheimScalabilityConfig.IncludedLayers?.Value); _excludedLayers = ParseLayers(ValheimScalabilityConfig.ExcludedLayers?.Value); _includedObjectNames = ParseCsv(ValheimScalabilityConfig.IncludedObjectNames?.Value); _excludedObjectNames = ParseCsv(ValheimScalabilityConfig.ExcludedObjectNames?.Value); _includedObjectRegex = ParseRegexList(ValheimScalabilityConfig.IncludedObjectRegexList?.Value, "IncludedObjectRegexList"); _excludedObjectRegex = ParseRegexList(ValheimScalabilityConfig.ExcludedObjectRegexList?.Value, "ExcludedObjectRegexList"); _excludedMaterialNames = ParseCsv(ValheimScalabilityConfig.ExcludedMaterialNames?.Value); _excludedMaterialRegex = ParseRegexList(ValheimScalabilityConfig.ExcludedMaterialRegexList?.Value, "ExcludedMaterialRegexList"); _excludedShaderNames = ParseCsv(ValheimScalabilityConfig.ExcludedShaderNames?.Value); _excludedShaderRegex = ParseRegexList(ValheimScalabilityConfig.ExcludedShaderRegexList?.Value, "ExcludedShaderRegexList"); _instancedObjectHints = ParseCsv(ValheimScalabilityConfig.InstancedObjectNameHints?.Value); _instancedMaterialHints = ParseCsv(ValheimScalabilityConfig.InstancedMaterialNameHints?.Value); _instancedShaderHints = ParseCsv(ValheimScalabilityConfig.InstancedShaderNameHints?.Value); _instancedCandidateRegex = ParseRegexList(ValheimScalabilityConfig.InstancedCandidateRegexList?.Value, "InstancedCandidateRegexList"); _windPropertyNames = ParseCsv(ValheimScalabilityConfig.WindShaderPropertyNames?.Value); _hasObjectIncludeFilter = _includedObjectNames.Length != 0 || _includedObjectRegex.Length != 0; _dirty = false; } } } private static string[] ParseCsv(string value) { if (string.IsNullOrWhiteSpace(value)) { return Array.Empty<string>(); } string[] array = value.Split(','); List<string> list = new List<string>(array.Length); string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string text = array2[i].Trim(); if (!string.IsNullOrWhiteSpace(text)) { list.Add(text); } } return list.ToArray(); } private static Regex[] ParseRegexList(string value, string settingName) { if (string.IsNullOrWhiteSpace(value)) { return Array.Empty<Regex>(); } string[] array = value.Split(new char[3] { ';', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); List<Regex> list = new List<Regex>(array.Length); string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string text = array2[i].Trim(); if (!string.IsNullOrWhiteSpace(text)) { try { list.Add(new Regex(text, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant)); } catch (ArgumentException ex) { Debug.LogWarning((object)("[ValheimScalability] Ignoring invalid regex in " + settingName + ": '" + text + "'. " + ex.Message)); } } } return list.ToArray(); } private static HashSet<int> ParseLayers(string value) { HashSet<int> hashSet = new HashSet<int>(); if (string.IsNullOrWhiteSpace(value)) { return hashSet; } string[] array = value.Split(','); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (string.IsNullOrWhiteSpace(text)) { continue; } if (int.TryParse(text, out var result)) { if (result >= 0 && result <= 31) { hashSet.Add(result); } continue; } int num = LayerMask.NameToLayer(text); if (num >= 0) { hashSet.Add(num); } else { Debug.LogWarning((object)("[ValheimScalability] Unknown layer '" + text + "' in clustering filter.")); } } return hashSet; } private static bool MatchesSubstring(string value, string[] patterns) { if (string.IsNullOrEmpty(value)) { return false; } foreach (string value2 in patterns) { if (value.IndexOf(value2, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } private static bool MatchesRegex(string value, Regex[] regexes) { if (string.IsNullOrEmpty(value)) { return false; } for (int i = 0; i < regexes.Length; i++) { if (regexes[i].IsMatch(value)) { return true; } } return false; } } public enum ClusterPresentationMode { Off, FullCluster, Adaptive } public enum ClusterRenderStrategy { Original, CombinedMesh, Instanced } internal static class DynamicHierarchyBatchExclusion { private const string MBParentIdKey = "MBParentId"; private const string SwivelParentIdKey = "SwivelParentId"; private static readonly int MBParentIdHash = StringExtensionMethods.GetStableHashCode("MBParentId"); public static bool HasPersistedMovingParent(ZDO zdo) { if (zdo == null) { return false; } if (zdo.GetInt(MBParentIdHash, 0) == 0) { return zdo.GetInt("SwivelParentId", 0) != 0; } return true; } public static bool ShouldExclude(GameObject root) { if (!Object.op_Implicit((Object)(object)root)) { return true; } ZNetView val = root.GetComponent<ZNetView>() ?? root.GetComponentInParent<ZNetView>(); if (Object.op_Implicit((Object)(object)val) && HasPersistedMovingParent(val.GetZDO())) { return true; } return (Object)(object)root.GetComponentInParent<Rigidbody>() != (Object)null; } public static bool ShouldExclude(ZDO zdo, GameObject root) { if (HasPersistedMovingParent(zdo)) { return true; } if (Object.op_Implicit((Object)(object)root)) { return (Object)(object)root.GetComponentInParent<Rigidbody>() != (Object)null; } return false; } public static bool ShouldExcludeRenderer(MeshRenderer renderer) { if (Object.op_Implicit((Object)(object)renderer)) { return (Object)(object)((Component)renderer).GetComponentInParent<Rigidbody>() != (Object)null; } return false; } } public sealed class InstancedClusterBatch { private readonly Matrix4x4[][] _matrixChunks; public Mesh Mesh { get; } public int SubMeshIndex { get; } public Material SourceMaterial { get; } public Material InstancedMaterial { get; } public int Layer { get; } public ShadowCastingMode ShadowCastingMode { get; } public bool ReceiveShadows { get; } public LightProbeUsage LightProbeUsage { get; } public int DrawCallCount => _matrixChunks.Length; public long EstimatedMemoryBytes { get { long num = 0L; Matrix4x4[][] matrixChunks = _matrixChunks; foreach (Matrix4x4[] array in matrixChunks) { if (array != null) { num += (long)array.Length * 4L * 16; } } return num; } } public InstancedClusterBatch(Mesh mesh, int subMeshIndex, Material sourceMaterial, Material instancedMaterial, int layer, ShadowCastingMode shadowCastingMode, bool receiveShadows, LightProbeUsage lightProbeUsage, List<Matrix4x4> matrices) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) Mesh = mesh; SubMeshIndex = subMeshIndex; SourceMaterial = sourceMaterial; InstancedMaterial = instancedMaterial; Layer = layer; ShadowCastingMode = shadowCastingMode; ReceiveShadows = receiveShadows; LightProbeUsage = lightProbeUsage; int num = Mathf.CeilToInt((float)matrices.Count / 1023f); _matrixChunks = new Matrix4x4[num][]; for (int i = 0; i < num; i++) { int num2 = i * 1023; int num3 = Mathf.Min(1023, matrices.Count - num2); Matrix4x4[] array = (Matrix4x4[])(object)new Matrix4x4[num3]; for (int j = 0; j < num3; j++) { array[j] = matrices[num2 + j]; } _matrixChunks[i] = array; } } public bool Draw() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Mesh) || !Object.op_Implicit((Object)(object)InstancedMaterial) || _matrixChunks.Length == 0) { return false; } try { Matrix4x4[][] matrixChunks = _matrixChunks; foreach (Matrix4x4[] array in matrixChunks) { Graphics.DrawMeshInstanced(Mesh, SubMeshIndex, InstancedMaterial, array, array.Length, (MaterialPropertyBlock)null, ShadowCastingMode, ReceiveShadows, Layer, (Camera)null, LightProbeUsage, (LightProbeProxyVolume)null); } return true; } catch (Exception ex) { string[] obj = new string[6] { "[ValheimScalability] GPU instancing failed for mesh '", ((Object)Mesh).name, "', material '", null, null, null }; Material sourceMaterial = SourceMaterial; obj[3] = ((sourceMaterial != null) ? ((Object)sourceMaterial).name : null); obj[4] = "'. Falling back to original renderers. "; obj[5] = ex.Message; Debug.LogWarning((object)string.Concat(obj)); return false; } } } public static class InstancedMaterialCache { private static readonly Dictionary<int, Material> Cache = new Dictionary<int, Material>(); private static readonly HashSet<int> Unsupported = new HashSet<int>(); public static Material GetOrCreate(Material source) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)source) || !SystemInfo.supportsInstancing) { return null; } int instanceID = ((Object)source).GetInstanceID(); if (Unsupported.Contains(instanceID)) { return null; } if (Cache.TryGetValue(instanceID, out Material value)) { return value; } Material val = null; try { val = new Material(source) { name = ((Object)source).name + "_ValheimScalability_Instanced", hideFlags = (HideFlags)52 }; val.enableInstancing = true; if (!val.enableInstancing) { Object.Destroy((Object)(object)val); Unsupported.Add(instanceID); return null; } Cache[instanceID] = val; return val; } catch { if (Object.op_Implicit((Object)(object)val)) { Object.Destroy((Object)(object)val); } Unsupported.Add(instanceID); return null; } } public static void MarkUnsupported(Material source) { if (!Object.op_Implicit((Object)(object)source)) { return; } int instanceID = ((Object)source).GetInstanceID(); Unsupported.Add(instanceID); if (Cache.TryGetValue(instanceID, out Material value)) { if (Object.op_Implicit((Object)(object)value)) { Object.Destroy((Object)(object)value); } Cache.Remove(instanceID); } } public static void Clear() { foreach (Material value in Cache.Values) { if (Object.op_Implicit((Object)(object)value)) { Object.Destroy((Object)(object)value); } } Cache.Clear(); Unsupported.Clear(); } } public readonly struct MaterialBatchIdentity : IEquatable<MaterialBatchIdentity> { private static readonly MethodInfo ComputeCrcMethod = typeof(Material).GetMethod("ComputeCRC", BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); public readonly int ShaderId; public readonly int MaterialContentId; public readonly int RenderQueue; public readonly bool UsesContentCrc; public MaterialBatchIdentity(int shaderId, int materialContentId, int renderQueue, bool usesContentCrc) { ShaderId = shaderId; MaterialContentId = materialContentId; RenderQueue = renderQueue; UsesContentCrc = usesContentCrc; } public static MaterialBatchIdentity From(Material material) { if (!Object.op_Implicit((Object)(object)material)) { return default(MaterialBatchIdentity); } int shaderId = (Object.op_Implicit((Object)(object)material.shader) ? ((Object)material.shader).GetInstanceID() : 0); if (TryComputeContentCrc(material, out var crc)) { return new MaterialBatchIdentity(shaderId, crc, material.renderQueue, usesContentCrc: true); } return new MaterialBatchIdentity(shaderId, ((Object)material).GetInstanceID(), material.renderQueue, usesContentCrc: false); } private static bool TryComputeContentCrc(Material material, out int crc) { crc = 0; if (ComputeCrcMethod == null) { return false; } try { object obj = ComputeCrcMethod.Invoke(material, null); if (obj == null) { return false; } crc = (int)Convert.ToUInt32(obj); return true; } catch { return false; } } public bool Equals(MaterialBatchIdentity other) { if (ShaderId == other.ShaderId && MaterialContentId == other.MaterialContentId) { return RenderQueue == other.RenderQueue; } return false; } public override bool Equals(object obj) { if (obj is MaterialBatchIdentity other) { return Equals(other); } return false; } public override int GetHashCode() { return (((ShaderId * 397) ^ MaterialContentId) * 397) ^ RenderQueue; } public override string ToString() { return $"{ShaderId:X8}:{MaterialContentId:X8}:Q{RenderQueue}"; } } public sealed class PlayerClusterProximityTracker : MonoBehaviour { private Player _player; private Coroutine _coroutine; private void Awake() { _player = ((Component)this).GetComponent<Player>(); } private void OnEnable() { if (_coroutine == null) { _coroutine = ((MonoBehaviour)this).StartCoroutine(ProximityCoroutine()); } } private IEnumerator ProximityCoroutine() { while (Object.op_Implicit((Object)(object)this) && Object.op_Implicit((Object)(object)_player) && (Object)(object)Player.m_localPlayer != (Object)(object)_player) { yield return null; } while (Object.op_Implicit((Object)(object)this) && Object.op_Implicit((Object)(object)_player)) { if ((Object)(object)Player.m_localPlayer == (Object)(object)_player && !Application.isBatchMode && ValheimScalabilityConfig.Mode == ClusterPresentationMode.Adaptive) { SectorMeshClusterManager.EnsureAttached()?.UpdateLocalPlayerProximity(((Component)_player).transform.position, Camera.main); } yield return (object)new WaitForSecondsRealtime(Mathf.Max(0.05f, ValheimScalabilityConfig.ProximityPollInterval)); } } private void OnDisable() { if (_coroutine != null) { ((MonoBehaviour)this).StopCoroutine(_coroutine); _coroutine = null; } } private void OnDestroy() { if ((Object)(object)Player.m_localPlayer == (Object)(object)_player) { SectorMeshClusterManager.Instance?.ClearLocalPlayerProximity(); } } } public sealed class SectorMeshClusterController : MonoBehaviour { private enum OptimizedPresentation { Uninitialized = -1, None, All, PieceLayerOnly } private sealed class ClusterCellState { public readonly int Index; public readonly Bounds WorldBounds; public readonly HashSet<GameObject> RegisteredRoots = new HashSet<GameObject>(); public readonly HashSet<GameObject> DamagedRoots = new HashSet<GameObject>(); public readonly Dictionary<GameObject, List<MeshRenderer>> SourceRenderersByRoot = new Dictionary<GameObject, List<MeshRenderer>>(); public readonly Dictionary<GameObject, List<MeshRenderer>> CurrentlyHiddenRenderersByRoot = new Dictionary<GameObject, List<MeshRenderer>>(); public readonly List<GeneratedRenderer> GeneratedRenderers = new List<GeneratedRenderer>(); public readonly List<Mesh> GeneratedMeshes = new List<Mesh>(); public readonly List<GameObject> GeneratedObjects = new List<GameObject>(); public readonly List<InstancedClusterBatch> InstancedBatches = new List<InstancedClusterBatch>(); public long EstimatedGeneratedMemoryBytes; public bool ClusterBuilt; public bool Dirty = true; public bool ContainsStaleGeometry; public bool NearLocalPlayer; public bool VisibleToLocalPlayer; public float NextBuildTime; public float SuspendedUntil; public OptimizedPresentation InstancedPresentation; public OptimizedPresentation CurrentPresentation = OptimizedPresentation.Uninitialized; public ClusterCellState(int index, Bounds worldBounds, float nextBuildTime) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) Index = index; WorldBounds = worldBounds; NextBuildTime = nextBuildTime; } } private readonly struct GeneratedRenderer { public readonly MeshRenderer Renderer; public readonly int Layer; public GeneratedRenderer(MeshRenderer renderer, int layer) { Renderer = renderer; Layer = layer; } } private sealed class CombinedBucket { public readonly Material Material; public readonly List<CombineInstance> Instances = new List<CombineInstance>(); public CombinedBucket(Material material) { Material = material; } } private sealed class InstancedBucket { public readonly List<Matrix4x4> Matrices = new List<Matrix4x4>(); } private readonly struct CombinedBucketKey : IEquatable<CombinedBucketKey> { public readonly MaterialBatchIdentity MaterialIdentity; public readonly int Layer; public readonly int LightmapIndex; public readonly ShadowCastingMode ShadowCastingMode; public readonly bool ReceiveShadows; public readonly LightProbeUsage LightProbeUsage; public readonly ReflectionProbeUsage ReflectionProbeUsage; public readonly uint RenderingLayerMask; public readonly int SortingLayerId; public readonly int SortingOrder; public CombinedBucketKey(Material material, int layer, int lightmapIndex, ShadowCastingMode shadowCastingMode, bool receiveShadows, LightProbeUsage lightProbeUsage, ReflectionProbeUsage reflectionProbeUsage, uint renderingLayerMask, int sortingLayerId, int sortingOrder) { //IL_001b: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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) MaterialIdentity = MaterialBatchIdentity.From(material); Layer = layer; LightmapIndex = lightmapIndex; ShadowCastingMode = shadowCastingMode; ReceiveShadows = receiveShadows; LightProbeUsage = lightProbeUsage; ReflectionProbeUsage = reflectionProbeUsage; RenderingLayerMask = renderingLayerMask; SortingLayerId = sortingLayerId; SortingOrder = sortingOrder; } public bool Equals(CombinedBucketKey other) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (MaterialIdentity.Equals(other.MaterialIdentity) && Layer == other.Layer && LightmapIndex == other.LightmapIndex && ShadowCastingMode == other.ShadowCastingMode && ReceiveShadows == other.ReceiveShadows && LightProbeUsage == other.LightProbeUsage && ReflectionProbeUsage == other.ReflectionProbeUsage && RenderingLayerMask == other.RenderingLayerMask && SortingLayerId == other.SortingLayerId) { return SortingOrder == other.SortingOrder; } return false; } public override bool Equals(object obj) { if (obj is CombinedBucketKey other) { return Equals(other); } return false; } public override int GetHashCode() { //IL_0032: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_008c: Expected I4, but got Unknown return (int)((((((((((((((((((MaterialIdentity.GetHashCode() * 397) ^ Layer) * 397) ^ LightmapIndex) * 397) ^ ShadowCastingMode) * 397) ^ ReceiveShadows.GetHashCode()) * 397) ^ LightProbeUsage) * 397) ^ ReflectionProbeUsage) * 397) ^ RenderingLayerMask) * 397) ^ SortingLayerId) * 397) ^ SortingOrder); } } private readonly struct InstancedBucketKey : IEquatable<InstancedBucketKey> { public readonly Mesh Mesh; public readonly int SubMeshIndex; public readonly Material SourceMaterial; public readonly Material InstancedMaterial; public readonly int Layer; public readonly ShadowCastingMode ShadowCastingMode; public readonly bool ReceiveShadows; public readonly LightProbeUsage LightProbeUsage; public InstancedBucketKey(Mesh mesh, int subMeshIndex, Material sourceMaterial, Material instancedMaterial, int layer, ShadowCastingMode shadowCastingMode, bool receiveShadows, LightProbeUsage lightProbeUsage) { //IL_0026: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) Mesh = mesh; SubMeshIndex = subMeshIndex; SourceMaterial = sourceMaterial; InstancedMaterial = instancedMaterial; Layer = layer; ShadowCastingMode = shadowCastingMode; ReceiveShadows = receiveShadows; LightProbeUsage = lightProbeUsage; } public bool Equals(InstancedBucketKey other) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Mesh == (Object)(object)other.Mesh && SubMeshIndex == other.SubMeshIndex && (Object)(object)SourceMaterial == (Object)(object)other.SourceMaterial && Layer == other.Layer && ShadowCastingMode == other.ShadowCastingMode && ReceiveShadows == other.ReceiveShadows) { return LightProbeUsage == other.LightProbeUsage; } return false; } public override bool Equals(object obj) { if (obj is InstancedBucketKey other) { return Equals(other); } return false; } public override int GetHashCode() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected I4, but got Unknown return ((((((((((((Object.op_Implicit((Object)(object)Mesh) ? ((Object)Mesh).GetInstanceID() : 0) * 397) ^ SubMeshIndex) * 397) ^ (Object.op_Implicit((Object)(object)SourceMaterial) ? ((Object)SourceMaterial).GetInstanceID() : 0)) * 397) ^ Layer) * 397) ^ ShadowCastingMode) * 397) ^ ReceiveShadows.GetHashCode()) * 397) ^ LightProbeUsage; } } private readonly Dictionary<GameObject, int> _rootToCell = new Dictionary<GameObject, int>(); private readonly Dictionary<int, ClusterCellState> _cells = new Dictionary<int, ClusterCellState>(); private readonly HashSet<GameObject> _hierarchyCandidateBuffer = new HashSet<GameObject>(); private readonly List<GameObject> _deadRootBuffer = new List<GameObject>(); private Vector2s _sector; private bool _initialized; private int _cellDivisions; private float _zoneSize; private float _cellSize; private float _nextDestroyedRootCleanupTime; private bool _isWarmCached; public Vector2s Sector => _sector; public bool HasRegisteredObjects => _rootToCell.Count > 0; public bool IsWarmCached => _isWarmCached; public long EstimatedGeneratedMemoryBytes { get { long num = 0L; foreach (ClusterCellState value in _cells.Values) { num += value.EstimatedGeneratedMemoryBytes; } return num; } } public void Initialize(Vector2s sector) { //IL_0011: 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_001d: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (!_initialized) { _initialized = true; _sector = sector; ((Component)this).transform.SetPositionAndRotation(ZoneSystem.GetZonePos(sector), Quaternion.identity); ((Component)this).transform.localScale = Vector3.one; RefreshCellDimensions(); } } public bool Register(GameObject root) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)root) || !_initialized || _rootToCell.ContainsKey(root) || !CanRegisterRoot(root)) { return false; } int cellIndex = GetCellIndex(root.transform.position); ClusterCellState orCreateCell = GetOrCreateCell(cellIndex); orCreateCell.RegisteredRoots.Add(root); orCreateCell.Dirty = true; orCreateCell.NextBuildTime = Mathf.Max(orCreateCell.NextBuildTime, Time.unscaledTime + ValheimScalabilityConfig.RegistrationSettleDelay); _rootToCell.Add(root, cellIndex); return true; } public void RegisterHierarchy(GameObject hierarchyRoot) { if (!Object.op_Implicit((Object)(object)hierarchyRoot)) { return; } _hierarchyCandidateBuffer.Clear(); MeshRenderer[] componentsInChildren = hierarchyRoot.GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val) && !Object.op_Implicit((Object)(object)((Component)val).GetComponentInParent<ZNetView>())) { Transform val2 = FindTopLevelChild(hierarchyRoot.transform, ((Component)val).transform); if (Object.op_Implicit((Object)(object)val2)) { _hierarchyCandidateBuffer.Add(((Component)val2).gameObject); } } } foreach (GameObject item in _hierarchyCandidateBuffer) { Register(item); } _hierarchyCandidateBuffer.Clear(); } public void Unregister(GameObject root) { if (Object.op_Implicit((Object)(object)root) && _rootToCell.TryGetValue(root, out var value) && _cells.TryGetValue(value, out ClusterCellState value2)) { _rootToCell.Remove(root); value2.RegisteredRoots.Remove(root); value2.DamagedRoots.Remove(root); value2.SourceRenderersByRoot.Remove(root); if (value2.CurrentlyHiddenRenderersByRoot.TryGetValue(root, out List<MeshRenderer> value3)) { RestoreRendererList(value3); value2.CurrentlyHiddenRenderersByRoot.Remove(root); } InvalidateCellForRemovedGeometry(value2); } } public bool NotifyDamage(GameObject damagedObject) { if (!Object.op_Implicit((Object)(object)damagedObject)) { return false; } GameObject val = FindRegisteredRoot(damagedObject.transform); if (!Object.op_Implicit((Object)(object)val) || !_rootToCell.TryGetValue(val, out var value) || !_cells.TryGetValue(value, out ClusterCellState value2)) { return false; } value2.DamagedRoots.Add(val); value2.Dirty = true; value2.ContainsStaleGeometry = value2.ClusterBuilt; value2.SuspendedUntil = Mathf.Max(value2.SuspendedUntil, Time.unscaledTime + ValheimScalabilityConfig.DamageCooldown); TransitionPresentation(value2, OptimizedPresentation.None); if (_isWarmCached) { DestroyOptimizedRepresentations(value2); value2.ClusterBuilt = false; } return true; } public void UpdateLocalPlayerProximity(Vector3 playerPosition, Camera camera) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) if (_isWarmCached) { return; } ClusterPresentationMode mode = ValheimScalabilityConfig.Mode; Plane[] array = null; if (mode == ClusterPresentationMode.Adaptive && ValheimScalabilityConfig.OnlyUnclusterVisibleCells && Object.op_Implicit((Object)(object)camera)) { array = GeometryUtility.CalculateFrustumPlanes(camera); } foreach (ClusterCellState value in _cells.Values) { if (mode != ClusterPresentationMode.Adaptive) { value.NearLocalPlayer = false; value.VisibleToLocalPlayer = false; ApplyPresentation(value); continue; } value.NearLocalPlayer = GetCardinalDistanceToBounds(playerPosition, value.WorldBounds) <= ValheimScalabilityConfig.UnclusterRadius; if (!value.NearLocalPlayer) { value.VisibleToLocalPlayer = false; } else if (!ValheimScalabilityConfig.OnlyUnclusterVisibleCells || !Object.op_Implicit((Object)(object)camera) || array == null) { value.VisibleToLocalPlayer = true; } else { value.VisibleToLocalPlayer = GeometryUtility.TestPlanesAABB(array, value.WorldBounds); } ApplyPresentation(value); } } public void ClearLocalPlayerProximity() { foreach (ClusterCellState value in _cells.Values) { value.NearLocalPlayer = false; value.VisibleToLocalPlayer = false; ApplyPresentation(value); } } public void EnterWarmCache() { if (_isWarmCached) { return; } _isWarmCached = true; CleanupDestroyedRoots(); foreach (ClusterCellState value in _cells.Values) { if (value.CurrentPresentation != OptimizedPresentation.None) { TransitionPresentation(value, OptimizedPresentation.None); } if (value.ContainsStaleGeometry) { DestroyOptimizedRepresentations(value); value.ClusterBuilt = false; } value.NearLocalPlayer = false; value.VisibleToLocalPlayer = false; } } public void ExitWarmCache() { if (!_isWarmCached) { return; } _isWarmCached = false; foreach (ClusterCellState value in _cells.Values) { value.CurrentPresentation = OptimizedPresentation.Uninitialized; } } public void RebuildForConfigurationChange() { List<GameObject> list = new List<GameObject>(_rootToCell.Count); HashSet<GameObject> hashSet = new HashSet<GameObject>(); foreach (KeyValuePair<GameObject, int> item in _rootToCell) { if (Object.op_Implicit((Object)(object)item.Key)) { list.Add(item.Key); } } foreach (ClusterCellState value3 in _cells.Values) { foreach (GameObject damagedRoot in value3.DamagedRoots) { if (Object.op_Implicit((Object)(object)damagedRoot)) { hashSet.Add(damagedRoot); } } RestoreOriginalRenderers(value3); value3.CurrentPresentation = OptimizedPresentation.Uninitialized; DestroyOptimizedRepresentations(value3); } _rootToCell.Clear(); _cells.Clear(); RefreshCellDimensions(); foreach (GameObject item2 in list) { Register(item2); if (hashSet.Contains(item2) && _rootToCell.TryGetValue(item2, out var value) && _cells.TryGetValue(value, out ClusterCellState value2)) { value2.DamagedRoots.Add(item2); } } } public void Tick() { if (!_initialized || _isWarmCached) { return; } if (Time.unscaledTime >= _nextDestroyedRootCleanupTime) { _nextDestroyedRootCleanupTime = Time.unscaledTime + 2f; CleanupDestroyedRoots(); } foreach (ClusterCellState value in _cells.Values) { if (ValheimScalabilityConfig.Mode == ClusterPresentationMode.Off) { if (value.CurrentPresentation != OptimizedPresentation.None) { TransitionPresentation(value, OptimizedPresentation.None); } } else if (value.RegisteredRoots.Count == 0) { RestoreOriginalRenderers(value); value.CurrentPresentation = OptimizedPresentation.Uninitialized; DestroyOptimizedRepresentations(value); value.ClusterBuilt = false; value.Dirty = true; value.ContainsStaleGeometry = false; } else { if (CanBuildCell(value)) { BuildCluster(value); } ApplyPresentation(value); } } } private void LateUpdate() { if (_isWarmCached || ValheimScalabilityConfig.Mode == ClusterPresentationMode.Off || !ValheimScalabilityConfig.IsGpuInstancingEnabled) { return; } foreach (ClusterCellState value in _cells.Values) { if (value.InstancedPresentation == OptimizedPresentation.None) { continue; } foreach (InstancedClusterBatch instancedBatch in value.InstancedBatches) { if ((value.InstancedPresentation != OptimizedPresentation.PieceLayerOnly || instancedBatch.Layer == SectorMeshClusterSettings.PieceLayer) && !instancedBatch.Draw()) { HandleInstancingFailure(value, instancedBatch.SourceMaterial); break; } } } } private bool CanBuildCell(ClusterCellState cell) { if (!cell.Dirty || Time.unscaledTime < cell.NextBuildTime || Time.unscaledTime < cell.SuspendedUntil) { return false; } if (ValheimScalabilityConfig.Mode == ClusterPresentationMode.Off) { return false; } if (ValheimScalabilityConfig.Mode == ClusterPresentationMode.Adaptive && cell.NearLocalPlayer && cell.VisibleToLocalPlayer) { return false; } return true; } private bool ShouldForceOriginals(ClusterCellState cell) { if (ValheimScalabilityConfig.Mode == ClusterPresentationMode.Off) { return true; } if (Time.unscaledTime < cell.SuspendedUntil) { return true; } if (cell.Dirty) { return cell.ContainsStaleGeometry; } return false; } private void ApplyPresentation(ClusterCellState cell) { OptimizedPresentation optimizedPresentation = DeterminePresentation(cell); if (cell.CurrentPresentation != optimizedPresentation) { TransitionPresentation(cell, optimizedPresentation); } } private OptimizedPresentation DeterminePresentation(ClusterCellState cell) { if (ValheimScalabilityConfig.Mode == ClusterPresentationMode.Off || !cell.ClusterBuilt || ShouldForceOriginals(cell)) { return OptimizedPresentation.None; } if (ValheimScalabilityConfig.Mode != ClusterPresentationMode.Adaptive || !cell.NearLocalPlayer || !cell.VisibleToLocalPlayer) { return OptimizedPresentation.All; } if (!ValheimScalabilityConfig.KeepPieceLayerClusteredNearPlayer) { return OptimizedPresentation.None; } return OptimizedPresentation.PieceLayerOnly; } private void TransitionPresentation(ClusterCellState cell, OptimizedPresentation desired) { if (cell.CurrentPresentation != OptimizedPresentation.None) { RestoreOriginalRenderers(cell); } SetOptimizedPresentation(cell, desired); switch (desired) { case OptimizedPresentation.All: HideSourceRenderers(cell, null); break; case OptimizedPresentation.PieceLayerOnly: HideSourceRenderers(cell, SectorMeshClusterSettings.PieceLayer); break; default: RestoreOriginalRenderers(cell); break; } cell.CurrentPresentation = desired; if (ValheimScalabilityConfig.IsBatchDiagnosticsEnabled) { Debug.Log((object)$"[ValheimScalability] Presentation sector={_sector.x},{_sector.y} cell={cell.Index} -> {desired}; roots={cell.RegisteredRoots.Count}; optimizedSources={cell.SourceRenderersByRoot.Count}; hiddenRenderers={CountHiddenRenderers(cell)}; generatedRenderers={cell.GeneratedRenderers.Count}; instancedBatches={cell.InstancedBatches.Count}"); } } private static int CountHiddenRenderers(ClusterCellState cell) { int num = 0; foreach (List<MeshRenderer> value in cell.CurrentlyHiddenRenderersByRoot.Values) { num += value.Count; } return num; } private void BuildCluster(ClusterCellState cell) { RestoreOriginalRenderers(cell); SetOptimizedPresentation(cell, OptimizedPresentation.None); cell.CurrentPresentation = OptimizedPresentation.Uninitialized; DestroyOptimizedRepresentations(cell); cell.SourceRenderersByRoot.Clear(); Dictionary<CombinedBucketKey, CombinedBucket> dictionary = new Dictionary<CombinedBucketKey, CombinedBucket>(); Dictionary<InstancedBucketKey, InstancedBucket> dictionary2 = new Dictionary<InstancedBucketKey, InstancedBucket>(); int num = 0; foreach (GameObject registeredRoot in cell.RegisteredRoots) { if (Object.op_Implicit((Object)(object)registeredRoot) && !cell.DamagedRoots.Contains(registeredRoot) && CanRegisterRoot(registeredRoot)) { num += CollectRootGeometry(registeredRoot, cell, dictionary, dictionary2); } } int num2 = CountCombinedDrawCalls(dictionary) + CountInstancedDrawCalls(dictionary2); if (num - num2 < ValheimScalabilityConfig.MinimumEstimatedDrawCallSavings) { cell.SourceRenderersByRoot.Clear(); cell.ClusterBuilt = false; cell.Dirty = false; cell.ContainsStaleGeometry = false; } else { BuildCombinedMeshes(cell, dictionary); BuildInstancedBatches(cell, dictionary2); cell.ClusterBuilt = cell.GeneratedRenderers.Count > 0 || cell.InstancedBatches.Count > 0; UpdateEstimatedGeneratedMemory(cell); cell.Dirty = false; cell.ContainsStaleGeometry = false; } } private int CollectRootGeometry(GameObject root, ClusterCellState cell, Dictionary<CombinedBucketKey, CombinedBucket> combinedBuckets, Dictionary<InstancedBucketKey, InstancedBucket> instancedBuckets) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_014e: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) int num = 0; HashSet<MeshRenderer> hashSet = new HashSet<MeshRenderer>(); ZNetView component = root.GetComponent<ZNetView>(); MeshRenderer[] componentsInChildren = root.GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val in componentsInChildren) { if (!TryGetRendererStrategy(root, component, val, out ClusterRenderStrategy strategy, out LODGroup selectedLodGroup, out Mesh mesh, out Material[] materials, out Material[] instancedMaterials)) { continue; } bool flag = false; switch (strategy) { case ClusterRenderStrategy.CombinedMesh: { Matrix4x4 transform = ((Component)this).transform.worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix; for (int k = 0; k < mesh.subMeshCount; k++) { Material material = materials[k]; CombinedBucketKey key2 = new CombinedBucketKey(material, ((Component)val).gameObject.layer, ((Renderer)val).lightmapIndex, ((Renderer)val).shadowCastingMode, ((Renderer)val).receiveShadows, ((Renderer)val).lightProbeUsage, ((Renderer)val).reflectionProbeUsage, ((Renderer)val).renderingLayerMask, ((Renderer)val).sortingLayerID, ((Renderer)val).sortingOrder); if (!combinedBuckets.TryGetValue(key2, out CombinedBucket value2)) { value2 = new CombinedBucket(material); combinedBuckets.Add(key2, value2); } List<CombineInstance> instances = value2.Instances; CombineInstance item = default(CombineInstance); ((CombineInstance)(ref item)).mesh = mesh; ((CombineInstance)(ref item)).subMeshIndex = k; ((CombineInstance)(ref item)).transform = transform; ((CombineInstance)(ref item)).lightmapScaleOffset = ((Renderer)val).lightmapScaleOffset; instances.Add(item); } flag = true; break; } case ClusterRenderStrategy.Instanced: { Matrix4x4 localToWorldMatrix = ((Component)val).transform.localToWorldMatrix; for (int j = 0; j < mesh.subMeshCount; j++) { Material sourceMaterial = materials[j]; Material instancedMaterial = instancedMaterials[j]; InstancedBucketKey key = new InstancedBucketKey(mesh, j, sourceMaterial, instancedMaterial, ((Component)val).gameObject.layer, ((Renderer)val).shadowCastingMode, ((Renderer)val).receiveShadows, ((Renderer)val).lightProbeUsage); if (!instancedBuckets.TryGetValue(key, out InstancedBucket value)) { value = new InstancedBucket(); instancedBuckets.Add(key, value); } value.Matrices.Add(localToWorldMatrix); } flag = true; break; } } if (flag) { num += mesh.subMeshCount; hashSet.Add(val); if (Object.op_Implicit((Object)(object)selectedLodGroup)) { AddAllLodRenderers(selectedLodGroup, hashSet); } } } if (hashSet.Count == 0) { return 0; } List<MeshRenderer> list = new List<MeshRenderer>(hashSet.Count); foreach (MeshRenderer item2 in hashSet) { if (Object.op_Implicit((Object)(object)item2)) { list.Add(item2); } } if (list.Count > 0) { cell.SourceRenderersByRoot[root] = list; } return num; } private bool TryGetRendererStrategy(GameObject root, ZNetView rootNetView, MeshRenderer renderer, out ClusterRenderStrategy strategy, out LODGroup selectedLodGroup, out Mesh mesh, out Material[] materials, out Material[] instancedMaterials) { //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Invalid comparison between Unknown and I4 strategy = ClusterRenderStrategy.Original; selectedLodGroup = null; mesh = null; materials = null; instancedMaterials = null; if (!Object.op_Implicit((Object)(object)renderer) || !((Renderer)renderer).enabled || !((Component)renderer).gameObject.activeInHierarchy || ((Renderer)renderer).forceRenderingOff) { return false; } if (DynamicHierarchyBatchExclusion.ShouldExcludeRenderer(renderer) || HasUnsafeDynamicRendering(((Component)renderer).gameObject)) { return false; } if (!ClusterBatchFilter.IsLayerAllowed(((Component)renderer).gameObject.layer)) { return false; } if (!ClusterBatchFilter.IsObjectAllowed(((Object)root).name, ((Object)((Component)renderer).gameObject).name)) { return false; } if (ValheimScalabilityConfig.SkipPropertyBlockRenderers && ((Renderer)renderer).HasPropertyBlock()) { return false; } if (HasAnimatorBetween(((Component)renderer).transform, root.transform)) { return false; } ZNetView componentInParent = ((Component)renderer).GetComponentInParent<ZNetView>(); if (Object.op_Implicit((Object)(object)rootNetView)) { if (Object.op_Implicit((Object)(object)componentInParent) && (Object)(object)componentInParent != (Object)(object)rootNetView) { return false; } } else if (Object.op_Implicit((Object)(object)componentInParent)) { return false; } if (!IsSelectedLodRenderer(renderer, root.transform, out selectedLodGroup)) { return false; } MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.sharedMesh)) { return false; } mesh = component.sharedMesh; materials = ((Renderer)renderer).sharedMaterials; if (mesh.subMeshCount <= 0 || materials.Length < mesh.subMeshCount) { return false; } for (int i = 0; i < mesh.subMeshCount; i++) { Material val = materials[i]; if (!Object.op_Implicit((Object)(object)val) || !ClusterBatchFilter.IsMaterialAllowed(val) || !ClusterBatchFilter.IsShaderAllowed(val.shader)) { return false; } } if (ClusterBatchFilter.IsInstancingCandidate(((Object)root).name, ((Object)((Component)renderer).gameObject).name, materials)) { if (!ValheimScalabilityConfig.IsGpuInstancingEnabled || !SystemInfo.supportsInstancing || IsLightmapped(renderer) || (int)((Renderer)renderer).lightProbeUsage == 2 || ((Renderer)renderer).sortingLayerID != 0 || ((Renderer)renderer).sortingOrder != 0) { return false; } instancedMaterials = (Material[])(object)new Material[mesh.subMeshCount]; for (int j = 0; j < mesh.subMeshCount; j++) { Material orCreate = InstancedMaterialCache.GetOrCreate(materials[j]); if (!Object.op_Implicit((Object)(object)orCreate)) { return false; } instancedMaterials[j] = orCreate; } strategy = ClusterRenderStrategy.Instanced; return true; } if (!mesh.isReadable) { return false; } strategy = ClusterRenderStrategy.CombinedMesh; return true; } private static bool IsLightmapped(MeshRenderer renderer) { if (((Renderer)renderer).lightmapIndex >= 0) { return ((Renderer)renderer).lightmapIndex < 65534; } return false; } private static int CountCombinedDrawCalls(Dictionary<CombinedBucketKey, CombinedBucket> buckets) { int num = 0; foreach (KeyValuePair<CombinedBucketKey, CombinedBucket> bucket in buckets) { if (Object.op_Implicit((Object)(object)bucket.Value.Material) && bucket.Value.Instances.Count > 0) { num++; } } return num; } private static int CountInstancedDrawCalls(Dictionary<InstancedBucketKey, InstancedBucket> buckets) { int num = 0; foreach (InstancedBucket value in buckets.Values) { if (value.Matrices.Count != 0) { num += Mathf.CeilToInt((float)value.Matrices.Count / 1023f); } } return num; } private void BuildCombinedMeshes(ClusterCellState cell, Dictionary<CombinedBucketKey, CombinedBucket> buckets) { //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Expected O, but got Unknown //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<CombinedBucketKey, CombinedBucket> bucket in buckets) { CombinedBucketKey key = bucket.Key; CombinedBucket value = bucket.Value; Material material = value.Material; if (Object.op_Implicit((Object)(object)material) && value.Instances.Count != 0) { if (ValheimScalabilityConfig.IsBatchDiagnosticsEnabled) { Debug.Log((object)$"[ValheimScalability] Combined batch sector={_sector.x},{_sector.y} cell={cell.Index} material='{((Object)material).name}' materialKey={key.MaterialIdentity} instances={value.Instances.Count} layer={key.Layer} lightmap={key.LightmapIndex} shadows={key.ShadowCastingMode} receiveShadows={key.ReceiveShadows} lightProbes={key.LightProbeUsage} reflectionProbes={key.ReflectionProbeUsage} renderingLayerMask={key.RenderingLayerMask} sortingLayer={key.SortingLayerId} sortingOrder={key.SortingOrder}"); } Mesh val = new Mesh(); ((Object)val).name = $"ValheimScalability_Sector_{_sector.x}_{_sector.y}_Cell_{cell.Index}_{((Object)material).name}"; val.indexFormat = (IndexFormat)1; Mesh val2 = val; bool flag = key.LightmapIndex >= 0 && key.LightmapIndex < 65534; val2.CombineMeshes(value.Instances.ToArray(), true, true, flag); val2.RecalculateBounds(); GameObject val3 = new GameObject($"Combined_{_sector.x}_{_sector.y}_Cell_{cell.Index}_{((Object)material).name}_x{value.Instances.Count}"); val3.layer = key.Layer; val3.transform.SetParent(((Component)this).transform, false); val3.transform.localPosition = Vector3.zero; val3.transform.localRotation = Quaternion.identity; val3.transform.localScale = Vector3.one; val3.AddComponent<MeshFilter>().sharedMesh = val2; MeshRenderer val4 = val3.AddComponent<MeshRenderer>(); ((Renderer)val4).sharedMaterial = material; ((Renderer)val4).shadowCastingMode = key.ShadowCastingMode; ((Renderer)val4).receiveShadows = key.ReceiveShadows; ((Renderer)val4).lightProbeUsage = key.LightProbeUsage; ((Renderer)val4).reflectionProbeUsage = key.ReflectionProbeUsage; ((Renderer)val4).renderingLayerMask = key.RenderingLayerMask; ((Renderer)val4).sortingLayerID = key.SortingLayerId; ((Renderer)val4).sortingOrder = key.SortingOrder; if (flag) { ((Renderer)val4).lightmapIndex = key.LightmapIndex; } ((Renderer)val4).enabled = false; cell.GeneratedMeshes.Add(val2); cell.GeneratedObjects.Add(val3); cell.GeneratedRenderers.Add(new GeneratedRenderer(val4, key.Layer)); } } } private static void BuildInstancedBatches(ClusterCellState cell, Dictionary<InstancedBucketKey, InstancedBucket> buckets) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<InstancedBucketKey, InstancedBucket> bucket in buckets) { InstancedBucketKey key = bucket.Key; InstancedBucket value = bucket.Value; if (Object.op_Implicit((Object)(object)key.Mesh) && Object.op_Implicit((Object)(object)key.SourceMaterial) && Object.op_Implicit((Object)(object)key.InstancedMaterial) && value.Matrices.Count != 0) { cell.InstancedBatches.Add(new InstancedClusterBatch(key.Mesh, key.SubMeshIndex, key.SourceMaterial, key.InstancedMaterial, key.Layer, key.ShadowCastingMode, key.ReceiveShadows, key.LightProbeUsage, value.Matrices)); } } } private void HandleInstancingFailure(ClusterCellState cell, Material sourceMaterial) { InstancedMaterialCache.MarkUnsupported(sourceMaterial); TransitionPresentation(cell, OptimizedPresentation.None); cell.Dirty = true; cell.ContainsStaleGeometry = true; cell.NextBuildTime = Time.unscaledTime + ValheimScalabilityConfig.RemovalRebuildDelay; } private bool CanRegisterRoot(GameObject root) { if (!Object.op_Implicit((Object)(object)root) || Object.op_Implicit((Object)(object)root.GetComponentInParent<Character>()) || DynamicHierarchyBatchExclusion.ShouldExclude(root) || HasUnsafeDynamicRendering(root)) { return false; } MeshRenderer[] componentsInChildren = root.GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)((Component)val).GetComponent<MeshFilter>())) { return true; } } return false; } private void InvalidateCellForRemovedGeometry(ClusterCellState cell) { cell.Dirty = true; cell.ContainsStaleGeometry = cell.ClusterBuilt; cell.NextBuildTime = Mathf.Max(cell.NextBuildTime, Time.unscaledTime + ValheimScalabilityConfig.RemovalRebuildDelay); if (cell.ContainsStaleGeometry) { TransitionPresentation(cell, OptimizedPresentation.None); if (_isWarmCached) { DestroyOptimizedRepresentations(cell); cell.ClusterBuilt = false; } } } private void RefreshCellDimensions() { _zoneSize = (Object.op_Implicit((Object)(object)ZoneSystem.instance) ? ZoneSystem.instance.m_zoneSize : 64f); _cellDivisions = ((ValheimScalabilityConfig.Mode == ClusterPresentationMode.FullCluster && ValheimScalabilityConfig.UseSingleCellInFullCluster) ? 1 : Mathf.Clamp(ValheimScalabilityConfig.CellDivisions, 1, 8)); _cellSize = _zoneSize / (float)_cellDivisions; } private ClusterCellState GetOrCreateCell(int cellIndex) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (_cells.TryGetValue(cellIndex, out ClusterCellState value)) { return value; } ClusterCellState clusterCellState = new ClusterCellState(cellIndex, GetCellBounds(cellIndex), Time.unscaledTime + ValheimScalabilityConfig.InitialBuildDelay); _cells.Add(cellIndex, clusterCellState); return clusterCellState; } private int GetCellIndex(Vector3 worldPosition) { //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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0045: Unknown result type (might be due to invalid IL or missing references) Vector3 zonePos = ZoneSystem.GetZonePos(_sector); float num = _zoneSize * 0.5f; float num2 = Mathf.Clamp(worldPosition.x - (zonePos.x - num), 0f, _zoneSize - 0.001f); float num3 = Mathf.Clamp(worldPosition.z - (zonePos.z - num), 0f, _zoneSize - 0.001f); int num4 = Mathf.Clamp(Mathf.FloorToInt(num2 / _cellSize), 0, _cellDivisions - 1); return Mathf.Clamp(Mathf.FloorToInt(num3 / _cellSize), 0, _cellDivisions - 1) * _cellDivisions + num4; } private Bounds GetCellBounds(int cellIndex) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) int num = cellIndex % _cellDivisions; int num2 = cellIndex / _cellDivisions; Vector3 zonePos = ZoneSystem.GetZonePos(_sector); float num3 = _zoneSize * 0.5f; float num4 = zonePos.x - num3 + (float)num * _cellSize; float num5 = zonePos.z - num3 + (float)num2 * _cellSize; return new Bounds(new Vector3(num4 + _cellSize * 0.5f, zonePos.y, num5 + _cellSize * 0.5f), new Vector3(_cellSize, ValheimScalabilityConfig.VisibilityHeight, _cellSize)); } private static float GetCardinalDistanceToBounds(Vector3 point, Bounds bounds) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) Vector3 min = ((Bounds)(ref bounds)).min; Vector3 max = ((Bounds)(ref bounds)).max; float num = ((point.x < min.x) ? (min.x - point.x) : ((point.x > max.x) ? (point.x - max.x) : 0f)); float num2 = ((point.z < min.z) ? (min.z - point.z) : ((point.z > max.z) ? (point.z - max.z) : 0f)); return num + num2; } private GameObject FindRegisteredRoot(Transform start) { Transform val = start; while (Object.op_Implicit((Object)(object)val)) { if (_rootToCell.ContainsKey(((Component)val).gameObject)) { return ((Component)val).gameObject; } val = val.parent; } return null; } private static Transform FindTopLevelChild(Transform hierarchyRoot, Transform item) { if (!Object.op_Implicit((Object)(object)hierarchyRoot) || !Object.op_Implicit((Object)(object)item)) { return null; } if ((Object)(object)item == (Object)(object)hierarchyRoot) { return item; } Transform val = item; while (Object.op_Implicit((Object)(object)val.parent) && (Object)(object)val.parent != (Object)(object)hierarchyRoot) { val = val.parent; } if (!((Object)(object)val.parent == (Object)(object)hierarchyRoot)) { return null; } return val; } private static bool IsSelectedLodRenderer(MeshRenderer renderer, Transform root, out LODGroup lodGroup) { lodGroup = FindNearestLodGroup(((Component)renderer).transform, root); if (!Object.op_Implicit((Object)(object)lodGroup)) { return true; } LOD[] lODs = lodGroup.GetLODs(); if (lODs.Length == 0) { return true; } int num = 0; if (ValheimScalabilityConfig.UseLowestLod) { for (int num2 = lODs.Length - 1; num2 >= 0; num2--) { if (lODs[num2].renderers != null && lODs[num2].renderers.Length != 0) { num = num2; break; } } } Renderer[] renderers = lODs[num].renderers; for (int i = 0; i < renderers.Length; i++) { if ((Object)(object)renderers[i] == (Object)(object)renderer) { return true; } } return false; } private static LODGroup FindNearestLodGroup(Transform start, Transform root) { Transform val = start; while (Object.op_Implicit((Object)(object)val)) { LODGroup component = ((Component)val).GetComponent<LODGroup>(); if (Object.op_Implicit((Object)(object)component)) { return component; } if ((Object)(object)val == (Object)(object)root) { break; } val = val.parent; } return null; } private static void AddAllLodRenderers(LODGroup lodGroup, HashSet<MeshRenderer> target) { //IL_000d: 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_0013: 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) LOD[] lODs = lodGroup.GetLODs(); foreach (LOD val in lODs) { if (val.renderers == null) { continue; } Renderer[] renderers = val.renderers; foreach (Renderer obj in renderers) { MeshRenderer val2 = (MeshRenderer)(object)((obj is MeshRenderer) ? obj : null); if (val2 != null && Object.op_Implicit((Object)(object)val2)) { target.Add(val2); } } } } private static bool HasUnsafeDynamicRendering(GameObject root) { if (!Object.op_Implicit((Object)(object)root)) { return true; } if (Object.op_Implicit((Object)(object)root.GetComponentInChildren<Cloth>(true))) { return true; } if (Object.op_Implicit((Object)(object)root.GetComponentInChildren<SkinnedMeshRenderer>(true))) { return true; } if (Object.op_Implicit((Object)(object)root.GetComponentInChildren<Animator>(true))) { return true; } if (Object.op_Implicit((Object)(object)root.GetComponentInChildren<Animation>(true))) { return true; } return false; } private static bool HasAnimatorBetween(Transform start, Transform root) { Transform val = start; while (Object.op_Implicit((Object)(object)val)) { if (Object.op_Implicit((Object)(object)((Component)val).GetComponent<Animator>())) { return true; } if ((Object)(object)val == (Object)(object)root) { break; } val = val.parent; } return false; } private static void HideSourceRenderers(ClusterCellState cell, int? onlyLayer) { foreach (KeyValuePair<GameObject, List<MeshRenderer>> item in cell.SourceRenderersByRoot) { GameObject key = item.Key; if (!Object.op_Implicit((Object)(object)key) || cell.DamagedRoots.Contains(key)) { continue; } if (!cell.CurrentlyHiddenRenderersByRoot.TryGetValue(key, out List<MeshRenderer> value)) { value = new List<MeshRenderer>(); cell.CurrentlyHiddenRenderersByRoot.Add(key, value); } foreach (MeshRenderer item2 in item.Value) { if (Object.op_Implicit((Object)(object)item2) && ((Renderer)item2).enabled && ((Component)item2).gameObject.activeInHierarchy && (!onlyLayer.HasValue || ((Component)item2).gameObject.layer == onlyLayer.Value)) { ((Renderer)item2).enabled = false; if (!value.Contains(item2)) { value.Add(item2); } } } } } private static void RestoreOriginalRenderers(ClusterCellState cell) { foreach (KeyValuePair<GameObject, List<MeshRenderer>> item in cell.CurrentlyHiddenRenderersByRoot) { RestoreRendererList(item.Value); } cell.CurrentlyHiddenRenderersByRoot.Clear(); } private static void RestoreRendererList(List<MeshRenderer> renderers) { foreach (MeshRenderer renderer in renderers) { if (Object.op_Implicit((Object)(object)renderer)) { ((Renderer)renderer).enabled = true; } } renderers.Clear(); } private static void SetOptimizedPresentation(ClusterCellState cell, OptimizedPresentation presentation) { cell.InstancedPresentation = presentation; foreach (GeneratedRenderer generatedRenderer in cell.GeneratedRenderers) { if (Object.op_Implicit((Object)(object)generatedRenderer.Renderer)) { ((Renderer)generatedRenderer.Renderer).enabled = presentation switch { OptimizedPresentation.PieceLayerOnly => generatedRenderer.Layer == SectorMeshClusterSettings.PieceLayer, OptimizedPresentation.All => true, _ => false, }; } } } private static void DestroyOptimizedRepresentations(ClusterCellState cell) { SetOptimizedPresentation(cell, OptimizedPresentation.None); foreach (GameObject generatedObject in cell.GeneratedObjects) { if (Object.op_Implicit((Object)(object)generatedObject)) { Object.Destroy((Object)(object)generatedObject); } } foreach (Mesh generatedMesh in cell.GeneratedMeshes) { if (Object.op_Implicit((Object)(object)generatedMesh)) { Object.Destroy((Object)(object)generatedMesh); } } cell.GeneratedObjects.Clear(); cell.GeneratedRenderers.Clear(); cell.GeneratedMeshes.Clear(); cell.InstancedBatches.Clear(); cell.EstimatedGeneratedMemoryBytes = 0L; } private static void UpdateEstimatedGeneratedMemory(ClusterCellState cell) { long num = 0L; foreach (Mesh generatedMesh in cell.GeneratedMeshes) { if (Object.op_Implicit((Object)(object)generatedMesh)) { try { num += Profiler.GetRuntimeMemorySizeLong((Object)(object)generatedMesh); } catch { num += (long)generatedMesh.vertexCount * 64L; } } } foreach (InstancedClusterBatch instancedBatch in cell.InstancedBatches) { if (instancedBatch != null) { num += instancedBatch.EstimatedMemoryBytes; } } num += (long)cell.GeneratedObjects.Count * 2048L; cell.EstimatedGeneratedMemoryBytes = num; } private void CleanupDestroyedRoots() { _deadRootBuffer.Clear(); foreach (KeyValuePair<GameObject, int> item in _rootToCell) { if (!Object.op_Implicit((Object)(object)item.Key)) { _deadRootBuffer.Add(item.Key); } } foreach (GameObject item2 in _deadRootBuffer) { if (_rootToCell.TryGetValue(item2, out var value)) { _rootToCell.Remove(item2); if (_cells.TryGetValue(value, out ClusterCellState value2)) { value2.RegisteredRoots.Remove(item2); value2.DamagedRoots.Remove(item2); value2.SourceRenderersByRoot.Remove(item2); value2.CurrentlyHiddenRenderersByRoot.Remove(item2); InvalidateCellForRemovedGeometry(value2); } } } _deadRootBuffer.Clear(); } private void OnDisable() { foreach (ClusterCellState value in _cells.Values) { SetOptimizedPresentation(value, OptimizedPresentation.None); RestoreOriginalRenderers(value); value.CurrentPresentation = OptimizedPresentation.Uninitialized; } } private void OnDestroy() { foreach (ClusterCellState value in _cells.Values) { RestoreOriginalRenderers(value); DestroyOptimizedRepresentations(value); } _rootToCell.Clear(); _cells.Clear(); } } public sealed class SectorMeshClusterManager : MonoBehaviour { private sealed class SectorCacheState { public bool IsActive; public int VisitCount; public float LastVisitCountTime; public float LastTouchTime; public float LastActiveTime; public float WarmSince; } private sealed class WarmCacheCandidate { public readonly Vector2s Sector; public readonly SectorMeshClusterController Controller; public readonly SectorCacheState State; public readonly long Bytes; public readonly bool IsFrequent; public bool Evicted; public WarmCacheCandidate(Vector2s sector, SectorMeshClusterController controller, SectorCacheState state, long bytes, bool isFrequent) { //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) Sector = sector; Controller = controller; State = state; Bytes = bytes; IsFrequent = isFrequent; } public static int CompareFrequentEvictionOrder(WarmCacheCandidate left, WarmCacheCandidate right) { if (left.IsFrequent != right.IsFrequent) { if (!left.IsFrequent) { return 1; } return -1; } int num = left.State.LastActiveTime.CompareTo(right.State.LastActiveTime); if (num != 0) { return num; } return right.Bytes.CompareTo(left.Bytes); } public static int CompareGlobalEvictionOrder(WarmCacheCandidate left, WarmCacheCandidate right) { if (left.IsFrequent != right.IsFrequent) { if (!left.IsFrequent) { return -1; } return 1; } int num = left.State.LastActiveTime.CompareTo(right.State.LastActiveTime); if (num != 0) { return num; } return right.Bytes.CompareTo(left.Bytes); } } private const float ActiveTouchGraceSeconds = 3f; private const float MinimumVisitCountIntervalSeconds = 30f; private const int MaxColdHistoryEntries = 4096; private readonly Dictionary<Vector2s, SectorMeshClusterController> _sectorControllers = new Dictionary<Vector2s, SectorMeshClusterController>(); private readonly Dictionary<Vector2s, SectorCacheState> _sectorCacheStates = new Dictionary<Vector2s, SectorCacheState>(); private readonly Dictionary<int, Vector2s> _networkObjectSectors = new Dictionary<int, Vector2s>(); private readonly List<Vector2s> _deadSectorBuffer = new List<Vector2s>(); private readonly List<int> _networkIdBuffer = new List<int>(); private readonly List<WarmCacheCandidate> _warmCandidateBuffer = new List<WarmCacheCandidate>(); private readonly List<Vector2s> _historyPruneBuffer = new List<Vector2s>(); private float _nextMaintenanceTime; public static SectorMeshClusterManager Instance { get; private set; } public static SectorMeshClusterManager EnsureAttached() { if (Object.op_Implicit((Object)(object)Instance)) { return Instance; } if (Application.isBatchMode || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { return null; } SectorMeshClusterManager component = ((Component)ZNetScene.instance).GetComponent<SectorMeshClusterManager>(); if (!Object.op_Implicit((Object)(object)component)) { return ((Component)ZNetScene.instance).gameObject.AddComponent<SectorMeshClusterManager>(); } return component; } private void Awake() { if (Object.op_Implicit((Object)(object)Instance) && (Object)(object)Instance != (Object)(object)this) { Object.Destroy((Object)(object)this); } else { Instance = this; } } public void RegisterNetworkObject(ZDO zdo, ZNetView nview) { //IL_0023: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (zdo != null && Object.op_Implicit((Object)(object)nview) && !Application.isBatchMode && !DynamicHierarchyBatchExclusion.ShouldExclude(zdo, ((Component)nview).gameObject)) { Vector2s sector = zdo.GetSector(); SectorMeshClusterController orCreateController = GetOrCreateController(sector); ActivateSector(sector, orCreateController, countVisit: true); if (orCreateController.Register(((Component)nview).gameObject)) { _networkObjectSectors[((Object)((Component)nview).gameObject).GetInstanceID()] = sector; } } } public void UnregisterNetworkObject(ZNetView nview) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)nview)) { return; } int instanceID = ((Object)((Component)nview).gameObject).GetInstanceID(); if (_networkObjectSectors.TryGetValue(instanceID, out var value)) { if (_sectorControllers.TryGetValue(value, out SectorMeshClusterController value2) && Object.op_Implicit((Object)(object)value2)) { value2.Unregister(((Component)nview).gameObject); } _networkObjectSectors.Remove(instanceID); return; } ZDO zDO = nview.GetZDO(); value = ((zDO != null) ? zDO.GetSector() : ZoneSystem.GetZone(((Component)nview).transform.position)); if (_sectorControllers.TryGetValue(value, out SectorMeshClusterController value3) && Object.op_Implicit((Object)(object)value3)) { value3.Unregister(((Component)nview).gameObject); } } public void RegisterZoneHierarchy(Vector2s sector, GameObject hierarchyRoot) { //IL_0011: 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_0029: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)hierarchyRoot) && !Application.isBatchMode) { SectorMeshClusterController orCreateController = GetOrCreateController(sector); ActivateSector(sector, orCreateController, countVisit: true); orCreateController.RegisterHierarchy(hierarchyRoot); RegisterExistingNetworkObjectsInSector(sector, orCreateController); } } public void RegisterLocationHierarchy(GameObject locationRoot) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_002a: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)locationRoot) && !Application.isBatchMode) { Vector2s zone = ZoneSystem.GetZone(locationRoot.transform.position); SectorMeshClusterController orCreateController = GetOrCreateController(zone); ActivateSector(zone, orCreateController, countVisit: true); orCreateController.RegisterHierarchy(locationRoot); } } public void NotifyDamage(GameObject damagedObject) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)damagedObject) && !Application.isBatchMode) { ZNetView componentInParent = damagedObject.GetComponentInParent<ZNetView>(); Vector2s value; Vector2s val = ((Object.op_Implicit((Object)(object)componentInParent) && _networkObjectSectors.TryGetValue(((Object)((Component)componentInParent).gameObject).GetInstanceID(), out value)) ? value : ((!Object.op_Implicit((Object)(object)componentInParent) || componentInParent.GetZDO() == null) ? ZoneSystem.GetZone(damagedObject.transform.position) : componentInParent.GetZDO().GetSector())); if (_sectorControllers.TryGetValue(val, out SectorMeshClusterController value2) && Object.op_Implicit((Object)(object)value2)) { ActivateSector(val, value2, countVisit: false); value2.NotifyDamage(damagedObject); } } } public void UpdateLocalPlayerProximity(Vector3 playerPosition, Camera camera) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (ValheimScalabilityConfig.Mode != ClusterPresentationMode.Adaptive) { return; } foreach (KeyValuePair<Vector2s, SectorMeshClusterController> sectorController in _sectorControllers) { SectorMeshClusterController value = sectorController.Value; if (Object.op_Implicit((Object)(object)value) && !value.IsWarmCached) { value.UpdateLocalPlayerProximity(playerPosition, camera); } } } public void ClearLocalPlayerProximity() { foreach (SectorMeshClusterController value in _sectorControllers.Values) { if (Object.op_Implicit((Object)(object)value) && !value.IsWarmCached) { value.ClearLocalPlayerProximity(); } } } public void RebuildAllForConfigurationChange() { ClusterBatchFilter.Invalidate(); SectorMeshClusterSettings.InvalidateLayerCache(); foreach (SectorMeshClusterController value in _sectorControllers.Values) { if (Object.op_Implicit((Object)(object)value)) { value.RebuildForConfigurationChange(); } } } private SectorMeshClusterController GetOrCreateController(Vector2s sector) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0051: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_007e: 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_0092: Unknown result type (might be due to invalid IL or missing references) if (_sectorControllers.TryGetValue(sector, out SectorMeshClusterController value) && Object.op_Implicit((Object)(object)value)) { return value; } GameObject val = new GameObject($"ValheimScalability_SectorMeshCluster_{sector.x}_{sector.y}"); val.transform.SetParent(((Component)this).transform, true); val.transform.SetPositionAndRotation(ZoneSystem.GetZonePos(sector), Quaternion.identity); val.transform.localScale = Vector3.one; SectorMeshClusterController sectorMeshClusterController = val.AddComponent<SectorMeshClusterController>(); sectorMeshClusterController.Initialize(sector); _sectorControllers[sector] = sectorMeshClusterController; SectorCacheState orCreateCacheState = GetOrCreateCacheState(sector); float num = (orCreateCacheState.LastActiveTime = (orCreateCacheState.LastTouchTime = Time.unscaledTime)); if (orCreateCacheState.VisitCount <= 0) { orCreateCacheState.VisitCount = 1; orCreateCacheState.LastVisitCountTime = num; } else if (!orCreateCacheState.IsActive && num - orCreateCacheState.LastVisitCountTime >= 30f) { orCreateCacheState.VisitCount++; orCreateCacheState.LastVisitCountTime = num; } orCreateCacheState.IsActive = true; return sectorMeshClusterController; } private SectorCacheState GetOrCreateCacheState(Vector2s sector) { //IL_0006: 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) if (_sectorCacheStates.TryGetValue(sector, out SectorCacheState value)) { return value; } SectorCacheState sectorCacheState = new SectorCacheState(); _sectorCacheStates.Add(sector, sectorCacheState); return sectorCacheState; } private void ActivateSector(Vector2s sector, SectorMeshClusterController controller, bool countVisit) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)controller)) { return; } SectorCacheState orCreateCacheState = GetOrCreateCacheState(sector); float num = (orCreateCacheState.LastActiveTime = (orCreateCacheState.LastTouchTime = Time.unscaledTime)); if (!orCreateCacheState.IsActive) { orCreateCacheState.IsActive = true; if (countVisit && num - orCreateCacheState.LastVisitCountTime >= 30f) { orCreateCacheState.VisitCount++; orCreateCacheState.LastVisitCountTime = num; } controller.ExitWarmCache(); if (ValheimScalabilityConfig.IsCacheDiagnosticsEnabled) { Debug.Log((object)$"[ValheimScalability] Warm-cache hit/reactivation sector={sector.x},{sector.y} visits={orCreateCacheState.VisitCount} retained={FormatMegabytes(controller.EstimatedGeneratedMemoryBytes)} MB"); } } else if (controller.IsWarmCached) { controller.ExitWarmCache(); } } private void RegisterExistingNetworkObjectsInSector(Vector2s sector, SectorMeshClusterController controller) { //IL_004b: 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) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)controller) || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { return; } foreach (KeyValuePair<ZDO, ZNetView> instance in ZNetScene.instance.m_instances) { ZDO key = instance.Key; ZNetView value = instance.Value; if (key != null && Object.op_Implicit((Object)(object)value) && !(key.GetSector() != sector) && controller.Register(((Component)value).gameObject)) { _networkObjectSectors[((Object)((Component)value).gameObject).GetInstanceID()] = sector; } } } private void Update() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: 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_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) if (Application.isBatchMode || Time.unscaledTime < _nextMaintenanceTime) { return; } float unscaledTime = Time.unscaledTime; _nextMaintenanceTime = unscaledTime + ValheimScalabilityConfig.MaintenanceInterval; _deadSectorBuffer.Clear(); foreach (KeyValuePair<Vector2s, SectorMeshClusterController> sectorController in _sectorControllers) { Vector2s key = sectorController.Key; SectorMeshClusterController value = sectorController.Value; if (!Object.op_Implicit((Object)(object)value)) { _deadSectorBuffer.Add(key); continue; } SectorCacheState orCreateCacheState = GetOrCreateCacheState(key); bool flag = Object.op_Implicit((Object)(object)ZoneSystem.instance) && ZoneSystem.instance.m_zones.ContainsKey(key); bool flag2 = unscaledTime - orCreateCacheState.LastTouchTime <= 3f; if (flag || flag2) { if (!orCreateCacheState.IsActive || value.IsWarmCached) { ActivateSector(key, value, flag); } orCreateCacheState.LastActiveTime = unscaledTime; value.Tick(); } else if (orCreateCacheState.IsActive) { orCreateCacheState.IsActive = false; orCreateCacheState.WarmSince = unscaledTime; value.EnterWarmCache(); if (ValheimScalabilityConfig.IsCacheDiagnosticsEnabled) { Debug.Log((object)$"[ValheimScalability] Sector entered warm cache sector={key.x},{key.y} visits={orCreateCacheState.VisitCount} retained={FormatMegabytes(value.EstimatedGeneratedMemoryBytes)} MB"); } } } RemoveDeadControllerEntries(); EnforceWarmCacheLimits(unscaledTime); PruneColdHistory(); } private void EnforceWarmCacheLimits(float now) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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_01df: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) _warmCandidateBuffer.Clear(); long totalWarmBytes = 0L; int totalWarmZones = 0; int frequentWarmZones = 0; foreach (KeyValuePair<Vector2s, SectorMeshClusterController> sectorController in _sectorControllers) { Vector2s key = sectorController.Key; SectorMeshClusterController value = sectorController.Value; if (Object.op_Implicit((Object)(object)value) && _sectorCacheStates.TryGetValue(key, out SectorCacheState value2) && !value2.IsActive) { long estimatedGeneratedMemoryBytes = value.EstimatedGeneratedMemoryBytes; bool flag = value2.VisitCount >= ValheimScalabilityConfig.FrequentZoneVisitThreshold; WarmCacheCandidate item = new WarmCacheCandidate(key, value, value2, estimatedGeneratedMemoryBytes, flag); _warmCandidateBuffer.Add(item); totalWarmBytes += estimatedGeneratedMemoryBytes; totalWarmZones++; if (flag) { frequentWarmZones++; } } } if (_warmCandidateBuffer.Count == 0) { return; } if (!ValheimScalabilityConfig.IsWarmCacheEnabled) { foreach (WarmCacheCandidate item2 in _warmCandidateBuffer) { EvictSector(item2.Sector, "warm cache disabled"); } return; } long singleWarmZoneMemoryLimitBytes = ValheimScalabilityConfig.SingleWarmZoneMemoryLimitBytes; foreach (WarmCacheCandidate item3 in _warmCandidateBuffer) { if (!item3.Evicted) { float num = (item3.IsFrequent ? ValheimScalabilityConfig.FrequentWarmRetentionSeconds : ValheimScalabilityConfig.WarmRetentionSeconds); float num2 = Mathf.Max(0f, now - item3.State.WarmSince); if (num >= 0f && num2 > num) { MarkEvicted(item3, ref totalWarmZones, ref frequentWarmZones, ref totalWarmBytes); EvictSector(item3.Sector, item3.IsFrequent ? "frequent-zone TTL expired" : "warm-zone TTL expired"); } else if (singleWarmZoneMemoryLimitBytes > 0 && item3.Bytes > singleWarmZoneMemoryLimitBytes) { MarkEvicted(item3, ref totalWarmZones, ref frequentWarmZones, ref totalWarmBytes); EvictSector(item3.Sector, "single-zone warm memory limit exceeded"); } } } int frequentWarmZoneLimit = ValheimScalabilityConfig.FrequentWarmZoneLimit; if (frequentWarmZoneLimit >= 0 && frequentWarmZones > frequentWarmZoneLimit) { _warmCandidateBuffer.Sort(WarmCacheCandidate.CompareFrequentEvictionOrder); foreach (WarmCacheCandidate item4 in _warmCandidateBuffer) { if (frequentWarmZones <= frequentWarmZoneLimit) { break; } if (!item4.Evicted && item4.IsFrequent) { MarkEvicted(item4, ref totalWarmZones, ref frequentWarmZones, ref totalWarmBytes); EvictSector(item4.Sector, "frequent warm-zone limit exceeded"); } } } int warmZoneLimit = ValheimScalabilityConfig.WarmZoneLimit; long warmMeshMemoryLimitBytes = ValheimScalabilityConfig.WarmMeshMemoryLimitBytes; bool num3 = warmZoneLimit > 0 && totalWarmZones > warmZoneLimit; bool flag2 = warmMeshMemoryLimitBytes > 0 && totalWarmBytes > warmMeshMemoryLimitBytes; if (!num3 && !flag2) { return; } _warmCandidateBuffer.Sort(WarmCacheCandidate.CompareGlobalEvictionOrder); foreach (WarmCacheCandidate item5 in _warmCandidateBuffer) { bool num4 = warmZoneLimit > 0 && totalWarmZones > warmZoneLimit; flag2 = warmMeshMemoryLimitBytes > 0 && totalWarmBytes > warmMeshMemoryLimitBytes; if (!num4 && !flag2) { break; } if (!item5.Evicted) { MarkEvicted(item5, ref totalWarmZones, ref frequentWarmZones, ref totalWarmBytes); EvictSector(item5.Sector, flag2 ? "warm mesh-memory budget exceeded" : "warm-zone count limit exceeded"); } } } private static void MarkEvicted(WarmCacheCandidate candidate, ref int totalWarmZones, ref int frequentWarmZones, ref long totalWarmBytes) { if (!candidate.Evicted) { candidate.Evicted = true; totalWarmZones = Mathf.Max(0, totalWarmZones - 1); if (candidate.IsFrequent) { frequentWarmZones = Mathf.Max(0, frequentWarmZones - 1); } totalWarmBytes = Math.Max(0L, totalWarmBytes - candidate.Bytes); } } private void EvictSector(Vector2s sector, string reason) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) if (_sectorControllers.TryGetValue(sector, out SectorMeshClusterController value)) { long bytes = (Object.op_Implicit((Object)(object)value) ? value.EstimatedGeneratedMemoryBytes : 0); if (ValheimScalabilityConfig.IsCacheDiagnosticsEnabled) { Debug.Log((object)$"[ValheimScalability] Cold-evict sector={sector.x},{sector.y} reason='{reason}' releasing≈{FormatMegabytes(bytes)} MB"); } if (Object.op_Implicit((Object)(object)value)) { Object.Destroy((Object)(object)((Component)value).gameObject); } _sectorControllers.Remove(sector); if (_sectorCacheStates.TryGetValue(sector, out SectorCacheState value2)) { va