Decompiled source of Monument v1.0.0

Monument.dll

Decompiled 17 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.Json;
using System.Text.RegularExpressions;
using AskaMonument.Core;
using AskaShared.Game;
using AwesomeTechnologies.VegetationSystem;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using SSSGame;
using SSSGame.Network;
using SSSGame.UI;
using SandSailorStudio;
using SandSailorStudio.Inventory;
using SandSailorStudio.Localization;
using SandSailorStudio.Render;
using SandSailorStudio.Storage;
using SandSailorStudio.UI;
using SandSailorStudio.WorldGen;
using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Monument")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ff7eea627217f74e2ed95e307f8ccc7117d1cbda")]
[assembly: AssemblyProduct("Monument")]
[assembly: AssemblyTitle("Monument")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte flag)
		{
			NullableFlags = new byte[1] { flag };
		}

		public NullableAttribute(byte[] flags)
		{
			NullableFlags = flags;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte flag)
		{
			Flag = flag;
		}
	}
}
namespace AskaMonument
{
	internal static class EmbeddedSprite
	{
		internal static Sprite Load(string fileName)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_009e: 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)
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string text = executingAssembly.GetName().Name + "." + fileName;
			using Stream stream = executingAssembly.GetManifestResourceStream(text) ?? throw new InvalidOperationException("the embedded image " + text + " is missing");
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, Il2CppStructArray<byte>.op_Implicit(memoryStream.ToArray())))
			{
				throw new InvalidOperationException("the embedded image " + text + " is not a readable PNG");
			}
			((Object)val).hideFlags = (HideFlags)61;
			Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
			((Object)obj).hideFlags = (HideFlags)61;
			return obj;
		}
	}
	internal sealed class GameObstacles : IObstacles
	{
		private const string FootprintTag = "Footprint";

		private const int StructureLayer = 12;

		private const int StructureVolumeLayer = 13;

		private const int ArrayDataOffset = 32;

		private const float HalfHeight = 1000f;

		private readonly Dictionary<IntPtr, FootprintRect?> _described = new Dictionary<IntPtr, FootprintRect?>();

		private Il2CppReferenceArray<Collider> _hits = new Il2CppReferenceArray<Collider>(256L);

		public unsafe void StructureFootprints(float minX, float minZ, float maxX, float maxZ, List<FootprintRect> into)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected O, but got Unknown
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor((minX + maxX) / 2f, 0f, (minZ + maxZ) / 2f);
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor((maxX - minX) / 2f, 1000f, (maxZ - minZ) / 2f);
			int num;
			for (num = Physics.OverlapBoxNonAlloc(val, val2, _hits, Quaternion.identity, 12288, (QueryTriggerInteraction)2); num == ((Il2CppArrayBase<Collider>)(object)_hits).Length; num = Physics.OverlapBoxNonAlloc(val, val2, _hits, Quaternion.identity, 12288, (QueryTriggerInteraction)2))
			{
				_hits = new Il2CppReferenceArray<Collider>((long)(((Il2CppArrayBase<Collider>)(object)_hits).Length * 2));
			}
			byte* ptr = (byte*)(void*)((Il2CppObjectBase)_hits).Pointer + 32;
			for (int i = 0; i < num; i++)
			{
				IntPtr intPtr = *(IntPtr*)(ptr + i * IntPtr.Size);
				if (!(intPtr == IntPtr.Zero))
				{
					if (!_described.TryGetValue(intPtr, out var value))
					{
						value = Describe(new Collider(intPtr));
						_described[intPtr] = value;
					}
					if (value.HasValue)
					{
						into.Add(value.Value);
					}
				}
			}
		}

		private static FootprintRect? Describe(Collider collider)
		{
			//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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: 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_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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)
			if (!((Component)collider).CompareTag("Footprint"))
			{
				return null;
			}
			Transform transform = ((Component)collider).transform;
			Transform marker = MonumentToolHost.Marker;
			if ((Object)(object)marker != (Object)null && transform.IsChildOf(marker))
			{
				return null;
			}
			Structure componentInParent = ((Component)collider).GetComponentInParent<Structure>();
			if ((Object)(object)componentInParent != (Object)null && (Object)(object)((Component)componentInParent).GetComponentInChildren<StructureSplineLayout>(true) != (Object)null)
			{
				return null;
			}
			BoxCollider val = ((Il2CppObjectBase)collider).TryCast<BoxCollider>();
			if ((Object)(object)val == (Object)null)
			{
				Bounds bounds = collider.bounds;
				return new FootprintRect(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).center.z, ((Bounds)(ref bounds)).extents.x, ((Bounds)(ref bounds)).extents.z, 0f);
			}
			Vector3 val2 = transform.TransformPoint(val.center);
			Vector3 val3 = Vector3.Scale(val.size, transform.lossyScale) * 0.5f;
			return new FootprintRect(val2.x, val2.z, Math.Abs(val3.x), Math.Abs(val3.z), transform.eulerAngles.y);
		}
	}
	internal sealed class TerrainScale
	{
		private readonly float _height;

		private readonly float _offset;

		internal TerrainScale(TerrainSurfaceManager manager)
		{
			_height = ((GeneratorTerrainConfiguration)manager._terrainConfig).terrainHeight;
			_offset = ((GeneratorTerrainConfiguration)manager._terrainConfig).terrainVerticalOffset;
		}

		internal float World(float stored)
		{
			return stored * _height + _offset;
		}

		internal float Stored(float world)
		{
			return (world - _offset) / _height;
		}

		internal static int FirstNode(float worldMin, float cell)
		{
			return (int)Math.Round(worldMin / cell);
		}
	}
	internal static class TerrainTypes
	{
		internal const int Mask = 51;

		internal const int VegetationBit = 4;

		internal static Vegetation Vegetation(int flags)
		{
			if ((flags & 4) == 0)
			{
				return AskaMonument.Core.Vegetation.Grow;
			}
			return AskaMonument.Core.Vegetation.Clear;
		}

		internal static int WithVegetation(int flags, Vegetation vegetation)
		{
			return vegetation switch
			{
				AskaMonument.Core.Vegetation.Clear => flags | 4, 
				AskaMonument.Core.Vegetation.Grow => flags & -5, 
				_ => throw new ArgumentOutOfRangeException("vegetation", vegetation, "LeaveAsIs writes no vegetation"), 
			};
		}

		internal static SurfacePaint Paint(int flags)
		{
			return (flags & 0x33) switch
			{
				1 => SurfacePaint.Dirt, 
				2 => SurfacePaint.Bedrock, 
				3 => SurfacePaint.Path, 
				19 => SurfacePaint.Road, 
				_ => SurfacePaint.Natural, 
			};
		}

		internal static int Type(SurfacePaint paint)
		{
			return paint switch
			{
				SurfacePaint.Natural => 0, 
				SurfacePaint.Dirt => 1, 
				SurfacePaint.Bedrock => 2, 
				SurfacePaint.Path => 3, 
				SurfacePaint.Road => 19, 
				_ => throw new ArgumentOutOfRangeException("paint", paint, "LeaveAsIs writes no terrain type"), 
			};
		}
	}
	internal sealed class GameGround : IGround
	{
		private const int ArrayBoundsOffset = 16;

		private const int ArrayLengthOffset = 24;

		private const int ArrayDataOffset = 32;

		private static readonly int FullHeightmapOffset = FieldOffset("_fullHeightmap");

		private static readonly int ValidDepthOffset = FieldOffset("_validDepth");

		private readonly TerrainSurfaceManager _manager;

		private readonly TerrainScale _scale;

		private readonly Dictionary<int, TerrainToolData> _bands = new Dictionary<int, TerrainToolData>();

		internal GameGround(TerrainSurfaceManager manager)
		{
			_manager = manager;
			_scale = new TerrainScale(manager);
		}

		public unsafe void Read(GroundGrid into, int firstRow, int rowCount)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			NodeRect area = into.Area;
			int columns = area.Columns;
			int num = area.MinZ + firstRow;
			if (!_bands.TryGetValue(rowCount, out TerrainToolData value))
			{
				value = new TerrainToolData(columns, rowCount, 0.5f, (TargetFlags)3);
				_bands[rowCount] = value;
			}
			value.worldArea = new Rect((float)area.MinX * 0.5f, (float)num * 0.5f, (float)columns * 0.5f, (float)rowCount * 0.5f);
			_manager.FillTerrainToolData(value);
			float heightmapTileSize = value._heightmapTileSize;
			Vector2Int size = value.size;
			Rect worldArea = value.worldArea;
			int num2 = TerrainScale.FirstNode(((Rect)(ref worldArea)).xMin, heightmapTileSize);
			int num3 = TerrainScale.FirstNode(((Rect)(ref worldArea)).yMin, heightmapTileSize);
			if (Math.Abs(heightmapTileSize - 0.5f) > 0.0001f || ((Vector2Int)(ref size)).x != columns || ((Vector2Int)(ref size)).y != rowCount || num2 != area.MinX || num3 != num)
			{
				throw new InvalidOperationException($"the ground read covers {((Vector2Int)(ref size)).x} x {((Vector2Int)(ref size)).y} nodes of {heightmapTileSize} m from node ({num2},{num3}), not {columns} x {rowCount} from ({area.MinX},{num})");
			}
			float* ptr = (float*)Array2D(value, FullHeightmapOffset, rowCount, columns);
			float* ptr2 = (float*)Array2D(value, ValidDepthOffset, rowCount, columns);
			int num4 = firstRow * columns;
			for (int i = 0; i < rowCount * columns; i++)
			{
				float floor = _scale.World(Math.Max(ptr2[i], 0f));
				into.Set(num4 + i, _scale.World(ptr[i]), floor);
			}
			into.Ceiling = _scale.World(1f);
		}

		private unsafe static byte* Array2D(TerrainToolData data, int fieldOffset, int rows, int cols)
		{
			nint num = *(nint*)((byte*)(void*)((Il2CppObjectBase)data).Pointer + fieldOffset);
			if (num == (nint)0)
			{
				throw new InvalidOperationException($"the ground read has no array at field offset {fieldOffset}");
			}
			long* ptr = *(long**)(num + 16);
			long num2 = *(long*)(num + 24);
			if (ptr == null || *ptr != rows || ptr[2] != cols || num2 != (long)rows * (long)cols)
			{
				throw new InvalidOperationException($"the ground read's array at field offset {fieldOffset} is not {rows} x {cols}");
			}
			return (byte*)(num + 32);
		}

		private static int FieldOffset(string name)
		{
			IntPtr il2CppField = IL2CPP.GetIl2CppField(Il2CppClassPointerStore<TerrainToolData>.NativeClassPtr, name);
			if (il2CppField == IntPtr.Zero)
			{
				throw new InvalidOperationException("TerrainToolData has no field " + name);
			}
			return (int)IL2CPP.il2cpp_field_get_offset(il2CppField);
		}
	}
	internal sealed class GameTerrainWriter : ITerrainWriter
	{
		[HarmonyPatch(typeof(TerrainSurfaceManager), "FillTerrainToolData", new Type[] { typeof(TerrainToolData) })]
		internal static class FillPatch
		{
			private static void Postfix(TerrainToolData data)
			{
				GameTerrainWriter active = _active;
				if (active == null || active._filled != IntPtr.Zero || data == null)
				{
					return;
				}
				try
				{
					active.Capture(data);
				}
				catch (Exception ex)
				{
					active._problem = "reading the stroke threw " + ex.GetType().Name + ": " + ex.Message;
				}
			}
		}

		[HarmonyPatch(typeof(TerrainSurfaceManager), "ApplyTerrainToolData", new Type[]
		{
			typeof(TerrainToolData),
			typeof(int)
		})]
		internal static class ApplyPatch
		{
			private static bool Prefix(TerrainToolData data)
			{
				GameTerrainWriter active = _active;
				if (active == null || active._written || data == null || ((Il2CppObjectBase)data).Pointer != active._filled)
				{
					return true;
				}
				try
				{
					return active.WriteAndApply(data);
				}
				catch (Exception ex)
				{
					active._problem = "writing the stroke threw " + ex.GetType().Name + ": " + ex.Message;
					return false;
				}
			}
		}

		[HarmonyPatch(typeof(TerrainSurfaceManager), "_ApplyTerrainToolDataInternalPerTile", new Type[]
		{
			typeof(TerrainToolData),
			typeof(int)
		})]
		internal static class PerTilePatch
		{
			private static void Prefix(TerrainToolData terrainToolData)
			{
				GameTerrainWriter active = _active;
				if (active == null || !active._written || active._applied || terrainToolData == null || ((Il2CppObjectBase)terrainToolData).Pointer != active._filled)
				{
					return;
				}
				try
				{
					active.RewriteAfterBlur(terrainToolData);
				}
				catch (Exception ex)
				{
					active._problem = "rewriting the stroke threw " + ex.GetType().Name + ": " + ex.Message;
				}
			}
		}

		private const float StrokeBlend = 1f;

		private static GameTerrainWriter _active;

		private readonly TerrainSurfaceManager _manager;

		private readonly TerrainScale _scale;

		private IReadOnlyList<NodeTarget> _targets;

		private int[] _rows;

		private int[] _cols;

		private List<NodeTarget> _before;

		private IntPtr _filled;

		private string _problem;

		private bool _written;

		private bool _applied;

		internal GameTerrainWriter(TerrainSurfaceManager manager)
		{
			_manager = manager;
			_scale = new TerrainScale(manager);
		}

		public WriteResult Write(IReadOnlyList<NodeTarget> targets)
		{
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Expected O, but got Unknown
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_0202: 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_03ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Expected O, but got Unknown
			//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
			int num = int.MaxValue;
			int num2 = int.MaxValue;
			int num3 = int.MinValue;
			int num4 = int.MinValue;
			float num5 = float.MinValue;
			foreach (NodeTarget target in targets)
			{
				num = Math.Min(num, target.Node.X);
				num3 = Math.Max(num3, target.Node.X);
				num2 = Math.Min(num2, target.Node.Z);
				num4 = Math.Max(num4, target.Node.Z);
				num5 = Math.Max(num5, target.Height);
			}
			int num6 = (num + num3) / 2;
			int num7 = (num2 + num4) / 2;
			float num8 = (float)Math.Max(Math.Max(num6 - num, num3 - num6), Math.Max(num7 - num2, num4 - num7)) * 0.5f;
			float num9 = 2f * Mathf.Ceil(num8) + 2f;
			_targets = targets;
			_rows = new int[targets.Count];
			_cols = new int[targets.Count];
			_before = new List<NodeTarget>(targets.Count);
			_filled = IntPtr.Zero;
			_problem = null;
			_written = false;
			_applied = false;
			GameObject val = new GameObject("Monument_Stroke");
			HeightmapTool val2 = val.AddComponent<HeightmapTool>();
			val2.setTerrainType = true;
			val2.setVegetationMask = true;
			val2.setBiomeType = false;
			val2.clearVegetation = false;
			val2.requiresTerrainType = false;
			val2.biasTerraformingWeights = false;
			val2.validateHeight = false;
			val2.onlyValidate = false;
			val2.propagateOnNetwork = true;
			val2.radius = 0f;
			Stopwatch stopwatch = Stopwatch.StartNew();
			TerraformingToolResult? val3 = null;
			_active = this;
			try
			{
				val2.SetReferenceHeight(num5, false);
				val3 = val2.RunOnArea((TerraformingToolOperation)2, num9, num9, 1f, new Vector3((float)num6 * 0.5f, num5, (float)num7 * 0.5f), 0f);
			}
			catch (Exception ex)
			{
				if (_problem == null)
				{
					_problem = "the stroke threw " + ex.GetType().Name + ": " + ex.Message;
				}
			}
			finally
			{
				_active = null;
				Object.Destroy((Object)(object)val);
			}
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(70, 7, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[Monument][stroke] nodes=");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(targets.Count);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" size=");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<float>(num9, "F0");
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" result=");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<TerraformingToolResult?>(val3);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" written=");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<bool>(_written);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" applied=");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<bool>(_applied);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" ms=");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<double>(stopwatch.Elapsed.TotalMilliseconds, "F1");
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" problem=");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(_problem ?? "none");
			}
			log.LogInfo(val4);
			if (_written)
			{
				if (_problem != null || !_applied)
				{
					ManualLogSource log2 = Plugin.Log;
					BepInExErrorLogInterpolatedStringHandler val5 = new BepInExErrorLogInterpolatedStringHandler(50, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[Monument][stroke] the edit applied with a fault: ");
						((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(_problem ?? "the blur write-back never ran");
					}
					log2.LogError(val5);
				}
				return WriteResult.Applied(_before);
			}
			if (val3.HasValue && (int)val3.Value != 0)
			{
				return WriteResult.Refused($"the game refused the edit: {val3.Value}");
			}
			return WriteResult.Refused(_problem ?? "the edit never reached the apply");
		}

		private void Capture(TerrainToolData data)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			_filled = ((Il2CppObjectBase)data).Pointer;
			Vector2Int size = data.size;
			int y = ((Vector2Int)(ref size)).y;
			size = data.size;
			int x = ((Vector2Int)(ref size)).x;
			float heightmapTileSize = data._heightmapTileSize;
			if (Math.Abs(heightmapTileSize - 0.5f) > 0.0001f)
			{
				_problem = $"the stroke has {heightmapTileSize} m nodes";
				return;
			}
			Rect worldArea = data.worldArea;
			int num = TerrainScale.FirstNode(((Rect)(ref worldArea)).xMin, heightmapTileSize);
			worldArea = data.worldArea;
			int num2 = TerrainScale.FirstNode(((Rect)(ref worldArea)).yMin, heightmapTileSize);
			for (int i = 0; i < _targets.Count; i++)
			{
				GridNode node = _targets[i].Node;
				int num3 = node.Z - num2;
				int num4 = node.X - num;
				if (num3 < 0 || num3 >= y || num4 < 0 || num4 >= x)
				{
					_problem = $"the stroke covers nodes ({num},{num2}) to ({num + x - 1},{num2 + y - 1}), not ({node.X},{node.Z})";
					break;
				}
				_rows[i] = num3;
				_cols[i] = num4;
				int terraformingFlags = data.GetTerraformingFlags(num3, num4);
				_before.Add(new NodeTarget(node, _scale.World(data.GetFullHeightmap(num3, num4)), TerrainTypes.Paint(terraformingFlags), TerrainTypes.Vegetation(terraformingFlags)));
			}
		}

		private bool WriteAndApply(TerrainToolData data)
		{
			if (_problem != null)
			{
				return false;
			}
			data.ClearFlags();
			for (int i = 0; i < _targets.Count; i++)
			{
				NodeTarget nodeTarget = _targets[i];
				int num = _rows[i];
				int num2 = _cols[i];
				data.SetFullHeightmap(num, num2, _scale.Stored(nodeTarget.Height));
				data.SetModified(num, num2, (TargetFlags)1);
				if (nodeTarget.Paint != SurfacePaint.LeaveAsIs || nodeTarget.Vegetation != Vegetation.LeaveAsIs)
				{
					int num3 = data.GetTerraformingFlags(num, num2);
					if (nodeTarget.Paint != SurfacePaint.LeaveAsIs)
					{
						num3 = (num3 & -52) | TerrainTypes.Type(nodeTarget.Paint);
						data.SetModified(num, num2, (TargetFlags)2);
					}
					if (nodeTarget.Vegetation != Vegetation.LeaveAsIs)
					{
						num3 = TerrainTypes.WithVegetation(num3, nodeTarget.Vegetation);
						data.SetModified(num, num2, (TargetFlags)4);
					}
					data.SetTerraformingFlags(num, num2, num3);
				}
			}
			_written = true;
			_manager._ApplyTerrainToolDataInternal(data, -1);
			return false;
		}

		private void RewriteAfterBlur(TerrainToolData data)
		{
			for (int i = 0; i < _targets.Count; i++)
			{
				data.SetFullHeightmap(_rows[i], _cols[i], _scale.Stored(_targets[i].Height));
			}
			_applied = true;
		}
	}
	internal sealed class GameWorldObjects : IWorldObjects
	{
		private enum Kind
		{
			WorldGen,
			Planted,
			Dropped
		}

		private sealed class Handle
		{
			public Kind Kind;

			public WorldItemInstance Instance;

			public ItemObject Proxy;

			public BiomeItemInstancesBuffer Buffer;

			public uint UniqueId;
		}

		private const string Prefix = "[Monument][objects]";

		private const float SlotTolerance = 0.05f;

		private static readonly List<Vector3> PendingRedraw = new List<Vector3>();

		private readonly ResourceManager _resources;

		private readonly List<Handle> _handles = new List<Handle>();

		internal float QueryHeight { get; set; }

		internal GameWorldObjects(ResourceManager resources)
		{
			_resources = resources;
		}

		public void List(float minX, float minZ, float maxX, float maxZ, List<WorldObject> into)
		{
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: 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_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			long timestamp = Stopwatch.GetTimestamp();
			_handles.Clear();
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			Dictionary<IntPtr, ItemObject> dictionary = new Dictionary<IntPtr, ItemObject>();
			foreach (ItemObject item in Object.FindObjectsOfType<ItemObject>())
			{
				WorldItemInstance val = (((Object)(object)item != (Object)null) ? ((WorldItemObject)item).WorldInstance : null);
				if (val == null || val.Destroyed)
				{
					continue;
				}
				if (IsExactly<BiomeItemInstance>((Il2CppObjectBase)(object)val))
				{
					dictionary[((Il2CppObjectBase)val).Pointer] = item;
				}
				else
				{
					if (!IsExactly<InventoryItemInstance>((Il2CppObjectBase)(object)val))
					{
						continue;
					}
					Vector3 position = val.GetPosition();
					if (Inside(position, minX, minZ, maxX, maxZ))
					{
						bool flag = (Object)(object)((Component)item).GetComponent<DynamicItemObject>() != (Object)null;
						Add(into, (!flag) ? Kind.Planted : Kind.Dropped, val, item, position);
						if (flag)
						{
							num2++;
						}
						else
						{
							num++;
						}
					}
				}
			}
			float num4 = (maxX - minX) / 2f;
			float num5 = (maxZ - minZ) / 2f;
			float num6 = 2f * MathF.Sqrt(num4 * num4 + num5 * num5);
			List<WorldItemInstance> val2 = new List<WorldItemInstance>();
			_resources.GetAllInstancesList(val2, new Vector3(minX + num4, QueryHeight, minZ + num5), Quaternion.identity, new Vector3(num6, num6, num6), (SDFShape)1, (IWorldItemInstanceFilter)null, (InstanceActivationContext)1024, false);
			for (int i = 0; i < val2.Count; i++)
			{
				WorldItemInstance val3 = val2[i];
				if (val3 != null && IsExactly<BiomeItemInstance>((Il2CppObjectBase)(object)val3) && !val3.Destroyed && ((Il2CppObjectBase)val3).Cast<BiomeItemInstance>().Descriptor != null)
				{
					Vector3 position2 = val3.GetPosition();
					if (Inside(position2, minX, minZ, maxX, maxZ))
					{
						dictionary.TryGetValue(((Il2CppObjectBase)val3).Pointer, out var value);
						Add(into, Kind.WorldGen, val3, value, position2);
						num3++;
					}
				}
			}
			double num7 = (double)(Stopwatch.GetTimestamp() - timestamp) * 1000.0 / (double)Stopwatch.Frequency;
			ManualLogSource log = Plugin.Log;
			bool flag2 = default(bool);
			BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(42, 5, ref flag2);
			if (flag2)
			{
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>("[Monument][objects]");
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" listed worldgen=");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(num3);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" planted=");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(num);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" dropped=");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(num2);
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" in ");
				((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<double>(num7, "F1");
				((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" ms");
			}
			log.LogInfo(val4);
		}

		public void Move(WorldObject item, float y)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			Place(item, new Vector3(item.X, y, item.Z));
		}

		public void Restore(WorldObject item)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			Place(item, new Vector3(item.X, item.Y, item.Z));
		}

		public bool Clear(WorldObject item)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			Handle handle = _handles[item.Id];
			if (handle.Kind == Kind.WorldGen)
			{
				NativeList<float3> positions;
				int num = SlotOf(handle, item, out positions);
				if (num < 0)
				{
					return true;
				}
				if (!FrontsSlot(handle, num))
				{
					return false;
				}
				BiomeItemInstance val = ((Il2CppObjectBase)handle.Instance).Cast<BiomeItemInstance>();
				if (((WorldItemInstance)val).Destroyed)
				{
					return true;
				}
				if (!((WorldItemInstance)val).IsRemovable((InstanceDestructionLevel)1))
				{
					return false;
				}
				bool flag = false;
				InstanceDestructionLevel val2 = (InstanceDestructionLevel)1;
				((WorldItemInstance)val).Destroy(ref flag, ref val2);
				return ((WorldItemInstance)val).Destroyed;
			}
			if (!Holds(handle))
			{
				return true;
			}
			if (!handle.Instance.IsRemovable((InstanceDestructionLevel)0) || !ProxyHolds(handle))
			{
				return false;
			}
			((WorldItemObject)handle.Proxy).RemoveObjectFromWorld();
			return handle.Instance.Destroyed;
		}

		internal static void RedrawMovedCells()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			if (PendingRedraw.Count == 0)
			{
				return;
			}
			VegetationSystemPro val = Object.FindObjectOfType<VegetationSystemPro>();
			List<VegetationCell> val2 = (((Object)(object)val != (Object)null) ? val.VegetationCellList : null);
			if (val2 == null || val2.Count == 0)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(46, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>("[Monument][objects]");
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" no vegetation cell list; redrawing every cell");
				}
				log.LogWarning(val3);
				if (val != null)
				{
					val.SetVegetationCellsDirty();
				}
				PendingRedraw.Clear();
				return;
			}
			Bounds[] array = (Bounds[])(object)new Bounds[val2.Count];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = val2[i].VegetationCellBounds;
			}
			HashSet<int> hashSet = new HashSet<int>();
			bool flag2 = false;
			foreach (Vector3 p in PendingRedraw)
			{
				int num = Array.FindIndex(array, (Bounds b) => p.x >= ((Bounds)(ref b)).min.x && p.x <= ((Bounds)(ref b)).max.x && p.z >= ((Bounds)(ref b)).min.z && p.z <= ((Bounds)(ref b)).max.z);
				if (num < 0)
				{
					flag2 = true;
				}
				else if (hashSet.Add(num))
				{
					val.ClearCache(val2[num]);
				}
			}
			if (flag2)
			{
				val.SetVegetationCellsDirty();
			}
			PendingRedraw.Clear();
		}

		internal static void ForgetRedraw()
		{
			PendingRedraw.Clear();
		}

		private void Add(List<WorldObject> into, Kind kind, WorldItemInstance instance, ItemObject proxy, Vector3 pos)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			into.Add(new WorldObject(_handles.Count, pos.x, pos.y, pos.z));
			Handle handle = new Handle
			{
				Kind = kind,
				Instance = instance,
				Proxy = proxy
			};
			if (kind == Kind.WorldGen)
			{
				handle.Buffer = ((Il2CppObjectBase)instance).Cast<BiomeItemInstance>().GetBuffer();
			}
			else
			{
				handle.UniqueId = instance.UniqueId;
			}
			_handles.Add(handle);
		}

		private void Place(WorldObject item, Vector3 target)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			Handle handle = _handles[item.Id];
			if (handle.Kind == Kind.WorldGen)
			{
				PlaceWorldGen(handle, item, target);
				return;
			}
			if (!Holds(handle))
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(63, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("[Monument][objects]");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" an object at (");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(item.X, "F1");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(",");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(item.Z, "F1");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(") is gone since it was listed; it is not placed");
				}
				log.LogWarning(val);
				return;
			}
			bool flag2 = true;
			bool flag3 = false;
			((Il2CppObjectBase)handle.Instance).Cast<InventoryItemInstance>().SetPosition(ref target, ref flag2, ref flag3);
			if (handle.Kind == Kind.Dropped && ProxyHolds(handle))
			{
				DynamicItemObject component = ((Component)handle.Proxy).GetComponent<DynamicItemObject>();
				if ((Object)(object)component != (Object)null)
				{
					component.EnsureAboveGround();
					component.ForceUpdateInstancePosition();
				}
			}
		}

		private static void PlaceWorldGen(Handle h, WorldObject item, Vector3 target)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_009c: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			NativeList<float3> positions;
			int num = SlotOf(h, item, out positions);
			if (num < 0)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(71, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("[Monument][objects]");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" no position slot for the world-gen object at (");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(item.X, "F1");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(",");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(item.Z, "F1");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("); it stays where it is");
				}
				log.LogWarning(val);
			}
			else
			{
				if (ProxyHolds(h) && FrontsSlot(h, num))
				{
					((Component)h.Proxy).transform.position = target;
				}
				positions[num] = new float3(target.x, target.y, target.z);
				PendingRedraw.Add(target);
			}
		}

		private static bool ProxyHolds(Handle h)
		{
			if ((Object)(object)h.Proxy == (Object)null)
			{
				return false;
			}
			WorldItemInstance worldInstance = ((WorldItemObject)h.Proxy).WorldInstance;
			if (worldInstance != null)
			{
				return ((Il2CppObjectBase)worldInstance).Pointer == ((Il2CppObjectBase)h.Instance).Pointer;
			}
			return false;
		}

		private static bool Holds(Handle h)
		{
			if (!h.Instance.Destroyed)
			{
				return h.Instance.UniqueId == h.UniqueId;
			}
			return false;
		}

		private static bool FrontsSlot(Handle h, int slot)
		{
			if (h.Instance.Index == slot)
			{
				BiomeItemInstancesBuffer buffer = ((Il2CppObjectBase)h.Instance).Cast<BiomeItemInstance>().GetBuffer();
				return ((buffer != null) ? new IntPtr?(((Il2CppObjectBase)buffer).Pointer) : ((IntPtr?)null)) == ((Il2CppObjectBase)h.Buffer).Pointer;
			}
			return false;
		}

		private static int SlotOf(Handle h, WorldObject item, out NativeList<float3> positions)
		{
			BiomeItemInstancesBuffer buffer = h.Buffer;
			object obj;
			if (buffer == null)
			{
				obj = null;
			}
			else
			{
				InstancesDataArrays instances = buffer.instances;
				obj = ((instances != null) ? instances.positions : null);
			}
			positions = (NativeList<float3>)obj;
			if (positions == null)
			{
				return -1;
			}
			return SlotAt(positions, item.X, item.Z);
		}

		private static int SlotAt(NativeList<float3> positions, float x, float z)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			int length = positions.Length;
			for (int i = 0; i < length; i++)
			{
				float3 val = positions[i];
				if (Mathf.Abs(val.x - x) <= 0.05f && Mathf.Abs(val.z - z) <= 0.05f)
				{
					return i;
				}
			}
			return -1;
		}

		private static bool Inside(Vector3 pos, float minX, float minZ, float maxX, float maxZ)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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)
			if (pos.x >= minX && pos.x <= maxX && pos.z >= minZ)
			{
				return pos.z <= maxZ;
			}
			return false;
		}

		private static bool IsExactly<T>(Il2CppObjectBase obj) where T : Il2CppObjectBase
		{
			return IL2CPP.il2cpp_object_get_class(obj.Pointer) == Il2CppClassPointerStore<T>.NativeClassPtr;
		}
	}
	internal sealed class GameWorldSession : IWorldSession
	{
		internal Role Role { get; }

		public bool IsSinglePlayer { get; }

		public ClearSettings ClearSettings => Plugin.ClearSettings;

		public StampLimits Limits => Plugin.Limits;

		internal GameWorldSession(NetworkSession session)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			Role = session.Parameters.role;
			IsSinglePlayer = (int)Role == 1;
		}
	}
	internal static class GhostView
	{
		private sealed class Edge
		{
			private readonly bool _loop;

			private readonly Color? _fixedColor;

			private readonly float _height;

			private readonly float _halfThickness;

			private readonly int _perPoint;

			private readonly LineRenderer _line;

			private readonly Mesh _mesh;

			private Il2CppStructArray<Vector3> _vertices;

			private Il2CppStructArray<Color> _colors;

			private int _count = -1;

			internal Edge(string name, bool loop, Color? fixedColor, float height, float thickness)
			{
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0074: Expected O, but got Unknown
				//IL_0121: Unknown result type (might be due to invalid IL or missing references)
				//IL_0126: 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_0147: Expected O, but got Unknown
				//IL_0152: Unknown result type (might be due to invalid IL or missing references)
				if (loop && thickness > 0f)
				{
					throw new ArgumentException("a slab closes its two ends, so it cannot loop", "loop");
				}
				_loop = loop;
				_fixedColor = fixedColor;
				_height = height;
				_halfThickness = thickness / 2f;
				_perPoint = ((thickness > 0f) ? 4 : 2);
				float num = Math.Max(0.15f, thickness);
				GameObject val = new GameObject(name);
				val.transform.SetParent(_root.transform, false);
				_line = val.AddComponent<LineRenderer>();
				_line.useWorldSpace = false;
				_line.loop = loop;
				_line.alignment = (LineAlignment)0;
				_line.numCornerVertices = 2;
				((Renderer)_line).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)_line).receiveShadows = false;
				((Renderer)_line).sortingOrder = 5000;
				_line.startWidth = num;
				_line.endWidth = num;
				((Renderer)_line).material = GhostMaterial();
				GameObject val2 = new GameObject(name + "Wall");
				val2.transform.SetParent(_root.transform, false);
				_mesh = new Mesh();
				_mesh.MarkDynamic();
				val2.AddComponent<MeshFilter>().sharedMesh = _mesh;
				MeshRenderer obj = val2.AddComponent<MeshRenderer>();
				((Renderer)obj).sharedMaterial = GhostMaterial();
				((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)obj).receiveShadows = false;
			}

			internal void Place(IReadOnlyList<OutlinePoint> outline, StampGhost ghost, bool red, bool repaint)
			{
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b6: 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_018d: 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_01cb: Unknown result type (might be due to invalid IL or missing references)
				int count = outline.Count;
				if (count != _count)
				{
					Resize(count);
					repaint = true;
				}
				for (int i = 0; i < count; i++)
				{
					OutlinePoint outlinePoint = outline[i];
					float num = outlinePoint.X - ghost.CenterX;
					float num2 = outlinePoint.Z - ghost.CenterZ;
					float num3 = outlinePoint.Y - 0.5f;
					float num4 = outlinePoint.Y + _height;
					_line.SetPosition(i, new Vector3(num, num4, num2));
					int num5 = _perPoint * i;
					if (_perPoint == 2)
					{
						((Il2CppArrayBase<Vector3>)(object)_vertices)[num5] = new Vector3(num, num3, num2);
						((Il2CppArrayBase<Vector3>)(object)_vertices)[num5 + 1] = new Vector3(num, num4, num2);
						continue;
					}
					OutlinePoint outlinePoint2 = outline[Math.Max(i - 1, 0)];
					OutlinePoint outlinePoint3 = outline[Math.Min(i + 1, count - 1)];
					float num6 = outlinePoint3.X - outlinePoint2.X;
					float num7 = outlinePoint3.Z - outlinePoint2.Z;
					float num8 = MathF.Sqrt(num6 * num6 + num7 * num7);
					float num9 = ((num8 > 0f) ? ((0f - num7) / num8 * _halfThickness) : _halfThickness);
					float num10 = ((num8 > 0f) ? (num6 / num8 * _halfThickness) : 0f);
					((Il2CppArrayBase<Vector3>)(object)_vertices)[num5] = new Vector3(num - num9, num3, num2 - num10);
					((Il2CppArrayBase<Vector3>)(object)_vertices)[num5 + 1] = new Vector3(num - num9, num4, num2 - num10);
					((Il2CppArrayBase<Vector3>)(object)_vertices)[num5 + 2] = new Vector3(num + num9, num4, num2 + num10);
					((Il2CppArrayBase<Vector3>)(object)_vertices)[num5 + 3] = new Vector3(num + num9, num3, num2 + num10);
				}
				_mesh.vertices = _vertices;
				_mesh.RecalculateBounds();
				if (repaint)
				{
					Paint(red);
				}
			}

			private void Paint(bool red)
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: 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_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_004f: 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_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_006a: Unknown result type (might be due to invalid IL or missing references)
				Color val = (Color)(((??)_fixedColor) ?? (red ? Red : Green));
				_line.startColor = val;
				_line.endColor = val;
				Color val2 = default(Color);
				((Color)(ref val2))..ctor(val.r, val.g, val.b, 0.3f);
				for (int i = 0; i < ((Il2CppArrayBase<Color>)(object)_colors).Length; i++)
				{
					((Il2CppArrayBase<Color>)(object)_colors)[i] = val2;
				}
				_mesh.colors = _colors;
			}

			private void Resize(int count)
			{
				_count = count;
				_line.positionCount = count;
				_mesh.Clear();
				_vertices = new Il2CppStructArray<Vector3>((long)(_perPoint * count));
				_colors = new Il2CppStructArray<Color>((long)(_perPoint * count));
				int num = ((count >= 2) ? (_loop ? count : (count - 1)) : 0);
				int num2 = ((_perPoint == 2) ? 1 : 3);
				int num3 = ((_perPoint != 2 && count >= 2) ? 2 : 0);
				Il2CppStructArray<int> triangles = new Il2CppStructArray<int>((long)(6 * (num * num2 + num3)));
				int t = 0;
				for (int i = 0; i < num; i++)
				{
					int num4 = _perPoint * i;
					int num5 = _perPoint * ((i + 1) % count);
					for (int j = 0; j < num2; j++)
					{
						t = Quad(triangles, t, num4 + j, num4 + j + 1, num5 + j + 1, num5 + j);
					}
				}
				if (num3 > 0)
				{
					int num6 = _perPoint * (count - 1);
					t = Quad(triangles, t, 0, 1, 2, 3);
					Quad(triangles, t, num6, num6 + 1, num6 + 2, num6 + 3);
				}
				_mesh.vertices = _vertices;
				_mesh.triangles = triangles;
			}

			private static int Quad(Il2CppStructArray<int> triangles, int t, int a, int b, int c, int d)
			{
				((Il2CppArrayBase<int>)(object)triangles)[t] = a;
				((Il2CppArrayBase<int>)(object)triangles)[t + 1] = b;
				((Il2CppArrayBase<int>)(object)triangles)[t + 2] = c;
				((Il2CppArrayBase<int>)(object)triangles)[t + 3] = a;
				((Il2CppArrayBase<int>)(object)triangles)[t + 4] = c;
				((Il2CppArrayBase<int>)(object)triangles)[t + 5] = d;
				return t + 6;
			}
		}

		private const string ObjectName = "AskaMonument_Ghost";

		private const float WallBelow = 0.5f;

		private const float WallHeight = 3f;

		private const float WallAlpha = 0.3f;

		private const float Width = 0.15f;

		private const float FrontHeight = 4f;

		private const float FrontThickness = 0.45000002f;

		private const int SortingOrder = 5000;

		private static readonly Color Green = new Color(0.35f, 0.95f, 0.4f, 1f);

		private static readonly Color Red = new Color(0.95f, 0.25f, 0.2f, 1f);

		private static readonly Color Yellow = new Color(1f, 0.85f, 0.1f, 1f);

		private static GameObject _root;

		private static Edge _pad;

		private static Edge _footprint;

		private static Edge _front;

		private static Material _material;

		private static bool _red;

		private static float _shownYaw;

		private static float _turn;

		private static bool _hasOutline;

		internal static void Show(StampGhost ghost)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root == (Object)null)
			{
				Build();
			}
			_root.transform.position = new Vector3(ghost.CenterX, 0f, ghost.CenterZ);
			_shownYaw = ghost.Yaw;
			SetTurn(0f);
			bool flag = !ghost.CanStamp;
			bool repaint = flag != _red;
			_red = flag;
			_pad.Place(ghost.PadOutline, ghost, flag, repaint);
			_footprint.Place(ghost.FootprintOutline, ghost, flag, repaint);
			_front.Place(ghost.FrontMark, ghost, flag, repaint);
			_hasOutline = true;
			if (!_root.activeSelf)
			{
				_root.SetActive(true);
			}
		}

		internal static void Turn(float yaw)
		{
			if ((Object)(object)_root != (Object)null && _root.activeSelf)
			{
				SetTurn(yaw - _shownYaw);
			}
		}

		internal static void Hide()
		{
			if ((Object)(object)_root != (Object)null && _root.activeSelf)
			{
				_root.SetActive(false);
			}
		}

		internal static void ShowLast()
		{
			if (_hasOutline && (Object)(object)_root != (Object)null && !_root.activeSelf)
			{
				_root.SetActive(true);
			}
		}

		internal static void Forget()
		{
			Hide();
			_hasOutline = false;
		}

		private static void SetTurn(float degrees)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (degrees != _turn)
			{
				_turn = degrees;
				_root.transform.rotation = Quaternion.Euler(0f, degrees, 0f);
			}
		}

		private static void Build()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			_root = new GameObject("AskaMonument_Ghost");
			_root.SetActive(false);
			_turn = 0f;
			_red = false;
			_pad = new Edge("Pad", loop: true, null, 3f, 0f);
			_footprint = new Edge("Footprint", loop: true, null, 3f, 0f);
			_front = new Edge("Front", loop: false, Yellow, 4f, 0.45000002f);
		}

		private static Material GhostMaterial()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			if ((Object)(object)_material != (Object)null)
			{
				return _material;
			}
			Shader obj = Shader.Find("Sprites/Default");
			if ((Object)(object)obj == (Object)null)
			{
				throw new InvalidOperationException("no ghost shader: Sprites/Default is missing");
			}
			_material = new Material(obj);
			return _material;
		}
	}
	internal sealed class MonumentListing
	{
		internal string Icon { get; }

		internal string Preview { get; }

		internal MonumentDesign Design { get; }

		internal string AssetName { get; }

		internal int Id { get; }

		internal string NameKey { get; }

		internal string DescriptionKey { get; }

		internal string StampKey { get; }

		internal string KeepKey { get; }

		internal DynamicDimensionTemplate Entry { get; set; }

		internal IntPtr Pointer { get; set; }

		internal int HeldCount { get; set; }

		internal MonumentListing(MonumentDesign design, string assetName, int id, string nameKey, string descriptionKey, string stampKey, string keepKey, string icon = null, string preview = null)
		{
			Design = design;
			AssetName = assetName;
			Id = id;
			NameKey = nameKey;
			DescriptionKey = descriptionKey;
			StampKey = stampKey;
			KeepKey = keepKey;
			Icon = icon;
			Preview = preview;
		}
	}
	internal static class MonumentEntry
	{
		private const string FieldAssetName = "Item_Structures_TerrainLevelField";

		private const string AssetPrefix = "Monument_";

		private const float GrantWindowSeconds = 5f;

		internal static readonly IReadOnlyList<MonumentListing> Listings = new MonumentListing[4]
		{
			new MonumentListing(Catalog.Terrace, "Monument_Terrace", 919191501, "monument.terrace", "monument.terrace_description", "dialog.stamp_terrace", "dialog.keep_terrace", "TerraceIcon.png", "TerracePreview.png"),
			new MonumentListing(Catalog.Babylon, "Monument_Babylon", 919191504, "monument.babylon", "monument.babylon_description", "dialog.stamp_babylon", "dialog.keep_babylon", "BabylonIcon.png", "BabylonPreview.png"),
			new MonumentListing(Catalog.Temple, "Monument_Temple", 919191505, "monument.temple", "monument.temple_description", "dialog.stamp_temple", "dialog.keep_temple", "TempleIcon.png", "TemplePreview.png"),
			new MonumentListing(Catalog.Motte, "Monument_Motte", 919191506, "monument.motte", "monument.motte_description", "dialog.stamp_motte", "dialog.keep_motte", "MotteIcon.png", "MottePreview.png")
		};

		private static float _grantWindowUntil;

		private static BuildItemsTabPage _lastPage;

		private static PlayerBuilder _builder;

		private static bool _granted;

		private static bool _granting;

		private static ItemCollection _heldBack;

		private static int _serializeDepth;

		internal static void ResetForWorld()
		{
			_builder = null;
			_lastPage = null;
			_granted = false;
		}

		internal static void Patch(Harmony harmony)
		{
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(ItemInfoDatabase), "Initialize", Type.EmptyTypes, (Type[])null), Hook("BeforeDatabaseInitialize"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(BuildItemsTabPage), "Init", new Type[1] { typeof(TabButton) }, (Type[])null), Hook("BeforeTabInit"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(BuildItemsTabPage), "Show", new Type[2]
			{
				typeof(bool),
				typeof(TabButton)
			}, (Type[])null), (HarmonyMethod)null, Hook("AfterTabShow"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(InventoryComponent), "GetItemCollection", Type.EmptyTypes, (Type[])null), (HarmonyMethod)null, Hook("AfterGetItemCollection"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(LocalizationManager), "Loc", new Type[2]
			{
				typeof(string),
				typeof(bool)
			}, (Type[])null), (HarmonyMethod)null, Hook("AfterLoc"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(PlayerInventory), "Serialize", new Type[1] { typeof(DataObject) }, (Type[])null), Hook("BeforeSerialize"), (HarmonyMethod)null, (HarmonyMethod)null, Hook("AfterSerialize"), (HarmonyMethod)null);
		}

		internal static bool IsEntry(StructureTemplate template)
		{
			return Find(template) != null;
		}

		internal static MonumentListing Find(StructureTemplate template)
		{
			if ((Object)(object)template == (Object)null)
			{
				return null;
			}
			for (int i = 0; i < Listings.Count; i++)
			{
				MonumentListing monumentListing = Listings[i];
				if (monumentListing.Pointer != IntPtr.Zero && ((Il2CppObjectBase)template).Pointer == monumentListing.Pointer)
				{
					return monumentListing;
				}
			}
			return null;
		}

		public static void BeforeDatabaseInitialize(ItemInfoDatabase __instance)
		{
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				ItemInfoList val = (((Object)(object)__instance != (Object)null) ? __instance.CompleteItemInfoList : null);
				List<ItemInfo> val2 = (((Object)(object)val != (Object)null) ? val.itemInfoList : null);
				if (val2 == null || IndexOfId(val2, Listings[0].Id) >= 0)
				{
					return;
				}
				DynamicDimensionTemplate val3 = null;
				for (int i = 0; i < val2.Count; i++)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						break;
					}
					ItemInfo val4 = val2[i];
					if ((Object)(object)val4 != (Object)null && ((Object)val4).name == "Item_Structures_TerrainLevelField")
					{
						val3 = ((Il2CppObjectBase)val4).TryCast<DynamicDimensionTemplate>();
					}
				}
				if ((Object)(object)val3 == (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					BepInExWarningLogInterpolatedStringHandler val5 = new BepInExWarningLogInterpolatedStringHandler(70, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[Monument][entry] the Monument entries were not added: ");
						((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>("Item_Structures_TerrainLevelField");
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" was not found.");
					}
					log.LogWarning(val5);
					return;
				}
				foreach (MonumentListing listing in Listings)
				{
					DynamicDimensionTemplate val6 = new DynamicDimensionTemplate(((Il2CppObjectBase)Object.Instantiate<DynamicDimensionTemplate>(val3)).Pointer);
					((Object)val6).name = listing.AssetName;
					((ItemInfo)val6).id = listing.Id;
					((ItemInfo)val6).databaseIndex = (ushort)val2.Count;
					((ItemInfo)val6).Localized = false;
					((ItemInfo)val6).localizedName = ModStrings.Get(listing.NameKey);
					((ItemInfo)val6).localizedDescription = ModStrings.Get(listing.DescriptionKey);
					((NodeTemplate)val6).showUnlockNotification = false;
					((NodeTemplate)val6).blueprintConditionsRules = new List<BlueprintConditionsRule>();
					if (listing.Icon != null)
					{
						((ItemInfo)val6).icon = EmbeddedSprite.Load(listing.Icon);
					}
					if (listing.Preview != null)
					{
						((ItemInfo)val6).previewImage = EmbeddedSprite.Load(listing.Preview);
					}
					val2.Add((ItemInfo)(object)val6);
					listing.Entry = val6;
					listing.Pointer = ((Il2CppObjectBase)val6).Pointer;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				BepInExErrorLogInterpolatedStringHandler val7 = new BepInExErrorLogInterpolatedStringHandler(47, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("[Monument][entry] the Monument entries failed: ");
					((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<Exception>(ex);
				}
				log2.LogError(val7);
			}
		}

		public static void BeforeTabInit(BuildItemsTabPage __instance)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			try
			{
				_lastPage = __instance;
				_grantWindowUntil = Time.realtimeSinceStartup + 5f;
				if (!_granted)
				{
					Grant(ResolveItemCollection());
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(59, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Monument][entry] the Monument entries failed on tab init: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				log.LogError(val);
			}
		}

		public static void AfterTabShow(BuildItemsTabPage __instance, bool value)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			try
			{
				_lastPage = __instance;
				if (value && !_granted)
				{
					Grant(ResolveItemCollection());
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(59, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Monument][entry] the Monument entries failed on tab show: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				log.LogError(val);
			}
		}

		public static void AfterGetItemCollection(InventoryComponent __instance, ItemCollection __result)
		{
			if (!_granted && __result != null && Time.realtimeSinceStartup <= _grantWindowUntil && IsLocalPlayerInventory(__instance))
			{
				Grant(__result);
			}
		}

		public static void BeforeSerialize(PlayerInventory __instance)
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			_serializeDepth++;
			if (_heldBack != null)
			{
				return;
			}
			try
			{
				ItemCollection val = (((Object)(object)Listings[0].Entry != (Object)null) ? ((InventoryComponent)__instance).GetItemCollection() : null);
				if (val == null)
				{
					return;
				}
				bool flag = false;
				foreach (MonumentListing listing in Listings)
				{
					int itemQuantity = val.GetItemQuantity((ItemInfo)(object)listing.Entry);
					listing.HeldCount = ((itemQuantity > 0) ? val.RemoveItems((ItemInfo)(object)listing.Entry, itemQuantity) : 0);
					flag |= listing.HeldCount > 0;
				}
				if (flag)
				{
					_heldBack = val;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag2 = default(bool);
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(74, 1, ref flag2);
				if (flag2)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[Monument][entry] the Monument entries could not be kept out of the save: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				log.LogError(val2);
			}
		}

		public static void AfterSerialize()
		{
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			_serializeDepth--;
			if (_serializeDepth > 0 || _heldBack == null)
			{
				return;
			}
			bool flag = default(bool);
			try
			{
				foreach (MonumentListing listing in Listings)
				{
					if (listing.HeldCount == 0)
					{
						continue;
					}
					int num = _heldBack.AddItems((ItemInfo)(object)listing.Entry, listing.HeldCount);
					if (num < listing.HeldCount)
					{
						_granted = false;
						ManualLogSource log = Plugin.Log;
						BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(64, 3, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Monument][entry] the ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(listing.Design.Name);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" entry was granted back ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" of ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(listing.HeldCount);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" after a save.");
						}
						log.LogWarning(val);
					}
				}
			}
			catch (Exception ex)
			{
				_granted = false;
				ManualLogSource log2 = Plugin.Log;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(80, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[Monument][entry] the Monument entries could not be granted again after a save: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				log2.LogError(val2);
			}
			finally
			{
				_heldBack = null;
				foreach (MonumentListing listing2 in Listings)
				{
					listing2.HeldCount = 0;
				}
			}
		}

		public static void AfterLoc(string key, ref string __result)
		{
			if (key == null || key.IndexOf("Monument_", StringComparison.Ordinal) < 0)
			{
				return;
			}
			MonumentListing monumentListing = null;
			for (int i = 0; i < Listings.Count; i++)
			{
				if (monumentListing != null)
				{
					break;
				}
				if (key.IndexOf(Listings[i].AssetName, StringComparison.Ordinal) >= 0)
				{
					monumentListing = Listings[i];
				}
			}
			if (monumentListing != null)
			{
				if (key.EndsWith("_name", StringComparison.OrdinalIgnoreCase))
				{
					__result = ModStrings.Get(monumentListing.NameKey);
				}
				else if (key.EndsWith("_description", StringComparison.OrdinalIgnoreCase) || key.EndsWith("_desc", StringComparison.OrdinalIgnoreCase))
				{
					__result = ModStrings.Get(monumentListing.DescriptionKey);
				}
				else if (key.EndsWith("_lore", StringComparison.OrdinalIgnoreCase))
				{
					__result = string.Empty;
				}
			}
		}

		private static bool IsLocalPlayerInventory(InventoryComponent inventory)
		{
			PlayerInventory val = (((Object)(object)inventory != (Object)null) ? ((Il2CppObjectBase)inventory).TryCast<PlayerInventory>() : null);
			Character localCharacter = LocalPlayerTool.LocalCharacter;
			Character val2 = (((Object)(object)val != (Object)null) ? ((CharacterInventory)val).character : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)localCharacter != (Object)null)
			{
				return ((Il2CppObjectBase)val2).Pointer == ((Il2CppObjectBase)localCharacter).Pointer;
			}
			return false;
		}

		private static void Grant(ItemCollection collection)
		{
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Expected O, but got Unknown
			if (_granted || _granting || _heldBack != null || collection == null || (Object)(object)Listings[0].Entry == (Object)null || !Plugin.ConfigEnabled.Value)
			{
				return;
			}
			_granting = true;
			try
			{
				if ((Object)(object)_builder == (Object)null)
				{
					_builder = LocalBuilder();
				}
				ItemInfoList val = (((Object)(object)_builder != (Object)null) ? _builder.knownBlueprints : null);
				List<ItemInfo> val2 = (((Object)(object)val != (Object)null) ? val.itemInfoList : null);
				if (val2 == null)
				{
					return;
				}
				foreach (MonumentListing listing in Listings)
				{
					if (collection.GetFirstItem((ItemInfo)(object)listing.Entry) == null)
					{
						collection.AddItems((ItemInfo)(object)listing.Entry, 1);
					}
					if (!val.Check((ItemInfo)(object)listing.Entry))
					{
						val2.Add((ItemInfo)(object)listing.Entry);
					}
				}
				ItemCollection val3 = ResolveItemCollection();
				bool flag = val3 != null;
				foreach (MonumentListing listing2 in Listings)
				{
					flag = flag && val3.GetFirstItem((ItemInfo)(object)listing2.Entry) != null && val.Check((ItemInfo)(object)listing2.Entry);
				}
				_granted = flag;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag2 = default(bool);
				BepInExErrorLogInterpolatedStringHandler val4 = new BepInExErrorLogInterpolatedStringHandler(56, 1, ref flag2);
				if (flag2)
				{
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[Monument][entry] the Monument entries failed to grant: ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<Exception>(ex);
				}
				log.LogError(val4);
			}
			finally
			{
				_granting = false;
			}
		}

		private static PlayerBuilder LocalBuilder()
		{
			Character localCharacter = LocalPlayerTool.LocalCharacter;
			PlayerBuilder val = (((Object)(object)localCharacter != (Object)null) ? ((Component)localCharacter).GetComponentInChildren<PlayerBuilder>(true) : null);
			if ((Object)(object)val == (Object)null && (Object)(object)localCharacter != (Object)null)
			{
				val = ((Component)localCharacter).GetComponentInParent<PlayerBuilder>();
			}
			if (!((Object)(object)val != (Object)null))
			{
				return Object.FindObjectOfType<PlayerBuilder>();
			}
			return val;
		}

		private static ItemCollection ResolveItemCollection()
		{
			PlayerInventory val = (((Object)(object)_lastPage != (Object)null) ? _lastPage._pi : null);
			if ((Object)(object)val == (Object)null)
			{
				Character localCharacter = LocalPlayerTool.LocalCharacter;
				val = (((Object)(object)localCharacter != (Object)null) ? ((Component)localCharacter).GetComponentInChildren<PlayerInventory>(true) : null);
			}
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((InventoryComponent)val).GetItemCollection();
		}

		private static int IndexOfId(List<ItemInfo> list, int id)
		{
			for (int i = 0; i < list.Count; i++)
			{
				ItemInfo val = list[i];
				if ((Object)(object)val != (Object)null && val.id == id)
				{
					return i;
				}
			}
			return -1;
		}

		private static HarmonyMethod Hook(string name)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return new HarmonyMethod(AccessTools.DeclaredMethod(typeof(MonumentEntry), name, (Type[])null, (Type[])null));
		}
	}
	internal static class MonumentsTab
	{
		private const string MaterialsKey = "misc.materials";

		private const string FirstRowName = "Row1";

		private const string SecondRowName = "Row2";

		private const string IconChildName = "Image";

		private const string IconResource = "MonumentsTabIcon.png";

		private const string TabName = "MonumentsTab";

		private static Sprite _icon;

		private static TabButtonCategory _tab;

		private static IntPtr _groupPointer;

		internal static void Patch(Harmony harmony)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(BuildMenu), "OnActivate", Type.EmptyTypes, (Type[])null), new HarmonyMethod(AccessTools.DeclaredMethod(typeof(MonumentsTab), "BeforeActivate", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		public static void BeforeActivate(BuildMenu __instance)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			try
			{
				Refresh(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(42, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Monument][tab] the Monuments tab failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				log.LogError(val);
			}
		}

		private static void Refresh(BuildMenu menu)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			TabGroup group;
			TabButtonCategory val = FindMaterials(menu, out group);
			if ((Object)(object)val == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(85, 0, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[Monument][tab] the build menu has no Materials tab; the Monuments tab was not added.");
				}
				log.LogWarning(val2);
				return;
			}
			bool flag2 = (Object)(object)MonumentEntry.Listings[0].Entry != (Object)null;
			if (flag2)
			{
				ExcludeFromVanillaTabs(group);
			}
			if ((!((Object)(object)_tab == (Object)null) && !(((Il2CppObjectBase)group).Pointer != _groupPointer)) || (Plugin.ConfigEnabled.Value && Create(val, group)))
			{
				_tab.CategoryDisplayName = ModStrings.Get("monument.tab");
				bool flag3 = Plugin.ConfigEnabled.Value && flag2;
				bool flag4 = IndexIn(group, (TabButton)(object)_tab) >= 0;
				if (flag3)
				{
					PlaceLast(((Component)group).transform);
				}
				((Component)_tab).gameObject.SetActive(flag3);
				if (flag3 && !flag4)
				{
					group.AddButton((TabButton)(object)_tab);
				}
				else if (!flag3 && flag4)
				{
					group.RemoveButton((TabButton)(object)_tab);
				}
			}
		}

		private static bool Create(TabButtonCategory materials, TabGroup group)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Expected O, but got Unknown
			bool flag = (Object)(object)MonumentEntry.Listings[0].Entry != (Object)null;
			Transform transform = ((Component)group).transform;
			bool flag2 = default(bool);
			if (!flag || (Object)(object)transform.Find("Row1") == (Object)null || (Object)(object)transform.Find("Row2") == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(65, 3, ref flag2);
				if (flag2)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Monument][tab] the Monuments tab was not added: entries=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(flag);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" rows=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>((Object)(object)transform.Find("Row1") != (Object)null);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(",");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>((Object)(object)transform.Find("Row2") != (Object)null);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
				}
				log.LogWarning(val);
				return false;
			}
			Sprite sprite = Icon();
			IconOf(((Component)materials).transform);
			GameObject val2 = Object.Instantiate<GameObject>(((Component)materials).gameObject, transform.Find("Row2"), false);
			((Object)val2).name = "MonumentsTab";
			TabButtonCategory component = val2.GetComponent<TabButtonCategory>();
			component.categoryInfos = new List<ItemCategoryInfo>();
			component.excludedInfos = new List<ItemInfo>();
			component.additionalInfos = new List<ItemInfo>();
			foreach (MonumentListing listing in MonumentEntry.Listings)
			{
				component.additionalInfos.Add((ItemInfo)(object)listing.Entry);
			}
			Image obj = IconOf(val2.transform);
			obj.sprite = sprite;
			((Transform)((Graphic)obj).rectTransform).localRotation = Quaternion.identity;
			_tab = component;
			_groupPointer = ((Il2CppObjectBase)group).Pointer;
			ManualLogSource log2 = Plugin.Log;
			BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(44, 0, ref flag2);
			if (flag2)
			{
				((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[Monument][tab] the Monuments tab was added.");
			}
			log2.LogInfo(val3);
			return true;
		}

		private static void PlaceLast(Transform bar)
		{
			Transform val = bar.Find("Row1");
			Transform val2 = bar.Find("Row2");
			int last;
			int num = ShownTabs(val, out last);
			int num2 = ShownTabs(val2, out last);
			Transform transform = ((Component)_tab).transform;
			Transform val3 = ((num > num2) ? val2 : val);
			if ((Object)(object)transform.parent == (Object)null || ((Il2CppObjectBase)transform.parent).Pointer != ((Il2CppObjectBase)val3).Pointer)
			{
				transform.SetParent(val3, false);
			}
			ShownTabs(val3, out var last2);
			transform.SetSiblingIndex((last2 >= 0) ? ((transform.GetSiblingIndex() < last2) ? last2 : (last2 + 1)) : 0);
		}

		private static int ShownTabs(Transform row, out int last)
		{
			int num = 0;
			last = -1;
			for (int i = 0; i < row.childCount; i++)
			{
				Transform child = row.GetChild(i);
				if (!(((Il2CppObjectBase)child).Pointer == ((Il2CppObjectBase)((Component)_tab).transform).Pointer) && ((Component)child).gameObject.activeSelf && !((Object)(object)((Component)child).GetComponent<TabButtonCategory>() == (Object)null))
				{
					num++;
					last = i;
				}
			}
			return num;
		}

		private static Image IconOf(Transform tab)
		{
			Transform obj = tab.Find("Image");
			return ((obj != null) ? ((Component)obj).GetComponent<Image>() : null) ?? throw new InvalidOperationException($"the {((Object)tab).name} tab has no {"Image"} child to draw an icon on");
		}

		private static Sprite Icon()
		{
			return _icon ?? (_icon = EmbeddedSprite.Load("MonumentsTabIcon.png"));
		}

		private static void ExcludeFromVanillaTabs(TabGroup group)
		{
			Transform transform = ((Component)group).transform;
			for (int i = 0; i < transform.childCount; i++)
			{
				Transform child = transform.GetChild(i);
				for (int j = 0; j < child.childCount; j++)
				{
					TabButtonCategory component = ((Component)child.GetChild(j)).GetComponent<TabButtonCategory>();
					if ((Object)(object)component == (Object)null || ((Object)(object)_tab != (Object)null && ((Il2CppObjectBase)component).Pointer == ((Il2CppObjectBase)_tab).Pointer))
					{
						continue;
					}
					TabButtonCategory val = component;
					if (val.excludedInfos == null)
					{
						List<ItemInfo> val2 = (val.excludedInfos = new List<ItemInfo>());
					}
					for (int k = 0; k < MonumentEntry.Listings.Count; k++)
					{
						ItemInfo entry = (ItemInfo)(object)MonumentEntry.Listings[k].Entry;
						if (!Holds(component.excludedInfos, entry))
						{
							component.excludedInfos.Add(entry);
						}
					}
				}
			}
		}

		private static TabButtonCategory FindMaterials(BuildMenu menu, out TabGroup group)
		{
			group = null;
			Il2CppArrayBase<TabGroup> componentsInChildren = ((Component)menu).GetComponentsInChildren<TabGroup>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Transform val = FindByKey(componentsInChildren[i], "misc.materials");
				if ((Object)(object)val != (Object)null)
				{
					group = componentsInChildren[i];
					return ((Component)val).GetComponent<TabButtonCategory>();
				}
			}
			return null;
		}

		private static Transform FindByKey(TabGroup group, string key)
		{
			Transform transform = ((Component)group).transform;
			for (int i = 0; i < transform.childCount; i++)
			{
				Transform child = transform.GetChild(i);
				for (int j = 0; j < child.childCount; j++)
				{
					TabButtonCategory component = ((Component)child.GetChild(j)).GetComponent<TabButtonCategory>();
					if ((Object)(object)component != (Object)null && component.CategoryDisplayName == key)
					{
						return ((Component)component).transform;
					}
				}
			}
			return null;
		}

		private static bool Holds(List<ItemInfo> list, ItemInfo item)
		{
			for (int i = 0; i < list.Count; i++)
			{
				if ((Object)(object)list[i] != (Object)null && ((Il2CppObjectBase)list[i]).Pointer == ((Il2CppObjectBase)item).Pointer)
				{
					return true;
				}
			}
			return false;
		}

		private static int IndexIn(TabGroup group, TabButton button)
		{
			List<TabButton> buttons = group.buttons;
			int num = 0;
			while (buttons != null && num < buttons.Count)
			{
				if ((Object)(object)buttons[num] != (Object)null && ((Il2CppObjectBase)buttons[num]).Pointer == ((Il2CppObjectBase)button).Pointer)
				{
					return num;
				}
				num++;
			}
			return -1;
		}
	}
	public class MonumentTool : MonoBehaviour
	{
		private void Update()
		{
			MonumentToolHost.Tick();
			StampHost.Tick();
		}

		private void OnDestroy()
		{
			StampHost.End();
			MonumentToolHost.ResetForWorld();
			MonumentEntry.ResetForWorld();
		}
	}
	internal static class MonumentToolHost
	{
		private static IntPtr _liveTool;

		private static PlayerBuilder _builder;

		private static DynamicDimensionsPlacementTool _tool;

		private static IntPtr _markerPointer;

		private static Renderer[] _markerRenderers = Array.Empty<Renderer>();

		internal static bool IsLive => _liveTool != IntPtr.Zero;

		internal static Transform Marker
		{
			get
			{
				GameObject val = (((Object)(object)_tool != (Object)null) ? _tool._marker : null);
				if (!((Object)(object)val != (Object)null))
				{
					return null;
				}
				return val.transform;
			}
		}

		internal static void ResetForWorld()
		{
			_liveTool = IntPtr.Zero;
			_builder = null;
			ForgetMarker();
		}

		internal static void Patch(Harmony harmony)
		{
			Type typeFromHandle = typeof(DynamicDimensionsPlacementTool);
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeFromHandle, "Begin", new Type[1] { typeof(StructurePreviewData) }, (Type[])null), Hook("BeforeBegin"), Hook("AfterBegin"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeFromHandle, "End", Type.EmptyTypes, (Type[])null), (HarmonyMethod)null, Hook("AfterEnd"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeFromHandle, "RefreshWidgetData", new Type[1] { typeof(IInteractionWidgetProvider) }, (Type[])null), Hook("BeforeRefreshWidget"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeFromHandle, "_OnSelect", Type.EmptyTypes, (Type[])null), Hook("BeforeSelect"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeFromHandle, "_OnSnap", Type.EmptyTypes, (Type[])null), Hook("BeforeSnap"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.DeclaredMethod(typeFromHandle, "_OnRotate", new Type[1] { typeof(float) }, (Type[])null), Hook("BeforeRotate"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.PropertySetter(typeof(PlayerBuilder), "StructureTemplate"), Hook("BeforeSetTemplate"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		public static bool BeforeSetTemplate(StructureTemplate value)
		{
			if (Plugin.ConfigEnabled.Value || (Object)(object)value == (Object)null || !MonumentEntry.IsEntry(value))
			{
				return true;
			}
			return false;
		}

		internal static void Tick()
		{
			if (!(_liveTool == IntPtr.Zero))
			{
				if (!Plugin.ConfigEnabled.Value)
				{
					CloseTool();
				}
				else
				{
					HideMarker();
				}
			}
		}

		private static void HideMarker()
		{
			GameObject val = (((Object)(object)_tool != (Object)null) ? _tool._marker : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if (((Il2CppObjectBase)val).Pointer != _markerPointer)
			{
				_markerPointer = ((Il2CppObjectBase)val).Pointer;
				_markerRenderers = Il2CppArrayBase<Renderer>.op_Implicit(val.GetComponentsInChildren<Renderer>(true));
			}
			Renderer[] markerRenderers = _markerRenderers;
			foreach (Renderer val2 in markerRenderers)
			{
				if ((Object)(object)val2 != (Object)null && val2.enabled)
				{
					val2.enabled = false;
				}
			}
		}

		private static void ForgetMarker()
		{
			_tool = null;
			_markerPointer = IntPtr.Zero;
			_markerRenderers = Array.Empty<Renderer>();
		}

		internal static void CloseTool()
		{
			PlayerBuilder_NewController val = (((Object)(object)_builder != (Object)null) ? ((Il2CppObjectBase)_builder).TryCast<PlayerBuilder_NewController>() : null);
			_liveTool = IntPtr.Zero;
			ForgetMarker();
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"[Monument][tool] the Monument tool could not be closed: no build controller was recorded.");
			}
			else
			{
				val.Stop();
			}
		}

		public static void BeforeBegin(DynamicDimensionsPlacementTool __instance)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			try
			{
				PlayerBuilder builder = ((PlacementTool)__instance).Builder;
				MonumentListing monumentListing = (((Object)(object)builder != (Object)null) ? MonumentEntry.Find(((StructureBuilder)builder).StructureTemplate) : null);
				if (monumentListing != null)
				{
					_liveTool = ((Il2CppObjectBase)__instance).Pointer;
					_builder = builder;
					StampHost.StartAiming(monumentListing);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(52, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Monument][tool] the Monument tool failed to start: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				log.LogError(val);
			}
		}

		public static void AfterBegin(DynamicDimensionsPlacementTool __instance)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			if (!IsLiveTool(__instance))
			{
				return;
			}
			try
			{
				_tool = __instance;
				_markerPointer = IntPtr.Zero;
				HideMarker();
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(70, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Monument][tool] the Monument tool failed to hide the field's marker: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				log.LogError(val);
			}
		}

		public static void AfterEnd(DynamicDimensionsPlacementTool __instance)
		{
			if (IsLiveTool(__instance))
			{
				_liveTool = IntPtr.Zero;
				ForgetMarker();
				StampHost.StopAiming();
			}
		}

		public static bool BeforeRefreshWidget(DynamicDimensionsPlacementTool __instance)
		{
			return !IsLiveTool(__instance);
		}

		public static bool BeforeSelect(DynamicDimensionsPlacementTool __instance)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			if (!IsLiveTool(__instance))
			{
				return true;
			}
			try
			{
				StampHost.Click();
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(54, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Monument][tool] the Monument tool failed on a click: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				log.LogError(val);
			}
			return false;
		}

		public static bool BeforeSnap(DynamicDimensionsPlacementTool __instance)
		{
			return !IsLiveTool(__instance);
		}

		public static bool BeforeRotate(DynamicDimensionsPlacementTool __instance, float value)
		{
			if (!IsLiveTool(__instance))
			{
				return true;
			}
			StampHost.Rotate(value * __instance.rotateSpeed);
			return false;
		}

		private static bool IsLiveTool(DynamicDimensionsPlacementTool tool)
		{
			if (_liveTool != IntPtr.Zero)
			{
				return ((Il2CppObjectBase)tool).Pointer == _liveTool;
			}
			return false;
		}

		private static HarmonyMethod Hook(string name)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return new HarmonyMethod(AccessTools.DeclaredMethod(typeof(MonumentToolHost), name, (Type[])null, (Type[])null));
		}
	}
	[BepInPlugin("mugsy33.monument", "Monument", "1.0.0")]
	public class Plugin : BasePlugin
	{
		public const string PluginGuid = "mugsy33.monument";

		public const string PluginName = "Monument";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> ConfigEnabled;

		private static ConfigEntry<bool> _clearPerimeter;

		private static ConfigEntry<bool> _clearStructure;

		private static ConfigEntry<bool> _clearPlateau;

		private static ConfigEntry<bool> _allowSteepBlend;

		private static ConfigEntry<bool> _clampToGameLimits;

		internal static ClearSettings ClearSettings => new ClearSettings(_clearPerimeter.Value, _clearStructure.Value, _clearPlateau.Value);

		internal static StampLimits Limits => new StampLimits(_allowSteepBlend.Value, _clampToGameLimits.Value);

		public override void Load()
		{
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_0131: 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_0146: 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_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Expected O, but got Unknown
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Expected O, but got Unknown
			//IL_01a7: Expected O, but got Unknown
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Expected O, but got Unknown
			Log = ((BasePlugin)this).Log;
			ConfigEnabled = ((BasePlugin)this).Config.Bind<bool>("Monument", "Enabled", true, "Master on/off switch for this tool.");
			ClearSettings clearSettings = ClearSettings.Default;
			_clearPerimeter = ((BasePlugin)this).Config.Bind<bool>("Monument", "ClearPerimeter", clearSettings.Perimeter, "When true, a Stamp clears trees, rocks, items, and grass from the flat border and the slope around the Monument. When false, it sets them on the new ground.");
			_clearStructure = ((BasePlugin)this).Config.Bind<bool>("Monument", "ClearStructure", clearSettings.Structure, "When true, a Stamp clears trees, rocks, items, and grass from the Monument's steps, ramps, road, and walls. When false, it sets them on the new ground.");
			_clearPlateau = ((BasePlugin)this).Config.Bind<bool>("Monument", "ClearPlateau", clearSettings.Plateau, "When true, a Stamp clears trees, rocks, items, and grass from the Monument's flat top. When false, it sets them on the new ground.");
			StampLimits stampLimits = StampLimits.Default;
			_allowSteepBlend = ((BasePlugin)this).Config.Bind<bool>("Monument", "AllowSteepBlend", stampLimits.AllowSteep, new ConfigDescription("When true, a Stamp goes ahead where the slope around the Monument would be steeper than 40 degrees. That slope can be too steep to walk.", (AcceptableValueBase)null, new object[1] { "Advanced" }));
			_clampToGameLimits = ((BasePlugin)this).Config.Bind<bool>("Monument", "ClampToGameLimits", stampLimits.ClampToGame, new ConfigDescription("When true, a Stamp that would pass the game's height limit or dig into a cave roof goes ahead, with the ground stopped just inside the limit. The Monument can come out cut flat there.", (AcceptableValueBase)null, new object[1] { "Advanced" }));
			ModStrings.Init(Log, "[Monument][strings]");
			Harmony val = new Harmony("mugsy33.monument");
			val.PatchAll(typeof(GameTerrainWriter.FillPatch));
			val.PatchAll(typeof(GameTerrainWriter.ApplyPatch));
			val.PatchAll(typeof(GameTerrainWriter.PerTilePatch));
			val.PatchAll(typeof(StampHost.AutosavePatch));
			val.PatchAll(typeof(StampHost.QuitToMainMenuPatch));
			val.PatchAll(typeof(StampHost.QuitToDesktopPatch));
			MonumentEntry.Patch(val);
			MonumentsTab.Patch(val);
			MonumentToolHost.Patch(val);
			ClassInjector.RegisterTypeInIl2Cpp<MonumentTool>();
			LocalPlayerTool.Register(Log, "AskaMonument_Tool", Vector3.zero, typeof(MonumentTool));
			ManualLogSource log = Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(10, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("Monument");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" v");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("1.0.0");
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" loaded.");
			}
			log.LogInfo(val2);
		}
	}
	internal static class StampDialog
	{
		internal const string ConfirmCaptionKey = "common.confirm";

		internal const string CancelCaptionKey = "common.cancel";

		private const string Prefix = "[Monument][dialog]";

		private const float VanishGraceSeconds = 5f;

		private const float BottomMargin = 0.06f;

		private const float PlaceTolerance = 1f;

		private static Action<ConfirmActionMenu> _confirmHandler;

		private static Action<ConfirmActionMenu> _cancelHandler;

		private static Action _onConfirm;

		private static Action _onCancel;

		private static Menu _menu;

		private static Menu _lastOpened;

		private static float _lastAliveAt;

		private static readonly RectTransform[] _measured = (RectTransform[])(object)new RectTransform[4];

		private static int _measuredCount;

		private static readonly RectTransform[] _parts = (RectTransform[])(object)new RectTransform[4];

		private static int _partCount;

		private static RectTransform _panel;

		private static RectTransform _canvas;

		internal static bool IsShowing
		{
			get
			{
				if ((Object)(object)_lastOpened != (Object)null)
				{
					return _lastOpened.IsActive;
				}
				return false;
			}
		}

		internal static bool TryOpen(string title, string message, string confirmCaption, string cancelCaption, Action onConfirm, Action onCancel)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Expected O, but got Unknown
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Expected O, but got Unknown
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Expected O, but got Unknown
			Close();
			MenuManager instance = MenuManager.Instance;
			bool flag = default(bool);
			if ((Object)(object)instance == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(49, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("[Monument][dialog]");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" there is no MenuManager; the dialog cannot open.");
				}
				log.LogWarning(val);
				return false;
			}
			ConfirmActionMenu val2 = ResolvePrefab(instance);
			if ((Object)(object)val2 == (Object)null)
			{
				ManualLogSource log2 = Plugin.Log;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(63, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("[Monument][dialog]");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" no ConfirmActionMenu prefab was found; the dialog cannot open.");
				}
				log2.LogWarning(val);
				return false;
			}
			_confirmHandler = HandleConfirm;
			_cancelHandler = HandleCancel;
			ConfirmActionMenuParameters val3 = new ConfirmActionMenuParameters
			{
				Title = title,
				Message = message,
				ConfirmMessage = confirmCaption,
				CancelMessage = cancelCaption,
				CloseOnConfirm = true,
				HideCancelButton = false,
				DontCloseOnEscape = false,
				OnConfirm = DelegateSupport.ConvertDelegate<Action<ConfirmActionMenu>>((Delegate)_confirmHandler),
				OnCancel = DelegateSupport.ConvertDelegate<Action<ConfirmActionMenu>>((Delegate)_cancelHandler)
			};
			Menu val4 = instance.OpenMenuPrefab((Menu)(object)val2, (MenuParameters)(object)val3);
			if ((Object)(object)val4 == (Object)null)
			{
				ManualLogSource log3 = Plugin.Log;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(58, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("[Monument][dialog]");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" OpenMenuPrefab returned nothing; the dialog did not open.");
				}
				log3.LogWarning(val);
				return false;
			}
			_onConfirm = onConfirm;
			_onCancel = onCancel;
			_menu = val4;
			_lastOpened = val4;
			_lastAliveAt = Time.unscaledTime;
			FindParts(((Il2CppObjectBase)val4).TryCast<ConfirmActionMenu>());
			ManualLogSource log4 = Plugin.Log;
			BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(10, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>("[Monument][dialog]");
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" opened '");
				((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(message);
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("'");
			}
			log4.LogInfo(val5);
			return true;
		}

		internal static void KeepAtBottom()
		{
			//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_0036: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_009c: 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)
			//