Decompiled source of PUP FPS v1.0.30

PUP_FPS.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public sealed class ServerZoneStreamBlock : MonoBehaviour
{
	private const string Id = "com.pup.instancecombiner.serverstream";

	private const int Vanilla = 10240;

	private static ConfigEntry<bool> enabledSetting;

	private static bool active;

	private static int limit = 10240;

	private static int extraObjects;

	private static long started;

	private static long extraStarted;

	private static double cooldown;

	private Harmony harmony;

	private bool initialized;

	private ManualLogSource Logger;

	private static double Seconds => (double)Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;

	public void Setup(ConfigFile config, ManualLogSource logger)
	{
		Logger = logger;
		enabledSetting = config.Bind<bool>("ServerStreaming", "Enabled", true, "Enable bounded dedicated-server ZDO packet growth. False restores vanilla packet size.");
	}

	private void Initialize()
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected O, but got Unknown
		//IL_0057: 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_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Expected O, but got Unknown
		//IL_00a1: Expected O, but got Unknown
		//IL_00a1: Expected O, but got Unknown
		//IL_00a1: Expected O, but got Unknown
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Expected O, but got Unknown
		//IL_0104: Expected O, but got Unknown
		//IL_0104: Expected O, but got Unknown
		initialized = true;
		if (!ZNet.instance.IsDedicated())
		{
			((Behaviour)this).enabled = false;
			return;
		}
		harmony = new Harmony("com.pup.instancecombiner.serverstream");
		try
		{
			harmony.Patch((MethodBase)AccessTools.Method(typeof(ZDOMan), "SendZDOs", (Type[])null, (Type[])null), new HarmonyMethod(typeof(ServerZoneStreamBlock), "Before", (Type[])null), new HarmonyMethod(typeof(ServerZoneStreamBlock), "After", (Type[])null), new HarmonyMethod(typeof(ServerZoneStreamBlock), "Rewrite", (Type[])null), new HarmonyMethod(typeof(ServerZoneStreamBlock), "Finish", (Type[])null), (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(ZDOMan), "AddForceSendZdos", (Type[])null, (Type[])null), new HarmonyMethod(typeof(ServerZoneStreamBlock), "BeforeForcedBatch", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(ServerZoneStreamBlock), "RewriteForcedBatch", (Type[])null), new HarmonyMethod(typeof(ServerZoneStreamBlock), "FinishForcedBatch", (Type[])null), (HarmonyMethod)null);
		}
		catch (Exception)
		{
			harmony.UnpatchSelf();
			((Behaviour)this).enabled = false;
		}
	}

	private static void Before(bool __1)
	{
		started = Stopwatch.GetTimestamp();
		extraStarted = 0L;
		extraObjects = 0;
		active = enabledSetting.Value && !__1 && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer();
		if (!active || Seconds < cooldown || Time.unscaledDeltaTime > 0.04f)
		{
			limit = 10240;
		}
	}

	private static int PayloadLimit()
	{
		if (!active)
		{
			return 10240;
		}
		return limit;
	}

	private static int CheckedSize(ZPackage package)
	{
		int num = package.Size();
		if (!active || limit <= 10240 || num <= 10240)
		{
			return num;
		}
		long timestamp = Stopwatch.GetTimestamp();
		if (extraStarted == 0L)
		{
			extraStarted = timestamp;
		}
		double num2 = (double)(timestamp - extraStarted) * 1000.0 / (double)Stopwatch.Frequency;
		double num3 = (double)(timestamp - started) * 1000.0 / (double)Stopwatch.Frequency;
		if (extraObjects >= 32 || num2 >= 1.0 || num3 >= 25.0)
		{
			return limit + 1;
		}
		extraObjects++;
		return num;
	}

	private static void After()
	{
		if (active)
		{
			double num = (double)(Stopwatch.GetTimestamp() - started) * 1000.0 / (double)Stopwatch.Frequency;
			if (num >= 25.0 || Time.unscaledDeltaTime > 0.04f)
			{
				limit = 10240;
				cooldown = Seconds + 2.0;
			}
			else if (Seconds >= cooldown && num < 15.0)
			{
				limit = Math.Min(20480, limit + 1024);
			}
		}
	}

	private static Exception Finish(Exception __exception)
	{
		active = false;
		return __exception;
	}

	private static void BeforeForcedBatch(List<ZDO> __1, out int __state)
	{
		__state = __1?.Count ?? (-1);
	}

	private static void AppendForcedZdo(List<ZDO> list, int index, ZDO zdo)
	{
		list.Add(zdo);
	}

	private static void RestoreForcedOrder(List<ZDO> list, int originalCount)
	{
		if (list != null && originalCount >= 0 && list.Count > originalCount)
		{
			list.Reverse(0, originalCount);
			list.Reverse();
		}
	}

	private static Exception FinishForcedBatch(List<ZDO> __1, int __state, Exception __exception)
	{
		RestoreForcedOrder(__1, __state);
		return __exception;
	}

	private static IEnumerable<CodeInstruction> RewriteForcedBatch(IEnumerable<CodeInstruction> source)
	{
		List<CodeInstruction> list = source.ToList();
		MethodInfo insert = AccessTools.Method(typeof(List<ZDO>), "Insert", (Type[])null, (Type[])null);
		var array = (from x in list.Select((CodeInstruction c, int i) => new { c, i })
			where CodeInstructionExtensions.Calls(x.c, insert)
			select x).ToArray();
		if (array.Length != 1 || array[0].i < 2 || list[array[0].i - 2].opcode != OpCodes.Ldc_I4_0)
		{
			throw new InvalidOperationException("Unexpected AddForceSendZdos IL; original behavior retained");
		}
		array[0].c.opcode = OpCodes.Call;
		array[0].c.operand = AccessTools.Method(typeof(ServerZoneStreamBlock), "AppendForcedZdo", (Type[])null, (Type[])null);
		return list;
	}

	private static IEnumerable<CodeInstruction> Rewrite(IEnumerable<CodeInstruction> source)
	{
		List<CodeInstruction> list = source.ToList();
		var array = (from x in list.Select((CodeInstruction c, int i) => new { c, i })
			where x.c.opcode == OpCodes.Ldc_I4 && object.Equals(x.c.operand, 10240)
			select x).ToArray();
		var array2 = (from x in list.Select((CodeInstruction c, int i) => new { c, i })
			where CodeInstructionExtensions.Calls(x.c, AccessTools.Method(typeof(ZPackage), "Size", (Type[])null, (Type[])null))
			select x).ToArray();
		if (array.Length != 2 || array2.Length != 1 || list[array[1].i + 1].opcode != OpCodes.Ldloc_0 || list[array[1].i + 2].opcode != OpCodes.Sub || list[array2[0].i + 1].opcode != OpCodes.Ldloc_1 || (list[array2[0].i + 2].opcode != OpCodes.Ble_S && list[array2[0].i + 2].opcode != OpCodes.Ble))
		{
			throw new InvalidOperationException("Unexpected SendZDOs IL; original behavior retained");
		}
		array[1].c.opcode = OpCodes.Call;
		array[1].c.operand = AccessTools.Method(typeof(ServerZoneStreamBlock), "PayloadLimit", (Type[])null, (Type[])null);
		array2[0].c.opcode = OpCodes.Call;
		array2[0].c.operand = AccessTools.Method(typeof(ServerZoneStreamBlock), "CheckedSize", (Type[])null, (Type[])null);
		return list;
	}

	private void Update()
	{
		if (!initialized && (Object)(object)ZNet.instance != (Object)null)
		{
			Initialize();
		}
	}

	private void OnDestroy()
	{
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
	}
}
namespace ValheimInstanceCombiner
{
	[BepInPlugin("com.pup.instancecombiner.safe", "PUP Safe Building Combiner", "1.0.30")]
	public class InstanceCombinerMod : BaseUnityPlugin
	{
		private sealed class GpuDrawGroup
		{
			public Mesh mesh;

			public int subMesh;

			public Material material;

			public readonly HashSet<string> stableIds = new HashSet<string>(StringComparer.Ordinal);

			public bool usesTessellation;

			public bool tessellationEnabled = true;

			public Bounds worldBounds;

			public bool hasWorldBounds;

			public bool cameraVisible = true;

			public readonly List<Matrix4x4[]> chunks = new List<Matrix4x4[]>();
		}

		private sealed class RawGpuGroup
		{
			public string meshName;

			public int vertexCount;

			public int subMeshCount;

			public Vector3 boundsSize;

			public int subMesh;

			public string materialName;

			public readonly List<Matrix4x4[]> chunks = new List<Matrix4x4[]>();
		}

		private sealed class RawGpuCache
		{
			public bool fullVisual;

			public readonly List<RawGpuGroup> groups = new List<RawGpuGroup>();
		}

		private sealed class RawMeshData
		{
			public Vector3[] vertices;

			public Vector3[] normals;

			public Vector4[] tangents;

			public Vector2[] uv;

			public int[][] triangles;
		}

		private sealed class RawSubCluster
		{
			public RawMeshData mesh;

			public string[] materialNames;

			public readonly List<CachedColliderData> colliders = new List<CachedColliderData>();
		}

		private sealed class PreparedSubCluster
		{
			public SubClusterCacheEntry entry;

			public RawSubCluster raw;

			public long sourceBytes;
		}

		private sealed class BakedRecord
		{
			public string customId;

			public long userId;

			public uint id;

			public int prefabHash;

			public Vector3 position;

			public Quaternion rotation;

			public Vector3 scale;
		}

		private sealed class CachedColliderData
		{
			public int subX = -1;

			public int subZ = -1;

			public int colliderIndex = -1;

			public byte type;

			public int layer;

			public Vector3 position;

			public Quaternion rotation;

			public Vector3 scale;

			public bool trigger;

			public Vector3 center;

			public Vector3 size;

			public float radius;

			public float height;

			public int direction;

			public bool convex;

			public string meshName;

			public Mesh mesh;

			public RawMeshData rawMesh;
		}

		private sealed class PendingCollider
		{
			public Vector2Int cell;

