Decompiled source of NordicWindmill v0.1.0

plugins/NordicWindmill.dll

Decompiled 14 hours ago
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyVersion("0.1.0.0")]
namespace NordicWindmill;

internal static class AuthoredRotorMesh
{
	private sealed class Data
	{
		internal Vector3[] Points;

		internal Vector3[] Normals;

		internal Vector2[] UV;

		internal int[] Indices;

		internal float Radius;
	}

	private static Data cached;

	private static Data Read()
	{
		//IL_0107: 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_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_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		if (cached != null)
		{
			return cached;
		}
		using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("NordicWindmill.RotorMesh");
		if (stream == null)
		{
			throw new InvalidDataException("Embedded authored rotor missing.");
		}
		using BinaryReader binaryReader = new BinaryReader(stream);
		if (binaryReader.ReadUInt32() != 827479886)
		{
			throw new InvalidDataException("Invalid rotor header.");
		}
		int num = binaryReader.ReadInt32();
		int num2 = binaryReader.ReadInt32();
		float num3 = binaryReader.ReadSingle();
		if (num < 3 || num > 1000000 || num2 < 3 || num2 > 6000000 || num2 % 3 != 0 || !Finite(num3) || num3 <= 0f)
		{
			throw new InvalidDataException("Invalid rotor dimensions.");
		}
		Data data = new Data();
		data.Points = (Vector3[])(object)new Vector3[num];
		data.Normals = (Vector3[])(object)new Vector3[num];
		data.UV = (Vector2[])(object)new Vector2[num];
		data.Indices = new int[num2];
		data.Radius = num3;
		Data data2 = data;
		for (int i = 0; i < num; i++)
		{
			ref Vector3 reference = ref data2.Points[i];
			reference = new Vector3(Number(binaryReader), Number(binaryReader), Number(binaryReader));
			ref Vector3 reference2 = ref data2.Normals[i];
			reference2 = new Vector3(Number(binaryReader), Number(binaryReader), Number(binaryReader));
			ref Vector2 reference3 = ref data2.UV[i];
			reference3 = new Vector2(Number(binaryReader), Number(binaryReader));
		}
		for (int j = 0; j < num2; j++)
		{
			int num4 = binaryReader.ReadInt32();
			if (num4 < 0 || num4 >= num)
			{
				throw new InvalidDataException("Invalid rotor index.");
			}
			data2.Indices[j] = num4;
		}
		if (stream.Position != stream.Length)
		{
			throw new InvalidDataException("Unexpected rotor data.");
		}
		cached = data2;
		return data2;
	}

	private static bool Finite(float x)
	{
		if (!float.IsNaN(x))
		{
			return !float.IsInfinity(x);
		}
		return false;
	}

	private static float Number(BinaryReader reader)
	{
		float num = reader.ReadSingle();
		if (!Finite(num))
		{
			throw new InvalidDataException("Nonfinite rotor vertex.");
		}
		return num;
	}

	internal static Mesh Create(MeshFilter source, Transform rotor, float nativeRadius, float multiplier, float nativePlane)
	{
		//IL_0046: 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_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_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: 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_00d7: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Expected O, but got Unknown
		if (!Finite(nativeRadius) || nativeRadius <= 0f || !Finite(multiplier) || multiplier <= 0f || !Finite(nativePlane))
		{
			throw new ArgumentOutOfRangeException("Invalid authored rotor scale.");
		}
		Data data = Read();
		float num = nativeRadius * multiplier / data.Radius;
		Matrix4x4 val = rotor.worldToLocalMatrix * ((Component)source).transform.localToWorldMatrix;
		Matrix4x4 inverse = ((Matrix4x4)(ref val)).inverse;
		Matrix4x4 transpose = ((Matrix4x4)(ref val)).transpose;
		int num2 = data.Points.Length;
		Vector3[] array = (Vector3[])(object)new Vector3[num2 * 2];
		Vector3[] array2 = (Vector3[])(object)new Vector3[array.Length];
		Color[] array3 = (Color[])(object)new Color[array.Length];
		for (int i = 0; i < num2; i++)
		{
			Vector3 val2 = data.Points[i] * num;
			val2.z += nativePlane;
			ref Vector3 reference = ref array[i];
			reference = ((Matrix4x4)(ref inverse)).MultiplyPoint3x4(val2);
			ref Vector3 reference2 = ref array2[i];
			Vector3 val3 = ((Matrix4x4)(ref transpose)).MultiplyVector(data.Normals[i]);
			reference2 = ((Vector3)(ref val3)).normalized;
			ref Color reference3 = ref array3[i];
			reference3 = Color.white;
			ref Vector3 reference4 = ref array[i + num2];
			reference4 = array[i];
			ref Vector3 reference5 = ref array2[i + num2];
			reference5 = array2[i] * -1f;
			ref Color reference6 = ref array3[i + num2];
			reference6 = Color.white;
		}
		Mesh val4 = new Mesh();
		((Object)val4).name = "BlenderAuthoredNordicRotor";
		val4.indexFormat = (IndexFormat)(array.Length > 65535);
		Mesh val5 = val4;
		Vector2[] array4 = (Vector2[])(object)new Vector2[array.Length];
		Array.Copy(data.UV, 0, array4, 0, num2);
		Array.Copy(data.UV, 0, array4, num2, num2);
		int[] array5 = new int[data.Indices.Length * 2];
		Array.Copy(data.Indices, array5, data.Indices.Length);
		for (int j = 0; j < data.Indices.Length; j += 3)
		{
			int num3 = data.Indices.Length + j;
			array5[num3] = data.Indices[j] + num2;
			array5[num3 + 1] = data.Indices[j + 2] + num2;
			array5[num3 + 2] = data.Indices[j + 1] + num2;
		}
		val5.vertices = array;
		val5.normals = array2;
		val5.uv = array4;
		val5.colors = array3;
		val5.subMeshCount = 1;
		val5.SetTriangles(array5, 0);
		val5.RecalculateTangents();
		val5.RecalculateBounds();
		return val5;
	}
}
internal sealed class ConfigurationManagerAttributes
{
	public bool? ShowRangeAsPercent;
}
public struct Point
{
	public float X;

	public float Y;

	public float Z;

	public float Length => (float)Math.Sqrt(X * X + Y * Y + Z * Z);

	public Point Normal => this * (1f / Math.Max(1E-05f, Length));

	public Point(float x, float y, float z)
	{
		X = x;
		Y = y;
		Z = z;
	}

