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 HighSeatPlus v0.2.0
plugins\HighSeatPlus.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.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ConfigReload; using HarmonyLib; using MagicaCloth2; using Microsoft.CodeAnalysis; using PatchGuard; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("HighSeatPlus")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("HighSeatPlus: the players' half of HighSeat for big servers")] [assembly: AssemblyFileVersion("0.2.0.0")] [assembly: AssemblyInformationalVersion("0.2.0+4958e6e28f49370e9871253dd69c30bb27b0fad3")] [assembly: AssemblyProduct("HighSeatPlus")] [assembly: AssemblyTitle("HighSeatPlus")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace HighSeatPlus { public static class DeltaClientStats { public static int Packages; public static int Deltas; public static int Whole; public static int Asked; public static bool GaveUp; public static int Held => HeldCopies.Count; internal static void Received(int deltas, int whole) { Packages++; Deltas += deltas; Whole += whole; } internal static void CountAsked(int count) { Asked += count; } internal static void Reset() { Packages = 0; Deltas = 0; Whole = 0; Asked = 0; GaveUp = false; } } internal static class DeltaFormat { public const int Version = 1; public const string HelloRpc = "HighSeatPlus_Deltas"; public const string DataRpc = "HighSeat_ZDODeltas"; public const string FullCopyRpc = "HighSeatPlus_FullCopy"; public const byte End = 0; public const byte Full = 1; public const byte Delta = 2; public const byte HasOwner = 1; public const byte HasPosition = 2; public const int HeaderSize = 42; public const int RevisionsSize = 18; public const int DataLengthAt = 38; } internal static class DeltaHeader { private const int MinData = 6; public static ZDOID Id; public static uint Data; public static ushort Owner; public static uint FromData; public static ushort FromOwner; private static int _at; private static int _ownerAt; private static int _positionAt; private static int _dataAt; private static int _dataLength; public static int Read(byte[] b, int p, int end) { //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) if (p + 18 + 1 > end) { return -1; } _at = p; Id = PackageBytes.Id(b, p); Owner = PackageBytes.U16(b, p + 12); Data = PackageBytes.U32(b, p + 14); byte b2 = b[p + 18]; int q = p + 18 + 1; if (!Steps(b, ref q, end)) { return -1; } _ownerAt = (((b2 & 1) != 0) ? PackageBytes.Take(ref q, 8, end) : (-1)); _positionAt = (((b2 & 2) != 0) ? PackageBytes.Take(ref q, 12, end) : (-1)); _dataLength = PackageBytes.Varint(b, ref q, end); _dataAt = ((_dataLength < 6) ? (-1) : PackageBytes.Take(ref q, _dataLength, end)); if (_dataAt >= 0) { return q; } return -1; } private static bool Steps(byte[] b, ref int q, int end) { int num = PackageBytes.Varint(b, ref q, end); int num2 = PackageBytes.Varint(b, ref q, end); if (num < 0 || num2 < 0 || (uint)num > Data || num2 > Owner) { return false; } FromData = Data - (uint)num; FromOwner = (ushort)(Owner - num2); return true; } public static void WriteGameRecord(ZPackage game, byte[] b, ZDO zdo) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) BinaryWriter writer = game.m_writer; writer.Write(b, _at, 18); if (_ownerAt >= 0) { writer.Write(b, _ownerAt, 8); } else { game.Write(zdo.GetOwner()); } if (_positionAt >= 0) { writer.Write(b, _positionAt, 12); } else { game.Write(zdo.GetPosition()); } writer.Write(_dataLength); writer.Write(b, _dataAt, _dataLength); } } internal static class DeltaLink { [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class Opened { private static void Postfix(ZNet __instance, ZNetPeer peer) { try { if (!__instance.IsServer() && peer != null && peer.m_server && peer.m_rpc != null) { HeldCopies.Clear(); DeltaClientStats.Reset(); DeltaReceiver.Listen(peer); } } catch (Exception ex) { HighSeatPlus.Log.LogWarning((object)("smaller world updates are off for this connection: " + ex.Message)); } } } [HarmonyPatch(typeof(ZDOMan), "HandleDestroyedZDO")] private static class Destroyed { private static void Postfix(ZDOID uid) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) HeldCopies.Forget(uid); } } [HarmonyPatch(typeof(ZDOMan), "ShutDown")] private static class Closed { private static void Postfix() { HeldCopies.Clear(); } } } internal static class DeltaReceiver { private static bool _gaveUp; private static bool _gameFailed; public static void Listen(ZNetPeer server) { _gaveUp = false; server.m_rpc.Register<ZPackage>("HighSeat_ZDODeltas", (Action<ZRpc, ZPackage>)Received); server.m_rpc.Invoke("HighSeatPlus_Deltas", new object[1] { 1 }); } private static void Received(ZRpc rpc, ZPackage pkg) { try { ZDOMan instance = ZDOMan.instance; if (instance != null && (Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer()) { Take(instance, rpc, pkg); } } catch (Exception ex) { GiveUp(rpc, ex.Message); } finally { PackageConvert.Clear(); } } private static void Take(ZDOMan man, ZRpc rpc, ZPackage pkg) { if (!PackageConvert.Convert(man, pkg)) { GiveUp(rpc, "a delta package could not be read"); return; } Apply(man, rpc); AskAgain(rpc); } private static void Apply(ZDOMan man, ZRpc rpc) { PackageConvert.Game.SetPos(0); try { man.RPC_ZDOData(rpc, PackageConvert.Game); } catch (Exception e) { GameFailed(rpc, e); return; } foreach (HeldCopies.Expect item in PackageConvert.Expected) { HeldCopies.Settle(item); } DeltaClientStats.Received(PackageConvert.Deltas, PackageConvert.Expected.Count - PackageConvert.Deltas); } private static void GameFailed(ZRpc rpc, Exception e) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) foreach (HeldCopies.Expect item in PackageConvert.Expected) { HeldCopies.Forget(item.Id); } if (!_gameFailed) { _gameFailed = true; HighSeatPlus.Log.LogWarning((object)$"the game's own handling of world data failed on a delta package (logged once): {e}"); } GiveUp(rpc, "the game's own handling of a package failed"); } private static void AskAgain(ZRpc rpc) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //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_0039: Unknown result type (might be due to invalid IL or missing references) if (PackageConvert.Asks.Count == 0) { return; } ZPackage val = new ZPackage(); val.Write(PackageConvert.Asks.Count); foreach (ZDOID ask in PackageConvert.Asks) { val.Write(ask); } rpc.Invoke("HighSeatPlus_FullCopy", new object[1] { val }); DeltaClientStats.CountAsked(PackageConvert.Asks.Count); } private static void GiveUp(ZRpc rpc, string why) { if (_gaveUp) { return; } _gaveUp = true; DeltaClientStats.GaveUp = true; HighSeatPlus.Log.LogWarning((object)("smaller world updates are off for this connection (" + why + "); the server sends whole objects")); try { rpc.Invoke("HighSeatPlus_Deltas", new object[1] { 0 }); } catch (Exception) { } } } internal static class HeldCopies { public enum Outcome : byte { Data, Owner, Skip } public struct Expect { public ZDOID Id; public uint Data; public ushort Owner; public Outcome What; public uint LocalData; public ushort LocalOwner; } private struct Revisions { public uint Data; public ushort Owner; } private static readonly Dictionary<ZDOID, Revisions> Held = new Dictionary<ZDOID, Revisions>(); public static int Count => Held.Count; public static bool Holds(ZDO zdo, uint data, ushort owner) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (zdo.DataRevision == data && zdo.OwnerRevision == owner && Held.TryGetValue(zdo.m_uid, out var value) && value.Data == data) { return value.Owner == owner; } return false; } public static Expect Predict(ZDOMan man, ZDOID id, uint data, ushort owner) { //IL_0001: 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) ZDO zDO = man.GetZDO(id); Expect result = new Expect { Id = id, Data = data, Owner = owner, What = Outcome.Skip }; if (zDO == null || data > zDO.DataRevision) { result.What = Outcome.Data; } else if (owner > zDO.OwnerRevision) { result.What = Outcome.Owner; result.LocalData = zDO.DataRevision; result.LocalOwner = zDO.OwnerRevision; } return result; } public static void Settle(Expect expect) { //IL_000e: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) if (expect.What == Outcome.Data) { Held[expect.Id] = new Revisions { Data = expect.Data, Owner = expect.Owner }; } else if (expect.What == Outcome.Owner) { Revisions value; bool num = Held.TryGetValue(expect.Id, out value) && value.Data == expect.LocalData && value.Owner == expect.LocalOwner && expect.Data == expect.LocalData; Forget(expect.Id); if (num) { Held[expect.Id] = new Revisions { Data = expect.Data, Owner = expect.Owner }; } } } public static void Forget(ZDOID id) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (Held.Count > 0) { Held.Remove(id); } } public static void Clear() { Held.Clear(); } } internal static class PackageBytes { public static ushort U16(byte[] b, int p) { return (ushort)(b[p] | (b[p + 1] << 8)); } public static int I32(byte[] b, int p) { return b[p] | (b[p + 1] << 8) | (b[p + 2] << 16) | (b[p + 3] << 24); } public static uint U32(byte[] b, int p) { return (uint)I32(b, p); } public static long I64(byte[] b, int p) { return (uint)I32(b, p) | ((long)I32(b, p + 4) << 32); } public static ZDOID Id(byte[] b, int p) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) return new ZDOID(I64(b, p), U32(b, p + 8)); } public static int Varint(byte[] b, ref int p, int end) { int num = 0; for (int i = 0; i < 35; i += 7) { if (p < 0 || p >= end) { return -1; } byte b2 = b[p++]; num |= (b2 & 0x7F) << i; if ((b2 & 0x80) == 0) { if (num >= 0) { return num; } return -1; } } return -1; } public static int Take(ref int p, int size, int end) { if (p < 0 || (long)p + (long)size > end) { p = -1; return -1; } int result = p; p += size; return result; } } internal static class PackageConvert { public static readonly ZPackage Game = new ZPackage(); public static readonly List<HeldCopies.Expect> Expected = new List<HeldCopies.Expect>(); public static readonly List<ZDOID> Asks = new List<ZDOID>(); public static int Deltas; public static bool Convert(ZDOMan man, ZPackage pkg) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) Clear(); byte[] buffer = pkg.m_stream.GetBuffer(); int num = pkg.Size(); int pos = pkg.GetPos(); if (pos >= num || buffer[pos++] != 1) { return false; } pos = Drops(buffer, pos, num); while (pos >= 0 && pos < num) { int num2; switch (buffer[pos++]) { case 0: Game.Write(ZDOID.None); return pos == num; default: num2 = -1; break; case 2: num2 = Delta(man, buffer, pos, num); break; case 1: num2 = Whole(man, buffer, pos, num); break; } pos = num2; } return false; } public static void Clear() { Game.Clear(); Expected.Clear(); Asks.Clear(); Deltas = 0; } private static int Drops(byte[] b, int p, int end) { int num = ((p + 4 <= end) ? PackageBytes.I32(b, p) : (-1)); p += 4; if (num < 0 || p + 12L * (long)num > end) { return -1; } Game.Write(num); Game.m_writer.Write(b, p, 12 * num); return p + 12 * num; } private static int Whole(ZDOMan man, byte[] b, int p, int end) { //IL_0029: 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_0035: Unknown result type (might be due to invalid IL or missing references) int num = ((p + 42 <= end) ? PackageBytes.I32(b, p + 38) : (-1)); if (num < 0 || (long)(p + 42) + (long)num > end) { return -1; } ZDOID id = PackageBytes.Id(b, p); Expected.Add(HeldCopies.Predict(man, id, PackageBytes.U32(b, p + 14), PackageBytes.U16(b, p + 12))); Game.m_writer.Write(b, p, 42 + num); return p + 42 + num; } private static int Delta(ZDOMan man, byte[] b, int p, int end) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) int num = DeltaHeader.Read(b, p, end); if (num < 0) { return -1; } ZDO zDO = man.GetZDO(DeltaHeader.Id); if (zDO == null || !HeldCopies.Holds(zDO, DeltaHeader.FromData, DeltaHeader.FromOwner)) { Asks.Add(DeltaHeader.Id); return num; } Expected.Add(HeldCopies.Predict(man, DeltaHeader.Id, DeltaHeader.Data, DeltaHeader.Owner)); DeltaHeader.WriteGameRecord(Game, b, zDO); Deltas++; return num; } } [BepInPlugin("com.HighSeatPlus", "HighSeatPlus", "0.2.0")] public class HighSeatPlus : BaseUnityPlugin { public const string PluginGuid = "com.HighSeatPlus"; public const string PluginName = "HighSeatPlus"; public const string PluginVersion = "0.2.0"; public static ManualLogSource Log { get; private set; } private void Awake() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Settings.Bind(((BaseUnityPlugin)this).Config); ConfigReloader.Setup(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); Harmony val = new Harmony("com.HighSeatPlus"); val.PatchAll(Assembly.GetExecutingAssembly()); Guard.Install(val, ((BaseUnityPlugin)this).Logger, Assembly.GetExecutingAssembly()); } } internal static class Settings { private const string General = "1 - General"; public static ConfigEntry<bool> CombineBuildingMeshes; public static ConfigEntry<bool> SimplerFarPlayers; public static void Bind(ConfigFile config) { CombineBuildingMeshes = config.Bind<bool>("1 - General", "Combine building meshes", true, "A building that has settled is drawn as a few combined meshes instead of one per piece; a piece that is placed, removed, damaged or repaired is split back out. Colliders and everything the game checks stay as they are."); SimplerFarPlayers = config.Bind<bool>("1 - General", "Simpler far players", true, "Players beyond the nearest few are drawn without cloth and animate less often. Nobody is ever hidden, and party members and anyone near enough to fight are always drawn in full."); } } internal static class SupportBounds { private static readonly List<Collider> Colliders = new List<Collider>(); private static int _mask; public static bool Of(GameObject root, out Bounds bounds) { //IL_0001: 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) //IL_004a: 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) bounds = default(Bounds); bool flag = false; root.GetComponentsInChildren<Collider>(false, Colliders); foreach (Collider collider in Colliders) { if (Seen(collider)) { if (flag) { ((Bounds)(ref bounds)).Encapsulate(collider.bounds); continue; } bounds = collider.bounds; flag = true; } } Colliders.Clear(); return flag; } private static bool Seen(Collider collider) { if (_mask == 0) { _mask = LayerMask.GetMask(new string[5] { "piece", "Default", "static_solid", "Default_small", "terrain" }); } if (collider.enabled && !collider.isTrigger && (Object)(object)collider.attachedRigidbody == (Object)null) { return (_mask & (1 << ((Component)collider).gameObject.layer)) != 0; } return false; } } internal static class SupportCells { internal sealed class Cell { public int Stamp; public float SettleUntil; } public const float GroundSettleSeconds = 0.5f; private const float Size = 4f; private const float Margin = 0.25f; private const int MaxRecordColumns = 64; private const int MaxChangeColumns = 4096; private static readonly Dictionary<long, Cell> Cells = new Dictionary<long, Cell>(); private static float _groundSettleUntil; public static void Reset() { Cells.Clear(); _groundSettleUntil = 0f; } public static void Changed(Bounds area, float settleSeconds) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) float num = Time.time + settleSeconds; if (!Range(area, 4096, out var x, out var x2, out var z, out var z2)) { RaiseAll(num); return; } for (int i = x; i <= x2; i++) { for (int j = z; j <= z2; j++) { Cell orAdd = GetOrAdd(Key(i, j)); orAdd.Stamp++; orAdd.SettleUntil = Mathf.Max(orAdd.SettleUntil, num); } } } public static void GroundChanged(Bounds area) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) _groundSettleUntil = Time.time + 0.5f; if (Cells.Count == 0) { return; } if (!Range(area, 4096, out var x, out var x2, out var z, out var z2)) { RaiseAll(0f); return; } for (int i = x; i <= x2; i++) { for (int j = z; j <= z2; j++) { if (Cells.TryGetValue(Key(i, j), out var value)) { value.Stamp++; } } } } public static bool Settling(List<BoundData> boxes) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (Time.time < _groundSettleUntil) { return true; } foreach (BoundData box in boxes) { if (Settling(SupportScan.Box(box))) { return true; } } return false; } public static bool Collect(List<BoundData> boxes, SupportRecord record) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) record.CellCount = 0; foreach (BoundData box in boxes) { if (!Range(SupportScan.Box(box), 64, out var x, out var x2, out var z, out var z2)) { return false; } for (int i = x; i <= x2; i++) { for (int j = z; j <= z2; j++) { record.AddCell(GetOrAdd(Key(i, j))); } } } record.StampSum = Sum(record.Cells, record.CellCount); return record.CellCount <= 64; } private static bool Settling(Bounds area) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) float time = Time.time; if (!Range(area, 64, out var x, out var x2, out var z, out var z2)) { return true; } for (int i = x; i <= x2; i++) { for (int j = z; j <= z2; j++) { if (Cells.TryGetValue(Key(i, j), out var value) && time < value.SettleUntil) { return true; } } } return false; } public static int Sum(Cell[] cells, int count) { int num = 0; for (int i = 0; i < count; i++) { num += cells[i].Stamp; } return num; } private static bool Range(Bounds area, int max, out int x0, out int x1, out int z0, out int z1) { //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_0011: 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_0044: 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) Vector3 min = ((Bounds)(ref area)).min; Vector3 max2 = ((Bounds)(ref area)).max; x0 = Mathf.FloorToInt((min.x - 0.25f) / 4f); x1 = Mathf.FloorToInt((max2.x + 0.25f) / 4f); z0 = Mathf.FloorToInt((min.z - 0.25f) / 4f); z1 = Mathf.FloorToInt((max2.z + 0.25f) / 4f); long num = (long)(x1 - x0 + 1) * (long)(z1 - z0 + 1); if (num > 0) { return num <= max; } return false; } private static void RaiseAll(float settleUntil) { foreach (Cell value in Cells.Values) { value.Stamp++; value.SettleUntil = Mathf.Max(value.SettleUntil, settleUntil); } } private static long Key(int x, int z) { return ((long)x << 32) | (uint)z; } private static Cell GetOrAdd(long key) { if (!Cells.TryGetValue(key, out var value)) { value = new Cell(); Cells.Add(key, value); } return value; } } [HarmonyPatch(typeof(WearNTear), "Start")] internal static class SupportPieceAppears { public const float SettleSeconds = 0.5f; private static void Postfix(WearNTear __instance) { try { Raise(__instance); } catch (Exception e) { SupportSkip.Fail(e); } } public static void Raise(WearNTear piece) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)piece.m_nview != (Object)null && piece.m_nview.GetZDO() != null && SupportBounds.Of(((Component)piece).gameObject, out var bounds)) { SupportCells.Changed(bounds, 0.5f); } } } [HarmonyPatch(typeof(WearNTear), "RPC_HealthChanged")] internal static class SupportPieceLook { private static void Prefix(WearNTear __instance, out int __state) { __state = Look(__instance.m_healthPercentage); } private static void Postfix(WearNTear __instance, int __state) { try { if (((Object)(object)__instance.m_new != (Object)null || (Object)(object)__instance.m_worn != (Object)null || (Object)(object)__instance.m_broken != (Object)null) && Look(__instance.m_healthPercentage) != __state) { SupportPieceAppears.Raise(__instance); } } catch (Exception e) { SupportSkip.Fail(e); } } private static int Look(float health) { if (!(health > 0.75f)) { return (health > 0.25f) ? 1 : 0; } return 2; } } [HarmonyPatch(typeof(WearNTear), "ClearCachedSupport")] internal static class SupportCacheCleared { private static void Postfix(WearNTear __instance) { try { SupportSkip.Drop(__instance); } catch (Exception e) { SupportSkip.Fail(e); } } } [HarmonyPatch(typeof(WearNTear), "OnDestroy")] internal static class SupportPieceGone { private static void Prefix(WearNTear __instance) { try { SupportSkip.Forget(__instance); } catch (Exception e) { SupportSkip.Fail(e); } } } internal sealed class SupportRecord { internal struct Anchor { public Collider Collider; public GameObject GameObject; public Transform Transform; public Vector3 Position; public Quaternion Rotation; public Vector3 Scale; } public bool Valid; public bool Static; public MaterialType Material; public float Support; public float ExpiresAt; public float RetryAt; public Transform Own; public Vector3 Position; public Quaternion Rotation; public int Entries; public Anchor[] Anchors = new Anchor[2]; public int AnchorCount; public SupportCells.Cell[] Cells = new SupportCells.Cell[4]; public int CellCount; public int StampSum; public bool Holds(WearNTear piece) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (piece.m_clearCachedSupport || !piece.m_support.Equals(Support) || piece.m_materialType != Material) { return false; } if (!Static && SupportCells.Sum(Cells, CellCount) != StampSum) { return false; } if (OwnUnchanged() && AnyAnchorIntact()) { return GameCacheUnchanged(piece); } return false; } public void AddAnchor(Collider collider) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (AnchorCount == Anchors.Length) { Array.Resize(ref Anchors, AnchorCount * 2); } Transform transform = ((Component)collider).transform; ref Anchor reference = ref Anchors[AnchorCount++]; reference.Collider = collider; reference.GameObject = ((Component)collider).gameObject; reference.Transform = transform; transform.GetPositionAndRotation(ref reference.Position, ref reference.Rotation); reference.Scale = transform.lossyScale; } public void AddCell(SupportCells.Cell cell) { for (int i = 0; i < CellCount; i++) { if (Cells[i] == cell) { return; } } if (CellCount == Cells.Length) { Array.Resize(ref Cells, CellCount * 2); } Cells[CellCount++] = cell; } public void Clear() { Array.Clear(Anchors, 0, AnchorCount); Array.Clear(Cells, 0, CellCount); AnchorCount = 0; CellCount = 0; Valid = false; } private bool OwnUnchanged() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); Quaternion val2 = default(Quaternion); Own.GetPositionAndRotation(ref val, ref val2); if (((Vector3)(ref val)).Equals(Position)) { return ((Quaternion)(ref val2)).Equals(Rotation); } return false; } private bool AnyAnchorIntact() { for (int i = 0; i < AnchorCount; i++) { if (Intact(ref Anchors[i])) { return true; } } return false; } private static bool Intact(ref Anchor anchor) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_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_0066: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)anchor.Collider == (Object)null || !anchor.Collider.enabled || !anchor.GameObject.activeInHierarchy) { return false; } Vector3 val = default(Vector3); Quaternion val2 = default(Quaternion); anchor.Transform.GetPositionAndRotation(ref val, ref val2); if (((Vector3)(ref val)).Equals(anchor.Position) && ((Quaternion)(ref val2)).Equals(anchor.Rotation)) { Vector3 lossyScale = anchor.Transform.lossyScale; return ((Vector3)(ref lossyScale)).Equals(anchor.Scale); } return false; } private bool GameCacheUnchanged(WearNTear piece) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) List<Collider> supportColliders = piece.m_supportColliders; int count = supportColliders.Count; if (count != Entries) { return false; } for (int i = 0; i < count; i++) { Collider val = supportColliders[i]; WearNTear val2 = piece.m_supportWearNTear[i]; if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || !val2.m_supports || ((Component)val).transform.position != piece.m_supportPositions[i] || !val2.GetSupport().Equals(piece.m_supportValue[i])) { return false; } } return true; } } internal static class SupportScan { private const int MaxCollidersPerBox = 64; private const int MaxAnchors = 16; private const float BoxMargin = 0.1f; private static readonly Collider[] Hits = (Collider[])(object)new Collider[128]; private static readonly List<Collider> Ground = new List<Collider>(4); private static readonly List<Collider> Things = new List<Collider>(4); private static int _terrainLayer = -1; public static bool Worth(WearNTear piece) { if (piece.m_clearCachedSupport || piece.m_colliders == null || piece.m_bounds == null || piece.m_bounds.Count == 0) { return false; } if (piece.m_support.Equals(piece.GetMaxSupport())) { return !GameCacheHolds(piece); } return false; } public static bool Look(WearNTear piece) { //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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_0053: Unknown result type (might be due to invalid IL or missing references) if (_terrainLayer < 0) { _terrainLayer = LayerMask.NameToLayer("terrain"); } Ground.Clear(); Things.Clear(); foreach (BoundData bound in piece.m_bounds) { int num = Physics.OverlapBoxNonAlloc(bound.m_pos, bound.m_size, Hits, bound.m_rot, WearNTear.s_rayMask); bool num2 = num > 64; if (!num2) { Classify(piece, num); } Array.Clear(Hits, 0, num); if (num2) { return Forget(); } } if (Things.Count <= 0 && Ground.Count <= 0) { return Forget(); } return true; } public static bool Forget() { Ground.Clear(); Things.Clear(); return false; } public static bool Fill(WearNTear piece, SupportRecord record) { //IL_0095: 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) record.Clear(); record.Static = Things.Count > 0; record.Entries = piece.m_supportColliders.Count; if (record.Static ? ((byte)record.Entries != 0) : (!SupportCells.Collect(piece.m_bounds, record))) { return Forget(); } List<Collider> list = (record.Static ? Things : Ground); for (int i = 0; i < list.Count; i++) { record.AddAnchor(list[i]); } record.Support = piece.m_support; record.Material = piece.m_materialType; record.Own = ((Component)piece).transform; record.Own.GetPositionAndRotation(ref record.Position, ref record.Rotation); Forget(); return true; } private static bool GameCacheHolds(WearNTear piece) { List<float> supportValue = piece.m_supportValue; if (supportValue.Count == 0) { return false; } float num = 0f; for (int i = 0; i < supportValue.Count; i++) { num = Mathf.Max(num, supportValue[i]); } return num >= piece.m_support; } private static void Classify(WearNTear piece, int count) { for (int i = 0; i < count; i++) { Collider val = Hits[i]; if (!((Object)(object)val.attachedRigidbody != (Object)null) && !val.isTrigger && !IsOwn(piece, val)) { if (((Component)val).gameObject.layer == _terrainLayer) { Keep(Ground, val); } else if ((Object)(object)((Component)val).GetComponentInParent<WearNTear>() == (Object)null) { Keep(Things, val); } } } } private static bool IsOwn(WearNTear piece, Collider collider) { Collider[] colliders = piece.m_colliders; for (int i = 0; i < colliders.Length; i++) { if (colliders[i] == collider) { return true; } } return false; } private static void Keep(List<Collider> list, Collider collider) { if (list.Count >= 16) { return; } for (int i = 0; i < list.Count; i++) { if (list[i] == collider) { return; } } list.Add(collider); } public static Bounds Box(BoundData bound) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_0043: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0064: 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_006c: 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_0083: 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_009a: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) Vector3 size = bound.m_size; Vector3 val = bound.m_rot * new Vector3(size.x, 0f, 0f); Vector3 val2 = bound.m_rot * new Vector3(0f, size.y, 0f); Vector3 val3 = bound.m_rot * new Vector3(0f, 0f, size.z); Vector3 val4 = default(Vector3); ((Vector3)(ref val4))..ctor(Mathf.Abs(val.x) + Mathf.Abs(val2.x) + Mathf.Abs(val3.x), Mathf.Abs(val.y) + Mathf.Abs(val2.y) + Mathf.Abs(val3.y), Mathf.Abs(val.z) + Mathf.Abs(val2.z) + Mathf.Abs(val3.z)); return new Bounds(bound.m_pos, val4 * 2f + new Vector3(0.1f, 0.1f, 0.1f) * 2f); } } [HarmonyPatch(typeof(WearNTear), "UpdateSupport")] internal static class SupportSkip { public const float SafetySeconds = 10f; private const float RetrySeconds = 10f; private const int Skipping = 0; private const int Running = 1; private const int Recheck = 2; private static readonly Dictionary<int, SupportRecord> Records = new Dictionary<int, SupportRecord>(); private static bool _broken; public static int Count => Records.Count; private static bool Prefix(WearNTear __instance, out int __state) { __state = 1; if (_broken) { return true; } try { __state = Decide(__instance); } catch (Exception e) { Fail(e); __state = 1; } return __state != 0; } private static void Postfix(WearNTear __instance, int __state) { if (__state == 0 || _broken) { return; } try { After(__instance, __state == 2); } catch (Exception e) { Fail(e); } } private static int Decide(WearNTear piece) { if (!Records.TryGetValue(((Object)piece).GetInstanceID(), out var value) || !value.Valid) { SupportStats.Plain++; return 1; } if (Time.time >= value.ExpiresAt) { value.Valid = false; SupportStats.Rechecked++; return 2; } if (!value.Holds(piece)) { value.Valid = false; SupportStats.AfterChange++; return 1; } SupportStats.Skipped++; return 0; } private static void After(WearNTear piece, bool recheck) { Records.TryGetValue(((Object)piece).GetInstanceID(), out var value); if ((value == null || Release(piece, value, recheck)) && SupportScan.Worth(piece) && !SupportCells.Settling(piece.m_bounds)) { if (value == null) { value = Add(piece); } if (!SupportScan.Look(piece) || !SupportScan.Fill(piece, value)) { value.RetryAt = Time.time + 10f; return; } value.Valid = true; value.ExpiresAt = Time.time + Interval(piece); } } private static bool Release(WearNTear piece, SupportRecord record, bool recheck) { if (recheck && !piece.m_support.Equals(record.Support)) { SupportStats.Miss(piece, record.Support); } record.Clear(); return Time.time >= record.RetryAt; } private static SupportRecord Add(WearNTear piece) { SupportRecord supportRecord = new SupportRecord(); Records[((Object)piece).GetInstanceID()] = supportRecord; return supportRecord; } private static float Interval(WearNTear piece) { uint num = (uint)(((Object)piece).GetInstanceID() * -1640531535) >> 16; return 10f * (0.8f + 0.4f * (float)(num & 0xFFFF) / 65535f); } public static void Drop(WearNTear piece) { if (Records.TryGetValue(((Object)piece).GetInstanceID(), out var value)) { value.Valid = false; } } public static void Forget(WearNTear piece) { Records.Remove(((Object)piece).GetInstanceID()); } public static void Reset() { Records.Clear(); } public static void Fail(Exception e) { if (!_broken) { _broken = true; HighSeatPlus.Log.LogWarning((object)$"building support is back to the game's own check every second after an error: {e}"); } } } internal static class SupportStats { private const int MaxWarnings = 5; public static long Skipped; public static long AfterChange; public static long Rechecked; public static long Missed; public static long Plain; public static void Miss(WearNTear piece, float before) { //IL_001d: 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_003e: 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_005a: Unknown result type (might be due to invalid IL or missing references) Missed++; if (Missed <= 5) { Vector3 position = ((Component)piece).transform.position; HighSeatPlus.Log.LogWarning((object)($"support recheck: {((Object)piece).name} at {position.x:0.0} {position.y:0.0} {position.z:0.0} went from " + $"{before:0.##} to {piece.m_support:0.##} without any change being seen; it took up to " + $"{12f:0} s to show. Please report it with the build around it.")); } } } [HarmonyPatch(typeof(Heightmap), "RebuildCollisionMesh")] internal static class SupportGroundRebuilt { private static void Postfix(Heightmap __instance) { try { Raise(__instance); } catch (Exception e) { SupportSkip.Fail(e); } } public static void Raise(Heightmap heightmap) { //IL_002c: 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_003d: Unknown result type (might be due to invalid IL or missing references) if (!heightmap.IsDistantLod && !((Object)(object)heightmap.m_collider == (Object)null)) { float num = (float)heightmap.m_width * heightmap.m_scale; SupportCells.GroundChanged(new Bounds(((Component)heightmap).transform.position, new Vector3(num, 1f, num))); } } } [HarmonyPatch(typeof(Heightmap), "Clear")] internal static class SupportGroundCleared { private static void Postfix(Heightmap __instance) { try { SupportGroundRebuilt.Raise(__instance); } catch (Exception e) { SupportSkip.Fail(e); } } } [HarmonyPatch(typeof(Door), "SetState")] internal static class SupportDoorSwings { private const float Reach = 3f; private const float SwingSeconds = 3f; private static readonly int StateHash = Animator.StringToHash("state"); private static void Prefix(Door __instance, int state) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) try { Animator animator = __instance.m_animator; if ((Object)(object)animator != (Object)null && animator.GetInteger(StateHash) != state && SupportBounds.Of(((Component)__instance).gameObject, out var bounds)) { ((Bounds)(ref bounds)).Expand(6f); SupportCells.Changed(bounds, 3f); } } catch (Exception e) { SupportSkip.Fail(e); } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class SupportWorldReset { private static void Postfix() { SupportSkip.Reset(); SupportCells.Reset(); } } } namespace HighSeatPlus.Meshes { internal sealed class CellGroup { public const float JoinDelaySeconds = 1f; public readonly GroupKey Key; public readonly Vector3 Origin; public readonly List<PieceEntry> Members = new List<PieceEntry>(); public GroupBuild Build; public bool Open; public bool Dirty; public bool Queued; public bool Discarded; public float QuietUntil; public int AllIndex = -1; public CellGroup(GroupKey key) { //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) Key = key; float num = 16f; Origin = new Vector3(((float)key.X + 0.5f) * num, ((float)key.Y + 0.5f) * num, ((float)key.Z + 0.5f) * num); } public bool Ready(float now) { return now >= QuietUntil; } public void Add(PieceEntry entry, float now) { entry.Group = this; entry.MemberIndex = Members.Count; entry.InBuild = false; Members.Add(entry); Dirty = true; QuietUntil = Mathf.Max(QuietUntil, now + 1f); CellGroups.Queue(this); } public void Touched(PieceEntry entry) { WaitFor(entry); if (entry.InBuild) { Hide(); } CellGroups.Queue(this); } public void Leave(PieceEntry entry) { if (entry.InBuild) { Hide(); Dirty = true; } Drop(entry); if (Members.Count == 0) { CellGroups.Discard(this); } else { CellGroups.Queue(this); } } public void Drop(PieceEntry entry) { entry.SetForced(off: false); int memberIndex = entry.MemberIndex; int num = Members.Count - 1; if (memberIndex >= 0 && memberIndex <= num && Members[memberIndex] == entry) { Members[memberIndex] = Members[num]; Members[memberIndex].MemberIndex = memberIndex; Members.RemoveAt(num); } entry.Group = null; entry.MemberIndex = -1; entry.InBuild = false; } public void WaitFor(PieceEntry entry) { float num = Mathf.Max(entry.TouchedAt + 5f, entry.RetryAt); QuietUntil = Mathf.Max(QuietUntil, num); } public void Hide() { if (!Open && Build != null) { Open = true; Build.SetShown(shown: false); for (int i = 0; i < Members.Count; i++) { Members[i].SetForced(off: false); } } } public int Settle(float now, int budget) { if (Open && !Dirty) { if (AllValid()) { Show(); return 0; } Dirty = true; } if (!Dirty || budget <= 0) { return 0; } return GroupBuilder.Rebuild(this, now); } private bool AllValid() { for (int i = 0; i < Members.Count; i++) { if (!Members[i].InBuild || !PartChecks.Valid(Members[i])) { return false; } } return true; } private void Show() { Open = false; for (int i = 0; i < Members.Count; i++) { Members[i].SetForced(off: true); } Build.SetShown(shown: true); } } internal static class CellGroups { public const float CellSize = 16f; private static readonly Dictionary<GroupKey, CellGroup> Map = new Dictionary<GroupKey, CellGroup>(); private static readonly List<CellGroup> All = new List<CellGroup>(); private static readonly Queue<CellGroup> Work = new Queue<CellGroup>(); private static int _sweepGroup; private static int _sweepMember; public static int Vertices { get; private set; } public static void Join(PieceEntry entry, float now) { if (!Map.TryGetValue(entry.Key, out var value)) { value = new CellGroup(entry.Key); Map.Add(entry.Key, value); value.AllIndex = All.Count; All.Add(value); } value.Add(entry, now); } public static void Queue(CellGroup group) { if (!group.Queued && !group.Discarded) { group.Queued = true; Work.Enqueue(group); } } public static void Process(float now, int groups, int vertexBudget) { for (int i = 0; i < groups; i++) { if (Work.Count <= 0) { break; } CellGroup cellGroup = Work.Dequeue(); cellGroup.Queued = false; if (!cellGroup.Discarded) { if (cellGroup.Ready(now)) { vertexBudget -= cellGroup.Settle(now, vertexBudget); } if (!cellGroup.Discarded && (cellGroup.Dirty || cellGroup.Open)) { Queue(cellGroup); } } } } public static void Sweep(int parts) { int num = parts * 2; while (parts > 0 && num-- > 0 && All.Count > 0) { if (_sweepGroup >= All.Count) { _sweepGroup = 0; } CellGroup cellGroup = All[_sweepGroup]; if (cellGroup.Open || cellGroup.Build == null || _sweepMember >= cellGroup.Members.Count) { _sweepGroup++; _sweepMember = 0; continue; } PieceEntry pieceEntry = cellGroup.Members[_sweepMember++]; parts -= pieceEntry.Parts.Count; if (pieceEntry.InBuild && !PartChecks.Valid(pieceEntry)) { PieceRegistry.Touch(pieceEntry); } } } public static void Replaced(GroupBuild old, GroupBuild build) { if (old != null) { Vertices -= old.Vertices; old.Destroy(); } if (build != null) { Vertices += build.Vertices; } } public static void Discard(CellGroup group) { if (!group.Discarded) { group.Discarded = true; Replaced(group.Build, null); group.Build = null; Map.Remove(group.Key); int allIndex = group.AllIndex; int num = All.Count - 1; if (allIndex >= 0 && allIndex <= num && All[allIndex] == group) { All[allIndex] = All[num]; All[allIndex].AllIndex = allIndex; All.RemoveAt(num); } } } public static void RefreshLods() { for (int i = 0; i < All.Count; i++) { All[i].Build?.UpdateLod(); } } public static void Clear() { for (int i = 0; i < All.Count; i++) { CellGroup cellGroup = All[i]; for (int j = 0; j < cellGroup.Members.Count; j++) { PieceEntry pieceEntry = cellGroup.Members[j]; pieceEntry.SetForced(off: false); pieceEntry.Group = null; pieceEntry.InBuild = false; } cellGroup.Members.Clear(); cellGroup.Discarded = true; cellGroup.Build?.Destroy(); cellGroup.Build = null; } All.Clear(); Map.Clear(); Work.Clear(); Vertices = 0; _sweepGroup = 0; _sweepMember = 0; } } internal sealed class CombinedMeshes : MonoBehaviour { public const float SettleSeconds = 5f; private const int InspectPerFrame = 16; private const int GroupsPerFrame = 8; private const int VerticesPerFrame = 24000; private const int SweepPartsPerFrame = 48; private const string ContainerName = "HighSeatPlus combined meshes"; private static CombinedMeshes _instance; private static bool _failed; public static bool Active { get; private set; } public static Transform Container { get; private set; } public static void Attach(GameObject host) { if ((Object)(object)_instance == (Object)null && !_failed) { host.AddComponent<CombinedMeshes>(); } } public static void Fail(Exception error) { if (_failed) { return; } _failed = true; HighSeatPlus.Log.LogWarning((object)("Combined building meshes stopped after an error; every piece is drawn by the game again. " + error)); try { TurnOff(); } catch (Exception ex) { HighSeatPlus.Log.LogWarning((object)("Could not hand every piece back: " + ex.Message)); } } private void Awake() { _instance = this; } private void Update() { if (_failed) { return; } try { Tick(); } catch (Exception error) { Fail(error); } } private void Tick() { bool flag = Settings.CombineBuildingMeshes.Value && ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsDedicated()); if (flag != Active) { if (flag) { TurnOn(); } else { TurnOff(); } } if (Active) { Work(Time.time); } } private static void Work(float now) { if (GroupLod.Refresh(now)) { CellGroups.RefreshLods(); } PieceRegistry.ProcessPending(now, 16); CellGroups.Process(now, 8, 24000); CellGroups.Sweep(48); } private static void TurnOn() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Container == (Object)null) { Container = new GameObject("HighSeatPlus combined meshes").transform; } Active = true; PieceRegistry.AddAll(); } private static void TurnOff() { Active = false; CellGroups.Clear(); PieceRegistry.Clear(); } private void OnDestroy() { if (!((Object)(object)_instance != (Object)(object)this)) { _instance = null; try { TurnOff(); } catch (Exception ex) { HighSeatPlus.Log.LogWarning((object)("Combined building meshes did not close cleanly: " + ex.Message)); } if ((Object)(object)Container != (Object)null) { Object.Destroy((Object)(object)((Component)Container).gameObject); } Container = null; GroupLod.Reset(); RenderRules.Clear(); LodLayouts.Clear(); } } } internal struct GroupShape { public int Levels; public float Detail; public float Cull; public float Radius; public Vector3 Center; } internal sealed class GroupBuild { private const string RootName = "HighSeatPlus combined"; private const string PartName = "combined part"; public readonly GameObject Root; public readonly int Vertices; private readonly List<Mesh> _meshes; private readonly List<MeshRenderer> _renderers; private readonly LODGroup _lod; private readonly LOD[] _lods; private readonly GroupShape _shape; public GroupBuild(GameObject root, List<Mesh> meshes, List<MeshRenderer> renderers, LODGroup lod, LOD[] lods, GroupShape shape, int vertices) { Root = root; _meshes = meshes; _renderers = renderers; _lod = lod; _lods = lods; _shape = shape; Vertices = vertices; } public static GameObject MakeRoot(Vector3 origin) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("HighSeatPlus combined"); val.SetActive(false); if ((Object)(object)CombinedMeshes.Container != (Object)null) { val.transform.SetParent(CombinedMeshes.Container, false); } val.transform.position = origin; return val; } public static MeshRenderer MakeRenderer(GameObject root, Mesh mesh, Material material, int look) { //IL_0005: 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_001c: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("combined part"); val.transform.SetParent(root.transform, false); val.AddComponent<MeshFilter>().sharedMesh = mesh; MeshRenderer obj = val.AddComponent<MeshRenderer>(); ((Renderer)obj).sharedMaterial = material; RenderRules.Apply(obj, look); return obj; } public void SetShown(bool shown) { if ((Object)(object)Root != (Object)null && Root.activeSelf != shown) { Root.SetActive(shown); } } public bool Visible() { for (int i = 0; i < _renderers.Count; i++) { if ((Object)(object)_renderers[i] != (Object)null && ((Renderer)_renderers[i]).isVisible) { return true; } } return false; } public void UpdateLod() { if (!((Object)(object)_lod == (Object)null) && _lods != null) { GroupLod.Fill(_lods, _shape.Detail, _shape.Cull, _shape.Radius); _lod.SetLODs(_lods); } } public void Destroy() { for (int i = 0; i < _meshes.Count; i++) { if ((Object)(object)_meshes[i] != (Object)null) { Object.Destroy((Object)(object)_meshes[i]); } } _meshes.Clear(); if ((Object)(object)Root != (Object)null) { Object.Destroy((Object)(object)Root); } } } internal static class GroupBuilder { private const int MaxVertices = 3000000; private static readonly List<PieceEntry> Included = new List<PieceEntry>(); private static readonly List<Bucket> Buckets = new List<Bucket>(); private static readonly Stack<Bucket> Spare = new Stack<Bucket>(); private static readonly Dictionary<long, Bucket> ByKey = new Dictionary<long, Bucket>(); private static int _stamp; private static bool _warned; public static int Rebuild(CellGroup group, float now) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) Collect(group, now); if (group.Members.Count == 0 || Included.Count == 0) { Swap(group, null); Release(); return 0; } GroupShape shape = Shape(group.Key.Lod != 0); int num = FillBuckets(group.Origin, Mathf.Max(shape.Levels, 1)); int num2 = ((group.Build != null) ? group.Build.Vertices : 0); bool num3 = CellGroups.Vertices - num2 + num <= 3000000; GroupBuild build = (num3 ? GroupMeshes.Make(group, Buckets, shape) : null); if (!num3) { Defer(group, now); } Swap(group, build); Release(); return num; } private static void Collect(CellGroup group, float now) { Included.Clear(); for (int num = group.Members.Count - 1; num >= 0; num--) { PieceEntry pieceEntry = group.Members[num]; if (!pieceEntry.Settled(now)) { group.WaitFor(pieceEntry); } else if (PartChecks.Valid(pieceEntry) || Recheck(group, pieceEntry, now)) { Included.Add(pieceEntry); } } if (group.Members.Count == 0) { CellGroups.Discard(group); } } private static bool Recheck(CellGroup group, PieceEntry member, float now) { member.SetForced(off: false); Verdict verdict = PieceInspector.Inspect(member); if (verdict == Verdict.Combine && member.Key.Equals(group.Key)) { return true; } group.Drop(member); PieceRegistry.Place(member, verdict, now); return false; } private static GroupShape Shape(bool managed) { //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_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) GroupShape result = default(GroupShape); Vector3 val = Included[0].LodPoint; Vector3 val2 = val; for (int i = 0; i < Included.Count; i++) { PieceEntry pieceEntry = Included[i]; val = Vector3.Min(val, pieceEntry.LodPoint); val2 = Vector3.Max(val2, pieceEntry.LodPoint); result.Detail = Mathf.Max(result.Detail, pieceEntry.DetailReach); result.Cull = Mathf.Max(result.Cull, pieceEntry.CullReach); } result.Center = (val + val2) * 0.5f; for (int j = 0; j < Included.Count; j++) { float radius = result.Radius; Vector3 val3 = Included[j].LodPoint - result.Center; result.Radius = Mathf.Max(radius, ((Vector3)(ref val3)).magnitude); } result.Levels = (managed ? ((!(result.Detail > 0f)) ? 1 : 2) : 0); return result; } private static int FillBuckets(Vector3 origin, int levels) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_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_0036: Unknown result type (might be due to invalid IL or missing references) Matrix4x4 toCell = Matrix4x4.Translate(-origin); int num = 0; for (int i = 0; i < Included.Count; i++) { PieceEntry pieceEntry = Included[i]; for (int j = 0; j < pieceEntry.Parts.Count; j++) { num += AddPart(pieceEntry, pieceEntry.Parts[j], toCell, levels); } } return num; } private static int AddPart(PieceEntry member, in Part part, Matrix4x4 toCell, int levels) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) MeshInfo meshInfo = RenderRules.Info(part.Mesh); Matrix4x4 transform = toCell * part.Matrix; int num = 0; for (int i = 0; i < levels; i++) { int num2 = 0; while ((part.Levels & (1 << i)) != 0 && num2 < part.MaterialCount) { Bucket bucket = BucketFor(i, member.Materials[part.MaterialStart + num2], meshInfo.Attributes, part.Look); List<CombineInstance> parts = bucket.Parts; CombineInstance item = default(CombineInstance); ((CombineInstance)(ref item)).mesh = part.Mesh; ((CombineInstance)(ref item)).subMeshIndex = num2; ((CombineInstance)(ref item)).transform = transform; parts.Add(item); bucket.Vertices += meshInfo.Vertices; num += meshInfo.Vertices; num2++; } } return num; } private static Bucket BucketFor(int level, Material material, int attributes, int look) { long key = ((long)level << 55) | ((long)(look & 0xFFFF) << 39) | ((long)attributes << 32) | (uint)((Object)material).GetInstanceID(); if (ByKey.TryGetValue(key, out var value)) { return value; } value = ((Spare.Count > 0) ? Spare.Pop() : new Bucket()); value.Level = level; value.Material = material; value.Look = look; value.Vertices = 0; ByKey.Add(key, value); Buckets.Add(value); return value; } private static void Swap(CellGroup group, GroupBuild build) { _stamp++; int num = 0; while (build != null && num < Included.Count) { Included[num].BuildStamp = _stamp; num++; } GroupBuild build2 = group.Build; group.Build = build; group.Open = false; int num2 = 0; for (int i = 0; i < group.Members.Count; i++) { PieceEntry pieceEntry = group.Members[i]; pieceEntry.InBuild = pieceEntry.BuildStamp == _stamp; pieceEntry.SetForced(pieceEntry.InBuild); num2 += (pieceEntry.InBuild ? 1 : 0); } group.Dirty = num2 < group.Members.Count; build?.SetShown(shown: true); CellGroups.Replaced(build2, build); } private static void Defer(CellGroup group, float now) { group.QuietUntil = Mathf.Max(group.QuietUntil, now + 20f); if (!_warned) { _warned = true; HighSeatPlus.Log.LogInfo((object)("Combined building meshes reached " + 3000000 + " vertices; more buildings are drawn by the game until some unload")); } } private static void Release() { for (int i = 0; i < Buckets.Count; i++) { Buckets[i].Parts.Clear(); Buckets[i].Material = null; Spare.Push(Buckets[i]); } Buckets.Clear(); ByKey.Clear(); Included.Clear(); } } internal readonly struct GroupKey : IEquatable<GroupKey> { public readonly int X; public readonly int Y; public readonly int Z; public readonly int Lod; public GroupKey(int x, int y, int z, int lod) { X = x; Y = y; Z = z; Lod = lod; } public bool Equals(GroupKey other) { if (X == other.X && Y == other.Y && Z == other.Z) { return Lod == other.Lod; } return false; } public override bool Equals(object obj) { if (obj is GroupKey other) { return Equals(other); } return false; } public override int GetHashCode() { return ((X * 73856093) ^ (Y * 19349663) ^ (Z * 83492791)) * 397 + Lod; } } internal static class GroupLod { private const float CheckSeconds = 1f; private const float ChangeShare = 0.02f; private const float DefaultFov = 65f; private const float MinHeight = 1E-05f; private static float _nextCheck; public static float K { get; private set; } public static bool Refresh(float now) { if (K > 0f && now < _nextCheck) { return false; } _nextCheck = now + 1f; Camera mainCamera = Utils.GetMainCamera(); float num = (((Object)(object)mainCamera != (Object)null) ? mainCamera.fieldOfView : 65f); float num2 = QualitySettings.lodBias / (2f * Mathf.Tan(num * 0.5f * ((float)Math.PI / 180f))); if (K > 0f && Mathf.Abs(num2 - K) <= K * 0.02f) { return false; } bool result = K > 0f; K = Mathf.Max(num2, 0.01f); return result; } public static void Fill(LOD[] lods, float detail, float cull, float radius) { float num = radius / Mathf.Max(K, 0.01f); if (lods.Length == 1) { lods[0].screenRelativeTransitionHeight = Height(cull + num, 1f); return; } float num2 = Height(detail + num, 1f); lods[0].screenRelativeTransitionHeight = num2; lods[1].screenRelativeTransitionHeight = Height(cull + num, num2); } public static void Reset() { K = 0f; _nextCheck = 0f; } private static float Height(float reach, float below) { float num = Mathf.Clamp(1f / Mathf.Max(reach, 1f), 1E-05f, 1f); if (!(num >= below)) { return num; } return below * 0.999f; } } internal sealed class Bucket { public int Level; public Material Material; public int Look; public int Vertices; public readonly List<CombineInstance> Parts = new List<CombineInstance>(); } internal static class GroupMeshes { private const int ShortIndexLimit = 65535; private const int PooledLength = 512; private const string MeshName = "HighSeatPlus combined"; private static readonly Dictionary<int, CombineInstance[]> Arrays = new Dictionary<int, CombineInstance[]>(); public static GroupBuild Make(CellGroup group, List<Bucket> buckets, GroupShape shape) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) GameObject root = GroupBuild.MakeRoot(group.Origin); List<Mesh> list = new List<Mesh>(buckets.Count); List<MeshRenderer> list2 = new List<MeshRenderer>(buckets.Count); int vertices = 0; for (int i = 0; i < buckets.Count; i++) { Mesh val = Combine(buckets[i], ref vertices); list.Add(val); list2.Add(GroupBuild.MakeRenderer(root, val, buckets[i].Material, buckets[i].Look)); } if (shape.Levels == 0) { return new GroupBuild(root, list, list2, null, null, shape, vertices); } LOD[] lods = Lods(shape.Levels, buckets, list2); LODGroup lod = AddLod(root, lods, shape); return new GroupBuild(root, list, list2, lod, lods, shape, vertices); } private static Mesh Combine(Bucket bucket, ref int vertices) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Mesh val = new Mesh { name = "HighSeatPlus combined" }; if (bucket.Vertices > 65535) { val.indexFormat = (IndexFormat)1; } CombineInstance[] array = ArrayOf(bucket.Parts.Count); bucket.Parts.CopyTo(array); val.CombineMeshes(array, true, true, false); Array.Clear(array, 0, array.Length); val.RecalculateBounds(); vertices += val.vertexCount; val.UploadMeshData(true); return val; } private static LOD[] Lods(int levels, List<Bucket> buckets, List<MeshRenderer> renderers) { //IL_0080: 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) LOD[] array = (LOD[])(object)new LOD[levels]; for (int i = 0; i < levels; i++) { int num = 0; for (int j = 0; j < buckets.Count; j++) { num += ((buckets[j].Level == i) ? 1 : 0); } Renderer[] array2 = (Renderer[])(object)new Renderer[num]; int k = 0; int num2 = 0; for (; k < buckets.Count; k++) { if (buckets[k].Level == i) { array2[num2++] = (Renderer)(object)renderers[k]; } } array[i] = new LOD(1f, array2); } return array; } private static LODGroup AddLod(GameObject root, LOD[] lods, GroupShape shape) { //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) LODGroup obj = root.AddComponent<LODGroup>(); obj.fadeMode = (LODFadeMode)0; obj.animateCrossFading = false; GroupLod.Fill(lods, shape.Detail, shape.Cull, shape.Radius); obj.SetLODs(lods); obj.localReferencePoint = root.transform.InverseTransformPoint(shape.Center); obj.size = 1f; return obj; } private static CombineInstance[] ArrayOf(int length) { if (length > 512) { return (CombineInstance[])(object)new CombineInstance[length]; } if (!Arrays.TryGetValue(length, out var value)) { value = (CombineInstance[])(object)new CombineInstance[length]; Arrays[length] = value; } return value; } } internal struct LodInfo { public float Size; public float[] Heights; } internal sealed class LodLayout { public int RendererCount; public int[] Levels = Array.Empty<int>(); public int[] Group = Array.Empty<int>(); public int[] MeshIds = Array.Empty<int>(); public LodInfo[] Groups = Array.Empty<LodInfo>(); public bool Never; } internal static class LodLayouts { public const int MaxLevels = 2; private const float MinHeight = 0.0001f; private static readonly Dictionary<int, LodLayout> Layouts = new Dictionary<int, LodLayout>(); private static readonly List<MeshRenderer> Renderers = new List<MeshRenderer>(); private static readonly List<LODGroup> Groups = new List<LODGroup>(); private static readonly Dictionary<Renderer, int> Index = new Dictionary<Renderer, int>(); public static LodLayout For(WearNTear piece) { ZDO zDO = piece.m_nview.GetZDO(); if (zDO == null) { return null; } int prefab = zDO.GetPrefab(); if (Layouts.TryGetValue(prefab, out var value)) { return value; } GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefab) : null); value = Build(((Object)(object)val != (Object)null) ? val : ((Component)piece).gameObject); Layouts[prefab] = value; return value; } public static float Reach(float worldSize, float height) { return worldSize / Mathf.Max(height, 0.0001f); } public static int MeshId(MeshRenderer renderer) { MeshFilter val = default(MeshFilter); if (!((Component)renderer).TryGetComponent<MeshFilter>(ref val) || !((Object)(object)val.sharedMesh != (Object)null)) { return 0; } return ((Object)val.sharedMesh).GetInstanceID(); } public static void Clear() { Layouts.Clear(); } private static LodLayout Build(GameObject template) { template.GetComponentsInChildren<MeshRenderer>(true, Renderers); template.GetComponentsInChildren<LODGroup>(true, Groups); int count = Renderers.Count; LodLayout lodLayout = new LodLayout { RendererCount = count, Levels = new int[count], Group = new int[count] }; lodLayout.MeshIds = new int[count]; lodLayout.Groups = new LodInfo[Groups.Count]; Index.Clear(); for (int i = 0; i < count; i++) { Index[(Renderer)(object)Renderers[i]] = i; lodLayout.Group[i] = -1; lodLayout.MeshIds[i] = MeshId(Renderers[i]); } for (int j = 0; j < Groups.Count; j++) { AddGroup(lodLayout, j, Groups[j]); } lodLayout.Never = !PieceRules.OnlySafeComponents(template); Index.Clear(); Renderers.Clear(); Groups.Clear(); return lodLayout; } private static void AddGroup(LodLayout layout, int g, LODGroup lodGroup) { LOD[] lODs = lodGroup.GetLODs(); float[] array = new float[lODs.Length]; for (int i = 0; i < lODs.Length; i++) { array[i] = lODs[i].screenRelativeTransitionHeight; Renderer[] array2 = lODs[i].renderers ?? Array.Empty<Renderer>(); for (int j = 0; j < array2.Length; j++) { Mark(layout, g, i, lODs.Length, array2[j]); } } layout.Groups[g] = new LodInfo { Size = lodGroup.size, Heights = array }; } private static void Mark(LodLayout layout, int g, int level, int levels, Renderer renderer) { if (!((Object)(object)renderer == (Object)null) && Index.TryGetValue(renderer, out var value) && layout.Levels[value] >= 0) { if (levels > 2 || (layout.Group[value] >= 0 && layout.Group[value] != g)) { layout.Levels[value] = -1; return; } layout.Group[value] = g; layout.Levels[value] |= 1 << level; } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class CombinedMeshesStart { private static void Postfix(ZNetScene __instance) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 try { if ((int)SystemInfo.graphicsDeviceType != 4) { CombinedMeshes.Attach(((Component)__instance).gameObject); } } catch (Exception ex) { HighSeatPlus.Log.LogWarning((object)("Combined building meshes could not start: " + ex.Message)); } } } [HarmonyPatch(typeof(WearNTear), "Awake")] internal static class PieceAwake { private static void Postfix(WearNTear __instance) { if (!CombinedMeshes.Active) { return; } try { PieceRegistry.Add(__instance); } catch (Exception error) { CombinedMeshes.Fail(error); } } } [HarmonyPatch(typeof(WearNTear), "OnDestroy")] internal static class PieceDestroyed { private static void Postfix(WearNTear __instance) { if (!CombinedMeshes.Active) { return; } try { PieceRegistry.Remove(__instance); } catch (Exception error) { CombinedMeshes.Fail(error); } } } [HarmonyPatch(typeof(WearNTear), "Highlight")] internal static class PieceHighlight { private static void Postfix(WearNTear __instance) { if (!CombinedMeshes.Active) { return; } try { if (PieceRegistry.TryGet(__instance, out var entry)) { PieceRegistry.Touch(entry); } } catch (Exception error) { CombinedMeshes.Fail(error); } } } [HarmonyPatch(typeof(WearNTear), "RPC_HealthChanged")] internal static class PieceHealthChanged { private static void Postfix(WearNTear __instance) { if (!CombinedMeshes.Active) { return; } try { if (PieceRegistry.TryGet(__instance, out var entry) && (!entry.InBuild || PieceRules.StateBits(__instance) != entry.StateBits)) { PieceRegistry.Touch(entry); } } catch (Exception error) { CombinedMeshes.Fail(error); } } } [HarmonyPatch(typeof(WearNTear), "SetAshlandsMaterialValue")] internal static class PieceGlow { private static void Postfix(WearNTear __instance, float v) { if (v == 0f || !CombinedMeshes.Active) { return; } try { if (PieceRegistry.TryGet(__instance, out var entry)) { PieceRegistry.Touch(entry); } } catch (Exception error) { CombinedMeshes.Fail(error); } } } [HarmonyPatch(typeof(Destructible), "CreateFragments")] internal static class PieceFragments { private static void Prefix(GameObject rootObject, ref bool visibleOnly) { if (!visibleOnly || !CombinedMeshes.Active || (Object)(object)rootObject == (Object)null) { return; } try { WearNTear piece = default(WearNTear); if (rootObject.TryGetComponent<WearNTear>(ref piece) && PieceRegistry.TryGet(piece, out var entry) && entry.Forced && entry.Group != null && entry.Group.Build != null && entry.Group.Build.Visible()) { visibleOnly = false; } } catch (Exception error) { CombinedMeshes.Fail(error); } } } internal static class PartChecks { private static readonly List<Material> Current = new List<Material>(); public static bool Valid(PieceEntry entry) { WearNTear piece = entry.Piece; if (entry.Removed || (Object)(object)piece == (Object)null || entry.Parts.Count == 0) { return false; } if (PieceRules.StateBits(piece) != entry.StateBits || PieceRules.LooksChanged(piece)) { return false; } for (int i = 0; i < entry.Parts.Count; i++) { if (!Valid(entry, piece, entry.Parts[i])) { return false; } } return true; } private static bool Valid(PieceEntry entry, WearNTear piece, in Part part) { //IL_0059: 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) MeshRenderer renderer = part.Renderer; if ((Object)(object)renderer == (Object)null || !((Renderer)renderer).enabled || ((Renderer)renderer).forceRenderingOff != entry.Forced) { return false; } if (!((Component)renderer).gameObject.activeInHierarchy || (Object)(object)part.Filter == (Object)null || part.Filter.sharedMesh != part.Mesh) { return false; } if (((Renderer)renderer).localToWorldMatrix != part.Matrix || PieceRules.ForeignBlock(piece, (Renderer)(object)renderer)) { return false; } return SameMaterials(entry, in part, renderer); } private static bool SameMaterials(PieceEntry entry, in Part part, MeshRenderer renderer) { ((Renderer)renderer).GetSharedMaterials(Current); bool flag = Current.Count == part.MaterialCount; int num = 0; while (flag && num < Current.Count) { flag = Current[num] == entry.Materials[part.MaterialStart + num]; num++; } Current.Clear(); return flag; } } internal enum Verdict { Combine, Later, Never } internal struct Part { public MeshRenderer Renderer; public MeshFilter Filter; public Mesh Mesh; public Matrix4x4 Matrix; public int Levels; public int Look; public int MaterialStart; public int MaterialCount; } internal sealed class PieceEntry { public readonly WearNTear Piece; public readonly int Id; public readonly List<Part> Parts = new List<Part>(2); public readonly List<Material> Materials = new List<Material>(2); public CellGroup Group; public int MemberIndex = -1; public GroupKey Key; public Vector3 LodPoint; public float DetailReach; public float CullReach; public int StateBits; public float TouchedAt; public float RetryAt; public int BuildStamp; public bool InBuild; public bool Forced; public bool Queued; public bool Removed; public bool LeftOut; public PieceEntry(WearNTear piece) { Piece = piece; Id = ((Object)piece).GetInstanceID(); } public bool Settled(float now) { if (now >= TouchedAt + 5f) { return now >= RetryAt; } return false; } public void SetForced(bool off) { if (Forced == off) { return; } Forced = off; for (int i = 0; i < Parts.Count; i++) { MeshRenderer renderer = Parts[i].Renderer; if ((Object)(object)renderer != (Object)null) { ((Renderer)renderer).forceRenderingOff = off; } } } } internal static class PieceInspector { private static readonly List<MeshRenderer> Renderers = new List<MeshRenderer>(); private static readonly List<LODGroup> LodGroups = new List<LODGroup>(); private static readonly List<Material> Found = new List<Material>(); private static bool _keyed; private static bool _passing; public static Verdict Inspect(PieceEntry entry) { WearNTear piece = entry.Piece; if ((Object)(object)piece == (Object)null || entry.Removed || (Object)(object)piece.m_nview == (Object)null || !piece.m_nview.IsValid()) { return Verdict.Never; } LodLayout lodLayout = LodLayouts.For(piece); if (lodLayout == null || lodLayout.Never) { return Verdict.Never; } Verdict verdict = PieceRules.CheckPiece(piece); if (verdict != Verdict.Combine) { return verdict; } return Collect(entry, piece, lodLayout); } private static Verdict Collect(PieceEntry entry, WearNTear piece, LodLayout layout) { ((Component)piece).GetComponentsInChildren<MeshRenderer>(true, Renderers); ((Component)piece).GetComponentsInChildren<LODGroup>(true, LodGroups); entry.Parts.Clear(); entry.Materials.Clear(); entry.DetailReach = 0f; entry.CullReach = 0f; _keyed = false; _passing = false; Verdict verdict = ((Renderers.Count < layout.RendererCount || LodGroups.Count < layout.Groups.Length) ? Verdict.Never : Verdict.Combine); for (int i = 0; i < layout.RendererCount; i++) { if (verdict != Verdict.Combine) { break; } verdict = AddRenderer(entry, piece, layout, i); } Renderers.Clear(); LodGroups.Clear(); return Conclude(entry, piece, verdict); } private static Verdict Conclude(PieceEntry entry, WearNTear piece, Verdict verdict) { if (verdict == Verdict.Combine && entry.Parts.Count > 0) { Finish(entry, piece); return Verdict.Combine; } entry.Parts.Clear(); entry.Materials.Clear(); if (verdict != Verdict.Combine) { return verdict; } if (!_passing) { return Verdict.Never; } return Verdict.Later; } private static Verdict AddRenderer(PieceEntry entry, WearNTear piece, LodLayout layout, int i) { MeshRenderer val = Renderers[i]; int num = layout.Levels[i]; if (!((Component)val).gameObject.activeInHierarchy) { return Verdict.Combine; } bool flag = !((Renderer)val).enabled || ((Renderer)val).forceRenderingOff || PieceRules.ForeignBlock(piece, (Renderer)(object)val); if (flag || PieceRules.IsOverlay(piece, val)) { _passing |= flag; if (num != 0) { return Verdict.Later; } return Verdict.Combine; } if (num < 0 || layout.MeshIds[i] != LodLayouts.MeshId(val)) { if (num != 0) { return Verdict.Never; } return Verdict.Combine; } if (RenderRules.Check(val, Found, out var filter) != Verdict.Combine) { if (num != 0) { return Verdict.Never; } return Verdict.Combine; } return AddPart(entry, layout, i, val, filter, num); } private static Verdict AddPart(PieceEntry entry, LodLayout layout, int i, MeshRenderer renderer, MeshFilter filter, int levels) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) int num = ((levels != 0) ? 1 : 0); if (_keyed && entry.Key.Lod != num) { return Verdict.Never; } int levels2 = ((levels == 0) ? 1 : Reaches(entry, layout, i, levels)); entry.Key = new GroupKey(0, 0, 0, num); _keyed = true; entry.Parts.Add(new Part { Renderer = renderer, Filter = filter, Mesh = filter.sharedMesh, Matrix = ((Renderer)renderer).localToWorldMatrix, Levels = levels2, Look = RenderRules.LookBits((Renderer)(object)renderer), MaterialStart = entry.Materials.Count, MaterialCount = Found.Count }); entry.Materials.AddRange(Found); return Verdict.Combine; } private static int Reaches(PieceEntry entry, LodLayout layout, int i, int levels) { //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_0032: 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_0048: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) int num = layout.Group[i]; LODGroup val = LodGroups[num]; Vector3 lossyScale = ((Component)val).transform.lossyScale; float worldSize = layout.Groups[num].Size * Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Max(Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z))); float[] heights = layout.Groups[num].Heights; if (!_keyed) { entry.LodPoint = ((Component)val).transform.TransformPoint(val.localReferencePoint); } entry.CullReach = Mathf.Max(entry.CullReach, LodLayouts.Reach(worldSize, heights[^1])); if (heights.Length == 1) { return 3; } entry.DetailReach = Mathf.Max(entry.DetailReach, LodLayouts.Reach(worldSize, heights[0])); return levels; } private static void Finish(PieceEntry entry, WearNTear piece) { //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_0026: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)piece).transform.position; if (entry.Key.Lod == 0) { entry.LodPoint = position; } float num = 16f; int x = Mathf.FloorToInt(position.x / num); int y = Mathf.FloorToInt(position.y / num); int z = Mathf.FloorToInt(position.z / num); entry.Key = new GroupKey(x, y, z, entry.Key.Lod); entry.StateBits = PieceRules.StateBits(piece); } } internal static class PieceRegistry { public const float RetrySeconds = 20f; private const int PopsPerFrame = 64; private static readonly Dictionary<int, PieceEntry> Entries = new Dictionary<int, PieceEntry>(); private static readonly Queue<PieceEntry> Pending = new Queue<PieceEntry>(); public static bool TryGet(WearNTear piece, out PieceEntry entry) { return Entries.TryGetValue(((Object)piece).GetInstanceID(), out entry); } public static void Add(WearNTear piece) { if (!((Object)(object)piece == (Object)null) && piece.m_myIndex >= 0 && !Entries.ContainsKey(((Object)piece).GetInstanceID())) { PieceEntry pieceEntry = new PieceEntry(piece); Entries.Add(pieceEntry.Id, pieceEntry); Touch(pieceEntry); } } public static void AddAll() { List<WearNTear> allInstances = WearNTear.GetAllInstances(); for (int i = 0; i < allInstances.Count; i++) { Add(allInstances[i]); } } public static void Remove(WearNTear piece) { if (Entries.TryGetValue(((Object)piece).GetInstanceID(), out var value)) { Entries.Remove(value.Id); value.Removed = true; value.Group?.Leave(value); value.SetForced(off: false); } } public static void Touch(PieceEntry entry) { entry.TouchedAt = Time.time; if (entry.Group != null) { entry.Group.Touched(entry); } else if (!entry.LeftOut) { Enqueue(entry); } } public static void ProcessPending(float now, int inspections) { for (int i = 0; i < 64; i++) { if (inspections <= 0) { break; } if (Pending.Count <= 0) { break; } PieceEntry pieceEntry = Pending.Dequeue(); pieceEntry.Queued = false; if (!pieceEntry.Removed && pieceEntry.Group == null && !pieceEntry.LeftOut) { if (!pieceEntry.Settled(now)) { Enqueue(pieceEntry); continue; } inspections--; Place(pieceEntry, PieceInspector.Inspect(pieceEntry), now); } } } public static void Place(PieceEntry entry, Verdict verdict, float now) { switch (verdict) { case Verdict.Combine: CellGroups.Join(entry, now); break; case Verdict.Never: entry.LeftOut = true; break; default: entry.RetryAt = now + 20f; Enqueue(entry); break; } } public static void Clear() { Entries.Clear(); Pending.Clear(); } private static void Enqueue(PieceEntry entry) { if (!entry.Queued && !entry.Removed) { entry.Queued = true; Pending.Enqueue(entry); } } } internal static class PieceRules { private static readonly List<Component> Components = new List<Component>(); private static readonly HashSet<Type> SafeScripts = new HashSet<Type> { typeof(ZNetView), typeof(Piece), typeof(WearNTear), typeof(Chair), typeof(Ladder), typeof(GuidePoint), typeof(StationExtension), typeof(EffectArea), typeof(HoverText), typeof(DisableInPlacementGhost), typeof(RandomPieceRotation), typeof(LodFadeInOut), typeof(AutoJumpLedge), typeof(Ledge) }; private static bool _resolved; public static Verdict CheckPiece(WearNTear piece) { if ((Object)(object)((Component)piece).transform.parent != (Object)null || !piece.m_staticPosition || Player.IsPlacementGhost(((Component)piece).gameObject)) { return Verdict.Never; } if (!LooksChanged(piece)) { return Verdict.Combine; } return Verdict.Later; } public static bool OnlySafeComponents(GameObject root) { Resolve(); WearNTear component = root.GetComponent<WearNTear>(); Transform val = (((Object)(object)component != (Object)null && (Object)(object)component.m_wet != (Object)null) ? component.m_wet.transform : null); root.GetComponentsInChildren<Component>(true, Components); bool flag = (Object)(object)component != (Object)null; for (int i = 0; i < Components.Count && flag; i++) { Component val2 = Components[i]; flag = (Object)(object)val2 != (Object)null && (Safe(val2) || ((Object)(object)val != (Object)null && val2.transform.IsChildOf(val))); } Components.Clear(); return flag; } public static bool IsOverlay(WearNTear piece, MeshRenderer renderer) { if ((Object)(object)renderer == (Object)(object)piece.m_snow || (Object)(object)renderer == (Object)(object)piece.m_snowWorn || (Object)(object)renderer == (Object)(object)piece.m_snowBroken) { return true; } if ((Object)(object)piece.m_wet != (Object)null && ((Component)renderer).transform.IsChildOf(piece.m_wet.transform)) { return true; } if (piece.m_nonSolidRenderers != null) { return piece.m_nonSolidRenderers.Contains((Renderer)(object)renderer); } return false; } public static int StateBits(WearNTear piece) { int num = 0; if ((Object)(object)piece.m_new != (Object)null && piece.m_new.activeSelf) { num |= 1; } if ((Object)(object)piece.m_worn != (Object)null && piece.m_worn.activeSelf) { num |= 2; } if ((Object)(object)piece.m_broken != (Object)null && piece.m_broken.activeSelf) { num |= 4; } return num; } public static bool LooksChanged(WearNTear piece) { MaterialMan instance = MaterialMan.instance; if ((Object)(object)instance == (Object)null || !instance.m_blocks.TryGetValue(((Object)((Component)piece).gameObject).GetInstanceID(), out var value)) { return false; } foreach (KeyValuePair<int, ShaderPropertyBase> shaderProperty in value.m_shaderProperties) { if (shaderProperty.Key != WearNTear.s_AshlandsDamageShaderID || !(shaderProperty.Value is ShaderProperty<float> val) || val.Get() != 0f) { return true; } } return false; } public static bool ForeignBlock(WearNTear piece, Renderer renderer) { if (!renderer.HasPropertyBlock()) { return false; } MaterialMan instance = MaterialMan.instance; if (!((Object)(object)instance == (Object)null)) { return !instance.m_blocks.ContainsKey(((Object)((Component)piece).gameObject).GetInstanceID()); } return true; } private static bool Safe(Component component) { if (component is Transform || component is MeshFilter || component is MeshRenderer || component is LODGroup || component is Collider) { return true; } return SafeScripts.Contains(((object)component).GetType()); } private static void Resolve() { if (!_resolved) { _resolved = true; Type type = Type.GetType("SimpleMeshCombine, assembly_simplemeshcombine", throwOnError: false); if (type != null) { SafeScripts.Add(type); } } } } internal sealed class MeshInfo { public bool Fits; public int Attributes; public int Vertices; public int SubMeshes; } internal static class RenderRules { private const int MaxOpaqueQueue = 2450; private static readonly HashSet<string> Shaders = new HashSet<string> { "Custom/Piece", "Custom/StaticRock", "Standard" }; private static readonly int MoveableObject = Shader.PropertyToID("_MoveableObject"); private static readonly int TriplanarLocal = Shader.PropertyToID("_TriplanarLocalPos"); private static readonly VertexAttribute[] Channels; private static readonly Dictionary<int, bool> MaterialFits; private static readonly Dictionary<int, MeshInfo> MeshInfos; public static Verdict Check(MeshRenderer renderer, List<Material> materials, out MeshFilter filter) { //IL_0070: 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) if (!((Component)renderer).TryGetComponent<MeshFilter>(ref filter) || (Object)(object)filter.sharedMesh == (Object)null) { return Verdict.Never; } MeshInfo meshInfo = Info(filter.sharedMesh); ((Renderer)renderer).GetSharedMaterials(materials); if (!meshInfo.Fits || materials.Count != meshInfo.SubMeshes || !SettingsFit((Renderer)(object)renderer)) { return Verdict.Never; } for (int i = 0; i < materials.Count; i++) { if (!Fits(materials[i])) { return Verdict.Never; } } Matrix4x4 localToWorldMatrix = ((Renderer)renderer).localToWorldMatrix; if (!(((Matrix4x4)(ref localToWorldMatrix)).determinant > 0f)) { return Verdict.Never; } return Verdict.Combine; } public static MeshInfo Info(Mesh mesh) { int instanceID = ((Object)mesh).GetInstanceID(); if (MeshInfos.TryGetValue(instanceID, out var value)) { return value; } value = new MeshInfo { Fits = (mesh.isReadable && AllTriangles(mesh)), Attributes = AttributeBits(mesh), Vertices = mesh.vertexCount, SubMeshes = mesh.subMeshCount }; MeshInfos[instanceID] = value; return value; } public static int LookBits(Renderer renderer) { //IL_000c: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_0031: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_004b: Expected I4, but got Unknown return (int)(((Component)renderer).gameObject.layer | (renderer.shadowCastingMode << 5) | ((renderer.receiveShadows ? 1u : 0u) << 7) | (renderer.lightProbeUsage << 8) | (renderer.reflectionProbeUsage << 11) | (renderer.motionVectorGenerationMode << 13) | ((renderer.allowOcclusionWhenDynamic ? 1u : 0u) << 15)); } public static void Apply(MeshRenderer renderer, int bits) { ((Component)renderer).gameObject.layer = bits & 0x1F; ((Renderer)renderer).shadowCastingMode = (ShadowCastingMode)((bits >> 5) & 3); ((Renderer)renderer).receiveShadows = ((bits >> 7) & 1) != 0; ((Renderer)renderer).lightProbeUsage = (LightProbeUsage)((bits >> 8) & 7); ((Renderer)renderer).reflectionProbeUsage = (ReflectionProbeUsage)((bits >> 11) & 3); ((Renderer)renderer).motionVectorGenerationMode = (MotionVectorGenerationMode)((bits >> 13) & 3); ((Renderer)renderer).allowOcclusionWhenDynamic = ((bits >> 15) & 1) != 0; } public static void Clear() { MaterialFits.Clear(); MeshInfos.Clear(); } private static bool SettingsFit(Renderer renderer) { //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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 LightProbeUsage lightProbeUsage = renderer.lightProbeUsage; if ((int)lightProbeUsage != 2) { return (int)lightProbeUsage != 4; } return false; } private static bool Fits(Material material) { if ((Object)(object)material == (Object)null) { return false; } int instanceID = ((Object)material).GetInstanceID(); if (!MaterialFits.TryGetValue(instanceID, out var value)) { value = Decide(material); MaterialFits[instanceID] = value; } return value; } private static bool Decide(Material material) { Shader shader = material.shader; if ((Object)(object)shader == (Object)null || !Shaders.Contains(((Object)shader).name) || material.renderQueue > 2450) { return false; } if (Off(material, MoveableObject)) { return Off(material, TriplanarLocal); } return false; } private static bool Off(Material material, int property) { if (material.HasProperty(property)) { return material.GetFloat(property) == 0f; } return true; } private static bool AllTriangles(Mesh mesh) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < mesh.subMeshCount; i++) { if ((int)mesh.GetTopology(i) != 0) { return false; } } return true; } private static int AttributeBits(Mesh mesh) { int num = 0; for (int i = 0; i < Channels.Length; i++) { if (mesh.HasVertexAttribute(Channels[i])) { num |= 1 << i; } } return num; } static RenderRules() { VertexAttribute[] array = new VertexAttribute[7]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); Channels = (VertexAttribute[])(object)array; MaterialFits = new Dictionary<i