			public GameObject root;

			public CachedColliderData data;
		}

		private sealed class SubClusterCacheEntry
		{
			public int x;

			public int z;

			public string name;

			public string fileName;
		}

		private sealed class MaterialCombineGroup
		{
			public Material source;

			public readonly List<CombineInstance> parts = new List<CombineInstance>();
		}

		[HarmonyPatch(typeof(Player), "OnSpawned")]
		private static class PlayerSpawnPatch
		{
			private static void Postfix()
			{
				InstanceCombinerMod instanceCombinerMod = Object.FindFirstObjectByType<InstanceCombinerMod>();
				if ((Object)(object)instanceCombinerMod != (Object)null)
				{
					instanceCombinerMod.LoadState();
					instanceCombinerMod.BeginSinglePlayerFastInitialLoad();
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "LoadWorld")]
		private static class SinglePlayerWorldLoadIndexPatch
		{
			private static void Postfix()
			{
				if ((Object)(object)Instance != (Object)null && (Object)(object)ZNet.instance != (Object)null && ZNet.IsSinglePlayer)
				{
					Instance.PrepareSinglePlayerStableIndexDuringWorldLoad();
					Instance.LoadState();
					Instance.BeginSinglePlayerFastWorldLoadPrewarm();
				}
			}
		}

		[HarmonyPatch(typeof(Player), "TeleportTo")]
		private static class PortalDestinationPrewarmPatch
		{
			private static void Postfix(Vector3 pos, bool distantTeleport, bool __result)
			{
				//IL_0017: 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 (__result && distantTeleport && (Object)(object)Instance != (Object)null)
				{
					Instance.BeginSinglePlayerFastPortal(pos);
					Instance.PrewarmRemotePortalDestination(pos);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateTeleport")]
		private static class SinglePlayerPortalArrivalPatch
		{
			private static void Prefix(Player __instance, out bool __state)
			{
				__state = (Object)(object)__instance != (Object)null && ((Character)__instance).IsTeleporting();
			}

			private static void Postfix(Player __instance, bool __state)
			{
				if (__state && (Object)(object)__instance != (Object)null && !((Character)__instance).IsTeleporting() && (Object)(object)Instance != (Object)null)
				{
					Instance.FinishSinglePlayerPortalCurtain();
				}
			}
		}

		[HarmonyPatch(typeof(Hud), "UpdateBlackScreen")]
		private static class SinglePlayerPortalCurtainPatch
		{
			private static void Postfix(Hud __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && !((Object)(object)Instance == (Object)null) && (Instance.ShouldHoldSinglePlayerPortalCurtain() | Instance.ShouldHoldRemotePortalCurtain()))
				{
					object? obj = AccessTools.Field(typeof(Hud), "m_loadingScreen")?.GetValue(__instance);
					Component val = (Component)((obj is Component) ? obj : null);
					if (!((Object)(object)val == (Object)null))
					{
						val.gameObject.SetActive(true);
						AccessTools.Property(((object)val).GetType(), "alpha")?.SetValue(val, 1f, null);
					}
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "Shutdown")]
		private static class MultiplayerClientShutdownPatch
		{
			private static void Prefix()
			{
				if ((Object)(object)Instance != (Object)null)
				{
					Instance.BeginMultiplayerClientShutdown();
				}
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "CreateObject")]
		private static class HideBakedObjectAtCreationPatch
		{
			private static bool Prefix(ZDO zdo, ref GameObject __result)
			{
				if ((Object)(object)Instance == (Object)null || !Instance.TrySuppressRemoteOriginalCreation(zdo))
				{
					return true;
				}
				__result = null;
				return false;
			}

			private static void Postfix(ZDO zdo, GameObject __result)
			{
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: Unknown result type (might be due to invalid IL or missing references)
				if (((Object)(object)Instance != (Object)null && Instance.TryUnloadRemoteOriginalAtCreation(zdo, __result)) || (Object)(object)Instance == (Object)null || zdo == null || (Object)(object)__result == (Object)null || !zdo.GetBool(BakedKey, false))
				{
					return;
				}
				Vector2Int item = default(Vector2Int);
				((Vector2Int)(ref item))..ctor(zdo.GetInt(CellXKey, int.MinValue), zdo.GetInt(CellZKey, int.MinValue));
				if (Instance.gpuCacheReadyCells.Contains(item) && !Instance.suppressedVisualCells.Contains(item))
				{
					ZNetView component = __result.GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null)
					{
						Instance.HideOriginalRenderers(component);
					}
				}
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "IsAreaReady")]
		private static class RemoteAreaReadyPatch
		{
			private static void Postfix(Vector3 point, ref bool __result)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				if (!__result && (Object)(object)Instance != (Object)null && Instance.IsRemoteAreaReadyIgnoringSuppressed(point))
				{
					__result = true;
				}
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "AddInstance")]
		private static class HideBakedObjectAtAddInstancePatch
		{
			private static void Postfix(ZDO zdo, ZNetView nview)
			{
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				Instance?.ObserveRestoreSupportView(zdo, nview);
				if (!((Object)(object)Instance == (Object)null) && zdo != null && !((Object)(object)nview == (Object)null) && zdo.GetBool(BakedKey, false))
				{
					Vector2Int item = default(Vector2Int);
					((Vector2Int)(ref item))..ctor(zdo.GetInt(CellXKey, int.MinValue), zdo.GetInt(CellZKey, int.MinValue));
					if (Instance.gpuCacheReadyCells.Contains(item) && !Instance.suppressedVisualCells.Contains(item))
					{
						Instance.HideOriginalRenderers(nview);
					}
				}
			}
		}

		[HarmonyPatch(typeof(WearNTear), "UpdateSupport")]
		private static class WearNTearSupportPatch
		{
			private static bool Prefix(WearNTear __instance, out float __state)
			{
				__state = (((Object)(object)Instance != (Object)null && WearSupportField != null) ? ((float)WearSupportField.GetValue(__instance)) : (-1f));
				if (!((Object)(object)Instance == (Object)null))
				{
					if (!Instance.ShouldBlockSupportUpdate())
					{
						return !Instance.IsRestoreSupportBlocked(__instance);
					}
					return false;
				}
				return true;
			}

			private static void Postfix(WearNTear __instance, float __state)
			{
				if ((Object)(object)Instance != (Object)null)
				{
					Instance.PreserveDependentSupport(__instance, __state);
				}
			}
		}

		[HarmonyPatch(typeof(WearNTear), "UpdateWear")]
		private static class WearNTearWearPatch
		{
			private static bool Prefix(WearNTear __instance)
			{
				if (!((Object)(object)Instance == (Object)null))
				{
					if (!Instance.ShouldBlockSupportUpdate())
					{
						return !Instance.IsRestoreSupportBlocked(__instance);
					}
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(ZNet), "SaveWorld")]
		private static class ZNetSaveWorldPatch
		{
			private static void Prefix()
			{
				if ((Object)(object)Instance != (Object)null)
				{
					Instance.BeforeVanillaWorldSave();
				}
			}
		}

		private sealed class DedicatedBakeTarget
		{
			public long userId;

			public uint id;

			public int prefabHash;

			public Vector3 position;
		}

		private sealed class RemoteVisualHandoff
		{
			public ZDOID id;

			public MeshRenderer[] allRenderers;

			public List<MeshRenderer> enabledRenderers;

			public LODGroup[] allLodGroups;

			public List<LODGroup> enabledLodGroups;
		}

		private sealed class RemoteProvisionalVisualPublication
		{
			public GameObject root;

			public List<GpuDrawGroup> groups;

			public List<RemoteVisualHandoff> originals;

			public int queuedFrame;
		}

		private sealed class IncomingRecordTransfer
		{
			public Vector2Int cell;

			public string cacheId;

			public int total;

			public readonly List<BakedRecord> records = new List<BakedRecord>();
		}

		private sealed class RemoteCellManifest
		{
			public Vector2Int cell;

			public string cacheId;

			public int recordCount;

			public ulong fingerprint;
		}

		private sealed class IncomingFile
		{
			public string name;

			public long length;

			public string sha256;

			public long received;
		}

		private sealed class IncomingCellTransfer
		{
			public Vector2Int cell;

			public string cacheId;

			public float lastActivity;

			public readonly Dictionary<string, IncomingFile> files = new Dictionary<string, IncomingFile>(StringComparer.OrdinalIgnoreCase);
		}

		private sealed class RemoteFinalVisualHandoff
		{
			public GameObject root;

			public List<GpuDrawGroup> groups;

			public GameObject previousRoot;

			public List<GpuDrawGroup> previousGroups;

			public int queuedFrame;

			public float queuedTime;
		}

		private sealed class RestoreLookup
		{
			internal readonly Dictionary<string, List<ZDO>> stable = new Dictionary<string, List<ZDO>>(StringComparer.Ordinal);

			internal readonly Dictionary<string, List<ZDO>> positions = new Dictionary<string, List<ZDO>>(StringComparer.Ordinal);

			internal readonly Dictionary<Vector2Int, Dictionary<ZDOID, ZDO>> parked = new Dictionary<Vector2Int, Dictionary<ZDOID, ZDO>>();
		}