	public static Point operator +(Point a, Point b)
	{
		return new Point(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
	}

	public static Point operator -(Point a, Point b)
	{
		return new Point(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
	}

	public static Point operator *(Point a, float b)
	{
		return new Point(a.X * b, a.Y * b, a.Z * b);
	}

	public static Point Cross(Point a, Point b)
	{
		return new Point(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);
	}
}
public enum Finish
{
	Stone,
	Wood,
	DarkWood,
	Roof,
	Canvas,
	Iron
}
public sealed class Surface
{
	public readonly List<Point> Vertices = new List<Point>();

	public readonly List<int> Triangles = new List<int>();

	public readonly List<float> UV = new List<float>();

	public void Quad(Point a, Point b, Point c, Point d)
	{
		int count = Vertices.Count;
		Vertices.AddRange(new Point[4] { a, b, c, d });
		float length = (b - a).Length;
		float length2 = (d - a).Length;
		UV.AddRange(new float[8] { 0f, 0f, length, 0f, length, length2, 0f, length2 });
		Triangles.AddRange(new int[6]
		{
			count,
			count + 1,
			count + 2,
			count,
			count + 2,
			count + 3
		});
	}

	public void Triangle(Point a, Point b, Point c)
	{
		int count = Vertices.Count;
		Vertices.AddRange(new Point[3] { a, b, c });
		UV.AddRange(new float[6] { 0f, 0f, 1f, 0f, 0.5f, 1f });
		Triangles.AddRange(new int[3]
		{
			count,
			count + 1,
			count + 2
		});
	}
}
public sealed class Model
{
	public readonly Dictionary<Finish, Surface> Surfaces = new Dictionary<Finish, Surface>();

	public Surface Get(Finish finish)
	{
		if (!Surfaces.TryGetValue(finish, out var value))
		{
			Surfaces.Add(finish, value = new Surface());
		}
		return value;
	}

	public void Beam(Point start, Point end, float width, float depth, Finish finish)
	{
		Point normal = (end - start).Normal;
		Point point = Point.Cross(normal, (Math.Abs(normal.Y) < 0.9f) ? new Point(0f, 1f, 0f) : new Point(0f, 0f, 1f)).Normal * (width * 0.5f);
		Point point2 = Point.Cross(normal, point.Normal).Normal * (depth * 0.5f);
		Point[] array = new Point[8]
		{
			start - point - point2,
			start + point - point2,
			start + point + point2,
			start - point + point2,
			end - point - point2,
			end + point - point2,
			end + point + point2,
			end - point + point2
		};
		Surface surface = Get(finish);
		surface.Quad(array[0], array[3], array[2], array[1]);
		surface.Quad(array[4], array[5], array[6], array[7]);
		surface.Quad(array[0], array[1], array[5], array[4]);
		surface.Quad(array[1], array[2], array[6], array[5]);
		surface.Quad(array[2], array[3], array[7], array[6]);
		surface.Quad(array[3], array[0], array[4], array[7]);
	}

	public void Wall(Point a, Point b, Point c, Point d, float thickness, Finish finish)
	{
		Point point = Point.Cross(b - a, c - a).Normal * (0f - thickness);
		Surface surface = Get(finish);
		surface.Quad(a, b, c, d);
		surface.Quad(a + point, d + point, c + point, b + point);
		surface.Quad(a, a + point, b + point, b);
		surface.Quad(b, b + point, c + point, c);
		surface.Quad(c, c + point, d + point, d);
		surface.Quad(d, d + point, a + point, a);
	}

	public void Ring(float bottom, float top, float lowerRadius, float upperRadius, int sides, Finish finish, float offset = 0f)
	{
		Surface surface = Get(finish);
		for (int i = 0; i < sides; i++)
		{
			float angle = offset + (float)(Math.PI * 2.0 * (double)i / (double)sides);
			float angle2 = offset + (float)(Math.PI * 2.0 * (double)(i + 1) / (double)sides);
			Point a = Radial(angle, lowerRadius, bottom);
			Point d = Radial(angle2, lowerRadius, bottom);
			Point c = Radial(angle2, upperRadius, top);
			Point b = Radial(angle, upperRadius, top);
			surface.Quad(a, b, c, d);
		}
	}

	public static Point Radial(float angle, float radius, float y)
	{
		return new Point((float)Math.Cos(angle) * radius, y, (float)Math.Sin(angle) * radius);
	}
}
public static class Design
{
	public static Model UpperTower(float height, float bottomRadius, float topRadius)
	{
		Model model = new Model();
		for (int i = 0; i < 8; i++)
		{
			float angle = (float)(Math.PI * 2.0 * (double)i / 8.0);
			float angle2 = (float)(Math.PI * 2.0 * (double)(i + 1) / 8.0);
			Point point = Model.Radial(angle, bottomRadius, 0f);
			Point point2 = Model.Radial(angle2, bottomRadius, 0f);
			Point point3 = Model.Radial(angle, topRadius, height);
			Point point4 = Model.Radial(angle2, topRadius, height);
			model.Wall(point, point3, point4, point2, 0.07f, Finish.Wood);
			model.Beam(point, point3, 0.12f, 0.12f, Finish.DarkWood);
			for (int j = 0; j < 3; j++)
			{
				float num = (float)j / 3f;
				float num2 = (float)(j + 1) / 3f;
				Point start = point + (point3 - point) * num;
				Point point5 = point2 + (point4 - point2) * num;
				Point end = point + (point3 - point) * num2;
				Point end2 = point2 + (point4 - point2) * num2;
				model.Beam(start, point5, 0.12f, 0.12f, Finish.DarkWood);
				model.Beam(start, end2, 0.08f, 0.08f, Finish.DarkWood);
				model.Beam(point5, end, 0.08f, 0.08f, Finish.DarkWood);
			}
			model.Beam(point3, point4, 0.15f, 0.15f, Finish.DarkWood);
			model.Get(Finish.DarkWood).Triangle(new Point(0f, 0f, 0f), point, point2);
			model.Get(Finish.DarkWood).Triangle(new Point(0f, height, 0f), point4, point3);
		}
		return model;
	}

	public static Model Tower(float height, float radius, bool includeRoof = true)
	{
		if (height <= 0f || radius <= 0f)
		{
			throw new ArgumentOutOfRangeException();
		}
		Model model = new Model();
		float num = height * 0.32f;
		float radius2 = radius * 0.7f;
		for (int i = 0; i < 32; i++)
		{
			float angle = (float)(Math.PI * 2.0 * (double)i / 32.0);
			float angle2 = (float)(Math.PI * 2.0 * (double)(i + 1) / 32.0);
			model.Wall(Model.Radial(angle, radius * 0.965f, 0f), Model.Radial(angle, radius * 0.9f, num), Model.Radial(angle2, radius * 0.9f, num), Model.Radial(angle2, radius * 0.965f, 0f), radius * 0.06f, Finish.Stone);
		}
		int num2 = Math.Max(4, (int)(num / (radius * 0.26f)));
		for (int j = 0; j < num2; j++)
		{
			float y = num * (float)j / (float)num2 + 0.014f;
			float y2 = num * (float)(j + 1) / (float)num2 - 0.014f;
			int num3 = 16;
			float num4 = (float)(j % 2) * (float)Math.PI / (float)num3;
			for (int k = 0; k < num3; k++)
			{
				float angle3 = (float)(Math.PI * 2.0 * (double)k / (double)num3) + num4 + 0.012f;
				float angle4 = (float)(Math.PI * 2.0 * (double)(k + 1) / (double)num3) + num4 - 0.012f;
				float num5 = radius * (1f - 0.09f * (float)j / (float)num2);
				Surface surface = model.Get(Finish.Stone);
				surface.Quad(Model.Radial(angle3, num5, y), Model.Radial(angle3, num5, y2), Model.Radial(angle4, num5, y2), Model.Radial(angle4, num5, y));
				surface.Quad(Model.Radial(angle3, num5, y2), Model.Radial(angle3, num5 * 0.96f, y2), Model.Radial(angle4, num5 * 0.96f, y2), Model.Radial(angle4, num5, y2));
				surface.Quad(Model.Radial(angle3, num5 * 0.96f, y), Model.Radial(angle3, num5 * 0.96f, y2), Model.Radial(angle3, num5, y2), Model.Radial(angle3, num5, y));
				surface.Quad(Model.Radial(angle4, num5, y), Model.Radial(angle4, num5, y2), Model.Radial(angle4, num5 * 0.96f, y2), Model.Radial(angle4, num5 * 0.96f, y));
			}
		}
		float radius3 = radius * 0.9f;
		float num6 = radius * 0.09f;
		for (int l = 0; l < 8; l++)
		{
			float angle5 = (float)(Math.PI * 2.0 * (double)l / 8.0);
			float angle6 = (float)(Math.PI * 2.0 * (double)(l + 1) / 8.0);
			Point point = Model.Radial(angle5, radius3, num);
			Point point2 = Model.Radial(angle6, radius3, num);
			Point point3 = Model.Radial(angle5, radius2, height);
			Point point4 = Model.Radial(angle6, radius2, height);
			for (int m = 0; m < 8; m++)
			{
				float num7 = (float)m / 8f;
				float num8 = (float)(m + 1) / 8f;
				model.Wall(point + (point2 - point) * num7, point3 + (point4 - point3) * num7, point3 + (point4 - point3) * num8, point + (point2 - point) * num8, radius * 0.025f, Finish.Wood);
			}
			model.Beam(point, point3, num6, num6, Finish.DarkWood);
			for (int n = 0; n < 3; n++)
			{
				float num9 = (float)n / 3f;
				float num10 = (float)(n + 1) / 3f;
				Point start = point + (point3 - point) * num9;
				Point point5 = point2 + (point4 - point2) * num9;
				Point end = point + (point3 - point) * num10;
				Point end2 = point2 + (point4 - point2) * num10;
				model.Beam(start, point5, num6, num6, Finish.DarkWood);
				model.Beam(start, end2, num6 * 0.65f, num6 * 0.65f, Finish.DarkWood);
				model.Beam(point5, end, num6 * 0.65f, num6 * 0.65f, Finish.DarkWood);
			}
			model.Beam(point3, point4, num6 * 1.5f, num6 * 1.5f, Finish.DarkWood);
		}
		if (includeRoof)
		{
			AddRoof(model, height, radius);
		}
		return model;
	}

	private static void RoundPole(Model model, Point start, Point end, float radius)
	{
		Point normal = (end - start).Normal;
		Point normal2 = Point.Cross(normal, new Point(0f, 0f, 1f)).Normal;
		Point normal3 = Point.Cross(normal, normal2).Normal;
		for (int i = 0; i < 8; i++)
		{
			float num = (float)((double)i * Math.PI / 4.0);
			float num2 = (float)((double)(i + 1) * Math.PI / 4.0);
			Point point = normal2 * ((float)Math.Cos(num) * radius) + normal3 * ((float)Math.Sin(num) * radius);
			Point point2 = normal2 * ((float)Math.Cos(num2) * radius) + normal3 * ((float)Math.Sin(num2) * radius);
			model.Get(Finish.Wood).Quad(start + point, start + point2, end + point2 * 0.85f, end + point * 0.85f);
			model.Get(Finish.Wood).Triangle(start, start + point2, start + point);
			model.Get(Finish.Wood).Triangle(end, end + point * 0.85f, end + point2 * 0.85f);
		}
	}

	public static Model VanillaFrameExtension(float nativeRadius, float multiplier)
	{
		Model model = new Model();
		float num = nativeRadius * 0.85f;
		float num2 = nativeRadius * 0.5f;
		for (int i = 0; i < 4; i++)
		{
			float a = (float)((double)i * Math.PI / 2.0);
			Func<float, float, Point> func = (float x, float height) => BladePoint(x, height, 0f, a);
			RoundPole(model, func(0f, num * 0.6f), func(0f, num * multiplier), 0.045f);
			RoundPole(model, func(num2, num * 0.9f), func(num2 * multiplier, num * multiplier), 0.036f);
			RoundPole(model, func(0f, num * multiplier), func(num2 * multiplier, num * multiplier), 0.04f);
			RoundPole(model, func(0f, num), func(num2, num), 0.032f);
		}
		return model;
	}

	public static Model SquareRoof(float halfWidth)
	{
		Model model = new Model();
		float y = 0.7f;
		Point[] array = new Point[4]
		{
			new Point(0f - halfWidth, 0f, 0f - halfWidth),
			new Point(0f - halfWidth, 0f, halfWidth),
			new Point(halfWidth, 0f, halfWidth),
			new Point(halfWidth, 0f, 0f - halfWidth)
		};
		Point point = new Point(0f, y, 0f);
		for (int i = 0; i < 4; i++)
		{
			Point point2 = array[i];
			Point point3 = array[(i + 1) % 4];
			model.Get(Finish.Roof).Triangle(point2, point3, point);
			model.Get(Finish.Roof).Triangle(point2 + new Point(0f, -0.05f, 0f), point + new Point(0f, -0.05f, 0f), point3 + new Point(0f, -0.05f, 0f));
			model.Beam(point2, point3, 0.12f, 0.12f, Finish.DarkWood);
			model.Beam(point2, point, 0.08f, 0.08f, Finish.DarkWood);
		}
		model.Get(Finish.DarkWood).Quad(array[0], array[3], array[2], array[1]);
		return model;
	}

	public static Model Roof(float radius)
	{
		Model model = new Model();
		AddRoof(model, 0f, radius);
		return model;
	}

	private static void AddRoof(Model m, float height, float radius)
	{
		float num = radius * 0.7f;
		float num2 = radius * 0.09f;
		m.Ring(height - 0.08f * radius, height + 0.08f * radius, num * 1.2f, num * 1.2f, 8, Finish.DarkWood);
		for (int i = 0; i < 10; i++)
		{
			float num3 = (float)i / 10f;
			float num4 = (float)(i + 1) / 10f;
			float num5 = num * 1.34f * (1f - num3) + radius * 0.025f;
			float upperRadius = num * 1.34f * (1f - num4) + radius * 0.025f;
			m.Ring(height + radius * 0.08f + radius * 1.15f * num3, height + radius * 0.08f + radius * 1.15f * num4, num5, upperRadius, 24, Finish.Roof);
			m.Ring(height + radius * 0.08f + radius * 1.15f * num3 - 0.015f, height + radius * 0.08f + radius * 1.15f * num3 + 0.015f, num5 * 1.015f, num5, 24, Finish.DarkWood);
		}
		float num6 = height + radius * 1.23f;
		m.Beam(new Point(0f, num6 - 0.1f * radius, 0f), new Point(0f, num6 + 0.35f * radius, 0f), num2, num2, Finish.DarkWood);
		m.Beam(new Point(0f, num6 + 0.1f * radius, 0f), new Point(radius * 0.2f, num6 + 0.35f * radius, 0f), num2 * 0.7f, num2 * 0.7f, Finish.DarkWood);
		m.Beam(new Point(0f, num6 + 0.1f * radius, 0f), new Point((0f - radius) * 0.2f, num6 + 0.35f * radius, 0f), num2 * 0.7f, num2 * 0.7f, Finish.DarkWood);
	}

	private static Point BladePoint(float x, float y, float z, float angle)
	{
		return new Point(x * (float)Math.Cos(angle) - y * (float)Math.Sin(angle), x * (float)Math.Sin(angle) + y * (float)Math.Cos(angle), z);
	}

	public static Model Rotor(float radius)
	{
		if (radius <= 0f)
		{
			throw new ArgumentOutOfRangeException();
		}
		Model model = new Model();
		for (int i = 0; i < 4; i++)
		{
			float angle = (float)i * (float)Math.PI / 2f;
			Func<float, float, float, Point> func = (float x, float y, float z) => BladePoint(x, y, z, angle);
			float num = radius * 0.026f;
			model.Beam(func(0f, radius * 0.04f, 0f), func((0f - radius) * 0.065f, radius, 0f), num * 1.4f, num, Finish.DarkWood);
			for (int num2 = 0; num2 < 9; num2++)
			{
				float num3 = (float)num2 / 9f;
				float num4 = (float)(num2 + 1) / 9f;
				float arg = radius * (0.23f + 0.75f * num3);
				float arg2 = radius * (0.23f + 0.75f * num4);
				float num5 = radius * (0.09f + 0.16f * (float)Math.Sin((double)num3 * Math.PI * 0.65));
				float num6 = radius * (0.09f + 0.16f * (float)Math.Sin((double)num4 * Math.PI * 0.65));
				float num7 = (0f - radius) * 0.065f * num3;
				float num8 = (0f - radius) * 0.065f * num4;
				for (int num9 = 0; num9 < 3; num9++)
				{
					float num10 = ((float)num9 + 0.04f) / 3f - 0.18f;
					float num11 = ((float)num9 + 0.96f) / 3f - 0.18f;
					float arg3 = num5 * num10 * 0.28f;
					float arg4 = num5 * num11 * 0.28f;
					float arg5 = num6 * num10 * 0.28f;
					float arg6 = num6 * num11 * 0.28f;
					Point point = func(num7 + num5 * num10, arg, arg3);
					Point point2 = func(num7 + num5 * num11, arg, arg4);
					Point point3 = func(num8 + num6 * num11, arg2, arg6);
					Point point4 = func(num8 + num6 * num10, arg2, arg5);
					Point point5 = new Point(0f, 0f, radius * 0.006f);
					Surface surface = model.Get(Finish.Canvas);
					surface.Quad(point, point2, point3, point4);
					surface.Quad(point - point5, point4 - point5, point3 - point5, point2 - point5);
					surface.Quad(point - point5, point2 - point5, point2, point);
					surface.Quad(point4, point3, point3 - point5, point4 - point5);
					surface.Quad(point, point4, point4 - point5, point - point5);
					surface.Quad(point2 - point5, point3 - point5, point3, point2);
				}
				model.Beam(func(num7 - num5 * 0.18f, arg, -0.01f), func(num7 + num5 * 0.82f, arg, num5 * 0.23f), num * 0.5f, num * 0.5f, Finish.Wood);
			}
			for (int num12 = 0; num12 < 2; num12++)
			{
				float num13 = ((num12 == 0) ? (-0.18f) : 0.82f);
				for (int num14 = 0; num14 < 12; num14++)
				{
					float num15 = (float)num14 / 12f;
					float num16 = (float)(num14 + 1) / 12f;
					float num17 = radius * (0.09f + 0.16f * (float)Math.Sin((double)num15 * Math.PI * 0.65));
					float num18 = radius * (0.09f + 0.16f * (float)Math.Sin((double)num16 * Math.PI * 0.65));
					model.Beam(func((0f - radius) * 0.065f * num15 + num17 * num13, radius * (0.23f + 0.75f * num15), num17 * num13 * 0.28f), func((0f - radius) * 0.065f * num16 + num18 * num13, radius * (0.23f + 0.75f * num16), num18 * num13 * 0.28f), num * 0.7f, num * 0.7f, Finish.Wood);
				}
			}
		}
		for (int num19 = 0; num19 < 16; num19++)
		{
			float num20 = (float)(Math.PI * 2.0 * (double)num19 / 16.0);
			float num21 = (float)(Math.PI * 2.0 * (double)(num19 + 1) / 16.0);
			float num22 = radius * 0.085f;
			Point a = new Point((float)Math.Cos(num20) * num22, (float)Math.Sin(num20) * num22, 0f - num22);
			Point b = new Point((float)Math.Cos(num21) * num22, (float)Math.Sin(num21) * num22, 0f - num22);
			Point point6 = new Point(a.X, a.Y, num22);
			Point c = new Point(b.X, b.Y, num22);
			model.Get(Finish.Iron).Quad(a, b, c, point6);
			model.Get(Finish.DarkWood).Triangle(new Point(0f, 0f, num22), point6, c);
		}
		return model;
	}
}
public sealed class Layout
{
	public float Ground;

	public float Centre;

	public float Radius;

	public float TowerRadius;

	public float RotorPlane;

	public float TotalHeight;

	public float TowerLift;

	public float RoofBase;

	public static Layout Create(float ground, float originalHeight, float nativeRadius, float towerRadius, float nativePlane, float heightMultiplier, float bladeMultiplier, float widthMultiplier, float nativeRotorHeight = 5.708f)
	{
		if (originalHeight <= 0f || nativeRadius <= 0f || towerRadius <= 0f)
		{
			throw new ArgumentOutOfRangeException();
		}
		Layout layout = new Layout();
		layout.Ground = ground;
		layout.TowerLift = originalHeight * (heightMultiplier - 1f);
		layout.RoofBase = 3.92f + layout.TowerLift;
		layout.Radius = nativeRadius * bladeMultiplier;
		layout.TowerRadius = towerRadius;
		layout.Centre = nativeRotorHeight + layout.TowerLift;
		layout.TotalHeight = Math.Max(layout.Centre + layout.Radius * 1.04f, ground + originalHeight + layout.TowerLift) - ground;
		layout.RotorPlane = Math.Abs(nativePlane);
		return layout;
	}
}
public static class MaterialRules
{
	public static bool Usable(string shader, string material, bool hasTexture)
	{
		if (shader != "Custom/Piece" || !hasTexture || string.IsNullOrEmpty(material))
		{
			return false;
		}
		string text = material.ToLowerInvariant();
		if (!text.Contains("snow") && !text.Contains("ghost") && !text.Contains("worn"))
		{
			return !text.Contains("broken");
		}
		return false;
	}
}
internal static class NativeRearVane
{
	private struct Vertex
	{
		internal Vector3 P;

		internal Vector3 N;

		internal Vector2 UV;

		internal Color Color;

		internal static Vertex Lerp(Vertex a, Vertex b, float t)
		{
			//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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0057: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			Vertex result = new Vertex
			{
				P = Vector3.Lerp(a.P, b.P, t)
			};
			Vector3 val = Vector3.Lerp(a.N, b.N, t);
			result.N = ((Vector3)(ref val)).normalized;
			result.UV = Vector2.Lerp(a.UV, b.UV, t);
			result.Color = Color.Lerp(a.Color, b.Color, t);
			return result;
		}
	}

	internal static Mesh Create(MeshFilter source, Transform frame)
	{
		//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0300: Expected O, but got Unknown
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: 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_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_0266: Unknown result type (might be due to invalid IL or missing references)
		//IL_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_0282: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)source == (Object)null || (Object)(object)source.sharedMesh == (Object)null || !source.sharedMesh.isReadable)
		{
			throw new InvalidOperationException("Native rear vane mesh is not readable.");
		}
		Mesh sharedMesh = source.sharedMesh;
		Vector3[] vertices = sharedMesh.vertices;
		Vector3[] normals = sharedMesh.normals;
		Vector2[] uv = sharedMesh.uv;
		Color[] colors = sharedMesh.colors;
		List<Vector3> list = new List<Vector3>();
		List<Vector3> list2 = new List<Vector3>();
		List<Vector2> list3 = new List<Vector2>();
		List<Color> list4 = new List<Color>();
		List<int> list5 = new List<int>();
		int[] triangles = sharedMesh.triangles;
		for (int i = 0; i < triangles.Length; i += 3)
		{
			List<Vertex> list6 = new List<Vertex>();
			for (int j = 0; j < 3; j++)
			{
				int num = triangles[i + j];
				Vertex item = new Vertex
				{
					P = frame.InverseTransformPoint(((Component)source).transform.TransformPoint(vertices[num]))
				};
				Vector3 n;
				if (normals.Length != vertices.Length)
				{
					n = Vector3.up;
				}
				else
				{
					Vector3 val = frame.InverseTransformDirection(((Component)source).transform.TransformDirection(normals[num]));
					n = ((Vector3)(ref val)).normalized;
				}
				item.N = n;
				item.UV = ((uv.Length == vertices.Length) ? uv[num] : Vector2.zero);
				item.Color = ((colors.Length == vertices.Length) ? colors[num] : Color.white);
				list6.Add(item);
			}
			List<Vertex> list7 = new List<Vertex>();
			for (int k = 0; k < list6.Count; k++)
			{
				Vertex vertex = list6[k];
				Vertex b = list6[(k + 1) % list6.Count];
				bool flag = vertex.P.z <= -0.3f;
				bool flag2 = b.P.z <= -0.3f;
				if (flag)
				{
					list7.Add(vertex);
				}
				if (flag != flag2)
				{
					list7.Add(Vertex.Lerp(vertex, b, (-0.3f - vertex.P.z) / (b.P.z - vertex.P.z)));
				}
			}
			if (list7.Count < 3)
			{
				continue;
			}
			int count = list.Count;
			foreach (Vertex item2 in list7)
			{
				list.Add(item2.P);
				list2.Add(item2.N);
				list3.Add(item2.UV);
				list4.Add(item2.Color);
			}
			for (int l = 1; l < list7.Count - 1; l++)
			{
				list5.AddRange(new int[3]
				{
					count,
					count + l,
					count + l + 1
				});
			}
		}
		Mesh val2 = new Mesh();
		((Object)val2).name = "OriginalRearWindVane";
		val2.SetVertices(list);
		val2.SetNormals(list2);
		val2.SetUVs(0, list3);
		val2.SetColors(list4);
		val2.SetTriangles(list5, 0);
		val2.RecalculateTangents();
		val2.RecalculateBounds();
		return val2;
	}
}
internal static class NativeSailMesh
{
	private sealed class Vertex
	{
		internal Vector3 P;

		internal Vector3 N;

		internal Color C;

		internal Vector4[] UV;

		internal static Vertex Mix(Vertex a, Vertex b, float t)
		{
			//IL_0008: 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_0014: 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_0020: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0040: 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_004c: 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_0080: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			Vertex vertex = new Vertex();
			vertex.P = Vector3.Lerp(a.P, b.P, t);
			Vector3 val = Vector3.Lerp(a.N, b.N, t);
			vertex.N = ((Vector3)(ref val)).normalized;
			vertex.C = Color.Lerp(a.C, b.C, t);
			vertex.UV = (Vector4[])(object)new Vector4[8];
			Vertex vertex2 = vertex;
			for (int i = 0; i < 8; i++)
			{
				ref Vector4 reference = ref vertex2.UV[i];
				reference = Vector4.Lerp(a.UV[i], b.UV[i], t);
			}
			return vertex2;
		}
	}

	private static float Y(Vertex v, int blade)
	{
		return NativeSailShape.Local(new Point(v.P.x, v.P.y, v.P.z), blade).Y;
	}

	private static List<Vertex> Clip(List<Vertex> input, int blade, float height, bool below)
	{
		List<Vertex> list = new List<Vertex>();
		for (int i = 0; i < input.Count; i++)
		{
			Vertex vertex = input[i];
			Vertex vertex2 = input[(i + 1) % input.Count];
			float num = Y(vertex, blade);
			float num2 = Y(vertex2, blade);
			bool flag = (below ? (num <= height) : (num >= height));
			bool flag2 = (below ? (num2 <= height) : (num2 >= height));
			if (flag)
			{
				list.Add(vertex);
			}
			if (flag != flag2)
			{
				list.Add(Vertex.Mix(vertex, vertex2, (height - num) / (num2 - num)));
			}
		}
		return list;
	}

	private static List<Vertex> Sector(List<Vertex> input, int blade, bool high)
	{
		Func<Vertex, float> func = delegate(Vertex v)
		{
			Point point = NativeSailShape.Local(new Point(v.P.x, v.P.y, v.P.z), blade);
			return (!high) ? (point.X + 0.36397022f * point.Y) : (point.Y - 0.36397022f * point.X);
		};
		List<Vertex> list = new List<Vertex>();
		for (int num = 0; num < input.Count; num++)
		{
			Vertex vertex = input[num];
			Vertex vertex2 = input[(num + 1) % input.Count];
			float num2 = func(vertex);
			float num3 = func(vertex2);
			bool flag = num2 >= 0f;
			bool flag2 = num3 >= 0f;
			if (flag)
			{
				list.Add(vertex);
			}
			if (flag != flag2)
			{
				list.Add(Vertex.Mix(vertex, vertex2, num2 / (num2 - num3)));
			}
		}
		return list;
	}

	internal static Mesh Create(MeshFilter source, Transform rotor, float radius, SailSettings settings)
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: 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)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: 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_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: 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_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_03df: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0456: Unknown result type (might be due to invalid IL or missing references)
		//IL_045b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0460: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f5: Expected O, but got Unknown
		Mesh sharedMesh = source.sharedMesh;
		if ((Object)(object)sharedMesh == (Object)null || !sharedMesh.isReadable)
		{
			throw new InvalidOperationException("Native sail mesh not readable. Original retained.");
		}
		Vector3[] vertices = sharedMesh.vertices;
		Vector3[] normals = sharedMesh.normals;
		Color[] colors = sharedMesh.colors;
		Matrix4x4 matrix = rotor.worldToLocalMatrix * ((Component)source).transform.localToWorldMatrix;
		Matrix4x4 inverse = ((Matrix4x4)(ref matrix)).inverse;
		Matrix4x4 transpose = ((Matrix4x4)(ref inverse)).transpose;
		List<Vector4>[] array = new List<Vector4>[8];
		for (int i = 0; i < 8; i++)
		{
			array[i] = new List<Vector4>();
			sharedMesh.GetUVs(i, array[i]);
		}
		Vertex[] array2 = new Vertex[vertices.Length];
		for (int j = 0; j < vertices.Length; j++)
		{
			Vector3 p = ((Matrix4x4)(ref matrix)).MultiplyPoint3x4(vertices[j]);
			int num = j;
			Vertex vertex = new Vertex
			{
				P = p
			};
			Vector3 n;
			if (normals.Length != vertices.Length)
			{
				n = Vector3.up;
			}
			else
			{
				Vector3 val = ((Matrix4x4)(ref transpose)).MultiplyVector(normals[j]);
				n = ((Vector3)(ref val)).normalized;
			}
			vertex.N = n;
			vertex.C = ((colors.Length == vertices.Length) ? colors[j] : Color.white);
			vertex.UV = (Vector4[])(object)new Vector4[8];
			array2[num] = vertex;
			for (int k = 0; k < 8; k++)
			{
				if (array[k].Count == vertices.Length)
				{
					ref Vector4 reference = ref array2[j].UV[k];
					reference = array[k][j];
				}
			}
		}
		List<Vector3> output = new List<Vector3>();
		List<Color> outputColors = new List<Color>();
		List<Vector4>[] outputUV = new List<Vector4>[8];
		for (int l = 0; l < 8; l++)
		{
			outputUV[l] = new List<Vector4>();
		}
		List<int[]> list = new List<int[]>();
		for (int m = 0; m < sharedMesh.subMeshCount; m++)
		{
			List<int> indices = new List<int>();
			int[] triangles = sharedMesh.GetTriangles(m);
			Action<List<Vertex>, int> action = delegate(List<Vertex> polygon, int blade)
			{
				//IL_008c: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_00af: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c5: 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_0137: Unknown result type (might be due to invalid IL or missing references)
				//IL_0148: Unknown result type (might be due to invalid IL or missing references)
				//IL_014d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0163: Unknown result type (might be due to invalid IL or missing references)
				//IL_0174: Unknown result type (might be due to invalid IL or missing references)
				//IL_0179: Unknown result type (might be due to invalid IL or missing references)
				//IL_017e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0183: Unknown result type (might be due to invalid IL or missing references)
				if (polygon.Count >= 3)
				{
					int count = output.Count;
					foreach (Vertex item in polygon)
					{
						Point p2 = new Point(item.P.x, item.P.y, item.P.z);
						Point point2 = NativeSailShape.Position(p2, radius, settings, blade);
						List<Vector3> list6 = output;
						Matrix4x4 inverse3 = ((Matrix4x4)(ref matrix)).inverse;
						list6.Add(((Matrix4x4)(ref inverse3)).MultiplyPoint3x4(new Vector3(point2.X, point2.Y, point2.Z)));
						outputColors.Add(item.C);
						for (int num9 = 0; num9 < 8; num9++)
						{
							outputUV[num9].Add(item.UV[num9]);
						}
					}
					for (int num10 = 1; num10 < polygon.Count - 1; num10++)
					{
						Vector3 val5 = Vector3.Cross(output[count + num10] - output[count], output[count + num10 + 1] - output[count]);
						if (((Vector3)(ref val5)).sqrMagnitude > 1E-12f)
						{
							indices.AddRange(new int[3]
							{
								count,
								count + num10,
								count + num10 + 1
							});
						}
					}
				}
			};
			for (int num2 = 0; num2 < triangles.Length; num2 += 3)
			{
				for (int num3 = 0; num3 < 4; num3++)
				{
					List<Vertex> list2 = new List<Vertex>();
					list2.Add(array2[triangles[num2]]);
					list2.Add(array2[triangles[num2 + 1]]);
					list2.Add(array2[triangles[num2 + 2]]);
					List<Vertex> input = list2;
					input = Sector(input, num3, high: false);
					input = Sector(input, num3, high: true);
					List<float> list3 = new List<float>();
					list3.Add(NativeSailShape.Root(radius));
					list3.Add(NativeSailShape.InnerEnd(radius));
					list3.Add(NativeSailShape.MiddleEnd(radius));
					List<float> list4 = list3;
					for (float num4 = NativeSailShape.Root(radius) + 0.2f; num4 < radius * 0.95f; num4 += 0.2f)
					{
						list4.Add(num4);
					}
					list4.Sort();
					foreach (float item2 in list4)
					{
						float height = item2;
						action(Clip(input, num3, height, below: true), num3);
						input = Clip(input, num3, height, below: false);
						if (input.Count < 3)
						{
							break;
						}
					}
					action(input, num3);
				}
			}
			list.Add(indices.ToArray());
		}
		float num5 = 0f;
		foreach (Vector3 item3 in output)
		{
			Vector3 val2 = ((Matrix4x4)(ref matrix)).MultiplyPoint3x4(item3);
			num5 = Math.Max(num5, (float)Math.Sqrt(val2.x * val2.x + val2.y * val2.y));
		}
		for (int num6 = 0; num6 < output.Count; num6++)
		{
			Vector3 val3 = ((Matrix4x4)(ref matrix)).MultiplyPoint3x4(output[num6]);
			Point point = NativeSailShape.NormalizeRadius(new Point(val3.x, val3.y, val3.z), radius, num5, settings.Radius);
			List<Vector3> list5 = output;
			int index = num6;
			Matrix4x4 inverse2 = ((Matrix4x4)(ref matrix)).inverse;
			list5[index] = ((Matrix4x4)(ref inverse2)).MultiplyPoint3x4(new Vector3(point.X, point.Y, point.Z));
		}
		Mesh val4 = new Mesh();
		((Object)val4).name = "ThreeSegmentNativeSails";
		val4.indexFormat = (IndexFormat)1;
		val4.SetVertices(output);
		val4.SetColors(outputColors);
		for (int num7 = 0; num7 < 8; num7++)
		{
			if (array[num7].Count == vertices.Length)
			{
				val4.SetUVs(num7, outputUV[num7]);
			}
		}
		val4.subMeshCount = list.Count;
		for (int num8 = 0; num8 < list.Count; num8++)
		{
			val4.SetTriangles(list[num8], num8);
		}
		val4.RecalculateNormals();
		val4.RecalculateTangents();
		val4.RecalculateBounds();
		return val4;
	}
}
public sealed class SailSettings
{
	public float Radius = 1.25f;

