Decompiled source of GeosBeltTweaks v0.7.0

GeosBeltTweaks.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CommonAPI;
using CommonAPI.Systems.ModLocalization;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
using crecheng.DSPModSave;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("GeosBeltTweaks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Geo's belt tweaks for Dyson Sphere Program")]
[assembly: AssemblyFileVersion("0.7.0.0")]
[assembly: AssemblyInformationalVersion("0.7.0+954ea16393523eea94c036482e9024018f25f01f")]
[assembly: AssemblyProduct("Geo's Belt Tweaks")]
[assembly: AssemblyTitle("GeosBeltTweaks")]
[assembly: AssemblyVersion("0.7.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GeosBeltTweaks
{
	[HarmonyPatch]
	internal static class BeltPreviewTiltPatch
	{
		private sealed class CapRenderer : IDisposable
		{
			internal readonly ConnGizmoRenderer Renderer;

			internal readonly CapBatch Major;

			internal readonly CapBatch Minor;

			internal bool Enabled;

			internal CapRenderer(ConnGizmoRenderer renderer, Mesh major, Mesh minor, Material majorMat, Material minorMat)
			{
				Renderer = renderer;
				Major = new CapBatch(major, majorMat);
				try
				{
					Minor = new CapBatch(minor, minorMat);
				}
				catch
				{
					Major.Dispose();
					throw;
				}
			}

			public void Dispose()
			{
				Major.Dispose();
				Minor.Dispose();
			}
		}

		private sealed class CapBatch : IDisposable
		{
			internal readonly Mesh OriginalMesh;

			internal Mesh GuideMesh;

			internal ConnGizmoObj[] CapInstances = Array.Empty<ConnGizmoObj>();

			private Mesh _capMesh;

			private Material _capMaterial;

			private ComputeBuffer? _instanceBuffer;

			private ComputeBuffer? _drawArgsBuffer;

			private readonly uint[] _drawArgs = new uint[5];

			private int _instanceCount;

			internal CapBatch(Mesh original, Material material)
			{
				//IL_0132: Unknown result type (might be due to invalid IL or missing references)
				//IL_0152: Unknown result type (might be due to invalid IL or missing references)
				//IL_0172: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_02d2: Expected O, but got Unknown
				//IL_02da: Unknown result type (might be due to invalid IL or missing references)
				//IL_02e4: Expected O, but got Unknown
				//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
				//IL_0201: Unknown result type (might be due to invalid IL or missing references)
				//IL_0210: Unknown result type (might be due to invalid IL or missing references)
				//IL_0227: Unknown result type (might be due to invalid IL or missing references)
				OriginalMesh = original;
				try
				{
					Vector3[] vertices = original.vertices;
					int[] triangles = original.triangles;
					List<int> list = new List<int>();
					List<int> list2 = new List<int>();
					for (int i = 0; i < triangles.Length; i += 3)
					{
						List<int> obj = ((vertices[triangles[i]].y >= -0.001f && vertices[triangles[i + 1]].y >= -0.001f && vertices[triangles[i + 2]].y >= -0.001f) ? list : list2);
						obj.Add(triangles[i]);
						obj.Add(triangles[i + 1]);
						obj.Add(triangles[i + 2]);
					}
					if (list.Count == 0 || list2.Count == 0)
					{
						throw new InvalidOperationException("GeosBeltTweaks: belt preview mesh has no separate cap and stem.");
					}
					_capMesh = Object.Instantiate<Mesh>(original);
					List<Vector3> list3 = new List<Vector3>(vertices);
					List<Vector3> list4 = new List<Vector3>(original.normals);
					List<Vector4> list5 = new List<Vector4>(original.tangents);
					List<Color32> list6 = new List<Color32>(original.colors32);
					Dictionary<int, int> dictionary = new Dictionary<int, int>();
					int count = list.Count;
					for (int j = 0; j < count; j += 3)
					{
						if (list4[list[j]].y < 0.99f || list4[list[j + 1]].y < 0.99f || list4[list[j + 2]].y < 0.99f)
						{
							continue;
						}
						for (int num = 2; num >= 0; num--)
						{
							int num2 = list[j + num];
							if (!dictionary.TryGetValue(num2, out var value))
							{
								value = list3.Count;
								dictionary.Add(num2, value);
								Vector3 item = vertices[num2];
								item.y = 0f;
								list3.Add(item);
								list4.Add(Vector3.down);
								if (list5.Count > 0)
								{
									Vector4 val = list5[num2];
									val.w = 0f - val.w;
									list5.Add(val);
								}
								if (list6.Count > 0)
								{
									list6.Add(list6[num2]);
								}
							}
							list.Add(value);
						}
					}
					_capMesh.SetVertices(list3);
					_capMesh.SetNormals(list4);
					if (list5.Count > 0)
					{
						_capMesh.SetTangents(list5);
					}
					if (list6.Count > 0)
					{
						_capMesh.SetColors(list6);
					}
					_capMesh.SetTriangles(list, 0, false);
					GuideMesh = Object.Instantiate<Mesh>(original);
					GuideMesh.SetTriangles(list2, 0, false);
					_capMaterial = new Material(material);
					_drawArgsBuffer = new ComputeBuffer(5, 4, (ComputeBufferType)256);
					_drawArgs[0] = _capMesh.GetIndexCount(0);
					_drawArgs[2] = _capMesh.GetIndexStart(0);
					_drawArgs[3] = _capMesh.GetBaseVertex(0);
				}
				catch
				{
					Dispose();
					throw;
				}
			}

			internal void CopyWithQueuedRotations(List<ConnGizmoObj> source)
			{
				//IL_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0074: 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_007b: 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_0053: Expected O, but got Unknown
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				//IL_0099: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: Unknown result type (might be due to invalid IL or missing references)
				//IL_008c: Unknown result type (might be due to invalid IL or missing references)
				_instanceCount = source.Count;
				if (_instanceCount > CapInstances.Length)
				{
					int num = Mathf.NextPowerOfTwo(_instanceCount);
					CapInstances = (ConnGizmoObj[])(object)new ConnGizmoObj[num];
					ComputeBuffer? instanceBuffer = _instanceBuffer;
					if (instanceBuffer != null)
					{
						instanceBuffer.Release();
					}
					_instanceBuffer = new ComputeBuffer(num, 36);
					_capMaterial.SetBuffer("_ObjBuffer", _instanceBuffer);
				}
				for (int i = 0; i < _instanceCount; i++)
				{
					ConnGizmoObj val = source[i];
					if (QueuedCapRotations.TryGetValue(val.pos, out var value))
					{
						val.rot = value;
					}
					CapInstances[i] = val;
				}
			}

			internal void UploadCaps()
			{
				if (_instanceCount != 0)
				{
					_instanceBuffer.SetData((Array)CapInstances, 0, 0, _instanceCount);
					if (_drawArgs[1] != (uint)_instanceCount)
					{
						_drawArgs[1] = (uint)_instanceCount;
						_drawArgsBuffer.SetData((Array)_drawArgs);
					}
				}
			}

			internal void DrawCaps()
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				if (_instanceCount > 0)
				{
					Graphics.DrawMeshInstancedIndirect(_capMesh, 0, _capMaterial, new Bounds(Vector3.zero, new Vector3(10000f, 10000f, 10000f)), _drawArgsBuffer, 0, (MaterialPropertyBlock)null, (ShadowCastingMode)0, false, 0, (Camera)null, (LightProbeUsage)1);
				}
			}

			public void Dispose()
			{
				ComputeBuffer? instanceBuffer = _instanceBuffer;
				if (instanceBuffer != null)
				{
					instanceBuffer.Release();
				}
				ComputeBuffer? drawArgsBuffer = _drawArgsBuffer;
				if (drawArgsBuffer != null)
				{
					drawArgsBuffer.Release();
				}
				Object.Destroy((Object)(object)_capMesh);
				Object.Destroy((Object)(object)GuideMesh);
				Object.Destroy((Object)(object)_capMaterial);
			}
		}

		private static CapRenderer? _capRenderer;

		private static bool _initializationFailed;

		private static ConnGizmoRenderer? _queuedRotationOwner;

		private static readonly Dictionary<Vector3, Quaternion> QueuedCapRotations = new Dictionary<Vector3, Quaternion>();

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ConnGizmoRenderer), "Update")]
		private static void BeginMarkerUpdate(ConnGizmoRenderer __instance, out bool __state)
		{
			__state = false;
			if (!Plugin.ShowBeltPreviewTilt.Value || _initializationFailed || __instance.factory == null || (Object)(object)__instance.factoryModel == (Object)null || GameMain.localPlanet?.factory != __instance.factory)
			{
				if (_queuedRotationOwner == __instance)
				{
					_queuedRotationOwner = null;
					QueuedCapRotations.Clear();
				}
				return;
			}
			if (_queuedRotationOwner != __instance)
			{
				_queuedRotationOwner = __instance;
				__instance.factoryModel.needRefreshConnGizmo012 = true;
			}
			__state = __instance.factoryModel.needRefreshConnGizmo012 || __instance.cursorGizmoGraph.pointCount > 0;
			if (__state)
			{
				QueuedCapRotations.Clear();
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(ConnGizmoRenderer), "Update")]
		private static IEnumerable<CodeInstruction> InjectQueuedRotationCapture(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			FieldInfo fieldInfo = AccessTools.Field(typeof(PrebuildData), "rot");
			FieldInfo fieldInfo2 = AccessTools.Field(typeof(ConnGizmoObj), "rot");
			int num = -1;
			for (int i = 1; i + 1 < list.Count; i++)
			{
				if (list[i - 1].opcode == OpCodes.Ldelema && object.Equals(list[i - 1].operand, typeof(PrebuildData)) && CodeInstructionExtensions.LoadsField(list[i], fieldInfo, false) && CodeInstructionExtensions.StoresField(list[i + 1], fieldInfo2))
				{
					if (num >= 0)
					{
						throw new InvalidOperationException("GeosBeltTweaks queued belt tilt: multiple marker rotation assignments in ConnGizmoRenderer.Update.");
					}
					num = i;
				}
			}
			if (num < 0)
			{
				throw new InvalidOperationException("GeosBeltTweaks queued belt tilt: marker rotation assignment not found in ConnGizmoRenderer.Update.");
			}
			list[num].opcode = OpCodes.Ldarg_0;
			list[num].operand = null;
			list.Insert(num + 1, new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(BeltPreviewTiltPatch), "CaptureQueuedCapRotation", (Type[])null, (Type[])null)));
			return list;
		}

		private static Quaternion CaptureQueuedCapRotation(ref PrebuildData belt, ConnGizmoRenderer renderer)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if (_queuedRotationOwner != renderer)
			{
				return belt.rot;
			}
			PlanetFactory factory = renderer.factory;
			Vector3 forward = belt.rot * Vector3.forward;
			bool flag = default(bool);
			int num = default(int);
			int num2 = default(int);
			for (int i = 0; i < 4; i++)
			{
				factory.ReadObjectConn(-belt.id, i, ref flag, ref num, ref num2);
				if (num != 0)
				{
					Vector3 val = ((num > 0) ? factory.entityPool[num].pos : factory.prebuildPool[-num].pos);
					forward = (flag ? (val - belt.pos) : (belt.pos - val));
					break;
				}
			}
			QueuedCapRotations[belt.pos] = CalculateCapRotation(belt.rot, belt.pos, forward, belt.tilt);
			return belt.rot;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ConnGizmoRenderer), "Update")]
		private static void UpdateCapBatches(ConnGizmoRenderer __instance, List<ConnGizmoObj> ___objs_0, List<ConnGizmoObj> ___objs_1, Mesh ___mesh_0, Mesh ___mesh_1, Material ___mat_0, Material ___mat_1, bool __state)
		{
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			if (!__state && _queuedRotationOwner == __instance && _capRenderer?.Renderer == __instance)
			{
				return;
			}
			if (_capRenderer?.Renderer == __instance)
			{
				_capRenderer.Enabled = false;
			}
			if (!Plugin.ShowBeltPreviewTilt.Value || _initializationFailed || _queuedRotationOwner != __instance)
			{
				return;
			}
			Player mainPlayer = GameMain.mainPlayer;
			PlayerAction_Build val = ((mainPlayer == null) ? null : mainPlayer.controller?.actionBuild);
			BuildTool_Path val2 = val?.pathTool;
			ConnGizmoGraph cursorGizmoGraph = __instance.cursorGizmoGraph;
			int num = ((val != null && val.active && val2 != null && ((BuildTool)val2).active && val.model.connRenderer == __instance && ((BuildTool)val2).buildPreviews.Count == cursorGizmoGraph.pointCount) ? cursorGizmoGraph.pointCount : 0);
			int num2 = 0;
			int num3 = 0;
			for (int i = 0; i < num; i++)
			{
				BuildPreview val3 = ((BuildTool)val2).buildPreviews[i];
				if (!val3.isConnNode || val3.desc == null || !val3.desc.isBelt)
				{
					return;
				}
				if (!(cursorGizmoGraph.pointsCurrent[i] == Vector3.zero))
				{
					if (i == 0 || i == cursorGizmoGraph.pointCount - 1)
					{
						num2++;
					}
					else
					{
						num3++;
					}
				}
			}
			if (___objs_0.Count + ___objs_1.Count == 0 || num2 > ___objs_0.Count || num3 > ___objs_1.Count)
			{
				return;
			}
			if (_capRenderer?.Renderer != __instance)
			{
				_capRenderer?.Dispose();
				_capRenderer = null;
				try
				{
					_capRenderer = new CapRenderer(__instance, ___mesh_0, ___mesh_1, ___mat_0, ___mat_1);
				}
				catch (Exception arg)
				{
					_initializationFailed = true;
					Plugin.Log.LogError((object)$"Belt preview tilt disabled until restart: could not split the marker meshes. {arg}");
					return;
				}
			}
			CapRenderer capRenderer = _capRenderer;
			capRenderer.Major.CopyWithQueuedRotations(___objs_0);
			capRenderer.Minor.CopyWithQueuedRotations(___objs_1);
			int num4 = ___objs_0.Count - num2;
			int num5 = ___objs_1.Count - num3;
			for (int j = 0; j < num; j++)
			{
				if (cursorGizmoGraph.pointsCurrent[j] == Vector3.zero)
				{
					continue;
				}
				int num6;
				CapBatch capBatch;
				if (j != 0)
				{
					num6 = ((j == cursorGizmoGraph.pointCount - 1) ? 1 : 0);
					if (num6 == 0)
					{
						capBatch = capRenderer.Minor;
						goto IL_0254;
					}
				}
				else
				{
					num6 = 1;
				}
				capBatch = capRenderer.Major;
				goto IL_0254;
				IL_0254:
				CapBatch capBatch2 = capBatch;
				int num7 = ((num6 != 0) ? num4++ : num5++);
				ConnGizmoObj val4 = capBatch2.CapInstances[num7];
				val4.rot = CursorCapRotation(val4.rot, val2, j);
				capBatch2.CapInstances[num7] = val4;
			}
			capRenderer.Major.UploadCaps();
			capRenderer.Minor.UploadCaps();
			capRenderer.Enabled = true;
		}

		private static Quaternion CursorCapRotation(Quaternion rotation, BuildTool_Path tool, int index)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			BuildPreview val = ((BuildTool)tool).buildPreviews[index];
			Vector3 forward;
			if (index + 1 < ((BuildTool)tool).buildPreviews.Count)
			{
				forward = ((BuildTool)tool).buildPreviews[index + 1].lpos - val.lpos;
			}
			else if (index > 0)
			{
				forward = val.lpos - ((BuildTool)tool).buildPreviews[index - 1].lpos;
			}
			else
			{
				if (val.tilt == 0f)
				{
					return rotation;
				}
				forward = rotation * Vector3.forward;
			}
			return CalculateCapRotation(rotation, val.lpos, forward, val.tilt);
		}

		private static Quaternion CalculateCapRotation(Quaternion rotation, Vector3 position, Vector3 forward, float tilt)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.ProjectOnPlane(position, forward);
			if (Vector3.Dot(forward, forward) < 1E-08f || ((Vector3)(ref val)).sqrMagnitude < 1E-08f)
			{
				return rotation;
			}
			Quaternion val2 = Quaternion.LookRotation(forward, val);
			if (tilt != 0f)
			{
				return Quaternion.AngleAxis(tilt, forward) * val2;
			}
			return val2;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ConnGizmoRenderer), "Draw")]
		private static void UseGuideMeshes(ConnGizmoRenderer __instance, ref Mesh ___mesh_0, ref Mesh ___mesh_1, out CapRenderer? __state)
		{
			__state = _capRenderer;
			if (__state == null || !__state.Enabled || __state.Renderer != __instance)
			{
				__state = null;
				return;
			}
			___mesh_0 = __state.Major.GuideMesh;
			___mesh_1 = __state.Minor.GuideMesh;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ConnGizmoRenderer), "Draw")]
		private static void DrawRotatedCaps(ref Mesh ___mesh_0, ref Mesh ___mesh_1, CapRenderer? __state)
		{
			if (__state != null)
			{
				___mesh_0 = __state.Major.OriginalMesh;
				___mesh_1 = __state.Minor.OriginalMesh;
				__state.Major.DrawCaps();
				__state.Minor.DrawCaps();
			}
		}

		[HarmonyFinalizer]
		[HarmonyPatch(typeof(ConnGizmoRenderer), "Draw")]
		private static void RestoreMeshes(ref Mesh ___mesh_0, ref Mesh ___mesh_1, CapRenderer? __state)
		{
			if (__state != null)
			{
				___mesh_0 = __state.Major.OriginalMesh;
				___mesh_1 = __state.Minor.OriginalMesh;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ConnGizmoRenderer), "Destroy")]
		private static void ReleaseRenderer(ConnGizmoRenderer __instance)
		{
			if (_capRenderer?.Renderer == __instance || _queuedRotationOwner == __instance)
			{
				Release();
			}
		}

		internal static void Release()
		{
			_capRenderer?.Dispose();
			_capRenderer = null;
			_initializationFailed = false;
			_queuedRotationOwner = null;
			QueuedCapRotations.Clear();
		}
	}
	[HarmonyPatch]
	internal static class ChainUpgradeAcrossTiersPatch
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(BuildTool_Upgrade), "DetermineMoreChainTargets")]
		private static IEnumerable<CodeInstruction> ChainTargetsTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			FieldInfo fieldInfo = AccessTools.Field(typeof(PrefabDesc), "beltSpeed");
			MethodInfo methodInfo = AccessTools.Method(typeof(ChainUpgradeAcrossTiersPatch), "StopsChain", (Type[])null, (Type[])null);
			int num = 0;
			for (int i = 0; i + 1 < list.Count; i++)
			{
				if (CodeInstructionExtensions.LoadsField(list[i], fieldInfo, false) && (list[i + 1].opcode == OpCodes.Bne_Un || list[i + 1].opcode == OpCodes.Bne_Un_S))
				{
					list[i + 1].opcode = OpCodes.Brtrue;
					list.Insert(++i, new CodeInstruction(OpCodes.Call, (object)methodInfo));
					num++;
				}
			}
			if (num != 1)
			{
				throw new InvalidOperationException($"GeosBeltTweaks chain upgrade across tiers: expected 1 belt speed comparison in BuildTool_Upgrade.DetermineMoreChainTargets, found {num}.");
			}
			return list;
		}

		private static bool StopsChain(int hoveredBeltSpeed, int beltSpeed)
		{
			if (!Plugin.ChainUpgradeAcrossTiers.Value)
			{
				return hoveredBeltSpeed != beltSpeed;
			}
			return false;
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(BuildTool_Upgrade), "UpgradeAction")]
		private static IEnumerable<CodeInstruction> UpgradeActionTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			FieldInfo fieldInfo = AccessTools.Field(typeof(BuildPreview), "objId");
			FieldInfo fieldInfo2 = AccessTools.Field(typeof(BuildTool_Upgrade), "upgradeLevel");
			MethodInfo methodInfo = AccessTools.Method(typeof(ChainUpgradeAcrossTiersPatch), "GetChainGrade", (Type[])null, (Type[])null);
			int num = 0;
			for (int i = 0; i + 3 < list.Count; i++)
			{
				if (CodeInstructionExtensions.LoadsField(list[i], fieldInfo, false) && CodeInstructionExtensions.LoadsConstant(list[i + 1], 0L) && list[i + 2].opcode == OpCodes.Ldarg_0 && CodeInstructionExtensions.LoadsField(list[i + 3], fieldInfo2, false))
				{
					list[i + 1].opcode = OpCodes.Ldarg_0;
					list[i + 1].operand = null;
					list.Insert(i + 2, new CodeInstruction(OpCodes.Call, (object)methodInfo));
					num++;
				}
			}
			if (num != 2)
			{
				throw new InvalidOperationException($"GeosBeltTweaks chain upgrade across tiers: expected 2 DoUpgradeObject grade arguments in BuildTool_Upgrade.UpgradeAction, found {num}.");
			}
			return list;
		}

		private static int GetChainGrade(BuildTool_Upgrade tool)
		{
			if (!Plugin.ChainUpgradeAcrossTiers.Value || !tool.chainReaction || tool.cursorType != 0)
			{
				return 0;
			}
			BuildPreview val = ((BuildTool)tool).buildPreviews[0];
			if (!val.desc.isBelt)
			{
				return 0;
			}
			return Math.Max(1, val.item.Grade + tool.upgradeLevel);
		}
	}
	[HarmonyPatch]
	internal static class HalfGridBeltSnapPatch
	{
		private const float TwoPi = (float)Math.PI * 2f;

		internal static bool Enabled;

		internal static bool HalfStep;

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(BuildTool_Path), "UpdateRaycast")]
		private static IEnumerable<CodeInstruction> SnapCursor(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			MethodInfo methodInfo = AccessTools.Method(typeof(PlanetAuxData), "Snap", new Type[2]
			{
				typeof(Vector3),
				typeof(bool)
			}, (Type[])null);
			List<int> list2 = new List<int>();
			List<int> list3 = new List<int>();
			for (int i = 0; i < list.Count; i++)
			{
				if (CodeInstructionExtensions.Calls(list[i], methodInfo))
				{
					list2.Add(i);
				}
				else if (list[i].opcode == OpCodes.Ldc_R4 && object.Equals(list[i].operand, 0.6f))
				{
					list3.Add(i);
				}
			}
			if (list2.Count != 2 || list3.Count != 2)
			{
				throw new InvalidOperationException($"GeosBeltTweaks half-grid snapping: expected 2 PlanetAuxData.Snap calls and 2 object snap radii in BuildTool_Path.UpdateRaycast, found {list2.Count} and {list3.Count}.");
			}
			foreach (int item in list2)
			{
				list[item].opcode = OpCodes.Call;
				list[item].operand = AccessTools.Method(typeof(HalfGridBeltSnapPatch), "Snap", (Type[])null, (Type[])null);
			}
			foreach (int item2 in list3)
			{
				list[item2].opcode = OpCodes.Call;
				list[item2].operand = AccessTools.Method(typeof(HalfGridBeltSnapPatch), "GetObjectSnapRadius", (Type[])null, (Type[])null);
			}
			return list;
		}

		private static Vector3 Snap(PlanetAuxData aux, Vector3 pos, bool onTerrain)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			Vector3 result = aux.Snap(pos, onTerrain);
			PlanetGrid activeGrid = aux.activeGrid;
			if (!Enabled || activeGrid == null)
			{
				return result;
			}
			Vector3 normalized = ((Vector3)(ref pos)).normalized;
			int segment = activeGrid.segment;
			float row = Mathf.Round(Mathf.Asin(normalized.y) / ((float)Math.PI * 2f) * (float)segment * 10f) / 10f;
			float columnCount = GetColumnCount(row, segment);
			float column = Mathf.Round(Mathf.Atan2(normalized.x, 0f - normalized.z) / ((float)Math.PI * 2f) * columnCount * 10f) / 10f;
			float num = ((Vector3)(ref result)).magnitude + (HalfStep ? 0.6666666f : 0f);
			return GetDirection(row, column, segment, columnCount) * num;
		}

		private static float GetObjectSnapRadius()
		{
			if (!Enabled)
			{
				return 0.6f;
			}
			return 0.3f;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(PlanetGrid), "SnapLineNonAlloc")]
		private static bool SnapLine(PlanetGrid __instance, Vector3 begin, Vector3 end, int path, Vector3[] snaps, out int swerveIndex, ref int __result)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			swerveIndex = 0;
			if (!Enabled)
			{
				return true;
			}
			int segment = __instance.segment;
			int capacity = snaps.Length - 10;
			int count = 0;
			__result = 0;
			if (capacity <= 0)
			{
				return false;
			}
			Vector3 normalized = ((Vector3)(ref begin)).normalized;
			Vector3 normalized2 = ((Vector3)(ref end)).normalized;
			float num = Mathf.Asin(normalized.y);
			float num2 = Mathf.Atan2(normalized.x, 0f - normalized.z);
			float num3 = Mathf.Asin(normalized2.y);
			float num4 = Mathf.Atan2(normalized2.x, 0f - normalized2.z);
			bool flag = (normalized.x * normalized.x + normalized.z * normalized.z) * (float)segment * (float)segment < 1f;
			bool flag2 = (normalized2.x * normalized2.x + normalized2.z * normalized2.z) * (float)segment * (float)segment < 1f;
			if (flag && flag2 && normalized.y * normalized2.y >= 0f)
			{
				snaps[0] = new Vector3(0f, (normalized.y >= 0f) ? 1f : (-1f), 0f);
				__result = 1;
				return false;
			}
			if (flag && flag2)
			{
				num2 = (num4 = 0f);
				num = Mathf.Sign(num) * (float)Math.PI * 0.5f;
				num3 = Mathf.Sign(num3) * (float)Math.PI * 0.5f;
			}
			else if (flag)
			{
				num2 = num4;
				num = Mathf.Sign(num) * (float)Math.PI * 0.5f;
			}
			else if (flag2)
			{
				num4 = num2;
				num3 = Mathf.Sign(num3) * (float)Math.PI * 0.5f;
			}
			float num5 = Mathf.Repeat(num4 - num2, (float)Math.PI * 2f);
			if (num5 > (float)Math.PI)
			{
				num5 -= (float)Math.PI * 2f;
			}
			if (num5 > 2f || num5 < -2f)
			{
				num5 -= Mathf.Sign(num5) * (float)Math.PI;
				num3 = ((num3 >= 0f) ? ((float)Math.PI) : (-(float)Math.PI)) - num3;
			}
			num4 = num2 + num5;
			int num6 = Mathf.RoundToInt(num / ((float)Math.PI * 2f) * (float)segment * 10f);
			int num7 = Mathf.RoundToInt(num3 / ((float)Math.PI * 2f) * (float)segment * 10f);
			float row;
			float columns;
			int num8 = Mathf.RoundToInt(GetHalfColumn(num6, num2, out row, out columns)) & 1;
			int num9 = Mathf.RoundToInt(GetHalfColumn(num7, num4, out columns, out row)) & 1;
			if (path == 1)
			{
				AddParallel(num6, num2, num8, num4, num9);
				swerveIndex = count;
				AddMeridian(num4, num9, num6, num7);
			}
			else
			{
				AddMeridian(num2, num8, num6, num7);
				swerveIndex = count;
				AddParallel(num7, num2, num8, num4, num9);
			}
			__result = count;
			return false;
			void Add(Vector3 point)
			{
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: 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_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				float num10 = 0.25f / (float)segment;
				if (count < capacity)
				{
					if (count != 0)
					{
						Vector3 val = point - snaps[count - 1];
						if (!(((Vector3)(ref val)).sqrMagnitude > num10 * num10))
						{
							return;
						}
					}
					snaps[count++] = point;
				}
			}
			void AddMeridian(float longitude, int parity, int fromHalfRow, int toHalfRow)
			{
				int num10 = ((toHalfRow >= fromHalfRow) ? 2 : (-2));
				for (int i = fromHalfRow; (toHalfRow - i) * num10 > 0; i += num10)
				{
					if (count >= capacity)
					{
						break;
					}
					AddOnMeridian(i, longitude, parity);
				}
				AddOnMeridian(toHalfRow, longitude, parity);
			}
			void AddOnMeridian(int halfRow, float longitude, int parity)
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				float row2;
				float columns2;
				int num10 = Align(GetHalfColumn(halfRow, longitude, out row2, out columns2), parity);
				Add(GetDirection(row2, (float)num10 / 10f, segment, columns2));
			}
			void AddParallel(int halfRow, float fromLongitude, int fromParity, float toLongitude, int toParity)
			{
				//IL_0089: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				float row2;
				float columns2;
				int num10 = Align(GetHalfColumn(halfRow, fromLongitude, out row2, out columns2), fromParity);
				float row3;
				float columns3;
				int num11 = Align(GetHalfColumn(halfRow, toLongitude, out row3, out columns3), toParity);
				int num12 = ((num11 >= num10) ? 2 : (-2));
				for (int i = num10; (num11 - i) * num12 > 0; i += num12)
				{
					if (count >= capacity)
					{
						break;
					}
					Add(GetDirection(row2, (float)i / 10f, segment, columns2));
				}
				Add(GetDirection(row2, (float)num11 / 10f, segment, columns2));
			}
			static int Align(float halfColumn, int parity)
			{
				return parity + 2 * Mathf.RoundToInt((halfColumn - (float)parity) / 2f);
			}
			float GetHalfColumn(int halfRow, float longitude, out float reference, out float reference2)
			{
				reference = (float)halfRow / 10f;
				if (Mathf.Abs(reference) > (float)segment / 4f)
				{
					reference = Mathf.Sign(reference) * (float)segment / 2f - reference;
					longitude += (float)Math.PI;
				}
				reference2 = GetColumnCount(reference, segment);
				return longitude / ((float)Math.PI * 2f) * reference2 * 10f;
			}
		}

		private static float GetColumnCount(float row, int segment)
		{
			return PlanetGrid.DetermineLongitudeSegmentCount(Mathf.FloorToInt(Mathf.Max(0f, Mathf.Abs(row) - 0.05f)), segment);
		}

		private static Vector3 GetDirection(float row, float column, int segment, float columns)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			float num = row / (float)segment * ((float)Math.PI * 2f);
			float num2 = column / columns * ((float)Math.PI * 2f);
			float num3 = Mathf.Cos(num);
			return new Vector3(num3 * Mathf.Sin(num2), Mathf.Sin(num), (0f - num3) * Mathf.Cos(num2));
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(BuildTool_Path), "DeterminePreviews")]
		private static void StepHalfHeight(BuildTool_Path __instance)
		{
			if (!Enabled)
			{
				return;
			}
			if (VFInput._notSnapBuild)
			{
				if (VFInput._liftBeltsHeight)
				{
					HalfStep &= __instance.altitude + 2 < 60;
					__instance.altitude -= 3;
				}
				if (VFInput._reduceBeltsHeight)
				{
					HalfStep &= __instance.altitude >= 2;
					__instance.altitude += 3;
				}
				return;
			}
			if (VFInput._liftBeltsHeight)
			{
				if (HalfStep)
				{
					HalfStep = false;
				}
				else if (__instance.altitude < 60)
				{
					HalfStep = true;
					__instance.altitude--;
				}
			}
			if (VFInput._reduceBeltsHeight)
			{
				if (HalfStep)
				{
					HalfStep = false;
					__instance.altitude++;
				}
				else if (__instance.altitude > 0)
				{
					HalfStep = true;
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BuildTool_Path), "_OnClose")]
		private static void ClearHalfStep()
		{
			HalfStep = false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIBuildingGrid), "Update")]
		private static void RaiseAltitudeGrid(UIBuildingGrid __instance)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			PlanetData localPlanet = GameMain.localPlanet;
			Player mainPlayer = GameMain.mainPlayer;
			if (HalfStep && __instance.altGridRnd.enabled && localPlanet != null && mainPlayer != null)
			{
				float num = (localPlanet.realRadius + 0.2f + ((float)mainPlayer.controller.actionBuild.pathTool.altitude + 0.5f) * 1.3333333f) * 2f;
				((Component)__instance.altGridRnd).transform.localScale = new Vector3(num, num, num);
			}
		}
	}
	[HarmonyPatch(typeof(BuildTool_Path), "ConfirmOperation")]
	internal static class MatchStartingBeltPatch
	{
		[HarmonyPrefix]
		private static void Prefix(BuildTool_Path __instance, out int __state)
		{
			__state = ((BuildTool)__instance).controller.cmd.stage;
		}

		[HarmonyPostfix]
		private static void Postfix(BuildTool_Path __instance, int __state)
		{
			if (__state != 0 || ((BuildTool)__instance).controller.cmd.stage != 1)
			{
				return;
			}
			ItemProto itemProto = ((BuildTool)__instance).GetItemProto(__instance.startObjectId);
			if (itemProto == null || (!itemProto.prefabDesc.isBelt && !itemProto.prefabDesc.isSplitter))
			{
				return;
			}
			if (Plugin.MatchStartingBeltHeight.Value)
			{
				float num = ((Vector3)(ref __instance.startTarget)).magnitude - ((BuildTool)__instance).planet.realRadius - 0.2f;
				if (HalfGridBeltSnapPatch.Enabled)
				{
					int num2 = Mathf.Clamp(Mathf.RoundToInt(num / 0.6666666f), 0, 120);
					__instance.altitude = num2 / 2;
					HalfGridBeltSnapPatch.HalfStep = num2 % 2 == 1;
				}
				else
				{
					__instance.altitude = Mathf.Clamp(Mathf.RoundToInt(num / 1.3333333f), 0, 60);
				}
			}
			if (itemProto.prefabDesc.isBelt && Plugin.MatchStartingBeltTier.Value && ((Proto)itemProto).ID != ((BuildTool)__instance).controller.cmd.refId)
			{
				((BuildTool)__instance).player.SetHandItems(((Proto)itemProto).ID, 0, 0);
				((BuildTool)__instance).controller.cmd.refId = ((Proto)itemProto).ID;
				__instance.UpdateHandItem();
			}
		}
	}
	[HarmonyPatch]
	internal static class PauseBattleBaseBuildingPatch
	{
		internal static bool Enabled;

		private static PlanetFactory? _pausedFactory;

		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(ConstructionModuleComponent), "GameTick", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ConstructionModuleComponent), "PlaceItems", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ConstructionModuleComponent), "SearchBuildTargets", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ConstructionSystem), "UpdateDrones", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ConstructionSystem), "AddBuildTargetToModules", (Type[])null, (Type[])null);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			FieldInfo fieldInfo = AccessTools.Field(typeof(ConstructionModuleComponent), "droneConstructEnabled");
			MethodInfo operand = AccessTools.Method(typeof(PauseBattleBaseBuildingPatch), "CanBuild", (Type[])null, (Type[])null);
			bool flag = false;
			foreach (CodeInstruction item in list)
			{
				if (CodeInstructionExtensions.LoadsField(item, fieldInfo, false))
				{
					item.opcode = OpCodes.Call;
					item.operand = operand;
					flag = true;
				}
			}
			if (!flag)
			{
				throw new InvalidOperationException("GeosBeltTweaks BAB building pause: droneConstructEnabled not read in " + original.DeclaringType.Name + "." + original.Name + ".");
			}
			return list;
		}

		private static bool CanBuild(ConstructionModuleComponent module)
		{
			ConstructionModuleComponent[] array = _pausedFactory?.constructionSystem.constructionModules.buffer;
			if (module.droneConstructEnabled)
			{
				if (array != null && module.id < array.Length)
				{
					return array[module.id] != module;
				}
				return true;
			}
			return false;
		}

		internal static void Update()
		{
			Player mainPlayer = GameMain.mainPlayer;
			PlanetFactory val = ((Enabled && ((mainPlayer != null) ? mainPlayer.controller.actionBuild.activeTool : null) is BuildTool_Path) ? mainPlayer.factory : null);
			if (val == _pausedFactory)
			{
				return;
			}
			PlanetFactory pausedFactory = _pausedFactory;
			_pausedFactory = val;
			if (mainPlayer != null)
			{
				if (pausedFactory != null && pausedFactory.gameData == GameMain.data)
				{
					SearchBuildTargets(pausedFactory, mainPlayer);
				}
				if (val != null)
				{
					SearchBuildTargets(val, mainPlayer);
				}
			}
		}

		private static void SearchBuildTargets(PlanetFactory factory, Player player)
		{
			ObjectPool<ConstructionModuleComponent> constructionModules = factory.constructionSystem.constructionModules;
			for (int i = 1; i < constructionModules.cursor; i++)
			{
				ConstructionModuleComponent val = constructionModules.buffer[i];
				if (val != null && val.id == i && val.entityId > 0 && factory.entityPool[val.entityId].id == val.entityId)
				{
					val.SearchBuildTargets(factory, player, true);
				}
			}
		}
	}
	[BepInPlugin("com.geostyx.dsp.geosbelttweaks", "Geo's Belt Tweaks", "0.7.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[CommonAPISubmoduleDependency(new string[] { "LocalizationModule" })]
	public class Plugin : BaseUnityPlugin, IModCanSave
	{
		private const int SaveVersion = 2;

		private Harmony? _harmony;

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> MatchStartingBeltTier;

		internal static ConfigEntry<bool> MatchStartingBeltHeight;

		internal static ConfigEntry<bool> ShowBeltPreviewTilt;

		internal static ConfigEntry<bool> ToggleBeltSurfaceHeight;

		internal static ConfigEntry<bool> RememberBeltFreeAngleMode;

		internal static ConfigEntry<bool> UnlimitedChainUpgradeRange;

		internal static ConfigEntry<bool> ChainUpgradeAcrossTiers;

		internal static ConfigEntry<KeyboardShortcut> ToggleHalfGridSnapKey;

		internal static ConfigEntry<KeyboardShortcut> ToggleSlopeFromStartKey;

		internal static ConfigEntry<KeyboardShortcut> ToggleBattleBaseConstructionKey;

		private void Awake()
		{
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			MatchStartingBeltHeight = ((BaseUnityPlugin)this).Config.Bind<bool>("Building", "MatchStartingBeltHeight", true, "Start new belts at the height of the belt or splitter you drag from.");
			MatchStartingBeltTier = ((BaseUnityPlugin)this).Config.Bind<bool>("Building", "MatchStartingBeltTier", true, "Select the starting belt's tier when extending it.");
			ShowBeltPreviewTilt = ((BaseUnityPlugin)this).Config.Bind<bool>("Building", "ShowBeltPreviewTilt", true, "Show slope and tilt in belt previews.");
			ToggleBeltSurfaceHeight = ((BaseUnityPlugin)this).Config.Bind<bool>("Building", "ToggleBeltSurfaceHeight", true, "The reset-height key toggles between the surface and the previous height.");
			RememberBeltFreeAngleMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Building", "RememberBeltFreeAngleMode", true, "Keep free-angle mode on when reopening the belt tool.");
			UnlimitedChainUpgradeRange = ((BaseUnityPlugin)this).Config.Bind<bool>("Building", "UnlimitedChainUpgradeRange", true, "Chain upgrades reach the whole belt, ignoring build range.");
			ChainUpgradeAcrossTiers = ((BaseUnityPlugin)this).Config.Bind<bool>("Building", "ChainUpgradeAcrossTiers", true, "Chain upgrades continue through tier changes.");
			ToggleHalfGridSnapKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Building", "ToggleHalfGridSnapKey", new KeyboardShortcut((KeyCode)96, Array.Empty<KeyCode>()), "Toggles half-grid snapping in the belt tool.");
			ToggleSlopeFromStartKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Building", "ToggleSlopeFromStartKey", new KeyboardShortcut((KeyCode)257, Array.Empty<KeyCode>()), "Toggles sloping from the first segment in the belt tool.");
			ToggleBattleBaseConstructionKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Building", "ToggleBattleBaseConstructionKey", new KeyboardShortcut((KeyCode)258, Array.Empty<KeyCode>()), "Toggles building by Battlefield Analysis Bases on the planet while the belt tool is open.");
			ToggleHalfGridSnapKey.SettingChanged += ToggleKeyTip.HalfGrid.OnKeyChanged;
			ToggleSlopeFromStartKey.SettingChanged += ToggleKeyTip.SlopeFromStart.OnKeyChanged;
			ToggleBattleBaseConstructionKey.SettingChanged += ToggleKeyTip.BattleBaseConstruction.OnKeyChanged;
			LocalizationModule.RegisterTranslation(ToggleKeyTip.HalfGrid.OnText, "Half-grid: on", "半格:开", "");
			LocalizationModule.RegisterTranslation(ToggleKeyTip.HalfGrid.OffText, "Half-grid: off", "半格:关", "");
			LocalizationModule.RegisterTranslation(ToggleKeyTip.SlopeFromStart.OnText, "Slope from start: on", "起点起坡:开", "");
			LocalizationModule.RegisterTranslation(ToggleKeyTip.SlopeFromStart.OffText, "Slope from start: off", "起点起坡:关", "");
			LocalizationModule.RegisterTranslation(ToggleKeyTip.BattleBaseConstruction.OnText, "BAB construction: on", "战场分析基站建设:开", "");
			LocalizationModule.RegisterTranslation(ToggleKeyTip.BattleBaseConstruction.OffText, "BAB construction: off", "战场分析基站建设:关", "");
			_harmony = new Harmony("com.geostyx.dsp.geosbelttweaks");
			try
			{
				_harmony.PatchAll(typeof(Plugin).Assembly);
			}
			catch
			{
				_harmony.UnpatchSelf();
				_harmony = null;
				throw;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Geo's Belt Tweaks 0.7.0 loaded");
		}

		private void Update()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			PauseBattleBaseBuildingPatch.Update();
			if (VFInput.inputing)
			{
				return;
			}
			Player mainPlayer = GameMain.mainPlayer;
			if (((mainPlayer != null) ? mainPlayer.controller.actionBuild.activeTool : null) is BuildTool_Path)
			{
				KeyboardShortcut value = ToggleHalfGridSnapKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					HalfGridBeltSnapPatch.Enabled = !HalfGridBeltSnapPatch.Enabled;
					HalfGridBeltSnapPatch.HalfStep = false;
				}
				value = ToggleSlopeFromStartKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					SlopeFromStartPatch.Enabled = !SlopeFromStartPatch.Enabled;
				}
				value = ToggleBattleBaseConstructionKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					PauseBattleBaseBuildingPatch.Enabled = !PauseBattleBaseBuildingPatch.Enabled;
				}
			}
		}

		private void OnDestroy()
		{
			ToggleHalfGridSnapKey.SettingChanged -= ToggleKeyTip.HalfGrid.OnKeyChanged;
			ToggleSlopeFromStartKey.SettingChanged -= ToggleKeyTip.SlopeFromStart.OnKeyChanged;
			ToggleBattleBaseConstructionKey.SettingChanged -= ToggleKeyTip.BattleBaseConstruction.OnKeyChanged;
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			BeltPreviewTiltPatch.Release();
			ToggleBeltSurfaceHeightPatch.ClearSavedHeight();
			ToggleKeyTip.HalfGrid.Destroy();
			ToggleKeyTip.SlopeFromStart.Destroy();
			ToggleKeyTip.BattleBaseConstruction.Destroy();
		}

		public void Export(BinaryWriter w)
		{
			w.Write(2);
			w.Write(HalfGridBeltSnapPatch.Enabled);
			w.Write(SlopeFromStartPatch.Enabled);
			Player mainPlayer = GameMain.mainPlayer;
			w.Write(mainPlayer != null && mainPlayer.controller.actionBuild.pathTool.geodesic);
			w.Write(PauseBattleBaseBuildingPatch.Enabled);
		}

		public void Import(BinaryReader r)
		{
			int num = r.ReadInt32();
			if (num > 2)
			{
				Log.LogWarning((object)$"Ignoring belt tool modes saved by a newer version (save data version {num})");
				IntoOtherSave();
				return;
			}
			HalfGridBeltSnapPatch.Enabled = r.ReadBoolean();
			HalfGridBeltSnapPatch.HalfStep = false;
			SlopeFromStartPatch.Enabled = r.ReadBoolean();
			bool geodesic = r.ReadBoolean();
			PauseBattleBaseBuildingPatch.Enabled = num >= 2 && r.ReadBoolean();
			if (GameMain.mainPlayer != null)
			{
				GameMain.mainPlayer.controller.actionBuild.pathTool.geodesic = geodesic;
			}
		}

		public void IntoOtherSave()
		{
			HalfGridBeltSnapPatch.Enabled = false;
			HalfGridBeltSnapPatch.HalfStep = false;
			SlopeFromStartPatch.Enabled = false;
			PauseBattleBaseBuildingPatch.Enabled = false;
		}
	}
	[HarmonyPatch(typeof(BuildTool_Path), "_OnOpen")]
	internal static class RememberBeltFreeAngleModePatch
	{
		[HarmonyPrefix]
		private static void Prefix(BuildTool_Path __instance, out bool __state)
		{
			__state = Plugin.RememberBeltFreeAngleMode.Value && __instance.geodesic;
		}

		[HarmonyPostfix]
		private static void Postfix(BuildTool_Path __instance, bool __state)
		{
			if (__state)
			{
				__instance.geodesic = true;
			}
		}
	}
	[HarmonyPatch(typeof(PlanetAuxData), "SnapLineNonAlloc")]
	internal static class SlopeFromStartPatch
	{
		internal static bool Enabled;

		private static bool _snappingFlatStart;

		[HarmonyPrefix]
		private static void Prefix(ref bool begin_flat, out bool __state)
		{
			__state = begin_flat && Enabled && !_snappingFlatStart;
			begin_flat &= !__state;
		}

		[HarmonyPostfix]
		private static void Postfix(PlanetAuxData __instance, Vector3 begin, Vector3 end, int path, bool geodesic, Vector3[] snaps, bool forceVertical, ref float maxGridSlope, bool useOldPath, ref int __result, bool __state)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			if (!__state || __result < 2 || CanSlopeFromStart(begin, snaps[1]))
			{
				return;
			}
			if (HalfGridBeltSnapPatch.Enabled && __result < snaps.Length - 10)
			{
				Vector3 val = snaps[0];
				Vector3 val2 = Vector3.Slerp(((Vector3)(ref val)).normalized, ((Vector3)(ref snaps[1])).normalized, 0.5f) * ((Vector3)(ref val)).magnitude;
				Vector3 val3 = val2 - val;
				if (((Vector3)(ref val3)).sqrMagnitude >= 0.28f)
				{
					for (int num = __result; num >= 2; num--)
					{
						snaps[num] = ((Vector3)(ref snaps[num - 1])).normalized * ((((Vector3)(ref snaps[num - 1])).magnitude + ((Vector3)(ref snaps[num - 2])).magnitude) / 2f);
					}
					snaps[1] = val2;
					__result++;
					return;
				}
			}
			_snappingFlatStart = true;
			try
			{
				__result = __instance.SnapLineNonAlloc(begin, end, path, geodesic, true, snaps, forceVertical, ref maxGridSlope, useOldPath);
			}
			finally
			{
				_snappingFlatStart = false;
			}
		}

		private static bool CanSlopeFromStart(Vector3 start, Vector3 next)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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)
			if (Mathf.Abs(Maths.SphericalSlopeRatio(start, next)) <= 0.1f)
			{
				return true;
			}
			Player mainPlayer = GameMain.mainPlayer;
			BuildTool_Path val = ((mainPlayer == null) ? null : mainPlayer.controller?.actionBuild?.pathTool);
			if (val == null || !((BuildTool)val).ObjectIsBelt(val.startObjectId))
			{
				return false;
			}
			PlanetFactory factory = ((BuildTool)val).factory;
			bool flag = default(bool);
			int num = default(int);
			int num2 = default(int);
			for (int i = 1; i < 4; i++)
			{
				factory.ReadObjectConn(val.startObjectId, i, ref flag, ref num, ref num2);
				if (num != 0)
				{
					Vector3 val2 = ((num > 0) ? factory.entityPool[num].pos : factory.prebuildPool[-num].pos);
					if (Maths.SphericalAngleAOBInRAD(start, next, val2) >= 2.5f)
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	[HarmonyPatch]
	internal static class ToggleBeltSurfaceHeightPatch
	{
		private static int _savedAltitude;

		private static bool _savedHalfStep;

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(BuildTool_Path), "DeterminePreviews")]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(VFInput), "_beltsZeroKey");
			FieldInfo fieldInfo = AccessTools.Field(typeof(BuildTool_Path), "altitude");
			int num = -1;
			for (int i = 0; i + 4 < list.Count; i++)
			{
				if (CodeInstructionExtensions.Calls(list[i], methodInfo) && (list[i + 1].opcode == OpCodes.Brfalse || list[i + 1].opcode == OpCodes.Brfalse_S) && list[i + 2].opcode == OpCodes.Ldarg_0 && CodeInstructionExtensions.LoadsConstant(list[i + 3], 0L) && CodeInstructionExtensions.StoresField(list[i + 4], fieldInfo))
				{
					if (num >= 0)
					{
						throw new InvalidOperationException("GeosBeltTweaks belt surface toggle: multiple reset-height assignments in BuildTool_Path.DeterminePreviews.");
					}
					num = i + 3;
				}
			}
			if (num < 0)
			{
				throw new InvalidOperationException("GeosBeltTweaks belt surface toggle: reset-height assignment not found in BuildTool_Path.DeterminePreviews.");
			}
			list[num].opcode = OpCodes.Ldarg_0;
			list[num].operand = null;
			list.Insert(num + 1, new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ToggleBeltSurfaceHeightPatch), "GetResetHeight", (Type[])null, (Type[])null)));
			return list;
		}

		private static int GetResetHeight(BuildTool_Path tool)
		{
			if (!Plugin.ToggleBeltSurfaceHeight.Value)
			{
				_savedAltitude = 0;
				_savedHalfStep = false;
				HalfGridBeltSnapPatch.HalfStep = false;
				return 0;
			}
			if (tool.altitude == 0 && !HalfGridBeltSnapPatch.HalfStep)
			{
				HalfGridBeltSnapPatch.HalfStep = _savedHalfStep && HalfGridBeltSnapPatch.Enabled;
				return _savedAltitude;
			}
			_savedAltitude = Math.Max(0, Math.Min(60, tool.altitude));
			_savedHalfStep = HalfGridBeltSnapPatch.HalfStep && _savedAltitude < 60;
			HalfGridBeltSnapPatch.HalfStep = false;
			return 0;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BuildTool_Path), "_OnOpen")]
		private static void OnOpen()
		{
			_savedAltitude = 0;
			_savedHalfStep = false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BuildTool_Path), "_OnClose")]
		internal static void ClearSavedHeight()
		{
			_savedAltitude = 0;
			_savedHalfStep = false;
		}
	}
	[HarmonyPatch]
	internal sealed class ToggleKeyTip(string onText, string offText)
	{
		internal static readonly ToggleKeyTip HalfGrid = new ToggleKeyTip("GeosBeltTweaks half-grid snapping on", "GeosBeltTweaks half-grid snapping off");

		internal static readonly ToggleKeyTip SlopeFromStart = new ToggleKeyTip("GeosBeltTweaks slope from start on", "GeosBeltTweaks slope from start off");

		internal static readonly ToggleKeyTip BattleBaseConstruction = new ToggleKeyTip("GeosBeltTweaks battle base construction on", "GeosBeltTweaks battle base construction off");

		internal readonly string OnText = onText;

		internal readonly string OffText = offText;

		private UIKeyTipNode? _keyTip;

		private string _onTip = "";

		private string _offTip = "";

		private bool _keyLabelStale;

		private bool _hasKey;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIKeyTips), "RegisterAllTips")]
		private static void RegisterKeyTips(UIKeyTips __instance)
		{
			HalfGrid.Register(__instance);
			SlopeFromStart.Register(__instance);
			BattleBaseConstruction.Register(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIKeyTips), "UpdateTipDesiredState")]
		private static void UpdateKeyTips(UIKeyTips __instance)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			HalfGrid.Update(__instance, Plugin.ToggleHalfGridSnapKey.Value, HalfGridBeltSnapPatch.Enabled);
			SlopeFromStart.Update(__instance, Plugin.ToggleSlopeFromStartKey.Value, SlopeFromStartPatch.Enabled);
			BattleBaseConstruction.Update(__instance, Plugin.ToggleBattleBaseConstructionKey.Value, !PauseBattleBaseBuildingPatch.Enabled);
		}

		private void Register(UIKeyTips tips)
		{
			_onTip = Localization.Translate(onText);
			_offTip = Localization.Translate(offText);
			_keyTip = tips.RegisterTip("", _offTip);
			_keyLabelStale = true;
		}

		private void Update(UIKeyTips tips, KeyboardShortcut shortcut, bool on)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected I4, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected I4, but got Unknown
			//IL_00ad: 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)
			if ((Object)(object)_keyTip == (Object)null)
			{
				return;
			}
			if (_keyLabelStale)
			{
				_keyLabelStale = false;
				_hasKey = (int)((KeyboardShortcut)(ref shortcut)).MainKey > 0;
				byte b = 0;
				foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
				{
					int num = b;
					int num2;
					switch (modifier - 303)
					{
					case 0:
					case 1:
						num2 = 1;
						break;
					case 2:
					case 3:
						num2 = 2;
						break;
					case 4:
					case 5:
						num2 = 4;
						break;
					default:
						num2 = 0;
						break;
					}
					b = (byte)(num | num2);
				}
				UIKeyTipNode? keyTip = _keyTip;
				CombineKey val = new CombineKey((int)((KeyboardShortcut)(ref shortcut)).MainKey, b, (ECombineKeyAction)0, false);
				keyTip.SetKeyTip(((CombineKey)(ref val)).ToTokenString(0), _offTip);
			}
			_keyTip.desired = _hasKey && tips.zeroKeyInBuildMode2.desired;
			_keyTip.tipTextComp.text = (on ? _onTip : _offTip);
		}

		internal void OnKeyChanged(object sender, EventArgs e)
		{
			_keyLabelStale = true;
		}

		internal void Destroy()
		{
			if ((Object)(object)_keyTip != (Object)null)
			{
				((ManualBehaviour)_keyTip)._Destroy();
			}
			_keyTip = null;
		}
	}
	[HarmonyPatch(typeof(BuildTool_Upgrade), "DetermineMoreChainTargets")]
	internal static class UnlimitedChainUpgradeRangePatch
	{
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			FieldInfo fieldInfo = AccessTools.Field(typeof(Mecha), "buildArea");
			MethodInfo methodInfo = AccessTools.Method(typeof(UnlimitedChainUpgradeRangePatch), "GetChainBuildArea", (Type[])null, (Type[])null);
			int num = 0;
			for (int i = 0; i < list.Count; i++)
			{
				if (CodeInstructionExtensions.LoadsField(list[i], fieldInfo, false))
				{
					list.Insert(++i, new CodeInstruction(OpCodes.Call, (object)methodInfo));
					num++;
				}
			}
			if (num != 2)
			{
				throw new InvalidOperationException($"GeosBeltTweaks unlimited chain upgrade range: expected 2 build area reads in BuildTool_Upgrade.DetermineMoreChainTargets, found {num}.");
			}
			return list;
		}

		private static float GetChainBuildArea(float buildArea)
		{
			if (!Plugin.UnlimitedChainUpgradeRange.Value)
			{
				return buildArea;
			}
			return float.PositiveInfinity;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "com.geostyx.dsp.geosbelttweaks";

		public const string PLUGIN_NAME = "Geo's Belt Tweaks";

		public const string PLUGIN_VERSION = "0.7.0";
	}
}