Decompiled source of PUP FPS v1.0.19

PUP_FPS.dll

Decompiled 18 hours 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.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
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: AssemblyTitle("PUP_FPS")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PUP_FPS")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("2db0cbbd-295f-4eae-b618-895c79638815")]
[assembly: AssemblyFileVersion("1.0.7.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.7.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ValheimInstanceCombiner
{
	[BepInPlugin("com.pup.instancecombiner.safe", "PUP Safe Building Combiner", "1.0.19")]
	public class InstanceCombinerMod : BaseUnityPlugin
	{
		private sealed class GpuDrawGroup
		{
			public Mesh mesh;

			public int subMesh;

			public Material material;

			public bool usesTessellation;

			public bool tessellationEnabled = true;

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

		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 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;
		}

		private sealed class PendingCollider
		{
			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();
				}
			}
		}

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

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

		internal static InstanceCombinerMod Instance;

		private const float CellSize = 64f;

		private const float ParkingCoordinate = 1900000f;

		private const string StateHeader = "PUP_SAFE|7|64|GRAUSTEN|SUBCLUSTER16";

		private const string BakedKey = "PUP_SAFE_Baked";

		private const string PositionKey = "PUP_SAFE_Position";

		private const string RotationKey = "PUP_SAFE_Rotation";

		private const string ScaleKey = "PUP_SAFE_Scale";

		private const string CellXKey = "PUP_SAFE_CellX";

		private const string CellZKey = "PUP_SAFE_CellZ";

		private const string CustomIdKey = "PUP_GRAUSTEN_ID";

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

		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<string, Material> materialCopies = new Dictionary<string, Material>(StringComparer.Ordinal);

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

		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 bool processing;

		private bool highlightEnabled;

		private string worldName = "";

		private readonly Dictionary<int, Material> highlightMaterials = new Dictionary<int, 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 bool safeSaveRestoreInProgress;

		private bool applicationQuitting;

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

		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 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();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"PUP Safe Building Combiner 1.0.19 loaded (exact darkwood depth renderers)");
		}

		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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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));
			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 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)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)camera == (Object)null || ((Object)camera).name != "SkyAlphaCamera")
			{
				return;
			}
			skyAlphaPreviousEnabled.Clear();
			skyAlphaPreviousLayer.Clear();
			skyAlphaPreviousShadowMode.Clear();
			foreach (List<MeshRenderer> value in precipitationRenderers.Values)
			{
				foreach (MeshRenderer item in value)
				{
					if (!((Object)(object)item == (Object)null))
					{
						skyAlphaPreviousEnabled[item] = ((Renderer)item).enabled;
						skyAlphaPreviousLayer[item] = ((Component)item).gameObject.layer;
						skyAlphaPreviousShadowMode[item] = ((Renderer)item).shadowCastingMode;
						((Component)item).gameObject.layer = 10;
						((Renderer)item).shadowCastingMode = (ShadowCastingMode)0;
						((Renderer)item).enabled = true;
					}
				}
			}
		}

		private void OnCameraPostRender(Camera camera)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)camera == (Object)null || ((Object)camera).name != "SkyAlphaCamera")
			{
				return;
			}
			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 Update()
		{
			//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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			if (UnityInput.Current.GetKeyDown((KeyCode)91) && !processing)
			{
				((MonoBehaviour)this).StartCoroutine(BakeCell(GetCell(((Component)Player.m_localPlayer).transform.position)));
			}
			if (UnityInput.Current.GetKeyDown((KeyCode)93) && !processing)
			{
				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))
			{
				highlightEnabled = !highlightEnabled;
				RefreshHighlights();
				ShowMessage(highlightEnabled ? "Cluster highlighting enabled" : "Cluster highlighting disabled");
			}
			if (UnityInput.Current.GetKeyDown((KeyCode)289) && !processing)
			{
				((MonoBehaviour)this).StartCoroutine(RestoreAllParked());
			}
			DrawGpuRenderTest();
			ProcessPendingColliders();
			if (!processing && Time.time >= nextCellCheck)
			{
				nextCellCheck = Time.time + 0.5f;
				UpdateVisibleClusters();
			}
		}

		private void DrawGpuRenderTest()
		{
			//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_002d: 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_0048: 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_0055: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)Player.m_localPlayer).transform.position;
			Vector3 val = default(Vector3);
			foreach (KeyValuePair<Vector2Int, List<GpuDrawGroup>> gpuBakedGroup in gpuBakedGroups)
			{
				Vector2Int key = gpuBakedGroup.Key;
				float num = ((float)((Vector2Int)(ref key)).x + 0.5f) * 64f;
				float y = position.y;
				key = gpuBakedGroup.Key;
				((Vector3)(ref val))..ctor(num, y, ((float)((Vector2Int)(ref key)).y + 0.5f) * 64f);
				float num2 = Vector3.Distance(position, val);
				foreach (GpuDrawGroup item in gpuBakedGroup.Value)
				{
					if (item.usesTessellation)
					{
						bool flag = (item.tessellationEnabled ? (num2 < 128f) : (num2 < 96f));
						if (flag != item.tessellationEnabled)
						{
							item.tessellationEnabled = flag;
							if (flag)
							{
								item.material.EnableKeyword("TESSELATION_ON");
							}
							else
							{
								item.material.DisableKeyword("TESSELATION_ON");
							}
						}
					}
					foreach (Matrix4x4[] chunk in item.chunks)
					{
						Graphics.DrawMeshInstanced(item.mesh, item.subMesh, item.material, chunk, chunk.Length, (MaterialPropertyBlock)null, (ShadowCastingMode)0, true, 0);
					}
				}
			}
		}

		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_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: 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_02b2: Invalid comparison between Unknown and I4
			//IL_0140: 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)
			{
				MeshFilter[] componentsInChildren = ((Component)target.piece).GetComponentsInChildren<MeshFilter>(false);
				foreach (MeshFilter val in componentsInChildren)
				{
					MeshRenderer component = ((Component)val).GetComponent<MeshRenderer>();
					if ((Object)(object)component == (Object)null || !((Renderer)component).enabled || (Object)(object)val.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 < val.sharedMesh.subMeshCount && num < ((Renderer)component).sharedMaterials.Length; num++)
					{
						Material val2 = ((Renderer)component).sharedMaterials[num];
						if (!((Object)(object)val2 == (Object)null))
						{
							string key = $"{((Object)val.sharedMesh).GetInstanceID()}|{num}|{((Object)val2).GetInstanceID()}";
							if (!dictionary.TryGetValue(key, out var value))
							{
								value = (dictionary[key] = (val.sharedMesh, num, val2, new List<Matrix4x4>()));
							}
							value.Item4.Add(((Component)val).transform.localToWorldMatrix);
						}
					}
				}
			}
			foreach (var value2 in dictionary.Values)
			{
				Material val3 = Object.Instantiate<Material>(value2.Item3);
				val3.enableInstancing = true;
				GpuDrawGroup gpuDrawGroup = new GpuDrawGroup
				{
					mesh = value2.Item1,
					subMesh = value2.Item2,
					material = val3,
					usesTessellation = val3.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[] componentsInChildren2 = cluster.GetComponentsInChildren<MeshRenderer>(false);
			foreach (MeshRenderer val4 in componentsInChildren2)
			{
				if (!((Object)(object)val4 == (Object)null) && ((Renderer)val4).enabled && (int)((Renderer)val4).shadowCastingMode != 3)
				{
					list2.Add(val4);
					((Renderer)val4).enabled = false;
				}
			}
			gpuBakedGroups[cell] = list;
			gpuClusterHidden[cell] = list2;
			BuildRoofDepthRenderers(cell, cluster, list);
			int num3 = list.Sum((GpuDrawGroup group) => group.chunks.Sum((Matrix4x4[] chunk) => chunk.Length));
			int num4 = list.Sum((GpuDrawGroup group) => group.chunks.Count);
			int num5 = list.Count((GpuDrawGroup group) => group.usesTessellation);
			((BaseUnityPlugin)this).Logger.LogInfo((object)($"[GPU-BAKE] cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: {targets.Count} parked targets, " + $"{list.Count} groups, {num3} instances, {num4} draw batches, " + $"tessellatedGroups={num5}, shadows=proxy"));
		}

		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 || !NormalizeMaterialName(((Object)group.material).name).Equals("RoofShingles", StringComparison.OrdinalIgnoreCase))
				{
					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 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_00b7: 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;
			}
			foreach (GpuDrawGroup item2 in value2)
			{
				if ((Object)(object)item2.material != (Object)null)
				{
					Object.Destroy((Object)(object)item2.material);
				}
			}
			gpuBakedGroups.Remove(cell);
		}

		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_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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: 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_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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)
			{
				return;
			}
			Vector3 position = ((Component)Player.m_localPlayer).transform.position;
			Vector2i zone = ZoneSystem.GetZone(position);
			int num = Mathf.Max(1, ZoneSystem.instance.m_activeArea);
			foreach (Vector2Int item in clusters.Keys.ToList())
			{
				if (!CellOverlapsValheimArea(item, zone, num + 1))
				{
					DestroyCluster(item);
				}
			}
			Vector2Int? val = null;
			float num2 = float.MaxValue;
			foreach (Vector2Int key in records.Keys)
			{
				Vector2Int current2 = key;
				if (!clusters.ContainsKey(current2) && !failedCacheCells.Contains(current2) && CellOverlapsValheimArea(current2, zone, num))
				{
					Vector3 val2 = new Vector3(((float)((Vector2Int)(ref current2)).x + 0.5f) * 64f, position.y, ((float)((Vector2Int)(ref current2)).y + 0.5f) * 64f) - position;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (!(sqrMagnitude >= num2))
					{
						num2 = sqrMagnitude;
						val = current2;
					}
				}
			}
			if (val.HasValue && !TryLoadClusterCache(val.Value))
			{
				ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
				Vector2Int value = val.Value;
				object arg = ((Vector2Int)(ref value)).x;
				value = val.Value;
				logger.LogWarning((object)$"Cached cluster unavailable for visible cell {arg},{((Vector2Int)(ref value)).y}; starting verified rebuild");
				((MonoBehaviour)this).StartCoroutine(RebuildParkedCell(val.Value));
			}
		}

		private static bool CellOverlapsValheimArea(Vector2Int cell, Vector2i centerZone, int rings)
		{
			//IL_002d: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)((Vector2Int)(ref cell)).x * 64f;
			float num2 = num + 64f;
			float num3 = (float)((Vector2Int)(ref cell)).y * 64f;
			float num4 = num3 + 64f;
			float num5 = (float)(centerZone.x - rings) * 64f - 32f;
			float num6 = (float)(centerZone.x + rings) * 64f + 32f;
			float num7 = (float)(centerZone.y - rings) * 64f - 32f;
			float num8 = (float)(centerZone.y + rings) * 64f + 32f;
			if (num2 >= num5 && num <= num6 && num4 >= num7)
			{
				return num3 <= num8;
			}
			return false;
		}

		private IEnumerator BakeCell(Vector2Int cell)
		{
			//IL_000e: 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)
			processing = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Bake start cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}");
			if (clusters.ContainsKey(cell))
			{
				ShowMessage("This cell is already baked");
				processing = false;
				yield break;
			}
			if (records.ContainsKey(cell))
			{
				if (!TryLoadClusterCache(cell))
				{
					ShowMessage("Baked cell cache is missing or corrupted");
				}
				processing = false;
				yield break;
			}
			List<(ZNetView, Piece)> list = CollectTargets(cell);
			int num = list.Count<(ZNetView, Piece)>(((ZNetView view, Piece piece) target) => (Object)(object)target.piece != (Object)null && ((Object)target.piece).name.IndexOf("flametal", StringComparison.OrdinalIgnoreCase) >= 0);
			int num2 = list.Count<(ZNetView, Piece)>(((ZNetView view, Piece piece) target) => (Object)(object)target.piece != (Object)null && ((Object)target.piece).name.IndexOf("darkwood_roof", StringComparison.OrdinalIgnoreCase) >= 0);
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"[TARGET-FILTER] cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: flametal={num}, darkwood_roof={num2}");
			if (list.Count == 0)
			{
				ShowMessage("No supported building pieces in this cell");
				processing = false;
				yield break;
			}
			List<BakedRecord> list2 = CreateRecords(list);
			records[cell] = list2;
			GameObject val = BuildCluster(cell, list, list2);
			if ((Object)(object)val == (Object)null)
			{
				records.Remove(cell);
				ShowMessage("Failed to create cluster");
				processing = false;
				yield break;
			}
			if (!TrySaveClusterCache(cell, val, list2))
			{
				Object.Destroy((Object)(object)val);
				records.Remove(cell);
				ShowMessage("Bake cancelled: cluster cache was not saved");
				processing = false;
				yield break;
			}
			failedCacheCells.Remove(cell);
			clusters[cell] = val;
			EnableGpuBakedRenderTest(cell, list, val);
			if (!TrySaveGpuCache(cell, list2))
			{
				RemoveGpuBakedCell(cell, restoreRenderers: true);
				Object.Destroy((Object)(object)val);
				clusters.Remove(cell);
				records.Remove(cell);
				ShowMessage("Bake cancelled: unreadable GPU cache was not saved");
				processing = false;
				yield break;
			}
			if (highlightEnabled)
			{
				RefreshHighlights();
			}
			foreach (var item in list)
			{
				Park(item.Item1, cell);
			}
			Physics.SyncTransforms();
			supportGuardUntil = Mathf.Max(supportGuardUntil, Time.time + 10f);
			SaveState();
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Bake complete cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: {list2.Count} ZDO");
			ShowMessage($"Baked objects: {list2.Count}");
			processing = false;
			yield return null;
		}

		private IEnumerator RebuildParkedCell(Vector2Int cell)
		{
			//IL_000e: 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)
			processing = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Rebuild parked cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}");
			List<BakedRecord> existing;
			int expected = (records.TryGetValue(cell, out existing) ? existing.Count : 0);
			int num = RestoreRecords(cell, removeRecords: false);
			if (num != expected)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Rebuild blocked for cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: restored {num}/{expected}");
				processing = false;
				yield break;
			}
			List<(ZNetView view, Piece piece)> targets = new List<(ZNetView, Piece)>();
			float deadline = Time.time + 180f;
			while (Time.time < deadline)
			{
				targets = CollectMarkedTargets(cell);
				if (targets.Count >= expected)
				{
					break;
				}
				yield return null;
			}
			if (targets.Count != expected)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Rebuild timed out for cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: loaded {targets.Count}/{expected}");
				ShowMessage("Cluster not created: some pieces are not loaded");
				processing = false;
				yield break;
			}
			if (targets.Count > 0)
			{
				List<BakedRecord> list = CreateRecords(targets);
				GameObject val = BuildCluster(cell, targets, list);
				if ((Object)(object)val != (Object)null && TrySaveClusterCache(cell, val, list))
				{
					records[cell] = list;
					clusters[cell] = val;
					failedCacheCells.Remove(cell);
					if (highlightEnabled)
					{
						RefreshHighlights();
					}
					foreach (var item in targets)
					{
						Park(item.view, cell);
					}
					Physics.SyncTransforms();
					supportGuardUntil = Mathf.Max(supportGuardUntil, Time.time + 10f);
					SaveState();
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Rebuild complete cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: {list.Count} ZDO");
				}
				else
				{
					if ((Object)(object)val != (Object)null)
					{
						Object.Destroy((Object)(object)val);
					}
					foreach (BakedRecord item2 in existing)
					{
						ZDO zDO = ZDOMan.instance.GetZDO(new ZDOID(item2.userId, item2.id));
						if (zDO != null)
						{
							ClearBakedMetadata(zDO);
						}
					}
					records.Remove(cell);
					SaveState();
					((BaseUnityPlugin)this).Logger.LogError((object)$"Rebuild cache save failed cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}; objects left safely unpacked");
				}
			}
			processing = false;
			yield return null;
		}

		private IEnumerator UnbakeCell(Vector2Int cell)
		{
			//IL_000e: 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)
			processing = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Unbake cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}");
			List<BakedRecord> value;
			int expected = (records.TryGetValue(cell, out value) ? value.Count : 0);
			List<BakedRecord> unbakeRecords = ((value != null) ? value.ToList() : new List<BakedRecord>());
			if (!TryGetValidatedParkedZDOs(cell, out var parked) || parked.Count != expected)
			{
				if ((parked == null || parked.Count == 0) && expected > 0 && TryForgetConfirmedRestoredCell(cell, unbakeRecords, out var message))
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)$"Safely removed stale cache cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: {message}");
					ShowMessage("Stale cache removed; original objects were verified");
					processing = false;
					yield break;
				}
				((BaseUnityPlugin)this).Logger.LogError((object)$"Unbake blocked for cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: validated {parked?.Count ?? 0}/{expected}");
				ShowMessage("Unbake blocked: object validation failed");
				processing = false;
				yield break;
			}
			float unbakeStarted = Time.realtimeSinceStartup;
			supportGuardUntil = Mathf.Max(supportGuardUntil, Time.time + 190f);
			int restored = 0;
			while (restored < parked.Count)
			{
				float realtimeSinceStartup = Time.realtimeSinceStartup;
				int num = 0;
				do
				{
					ZDO val = parked[restored++];
					Vector3 vec = val.GetVec3("PUP_SAFE_Position", Vector3.zero);
					Quaternion quaternion = val.GetQuaternion("PUP_SAFE_Rotation", Quaternion.identity);
					val.SetPosition(vec);
					val.SetRotation(quaternion);
					ZNetView val2 = ZNetScene.instance.FindInstance(val);
					if ((Object)(object)val2 != (Object)null)
					{
						((Component)val2).transform.position = vec;
						((Component)val2).transform.rotation = quaternion;
						HideOriginalRenderers(val2);
					}
					num++;
				}
				while (restored < parked.Count && num < 128 && (Time.realtimeSinceStartup - realtimeSinceStartup) * 1000f < 2f);
				yield return null;
			}
			float deadline = Time.time + 180f;
			Queue<BakedRecord> pending = new Queue<BakedRecord>(unbakeRecords);
			int loaded = 0;
			while (pending.Count != 0 && Time.time < deadline)
			{
				int num2 = Mathf.Min(256, pending.Count);
				for (int i = 0; i < num2; i++)
				{
					BakedRecord bakedRecord = pending.Dequeue();
					ZDO zDO = ZDOMan.instance.GetZDO(new ZDOID(bakedRecord.userId, bakedRecord.id));
					ZNetView val3 = ((zDO != null) ? ZNetScene.instance.FindInstance(zDO) : null);
					if ((Object)(object)val3 != (Object)null)
					{
						HideOriginalRenderers(val3);
						loaded++;
					}
					else
					{
						pending.Enqueue(bakedRecord);
					}
				}
				yield return null;
			}
			if (loaded != expected)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Unbake staging timed out cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: loaded {loaded}/{expected}; cluster retained");
				ShowMessage($"Unbake is waiting for pieces: {loaded}/{expected}");
				processing = false;
				yield break;
			}
			int cleared = 0;
			while (cleared < unbakeRecords.Count)
			{
				float realtimeSinceStartup2 = Time.realtimeSinceStartup;
				int num3 = 0;
				do
				{
					BakedRecord bakedRecord2 = unbakeRecords[cleared++];
					ZDO zDO2 = ZDOMan.instance.GetZDO(new ZDOID(bakedRecord2.userId, bakedRecord2.id));
					if (zDO2 != null)
					{
						ClearBakedMetadata(zDO2);
					}
					num3++;
				}
				while (cleared < unbakeRecords.Count && num3 < 256 && (Time.realtimeSinceStartup - realtimeSinceStartup2) * 1000f < 2f);
				yield return null;
			}
			records.Remove(cell);
			Physics.SyncTransforms();
			supportGuardUntil = Mathf.Max(supportGuardUntil, Time.time + 10f);
			int shown = 0;
			while (shown < unbakeRecords.Count)
			{
				float realtimeSinceStartup3 = Time.realtimeSinceStartup;
				int num4 = 0;
				do
				{
					BakedRecord bakedRecord3 = unbakeRecords[shown++];
					ZDO zDO3 = ZDOMan.instance.GetZDO(new ZDOID(bakedRecord3.userId, bakedRecord3.id));
					ZNetView val4 = ((zDO3 != null) ? ZNetScene.instance.FindInstance(zDO3) : null);
					if ((Object)(object)val4 != (Object)null)
					{
						ShowOriginalRenderers(val4);
					}
					num4++;
				}
				while (shown < unbakeRecords.Count && num4 < 128 && (Time.realtimeSinceStartup - realtimeSinceStartup3) * 1000f < 2f);
				yield return null;
			}
			DestroyCluster(cell);
			SaveState();
			((BaseUnityPlugin)this).Logger.LogInfo((object)($"Unbake complete cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: {restored} ZDO in " + $"{Time.realtimeSinceStartup - unbakeStarted:0.00}s"));
			ShowMessage($"Restored objects: {restored}");
			processing = false;
			yield return null;
		}

		private bool TryForgetConfirmedRestoredCell(Vector2Int cell, List<BakedRecord> cellRecords, out string message)
		{
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: 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_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			message = "";
			if (cellRecords == null || cellRecords.Count == 0 || ZDOMan.instance == null)
			{
				return false;
			}
			Dictionary<string, ZDO> dictionary = new Dictionary<string, ZDO>(StringComparer.Ordinal);
			Dictionary<string, List<ZDO>> dictionary2 = new Dictionary<string, List<ZDO>>(StringComparer.Ordinal);
			ZNetView[] array = Object.FindObjectsByType<ZNetView>((FindObjectsSortMode)0);
			foreach (ZNetView val in array)
			{
				if ((Object)(object)val == (Object)null || !val.IsValid() || val.GetZDO() == null || (Object)(object)((Component)val).GetComponent<Piece>() == (Object)null)
				{
					continue;
				}
				ZDO zDO = val.GetZDO();
				if (!zDO.GetBool("PUP_SAFE_Baked", false) && !(Mathf.Abs(zDO.GetPosition().x - 1900000f) < 1024f))
				{
					string text = zDO.GetString("PUP_GRAUSTEN_ID", "");
					if (!string.IsNullOrEmpty(text) && !dictionary.ContainsKey(text))
					{
						dictionary[text] = zDO;
					}
					string key = RecordPositionKey(zDO.GetPrefab(), zDO.GetPosition());
					if (!dictionary2.TryGetValue(key, out var value))
					{
						value = (dictionary2[key] = new List<ZDO>());
					}
					value.Add(zDO);
				}
			}
			int num = 0;
			HashSet<ZDOID> used = new HashSet<ZDOID>();
			foreach (BakedRecord record in cellRecords)
			{
				ZDO val2 = ZDOMan.instance.GetZDO(new ZDOID(record.userId, record.id));
				if (!MatchesRestoredRecord(val2, record) && !string.IsNullOrEmpty(record.customId))
				{
					dictionary.TryGetValue(record.customId, out var value2);
					val2 = (MatchesRestoredRecord(value2, record) ? value2 : null);
				}
				if (!MatchesRestoredRecord(val2, record))
				{
					string key2 = RecordPositionKey(record.prefabHash, record.position);
					val2 = null;
					if (dictionary2.TryGetValue(key2, out var value3))
					{
						val2 = ((IEnumerable<ZDO>)value3).FirstOrDefault((Func<ZDO, bool>)((ZDO candidate) => !used.Contains(candidate.m_uid) && MatchesRestoredRecord(candidate, record)));
					}
				}
				if (val2 == null)
				{
					message = $"missing exact prefab/position/rotation match {num + 1}/{cellRecords.Count}";
					return false;
				}
				if (!used.Add(val2.m_uid))
				{
					message = "one ordinary object matched more than one cache record";
					return false;
				}
				num++;
			}
			records.Remove(cell);
			DestroyCluster(cell);
			failedCacheCells.Remove(cell);
			DeleteCellCacheFiles(cell);
			SaveState();
			message = $"verified {num}/{cellRecords.Count} original objects";
			return true;
		}

		private static bool MatchesRestoredRecord(ZDO zdo, BakedRecord record)
		{
			//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_0043: 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_004f: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			if (zdo == null || record == null || zdo.GetBool("PUP_SAFE_Baked", false) || zdo.GetPrefab() != record.prefabHash)
			{
				return false;
			}
			Vector3 position = zdo.GetPosition();
			if (!(Mathf.Abs(position.x - 1900000f) < 1024f))
			{
				Vector3 val = position - record.position;
				if (!(((Vector3)(ref val)).sqrMagnitude > 0.0004f))
				{
					return Quaternion.Angle(zdo.GetRotation(), record.rotation) <= 0.5f;
				}
			}
			return false;
		}

		private void DeleteCellCacheFiles(Vector2Int cell)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			string cachePath = GetCachePath(cell);
			string directoryName = Path.GetDirectoryName(cachePath);
			string fileName = Path.GetFileName(cachePath);
			if (string.IsNullOrEmpty(directoryName) || string.IsNullOrEmpty(fileName) || !Directory.Exists(directoryName))
			{
				return;
			}
			string[] files = Directory.GetFiles(directoryName, fileName + "*", SearchOption.TopDirectoryOnly);
			for (int i = 0; i < files.Length; i++)
			{
				string fullPath = Path.GetFullPath(files[i]);
				string fullPath2 = Path.GetFullPath(directoryName);
				char directorySeparatorChar = Path.DirectorySeparatorChar;
				if (fullPath.StartsWith(fullPath2 + directorySeparatorChar, StringComparison.OrdinalIgnoreCase))
				{
					try
					{
						File.Delete(fullPath);
					}
					catch (Exception ex)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not delete stale cache file " + Path.GetFileName(fullPath) + ": " + ex.Message));
					}
				}
			}
		}

		private List<(ZNetView view, Piece piece)> CollectTargets(Vector2Int cell)
		{
			//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)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			List<(ZNetView, Piece)> list = new List<(ZNetView, Piece)>();
			ZNetView[] array = Object.FindObjectsByType<ZNetView>((FindObjectsSortMode)0);
			foreach (ZNetView val in array)
			{
				if ((Object)(object)val == (Object)null || !val.IsValid() || val.GetZDO() == null || !ZNetScene.instance.HasPrefab(val.GetZDO().GetPrefab()))
				{
					continue;
				}
				Piece component = ((Component)val).GetComponent<Piece>();
				if (!((Object)(object)component == (Object)null) && ((Component)component).gameObject.activeInHierarchy && !(GetCell(GetPieceCenter(component)) != cell) && !((Object)(object)((Component)component).GetComponent<WearNTear>() == (Object)null))
				{
					bool num = HasMaterialGroup(component, 1);
					bool targetedUnreadable = IsTargetedUnreadablePiece(val);
					if (num || (IsSafeStaticPiece(component, targetedUnreadable) && HasSupportedRenderer(component)))
					{
						list.Add((val, component));
					}
				}
			}
			return list;
		}

		private List<(ZNetView view, Piece piece)> CollectMarkedTargets(Vector2Int cell)
		{
			List<(ZNetView, Piece)> list = new List<(ZNetView, Piece)>();
			ZNetView[] array = Object.FindObjectsByType<ZNetView>((FindObjectsSortMode)0);
			foreach (ZNetView val in array)
			{
				if ((Object)(object)val == (Object)null || !val.IsValid() || val.GetZDO() == null)
				{
					continue;
				}
				ZDO zDO = val.GetZDO();
				if (zDO.GetBool("PUP_SAFE_Baked", false) && zDO.GetInt("PUP_SAFE_CellX", int.MinValue) == ((Vector2Int)(ref cell)).x && zDO.GetInt("PUP_SAFE_CellZ", int.MinValue) == ((Vector2Int)(ref cell)).y)
				{
					Piece component = ((Component)val).GetComponent<Piece>();
					if (!((Object)(object)component == (Object)null) && ((Component)component).gameObject.activeInHierarchy)
					{
						list.Add((val, component));
					}
				}
			}
			return list;
		}

		private static Vector3 GetPieceCenter(Piece piece)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = ((Component)piece).GetComponentsInChildren<Renderer>(false);
			if (componentsInChildren.Length == 0)
			{
				return ((Component)piece).transform.position;
			}
			Bounds bounds = componentsInChildren[0].bounds;
			for (int i = 1; i < componentsInChildren.Length; i++)
			{
				((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds);
			}
			return ((Bounds)(ref bounds)).center;
		}

		private static int GetMaterialGroup(Material material)
		{
			if ((Object)(object)material == (Object)null)
			{
				return 0;
			}
			string text = NormalizeMaterialName(((Object)material).name);
			if (text.StartsWith("Grausten_mat", StringComparison.OrdinalIgnoreCase) || text.StartsWith("Grausten_Broken_mat", StringComparison.OrdinalIgnoreCase) || text.Equals("Grausten_RoofSlab_mat", StringComparison.OrdinalIgnoreCase))
			{
				return 1;
			}
			if (text.Equals("woodpole", StringComparison.OrdinalIgnoreCase) || text.Equals("woodpole2", StringComparison.OrdinalIgnoreCase) || text.Equals("woodpole_worn", StringComparison.OrdinalIgnoreCase) || text.Equals("woodwall", StringComparison.OrdinalIgnoreCase) || text.Equals("woodwall_lowlod", StringComparison.OrdinalIgnoreCase) || text.Equals("woodwall_worn", StringComparison.OrdinalIgnoreCase) || text.Equals("woodwall_worn_lowlod", StringComparison.OrdinalIgnoreCase) || text.Equals("stake", StringComparison.OrdinalIgnoreCase) || text.Equals("stake_old", StringComparison.OrdinalIgnoreCase))
			{
				return 2;
			}
			if ((text.StartsWith("DarkWood_", StringComparison.OrdinalIgnoreCase) || text.Equals("DarkWood_mat", StringComparison.OrdinalIgnoreCase) || text.Equals("RoofShingles", StringComparison.OrdinalIgnoreCase)) && text.IndexOf("door", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("gate", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return 3;
			}
			if (text.StartsWith("AshWood_", StringComparison.OrdinalIgnoreCase) && text.IndexOf("door", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("gate", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return 4;
			}
			if (text.Equals("logwall", StringComparison.OrdinalIgnoreCase) || text.Equals("logwall_broken", StringComparison.OrdinalIgnoreCase) || text.Equals("logwall_worn", StringComparison.OrdinalIgnoreCase) || text.Equals("finewood_log", StringComparison.OrdinalIgnoreCase) || text.Equals("roundlog_new", StringComparison.OrdinalIgnoreCase))
			{
				return 5;
			}
			if (text.Equals("straw_roof", StringComparison.OrdinalIgnoreCase) || text.Equals("straw_roof_alpha", StringComparison.OrdinalIgnoreCase) || text.Equals("straw_roof_corner_alpha", StringComparison.OrdinalIgnoreCase) || text.Equals("straw_roof_worn", StringComparison.OrdinalIgnoreCase) || text.Equals("straw_roof_worn_alpha", StringComparison.OrdinalIgnoreCase))
			{
				return 6;
			}
			if (text.Equals("stone_mat", StringComparison.OrdinalIgnoreCase) || text.Equals("stone_mat_4x2", StringComparison.OrdinalIgnoreCase) || text.Equals("stonefloor", StringComparison.OrdinalIgnoreCase) || text.Equals("stonefloor_2x2", StringComparison.OrdinalIgnoreCase) || text.Equals("stone_stairs", StringComparison.OrdinalIgnoreCase) || text.Equals("stone", StringComparison.OrdinalIgnoreCase))
			{
				return 7;
			}
			if (text.Equals("blackmarble", StringComparison.OrdinalIgnoreCase))
			{
				return 8;
			}
			if (text.Equals("dvergr_copper", StringComparison.OrdinalIgnoreCase))
			{
				return 9;
			}
			if (text.Equals("flametalbeam_mat", StringComparison.OrdinalIgnoreCase))
			{
				return 10;
			}
			if (text.Equals("crystal_window", StringComparison.OrdinalIgnoreCase) || text.Equals("crystal_window_lod", StringComparison.OrdinalIgnoreCase))
			{
				return 11;
			}
			return 0;
		}

		private static bool HasSupportedRenderer(Piece piece)
		{
			return ((Component)piece).GetComponentsInChildren<MeshRenderer>(false).Any((MeshRenderer renderer) => ((Renderer)renderer).sharedMaterials.Any((Material material) => GetMaterialGroup(material) != 0));
		}

		private static bool HasMaterialGroup(Piece piece, int group)
		{
			return ((Component)piece).GetComponentsInChildren<MeshRenderer>(false).Any((MeshRenderer renderer) => ((Renderer)renderer).sharedMaterials.Any((Material material) => GetMaterialGroup(material) == group));
		}

		private static bool IsTargetedUnreadablePiece(ZNetView view)
		{
			if ((Object)(object)view == (Object)null || view.GetZDO() == null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return false;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(view.GetZDO().GetPrefab());
			if ((Object)(object)prefab == (Object)null)
			{
				return false;
			}
			string text = ((Object)prefab).name ?? "";
			if (!text.StartsWith("Piece_flametal_", StringComparison.OrdinalIgnoreCase) && !text.Equals("darkwood_roof", StringComparison.OrdinalIgnoreCase) && !text.Equals("darkwood_roof_45", StringComparison.OrdinalIgnoreCase) && !text.Equals("darkwood_roof_top", StringComparison.OrdinalIgnoreCase))
			{
				return text.Equals("darkwood_roof_top_45", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static bool IsSafeStaticPiece(Piece piece, bool targetedUnreadable)
		{
			if ((Object)(object)piece == (Object)null || (Object)(object)((Component)piece).GetComponent<WearNTear>() == (Object)null)
			{
				return false;
			}
			if (((Component)piece).GetComponentsInChildren<Animator>(true).Length != 0)
			{
				return false;
			}
			Rigidbody[] componentsInChildren = ((Component)piece).GetComponentsInChildren<Rigidbody>(true);
			foreach (Rigidbody val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && !val.isKinematic)
				{
					return false;
				}
			}
			string[] source = new string[17]
			{
				"Door", "Container", "CraftingStation", "Fermenter", "Smelter", "Fireplace", "Bed", "Chair", "Ship", "TeleportWorld",
				"ItemStand", "ArmorStand", "Switch", "Lever", "Sign", "Beehive", "SapCollector"
			};
			Component[] componentsInChildren2 = ((Component)piece).GetComponentsInChildren<Component>(true);
			foreach (Component val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					string typeName = ((object)val2).GetType().Name;
					if (source.Any((string value) => typeName.Equals(value, StringComparison.OrdinalIgnoreCase)))
					{
						return false;
					}
				}
			}
			MeshRenderer[] componentsInChildren3 = ((Component)piece).GetComponentsInChildren<MeshRenderer>(false);
			foreach (MeshRenderer val3 in componentsInChildren3)
			{
				Material[] sharedMaterials = ((Renderer)val3).sharedMaterials;
				if (sharedMaterials.Length == 0 || sharedMaterials.Any((Material value) => (Object)(object)value == (Object)null))
				{
					return false;
				}
				if (!targetedUnreadable && sharedMaterials.Any((Material value) => NormalizeMaterialName(((Object)value).name).Equals("RoofShingles", StringComparison.OrdinalIgnoreCase)))
				{
					return false;
				}
				MeshFilter component = ((Component)val3).GetComponent<MeshFilter>();
				if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null)
				{
					return false;
				}
				if (!targetedUnreadable && !component.sharedMesh.isReadable)
				{
					return false;
				}
				if ((!targetedUnreadable && ((Renderer)val3).sharedMaterials.Length != component.sharedMesh.subMeshCount) || (targetedUnreadable && ((Renderer)val3).sharedMaterials.Length < component.sharedMesh.subMeshCount))
				{
					return false;
				}
			}
			return true;
		}

		private List<BakedRecord> CreateRecords(List<(ZNetView view, Piece piece)> targets)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00d0: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			List<BakedRecord> list = new List<BakedRecord>();
			foreach (var target in targets)
			{
				ZDO zDO = target.view.GetZDO();
				string text = zDO.GetString("PUP_GRAUSTEN_ID", "");
				if (string.IsNullOrEmpty(text))
				{
					text = "PUP_GRAUSTEN_" + Guid.NewGuid().ToString("N");
					zDO.Set("PUP_GRAUSTEN_ID", text);
				}
				list.Add(new BakedRecord
				{
					customId = text,
					userId = ((ZDOID)(ref zDO.m_uid)).UserID,
					id = ((ZDOID)(ref zDO.m_uid)).ID,
					prefabHash = zDO.GetPrefab(),
					position = ((Component)target.piece).transform.position,
					rotation = ((Component)target.piece).transform.rotation,
					scale = ((Component)target.piece).transform.localScale
				});
			}
			return list;
		}

		private GameObject BuildCluster(Vector2Int cell, List<(ZNetView view, Piece piece)> targets, List<BakedRecord> cellRecords)
		{
			//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_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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Expected O, but got Unknown
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Expected O, but got Unknown
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Expected O, but got Unknown
			//IL_0480: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Unknown result type (might be due to invalid IL or missing references)
			//IL_0495: Unknown result type (might be due to invalid IL or missing references)
			//IL_049a: 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_04b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c5: 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_055f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: 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_021e: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<Vector2Int, Dictionary<string, MaterialCombineGroup>> dictionary = new Dictionary<Vector2Int, Dictionary<string, MaterialCombineGroup>>();
			List<Mesh> list = new List<Mesh>();
			List<Mesh> list2 = new List<Mesh>();
			Matrix4x4 val = Matrix4x4.Translate(-new Vector3((float)((Vector2Int)(ref cell)).x * 64f, 0f, (float)((Vector2Int)(ref cell)).y * 64f));
			Vector2Int key = default(Vector2Int);
			CombineInstance item;
			foreach (var target in targets)
			{
				Vector3 pieceCenter = GetPieceCenter(target.piece);
				int num = Mathf.Clamp(Mathf.FloorToInt((pieceCenter.x - (float)((Vector2Int)(ref cell)).x * 64f) / 16f), 0, 3);
				int num2 = Mathf.Clamp(Mathf.FloorToInt((pieceCenter.z - (float)((Vector2Int)(ref cell)).y * 64f) / 16f), 0, 3);
				((Vector2Int)(ref key))..ctor(num, num2);
				if (!dictionary.TryGetValue(key, out var value))
				{
					value = (dictionary[key] = new Dictionary<string, MaterialCombineGroup>(StringComparer.Ordinal));
				}
				MeshFilter[] componentsInChildren = ((Component)target.piece).GetComponentsInChildren<MeshFilter>(false);
				foreach (MeshFilter val2 in componentsInChildren)
				{
					MeshRenderer component = ((Component)val2).GetComponent<MeshRenderer>();
					if ((Object)(object)component == (Object)null || !((Renderer)component).enabled || (Object)(object)val2.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))) || !val2.sharedMesh.isReadable)
					{
						continue;
					}
					Mesh val3 = Object.Instantiate<Mesh>(val2.sharedMesh);
					list.Add(val3);
					for (int num3 = 0; num3 < val3.subMeshCount && num3 < ((Renderer)component).sharedMaterials.Length; num3++)
					{
						Material val4 = ((Renderer)component).sharedMaterials[num3];
						if (!((Object)(object)val4 == (Object)null))
						{
							string key2 = NormalizeMaterialName(((Object)val4).name);
							if (!value.TryGetValue(key2, out var value2))
							{
								MaterialCombineGroup obj = new MaterialCombineGroup
								{
									source = val4
								};
								value2 = (value[key2] = obj);
							}
							List<CombineInstance> parts = value2.parts;
							item = default(CombineInstance);
							((CombineInstance)(ref item)).mesh = val3;
							((CombineInstance)(ref item)).subMeshIndex = num3;
							((CombineInstance)(ref item)).transform = val * ((Component)val2).transform.localToWorldMatrix;
							parts.Add(item);
						}
					}
				}
			}
			if (dictionary.Count == 0)
			{
				foreach (Mesh item2 in list)
				{
					Object.Destroy((Object)(object)item2);
				}
				return null;
			}
			GameObject val5 = new GameObject($"PUP_SafeCluster_{((Vector2Int)(ref cell)).x}_{((Vector2Int)(ref cell)).y}");
			val5.transform.position = new Vector3((float)((Vector2Int)(ref cell)).x * 64f, 0f, (float)((Vector2Int)(ref cell)).y * 64f);
			foreach (KeyValuePair<Vector2Int, Dictionary<string, MaterialCombineGroup>> item3 in dictionary.OrderBy(delegate(KeyValuePair<Vector2Int, Dictionary<string, MaterialCombineGroup>> keyValuePair)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				Vector2Int key4 = keyValuePair.Key;
				return ((Vector2Int)(ref key4)).y;
			}).ThenBy(delegate(KeyValuePair<Vector2Int, Dictionary<string, MaterialCombineGroup>> keyValuePair)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				Vector2Int key4 = keyValuePair.Key;
				return ((Vector2Int)(ref key4)).x;
			}))
			{
				List<CombineInstance> list3 = new List<CombineInstance>();
				List<Material> list4 = new List<Material>();
				foreach (KeyValuePair<string, MaterialCombineGroup> item4 in item3.Value)
				{
					Mesh val6 = new Mesh
					{
						indexFormat = (IndexFormat)1
					};
					val6.CombineMeshes(item4.Value.parts.ToArray(), true, true, false);
					list.Add(val6);
					item = default(CombineInstance);
					((CombineInstance)(ref item)).mesh = val6;
					((CombineInstance)(ref item)).transform = Matrix4x4.identity;
					list3.Add(item);
					if (!materialCopies.TryGetValue(item4.Key, out var value3) || (Object)(object)value3 == (Object)null)
					{
						value3 = Object.Instantiate<Material>(item4.Value.source);
						materialCopies[item4.Key] = value3;
					}
					list4.Add(value3);
				}
				Mesh val7 = new Mesh
				{
					indexFormat = (IndexFormat)1
				};
				val7.CombineMeshes(list3.ToArray(), false, false, false);
				list2.Add(val7);
				Vector2Int key3 = item3.Key;
				object arg = ((Vector2Int)(ref key3)).x;
				key3 = item3.Key;
				GameObject val8 = new GameObject($"PUP_SubCluster_{arg}_{((Vector2Int)(ref key3)).y}");
				val8.transform.SetParent(val5.transform, false);
				val8.AddComponent<MeshFilter>().sharedMesh = val7;
				MeshRenderer val9 = val8.AddComponent<MeshRenderer>();
				((Renderer)val9).sharedMaterials = list4.ToArray();
				RegisterPrecipitationRenderer(cell, val9);
			}
			CloneOriginalColliders(val5, targets);
			BuildShadowProxies(val5, targets, list2);
			foreach (Mesh item5 in list)
			{
				if ((Object)(object)item5 != (Object)null)
				{
					Object.Destroy((Object)(object)item5);
				}
			}
			generatedMeshes[cell] = list2;
			return val5;
		}

		private void BuildShadowProxies(GameObject root, List<(ZNetView view, Piece piece)> targets, List<Mesh> finalMeshes)
		{
			//IL_0021: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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_00d0: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Expected O, but got Unknown
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: 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_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			Mesh builtinResource = Resources.GetBuiltinResource<Mesh>("Cube.fbx");
			if ((Object)(object)builtinResource == (Object)null)
			{
				return;
			}
			Dictionary<Vector2Int, List<CombineInstance>> dictionary = new Dictionary<Vector2Int, List<CombineInstance>>();
			Matrix4x4 worldToLocalMatrix = root.transform.worldToLocalMatrix;
			Material val = null;
			Vector2Int key = default(Vector2Int);
			foreach (var target in targets)
			{
				BoxCollider[] componentsInChildren = ((Component)target.piece).GetComponentsInChildren<BoxCollider>(false);
				foreach (BoxCollider val2 in componentsInChildren)
				{
					if ((Object)(object)val2 == (Object)null || !((Collider)val2).enabled || ((Collider)val2).isTrigger)
					{
						continue;
					}
					Vector3 val3 = Vector3.Scale(val2.size, ((Component)val2).transform.lossyScale);
					if (val3.x * val3.y * val3.z < 0.2f)
					{
						continue;
					}
					Vector3 val4 = ((Component)val2).transform.TransformPoint(val2.center);
					int num = Mathf.Clamp(Mathf.FloorToInt((val4.x - root.transform.position.x) / 16f), 0, 3);
					int num2 = Mathf.Clamp(Mathf.FloorToInt((val4.z - root.transform.position.z) / 16f), 0, 3);
					((Vector2Int)(ref key))..ctor(num, num2);
					if (!dictionary.TryGetValue(key, out var value))
					{
						value = (dictionary[key] = new List<CombineInstance>());
					}
					List<CombineInstance> list2 = value;
					CombineInstance item = default(CombineInstance);
					((CombineInstance)(ref item)).mesh = builtinResource;
					((CombineInstance)(ref item)).subMeshIndex = 0;
					((CombineInstance)(ref item)).transform = worldToLocalMatrix * Matrix4x4.TRS(val4, ((Component)val2).transform.rotation, val3);
					list2.Add(item);
					if ((Object)(object)val == (Object)null)
					{
						MeshRenderer componentInChildren = ((Component)target.piece).GetComponentInChildren<MeshRenderer>(false);
						if ((Object)(object)componentInChildren != (Object)null)
						{
							val = ((Renderer)componentInChildren).sharedMaterial;
						}
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Vector2Int val6;
			foreach (KeyValuePair<Vector2Int, List<CombineInstance>> item2 in dictionary)
			{
				if (item2.Value.Count != 0)
				{
					Mesh val5 = new Mesh
					{
						indexFormat = (IndexFormat)1
					};
					val5.CombineMeshes(item2.Value.ToArray(), true, true, false);
					finalMeshes.Add(val5);
					val6 = item2.Key;
					object arg = ((Vector2Int)(ref val6)).x;
					val6 = item2.Key;
					GameObject val7 = new GameObject($"PUP_ShadowProxy_{arg}_{((Vector2Int)(ref val6)).y}");
					val7.transform.SetParent(root.transform, false);
					val7.AddComponent<MeshFilter>().sharedMesh = val5;
					MeshRenderer obj = val7.AddComponent<MeshRenderer>();
					((Renderer)obj).sharedMaterial = val;
					((Renderer)obj).shadowCastingMode = (ShadowCastingMode)3;
					((Renderer)obj).receiveShadows = false;
				}
			}
			ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
			val6 = GetCell(root.transform.position);
			string text = $"[SHADOW-PROXY] cell {((Vector2Int)(ref val6)).x},";
			val6 = GetCell(root.transform.position);
			logger.LogInfo((object)(text + $"{((Vector2Int)(ref val6)).y}: {dictionary.Sum((KeyValuePair<Vector2Int, List<CombineInstance>> keyValuePair) => keyValuePair.Value.Count)} boxes, " + $"{dictionary.Count} proxy meshes"));
		}

		private static void CloneOriginalColliders(GameObject root, List<(ZNetView view, Piece piece)> targets)
		{
			foreach (var target in targets)
			{
				Collider[] componentsInChildren = ((Component)target.piece).GetComponentsInChildren<Collider>(false);
				foreach (Collider val in componentsInChildren)
				{
					if ((Object)(object)val != (Object)null && val.enabled)
					{
						CloneSingleCollider(root, val);
					}
				}
			}
		}

		private static void CloneSingleCollider(GameObject root, Collider source)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_003a: 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_0066: 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_0090: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("PUP_Collider")
			{
				layer = ((Component)source).gameObject.layer
			};
			val.transform.SetParent(root.transform, false);
			val.transform.position = ((Component)source).transform.position;
			val.transform.rotation = ((Component)source).transform.rotation;
			val.transform.localScale = ((Component)source).transform.lossyScale;
			Collider val2 = null;
			BoxCollider val3 = (BoxCollider)(object)((source is BoxCollider) ? source : null);
			if (val3 != null)
			{
				BoxCollider obj = val.AddComponent<BoxCollider>();
				obj.center = val3.center;
				obj.size = val3.size;
				val2 = (Collider)(object)obj;
			}
			else
			{
				SphereCollider val4 = (SphereCollider)(object)((source is SphereCollider) ? source : null);
				if (val4 != null)
				{
					SphereCollider obj2 = val.AddComponent<SphereCollider>();
					obj2.center = val4.center;
					obj2.radius = val4.radius;
					val2 = (Collider)(object)obj2;
				}
				else
				{
					CapsuleCollider val5 = (CapsuleCollider)(object)((source is CapsuleCollider) ? source : null);
					if (val5 != null)
					{
						CapsuleCollider obj3 = val.AddComponent<CapsuleCollider>();
						obj3.center = val5.center;
						obj3.radius = val5.radius;
						obj3.height = val5.height;
						obj3.direction = val5.direction;
						val2 = (Collider)(object)obj3;
					}
					else
					{
						MeshCollider val6 = (MeshCollider)(object)((source is MeshCollider) ? source : null);
						if (val6 != null && (Object)(object)val6.sharedMesh != (Object)null)
						{
							MeshCollider obj4 = val.AddComponent<MeshCollider>();
							obj4.sharedMesh = val6.sharedMesh;
							obj4.convex = val6.convex;
							val2 = (Collider)(object)obj4;
						}
					}
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				Object.Destroy((Object)(object)val);
				return;
			}
			val2.isTrigger = source.isTrigger;
			val2.sharedMaterial = source.sharedMaterial;
		}

		private void Park(ZNetView view, Vector2Int cell)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)view == (Object)null) && view.GetZDO() != null)
			{
				ZDO zDO = view.GetZDO();
				zDO.Set("PUP_SAFE_Baked", true);
				zDO.Set("PUP_SAFE_Position", ((Component)view).transform.position);
				zDO.Set("PUP_SAFE_Rotation", ((Component)view).transform.rotation);
				zDO.Set("PUP_SAFE_Scale", ((Component)view).transform.localScale);
				zDO.Set("PUP_SAFE_CellX", ((Vector2Int)(ref cell)).x);
				zDO.Set("PUP_SAFE_CellZ", ((Vector2Int)(ref cell)).y);
				uint iD = ((ZDOID)(ref zDO.m_uid)).ID;
				float num = 1900000f + (float)(iD % 200) * 0.05f;
				float num2 = 1900000f + (float)(iD / 200 % 200) * 0.05f;
				Vector3 position = default(Vector3);
				((Vector3)(ref position))..ctor(num, ((Component)view).transform.position.y, num2);
				zDO.SetPosition(position);
				((Component)view).transform.position = position;
			}
		}

		private int RestoreRecords(Vector2Int cell, bool removeRecords)
		{
			//IL_0001: 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_0033: 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_0040: 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_0048: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetValidatedParkedZDOs(cell, out var parked))
			{
				return 0;
			}
			int num = 0;
			foreach (ZDO item in parked)
			{
				Vector3 vec = item.GetVec3("PUP_SAFE_Position", Vector3.zero);
				Quaternion quaternion = item.GetQuaternion("PUP_SAFE_Rotation", Quaternion.identity);
				item.SetPosition(vec);
				item.SetRotation(quaternion);
				ZNetView val = ZNetScene.instance.FindInstance(item);
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).transform.position = vec;
					((Component)val).transform.rotation = quaternion;
					ShowOriginalRenderers(val);
				}
				if (removeRecords)
				{
					ClearBakedMetadata(item);
				}
				num++;
			}
			if (removeRecords)
			{
				records.Remove(cell);
			}
			return num;
		}

		private bool TryGetValidatedParkedZDOs(Vector2Int cell, out List<ZDO> parked)
		{
			//IL_0002: 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_01a0: Unknown result type (might be due to invalid IL or missing references)
			parked = DiscoverTaggedZDOs(cell);
			if (parked.Count == 0)
			{
				return false;
			}
			if (records.TryGetValue(cell, out var value) && value.Count != parked.Count)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Restore count mismatch in cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: {parked.Count}/{value.Count}");
				return false;
			}
			HashSet<string> hashSet = new HashSet<string>();
			foreach (ZDO item in parked)
			{
				string text = item.GetString("PUP_GRAUSTEN_ID", "");
				if (!text.StartsWith("PUP_GRAUSTEN_", StringComparison.Ordinal))
				{
					((BaseUnityPlugin)this).Logger.LogError((object)$"Restore validation failed in cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: invalid custom ID");
					return false;
				}
				if (!hashSet.Add(text))
				{
					((BaseUnityPlugin)this).Logger.LogError((object)$"Restore validation failed in cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: duplicate custom ID {text}");
					return false;
				}
				if (!ZNetScene.instance.HasPrefab(item.GetPrefab()))
				{
					((BaseUnityPlugin)this).Logger.LogError((object)$"Restore validation failed in cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: prefab unavailable for {text}");
					return false;
				}
			}
			if (!RebindCellRecordIds(cell, parked))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Restore validation failed in cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: ID rebinding failed");
				return false;
			}
			return true;
		}

		private List<ZDO> GetBakedZDOs(Vector2Int cell)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!records.TryGetValue(cell, out var value))
			{
				return new List<ZDO>();
			}
			return (from record in value
				select ZDOMan.instance.GetZDO(new ZDOID(record.userId, record.id)) into zdo
				where zdo != null && zdo.GetBool("PUP_SAFE_Baked", false) && zdo.GetInt("PUP_SAFE_CellX", int.MinValue) == ((Vector2Int)(ref cell)).x && zdo.GetInt("PUP_SAFE_CellZ", int.MinValue) == ((Vector2Int)(ref cell)).y
				select zdo).ToList();
		}

		private void HideOriginalRenderers(ZNetView view)
		{
			//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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)view == (Object)null || view.GetZDO() == null)
			{
				return;
			}
			ZDOID uid = view.GetZDO().m_uid;
			if (!hiddenRenderers.TryGetValue(uid, out var value))
			{
				value = (from renderer in ((Component)view).GetComponentsInChildren<MeshRenderer>(true)
					where (Object)(object)renderer != (Object)null && ((Renderer)renderer).enabled
					select renderer).ToList();
				hiddenRenderers[uid] = value;
			}
			MeshRenderer[] componentsInChildren = ((Component)view).GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null)
				{
					((Renderer)val).enabled = false;
				}
			}
			if (!hiddenLodGroups.TryGetValue(uid, out var value2))
			{
				value2 = (from @group in ((Component)view).GetComponentsInChildren<LODGroup>(true)
					where (Object)(object)@group != (Object)null && @group.enabled
					select @group).ToList();
				hiddenLodGroups[uid] = value2;
			}
			LODGroup[] componentsInChildren2 = ((Component)view).GetComponentsInChildren<LODGroup>(true);
			foreach (LODGroup val2 in componentsInChildren2)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					val2.enabled = false;
				}
			}
			foreach (MeshRenderer item in value)
			{
				if ((Object)(object)item != (Object)null)
				{
					((Renderer)item).enabled = false;
				}
			}
		}

		private void ShowOriginalRenderers(ZNetView view)
		{
			//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_0024: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)view == (Object)null || view.GetZDO() == null)
			{
				return;
			}
			ZDOID uid = view.GetZDO().m_uid;
			if (!hiddenRenderers.TryGetValue(uid, out var value))
			{
				return;
			}
			foreach (MeshRenderer item in value)
			{
				if ((Object)(object)item != (Object)null)
				{
					((Renderer)item).enabled = true;
				}
			}
			hiddenRenderers.Remove(uid);
			if (!hiddenLodGroups.TryGetValue(uid, out var value2))
			{
				return;
			}
			foreach (LODGroup item2 in value2)
			{
				if ((Object)(object)item2 != (Object)null)
				{
					item2.enabled = true;
				}
			}
			hiddenLodGroups.Remove(uid);
		}

		private List<ZDO> GetParkedZDOs(Vector2Int cell)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return GetBakedZDOs(cell);
		}

		private List<ZDO> DiscoverTaggedZDOs(Vector2Int cell)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<ZDOID, ZDO> found = new Dictionary<ZDOID, ZDO>();
			Action<ZDO> action = delegate(ZDO zdo)
			{
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				if (zdo != null && zdo.GetBool("PUP_SAFE_Baked", false) && zdo.GetInt("PUP_SAFE_CellX", int.MinValue) == ((Vector2Int)(ref cell)).x && zdo.GetInt("PUP_SAFE_CellZ", int.MinValue) == ((Vector2Int)(ref cell)).y && zdo.GetString("PUP_GRAUSTEN_ID", "").StartsWith("PUP_GRAUSTEN_", StringComparison.Ordinal))
				{
					found[zdo.m_uid] = zdo;
				}
			};
			foreach (ZDO bakedZDO in GetBakedZDOs(cell))
			{
				action(bakedZDO);
			}
			List<ZDO> list = new List<ZDO>();
			Vector2i zone = ZoneSystem.GetZone(new Vector3(1900000f, 0f, 1900000f));
			ZDOMan.instance.FindSectorObjects(zone, 0, 0, list, (List<ZDO>)null);
			foreach (ZDO item in list)
			{
				action(item);
			}
			if (records.TryGetValue(cell, out var value))
			{
				foreach (Vector2i item2 in new HashSet<Vector2i>(value.Select((BakedRecord record) => ZoneSystem.GetZone(record.position))))
				{
					list.Clear();
					ZDOMan.instance.FindSectorObjects(item2, 0, 0, list, (List<ZDO>)null);
					foreach (ZDO item3 in list)
					{
						action(item3);
					}
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Restore discovery cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}: {found.Count} self-tagged ZDO");
			return found.Values.ToList();
		}

		private static string RecordPositionKey(int prefabHash, Vector3 position)
		{
			//IL_001c: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			return string.Join("|", prefabHash.ToString(CultureInfo.InvariantCulture), Mathf.RoundToInt(position.x * 100f).ToString(CultureInfo.InvariantCulture), Mathf.RoundToInt(position.y * 100f).ToString(CultureInfo.InvariantCulture), Mathf.RoundToInt(position.z * 100f).ToString(CultureInfo.InvariantCulture));
		}

		private bool RebindCellRecordIds(Vector2Int cell, List<ZDO> discovered)
		{
			//IL_0006: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			if (!records.TryGetValue(cell, out var value) || value.Count != discovered.Count)
			{
				return false;
			}
			Dictionary<string, Queue<ZDO>> dictionary = new Dictionary<string, Queue<ZDO>>();
			foreach (ZDO item in discovered)
			{
				string key = RecordPositionKey(item.GetPrefab(), item.GetVec3("PUP_SAFE_Position", item.GetPosition()));
				if (!dictionary.TryGetValue(key, out var value2))
				{
					value2 = (dictionary[key] = new Queue<ZDO>());
				}
				value2.Enqueue(item);
			}
			int num = 0;
			foreach (BakedRecord item2 in value)
			{
				string key2 = RecordPositionKey(item2.prefabHash, item2.position);
				if (!dictionary.TryGetValue(key2, out var value3) || value3.Count == 0)
				{
					return false;
				}
				ZDO val = value3.Dequeue();
				if (item2.userId != ((ZDOID)(ref val.m_uid)).UserID || item2.id != ((ZDOID)(ref val.m_uid)).ID)
				{
					num++;
				}
				item2.userId = ((ZDOID)(ref val.m_uid)).UserID;
				item2.id = ((ZDOID)(ref val.m_uid)).ID;
				item2.customId = val.GetString("PUP_GRAUSTEN_ID", "");
			}
			if (dictionary.Values.Any((Queue<ZDO> queue2) => queue2.Count != 0))
			{
				return false;
			}
			if (num > 0)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"Rebound {num} changed ZDO IDs in cell {((Vector2Int)(ref cell)).x},{((Vector2Int)(ref cell)).y}");
			}
			return true;
		}

		private bool ValidateCellRecords(Vector2Int cell, out string error)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			error = "";
			if (!records.TryGetValue(cell, out var value) || value.Count == 0)
			{
				error = "records missing";
				return false;
			}
			foreach (BakedRecord item in value)
			{
				ZDO zDO = ZDOMan.instance.GetZDO(new ZDOID(item.userId, item.id));
				if (zDO == null)
				{
					error = $"ZDO missing {item.userId}:{item.id}";
					return false;
				}
				if (zDO.GetPrefab() != item.prefabHash)
				{
					error = $"prefab mismatch {item.userId}:{item.id}";
					return false;
				}
				if (!zDO.GetBool("PUP_SAFE_Baked", false))
				{
					error = $"baked marker missing {item.userId}:{item.id}";
					return false;
				}
				if (zDO.GetInt("PUP_SAFE_CellX", int.MinValue) != ((Vector2Int)(ref cell)).x || zDO.GetInt("PUP_SAFE_CellZ", int.MinValue) != ((Vector2Int)(ref cell)).y)
				{
					error = $"cell marker mismatch {item.userId}:{item.id}";
					return false;
				}
				Vector3 val = zDO.GetVec3("PUP_SAFE_Position", new Vector3(float.MaxValue, 0f, 0f)) - item.position;
				if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
				{
					error = $"position marker mismatch {item.userId}:{item.id}";
					return false;
				}
			}
			return true;
		}

		private static void ClearBakedMetadata(ZDO zdo)
		{
			zdo.RemoveInt("PUP_SAFE_Baked");
			zdo.RemoveVec3("PUP_SAFE_Position");
			zdo.RemoveQuaternion("PUP_SAFE_Rotation");
			zdo.RemoveVec3("PUP_SAFE_Scale");
			zdo.RemoveInt("PUP_SAFE_CellX");
			zdo.RemoveInt("PUP_SAFE_CellZ");
		}

		private IEnumerator RestoreAllParked()
		{
			processing = true;
			supportGuardUntil = Mathf.Max(supportGuardUntil, Time.time + 10f);
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Emergency restore started");
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Emergency support guard enabled for the complete restore");
			List<Vector2Int> list = records.Keys.ToList();
			int total = 0;
			int cleanedStale = 0;
			int blocked = 0;
			foreach (Vector2Int item in list)
			{
				Vector2Int current = item;
				if (!records.TryGetValue(current, out var value))
				{
					continue;
				}
				int count = value.Count;
				string message;
				if (TryGetValidatedParkedZDOs(current, out var parked) && parked.Count == count)
				{
					int num = RestoreRecords(current, removeRecords: false);
					if (num == count)
					{
						foreach (BakedRecord item2 in value)
						{
							ZDO zDO = ZDOMan.instance.GetZDO(new ZDOID(item2.userId, item2.id));
							if (zDO != null)
							{
								ClearBakedMetadata(zDO);
							}
						}
						records.Remove(current);
						DestroyCluster(current);
						DeleteCellCacheFiles(current);
						total += num;
						((BaseUnityPlugin)this).Logger.LogWarning((object)$"Emergency restore verified cell {((Vector2Int)(ref current)).x},{((Vector2Int)(ref current)).y}: {num}/{count}");
					}
					else
					{
						blocked++;
						((BaseUnityPlugin)this).Logger.LogError((object)$"Emergency restore blocked cell {((Vector2Int)(ref current)).x},{((Vector2Int)(ref current)).y}: {num}/{count}");
					}
				}
				else if ((parked == null || parked.Count == 0) && TryForgetConfirmedRestoredCell(current, value.ToList(), out message))
				{
					cleanedStale++;
					((BaseUnityPlugin)this).Logger.LogWarning((object)$"Emergency cleanup verified stale cell {((Vector2Int)(ref current)).x},{((Vector2Int)(ref current)).y}: {message}");
				}
				else
				{
					blocked++;
					((BaseUnityPlugin)this).Logger.LogError((object)($"Emergency restore blocked cell {((Vector2Int)(ref current)).x},{((Vector2Int)(ref current)).y}: " + $"{parked?.Count ?? 0}/{count}; cache preserved"));
				}
				yield return null;
			}
			Physics.SyncTransforms();
			supportGuardUntil = Mathf.Max(supportGuardUntil, Time.time + 10f);
			SaveState();
			ShowMessage($"Emergency restore: {total} objects, {cleanedStale} stale zones, {blocked} blocked");
			((BaseUnityPlugin)this).Logger.LogWarning((object)($"Emergency restore complete: restored={total}, staleCleaned={cleanedStale}, " + $"blocked={blocked}; support guard remains active for 10 seconds"));
			processing = false;
		}

		private Vector2Int? FindNearestBakedCell(Vector3 position, float maxDistance)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			Vector2Int cell = GetCell(position);
			if (records.ContainsKey(cell) || clusters.ContainsKey(cell))
			{
				return cell;
			}
			float num = maxDistance * maxDistance;
			Vector2Int? result = null;
			foreach (Vector2Int item in records.Keys.Union(clusters.Keys))
			{
				Vector2Int current = item;
				float num2 = (float)((Vector2Int)(ref current)).x * 64f;
				float num3 = num2 + 64f;
				float num4 = (float)((Vector2Int)(ref current)).y * 64f;
				float num5 = num4 + 64f;
				float num6 = ((position.x < num2) ? (num2 - position.x) : ((position.x > num3) ? (position.x - num3) : 0f));
				float num7 = ((position.z < num4) ? (num4 - position.z) : ((position.z > num5) ? (position.z - num5) : 0f));
				float num8 = num6 * num6 + num7 * num7;
				if (num8 < num)
				{
					num = num8;
					result = current;
				}
			}
			return result;
		}

		private void DestroyCluster(Vector2Int cell)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			RemoveGpuBakedCell(cell, restoreRenderers: false);
			precipitationRenderers.Remove(cell);
			if (clusters.TryGetValue(cell, out var value) && (Object)(object)value != (Object)null)
			{
				Object.Destroy((Object)(object)value);
			}
			clusters.Remove(cell);
			if (!generatedMeshes.TryGetValue(cell, out var value2))
			{
				return;
			}
			foreach (Mesh item in value2)
			{
				if ((Object)(object)item != (Object)null)
				{
					Object.Destroy((Object)(object)item);
				}
			}
			generatedMeshes.Remove(cell);
		}

		private void RefreshHighlights()
		{
			ClearHighlightOverlay();
			if (!highlightEnabled)
			{
				return;
			}
			foreach (KeyValuePair<Vector2Int, GameObject> cluster in clusters)
			{
				if ((Object)(object)cluster.Value != (Object)null)
				{
					AddMaterialHighlights(cluster.Value);
				}
			}
		}

		private Material GetHighlightMaterial(int group)
		{
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Expected O, but got Unknown
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_00e6: 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_00aa: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			if (highlightMaterials.TryGetValue(group, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Color color = (Color)(group switch
			{
				10 => new Color(1f, 0.24f, 0.04f, 0.42f), 
				9 => new Color(0.1f, 0.9f, 0.82f, 0.42f), 
				8 => new Color(1f, 0.08f, 0.35f, 0.42f), 
				7 => new Color(0.65f, 0.68f, 0.72f, 0.42f), 
				6 => new Color(0.95f, 0.7f, 0.25f, 0.42f), 
				5 => new Color(1f, 0.85f, 0.05f, 0.42f), 
				4 => new Color(1f, 0.42f, 0.05f, 0.42f), 
				3 => new Color(0.65f, 0.15f, 1f, 0.42f), 
				2 => new Color(0.1f, 1f, 0.25f, 0.42f), 
				1 => new Color(0.05f, 0.45f, 1f, 0.42f), 
				_ => new Color(0.48f, 0.25f, 0.1f, 0.42f), 
			});
			Material val = new Material(Shader.Find("Hidden/Internal-Colored") ?? Shader.Find("Sprites/Default"))
			{
				color = color
			};
			val.SetInt("_SrcBlend", 5);
			val.SetInt("_DstBlend", 10);
			val.SetInt("_Cull", 0);
			val.SetInt("_ZWrite", 0);
			val.SetInt("_ZTest", 8);
			val.renderQueue = 5000;
			highlightMaterials[group] = val;
			return val;
		}

		private void AddMaterialHighlights(GameObject root)
		{
			//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_010a: Unknown result type (might be due to invalid IL or missing references)
			MeshFilter[] array = (from value in root.GetComponentsInChildren<MeshFilter>(false)
				where (Object)(object)value != (Object)null && ((Object)((Component)value).gameObject).name != "PUP_MaterialHighlight"
				select value).ToArray();
			forea