	public float InnerLength = 1f;

	public float MiddleLength = 1f;

	public float TipLength = 0.85f;

	public float InnerWidth = 1.15f;

	public float MiddleWidth = 1.4f;

	public float TipWidth = 0.65f;

	public float MiddleAngle = -8f;

	public float TipAngle = 30f;
}
public static class NativeSailShape
{
	public static Point Local(Point p, int blade)
	{
		return (blade & 3) switch
		{
			1 => new Point(0f - p.Y, p.X, p.Z), 
			2 => new Point(0f - p.X, 0f - p.Y, p.Z), 
			3 => new Point(p.Y, 0f - p.X, p.Z), 
			_ => p, 
		};
	}

	public static Point World(Point p, int blade)
	{
		return Local(p, (4 - blade) & 3);
	}

	public static float Root(float radius)
	{
		return radius * 0.2f;
	}

	public static float InnerEnd(float radius)
	{
		return radius * 0.85f * 0.46f;
	}

	public static float MiddleEnd(float radius)
	{
		return radius * 0.85f * 0.76f;
	}

	public static int Blade(Point p)
	{
		if (Math.Abs(p.Y) >= Math.Abs(p.X))
		{
			if (!(p.Y >= 0f))
			{
				return 2;
			}
			return 0;
		}
		if (!(p.X >= 0f))
		{
			return 3;
		}
		return 1;
	}