		[HarmonyPatch(typeof(ZDO), "InternalSetPosition")]
		private static class RestoreSectorAfterPositionPatch
		{
			private static void Postfix(ZDO __instance)
			{
				if ((Object)(object)Instance != (Object)null && Instance.IsMultiplayerGuest())
				{
					Instance.RepairRestoredZdoSector(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(ZDOMan), "RPC_ZDOData")]
		private static class RestoreSectorAfterPacketPatch
		{
			private static void Prefix(ZPackage pkg, out List<KeyValuePair<ZDOID, string>> __state)
			{
				__state = (((Object)(object)Instance != (Object)null && Instance.IsMultiplayerGuest() && ZDOMan.instance != null) ? Instance.CaptureRestoreSectorCandidates(pkg) : null);
			}

			private static void Postfix(List<KeyValuePair<ZDOID, string>> __state)
			{
				if ((Object)(object)Instance != (Object)null && Instance.IsMultiplayerGuest())
				{
					Instance.RepairReceivedRestoreSectors(__state);
				}
			}
		}

		private sealed class RestoreSupportCell
		{
			internal List<BakedRecord> pending;

			internal List<BakedRecord> materialized = new List<BakedRecord>();

			internal float readyAfter;

			internal bool visualCover;

			internal HashSet<string> identities;
		}

		private sealed class FastColliderCellState
		{
			public string directory;

			public string cacheId;

			public GameObject root;

			public List<Mesh> owned;

			public readonly List<SubClusterCacheEntry> pending = new List<SubClusterCacheEntry>();
		}

		private sealed class PreparedGpuRead
		{
			public string cacheId;

			public ulong fingerprint;

			public Task<RawGpuCache> task;
		}

		internal static InstanceCombinerMod Instance;

		private const float CellSize = 64f;

		private const float ParkingCoordinate = 1900000f;

		private const string CacheSchema = "c14";

		private const string StateHeader = "PUP_SAFE|11|64|STABLE_OBJECT_ID|CACHE_ID|TRANSACTIONAL|MODE_ISOLATED";

		private const string LegacyStateHeader = "PUP_SAFE|8|64|GRAUSTEN|SUBCLUSTER16|CUSTOM_ID";

		private readonly Harmony harmony = new Harmony("com.pup.instancecombiner.safe");

		private static readonly FieldInfo WearSupportField = AccessTools.Field(typeof(WearNTear), "m_support");

		private readonly Dictionary<Vector2Int, GameObject> clusters = new Dictionary<Vector2Int, GameObject>();

		private readonly Dictionary<Vector2Int, List<Mesh>> generatedMeshes = new Dictionary<Vector2Int, List<Mesh>>();

		private readonly Dictionary<Vector2Int, List<BakedRecord>> records = new Dictionary<Vector2Int, List<BakedRecord>>();

		private readonly Dictionary<Vector2Int, string> cacheIds = new Dictionary<Vector2Int, string>();

		private readonly Dictionary<string, Material> materialCopies = new Dictionary<string, Material>(StringComparer.Ordinal);

		private readonly HashSet<Vector2Int> failedCacheCells = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> staleCleanupPending = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> pendingWorldSaveRestores = new HashSet<Vector2Int>();

		private const string RestorePendingCacheId = "RESTORE_PENDING";

		private readonly Dictionary<Vector2Int, HashSet<ZDOID>> pendingRestoredInstances = new Dictionary<Vector2Int, HashSet<ZDOID>>();

		private readonly Dictionary<ZDOID, List<MeshRenderer>> hiddenRenderers = new Dictionary<ZDOID, List<MeshRenderer>>();

		private readonly Dictionary<ZDOID, List<LODGroup>> hiddenLodGroups = new Dictionary<ZDOID, List<LODGroup>>();

		private static Dictionary<string, Mesh> meshAssetCache;

		private static Dictionary<string, Material> materialAssetCache;

		private static Dictionary<string, (Mesh mesh, Material material)> gpuSourceCache;

		private static bool gpuSourceCacheBuilding;

		private readonly HashSet<Vector2Int> gpuCacheReadyCells = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> suppressedVisualCells = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> startupVisualBatchCells = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> warmingStartupCells = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> revealedStartupCells = new HashSet<Vector2Int>();

		private bool startupVisualBatchRevealed;

		private bool visualWarmupRunning;

		private readonly HashSet<Vector2Int> loadingCells = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> singlePlayerFullGpuCells = new HashSet<Vector2Int>();

		private readonly Dictionary<Vector2Int, bool> colliderCellActive = new Dictionary<Vector2Int, bool>();

		private readonly Dictionary<Vector2Int, HashSet<string>> protectedSupportColliders = new Dictionary<Vector2Int, HashSet<string>>();

		private Vector3 previousPlayerPosition;

		private Vector3 smoothedTravelDirection;

		private float nextColliderActivationCheck;

		private const float ColliderEnableRadius = 80f;

		private const float ColliderDisableRadius = 96f;

		private const float ColliderPreloadSeconds = 2f;

		private const double MainThreadLoadBudgetMs = 2.0;

		private const double ColliderLoadBudgetMs = 1.0;

		private const float SupportGuardGraceSeconds = 10f;

		private bool processing;

		private bool highlightEnabled;

		private readonly HashSet<Vector2Int> highlightSuppressedCells = new HashSet<Vector2Int>();

		private bool cacheLoadingProgressActive;

		private bool cacheLoadingProgressVisible;

		private float cacheLoadingProgressStarted;

		private int cacheLoadingProgressCompleted;

		private int cacheLoadingProgressTotal;

		private readonly HashSet<Vector2Int> multiplayerStartupProgressCells = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> multiplayerStartupReadyCells = new HashSet<Vector2Int>();

		private bool multiplayerStartupProgressCaptured;

		private bool multiplayerStartupProgressCompleted;

		private GUIStyle cacheLoadingProgressStyle;

		private GUIStyle cacheLoadingProgressShadowStyle;

		private string worldName = "";

		private long worldUid;

		private readonly Dictionary<int, Material> highlightMaterials = new Dictionary<int, Material>();

		private readonly Dictionary<MeshRenderer, Material[]> highlightedClusterMaterials = new Dictionary<MeshRenderer, Material[]>();

		private float nextCellCheck;

		private int activeColliderLoads;

		private int pendingSubClusterLoads;

		private readonly SortedDictionary<int, Queue<PendingCollider>> pendingColliders = new SortedDictionary<int, Queue<PendingCollider>>();

		private int queuedColliderCount;

		private int loadedQueuedColliders;

		private float supportGuardUntil;

		private ZNet loadedZNet;

		private ZDOMan stableZdoIndexOwner;

		private long stableZdoIndexWorldUid;

		private Dictionary<string, List<ZDO>> stableZdoIndexCache;

		private bool safeSaveRestoreInProgress;

		private bool applicationQuitting;

		private readonly Dictionary<Vector2Int, List<GpuDrawGroup>> gpuBakedGroups = new Dictionary<Vector2Int, List<GpuDrawGroup>>();

		private readonly HashSet<Material> retiredGpuMaterials = new HashSet<Material>();

		private readonly Dictionary<Vector2Int, List<MeshRenderer>> gpuClusterHidden = new Dictionary<Vector2Int, List<MeshRenderer>>();

		private readonly Dictionary<Vector2Int, List<MeshRenderer>> precipitationRenderers = new Dictionary<Vector2Int, List<MeshRenderer>>();

		private readonly Dictionary<MeshRenderer, bool> skyAlphaPreviousEnabled = new Dictionary<MeshRenderer, bool>();

		private readonly Dictionary<MeshRenderer, int> skyAlphaPreviousLayer = new Dictionary<MeshRenderer, int>();

		private readonly Dictionary<MeshRenderer, ShadowCastingMode> skyAlphaPreviousShadowMode = new Dictionary<MeshRenderer, ShadowCastingMode>();

		private Mesh singlePlayerPrecipitationCubeMesh;

		private readonly Plane[] gpuFrustumPlanes = (Plane[])(object)new Plane[6];

		private readonly Dictionary<Vector2Int, Bounds> gpuCellWorldBounds = new Dictionary<Vector2Int, Bounds>();

		private readonly Dictionary<Vector2Int, bool> gpuCellCameraVisible = new Dictionary<Vector2Int, bool>();

		private Camera gpuCullCamera;

		private Vector3 gpuCullCameraPosition;

		private Quaternion gpuCullCameraRotation;

		private float gpuCullCameraFieldOfView;

		private float gpuCullCameraAspect;

		private bool gpuCullVisibilityDirty = true;

		private static readonly FieldInfo ZNetSceneInstancesField = typeof(ZNetScene).GetField("m_instances", BindingFlags.Instance | BindingFlags.NonPublic);

		private const string MultiplayerProtocol = "PUP_MP_7";

		private const string MultiplayerVersion = "1.0.29";

		private const string MultiplayerClientCacheHeader = "PUP_MP_CLIENT_RECORDS_3";

		private const int MultiplayerRecordBatchSize = 512;

		private const string MetadataAckName = "__PUP_METADATA_READY__";

		private const int MultiplayerChunkSize = 8192;

		private const float MultiplayerRequestRadius = 192f;

		private const float MultiplayerChunkAckTimeout = 15f;

		private const float MultiplayerReceiveTimeout = 60f;

		private const float MultiplayerHandshakeTimeout = 30f;

		private const string RpcHello = "PUP_FPS_MP_HELLO";

		private const string RpcReject = "PUP_FPS_MP_REJECT";

		private const string RpcManifest = "PUP_FPS_MP_MANIFEST";

		private const string RpcRequestCell = "PUP_FPS_MP_REQUEST_CELL";

		private const string RpcCellFiles = "PUP_FPS_MP_CELL_FILES";

		private const string RpcCellChunk = "PUP_FPS_MP_CELL_CHUNK";

		private const string RpcCellAck = "PUP_FPS_MP_CELL_ACK";

		private const string RpcCellRemoved = "PUP_FPS_MP_CELL_REMOVED";

		private const string RpcCellRecords = "PUP_FPS_MP_CELL_RECORDS";

		private const string RpcRecordAck = "PUP_FPS_MP_RECORD_ACK";

		private const string RpcAdminCommand = "PUP_FPS_ADMIN_COMMAND";

		private const string RpcAdminResult = "PUP_FPS_ADMIN_RESULT";

		private const string RpcAdminHighlight = "PUP_FPS_ADMIN_HIGHLIGHT";

		private const string RpcRestoreAck = "PUP_FPS_MP_RESTORE_ACK";

		private const string RpcRestoreProgress = "PUP_FPS_MP_RESTORE_PROGRESS";

		private const string RpcBakeReady = "PUP_FPS_MP_BAKE_READY";

		private ZRoutedRpc multiplayerRpc;

		private float nextMultiplayerHello;

		private float nextMultiplayerPeerCheck;

		private bool multiplayerManifestReceived;

		private bool multiplayerRejected;

		private readonly HashSet<long> multiplayerVerifiedPeers = new HashSet<long>();

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

		private readonly Dictionary<Vector2Int, RemoteCellManifest> multiplayerRemoteCells = new Dictionary<Vector2Int, RemoteCellManifest>();

		private readonly HashSet<Vector2Int> multiplayerRequestedCells = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> multiplayerPendingLoadCells = new HashSet<Vector2Int>();

		private readonly Dictionary<Vector2Int, int> multiplayerBuildGenerations = new Dictionary<Vector2Int, int>();

		private readonly HashSet<Vector2Int> multiplayerPendingVanillaRestore = new HashSet<Vector2Int>();

		private readonly Dictionary<ZDOID, Vector2Int> multiplayerRestoreTrackedZdos = new Dictionary<ZDOID, Vector2Int>();

		private readonly Dictionary<Vector2Int, List<ZNetView>> multiplayerRestoredViews = new Dictionary<Vector2Int, List<ZNetView>>();

		private IncomingCellTransfer multiplayerIncomingTransfer;

		private long multiplayerServerPeerUid;

		private ConnectionStatus multiplayerLastConnectionStatus;

		private readonly HashSet<long> multiplayerSendingPeers = new HashSet<long>();

		private readonly HashSet<string> multiplayerPendingChunkAcks = new HashSet<string>();

		private Vector2Int? multiplayerOutstandingRequest;

		private float multiplayerOutstandingRequestStarted;

		private float nextMultiplayerCellRequestAllowed;

		private IncomingRecordTransfer multiplayerIncomingRecords;

		private readonly Dictionary<Vector2Int, List<BakedRecord>> multiplayerDiskCachedRecords = new Dictionary<Vector2Int, List<BakedRecord>>();

		private readonly Dictionary<Vector2Int, Dictionary<string, Queue<BakedRecord>>> multiplayerRemoteCreationIndex = new Dictionary<Vector2Int, Dictionary<string, Queue<BakedRecord>>>();

		private readonly Dictionary<ZDOID, ZDO> multiplayerSuppressedRemoteZdos = new Dictionary<ZDOID, ZDO>();

		private readonly Dictionary<string, Vector2Int> multiplayerSuppressedStableCells = new Dictionary<string, Vector2Int>(StringComparer.Ordinal);

		private readonly Dictionary<Vector2Int, HashSet<long>> multiplayerPendingRestoreAcks = new Dictionary<Vector2Int, HashSet<long>>();

		private readonly Dictionary<Vector2Int, Dictionary<long, float>> multiplayerRestoreProgress = new Dictionary<Vector2Int, Dictionary<long, float>>();

		private readonly HashSet<Vector2Int> multiplayerRemotePhysicsReady = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> multiplayerProvisionalVisualCells = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> multiplayerProvisionalBuildsInProgress = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> multiplayerRemoteBuildsInProgress = new HashSet<Vector2Int>();

		private readonly Dictionary<Vector2Int, List<RemoteVisualHandoff>> multiplayerPendingVisualHandoffs = new Dictionary<Vector2Int, List<RemoteVisualHandoff>>();

		private readonly Dictionary<Vector2Int, int> multiplayerGpuSubmittedFrames = new Dictionary<Vector2Int, int>();

		private readonly Dictionary<Vector2Int, int> multiplayerHandoffPublishedFrames = new Dictionary<Vector2Int, int>();

		private readonly Dictionary<Vector2Int, float> multiplayerHandoffPublishedTimes = new Dictionary<Vector2Int, float>();

		private readonly Dictionary<Vector2Int, RemoteFinalVisualHandoff> multiplayerPendingFinalVisualHandoffs = new Dictionary<Vector2Int, RemoteFinalVisualHandoff>();

		private readonly Dictionary<Vector2Int, RemoteProvisionalVisualPublication> multiplayerPendingProvisionalVisualPublications = new Dictionary<Vector2Int, RemoteProvisionalVisualPublication>();

		private readonly Dictionary<Vector2Int, float> multiplayerPortalPrewarmUntil = new Dictionary<Vector2Int, float>();

		private bool multiplayerClientShutdownInProgress;

		private bool multiplayerServerAdminAllowed;

		private bool multiplayerRemoteServerDedicated;

		private int multiplayerDedicatedBudgetFrame = -1;

		private long multiplayerDedicatedBudgetStarted;

		private int multiplayerDedicatedLastProvisionalStartFrame = -1;

		private bool multiplayerDedicatedPortalPending;

		private Vector3 multiplayerDedicatedPortalTarget;

		private float multiplayerDedicatedPortalDeadline;

		private bool multiplayerProvisionalCacheScanned;

		private long multiplayerManifestRevision;

		private long multiplayerLastReceivedManifestRevision = -1L;

		private GameObject multiplayerSpawnSafety;

		private Vector2Int multiplayerSpawnSafetyCell;

		private float multiplayerSpawnSafetyY;

		private float multiplayerSpawnSafetyReadySince = -1f;

		private readonly Dictionary<Vector2Int, HashSet<long>> multiplayerPendingBakeReady = new Dictionary<Vector2Int, HashSet<long>>();

		private readonly Dictionary<GameObject, HashSet<Mesh>> remoteOwnedColliderMeshes = new Dictionary<GameObject, HashSet<Mesh>>();

		private static readonly Func<ZDO, bool> IsOutsideRestoreSector = AccessTools.MethodDelegate<Func<ZDO, bool>>(AccessTools.PropertyGetter(typeof(ZDO), "OutsideZones"), (object)null, true);

		private static readonly Action<ZDO, SectorIndex> SetRestoreSector = AccessTools.MethodDelegate<Action<ZDO, SectorIndex>>(AccessTools.Method(typeof(ZDO), "SetSector", (Type[])null, (Type[])null), (object)null, true);

		private int remoteRestoreWorkFrame = -1;

		private int remoteRestoreWorkCount;

		private long remoteRestoreWorkStarted;

		private Dictionary<string, List<ZDO>> remoteRestoreFallback;

		private ZDOMan remoteRestoreFallbackOwner;

		private bool remoteRestoreFallbackBuilding;

		private readonly Dictionary<Vector2Int, RestoreSupportCell> restoreSupportCells = new Dictionary<Vector2Int, RestoreSupportCell>();

		private readonly Dictionary<string, ZNetView> restoreSupportViews = new Dictionary<string, ZNetView>(StringComparer.Ordinal);

		private ZDOMan restoreSupportOwner;

		private bool restoreSupportChecking;

		private float restoreSupportNextCheck;

		private readonly Dictionary<Vector2Int, FastColliderCellState> fastColliderCells = new Dictionary<Vector2Int, FastColliderCellState>();

		private readonly Dictionary<Vector2Int, HashSet<string>> fastLoadedSubclusters = new Dictionary<Vector2Int, HashSet<string>>();

		private readonly Dictionary<Vector2Int, Vector3> singlePlayerFastFocus = new Dictionary<Vector2Int, Vector3>();

		private readonly Dictionary<Vector2Int, float> singlePlayerFastRetainUntil = new Dictionary<Vector2Int, float>();

		private readonly HashSet<Vector2Int> singlePlayerDormantCells = new HashSet<Vector2Int>();

		private readonly Dictionary<Vector2Int, float> singlePlayerFastLastUsed = new Dictionary<Vector2Int, float>();

		private const int SinglePlayerDormantCellLimit = 20;

		private readonly Dictionary<Vector2Int, PreparedGpuRead> singlePlayerPreparedGpuReads = new Dictionary<Vector2Int, PreparedGpuRead>();

		private bool singlePlayerInitialVisualPipelineRunning;

		private readonly Dictionary<Vector2Int, float> singlePlayerVisualHandoffStarted = new Dictionary<Vector2Int, float>();

		private bool fastColliderPumpRunning;

		private bool singlePlayerPortalCurtainActive;

		private float singlePlayerPortalCurtainReleaseAt;

		private bool singlePlayerStartupCurtainActive;

		private float singlePlayerStartupCurtainStarted;

		private readonly HashSet<Vector2Int> singlePlayerStartupCurtainCells = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> singlePlayerVisualHandoffNeedsParking = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> singlePlayerReparkRunning = new HashSet<Vector2Int>();

		private readonly HashSet<Vector2Int> invalidCacheRecoveryCells = new HashSet<Vector2Int>();

		private readonly Dictionary<Vector2Int, List<ZNetView>> pendingSoloBakePublications = new Dictionary<Vector2Int, List<ZNetView>>();

		private static string MetadataScope => GetWorldMetadataScope();

		private static string BakedKey => "PUP_SAFE_Baked_" + MetadataScope;

		private static string PositionKey => "PUP_SAFE_Position_" + MetadataScope;

		private static string RotationKey => "PUP_SAFE_Rotation_" + MetadataScope;

		private static string ScaleKey => "PUP_SAFE_Scale_" + MetadataScope;

		private static string CellXKey => "PUP_SAFE_CellX_" + MetadataScope;

		private static string CellZKey => "PUP_SAFE_CellZ_" + MetadataScope;

		private static string CustomIdKey => "PUP_GRAUSTEN_ID_" + MetadataScope;

		private static string GetWorldMetadataScope()
		{
			if (IsDedicatedServerRuntime())
			{
				return "multiplayer";
			}
			if (ZNet.IsSinglePlayer || ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()))
			{
				return "solo";
			}
			if (!((Object)(object)Instance != (Object)null) || !Instance.multiplayerRemoteServerDedicated)
			{
				return "solo";
			}
			return "multiplayer";
		}