	private static Point Candidate(Point p, float radius, SailSettings s, int blade)
	{
		Point point = Local(p, blade);
		float num = Root(radius);
		float num2 = InnerEnd(radius);
		float num3 = MiddleEnd(radius);
		float num4 = radius * 0.85f;
		if (point.Y <= num)
		{
			return p;
		}
		float num5 = 0f;
		float num6 = s.MiddleAngle * (float)Math.PI / 180f;
		float num7 = s.TipAngle * (float)Math.PI / 180f;
		float num8 = (num2 - num) * s.InnerLength * s.Radius;
		float num9 = (num3 - num2) * s.MiddleLength * s.Radius;
		float y;
		float num11;
		if (point.Y <= num2)
		{
			float num10 = (point.Y - num) / (num2 - num);
			y = num + num8 * num10;
			num11 = 1f + (s.Radius * s.InnerWidth - 1f) * num10;
		}
		else if (point.Y <= num3)
		{
			float num12 = (point.Y - num2) / (num3 - num2);
			num5 = (float)Math.Sin(num6) * num9 * num12;
			y = num + num8 + (float)Math.Cos(num6) * num9 * num12;
			num11 = s.Radius * (s.InnerWidth + (s.MiddleWidth - s.InnerWidth) * num12);
		}
		else
		{
			float val = (point.Y - num3) / (num4 - num3);
			float num13 = (point.Y - num3) * s.TipLength * s.Radius;
			num5 = (float)Math.Sin(num6) * num9 + (float)Math.Sin(num7) * num13;
			y = num + num8 + (float)Math.Cos(num6) * num9 + (float)Math.Cos(num7) * num13;
			num11 = s.Radius * (s.MiddleWidth + (s.TipWidth - s.MiddleWidth) * Math.Min(1f, val));
		}
		return World(new Point(num5 + point.X * num11, y, point.Z), blade);
	}

	public static Point Position(Point p, float radius, SailSettings s, int unused = 0)
	{
		float num = (float)(Math.Atan2(p.X, p.Y) * 180.0 / Math.PI) + 20f;
		int num2 = (int)Math.Floor(num / 90f);
		int blade = (num2 % 4 + 4) % 4;
		float num3 = (float)Math.Sqrt(p.X * p.X + p.Y * p.Y);
		float num4 = Math.Max(0f, Math.Min(1f, (num3 - radius * 0.445f) / (radius * 0.12f)));
		num4 = num4 * num4 * (3f - 2f * num4);
		Point point = Candidate(p, radius, s, blade);
		return p + (point - p) * num4;
	}

	public static Point NormalizeRadius(Point p, float nativeRadius, float rawMaximum, float targetMultiplier)
	{
		float num = nativeRadius * 0.445f;
		float num2 = (float)Math.Sqrt(p.X * p.X + p.Y * p.Y);
		if (num2 <= num || rawMaximum <= num)
		{
			return p;
		}
		float num3 = num + (num2 - num) * (nativeRadius * targetMultiplier - num) / (rawMaximum - num);
		return new Point(p.X * num3 / num2, p.Y * num3 / num2, p.Z);
	}

	public static Point Normal(Point p, Point normal, float radius, SailSettings s, int blade)
	{
		Point point = (Position(p + new Point(0.0001f, 0f, 0f), radius, s, blade) - Position(p - new Point(0.0001f, 0f, 0f), radius, s, blade)) * 5000f;
		Point point2 = (Position(p + new Point(0f, 0.0001f, 0f), radius, s, blade) - Position(p - new Point(0f, 0.0001f, 0f), radius, s, blade)) * 5000f;
		float num = point.X * point2.Y - point2.X * point.Y;
		if (num < 1E-05f)
		{
			return normal;
		}
		return new Point((point2.Y * normal.X - point.Y * normal.Y) / num, ((0f - point2.X) * normal.X + point.X * normal.Y) / num, normal.Z).Normal;
	}
}
internal static class NativeTowerMesh
{
	private struct Vertex
	{
		internal Vector3 P;

		internal Vector3 N;

		internal Vector2 UV;

		internal Vector2 UV2;

		internal Color C;

		internal static Vertex Mix(Vertex a, Vertex b, float t)
		{
			//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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0057: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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)
			Vertex result = new Vertex
			{
				P = Vector3.Lerp(a.P, b.P, t)
			};
			Vector3 val = Vector3.Lerp(a.N, b.N, t);
			result.N = ((Vector3)(ref val)).normalized;
			result.UV = Vector2.Lerp(a.UV, b.UV, t);
			result.UV2 = Vector2.Lerp(a.UV2, b.UV2, t);
			result.C = Color.Lerp(a.C, b.C, t);
			return result;
		}
	}

	internal const float Rail = 3.76f;

	private static List<Vertex> Clip(List<Vertex> input, float y, bool below)
	{
		List<Vertex> list = new List<Vertex>();
		for (int i = 0; i < input.Count; i++)
		{
			Vertex vertex = input[i];
			Vertex b = input[(i + 1) % input.Count];
			bool flag = (below ? (vertex.P.y <= y) : (vertex.P.y >= y));
			bool flag2 = (below ? (b.P.y <= y) : (b.P.y >= y));
			if (flag)
			{
				list.Add(vertex);
			}
			if (flag != flag2)
			{
				list.Add(Vertex.Mix(vertex, b, (y - vertex.P.y) / (b.P.y - vertex.P.y)));
			}
		}
		return list;
	}