		private void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			Instance = this;
			Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnCameraPreCull));
			Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnCameraPostRender));
			harmony.PatchAll();
			InitializeMultiplayerSync();
			((Component)this).gameObject.AddComponent<ServerZoneStreamBlock>().Setup(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
		}

		private void OnDestroy()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_00b7: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnCameraPreCull));
			Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnCameraPostRender));
			if ((Object)(object)singlePlayerPrecipitationCubeMesh != (Object)null)
			{
				Object.Destroy((Object)(object)singlePlayerPrecipitationCubeMesh);
			}
			singlePlayerPrecipitationCubeMesh = null;
			RestoreCoordinatesForVanillaSave("plugin unload");
			pendingColliders.Clear();
			queuedColliderCount = 0;
			loadedQueuedColliders = 0;
			activeColliderLoads = 0;
			Instance = null;
			harmony.UnpatchSelf();
			foreach (Vector2Int item in clusters.Keys.ToList())
			{
				DestroyCluster(item);
			}
			foreach (Material retiredGpuMaterial in retiredGpuMaterials)
			{
				if ((Object)(object)retiredGpuMaterial != (Object)null)
				{
					Object.Destroy((Object)(object)retiredGpuMaterial);
				}
			}
			retiredGpuMaterials.Clear();
			foreach (Material value in materialCopies.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			foreach (Material value2 in highlightMaterials.Values)
			{
				if ((Object)(object)value2 != (Object)null)
				{
					Object.Destroy((Object)(object)value2);
				}
			}
			foreach (List<MeshRenderer> value3 in hiddenRenderers.Values)
			{
				foreach (MeshRenderer item2 in value3)
				{
					if ((Object)(object)item2 != (Object)null)
					{
						((Renderer)item2).enabled = true;
					}
				}
			}
			hiddenRenderers.Clear();
			foreach (List<LODGroup> value4 in hiddenLodGroups.Values)
			{
				foreach (LODGroup item3 in value4)
				{
					if ((Object)(object)item3 != (Object)null)
					{
						item3.enabled = true;
					}
				}
			}
			hiddenLodGroups.Clear();
			DisableGpuRenderTest();
		}

		private void OnApplicationQuit()
		{
			applicationQuitting = true;
			RestoreCoordinatesForVanillaSave("application quit");
		}

		private void OnCameraPreCull(Camera camera)
		{
			if ((Object)(object)camera != (Object)null && (Object)(object)camera == (Object)(object)Camera.main)
			{
				CommitRemoteVisualHandoffsBeforeMainCameraCull();
			}
			if (!((Object)(object)camera == (Object)null) && !(((Object)camera).name != "SkyAlphaCamera"))
			{
				RestoreSkyAlphaRendererState();
				DrawSinglePlayerPrecipitationMasks(camera);
			}
		}

		private void OnCameraPostRender(Camera camera)
		{
			if (!((Object)(object)camera == (Object)null) && !(((Object)camera).name != "SkyAlphaCamera"))
			{
				RestoreSkyAlphaRendererState();
			}
		}

		private void RestoreSkyAlphaRendererState()
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyValuePair<MeshRenderer, bool> item in skyAlphaPreviousEnabled)
			{
				if ((Object)(object)item.Key != (Object)null)
				{
					((Renderer)item.Key).enabled = item.Value;
					if (skyAlphaPreviousLayer.TryGetValue(item.Key, out var value))
					{
						((Component)item.Key).gameObject.layer = value;
					}
					if (skyAlphaPreviousShadowMode.TryGetValue(item.Key, out var value2))
					{
						((Renderer)item.Key).shadowCastingMode = value2;
					}
				}
			}
			skyAlphaPreviousEnabled.Clear();
			skyAlphaPreviousLayer.Clear();
			skyAlphaPreviousShadowMode.Clear();
		}

		private void DrawSinglePlayerPrecipitationMasks(Camera camera)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			foreach (List<MeshRenderer> value in precipitationRenderers.Values)
			{
				foreach (MeshRenderer item in value)
				{
					if ((Object)(object)item == (Object)null)
					{
						continue;
					}
					MeshFilter component = ((Component)item).GetComponent<MeshFilter>();
					Mesh val = (((Object)(object)component != (Object)null) ? component.sharedMesh : null);
					Material[] sharedMaterials = ((Renderer)item).sharedMaterials;
					if ((Object)(object)val == (Object)null || sharedMaterials == null || sharedMaterials.Length == 0)
					{
						continue;
					}
					Matrix4x4 localToWorldMatrix = ((Component)item).transform.localToWorldMatrix;
					for (int i = 0; i < val.subMeshCount; i++)
					{
						Material val2 = sharedMaterials[Mathf.Min(i, sharedMaterials.Length - 1)];
						if (!((Object)(object)val2 == (Object)null))
						{
							Graphics.DrawMesh(val, localToWorldMatrix, val2, 10, camera, i, (MaterialPropertyBlock)null, (ShadowCastingMode)0, false, (Transform)null, (LightProbeUsage)0, (LightProbeProxyVolume)null);
						}
					}
				}
			}
		}

		private void Update()
		{
			//IL_0067: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			MultiplayerUpdate();
			UpdateRestoreSupportGuard();
			if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			if (UnityInput.Current.GetKeyDown((KeyCode)91) && !processing)
			{
				if (IsMultiplayerGuest())
				{
					SendServerAdminCommand(1);
				}
				else if (loadingCells.Count == 0)
				{
					((MonoBehaviour)this).StartCoroutine(BakeCell(GetCell(((Component)Player.m_localPlayer).transform.position)));
				}
				else
				{
					ShowMessage("Please wait for streamed zone loading");
				}
			}
			if (UnityInput.Current.GetKeyDown((KeyCode)93) && !processing)
			{
				if (IsMultiplayerGuest())
				{
					SendServerAdminCommand(2);
				}
				else if (loadingCells.Count != 0)
				{
					ShowMessage("Please wait for streamed zone loading");
				}
				else
				{
					Vector2Int? val = FindNearestBakedCell(((Component)Player.m_localPlayer).transform.position, 96f);
					if (val.HasValue)
					{
						((MonoBehaviour)this).StartCoroutine(UnbakeCell(val.Value));
					}
					else
					{
						ShowMessage("No baked cluster nearby");
					}
				}
			}
			if (UnityInput.Current.GetKeyDown((KeyCode)92))
			{
				if (IsMultiplayerGuest())
				{
					SendServerAdminCommand(4);
				}
				else
				{
					highlightEnabled = !highlightEnabled;
					RefreshHighlights();
					ShowMessage(highlightEnabled ? "Cluster highlighting enabled" : "Cluster highlighting disabled");
				}
			}
			if (UnityInput.Current.GetKeyDown((KeyCode)289) && !processing)
			{
				if (IsMultiplayerGuest())
				{
					SendServerAdminCommand(3);
				}
				else if (loadingCells.Count == 0)
				{
					((MonoBehaviour)this).StartCoroutine(RestoreAllParked());
				}
				else
				{
					ShowMessage("Please wait for streamed zone loading");
				}
			}
			DrawGpuRenderTest();
			ProcessPendingColliders();
			UpdateTravelPrediction();
			UpdateCacheLoadingProgress();
			if (Time.time >= nextColliderActivationCheck)
			{
				nextColliderActivationCheck = Time.time + 0.2f;
				UpdateColliderActivation();
			}
			if (!processing && Time.time >= nextCellCheck)
			{
				nextCellCheck = Time.time + 0.5f;
				UpdateVisibleClusters();
			}
		}

		private void UpdateCacheLoadingProgress()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null)
			{
				ResetCacheLoadingProgress();
				return;
			}
			if (IsMultiplayerGuest())
			{
				UpdateMultiplayerCacheLoadingProgress();
				return;
			}
			if (records.Count == 0)
			{
				ResetCacheLoadingProgress();
				return;
			}
			Vector2s valheimZone = ZoneSystem.GetZone(((Component)Player.m_localPlayer).transform.position);
			SimulationDistance syncedSimulationDistance = ZNet.instance.GetSyncedSimulationDistance();
			int activeArea = Mathf.Max(1, ((SimulationDistance)(ref syncedSimulationDistance)).NearSimulationDistance);
			List<Vector2Int> list = records.Keys.Where((Vector2Int cell) => !pendingWorldSaveRestores.Contains(cell) && CellOverlapsValheimArea(cell, valheimZone, activeArea)).ToList();
			int count = list.Count;
			int num = list.Count((Vector2Int cell) => clusters.ContainsKey(cell) && gpuCacheReadyCells.Contains(cell) && !loadingCells.Contains(cell) && !suppressedVisualCells.Contains(cell));
			if (count <= 0 || (num >= count && loadingCells.Count == 0 && pendingSubClusterLoads == 0 && queuedColliderCount == 0 && activeColliderLoads == 0 && !visualWarmupRunning))
			{
				ResetCacheLoadingProgress();
				return;
			}
			if (!cacheLoadingProgressActive)
			{
				cacheLoadingProgressActive = true;
				cacheLoadingProgressStarted = Time.realtimeSinceStartup;
			}
			cacheLoadingProgressCompleted = Mathf.Clamp(num, 0, count);
			cacheLoadingProgressTotal = count;
			cacheLoadingProgressVisible = Time.realtimeSinceStartup - cacheLoadingProgressStarted >= 2f;
		}

		private void UpdateMultiplayerCacheLoadingProgress()
		{
			//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_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			if (!multiplayerManifestReceived)
			{
				ResetCacheLoadingProgress();
			}
			else
			{
				if (multiplayerRemoteServerDedicated && !IsDedicatedVanillaStreamingReady())
				{
					return;
				}
				Vector3 playerPosition = ((Component)Player.m_localPlayer).transform.position;
				float requestRadiusSquared = 36864f;
				if (!multiplayerStartupProgressCaptured)
				{
					multiplayerStartupProgressCells.Clear();
					multiplayerStartupProgressCells.UnionWith(multiplayerRemoteCells.Keys.Where((Vector2Int cell) => CellDistanceSquared(cell, playerPosition) <= requestRadiusSquared && (!multiplayerRemoteServerDedicated || IsDedicatedVanillaStreamingReady(cell)) && !multiplayerPendingVanillaRestore.Contains(cell)));
					multiplayerStartupProgressCaptured = true;
					multiplayerStartupProgressCompleted = multiplayerStartupProgressCells.Count == 0;
				}
				if (multiplayerStartupProgressCompleted)
				{
					ResetCacheLoadingProgress();
					return;
				}
				List<Vector2Int> list = multiplayerStartupProgressCells.Where((Vector2Int cell) => multiplayerRemoteCells.ContainsKey(cell) && !multiplayerPendingVanillaRestore.Contains(cell) && CellDistanceSquared(cell, playerPosition) <= requestRadiusSquared && (!multiplayerRemoteServerDedicated || IsDedicatedVanillaStreamingReady(cell))).ToList();
				int count = list.Count;
				foreach (Vector2Int item in list)
				{
					if (clusters.ContainsKey(item) && gpuCacheReadyCells.Contains(item) && !suppressedVisualCells.Contains(item) && multiplayerRemotePhysicsReady.Contains(item) && !multiplayerPendingVanillaRestore.Contains(item))
					{
						multiplayerStartupReadyCells.Add(item);
					}
				}
				int num = list.Count((Vector2Int cell) => multiplayerStartupReadyCells.Contains(cell));
				if (count <= 0 || num >= count)
				{
					multiplayerStartupProgressCompleted = true;
					ResetCacheLoadingProgress();
					return;
				}
				if (!cacheLoadingProgressActive)
				{
					cacheLoadingProgressActive = true;
					cacheLoadingProgressStarted = Time.realtimeSinceStartup;
				}
				cacheLoadingProgressCompleted = Mathf.Clamp(num, 0, count);
				cacheLoadingProgressTotal = count;
				cacheLoadingProgressVisible = Time.realtimeSinceStartup - cacheLoadingProgressStarted >= 2f;
			}
		}

		private void ResetCacheLoadingProgress()
		{
			cacheLoadingProgressActive = false;
			cacheLoadingProgressVisible = false;
			cacheLoadingProgressStarted = 0f;
			cacheLoadingProgressCompleted = 0;
			cacheLoadingProgressTotal = 0;
		}

		private void OnGUI()
		{
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (cacheLoadingProgressVisible && cacheLoadingProgressTotal > 0)
			{
				if (cacheLoadingProgressStyle == null)
				{
					cacheLoadingProgressStyle = new GUIStyle(GUI.skin.label)
					{
						alignment = (TextAnchor)4,
						fontSize = 20,
						fontStyle = (FontStyle)1
					};
					cacheLoadingProgressStyle.normal.textColor = Color.white;
					cacheLoadingProgressShadowStyle = new GUIStyle(cacheLoadingProgressStyle);
					cacheLoadingProgressShadowStyle.normal.textColor = new Color(0f, 0f, 0f, 0.9f);
				}
				int num = Mathf.Clamp(Mathf.RoundToInt((float)cacheLoadingProgressCompleted * 100f / (float)cacheLoadingProgressTotal), 0, 100);
				string text = $"Cache loading: {cacheLoadingProgressCompleted} / " + $"{cacheLoadingProgressTotal} zones ({num}%)";
				float num2 = Mathf.Min(640f, (float)Screen.width - 20f);
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(((float)Screen.width - num2) * 0.5f, 92f, num2, 34f);
				GUI.Label(new Rect(((Rect)(ref val)).x + 2f, ((Rect)(ref val)).y + 2f, ((Rect)(ref val)).width, ((Rect)(ref val)).height), text, cacheLoadingProgressShadowStyle);
				GUI.Label(val, text, cacheLoadingProgressStyle);
			}
		}

		private void UpdateTravelPrediction()
		{
			//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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)Player.m_localPlayer).transform.position;
			if (previousPlayerPosition != Vector3.zero)
			{
				Vector3 val = position - previousPlayerPosition;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude > 0.0025f)
				{
					smoothedTravelDirection = Vector3.Lerp(smoothedTravelDirection, val / Mathf.Max(Time.deltaTime, 0.001f), 0.2f);
				}
			}
			previousPlayerPosition = position;
		}

		private Vector3 GetPredictedPlayerPosition()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 result = ((Component)Player.m_localPlayer).transform.position + Vector3.ClampMagnitude(smoothedTravelDirection * 2f, 64f);
			result.y = ((Component)Player.m_localPlayer).transform.position.y;
			return result;
		}

		private static Vector3 GetHorizontalViewForward()
		{
			//IL_0027: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			Vector3 val = (((Object)(object)main != (Object)null && (Object)(object)((Component)main).transform != (Object)null) ? ((Component)main).transform.forward : ((Component)Player.m_localPlayer).transform.forward);
			val.y = 0f;
			if (!(((Vector3)(ref val)).sqrMagnitude > 0.0001f))
			{
				return Vector3.forward;
			}
			return ((Vector3)(ref val)).normalized;
		}

		private static float GetForwardZonePriority(Vector2Int cell, Vector2Int playerCell, Vector3 playerPosition, Vector3 viewForward)
		{
			//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_0023: 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_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_006c: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			if (cell == playerCell)
			{
				return -1E+09f;
			}
			Vector3 val = new Vector3(((float)((Vector2Int)(ref cell)).x + 0.5f) * 64f, playerPosition.y, ((float)((Vector2Int)(ref cell)).y + 0.5f) * 64f) - playerPosition;
			val.y = 0f;
			float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
			float num = ((sqrMagnitude > 0.001f) ? Vector3.Dot(val / Mathf.Sqrt(sqrMagnitude), viewForward) : 1f);
			return ((num >= 0.35f) ? 0f : ((num >= -0.35f) ? 1f : 2f)) * 1000000f + sqrMagnitude;
		}

		private void UpdateColliderActivation()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			Vector3 position = ((Component)Player.m_localPlayer).transform.position;
			Vector3 predictedPlayerPosition = GetPredictedPlayerPosition();
			Vector2Int cell = GetCell(position);
			Vector3 val = default(Vector3);
			foreach (KeyValuePair<Vector2Int, GameObject> cluster in clusters)
			{
				if ((Object)(object)cluster.Value == (Object)null)
				{
					continue;
				}
				Vector2Int key = cluster.Key;
				float num = ((float)((Vector2Int)(ref key)).x + 0.5f) * 64f;
				float y = position.y;
				key = cluster.Key;
				((Vector3)(ref val))..ctor(num, y, ((float)((Vector2Int)(ref key)).y + 0.5f) * 64f);
				bool value;
				bool flag = colliderCellActive.TryGetValue(cluster.Key, out value) && value;
				float num2 = (flag ? 96f : 80f);
				float num3 = num2 * num2;
				int num4;
				if (!ShouldRetainPortalPrewarmCell(cluster.Key) && !(cluster.Key == cell))
				{
					Vector3 val2 = val - position;
					if (!(((Vector3)(ref val2)).sqrMagnitude <= num3))
					{
						val2 = val - predictedPlayerPosition;
						num4 = ((((Vector3)(ref val2)).sqrMagnitude <= num3) ? 1 : 0);
						goto IL_011a;
					}
				}
				num4 = 1;
				goto IL_011a;
				IL_011a:
				bool flag2 = (byte)num4 != 0;
				if (colliderCellActive.ContainsKey(cluster.Key) && flag == flag2)
				{
					continue;
				}
				Collider[] componentsInChildren = cluster.Value.GetComponentsInChildren<Collider>(true);
				foreach (Collider val3 in componentsInChildren)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						bool flag3 = !flag2 && IsProtectedSupportCollider(cluster.Key, val3);
						val3.enabled = flag2 || flag3;
					}
				}
				colliderCellActive[cluster.Key] = flag2;
			}
		}

		private static bool TryGetColliderCoordinates(Collider collider, out int subX, out int subZ, out int colliderIndex)
		{
			subX = (subZ = (colliderIndex = -1));
			string[] array = ((Object)((Component)collider).gameObject).name.Split(new char[1] { '_' });
			if (array.Length >= 5 && int.TryParse(array[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out subX) && int.TryParse(array[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out subZ))
			{
				return int.TryParse(array[4], NumberStyles.Integer, CultureInfo.InvariantCulture, out colliderIndex);
			}
			return false;
		}

		private bool IsProtectedSupportCollider(Vector2Int cell, Collider collider)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (!protectedSupportColliders.TryGetValue(cell, out var value) || value.Count == 0)
			{
				return false;
			}
			if (value.Contains("*"))
			{
				return true;
			}
			if (!TryGetColliderCoordinates(collider, out var subX, out var subZ, out var colliderIndex))
			{
				return true;
			}
			return value.Contains($"{subX}:{subZ}:{colliderIndex}");
		}

		private void DrawGpuRenderTest()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_049b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d3: Unknown result type (might be due to invalid IL or missing references)
			CommitRemoteProvisionalVisualPublicationsBeforeDraw();
			CommitRemoteFinalVisualHandoffsBeforeDraw();
			Vector3 position = ((Component)Player.m_localPlayer).transform.position;
			Camera main = Camera.main;
			bool flag = (Object)(object)main != (Object)null;
			int num;
			if (flag)
			{
				if (!gpuCullVisibilityDirty && !((Object)(object)gpuCullCamera != (Object)(object)main))
				{
					Vector3 val = gpuCullCameraPosition - ((Component)main).transform.position;
					if (!(((Vector3)(ref val)).sqrMagnitude > 0.01f) && !(Quaternion.Angle(gpuCullCameraRotation, ((Component)main).transform.rotation) > 0.25f) && !(Mathf.Abs(gpuCullCameraFieldOfView - main.fieldOfView) > 0.01f))
					{
						num = ((Mathf.Abs(gpuCullCameraAspect - main.aspect) > 0.001f) ? 1 : 0);
						goto IL_00c4;
					}
				}
				num = 1;
			}
			else
			{
				num = 0;
			}
			goto IL_00c4;
			IL_00c4:
			bool flag2 = (byte)num != 0;
			if (flag2)
			{
				GeometryUtility.CalculateFrustumPlanes(main, gpuFrustumPlanes);
				gpuCullCamera = main;
				gpuCullCameraPosition = ((Component)main).transform.position;
				gpuCullCameraRotation = ((Component)main).transform.rotation;
				gpuCullCameraFieldOfView = main.fieldOfView;
				gpuCullCameraAspect = main.aspect;
				gpuCullVisibilityDirty = false;
			}
			Vector3 val2 = default(Vector3);
			foreach (KeyValuePair<Vector2Int, List<GpuDrawGroup>> gpuBakedGroup in gpuBakedGroups)
			{
				bool flag3 = pendingSoloBakePublications.ContainsKey(gpuBakedGroup.Key);
				if (suppressedVisualCells.Contains(gpuBakedGroup.Key) && (!ZNet.IsSinglePlayer || !gpuCacheReadyCells.Contains(gpuBakedGroup.Key)))
				{
					continue;
				}
				bool value = true;
				if (flag && !flag3)
				{
					if (flag2 && TryGetGpuCellWorldBounds(gpuBakedGroup.Key, gpuBakedGroup.Value, out var bounds))
					{
						value = GeometryUtility.TestPlanesAABB(gpuFrustumPlanes, bounds);
						gpuCellCameraVisible[gpuBakedGroup.Key] = value;
					}
					else if (!flag2 && !gpuCellCameraVisible.TryGetValue(gpuBakedGroup.Key, out value))
					{
						value = true;
					}
					if (!value)
					{
						continue;
					}
				}
				Vector2Int key = gpuBakedGroup.Key;
				float num2 = ((float)((Vector2Int)(ref key)).x + 0.5f) * 64f;
				float y = position.y;
				key = gpuBakedGroup.Key;
				((Vector3)(ref val2))..ctor(num2, y, ((float)((Vector2Int)(ref key)).y + 0.5f) * 64f);
				float num3 = Vector3.Distance(position, val2);
				bool flag4 = false;
				foreach (GpuDrawGroup item in gpuBakedGroup.Value)
				{
					if (item == null || (Object)(object)item.mesh == (Object)null || (Object)(object)item.material == (Object)null)
					{
						continue;
					}
					if (flag && !flag3)
					{
						if (flag2)
						{
							EnsureGpuGroupWorldBounds(item);
							item.cameraVisible = !item.hasWorldBounds || GeometryUtility.TestPlanesAABB(gpuFrustumPlanes, item.worldBounds);
						}
						if (!item.cameraVisible)
						{
							continue;
						}
					}
					if (item.usesTessellation)
					{
						bool flag5 = (item.tessellationEnabled ? (num3 < 128f) : (num3 < 96f));
						if (flag5 != item.tessellationEnabled)
						{
							item.tessellationEnabled = flag5;
							if (flag5)
							{
								item.material.EnableKeyword("TESSELATION_ON");
							}
							else
							{
								item.material.DisableKeyword("TESSELATION_ON");
							}
						}
					}
					int materialGroup = GetMaterialGroup(item.material);
					foreach (Matrix4x4[] chunk in item.chunks)
					{
						if (ShouldDrawCellHighlight(gpuBakedGroup.Key))
						{
							Material gpuHighlightMaterial = GetGpuHighlightMaterial(item.material, (materialGroup == 0) ? 1 : materialGroup);
							Graphics.DrawMeshInstanced(item.mesh, item.subMesh, gpuHighlightMaterial, chunk, chunk.Length, (MaterialPropertyBlock)null, (ShadowCastingMode)0, false, 0, main);
						}
						else
						{
							Graphics.DrawMeshInstanced(item.mesh, item.subMesh, item.material, chunk, chunk.Length, (MaterialPropertyBlock)null, (ShadowCastingMode)0, true, 0, main);
						}
						flag4 = true;
					}
				}
				if (flag4)
				{
					PublishSoloBakeAfterDraw(gpuBakedGroup.Key);
					multiplayerGpuSubmittedFrames[gpuBakedGroup.Key] = Time.frameCount;
				}
				if (!flag4 || !singlePlayerVisualHandoffStarted.TryGetValue(gpuBakedGroup.Key, out var _))
				{
					continue;
				}
				if (singlePlayerVisualHandoffNeedsParking.Contains(gpuBakedGroup.Key))
				{
					if (CanParkSinglePlayerCell(gpuBakedGroup.Key) && ((Behaviour)this).isActiveAndEnabled && ((Component)this).gameObject.activeInHierarchy && singlePlayerReparkRunning.Add(gpuBakedGroup.Key))
					{
						ReparkBakedCell(gpuBakedGroup.Key);
						singlePlayerVisualHandoffNeedsParking.Remove(gpuBakedGroup.Key);
						singlePlayerVisualHandoffStarted.Remove(gpuBakedGroup.Key);
						singlePlayerReparkRunning.Remove(gpuBakedGroup.Key);
					}
				}
				else
				{
					singlePlayerVisualHandoffStarted.Remove(gpuBakedGroup.Key);
				}
			}
		}

		private void CommitRemoteVisualHandoffsBeforeMainCameraCull()
		{
			//IL_0033: 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_003f: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			if (!multiplayerRemoteServerDedicated || multiplayerPendingVisualHandoffs.Count == 0)
			{
				return;
			}
			foreach (Vector2Int item in multiplayerPendingVisualHandoffs.Keys.ToList())
			{
				if (!multiplayerGpuSubmittedFrames.TryGetValue(item, out var value) || value != Time.frameCount)
				{
					continue;
				}
				foreach (RemoteVisualHandoff item2 in multiplayerPendingVisualHandoffs[item])
				{
					if (item2 == null)
					{
						continue;
					}
					if (!hiddenRenderers.TryGetValue(item2.id, out var value2))
					{
						value2 = (hiddenRenderers[item2.id] = new List<MeshRenderer>());
					}
					foreach (MeshRenderer enabledRenderer in item2.enabledRenderers)
					{
						if ((Object)(object)enabledRenderer != (Object)null && !value2.Contains(enabledRenderer))
						{
							value2.Add(enabledRenderer);
						}
					}
					MeshRenderer[] allRenderers = item2.allRenderers;
					foreach (MeshRenderer val in allRenderers)
					{
						if ((Object)(object)val != (Object)null)
						{
							((Renderer)val).enabled = false;
						}
					}
					if (!hiddenLodGroups.TryGetValue(item2.id, out var value3))
					{
						value3 = (hiddenLodGroups[item2.id] = new List<LODGroup>());
					}
					foreach (LODGroup enabledLodGroup in item2.enabledLodGroups)
					{
						if ((Object)(object)enabledLodGroup != (Object)null && !value3.Contains(enabledLodGroup))
						{
							value3.Add(enabledLodGroup);
						}
					}
					LODGroup[] allLodGroups = item2.allLodGroups;
					foreach (LODGroup val2 in allLodGroups)
					{
						if ((Object)(object)val2 != (Object)null)
						{
							val2.enabled = false;
						}
					}
				}
				multiplayerPendingVisualHandoffs.Remove(item);
				multiplayerGpuSubmittedFrames.Remove(item);
				multiplayerHandoffPublishedFrames.TryGetValue(item, out var _);
				if (!multiplayerHandoffPublishedTimes.TryGetValue(item, out var _))
				{
					_ = Time.realtimeSinceStartup;
				}
				multiplayerHandoffPublishedFrames.Remove(item);
				multiplayerHandoffPublishedTimes.Remove(item);
			}
		}

		private bool TryGetGpuCellWorldBounds(Vector2Int cell, List<GpuDrawGroup> groups, out Bounds bounds)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (gpuCellWorldBounds.TryGetValue(cell, out bounds))
			{
				return true;
			}
			bool flag = false;
			bounds = default(Bounds);
			foreach (GpuDrawGroup group in groups)
			{
				if (group == null)
				{
					continue;
				}
				EnsureGpuGroupWorldBounds(group);
				if (group.hasWorldBounds)
				{
					if (!flag)
					{
						bounds = group.worldBounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(group.worldBounds);
					}
				}
			}
			if (flag)
			{
				gpuCellWorldBounds[cell] = bounds;
			}
			return flag;
		}

		private static void EnsureGpuGroupWorldBounds(GpuDrawGroup group)
		{
			//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_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			if (group.hasWorldBounds || (Object)(object)group.mesh == (Object)null)
			{
				return;
			}
			Bounds bounds = group.mesh.bounds;
			bool flag = false;
			Bounds worldBounds = default(Bounds);
			Vector3 val3 = default(Vector3);
			Bounds val4 = default(Bounds);
			foreach (Matrix4x4[] chunk in group.chunks)
			{
				if (chunk == null)
				{
					continue;
				}
				Matrix4x4[] array = chunk;
				for (int i = 0; i < array.Length; i++)
				{
					Matrix4x4 val = array[i];
					Vector3 val2 = ((Matrix4x4)(ref val)).MultiplyPoint3x4(((Bounds)(ref bounds)).center);
					Vector3 extents = ((Bounds)(ref bounds)).extents;
					((Vector3)(ref val3))..ctor(Mathf.Abs(val.m00) * extents.x + Mathf.Abs(val.m01) * extents.y + Mathf.Abs(val.m02) * extents.z, Mathf.Abs(val.m10) * extents.x + Mathf.Abs(val.m11) * extents.y + Mathf.Abs(val.m12) * extents.z, Mathf.Abs(val.m20) * extents.x + Mathf.Abs(val.m21) * extents.y + Mathf.Abs(val.m22) * extents.z);
					((Bounds)(ref val4))..ctor(val2, val3 * 2f);
					if (!flag)
					{
						worldBounds = val4;
						flag = true;
					}
					else
					{
						((Bounds)(ref worldBounds)).Encapsulate(val4);
					}
				}
			}
			if (flag)
			{
				((Bounds)(ref worldBounds)).Expand(4f);
				group.worldBounds = worldBounds;
				group.hasWorldBounds = true;
			}
		}

		private void EnableGpuBakedRenderTest(Vector2Int cell, List<(ZNetView view, Piece piece)> targets, GameObject cluster)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Invalid comparison between Unknown and I4
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			RemoveGpuBakedCell(cell, restoreRenderers: true);
			List<GpuDrawGroup> list = new List<GpuDrawGroup>();
			Dictionary<string, (Mesh, int, Material, List<Matrix4x4>)> dictionary = new Dictionary<string, (Mesh, int, Material, List<Matrix4x4>)>(StringComparer.Ordinal);
			foreach (var target in targets)
			{
				foreach (MeshFilter remoteGpuVisualMeshFilter in GetRemoteGpuVisualMeshFilters(target.piece))
				{
					MeshRenderer component = ((Component)remoteGpuVisualMeshFilter).GetComponent<MeshRenderer>();
					if ((Object)(object)component == (Object)null || !((Renderer)component).enabled || (Object)(object)remoteGpuVisualMeshFilter.sharedMesh == (Object)null || (((Renderer)component).sharedMaterials.Length != 0 && ((Renderer)component).sharedMaterials.All((Material material) => (Object)(object)material != (Object)null && NormalizeMaterialName(((Object)material).name).Equals("crystal_window_lod", StringComparison.OrdinalIgnoreCase))))
					{
						continue;
					}
					for (int num = 0; num < remoteGpuVisualMeshFilter.sharedMesh.subMeshCount && num < ((Renderer)component).sharedMaterials.Length; num++)
					{
						Material val = ((Renderer)component).sharedMaterials[num];
						if (!((Object)(object)val == (Object)null))
						{
							string key = $"{((Object)remoteGpuVisualMeshFilter.sharedMesh).GetInstanceID()}|{num}|{((Object)val).GetInstanceID()}";
							if (!dictionary.TryGetValue(key, out var value))
							{
								value = (dictionary[key] = (remoteGpuVisualMeshFilter.sharedMesh, num, val, new List<Matrix4x4>()));
							}
							value.Item4.Add(((Component)remoteGpuVisualMeshFilter).transform.localToWorldMatrix);
						}
					}
				}
			}
			foreach (var value2 in dictionary.Values)
			{
				Material val2 = Object.Instantiate<Material>(value2.Item3);
				val2.enableInstancing = true;
				GpuDrawGroup gpuDrawGroup = new GpuDrawGroup
				{
					mesh = value2.Item1,
					subMesh = value2.Item2,
					material = val2,
					usesTessellation = val2.IsKeywordEnabled("TESSELATION_ON"),
					tessellationEnabled = true
				};
				for (int num2 = 0; num2 < value2.Item4.Count; num2 += 1023)
				{
					gpuDrawGroup.chunks.Add(value2.Item4.Skip(num2).Take(1023).ToArray());
				}
				list.Add(gpuDrawGroup);
			}
			List<MeshRenderer> list2 = new List<MeshRenderer>();
			MeshRenderer[] componentsInChildren = cluster.GetComponentsInChildren<MeshRenderer>(false);
			foreach (MeshRenderer val3 in componentsInChildren)
			{
				if (!((Object)(object)val3 == (Object)null) && ((Renderer)val3).enabled && (int)((Renderer)val3).shadowCastingMode != 3)
				{
					list2.Add(val3);
					((Renderer)val3).enabled = false;
				}
			}
			gpuBakedGroups[cell] = list;
			gpuCellWorldBounds.Remove(cell);
			gpuCellCameraVisible.Remove(cell);
			gpuCullVisibilityDirty = true;
			gpuClusterHidden[cell] = list2;
			BuildRoofDepthRenderers(cell, cluster, list);
			BuildCompositeAshwoodDepthRenderers(cell, cluster, targets);
		}

		private void HideClusterRenderersForGpu(Vector2Int cell, GameObject root)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Invalid comparison between Unknown and I4
			if ((Object)(object)root == (Object)null || !gpuBakedGroups.ContainsKey(cell))
			{
				return;
			}
			if (!gpuClusterHidden.TryGetValue(cell, out var value))
			{
				value = new List<MeshRenderer>();
				gpuClusterHidden[cell] = value;
			}
			MeshRenderer[] componentsInChildren = root.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && ((Renderer)val).enabled && (int)((Renderer)val).shadowCastingMode != 3)
				{
					if (!value.Contains(val))
					{
						value.Add(val);
					}
					((Renderer)val).enabled = false;
				}
			}
		}

		private void BuildRoofDepthRenderers(Vector2Int cell, GameObject root, IEnumerable<GpuDrawGroup> groups)
		{
			//IL_0015: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null || groups == null)
			{
				return;
			}
			int num = 0;
			Matrix4x4 worldToLocalMatrix = root.transform.worldToLocalMatrix;
			foreach (GpuDrawGroup group in groups)
			{
				if (group == null || (Object)(object)group.mesh == (Object)null || (Object)(object)group.material == (Object)null || group.subMesh != 0 || !NeedsGpuPrecipitationMask(((Object)group.material).name, group.mesh.isReadable))
				{
					continue;
				}
				foreach (Matrix4x4[] chunk in group.chunks)
				{
					foreach (Matrix4x4 val in chunk)
					{
						Matrix4x4 val2 = worldToLocalMatrix * val;
						GameObject val3 = new GameObject("PUP_DarkwoodDepth")
						{
							layer = 10
						};
						val3.transform.SetParent(root.transform, false);
						val3.transform.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref val2)).GetColumn(3));
						val3.transform.localRotation = ((Matrix4x4)(ref val2)).rotation;
						val3.transform.localScale = ((Matrix4x4)(ref val2)).lossyScale;
						val3.AddComponent<MeshFilter>().sharedMesh = group.mesh;
						MeshRenderer val4 = val3.AddComponent<MeshRenderer>();
						((Renderer)val4).sharedMaterial = group.material;
						((Renderer)val4).shadowCastingMode = (ShadowCastingMode)0;
						((Renderer)val4).receiveShadows = false;
						((Renderer)val4).enabled = false;
						RegisterPrecipitationRenderer(cell, val4);
						num++;
					}
				}
			}
		}

		private static bool NeedsGpuPrecipitationMask(string materialName, bool readable)
		{
			string text = NormalizeMaterialName(materialName);
			if (text.Equals("RoofShingles", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (!readable)
			{
				if (!text.Equals("woodwall_67_mat", StringComparison.OrdinalIgnoreCase) && !text.Equals("DarkWood_mat", StringComparison.OrdinalIgnoreCase) && !text.Equals("AshWood_mat", StringComparison.OrdinalIgnoreCase))
				{
					return text.Equals("stonefence_mat", StringComparison.OrdinalIgnoreCase);
				}
				return true;
			}
			return false;
		}

		private void BuildCompositeAshwoodDepthRenderers(Vector2Int cell, GameObject root, IEnumerable<(ZNetView view, Piece piece)> targets)
		{
			//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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null || targets == null)
			{
				return;
			}
			Matrix4x4 worldToLocalMatrix = root.transform.worldToLocalMatrix;
			foreach (var target in targets)
			{
				if (!IsCompositeAshwoodPrefab(target.view))
				{
					continue;
				}
				foreach (MeshFilter visualMeshFilter in GetVisualMeshFilters(target.view, target.piece))
				{
					if (!((Object)(object)visualMeshFilter == (Object)null) && !((Object)(object)visualMeshFilter.sharedMesh == (Object)null))
					{
						MeshRenderer component = ((Component)visualMeshFilter).GetComponent<MeshRenderer>();
						if (!((Object)(object)component == (Object)null) && ((Renderer)component).sharedMaterials.Length != 0)
						{
							Matrix4x4 val = worldToLocalMatrix * ((Component)visualMeshFilter).transform.localToWorldMatrix;
							GameObject val2 = new GameObject("PUP_AshwoodDepth")
							{
								layer = 10
							};
							val2.transform.SetParent(root.transform, false);
							val2.transform.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref val)).GetColumn(3));
							val2.transform.localRotation = ((Matrix4x4)(ref val)).rotation;
							val2.transform.localScale = ((Matrix4x4)(ref val)).lossyScale;
							val2.AddComponent<MeshFilter>().sharedMesh = visualMeshFilter.sharedMesh;
							MeshRenderer val3 = val2.AddComponent<MeshRenderer>();
							((Renderer)val3).sharedMaterials = ((Renderer)component).sharedMaterials;
							((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0;
							((Renderer)val3).receiveShadows = false;
							((Renderer)val3).enabled = false;
							RegisterPrecipitationRenderer(cell, val3);
						}
					}
				}
			}
		}

		private void DisableGpuRenderTest()
		{
			//IL_001a: 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)
			foreach (Vector2Int item in gpuBakedGroups.Keys.ToList())
			{
				RemoveGpuBakedCell(item, restoreRenderers: true);
			}
		}

		private void RemoveGpuBakedCell(Vector2Int cell, bool restoreRenderers)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			if (gpuClusterHidden.TryGetValue(cell, out var value))
			{
				if (restoreRenderers)
				{
					foreach (MeshRenderer item in value)
					{
						if ((Object)(object)item != (Object)null)
						{
							((Renderer)item).enabled = true;
						}
					}
				}
				gpuClusterHidden.Remove(cell);
			}
			if (!gpuBakedGroups.TryGetValue(cell, out var value2))
			{
				return;
			}
			bool flag = (Object)(object)ZNet.instance != (Object)null && ZNet.IsSinglePlayer && singlePlayerFullGpuCells.Contains(cell) && ((Behaviour)this).isActiveAndEnabled && ((Component)this).gameObject.activeInHierarchy && !applicationQuitting;
			foreach (Material item2 in (from @group in value2
				where @group != null && (Object)(object)@group.material != (Object)null
				select @group.material).Distinct())
			{
				if ((Object)(object)item2 != (Object)null)
				{
					if (flag)
					{
						((MonoBehaviour)this).StartCoroutine(DestroySinglePlayerFastMaterialDeferred(item2));
					}
					else
					{
						retiredGpuMaterials.Add(item2);
					}
				}
			}
			gpuBakedGroups.Remove(cell);
			gpuCellWorldBounds.Remove(cell);
			gpuCellCameraVisible.Remove(cell);
			gpuCullVisibilityDirty = true;
		}

		private static Vector2Int GetCell(Vector3 position)
		{
			//IL_0000: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2Int(Mathf.FloorToInt(position.x / 64f), Mathf.FloorToInt(position.z / 64f));
		}

		private void UpdateVisibleClusters()
		{
			//IL_0025: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0038: 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_003e: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_0088: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due