	internal static Mesh Create(MeshFilter source, Transform root, float lift)
	{
		//IL_0050: 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_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0282: Unknown result type (might be due to invalid IL or missing references)
		//IL_0287: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0327: Unknown result type (might be due to invalid IL or missing references)
		//IL_0318: Unknown result type (might be due to invalid IL or missing references)
		//IL_032c: Unknown result type (might be due to invalid IL or missing references)
		//IL_037a: Unknown result type (might be due to invalid IL or missing references)
		//IL_037f: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b61: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b68: Expected O, but got Unknown
		//IL_04bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0518: Unknown result type (might be due to invalid IL or missing references)
		//IL_0509: Unknown result type (might be due to invalid IL or missing references)
		//IL_051d: Unknown result type (might be due to invalid IL or missing references)
		//IL_053d: Unknown result type (might be due to invalid IL or missing references)
		//IL_052d: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_06dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_06fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0701: Unknown result type (might be due to invalid IL or missing references)
		//IL_0706: Unknown result type (might be due to invalid IL or missing references)
		//IL_070b: Unknown result type (might be due to invalid IL or missing references)
		//IL_070f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0714: Unknown result type (might be due to invalid IL or missing references)
		//IL_0724: Unknown result type (might be due to invalid IL or missing references)
		//IL_0729: Unknown result type (might be due to invalid IL or missing references)
		//IL_0542: Unknown result type (might be due to invalid IL or missing references)
		//IL_0752: Unknown result type (might be due to invalid IL or missing references)
		//IL_0759: Unknown result type (might be due to invalid IL or missing references)
		//IL_075e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0763: Unknown result type (might be due to invalid IL or missing references)
		//IL_0768: Unknown result type (might be due to invalid IL or missing references)
		//IL_076d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0562: Unknown result type (might be due to invalid IL or missing references)
		//IL_0552: Unknown result type (might be due to invalid IL or missing references)
		//IL_079a: Unknown result type (might be due to invalid IL or missing references)
		//IL_079f: Unknown result type (might be due to invalid IL or missing references)
		//IL_07a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_07a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_07b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_07b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_07b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_07b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_07c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_07de: Unknown result type (might be due to invalid IL or missing references)
		//IL_07e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_07fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0801: Unknown result type (might be due to invalid IL or missing references)
		//IL_0806: Unknown result type (might be due to invalid IL or missing references)
		//IL_080f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0814: Unknown result type (might be due to invalid IL or missing references)
		//IL_0819: Unknown result type (might be due to invalid IL or missing references)
		//IL_081b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0824: Unknown result type (might be due to invalid IL or missing references)
		//IL_0829: Unknown result type (might be due to invalid IL or missing references)
		//IL_082b: Unknown result type (might be due to invalid IL or missing references)
		//IL_082d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0836: Unknown result type (might be due to invalid IL or missing references)
		//IL_0838: Unknown result type (might be due to invalid IL or missing references)
		//IL_0841: Unknown result type (might be due to invalid IL or missing references)
		//IL_0843: Unknown result type (might be due to invalid IL or missing references)
		//IL_0567: Unknown result type (might be due to invalid IL or missing references)
		//IL_086a: Unknown result type (might be due to invalid IL or missing references)
		//IL_086c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0876: Unknown result type (might be due to invalid IL or missing references)
		//IL_0878: Unknown result type (might be due to invalid IL or missing references)
		//IL_0888: Unknown result type (might be due to invalid IL or missing references)
		//IL_088a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0894: Unknown result type (might be due to invalid IL or missing references)
		//IL_0896: Unknown result type (might be due to invalid IL or missing references)
		//IL_08ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_08bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_08c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_08c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_08d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_08e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_08e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_08ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_08f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_08f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_09a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_09a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_09ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_09b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_09b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_09bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_09c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_09cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_09d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_09d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_09dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_09e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_09ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_09f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_09f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_09fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a03: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a0d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a12: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a17: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a22: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a27: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a31: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a36: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a3b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a40: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a4b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a50: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a5a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a5f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a64: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a69: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a74: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a79: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a86: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a8b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a90: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a95: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aa0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aa5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ab2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ab7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0abc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ac1: Unknown result type (might be due to invalid IL or missing references)
		Mesh sharedMesh = source.sharedMesh;
		if ((Object)(object)sharedMesh == (Object)null || !sharedMesh.isReadable)
		{
			throw new InvalidOperationException("Native windmill mesh is not readable. Original retained.");
		}
		Vector3[] vertices = sharedMesh.vertices;
		Vector3[] normals = sharedMesh.normals;
		Vector2[] uv = sharedMesh.uv;
		Vector2[] uv2 = sharedMesh.uv2;
		Color[] colors = sharedMesh.colors;
		Matrix4x4 val = root.worldToLocalMatrix * ((Component)source).transform.localToWorldMatrix;
		Matrix4x4 inverse = ((Matrix4x4)(ref val)).inverse;
		Matrix4x4 transpose = ((Matrix4x4)(ref inverse)).transpose;
		Vector3 val3;
		if (lift <= 1E-05f)
		{
			Mesh val2 = Object.Instantiate<Mesh>(sharedMesh);
			((Object)val2).name = "OriginalTowerAtVanillaHeight";
			Vector3[] vertices2 = val2.vertices;
			Vector3[] normals2 = val2.normals;
			for (int i = 0; i < vertices2.Length; i++)
			{
				ref Vector3 reference = ref vertices2[i];
				reference = ((Matrix4x4)(ref val)).MultiplyPoint3x4(vertices2[i]);
				if (normals2.Length == vertices2.Length)
				{
					ref Vector3 reference2 = ref normals2[i];
					val3 = ((Matrix4x4)(ref transpose)).MultiplyVector(normals2[i]);
					reference2 = ((Vector3)(ref val3)).normalized;
				}
			}
			val2.vertices = vertices2;
			if (normals2.Length == vertices2.Length)
			{
				val2.normals = normals2;
			}
			val2.RecalculateTangents();
			val2.RecalculateBounds();
			return val2;
		}
		int[] chart = new int[vertices.Length];
		for (int j = 0; j < chart.Length; j++)
		{
			chart[j] = j;
		}
		Func<int, int> find = null;
		find = (int k) => (chart[k] != k) ? (chart[k] = find(chart[k])) : k;
		for (int num = 0; num < sharedMesh.subMeshCount; num++)
		{
			int[] triangles = sharedMesh.GetTriangles(num);
			for (int num2 = 0; num2 < triangles.Length; num2 += 3)
			{
				chart[find(triangles[num2 + 1])] = find(triangles[num2]);
				chart[find(triangles[num2 + 2])] = find(triangles[num2]);
			}
		}
		float[] array = new float[vertices.Length];
		float[] array2 = new float[vertices.Length];
		Vector2[] minUV = (Vector2[])(object)new Vector2[vertices.Length];
		Vector2[] maxUV = (Vector2[])(object)new Vector2[vertices.Length];
		for (int num3 = 0; num3 < vertices.Length; num3++)
		{
			array[num3] = float.MaxValue;
			array2[num3] = float.MinValue;
			ref Vector2 reference3 = ref minUV[num3];
			reference3 = new Vector2(float.MaxValue, float.MaxValue);
			ref Vector2 reference4 = ref maxUV[num3];
			reference4 = new Vector2(float.MinValue, float.MinValue);
		}
		for (int num4 = 0; num4 < vertices.Length; num4++)
		{
			int num5 = find(num4);
			float y = ((Matrix4x4)(ref val)).MultiplyPoint3x4(vertices[num4]).y;
			array[num5] = Math.Min(array[num5], y);
			array2[num5] = Math.Max(array2[num5], y);
			Vector2 val4 = ((uv.Length == vertices.Length) ? uv[num4] : Vector2.zero);
			ref Vector2 reference5 = ref minUV[num5];
			reference5 = new Vector2(Math.Min(minUV[num5].x, val4.x), Math.Min(minUV[num5].y, val4.y));
			ref Vector2 reference6 = ref maxUV[num5];
			reference6 = new Vector2(Math.Max(maxUV[num5].x, val4.x), Math.Max(maxUV[num5].y, val4.y));
		}
		List<Vector3> positions = new List<Vector3>();
		List<Vector3> normals3 = new List<Vector3>();
		List<Vector2> tex = new List<Vector2>();
		List<Vector2> tex2 = new List<Vector2>();
		List<Color> col = new List<Color>();
		List<int[]> list = new List<int[]>();
		int num6 = 0;
		for (int num7 = 0; num7 < sharedMesh.subMeshCount; num7++)
		{
			List<int> triangles2 = new List<int>();
			int[] triangles3 = sharedMesh.GetTriangles(num7);
			Action<List<Vertex>, float> action = delegate(List<Vertex> polygon, float dy)
			{
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: 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_0063: 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_0091: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
				//IL_010e: Unknown result type (might be due to invalid IL or missing references)
				//IL_011f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0124: Unknown result type (might be due to invalid IL or missing references)
				//IL_0129: Unknown result type (might be due to invalid IL or missing references)
				//IL_012e: Unknown result type (might be due to invalid IL or missing references)
				if (polygon.Count >= 3)
				{
					int count = positions.Count;
					foreach (Vertex item6 in polygon)
					{
						positions.Add(item6.P + Vector3.up * dy);
						normals3.Add(item6.N);
						tex.Add(item6.UV);
						tex2.Add(item6.UV2);
						col.Add(item6.C);
					}
					for (int k = 1; k < polygon.Count - 1; k++)
					{
						Vector3 val11 = Vector3.Cross(positions[count + k] - positions[count], positions[count + k + 1] - positions[count]);
						if (((Vector3)(ref val11)).sqrMagnitude > 1E-12f)
						{
							triangles2.AddRange(new int[3]
							{
								count,
								count + k,
								count + k + 1
							});
						}
					}
				}
			};
			for (int num8 = 0; num8 < triangles3.Length; num8 += 3)
			{
				List<Vertex> list2 = new List<Vertex>();
				for (int num9 = 0; num9 < 3; num9++)
				{
					int num10 = triangles3[num8 + num9];
					Vertex item = new Vertex
					{
						P = ((Matrix4x4)(ref val)).MultiplyPoint3x4(vertices[num10])
					};
					Vector3 n;
					if (normals.Length != vertices.Length)
					{
						n = Vector3.up;
					}
					else
					{
						val3 = ((Matrix4x4)(ref transpose)).MultiplyVector(normals[num10]);
						n = ((Vector3)(ref val3)).normalized;
					}
					item.N = n;
					item.UV = ((uv.Length == vertices.Length) ? uv[num10] : Vector2.zero);
					item.UV2 = ((uv2.Length == vertices.Length) ? uv2[num10] : Vector2.zero);
					item.C = ((colors.Length == vertices.Length) ? colors[num10] : Color.white);
					list2.Add(item);
				}
				action(Clip(list2, 3.76f, below: true), 0f);
				if (list2.TrueForAll((Vertex v) => v.P.y <= 3.76f))
				{
					continue;
				}
				action(Clip(list2, 3.76f, below: false), lift);
				action(Clip(Clip(list2, 3.76f, below: false), 3.94f, below: true), 0f);
				List<Vertex> list3 = new List<Vertex>();
				for (int num11 = 0; num11 < 3; num11++)
				{
					Vertex a = list2[num11];
					Vertex b = list2[(num11 + 1) % 3];
					if ((a.P.y < 3.76f && b.P.y > 3.76f) || (a.P.y > 3.76f && b.P.y < 3.76f))
					{
						list3.Add(Vertex.Mix(a, b, (3.76f - a.P.y) / (b.P.y - a.P.y)));
					}
				}
				if (list3.Count != 2)
				{
					continue;
				}
				val3 = Vector3.Cross(list2[1].P - list2[0].P, list2[2].P - list2[0].P);
				Vector3 normalized = ((Vector3)(ref val3)).normalized;
				Vector2 val5 = new Vector2(normalized.x, normalized.z);
				if (((Vector2)(ref val5)).sqrMagnitude < 0.01f)
				{
					continue;
				}
				Vertex vertex = list3[0];
				Vertex vertex2 = list3[1];
				if (Vector3.Dot(Vector3.Cross(vertex2.P - vertex.P, Vector3.up), normalized) < 0f)
				{
					Vertex vertex3 = vertex;
					vertex = vertex2;
					vertex2 = vertex3;
				}
				val3 = new Vector3(normalized.x, 0f, normalized.z);
				Vector3 normalized2 = ((Vector3)(ref val3)).normalized;
				val3 = (vertex.N = (vertex2.N = normalized2));
				Vector3 val6 = list2[1].P - list2[0].P;
				Vector3 val7 = list2[2].P - list2[0].P;
				Vector3 val8 = Vector3.up - normalized * normalized.y;
				val8 /= val8.y;
				float num12 = Vector3.Dot(val6, val6);
				float num13 = Vector3.Dot(val6, val7);
				float num14 = Vector3.Dot(val7, val7);
				float num15 = num12 * num14 - num13 * num13;
				if (!(Math.Abs(num15) < 1E-12f))
				{
					float num16 = (Vector3.Dot(val8, val6) * num14 - Vector3.Dot(val8, val7) * num13) / num15;
					float num17 = (Vector3.Dot(val8, val7) * num12 - Vector3.Dot(val8, val6) * num13) / num15;
					Vector2 val9 = (list2[1].UV - list2[0].UV) * num16 + (list2[2].UV - list2[0].UV) * num17;
					int component = find(triangles3[num8]);
					float num18 = Math.Max(array[component], 2.15f);
					float num19 = Math.Min(array2[component], 3.76f);
					if (num19 - num18 < 0.01f)
					{
						num18 = array[component];
					}
					float num20 = Math.Max(0.01f, num19 - num18);
					Func<Vector2, Vector2> func = (Vector2 t) => new Vector2(Math.Max(minUV[component].x, Math.Min(maxUV[component].x, t.x)), Math.Max(minUV[component].y, Math.Min(maxUV[component].y, t.y)));
					for (float num21 = 0f; num21 < lift - 1E-06f; num21 += num20)
					{
						float num22 = Math.Min(num20, lift - num21);
						Vertex item2 = vertex;
						Vertex item3 = vertex2;
						Vertex item4 = vertex;
						Vertex item5 = vertex2;
						item2.P += Vector3.up * num21;
						item3.P += Vector3.up * num21;
						item4.P += Vector3.up * (num21 + num22);
						item5.P += Vector3.up * (num21 + num22);
						item2.UV = func(vertex.UV + val9 * (num18 - 3.76f));
						item3.UV = func(vertex2.UV + val9 * (num18 - 3.76f));
						item4.UV = func(vertex.UV + val9 * (num18 + num22 - 3.76f));
						item5.UV = func(vertex2.UV + val9 * (num18 + num22 - 3.76f));
						action(new List<Vertex> { item2, item3, item5, item4 }, 0f);
					}
					num6++;
				}
			}
			list.Add(triangles2.ToArray());
		}
		if (num6 < 4)
		{
			throw new InvalidOperationException("Native tower cross-section not found. Original retained.");
		}
		Mesh val10 = new Mesh();
		((Object)val10).name = "OriginalTowerWithStraightInsertedSection";
		val10.indexFormat = (IndexFormat)1;
		val10.SetVertices(positions);
		val10.SetNormals(normals3);
		val10.SetUVs(0, tex);
		val10.SetUVs(1, tex2);
		val10.SetColors(col);
		val10.subMeshCount = list.Count;
		for (int num23 = 0; num23 < list.Count; num23++)
		{
			val10.SetTriangles(list[num23], num23);
		}
		val10.RecalculateTangents();
		val10.RecalculateBounds();
		return val10;
	}
}
public sealed class NordicVisual : MonoBehaviour
{
	private sealed class TransformState
	{
		internal Transform Target;

		internal Transform Parent;

		internal Vector3 Position;

		internal Vector3 Scale;

		internal Quaternion Rotation;

		internal TransformState(Transform target)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			Target = target;
			Parent = target.parent;
			Position = target.localPosition;
			Scale = target.localScale;
			Rotation = target.localRotation;
		}

		internal void Restore()
		{
			//IL_0028: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Target == (Object)null))
			{
				Target.SetParent(Parent, false);
				Target.localPosition = Position;
				Target.localRotation = Rotation;
				Target.localScale = Scale;
			}
		}
	}

	internal static readonly HashSet<NordicVisual> Live = new HashSet<NordicVisual>();

	private Windmill mill;

	private Transform boom;

	private Transform rotor;

	private MeshRenderer[] originals;

	private bool[] rendererStates;

	private LODGroup[] lods;

	private bool[] lodStates;

	private Collider[] rotatingColliders;

	private bool[] colliderStates;

	private float ground;

	private float nativeRadius;

	private float nativeHeight;

	private float baseRadius;

	private float nativePlane;

	private float rotorHeight;

	private float headLift;

	private GameObject visualRoot;

	private Transform head;

	private Transform sails;

	private Transform nativeBase;

	private Transform nativeStone;

	private Transform stoneProxy;

	private readonly List<Mesh> meshes = new List<Mesh>();

	private readonly List<Material> materials = new List<Material>();

	private readonly List<Texture2D> textures = new List<Texture2D>();

	private readonly List<TransformState> moved = new List<TransformState>();

	private bool initialized;

	internal void Initialize(Windmill source)
	{
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: Unknown result type (might be due to invalid IL or missing references)
		//IL_0266: Unknown result type (might be due to invalid IL or missing references)
		//IL_027f: Unknown result type (might be due to invalid IL or missing references)
		//IL_029a: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02be: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c3: 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_02cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			mill = source;
			boom = mill.m_bom;
			rotor = mill.m_propeller;
			if ((Object)(object)boom == (Object)null || (Object)(object)rotor == (Object)null)
			{
				throw new InvalidOperationException("Missing native windmill pivots.");
			}
			originals = ((Component)this).GetComponentsInChildren<MeshRenderer>(true);
			rendererStates = originals.Select((MeshRenderer r) => ((Renderer)r).enabled).ToArray();
			lods = ((Component)this).GetComponentsInChildren<LODGroup>(true);
			lodStates = lods.Select((LODGroup l) => l.enabled).ToArray();
			rotatingColliders = ((Component)boom).GetComponentsInChildren<Collider>(true);
			colliderStates = rotatingColliders.Select((Collider c) => c.enabled).ToArray();
			Transform val = ((Component)this).transform.Find("New/high") ?? ((Component)this).transform.Find("new/high");
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException("Unsupported windmill: healthy New/high mesh not found. Original retained.");
			}
			nativeBase = val;
			nativeStone = (((Object)(object)mill.m_grindstone == (Object)null) ? null : mill.m_grindstone.Find("high"));
			Bounds val2 = BoundsOf(((Component)val).GetComponentsInChildren<MeshFilter>(true), ((Component)this).transform);
			ground = ((Bounds)(ref val2)).min.y;
			rotorHeight = ((Component)this).transform.InverseTransformPoint(rotor.position).y;
			baseRadius = Mathf.Min(((Bounds)(ref val2)).size.x, ((Bounds)(ref val2)).size.z) * 0.46f;
			MeshFilter val3 = (((Object)(object)rotor.Find("high") == (Object)null) ? null : ((Component)rotor.Find("high")).GetComponent<MeshFilter>());
			if ((Object)(object)val3 == (Object)null || (Object)(object)val3.sharedMesh == (Object)null)
			{
				throw new InvalidOperationException("Native rotor high mesh not found.");
			}
			Bounds val4 = BoundsOf((IEnumerable<MeshFilter>)(object)new MeshFilter[1] { val3 }, rotor);
			nativePlane = ((Bounds)(ref val4)).center.z;
			nativeRadius = MeasureRadius(val3, rotor, ((Bounds)(ref val4)).center);
			Vector3 val5 = ((Component)this).transform.InverseTransformVector(rotor.TransformVector(Vector3.right));
			float magnitude = ((Vector3)(ref val5)).magnitude;
			Vector3 val6 = ((Component)this).transform.InverseTransformVector(rotor.TransformVector(Vector3.up));
			float num = Mathf.Max(magnitude, ((Vector3)(ref val6)).magnitude);
			nativeRadius *= num;
			nativeHeight = Mathf.Max(((Bounds)(ref val2)).max.y, rotorHeight + nativeRadius) - ground;
			if (nativeRadius < 0.5f || nativeHeight < 2f || baseRadius < 0.5f)
			{
				throw new InvalidOperationException("Invalid native dimensions.");
			}
			initialized = true;
			Live.Add(this);
			Rebuild();
		}
		catch (Exception error)
		{
			Restore();
			Plugin.Report(error);
			((Behaviour)this).enabled = false;
		}
	}

	private static Bounds BoundsOf(IEnumerable<MeshFilter> filters, Transform frame)
	{
		//IL_0002: 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_0113: 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_004e: 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_006e: 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_008e: 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_00b4: 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_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		Bounds result = default(Bounds);
		bool flag = false;
		Vector3 val = default(Vector3);
		foreach (MeshFilter filter in filters)
		{
			if ((Object)(object)filter.sharedMesh == (Object)null)
			{
				continue;
			}
			Bounds bounds = filter.sharedMesh.bounds;
			for (int i = 0; i < 8; i++)
			{
				((Vector3)(ref val))..ctor(((i & 1) == 0) ? ((Bounds)(ref bounds)).min.x : ((Bounds)(ref bounds)).max.x, ((i & 2) == 0) ? ((Bounds)(ref bounds)).min.y : ((Bounds)(ref bounds)).max.y, ((i & 4) == 0) ? ((Bounds)(ref bounds)).min.z : ((Bounds)(ref bounds)).max.z);
				val = frame.InverseTransformPoint(((Component)filter).transform.TransformPoint(val));
				if (!flag)
				{
					result = new Bounds(val, Vector3.zero);
					flag = true;
				}
				else
				{
					((Bounds)(ref result)).Encapsulate(val);
				}
			}
		}
		if (!flag)
		{
			throw new InvalidOperationException("No imported mesh bounds.");
		}
		return result;
	}

	private static float MeasureRadius(MeshFilter filter, Transform frame, Vector3 centre)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: 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_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//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_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		Mesh sharedMesh = filter.sharedMesh;
		if (!sharedMesh.isReadable)
		{
			Bounds val = BoundsOf((IEnumerable<MeshFilter>)(object)new MeshFilter[1] { filter }, frame);
			return Mathf.Max(((Bounds)(ref val)).extents.x, ((Bounds)(ref val)).extents.y);
		}
		float num = 0f;
		Vector3[] vertices = sharedMesh.vertices;
		foreach (Vector3 val2 in vertices)
		{
			Vector3 val3 = frame.InverseTransformPoint(((Component)filter).transform.TransformPoint(val2)) - centre;
			float num2 = num;
			Vector2 val4 = new Vector2(val3.x, val3.y);
			num = Mathf.Max(num2, ((Vector2)(ref val4)).magnitude);
		}
		return num;
	}

	internal void Rebuild()
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Expected O, but got Unknown
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0213: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_023f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0407: Unknown result type (might be due to invalid IL or missing references)
		//IL_040e: Expected O, but got Unknown
		//IL_044e: Unknown result type (might be due to invalid IL or missing references)
		//IL_045e: Unknown result type (might be due to invalid IL or missing references)
		//IL_047f: Unknown result type (might be due to invalid IL or missing references)
		if (!initialized)
		{
			return;
		}
		Restore();
		if (!Plugin.Enabled.Value)
		{
			return;
		}
		try
		{
			Layout layout = Layout.Create(ground, nativeHeight, nativeRadius, baseRadius, nativePlane, Plugin.Height.Value, Plugin.Blades.Value, 1f, rotorHeight);
			visualRoot = new GameObject("NordicWindmill_Visuals");
			visualRoot.transform.SetParent(((Component)this).transform, false);
			float num = (headLift = layout.TowerLift);
			Transform val = CloneNativeDisplay(nativeBase, visualRoot.transform, "OriginalExtendedTower");
			val.localPosition = Vector3.zero;
			val.localRotation = Quaternion.identity;
			val.localScale = Vector3.one;
			Mesh val2 = NativeTowerMesh.Create(((Component)nativeBase).GetComponent<MeshFilter>(), ((Component)this).transform, num);
			meshes.Add(val2);
			((Component)val).GetComponent<MeshFilter>().sharedMesh = val2;
			if ((Object)(object)nativeStone != (Object)null)
			{
				stoneProxy = CloneNativeDisplay(nativeStone, visualRoot.transform, "VisibleNativeMillstones");
			}
			head = new GameObject("NativeYawingHead").transform;
			head.SetParent(visualRoot.transform, false);
			head.position = boom.position + ((Component)this).transform.TransformVector(Vector3.up * num);
			head.rotation = boom.rotation;
			Transform val3 = boom.Find("high");
			if ((Object)(object)val3 == (Object)null)
			{
				throw new InvalidOperationException("Native head and wind vane mesh missing.");
			}
			CloneLocalDisplay(val3, head, "UnmodifiedNativeHeadAndVane");
			sails = new GameObject("NativeSpinningSails").transform;
			sails.SetParent(head, false);
			sails.localPosition = rotor.localPosition;
			sails.localRotation = rotor.localRotation;
			sails.localScale = rotor.localScale;
			Transform val4 = rotor.Find("high");
			Transform val5 = CloneLocalDisplay(val4, sails, "BlenderAuthoredSails");
			Mesh val6 = AuthoredRotorMesh.Create(((Component)val4).GetComponent<MeshFilter>(), rotor, nativeRadius, Plugin.Blades.Value, nativePlane);
			meshes.Add(val6);
			((Component)val5).GetComponent<MeshFilter>().sharedMesh = val6;
			LODGroup[] array = lods;
			foreach (LODGroup val7 in array)
			{
				if ((Object)(object)val7 != (Object)null)
				{
					val7.enabled = false;
				}
			}
			MeshRenderer[] array2 = originals;
			foreach (MeshRenderer val8 in array2)
			{
				if ((Object)(object)val8 != (Object)null)
				{
					((Renderer)val8).enabled = false;
				}
			}
			Collider[] array3 = rotatingColliders;
			foreach (Collider val9 in array3)
			{
				if ((Object)(object)val9 != (Object)null)
				{
					val9.enabled = false;
				}
			}
			if ((Object)(object)mill.m_propellerAOE != (Object)null)
			{
				MoveNative(mill.m_propellerAOE.transform, layout);
			}
			Transform val10 = boom.Find("bladecollider");
			if ((Object)(object)val10 != (Object)null)
			{
				MoveNative(val10, layout);
			}
			AudioSource[] sfxLoops = mill.m_sfxLoops;
			foreach (AudioSource val11 in sfxLoops)
			{
				if ((Object)(object)val11 != (Object)null && ((Component)val11).transform.IsChildOf(boom))
				{
					MoveNative(((Component)val11).transform, layout);
				}
			}
			if (Plugin.ExtensionCollision.Value)
			{
				GameObject val12 = new GameObject("UpperTowerCollision");
				val12.layer = CollisionLayer();
				val12.transform.SetParent(visualRoot.transform, false);
				float num2 = 3.76f;
				float num3 = Mathf.Max(0.1f, num);
				val12.transform.localPosition = Vector3.up * (num2 + num3 * 0.5f);
				BoxCollider val13 = val12.AddComponent<BoxCollider>();
				val13.size = new Vector3(1.95f, num3, 1.95f);
			}
			FollowNative();
			Plugin.LogDesign("Nordic Windmill 0.1.0: nativeHeight=" + nativeHeight + ", radius=" + nativeRadius + ", nativeBladePlane=" + nativePlane + ", newCentre=" + layout.Centre + ", newBladePlane=" + layout.RotorPlane);
		}
		catch (Exception error)
		{
			Restore();
			Plugin.Report(error);
		}
	}

	private int CollisionLayer()
	{
		Collider val = ((IEnumerable<Collider>)((Component)this).GetComponentsInChildren<Collider>(true)).FirstOrDefault((Func<Collider, bool>)((Collider x) => !((Component)x).transform.IsChildOf(boom)));
		if (!((Object)(object)val == (Object)null))
		{
			return ((Component)val).gameObject.layer;
		}
		return ((Component)this).gameObject.layer;
	}

	private void MoveNative(Transform target, Layout layout)
	{
		//IL_0020: 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_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_0040: Unknown result type (might be due to invalid IL or missing references)
		moved.Add(new TransformState(target));
		target.SetParent(head, true);
		target.position += ((Component)this).transform.TransformVector(Vector3.up * layout.TowerLift);
		Collider[] componentsInChildren = ((Component)target).GetComponentsInChildren<Collider>(true);
		foreach (Collider val in componentsInChildren)
		{
			int num = Array.IndexOf(rotatingColliders, val);
			if (num >= 0)
			{
				val.enabled = colliderStates[num];
			}
		}
	}

	internal void FollowNative()
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0065: 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_0091: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)head == (Object)null) && !((Object)(object)sails == (Object)null) && !((Object)(object)boom == (Object)null) && !((Object)(object)rotor == (Object)null))
		{
			head.position = boom.position + ((Component)this).transform.TransformVector(Vector3.up * headLift);
			head.rotation = boom.rotation;
			sails.localRotation = rotor.localRotation;
			if ((Object)(object)stoneProxy != (Object)null && (Object)(object)nativeStone != (Object)null)
			{
				CopyPose(nativeStone, stoneProxy);
			}
		}
	}

	private Transform CloneNativeDisplay(Transform source, Transform parent, string name)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Expected O, but got Unknown
		MeshFilter component = ((Component)source).GetComponent<MeshFilter>();
		MeshRenderer component2 = ((Component)source).GetComponent<MeshRenderer>();
		if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
		{
			return null;
		}
		GameObject val = new GameObject(name);
		val.transform.SetParent(parent, false);
		val.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
		MeshRenderer val2 = val.AddComponent<MeshRenderer>();
		((Renderer)val2).sharedMaterials = ((Renderer)component2).sharedMaterials;
		((Renderer)val2).shadowCastingMode = (ShadowCastingMode)1;
		CopyPose(source, val.transform);
		return val.transform;
	}

	private Transform CloneLocalDisplay(Transform source, Transform parent, string name)
	{
		//IL_0040: 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_0058: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)source == (Object)null)
		{
			throw new InvalidOperationException("Native display mesh missing: " + name);
		}
		Transform val = CloneNativeDisplay(source, parent, name);
		if ((Object)(object)val == (Object)null)
		{
			throw new InvalidOperationException("Native renderer missing: " + name);
		}
		val.localPosition = source.localPosition;
		val.localRotation = source.localRotation;
		val.localScale = source.localScale;
		return val;
	}

	private static void CopyPose(Transform source, Transform target)
	{
		//IL_0002: 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_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_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		target.position = source.position;
		target.rotation = source.rotation;
		Vector3 lossyScale = target.parent.lossyScale;
		Vector3 lossyScale2 = source.lossyScale;
		target.localScale = new Vector3(lossyScale2.x / lossyScale.x, lossyScale2.y / lossyScale.y, lossyScale2.z / lossyScale.z);
	}

	private Material[] CreateMaterials()
	{
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		Material val = originals.SelectMany((MeshRenderer r) => ((Renderer)r).sharedMaterials).FirstOrDefault((Func<Material, bool>)Usable);
		if ((Object)(object)val == (Object)null)
		{
			throw new InvalidOperationException("No safe Custom/Piece material; refusing snow/transparent shader fallback.");
		}
		Material source = FindMaterial(new string[3] { "wood_pole", "wood_wall_half", "wood_wall" }, val);
		Material element = Tint(source, new Color(0.9f, 0.82f, 0.7f), "Wood");
		return Enumerable.Repeat<Material>(element, Enum.GetNames(typeof(Finish)).Length).ToArray();
	}

	private static bool Usable(Material m)
	{
		if ((Object)(object)m != (Object)null && (Object)(object)m.shader != (Object)null)
		{
			return MaterialRules.Usable(((Object)m.shader).name, ((Object)m).name, m.HasProperty("_MainTex") && (Object)(object)m.GetTexture("_MainTex") != (Object)null);
		}
		return false;
	}

	private static Material FindMaterial(string[] names, Material fallback)
	{
		if ((Object)(object)ZNetScene.instance == (Object)null)
		{
			return fallback;
		}
		foreach (string text in names)
		{
			GameObject prefab = ZNetScene.instance.GetPrefab(text);
			if (!((Object)(object)prefab == (Object)null))
			{
				Material val = prefab.GetComponentsInChildren<MeshRenderer>(true).SelectMany((MeshRenderer r) => ((Renderer)r).sharedMaterials).FirstOrDefault((Func<Material, bool>)Usable);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
		}
		return fallback;
	}

	private Material Tint(Material source, Color tint, string name)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_002b: 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)
		Material val = new Material(source);
		((Object)val).name = "NordicWindmill_" + name;
		if (val.HasProperty("_Color"))
		{
			val.SetColor("_Color", tint);
		}
		if (val.HasProperty("_Glossiness"))
		{
			val.SetFloat("_Glossiness", 0.05f);
		}
		Texture2D val2 = OpaqueTexture.Create(name);
		textures.Add(val2);
		val.SetTexture("_MainTex", (Texture)(object)val2);
		if (val.HasProperty("_BumpMap"))
		{
			val.SetTexture("_BumpMap", (Texture)(object)Texture2D.normalTexture);
		}
		if (val.HasProperty("_Color"))
		{
			val.SetColor("_Color", Color.white);
		}
		if (val.HasProperty("_Cutoff"))
		{
			val.SetFloat("_Cutoff", 0f);
		}
		val.DisableKeyword("_ALPHATEST_ON");
		val