Decompiled source of CogaCurtains v0.2.1

plugins/CogaCurtains.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CogaCosmos.Procedural;
using CogaCurtains.Procedural;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace CogaCosmos.Procedural
{
	public struct V3
	{
		public float X;

		public float Y;

		public float Z;

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

		public V3 Normalized => this * (1f / Math.Max(1E-06f, Length));

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

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

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

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

		public static float Dot(V3 a, V3 b)
		{
			return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
		}

		public V3 RotZ(float deg)
		{
			float x = deg * ((float)Math.PI / 180f);
			float num = M.Cos(x);
			float num2 = M.Sin(x);
			return new V3(X * num - Y * num2, X * num2 + Y * num, Z);
		}

		public V3 RotY(float deg)
		{
			float x = deg * ((float)Math.PI / 180f);
			float num = M.Cos(x);
			float num2 = M.Sin(x);
			return new V3(X * num + Z * num2, Y, (0f - X) * num2 + Z * num);
		}
	}
	public struct Col
	{
		public float R;

		public float G;

		public float B;

		public float A;

		public float Luma => 0.2126f * R + 0.7152f * G + 0.0722f * B;

		public Col(float r, float g, float b, float a = 1f)
		{
			R = r;
			G = g;
			B = b;
			A = a;
		}

		public static Col Hex(string hex, float a = 1f)
		{
			hex = hex.TrimStart(new char[1] { '#' });
			int num = Convert.ToInt32(hex.Substring(0, 6), 16);
			return new Col((float)((num >> 16) & 0xFF) / 255f, (float)((num >> 8) & 0xFF) / 255f, (float)(num & 0xFF) / 255f, a);
		}

		public static Col operator +(Col a, Col b)
		{
			return new Col(a.R + b.R, a.G + b.G, a.B + b.B, a.A);
		}

		public static Col operator *(Col a, float s)
		{
			return new Col(a.R * s, a.G * s, a.B * s, a.A);
		}

		public static Col operator *(Col a, Col b)
		{
			return new Col(a.R * b.R, a.G * b.G, a.B * b.B, a.A * b.A);
		}

		public static Col Lerp(Col a, Col b, float t)
		{
			t = M.Clamp01(t);
			return new Col(a.R + (b.R - a.R) * t, a.G + (b.G - a.G) * t, a.B + (b.B - a.B) * t, a.A + (b.A - a.A) * t);
		}

		public static Col Ramp(float t, params Col[] stops)
		{
			t = M.Clamp01(t) * (float)(stops.Length - 1);
			int num = Math.Min(stops.Length - 2, (int)t);
			return Lerp(stops[num], stops[num + 1], t - (float)num);
		}

		public Col WithA(float a)
		{
			return new Col(R, G, B, a);
		}
	}
	public struct Rgba
	{
		public byte R;

		public byte G;

		public byte B;

		public byte A;

		public static Rgba From(Col c)
		{
			return new Rgba
			{
				R = (byte)(M.Clamp01(c.R) * 255f + 0.5f),
				G = (byte)(M.Clamp01(c.G) * 255f + 0.5f),
				B = (byte)(M.Clamp01(c.B) * 255f + 0.5f),
				A = (byte)(M.Clamp01(c.A) * 255f + 0.5f)
			};
		}
	}
	public sealed class Image
	{
		public readonly int W;

		public readonly int H;

		public readonly Col[] Px;

		public Col this[int x, int y]
		{
			get
			{
				return Px[y * W + x];
			}
			set
			{
				Px[y * W + x] = value;
			}
		}

		public Image(int w, int h)
		{
			W = w;
			H = h;
			Px = new Col[w * h];
		}

		public Col Sample(float u, float v)
		{
			float num = u * (float)W - 0.5f;
			float num2 = M.Clamp(v * (float)H - 0.5f, 0f, H - 1);
			int num3 = (int)Math.Floor(num);
			int num4 = (int)Math.Floor(num2);
			float t = num - (float)num3;
			float t2 = num2 - (float)num4;
			int num5 = num3 + 1;
			int y = Math.Min(H - 1, num4 + 1);
			num3 = (num3 % W + W) % W;
			num5 = (num5 % W + W) % W;
			Col a = Col.Lerp(this[num3, num4], this[num5, num4], t);
			Col b = Col.Lerp(this[num3, y], this[num5, y], t);
			return Col.Lerp(a, b, t2);
		}

		public Rgba[] ToRgba()
		{
			Rgba[] array = new Rgba[Px.Length];
			for (int i = 0; i < Px.Length; i++)
			{
				array[i] = Rgba.From(Px[i]);
			}
			return array;
		}
	}
	public static class M
	{
		public const float Pi = (float)Math.PI;

		public const float Deg2Rad = (float)Math.PI / 180f;

		public static float Sin(float x)
		{
			return (float)Math.Sin(x);
		}

		public static float Cos(float x)
		{
			return (float)Math.Cos(x);
		}

		public static float Sqrt(float x)
		{
			return (float)Math.Sqrt(Math.Max(0f, x));
		}

		public static float Pow(float x, float p)
		{
			return (float)Math.Pow(Math.Max(0f, x), p);
		}

		public static float Exp(float x)
		{
			return (float)Math.Exp(x);
		}

		public static float Atan2(float y, float x)
		{
			return (float)Math.Atan2(y, x);
		}

		public static float Asin(float x)
		{
			return (float)Math.Asin(Clamp(x, -1f, 1f));
		}

		public static float Acos(float x)
		{
			return (float)Math.Acos(Clamp(x, -1f, 1f));
		}

		public static float Clamp(float v, float lo, float hi)
		{
			if (!(v < lo))
			{
				if (!(v > hi))
				{
					return v;
				}
				return hi;
			}
			return lo;
		}

		public static float Clamp01(float v)
		{
			if (!(v < 0f))
			{
				if (!(v > 1f))
				{
					return v;
				}
				return 1f;
			}
			return 0f;
		}

		public static float Lerp(float a, float b, float t)
		{
			return a + (b - a) * Clamp01(t);
		}

		public static float Smooth(float e0, float e1, float x)
		{
			float num = Clamp01((x - e0) / (e1 - e0));
			return num * num * (3f - 2f * num);
		}
	}
	public static class Noise
	{
		private static readonly V3[] Grad = new V3[12]
		{
			new V3(1f, 1f, 0f),
			new V3(-1f, 1f, 0f),
			new V3(1f, -1f, 0f),
			new V3(-1f, -1f, 0f),
			new V3(1f, 0f, 1f),
			new V3(-1f, 0f, 1f),
			new V3(1f, 0f, -1f),
			new V3(-1f, 0f, -1f),
			new V3(0f, 1f, 1f),
			new V3(0f, -1f, 1f),
			new V3(0f, 1f, -1f),
			new V3(0f, -1f, -1f)
		};

		private static uint Hash(int x, int y, int z, int seed)
		{
			uint num = (uint)(seed * -1640531535);
			num ^= (uint)(x * -2048144789);
			num = (num << 13) | (num >> 19);
			num ^= (uint)(y * -1028477387);
			num = (num << 17) | (num >> 15);
			num ^= (uint)(z * 668265263);
			num ^= num >> 16;
			num *= 2146121005;
			num ^= num >> 15;
			num *= 2221713035u;
			return num ^ (num >> 16);
		}

		private static float Fade(float t)
		{
			return t * t * t * (t * (t * 6f - 15f) + 10f);
		}

		private static float Corner(int x, int y, int z, float dx, float dy, float dz, int seed)
		{
			V3 v = Grad[Hash(x, y, z, seed) % 12];
			return v.X * dx + v.Y * dy + v.Z * dz;
		}

		public static float Gradient(V3 p, int seed)
		{
			int num = (int)Math.Floor(p.X);
			int num2 = (int)Math.Floor(p.Y);
			int num3 = (int)Math.Floor(p.Z);
			float num4 = p.X - (float)num;
			float num5 = p.Y - (float)num2;
			float num6 = p.Z - (float)num3;
			float num7 = Fade(num4);
			float num8 = Fade(num5);
			float num9 = Fade(num6);
			float num10 = Corner(num, num2, num3, num4, num5, num6, seed);
			float num11 = Corner(num + 1, num2, num3, num4 - 1f, num5, num6, seed);
			float num12 = Corner(num, num2 + 1, num3, num4, num5 - 1f, num6, seed);
			float num13 = Corner(num + 1, num2 + 1, num3, num4 - 1f, num5 - 1f, num6, seed);
			float num14 = Corner(num, num2, num3 + 1, num4, num5, num6 - 1f, seed);
			float num15 = Corner(num + 1, num2, num3 + 1, num4 - 1f, num5, num6 - 1f, seed);
			float num16 = Corner(num, num2 + 1, num3 + 1, num4, num5 - 1f, num6 - 1f, seed);
			float num17 = Corner(num + 1, num2 + 1, num3 + 1, num4 - 1f, num5 - 1f, num6 - 1f, seed);
			float num18 = num10 + (num11 - num10) * num7;
			float num19 = num12 + (num13 - num12) * num7;
			float num20 = num14 + (num15 - num14) * num7;
			float num21 = num16 + (num17 - num16) * num7;
			float num22 = num18 + (num19 - num18) * num8;
			float num23 = num20 + (num21 - num20) * num8;
			return num22 + (num23 - num22) * num9;
		}

		public static float Fbm(V3 p, int seed, int octaves, float lacunarity = 2f, float gain = 0.5f)
		{
			float num = 0f;
			float num2 = 1f;
			float num3 = 0f;
			for (int i = 0; i < octaves; i++)
			{
				num += Gradient(p, seed + i * 101) * num2;
				num3 += num2;
				num2 *= gain;
				p *= lacunarity;
			}
			return M.Clamp01(0.5f + 0.5f * (num / num3) * 1.6f);
		}

		public static float Ridged(V3 p, int seed, int octaves)
		{
			float num = 0f;
			float num2 = 1f;
			float num3 = 0f;
			for (int i = 0; i < octaves; i++)
			{
				float num4 = 1f - Math.Abs(Gradient(p, seed + i * 131));
				num += num4 * num4 * num2;
				num3 += num2;
				num2 *= 0.5f;
				p *= 2.1f;
			}
			return num / num3;
		}
	}
}
namespace CogaCurtains
{
	internal sealed class Fabric
	{
		public string Id;

		public string Name;

		public string Description;

		public Color Color;

		public float Gloss = 0.6f;

		public bool Sheer;

		public bool Embroidered;

		public bool RibbonBow;

		public bool Dyed;

		public int Lace;

		public string Sash = "gold";

		public Fabric Under;

		public float FoldsPerMeter = 4.2f;

		public float Depth = 0.075f;

		public int Seed = 1;

		public Material Material;

		public Sprite Icon;
	}
	internal static class CurtainAssets
	{
		public static Material IronMat;

		public static Material BrassMat;

		public static Material GoldSashMat;

		public static Material BlackSashMat;

		public static Material RibbonMat;

		public static Mesh Rod;

		public static Mesh Finial;

		public static Mesh Band;

		public static Mesh Loop;

		public static Mesh Tail;

		public static readonly Fabric WhiteSheer = new Fabric
		{
			Id = "white_sheer",
			Name = "White Sheer Drapes",
			Description = "Light, airy sheer that glows when the sun is behind it.",
			Color = new Color(0.97f, 0.96f, 0.93f, 0.42f),
			Gloss = 0.45f,
			Sheer = true,
			RibbonBow = true,
			Sash = "ribbon",
			FoldsPerMeter = 5f,
			Depth = 0.06f,
			Seed = 21
		};

		public static readonly Fabric[] Fabrics = new Fabric[12]
		{
			new Fabric
			{
				Id = "black_satin",
				Name = "Black Satin Drapes",
				Description = "Heavy black satin with a cool sheen. Gold tie-backs.",
				Color = new Color(0.03f, 0.03f, 0.035f),
				Gloss = 0.82f,
				Sash = "gold",
				Seed = 11
			},
			new Fabric
			{
				Id = "white_satin",
				Name = "White Satin Drapes",
				Description = "Soft white satin. Black tie-backs.",
				Color = new Color(0.86f, 0.84f, 0.8f),
				Gloss = 0.62f,
				Sash = "black",
				Seed = 41
			},
			WhiteSheer,
			new Fabric
			{
				Id = "black_over_sheer",
				Name = "Black Satin over White Sheer",
				Description = "Black satin that ties back to reveal white sheer behind it.",
				Color = new Color(0.03f, 0.03f, 0.035f),
				Gloss = 0.82f,
				Sash = "gold",
				Seed = 31,
				Under = WhiteSheer
			},
			new Fabric
			{
				Id = "voile",
				Name = "Embroidered Voile",
				Description = "White sheer voile with leafy embroidery along the hem, tied with linen ribbon bows.",
				Color = new Color(1f, 1f, 1f, 1f),
				Gloss = 0.4f,
				Sheer = true,
				Embroidered = true,
				RibbonBow = true,
				Sash = "ribbon",
				FoldsPerMeter = 5f,
				Depth = 0.065f,
				Seed = 61
			},
			new Fabric
			{
				Id = "red_satin",
				Name = "Red Satin Drapes",
				Description = "Rich red satin with a warm sheen. Gold tie-backs.",
				Color = new Color(0.62f, 0.07f, 0.08f),
				Gloss = 0.7f,
				Dyed = true,
				Sash = "gold",
				Seed = 71
			},
			new Fabric
			{
				Id = "burgundy_velvet",
				Name = "Burgundy Velvet Drapes",
				Description = "Deep burgundy velvet, heavy and soft. Gold tie-backs.",
				Color = new Color(0.33f, 0.045f, 0.085f),
				Gloss = 0.3f,
				Dyed = true,
				Sash = "gold",
				FoldsPerMeter = 3.8f,
				Depth = 0.085f,
				Seed = 81
			},
			new Fabric
			{
				Id = "blue_satin",
				Name = "Royal Blue Satin Drapes",
				Description = "Royal blue satin with a cool sheen. Gold tie-backs.",
				Color = new Color(0.1f, 0.19f, 0.55f),
				Gloss = 0.7f,
				Dyed = true,
				Sash = "gold",
				Seed = 91
			},
			new Fabric
			{
				Id = "green_satin",
				Name = "Forest Green Satin Drapes",
				Description = "Forest green satin. Gold tie-backs.",
				Color = new Color(0.08f, 0.31f, 0.15f),
				Gloss = 0.7f,
				Dyed = true,
				Sash = "gold",
				Seed = 101
			},
			new Fabric
			{
				Id = "black_lace",
				Name = "Black Lace Drapes",
				Description = "Black lace: rosettes on a fine net with a scalloped hem. Light shows through the pattern. Black tie-backs.",
				Color = new Color(0.07f, 0.065f, 0.08f, 1f),
				Gloss = 0.3f,
				Sheer = true,
				Lace = 1,
				Sash = "black",
				FoldsPerMeter = 4.6f,
				Depth = 0.06f,
				Seed = 111
			},
			new Fabric
			{
				Id = "black_lace_floral",
				Name = "Black Floral Lace Drapes",
				Description = "Dense black floral lace: roses, leaves and curling scrolls on a honeycomb net, with a scalloped hem. Black tie-backs.",
				Color = new Color(0.07f, 0.065f, 0.08f, 1f),
				Gloss = 0.3f,
				Sheer = true,
				Lace = 2,
				Sash = "black",
				FoldsPerMeter = 4.6f,
				Depth = 0.06f,
				Seed = 121
			},
			new Fabric
			{
				Id = "black_lace_web",
				Name = "Spider Web Lace Drapes",
				Description = "Black lace of orb webs with little spiders, some hanging on a thread, and a scalloped hem of web fans. Black tie-backs.",
				Color = new Color(0.07f, 0.065f, 0.08f, 1f),
				Gloss = 0.3f,
				Sheer = true,
				Lace = 3,
				Sash = "black",
				FoldsPerMeter = 4.6f,
				Depth = 0.06f,
				Seed = 131
			}
		};

		private static Material _opaqueTpl;

		private static Material _alphaTpl;

		private static Color[] _sail;

		private static Color[] _weave;

		private static int _sailW;

		private static int _sailH;

		private static int _weaveW;

		private static int _weaveH;

		private static float _sailMean;

		private static float _weaveMean;

		public const float TextureDropMeters = 40f;

		public const float FabricTileMeters = 4f;

		private const float EmbroideryRefDrop = 2.2f;

		public static bool Ready { get; private set; }

		public static bool Headless => (int)SystemInfo.graphicsDeviceType == 4;

		public static bool TwoSided { get; private set; }

		public static void Build(ManualLogSource log)
		{
			//IL_041c: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_048a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0499: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0507: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Expected O, but got Unknown
			//IL_0225: 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)
			if (Ready)
			{
				return;
			}
			Material[] source = (from m in Resources.FindObjectsOfTypeAll<Material>()
				where Object.op_Implicit((Object)(object)m) && !((Object)m).name.StartsWith("coga_", StringComparison.Ordinal)
				select m).ToArray();
			_opaqueTpl = (from m in source
				where Object.op_Implicit((Object)(object)m.shader) && ((Object)m.shader).name == "Standard" && m.IsKeywordEnabled("_EMISSION") && OnlyKeywords(m, "_EMISSION", "_NORMALMAP")
				orderby m.shaderKeywords.Length, ((Object)m).name
				select m).FirstOrDefault();
			_alphaTpl = (from m in source
				where Object.op_Implicit((Object)(object)m.shader) && ((Object)m.shader).name == "Standard" && m.IsKeywordEnabled("_ALPHABLEND_ON") && OnlyKeywords(m, "_EMISSION", "_NORMALMAP", "_ALPHABLEND_ON")
				orderby m.shaderKeywords.Length, ((Object)m).name
				select m).FirstOrDefault();
			Material val = ((IEnumerable<Material>)source).FirstOrDefault((Func<Material, bool>)((Material m) => ((Object)m).name == "jutered_mat" && Object.op_Implicit((Object)(object)m.shader) && ((Object)m.shader).name == "Standard TwoSided"));
			Material val2 = ((IEnumerable<Material>)source).FirstOrDefault((Func<Material, bool>)((Material m) => ((Object)m).name == "Banner_Dvergr_mat" && Object.op_Implicit((Object)(object)m.shader) && ((Object)m.shader).name == "Standard TwoSided"));
			TwoSided = Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2);
			foreach (Fabric item in Fabrics.Concat(new Fabric[1] { WhiteSheer }).Distinct())
			{
				if (!Object.op_Implicit((Object)(object)item.Material))
				{
					Texture2D t = PixelTexture(item);
					Material val3 = ((!item.Sheer) ? (Object.op_Implicit((Object)(object)val) ? val : _opaqueTpl) : (Object.op_Implicit((Object)(object)_alphaTpl) ? _alphaTpl : val2));
					item.Material = new Material(val3)
					{
						name = "coga_curtain_" + item.Id
					};
					item.Material.color = Color.white;
					SetTex(item.Material, "_MainTex", (Texture)(object)t);
					if (item.Material.HasProperty("_Glossiness"))
					{
						item.Material.SetFloat("_Glossiness", (item.Lace > 0) ? 0.2f : (item.Sheer ? 0.1f : (item.Id.Contains("satin") ? 0.35f : 0.15f)));
					}
					if (item.Material.HasProperty("_Metallic"))
					{
						item.Material.SetFloat("_Metallic", 0f);
					}
					if (item.Material.HasProperty("_Cutoff"))
					{
						item.Material.SetFloat("_Cutoff", 0.5f);
					}
					if (item.Material.HasProperty("_BumpMap") && Object.op_Implicit((Object)(object)item.Material.GetTexture("_BumpMap")))
					{
						item.Material.SetTextureScale("_BumpMap", new Vector2(2f, 3f));
					}
					Image image = (Headless ? null : ((item.Lace > 0) ? DrapeConcepts.LaceIcon(item.Lace, 128) : (item.Dyed ? DrapeConcepts.DyedIcon(new Col(item.Color.r, item.Color.g, item.Color.b), (item.Gloss > 0.5f) ? 55f : 12f, 128) : DrapeConcepts.Icon(item.Id, 128))));
					item.Icon = ((image == null) ? null : ToSprite(image, "coga_curtain_icon_" + item.Id));
				}
			}
			IronMat = Make(_opaqueTpl, "coga_curtain_iron", new Color(0.13f, 0.12f, 0.11f), 0.5f, 0.75f, Color.black);
			BrassMat = Make(_opaqueTpl, "coga_curtain_brass", new Color(0.78f, 0.6f, 0.33f), 0.65f, 0.9f, Color.black);
			GoldSashMat = Make(_opaqueTpl, "coga_curtain_gold", new Color(0.83f, 0.66f, 0.32f), 0.7f, 0.85f, Color.black);
			BlackSashMat = Make(_opaqueTpl, "coga_curtain_blacksash", new Color(0.03f, 0.03f, 0.035f), 0.8f, 0f, Color.black);
			RibbonMat = Make(_opaqueTpl, "coga_curtain_ribbon", new Color(0.84f, 0.76f, 0.62f), 0.25f, 0f, Color.black);
			Rod = CurtainMeshes.CylinderX(0.016f, 16);
			Finial = CurtainMeshes.Sphere(16, 10);
			Band = CurtainMeshes.Torus(1f, 0.08f, 32, 8);
			Loop = CurtainMeshes.Torus(1f, 0.18f, 24, 8);
			Tail = CurtainMeshes.Tail();
			Ready = true;
			log.LogInfo((object)string.Format("Curtain assets built: {0} fabrics; vanilla cloth templates {1}; opaque={2} alpha={3}", Fabrics.Length, TwoSided ? "jutered_mat + Banner_Dvergr_mat (two-sided)" : "NOT found, using Standard", Object.op_Implicit((Object)(object)_opaqueTpl) ? ((Object)_opaqueTpl).name : "<none>", Object.op_Implicit((Object)(object)_alphaTpl) ? ((Object)_alphaTpl).name : "<none>"));
		}

		public static Texture2D ReadableCopy(string textureName)
		{
			//IL_0064: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Expected O, but got Unknown
			Texture2D val = ((IEnumerable<Texture2D>)Resources.FindObjectsOfTypeAll<Texture2D>()).FirstOrDefault((Func<Texture2D, bool>)((Texture2D t) => Object.op_Implicit((Object)(object)t) && ((Object)t).name == textureName));
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)val).width, ((Texture)val).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
			RenderTexture active = RenderTexture.active;
			try
			{
				Graphics.Blit((Texture)(object)val, temporary);
				RenderTexture.active = temporary;
				Texture2D val2 = new Texture2D(((Texture)val).width, ((Texture)val).height, (TextureFormat)4, false)
				{
					name = textureName + "_readable"
				};
				val2.ReadPixels(new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), 0, 0);
				val2.Apply(false, false);
				return val2;
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
		}

		private static bool LoadVanillaFabric()
		{
			if (_sail != null)
			{
				return true;
			}
			Texture2D val = ReadableCopy("sail_white");
			Texture2D val2 = ReadableCopy("jutecarpet_d");
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2))
			{
				return false;
			}
			_sail = val.GetPixels();
			_sailW = ((Texture)val).width;
			_sailH = ((Texture)val).height;
			_weave = val2.GetPixels();
			_weaveW = ((Texture)val2).width;
			_weaveH = ((Texture)val2).height;
			_sailMean = _sail.Average((Color c) => ((Color)(ref c)).grayscale);
			_weaveMean = _weave.Average((Color c) => ((Color)(ref c)).grayscale);
			Object.Destroy((Object)(object)val);
			Object.Destroy((Object)(object)val2);
			return true;
		}

		private static float Lum(Color[] px, int w, int h, float u, float v, float crop = 0f)
		{
			float num = crop + (1f - 2f * crop) * (1f - Mathf.Abs(2f * Mathf.Repeat(u * 0.5f, 1f) - 1f));
			float num2 = crop + (1f - 2f * crop) * (1f - Mathf.Abs(2f * Mathf.Repeat(v * 0.5f, 1f) - 1f));
			int num3 = Mathf.Clamp((int)(num * (float)w), 0, w - 1);
			int num4 = Mathf.Clamp((int)(num2 * (float)h), 0, h - 1);
			return ((Color)(ref px[num4 * w + num3])).grayscale;
		}

		private static Color32[] VanillaFabric(Fabric f, int cols, int rows, int tpm)
		{
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0422: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_0464: Unknown result type (might be due to invalid IL or missing references)
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: 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_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c5: 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)
			string id = f.Id;
			Color32[] array = (Color32[])(object)new Color32[cols * rows];
			for (int i = 0; i < rows; i++)
			{
				float num = ((float)i + 0.5f) / (float)tpm;
				float num2 = 1f - num / 2.2f;
				for (int j = 0; j < cols; j++)
				{
					float num3 = ((float)j + 0.5f) / (float)tpm;
					float num4 = num3 / 4f;
					float num5 = num4 * 2f * (float)Math.PI;
					float num6 = (Noise.Fbm(new V3(Mathf.Cos(num5) * 1.2f, Mathf.Sin(num5) * 1.2f, num * 0.35f), 5, 2) - 0.5f) * 0.5f;
					float num7 = (Noise.Fbm(new V3(Mathf.Cos(num5) * 1.2f, Mathf.Sin(num5) * 1.2f, num * 0.35f + 9f), 6, 2) - 0.5f) * 0.9f;
					float num8 = (1f - Mathf.Abs(2f * num4 - 1f)) * 0.8f;
					float num9 = Lum(_sail, _sailW, _sailH, num8 + num6, num / 2.5f + num7, 0.18f) / _sailMean;
					float num10 = Mathf.Clamp(Lum(_weave, _weaveW, _weaveH, num3 * 2f, num * 2f) / _weaveMean, 0.88f, 1.12f);
					float num11 = Mathf.Lerp(num9, num9 * num10, 0.15f);
					float num12 = 1f;
					Color val;
					if (f.Lace > 0)
					{
						float cov = DrapeRender.Lace(f.Lace, j, i);
						val = f.Color * Mathf.Lerp(1f, num11, 1.3f);
						num12 = DrapeRender.LaceAlpha(cov);
						array[i * cols + j] = new Color32((byte)(Mathf.Clamp01(val.r) * 255f), (byte)(Mathf.Clamp01(val.g) * 255f), (byte)(Mathf.Clamp01(val.b) * 255f), (byte)(num12 * 255f));
						continue;
					}
					if (f.Dyed)
					{
						val = f.Color * Mathf.Lerp(1f, num11, 1.25f);
						array[i * cols + j] = new Color32((byte)(Mathf.Clamp01(val.r) * 255f), (byte)(Mathf.Clamp01(val.g) * 255f), (byte)(Mathf.Clamp01(val.b) * 255f), byte.MaxValue);
						continue;
					}
					switch (id)
					{
					case "black_satin":
					case "black_over_sheer":
						val = new Color(0.085f, 0.08f, 0.1f) * Mathf.Lerp(1f, num11, 1.4f);
						break;
					case "white_satin":
						val = new Color(0.86f, 0.83f, 0.77f) * Mathf.Lerp(1f, num11, 1.1f);
						break;
					default:
						val = new Color(0.95f, 0.93f, 0.89f) * Mathf.Lerp(1f, num11, 0.6f);
						num12 = Mathf.Clamp(0.5f * Mathf.Pow(num11, 2f), 0.28f, 0.72f);
						if (id == "voile")
						{
							float num13 = ((num2 > 0f) ? PixelEmbroidery(j, i, cols) : 0f);
							if (num13 > 0.35f)
							{
								val = new Color(1f, 1f, 0.98f) * ((num13 > 0.8f) ? 1f : 0.9f);
								num12 = 0.95f;
							}
							if (num < 0.033f + 0.026f * Mathf.Abs(Mathf.Sin(num3 * 1f * 31.4f)))
							{
								num12 = 0f;
							}
						}
						break;
					}
					array[i * cols + j] = new Color32((byte)(Mathf.Clamp01(val.r) * 255f), (byte)(Mathf.Clamp01(val.g) * 255f), (byte)(Mathf.Clamp01(val.b) * 255f), (byte)(num12 * 255f));
				}
			}
			return array;
		}

		private static float PixelEmbroidery(int x, int y, int cols)
		{
			float num = 0f;
			for (int i = 0; i < 4; i++)
			{
				for (int j = 0; j < 4; j++)
				{
					float num2 = ((float)x + ((float)j + 0.5f) / 4f) / 32f;
					float v = 1f - ((float)y + ((float)i + 0.5f) / 4f) / 32f / 2.2f;
					num = Mathf.Max(num, DrapeRender.Embroidery(num2 * 1f, v, 61));
				}
			}
			return num;
		}

		private static Texture2D PixelTexture(Fabric f)
		{
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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_0100: 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_0110: Expected O, but got Unknown
			string id = f.Id;
			int num = ((f.Lace > 0) ? 64 : 32);
			int num2 = (Headless ? 8 : ((int)(40f * (float)num)));
			int num3;
			Color32[] array;
			if (!Headless && LoadVanillaFabric())
			{
				num3 = (int)((float)num * 4f);
				array = VanillaFabric(f, num3, num2, num);
			}
			else
			{
				Image image = DrapeRender.FabricTexture(id, num2);
				num3 = image.W;
				Rgba[] array2 = image.ToRgba();
				array = (Color32[])(object)new Color32[array2.Length];
				for (int i = 0; i < array2.Length; i++)
				{
					array[i] = new Color32(array2[i].R, array2[i].G, array2[i].B, array2[i].A);
				}
			}
			Texture2D val = new Texture2D(num3, num2, (TextureFormat)4, true)
			{
				name = "coga_curtain_px_" + id,
				filterMode = (FilterMode)0,
				wrapModeU = (TextureWrapMode)0,
				wrapModeV = (TextureWrapMode)1,
				anisoLevel = 0
			};
			val.SetPixels32(array);
			val.Apply(true, true);
			return val;
		}

		public static Material SashFor(Fabric f)
		{
			if (!(f.Sash == "black"))
			{
				if (!(f.Sash == "ribbon"))
				{
					return GoldSashMat;
				}
				return RibbonMat;
			}
			return BlackSashMat;
		}

		private static bool OnlyKeywords(Material m, params string[] allowed)
		{
			return m.shaderKeywords.All((string k) => allowed.Contains(k));
		}

		private static Material Make(Material tpl, string name, Color color, float gloss, float metallic, Color emission)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			Material val = (Object.op_Implicit((Object)(object)tpl) ? new Material(tpl) : new Material(Shader.Find("Standard")));
			((Object)val).name = name;
			string[] array = new string[8] { "_BumpMap", "_MetallicGlossMap", "_SpecGlossMap", "_OcclusionMap", "_ParallaxMap", "_DetailMask", "_DetailAlbedoMap", "_DetailNormalMap" };
			foreach (string text in array)
			{
				if (val.HasProperty(text))
				{
					val.SetTexture(text, (Texture)null);
				}
			}
			SetTex(val, "_MainTex", (Texture)(object)Texture2D.whiteTexture);
			SetTex(val, "_EmissionMap", (Texture)(object)Texture2D.whiteTexture);
			val.color = color;
			if (val.HasProperty("_EmissionColor"))
			{
				val.SetColor("_EmissionColor", emission);
			}
			val.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)0;
			if (val.HasProperty("_Metallic"))
			{
				val.SetFloat("_Metallic", metallic);
			}
			if (val.HasProperty("_Glossiness"))
			{
				val.SetFloat("_Glossiness", gloss);
			}
			if (val.HasProperty("_GlossMapScale"))
			{
				val.SetFloat("_GlossMapScale", gloss);
			}
			return val;
		}

		private static void SetTex(Material m, string prop, Texture t)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (m.HasProperty(prop))
			{
				m.SetTexture(prop, t);
				m.SetTextureScale(prop, Vector2.one);
				m.SetTextureOffset(prop, Vector2.zero);
			}
		}

		private static Sprite ToSprite(Image img, string name)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0068: 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_00a4: 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)
			Texture2D val = new Texture2D(img.W, img.H, (TextureFormat)4, false)
			{
				name = name,
				wrapMode = (TextureWrapMode)1
			};
			Rgba[] array = img.ToRgba();
			Color32[] array2 = (Color32[])(object)new Color32[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array2[i] = new Color32(array[i].R, array[i].G, array[i].B, array[i].A);
			}
			val.SetPixels32(array2);
			val.Apply(false, false);
			return Sprite.Create(val, new Rect(0f, 0f, (float)img.W, (float)img.H), new Vector2(0.5f, 0.5f), 100f);
		}
	}
	internal static class CurtainMeshes
	{
		public static Mesh CylinderX(float radius, int seg)
		{
			//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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: 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)
			List<Vector3> list = new List<Vector3>();
			List<Vector3> list2 = new List<Vector3>();
			List<int> t = new List<int>();
			Vector3 val = default(Vector3);
			for (int i = 0; i <= seg; i++)
			{
				float num = (float)i * (float)Math.PI * 2f / (float)seg;
				((Vector3)(ref val))..ctor(0f, Mathf.Cos(num), Mathf.Sin(num));
				list.Add(new Vector3(-0.5f, 0f, 0f) + val * radius);
				list.Add(new Vector3(0.5f, 0f, 0f) + val * radius);
				list2.Add(val);
				list2.Add(val);
			}
			for (int j = 0; j < seg; j++)
			{
				int num2 = j * 2;
				Facing(t, list, list2[num2], num2, num2 + 1, num2 + 3);
				Facing(t, list, list2[num2], num2, num2 + 3, num2 + 2);
			}
			return Make(list, list2, t);
		}

		public static Mesh Sphere(int lon, int lat)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00e0: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>();
			List<int> t = new List<int>();
			for (int i = 0; i <= lat; i++)
			{
				for (int j = 0; j <= lon; j++)
				{
					float num = (float)Math.PI * (float)i / (float)lat;
					float num2 = (float)Math.PI * 2f * (float)j / (float)lon;
					list.Add(new Vector3(Mathf.Sin(num) * Mathf.Cos(num2), Mathf.Cos(num), Mathf.Sin(num) * Mathf.Sin(num2)));
				}
			}
			for (int k = 0; k < lat; k++)
			{
				for (int l = 0; l < lon; l++)
				{
					int num3 = k * (lon + 1) + l;
					int b = num3 + 1;
					int num4 = num3 + lon + 1;
					int num5 = num4 + 1;
					Vector3 val = list[num3] + list[num5];
					Facing(t, list, ((Vector3)(ref val)).normalized, num3, b, num5);
					val = list[num3] + list[num5];
					Facing(t, list, ((Vector3)(ref val)).normalized, num3, num5, num4);
				}
			}
			return Make(list, new List<Vector3>(list), t);
		}

		public static Mesh Torus(float radius, float tube, int seg, int tubeSeg)
		{
			//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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>();
			List<Vector3> list2 = new List<Vector3>();
			List<int> t = new List<int>();
			for (int i = 0; i <= seg; i++)
			{
				float num = (float)i * (float)Math.PI * 2f / (float)seg;
				Vector3 val = new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num)) * radius;
				for (int j = 0; j <= tubeSeg; j++)
				{
					float num2 = (float)j * (float)Math.PI * 2f / (float)tubeSeg;
					Vector3 val2 = ((Vector3)(ref val)).normalized * Mathf.Cos(num2) + Vector3.up * Mathf.Sin(num2);
					list.Add(val + val2 * tube);
					list2.Add(val2);
				}
			}
			int num3 = tubeSeg + 1;
			for (int k = 0; k < seg; k++)
			{
				for (int l = 0; l < tubeSeg; l++)
				{
					int num4 = k * num3 + l;
					Facing(t, list, list2[num4], num4, num4 + num3, num4 + num3 + 1);
					Facing(t, list, list2[num4], num4, num4 + num3 + 1, num4 + 1);
				}
			}
			return Make(list, list2, t);
		}

		public static Mesh Tail()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>();
			List<Vector3> list2 = new List<Vector3>();
			List<int> t = new List<int>();
			for (int i = 0; i < 2; i++)
			{
				Vector3 val = ((i == 0) ? Vector3.forward : Vector3.back);
				int count = list.Count;
				for (int j = 0; j <= 8; j++)
				{
					float num = (float)j / 8f;
					float num2 = 0.5f * (1f - 0.2f * num);
					float num3 = Mathf.Sin(num * 3f) * 0.08f;
					list.Add(new Vector3(0f - num2, 0f - num, num3));
					list.Add(new Vector3(num2, 0f - num, 0f - num3));
					list2.Add(val);
					list2.Add(val);
				}
				for (int k = 0; k < 8; k++)
				{
					int num4 = count + k * 2;
					Facing(t, list, val, num4, num4 + 1, num4 + 3);
					Facing(t, list, val, num4, num4 + 3, num4 + 2);
				}
			}
			return Make(list, list2, t);
		}

		private static void Facing(List<int> t, List<Vector3> v, Vector3 want, int a, int b, int c)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			bool flag = Vector3.Dot(Vector3.Cross(v[b] - v[a], v[c] - v[a]), want) >= 0f;
			t.Add(a);
			t.Add(flag ? b : c);
			t.Add(flag ? c : b);
		}

		private static Mesh Make(List<Vector3> v, List<Vector3> n, List<int> t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			Mesh val = new Mesh();
			val.SetVertices(v);
			val.SetNormals(n);
			val.SetTriangles(t, 0);
			val.RecalculateBounds();
			return val;
		}
	}
	internal static class CurtainTime
	{
		public static double? Override { get; set; }

		public static float Now => (float)((Override ?? (Object.op_Implicit((Object)(object)ZNet.instance) ? ZNet.instance.GetTimeSeconds() : Time.timeAsDouble)) % 100000.0);
	}
	public interface IBoothPrepare
	{
		void Prepare();
	}
	public sealed class CurtainControl : MonoBehaviour, Hoverable, Interactable
	{
		private const string TiedKey = "coga_curtain_tied";

		private const string WidthKey = "coga_curtain_w";

		private const string HeightKey = "coga_curtain_h";

		public string DisplayName = "Curtains";

		public bool Tieable = true;

		public float DefaultWidth = 2f;

		public float DefaultHeight = 2.2f;

		public float ForceTie = -1f;

		private ZNetView _nview;

		private float _nextSizeCheck;

		private float _appliedW = -1f;

		private float _appliedH = -1f;

		private bool Valid
		{
			get
			{
				if (Object.op_Implicit((Object)(object)_nview) && _nview.IsValid())
				{
					return _nview.GetZDO() != null;
				}
				return false;
			}
		}

		public bool Tied
		{
			get
			{
				if (!(ForceTie >= 0f))
				{
					if (Valid)
					{
						return _nview.GetZDO().GetBool("coga_curtain_tied", false);
					}
					return false;
				}
				return ForceTie > 0.5f;
			}
		}

		public float Width
		{
			get
			{
				if (!Valid)
				{
					return DefaultWidth;
				}
				return _nview.GetZDO().GetFloat("coga_curtain_w", DefaultWidth);
			}
		}

		public float Height
		{
			get
			{
				if (!Valid)
				{
					return DefaultHeight;
				}
				return _nview.GetZDO().GetFloat("coga_curtain_h", DefaultHeight);
			}
		}

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
		}

		private void Start()
		{
			ApplySize(force: true);
		}

		private void Update()
		{
			if (Time.time >= _nextSizeCheck)
			{
				long start = CurtainPerf.Begin();
				_nextSizeCheck = Time.time + 0.5f;
				ApplySize(force: false);
				CurtainPerf.End(start);
			}
		}

		public void ApplySize(bool force)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: 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)
			float width = Width;
			float height = Height;
			if (!force && Mathf.Approximately(width, _appliedW) && Mathf.Approximately(height, _appliedH))
			{
				return;
			}
			_appliedW = width;
			_appliedH = height;
			Transform val = ((Component)this).transform.Find("Rod");
			if (Object.op_Implicit((Object)(object)val))
			{
				val.localPosition = new Vector3(0f, height + 0.07f, 0f);
				val.localScale = new Vector3(width + 0.3f, 1f, 1f);
			}
			int num = 0;
			foreach (Transform item in ((Component)this).transform)
			{
				Transform val2 = item;
				if (((Object)val2).name == "Finial")
				{
					val2.localPosition = new Vector3(((num++ == 0) ? (-1f) : 1f) * (width * 0.5f + 0.15f), height + 0.07f, 0f);
				}
			}
			BoxCollider component = ((Component)this).GetComponent<BoxCollider>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.center = new Vector3(0f, height * 0.5f + 0.05f, 0f);
				component.size = new Vector3(width, height + 0.1f, 0.25f);
			}
			CurtainCloth[] componentsInChildren = ((Component)this).GetComponentsInChildren<CurtainCloth>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].Resize(width, height);
			}
		}

		public bool TryResize(float dw, float dh, out string message)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			message = null;
			if (!Valid)
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				message = "Curtains: this is inside someone else's ward";
				return false;
			}
			float num = Mathf.Clamp(Mathf.Round((Width + dw) * 4f) / 4f, 0.5f, 40f);
			float num2 = Mathf.Clamp(Mathf.Round((Height + dh) * 4f) / 4f, 0.5f, 40f);
			if (!_nview.IsOwner())
			{
				_nview.ClaimOwnership();
			}
			_nview.GetZDO().Set("coga_curtain_w", num);
			_nview.GetZDO().Set("coga_curtain_h", num2);
			ApplySize(force: false);
			message = $"{DisplayName}: {num:0.##} m wide × {num2:0.##} m tall";
			return true;
		}

		public string GetHoverText()
		{
			string text = DisplayName;
			if (Tieable)
			{
				text = text + "\n[<color=yellow><b>$KEY_Use</b></color>] " + (Tied ? "Let down" : "Tie back");
			}
			text += $"\n[<color=yellow><b>[ ]</b></color>] width  [<color=yellow><b>Shift + [ ]</b></color>] height  ({Width:0.##} × {Height:0.##} m)";
			if (Localization.instance == null)
			{
				return text;
			}
			return Localization.instance.Localize(text);
		}

		public string GetHoverName()
		{
			return DisplayName;
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if (hold || !Tieable || !Valid)
			{
				return false;
			}
			bool flag = !Tied;
			if (!_nview.IsOwner())
			{
				_nview.ClaimOwnership();
			}
			_nview.GetZDO().Set("coga_curtain_tied", flag);
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}
	}
	public sealed class CurtainCloth : MonoBehaviour, IBoothPrepare
	{
		private static readonly FieldInfo CharacterCollider = AccessTools.Field(typeof(Character), "m_collider");

		public CurtainControl Control;

		public float Width = 2f;

		public float Height = 2.2f;

		public bool Tieable = true;

		public float TieV = 0.58f;

		public float TieWidth = 0.36f;

		private float _tv = 0.58f;

		private float _tw = 0.36f;

		public float FoldsPerMeter = 4.2f;

		public float Depth = 0.075f;

		public float Flare = 0.2f;

		public float Overlap = 0.04f;

		public int Seed = 1;

		public Transform TieL;

		public Transform TieR;

		public Material Material;

		public bool Sheer;

		private SkinnedMeshRenderer _smr;

		private Cloth _cloth;

		private Mesh _pose;

		private Mesh _back;

		private MeshFilter _backFilter;

		private Vector3[] _poseVerts;

		private Vector3[] _backVerts;

		private Vector3[] _backNormals;

		private float[] _shape;

		private int _segU;

		private int _segV;

		private float _tie;

		private float _appliedTie = -1f;

		private float _lastTarget = -1f;

		private bool _clothPending;

		private bool _coeffPending;

		private bool _weldWarned;

		private int _coeffTries;

		private bool _ready;

		private float _nextColliders;

		private bool? _clothIsLocal;

		private int PerPanel => (_segU + 1) * (_segV + 1);

		private float PanelWidth => Width * 0.5f + Overlap;

		public bool Simulating
		{
			get
			{
				if (Object.op_Implicit((Object)(object)_cloth))
				{
					return _cloth.enabled;
				}
				return false;
			}
		}

		public int VertexCount
		{
			get
			{
				if (_poseVerts == null)
				{
					return 0;
				}
				return _poseVerts.Length;
			}
		}

		private void ComputeTie()
		{
			float panelWidth = PanelWidth;
			float num = Mathf.Clamp(0.3f + 0.08f * panelWidth, 0.3f, 0.7f);
			_tw = Mathf.Clamp(num / panelWidth, 0.08f, 0.6f);
			float num2 = Mathf.Clamp(Height * 0.42f, 0.9f, 1.6f);
			_tv = Mathf.Clamp(1f - num2 / Height, 0.3f, 0.85f);
		}

		public void Resize(float w, float h)
		{
			if (!_ready || !Mathf.Approximately(w, Width) || !Mathf.Approximately(h, Height))
			{
				Width = w;
				Height = h;
				Teardown();
				Init();
			}
		}

		private void Start()
		{
			Init();
		}

		public void Prepare()
		{
			Init();
			_tie = ((Object.op_Implicit((Object)(object)Control) && Control.Tied && Tieable) ? 1f : 0f);
			WritePose(_tie);
			CopyBack(forcePose: true);
		}

		private void Update()
		{
			long start = CurtainPerf.Begin();
			try
			{
				UpdateInner();
			}
			finally
			{
				CurtainPerf.End(start);
			}
		}

		private void UpdateInner()
		{
			if (!_ready)
			{
				return;
			}
			float num = ((Object.op_Implicit((Object)(object)Control) && Control.Tied && Tieable) ? 1f : 0f);
			if (!Mathf.Approximately(num, _lastTarget))
			{
				_lastTarget = num;
				if (Object.op_Implicit((Object)(object)_cloth))
				{
					DropCloth();
					_clothPending = true;
				}
			}
			_tie = Mathf.MoveTowards(_tie, num, Time.deltaTime / 1.1f);
			float num2 = Mathf.SmoothStep(0f, 1f, _tie);
			if (!Mathf.Approximately(num2, _appliedTie))
			{
				WritePose(num2);
			}
			if (_clothPending && Mathf.Approximately(_tie, num))
			{
				_clothPending = false;
				TrySetupCloth();
			}
			if (Object.op_Implicit((Object)(object)_cloth) && _coeffPending)
			{
				if (ApplyCoefficients(num2))
				{
					_cloth.enabled = true;
					_coeffPending = false;
				}
				else if (++_coeffTries > 120)
				{
					Debug.LogWarning((object)"[Coga Curtains] Cloth never reported its vertices; leaving this curtain static.");
					_coeffPending = false;
					DropCloth();
				}
			}
			if (Object.op_Implicit((Object)(object)_cloth) && Time.time >= _nextColliders)
			{
				_nextColliders = Time.time + 0.5f;
				UpdateColliders();
				if (ClothBlewUp())
				{
					DropCloth();
					TrySetupCloth();
				}
			}
		}

		private bool ClothBlewUp()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_cloth) || !_cloth.enabled)
			{
				return false;
			}
			Vector3[] vertices = _cloth.vertices;
			if (vertices == null || vertices.Length == 0)
			{
				return false;
			}
			float num = Width + Height + 3f;
			for (int i = 0; i < vertices.Length; i += Mathf.Max(1, vertices.Length / 8))
			{
				Vector3 val = vertices[i];
				if (float.IsNaN(val.x) || float.IsNaN(val.y) || float.IsNaN(val.z) || float.IsInfinity(val.x) || float.IsInfinity(val.y) || float.IsInfinity(val.z))
				{
					return true;
				}
				Vector3 val2 = ((_clothIsLocal == false) ? ((Component)this).transform.InverseTransformPoint(val) : val);
				if (_clothIsLocal.HasValue && ((Vector3)(ref val2)).magnitude > num)
				{
					return true;
				}
			}
			return false;
		}

		private void LateUpdate()
		{
			if (_ready)
			{
				long start = CurtainPerf.Begin();
				CopyBack(forcePose: false);
				CurtainPerf.End(start);
			}
		}

		private void Init()
		{
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Expected O, but got Unknown
			//IL_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Expected O, but got Unknown
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0442: 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_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e9: 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)
			if (_ready || !Object.op_Implicit((Object)(object)Material))
			{
				return;
			}
			ComputeTie();
			float panelWidth = PanelWidth;
			_segU = Mathf.Clamp(Mathf.RoundToInt(panelWidth * 14f), 10, 36);
			_segV = Mathf.Clamp(Mathf.RoundToInt(Height * 6f), 10, 32);
			int perPanel = PerPanel;
			float folds = FoldsPerMeter * panelWidth;
			_shape = new float[perPanel * 2];
			_poseVerts = (Vector3[])(object)new Vector3[perPanel * 2];
			_backVerts = (Vector3[])(object)new Vector3[perPanel * 2];
			_backNormals = (Vector3[])(object)new Vector3[perPanel * 2];
			Vector2[] array = (Vector2[])(object)new Vector2[perPanel * 2];
			List<int> list = new List<int>();
			List<int> list2 = new List<int>();
			for (int i = 0; i < 2; i++)
			{
				for (int j = 0; j <= _segV; j++)
				{
					float num = (float)j / (float)_segV;
					for (int k = 0; k <= _segU; k++)
					{
						float num2 = (float)k / (float)_segU;
						int num3 = i * perPanel + j * (_segU + 1) + k;
						_shape[num3] = DrapeRender.FoldShape(folds, Seed + i, num2, num);
						array[num3] = new Vector2(num2 * panelWidth / 4f, Height * (1f - num) / 40f);
					}
				}
				for (int l = 0; l < _segV; l++)
				{
					for (int m = 0; m < _segU; m++)
					{
						int num4 = i * perPanel + l * (_segU + 1) + m;
						int num5 = num4 + 1;
						int num6 = num4 + _segU + 1;
						int num7 = num6 + 1;
						if (i == 0)
						{
							list.AddRange(new int[6] { num4, num6, num5, num5, num6, num7 });
							list2.AddRange(new int[6] { num4, num5, num6, num5, num7, num6 });
						}
						else
						{
							list.AddRange(new int[6] { num4, num5, num6, num5, num7, num6 });
							list2.AddRange(new int[6] { num4, num6, num5, num5, num6, num7 });
						}
					}
				}
			}
			_tie = ((Object.op_Implicit((Object)(object)Control) && Control.Tied && Tieable) ? 1f : 0f);
			WritePoseVerts(Mathf.SmoothStep(0f, 1f, _tie));
			Bounds val = default(Bounds);
			((Bounds)(ref val))..ctor(new Vector3(0f, Height * 0.5f, 0f), new Vector3(Width + 1.5f, Height + 1.5f, 2.5f));
			_pose = new Mesh
			{
				name = "coga_curtain_pose"
			};
			_pose.MarkDynamic();
			_pose.vertices = _poseVerts;
			_pose.uv = array;
			_pose.SetTriangles(list, 0);
			_pose.RecalculateNormals();
			_pose.bounds = val;
			_back = new Mesh
			{
				name = "coga_curtain_back"
			};
			_back.MarkDynamic();
			_back.vertices = _poseVerts;
			_back.uv = array;
			_back.SetTriangles(list2, 0);
			_back.RecalculateNormals();
			_back.bounds = val;
			_smr = ((Component)this).gameObject.GetComponent<SkinnedMeshRenderer>();
			if (!Object.op_Implicit((Object)(object)_smr))
			{
				_smr = ((Component)this).gameObject.AddComponent<SkinnedMeshRenderer>();
			}
			_smr.sharedMesh = _pose;
			((Renderer)_smr).sharedMaterial = Material;
			((Renderer)_smr).localBounds = val;
			_smr.updateWhenOffscreen = false;
			((Renderer)_smr).shadowCastingMode = (ShadowCastingMode)(!Sheer);
			Transform val2 = ((Component)this).transform.Find("Back");
			if (Object.op_Implicit((Object)(object)Material.shader) && ((Object)Material.shader).name.Contains("TwoSided"))
			{
				if (Object.op_Implicit((Object)(object)val2))
				{
					Object.Destroy((Object)(object)((Component)val2).gameObject);
				}
				Object.Destroy((Object)(object)_back);
				_back = null;
			}
			else
			{
				if (!Object.op_Implicit((Object)(object)val2))
				{
					val2 = new GameObject("Back")
					{
						layer = ((Component)this).gameObject.layer
					}.transform;
					val2.SetParent(((Component)this).transform, false);
				}
				_backFilter = ((Component)val2).GetComponent<MeshFilter>();
				if (!Object.op_Implicit((Object)(object)_backFilter))
				{
					_backFilter = ((Component)val2).gameObject.AddComponent<MeshFilter>();
				}
				MeshRenderer val3 = ((Component)val2).GetComponent<MeshRenderer>();
				if (!Object.op_Implicit((Object)(object)val3))
				{
					val3 = ((Component)val2).gameObject.AddComponent<MeshRenderer>();
				}
				((Renderer)val3).sharedMaterial = Material;
				((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0;
				_backFilter.sharedMesh = _back;
			}
			_lastTarget = _tie;
			TrySetupCloth();
			_appliedTie = -1f;
			_ready = true;
			PlaceTies(Mathf.SmoothStep(0f, 1f, _tie));
		}

		private void TrySetupCloth()
		{
			if (!CurtainsConfig.ClothPhysics || CurtainAssets.Headless)
			{
				return;
			}
			try
			{
				SetupCloth();
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[Coga Curtains] Cloth setup failed, curtains stay static: " + ex.Message));
				DropCloth();
			}
		}

		private void DropCloth()
		{
			GlobalWind component = ((Component)this).GetComponent<GlobalWind>();
			if (Object.op_Implicit((Object)(object)component))
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			if (Object.op_Implicit((Object)(object)_cloth))
			{
				Object.DestroyImmediate((Object)(object)_cloth);
			}
			_cloth = null;
			_clothIsLocal = null;
		}

		private void SetupCloth()
		{
			_cloth = ((Component)this).gameObject.GetComponent<Cloth>();
			if (!Object.op_Implicit((Object)(object)_cloth))
			{
				_cloth = ((Component)this).gameObject.AddComponent<Cloth>();
			}
			_cloth.useGravity = true;
			_cloth.stretchingStiffness = 0.95f;
			_cloth.bendingStiffness = 0.12f;
			_cloth.damping = 0.4f;
			_cloth.friction = 0.6f;
			_cloth.collisionMassScale = 0.1f;
			_cloth.worldVelocityScale = 0.3f;
			_cloth.worldAccelerationScale = 0.5f;
			_cloth.useTethers = true;
			_cloth.sleepThreshold = 0.03f;
			_cloth.clothSolverFrequency = 90f;
			_cloth.enabled = false;
			_coeffPending = true;
			_coeffTries = 0;
			if (ApplyCoefficients(Mathf.SmoothStep(0f, 1f, _tie)))
			{
				_cloth.enabled = true;
				_coeffPending = false;
			}
			GlobalWind val = ((Component)this).gameObject.GetComponent<GlobalWind>();
			if (!Object.op_Implicit((Object)(object)val))
			{
				val = ((Component)this).gameObject.AddComponent<GlobalWind>();
			}
			Set(val, "m_multiplier", Sheer ? 0.6f : 0.35f);
			Set(val, "m_checkPlayerShelter", true);
			Set(val, "m_clothRandomAccelerationFactor", 0.5f);
			Set(val, "m_smoothUpdate", true);
			UpdateColliders();
		}

		private static void Set(object target, string field, object value)
		{
			AccessTools.Field(target.GetType(), field)?.SetValue(target, value);
		}

		private float MaxDistanceAt(float v, float tie)
		{
			float num = ((v <= 1.5f / (float)_segV) ? 0f : (0.08f + 0.95f * Mathf.Pow(v, 1.1f)));
			if (Tieable && tie > 0f)
			{
				num = Mathf.Lerp(num, Mathf.Min(num, 0.01f + 1.4f * Mathf.Abs(v - _tv)), tie);
			}
			return num;
		}

		private bool ApplyCoefficients(float tie)
		{
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_cloth))
			{
				return true;
			}
			ClothSkinningCoefficient[] coefficients = _cloth.coefficients;
			if (coefficients == null || coefficients.Length == 0)
			{
				return false;
			}
			if (coefficients.Length == _poseVerts.Length)
			{
				int perPanel = PerPanel;
				for (int i = 0; i < 2; i++)
				{
					for (int j = 0; j <= _segV; j++)
					{
						float maxDistance = MaxDistanceAt((float)j / (float)_segV, tie);
						for (int k = 0; k <= _segU; k++)
						{
							int num = i * perPanel + j * (_segU + 1) + k;
							coefficients[num].maxDistance = maxDistance;
							coefficients[num].collisionSphereDistance = 0f;
						}
					}
				}
			}
			else
			{
				Vector3[] vertices = _cloth.vertices;
				if (vertices == null || vertices.Length != coefficients.Length)
				{
					return false;
				}
				if (!_weldWarned)
				{
					_weldWarned = true;
					Debug.Log((object)$"[Coga Curtains] Cloth welded {_poseVerts.Length} -> {coefficients.Length} vertices; pinning by height instead.");
				}
				Vector3 val = vertices[0] - _poseVerts[0];
				bool flag = ((Vector3)(ref val)).sqrMagnitude < 4f;
				for (int l = 0; l < coefficients.Length; l++)
				{
					float num2 = (flag ? vertices[l].y : ((Component)this).transform.InverseTransformPoint(vertices[l]).y);
					coefficients[l].maxDistance = MaxDistanceAt(Mathf.Clamp01(1f - num2 / Height), tie);
					coefficients[l].collisionSphereDistance = 0f;
				}
			}
			_cloth.coefficients = coefficients;
			return true;
		}

		private void UpdateColliders()
		{
			//IL_0031: 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)
			List<CapsuleCollider> list = new List<CapsuleCollider>();
			List<Player> allPlayers = Player.GetAllPlayers();
			if (allPlayers != null)
			{
				foreach (Player item in allPlayers)
				{
					if (Object.op_Implicit((Object)(object)item) && Vector3.Distance(((Component)item).transform.position, ((Component)this).transform.position) < Width * 0.5f + Height + 3f)
					{
						object? obj = CharacterCollider?.GetValue(item);
						CapsuleCollider val = (CapsuleCollider)((obj is CapsuleCollider) ? obj : null);
						if (val != null && Object.op_Implicit((Object)(object)val))
						{
							list.Add(val);
						}
					}
				}
			}
			_cloth.capsuleColliders = list.ToArray();
		}

		private void WritePose(float tie)
		{
			WritePoseVerts(tie);
			_pose.vertices = _poseVerts;
			_pose.RecalculateNormals();
			ApplyCoefficients(tie);
			PlaceTies(tie);
			_appliedTie = tie;
		}

		private void WritePoseVerts(float tie)
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			int perPanel = PerPanel;
			float panelWidth = PanelWidth;
			for (int i = 0; i < 2; i++)
			{
				bool flag = i == 0;
				float anchor = (flag ? ((0f - Width) * 0.5f) : (Width * 0.5f));
				for (int j = 0; j <= _segV; j++)
				{
					float num = (float)j / (float)_segV;
					Span(num, tie, panelWidth, anchor, flag, out var left, out var extent, out var compress);
					float num2 = DrapeRender.FoldAmp(Depth, num, Mathf.Min(compress, 3.5f));
					float num3 = Height * (1f - num);
					for (int k = 0; k <= _segU; k++)
					{
						float num4 = (float)k / (float)_segU;
						int num5 = i * perPanel + j * (_segU + 1) + k;
						float num6 = (flag ? (left + num4 * extent) : (left + extent - num4 * extent));
						_poseVerts[num5] = new Vector3(num6, num3, num2 * _shape[num5]);
					}
				}
			}
		}

		private void Span(float v, float tie, float panelW, float anchor, bool fromLeft, out float left, out float extent, out float compress)
		{
			float num = (Tieable ? (DrapeRender.Pinch(_tv, v) * tie) : 0f);
			float num2 = (1f - (1f - _tw) * num) * (1f + Mathf.Min(Flare * panelW, 0.25f) / panelW * Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(0.72f, 1f, v)));
			extent = panelW * num2;
			float num3 = Mathf.Min(panelW * 0.12f, 0.25f) * num;
			left = (fromLeft ? (anchor + num3) : (anchor - num3 - extent));
			compress = 1f / Mathf.Max(0.05f, num2);
		}

		private void PlaceTies(float tie)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			float panelWidth = PanelWidth;
			for (int i = 0; i < 2; i++)
			{
				Transform val = ((i == 0) ? TieL : TieR);
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				bool flag = tie > 0.02f;
				if (((Component)val).gameObject.activeSelf != flag)
				{
					((Component)val).gameObject.SetActive(flag);
				}
				if (flag)
				{
					bool flag2 = i == 0;
					Span(_tv, tie, panelWidth, flag2 ? ((0f - Width) * 0.5f) : (Width * 0.5f), flag2, out var left, out var extent, out var compress);
					val.localPosition = new Vector3(left + extent * 0.5f, Height * (1f - _tv), 0f);
					Transform val2 = val.Find("Band");
					if (Object.op_Implicit((Object)(object)val2))
					{
						val2.localScale = new Vector3(extent * 0.52f, 0.25f, DrapeRender.FoldAmp(Depth, _tv, Mathf.Min(compress, 3.5f)) + 0.03f);
					}
					val.localScale = Vector3.one * Mathf.Lerp(0.6f, 1f, tie);
				}
			}
		}

		private void CopyBack(bool forcePose)
		{
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_back) || (!forcePose && Object.op_Implicit((Object)(object)_smr) && !((Renderer)_smr).isVisible))
			{
				return;
			}
			Vector3[] array = null;
			Vector3[] array2 = null;
			if (!forcePose && Object.op_Implicit((Object)(object)_cloth) && _cloth.enabled)
			{
				Vector3[] vertices = _cloth.vertices;
				if (vertices != null && vertices.Length == _poseVerts.Length)
				{
					if (!_clothIsLocal.HasValue)
					{
						Vector3 val = vertices[0] - _poseVerts[0];
						float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
						val = ((Component)this).transform.InverseTransformPoint(vertices[0]) - _poseVerts[0];
						_clothIsLocal = sqrMagnitude <= ((Vector3)(ref val)).sqrMagnitude;
					}
					array = vertices;
					array2 = _cloth.normals;
				}
			}
			if (array == null)
			{
				for (int i = 0; i < _poseVerts.Length; i++)
				{
					_backVerts[i] = _poseVerts[i];
				}
				_back.vertices = _backVerts;
				_back.RecalculateNormals();
				return;
			}
			bool valueOrDefault = _clothIsLocal == true;
			for (int j = 0; j < array.Length; j++)
			{
				_backVerts[j] = (valueOrDefault ? array[j] : ((Component)this).transform.InverseTransformPoint(array[j]));
				Vector3 val2 = ((array2 != null && j < array2.Length) ? (valueOrDefault ? array2[j] : ((Component)this).transform.InverseTransformDirection(array2[j])) : Vector3.forward);
				_backNormals[j] = -val2;
			}
			_back.vertices = _backVerts;
			_back.normals = _backNormals;
		}

		private void Teardown()
		{
			_ready = false;
			if (Object.op_Implicit((Object)(object)_cloth))
			{
				Object.DestroyImmediate((Object)(object)_cloth);
			}
			GlobalWind component = ((Component)this).GetComponent<GlobalWind>();
			if (Object.op_Implicit((Object)(object)component))
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			if (Object.op_Implicit((Object)(object)_pose))
			{
				Object.Destroy((Object)(object)_pose);
			}
			if (Object.op_Implicit((Object)(object)_back))
			{
				Object.Destroy((Object)(object)_back);
			}
			_cloth = null;
			_clothIsLocal = null;
		}

		private void OnDestroy()
		{
			Teardown();
		}
	}
	internal static class CurtainPerf
	{
		private static readonly Stopwatch Watch = new Stopwatch();

		private static double _ticks;

		private static int _frames;

		private static float _frameTime;

		private static float _nextReport;

		private static int _lastFrame = -1;

		private static double _worstFrameMs;

		private static double _thisFrameTicks;

		public static bool Enabled = true;

		public static long Begin()
		{
			if (!Enabled)
			{
				return 0L;
			}
			return Stopwatch.GetTimestamp();
		}

		public static void End(long start)
		{
			if (Enabled && start != 0L)
			{
				long num = Stopwatch.GetTimestamp() - start;
				_ticks += num;
				if (Time.frameCount != _lastFrame)
				{
					_lastFrame = Time.frameCount;
					_thisFrameTicks = 0.0;
				}
				_thisFrameTicks += num;
				double num2 = _thisFrameTicks * 1000.0 / (double)Stopwatch.Frequency;
				if (num2 > _worstFrameMs)
				{
					_worstFrameMs = num2;
				}
			}
		}

		public static void Tick(ManualLogSource log)
		{
			if (!Enabled)
			{
				return;
			}
			_frames++;
			_frameTime += Time.unscaledDeltaTime;
			if (Time.unscaledTime < _nextReport)
			{
				return;
			}
			_nextReport = Time.unscaledTime + 10f;
			if (_frames > 0)
			{
				CurtainCloth[] array = Object.FindObjectsByType<CurtainCloth>((FindObjectsSortMode)0);
				int num = 0;
				int num2 = 0;
				CurtainCloth[] array2 = array;
				foreach (CurtainCloth curtainCloth in array2)
				{
					if (curtainCloth.Simulating)
					{
						num++;
						num2 += curtainCloth.VertexCount;
					}
				}
				double num3 = _ticks * 1000.0 / (double)Stopwatch.Frequency / (double)_frames;
				float num4 = _frameTime / (float)_frames * 1000f;
				if (array.Length != 0 || num3 > 0.01)
				{
					log.LogInfo((object)$"Curtains perf (10 s): our code {num3:0.000} ms/frame avg, {_worstFrameMs:0.00} ms worst | {array.Length} cloth layers, {num} simulating ({num2} cloth verts) | game frame {num4:0.0} ms ({1000f / Mathf.Max(0.01f, num4):0} fps)");
				}
			}
			_ticks = 0.0;
			_frames = 0;
			_frameTime = 0f;
			_worstFrameMs = 0.0;
		}
	}
	internal sealed class CurtainDef
	{
		public string Prefab;

		public string Name;

		public string Description;

		public Fabric Fabric;

		public float Width;

		public float Height;
	}
	internal static class CurtainPieces
	{
		public const string Category = "Curtains";

		private static readonly (float W, float H, string Prefix, string Suffix)[] Sizes = new(float, float, string, string)[3]
		{
			(2f, 2.2f, "", "2x2"),
			(2f, 3.2f, "Tall ", "2x3"),
			(4f, 4.2f, "Grand ", "4x4")
		};

		private static bool _registered;

		private static readonly List<Piece> Registered = new List<Piece>();

		private static readonly HashSet<string> FirstReleaseFabrics = new HashSet<string> { "black_satin", "white_satin", "white_sheer", "black_over_sheer", "voile" };

		private static int _lastGateKey = int.MinValue;

		public static bool IsRegistered => _registered;

		public static IReadOnlyList<CurtainDef> Defs { get; } = MakeDefs();

		private static List<CurtainDef> MakeDefs()
		{
			List<CurtainDef> list = new List<CurtainDef>();
			(float, float, string, string)[] sizes = Sizes;
			for (int i = 0; i < sizes.Length; i++)
			{
				(float, float, string, string) tuple = sizes[i];
				Fabric[] fabrics = CurtainAssets.Fabrics;
				foreach (Fabric fabric in fabrics)
				{
					CurtainDef obj = new CurtainDef
					{
						Prefab = "coga_curtain_" + fabric.Id + "_" + tuple.Item4,
						Name = tuple.Item3 + fabric.Name,
						Description = $"{fabric.Description} {tuple.Item1:0} m wide, {tuple.Item2:0.#} m drop. Press E to tie back or let down. Place on the floor; snaps to wall edges.",
						Fabric = fabric
					};
					(obj.Width, obj.Height, _, _) = tuple;
					list.Add(obj);
				}
			}
			return list;
		}

		public static void Build(GameObject root, CurtainDef def)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			Fabric fabric = def.Fabric;
			float width = def.Width;
			float height = def.Height;
			Transform obj = Child(root.transform, "Rod", new Vector3(0f, height + 0.07f, 0f));
			obj.localScale = new Vector3(width + 0.3f, 1f, 1f);
			Render(obj, CurtainAssets.Rod, CurtainAssets.IronMat, shadows: true);
			float[] array = new float[2]
			{
				0f - (width * 0.5f + 0.15f),
				width * 0.5f + 0.15f
			};
			foreach (float num in array)
			{
				Transform obj2 = Child(root.transform, "Finial", new Vector3(num, height + 0.07f, 0f));
				obj2.localScale = Vector3.one * 0.045f;
				Render(obj2, CurtainAssets.Finial, CurtainAssets.BrassMat, shadows: true);
			}
			CurtainControl curtainControl = root.GetComponent<CurtainControl>();
			if (!Object.op_Implicit((Object)(object)curtainControl))
			{
				curtainControl = root.AddComponent<CurtainControl>();
			}
			curtainControl.DisplayName = def.Name;
			curtainControl.Tieable = true;
			curtainControl.DefaultWidth = width;
			curtainControl.DefaultHeight = height;
			if (fabric.Under != null)
			{
				Layer(root, curtainControl, fabric.Under, def, -0.1f, tieable: false);
			}
			Layer(root, curtainControl, fabric, def, 0f, tieable: true);
		}

		private static void Layer(GameObject root, CurtainControl control, Fabric f, CurtainDef def, float z, bool tieable)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			Transform val = Child(root.transform, "Layer_" + f.Id, new Vector3(0f, 0.02f, z));
			CurtainCloth curtainCloth = ((Component)val).gameObject.AddComponent<CurtainCloth>();
			curtainCloth.Control = control;
			curtainCloth.Width = def.Width;
			curtainCloth.Height = def.Height;
			curtainCloth.Tieable = tieable;
			curtainCloth.FoldsPerMeter = f.FoldsPerMeter;
			curtainCloth.Depth = f.Depth * Mathf.Lerp(1f, 1.35f, Mathf.InverseLerp(2.2f, 4.2f, def.Height));
			curtainCloth.Seed = f.Seed;
			curtainCloth.Material = f.Material;
			curtainCloth.Sheer = f.Sheer;
			if (tieable)
			{
				curtainCloth.TieL = Tie(val, "TieL", f);
				curtainCloth.TieR = Tie(val, "TieR", f);
			}
		}

		private static Transform Tie(Transform layer, string name, Fabric f)
		{
			//IL_0002: 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_0081: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: 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_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: 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)
			Transform val = Child(layer, name, Vector3.zero);
			Render(Child(val, "Band", Vector3.zero), CurtainAssets.Band, CurtainAssets.SashFor(f), shadows: true);
			if (f.RibbonBow)
			{
				float[] array = new float[2] { 1f, -1f };
				foreach (float num in array)
				{
					Transform val2 = Child(val, (num > 0f) ? "BowFront" : "BowBack", new Vector3(0f, 0f, num * 0.1f));
					val2.localRotation = Quaternion.Euler(0f, (num > 0f) ? 0f : 180f, 0f);
					float[] array2 = new float[2] { -0.075f, 0.075f };
					foreach (float num2 in array2)
					{
						Transform obj = Child(val2, "Loop", new Vector3(num2, 0.015f, 0f));
						obj.localRotation = Quaternion.Euler(90f, 0f, (num2 > 0f) ? (-15f) : 15f);
						obj.localScale = new Vector3(0.07f, 0.12f, 0.04f);
						Render(obj, CurtainAssets.Loop, CurtainAssets.RibbonMat, shadows: false);
					}
					Transform obj2 = Child(val2, "Knot", Vector3.zero);
					obj2.localScale = new Vector3(0.028f, 0.024f, 0.02f);
					Render(obj2, CurtainAssets.Finial, CurtainAssets.RibbonMat, shadows: false);
					(float, float, float)[] array3 = new(float, float, float)[2]
					{
						(-0.012f, 0.55f, 8f),
						(0.012f, 0.45f, -7f)
					};
					for (int j = 0; j < array3.Length; j++)
					{
						(float, float, float) tuple = array3[j];
						float item = tuple.Item1;
						float item2 = tuple.Item2;
						float item3 = tuple.Item3;
						Transform obj3 = Child(val2, "Tail", new Vector3(item, -0.01f, 0.004f));
						obj3.localRotation = Quaternion.Euler(0f, 0f, item3);
						obj3.localScale = new Vector3(0.045f, item2, 1f);
						Render(obj3, CurtainAssets.Tail, CurtainAssets.RibbonMat, shadows: false);
					}
				}
			}
			((Component)val).gameObject.SetActive(false);
			return val;
		}

		private static Transform Child(Transform parent, string name, Vector3 pos)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name)
			{
				layer = ((Component)parent).gameObject.layer
			};
			val.transform.SetParent(parent, false);
			val.transform.localPosition = pos;
			return val.transform;
		}

		private static void Render(Transform t, Mesh mesh, Material mat, bool shadows)
		{
			((Component)t).gameObject.AddComponent<MeshFilter>().sharedMesh = mesh;
			MeshRenderer obj = ((Component)t).gameObject.AddComponent<MeshRenderer>();
			((Renderer)obj).sharedMaterial = mat;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)(shadows ? 1 : 0);
		}

		public static void Register(ManualLogSource log)
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Expected O, but got Unknown
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Expected O, but got Unknown
			if (_registered)
			{
				return;
			}
			CurtainAssets.Build(log);
			int num = LayerMask.NameToLayer("piece_nonsolid");
			if (num < 0)
			{
				num = LayerMask.NameToLayer("piece");
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab("piece_cloth_hanging_door");
			Piece val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<Piece>() : null);
			foreach (CurtainDef def in Defs)
			{
				GameObject val2 = PrefabManager.Instance.GetPrefab(def.Prefab);
				if (!Object.op_Implicit((Object)(object)val2))
				{
					val2 = PrefabManager.Instance.CreateEmptyPrefab(def.Prefab, true);
				}
				Strip(val2);
				val2.layer = num;
				ZNetView component = val2.GetComponent<ZNetView>();
				component.m_persistent = true;
				component.m_distant = true;
				BoxCollider val3 = val2.GetComponent<BoxCollider>();
				if (!Object.op_Implicit((Object)(object)val3))
				{
					val3 = val2.AddComponent<BoxCollider>();
				}
				val3.center = new Vector3(0f, def.Height * 0.5f + 0.05f, 0f);
				val3.size = new Vector3(def.Width, def.Height + 0.1f, 0.25f);
				((Collider)val3).isTrigger = false;
				Piece val4 = val2.GetComponent<Piece>();
				if (!Object.op_Implicit((Object)(object)val4))
				{
					val4 = val2.AddComponent<Piece>();
				}
				val4.m_groundPiece = false;
				val4.m_canBeRemoved = true;
				((StaticTarget)val4).m_randomTarget = false;
				((StaticTarget)val4).m_primaryTarget = false;
				val4.m_resources = Array.Empty<Requirement>();
				if (Object.op_Implicit((Object)(object)val))
				{
					val4.m_placeEffect = val.m_placeEffect;
				}
				Build(val2, def);
				AddSnapPoints(val2, def);
				PieceConfig val5 = new PieceConfig
				{
					Name = def.Name,
					Description = def.Description,
					PieceTable = "Hammer",
					Category = "Curtains",
					Icon = def.Fabric.Icon,
					Requirements = Array.Empty<RequirementConfig>()
				};
				PieceManager.Instance.AddPiece(new CustomPiece(val2, false, val5));
				RegisterLate(val2);
				Registered.Add(val4);
			}
			_registered = true;
			_lastGateKey = int.MinValue;
			log.LogInfo((object)string.Format("Curtains: {0} pieces on the hammer ({1} tab). Collider layer {2} trigger={3}.", Registered.Count, "Curtains", LayerMask.LayerToName(num), false));
		}

		private static void AddSnapPoints(GameObject prefab, CurtainDef def)
		{
			//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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] array = (Vector3[])(object)new Vector3[4]
			{
				new Vector3((0f - def.Width) * 0.5f, 0f, 0f),
				new Vector3(def.Width * 0.5f, 0f, 0f),
				new Vector3((0f - def.Width) * 0.5f, def.Height + 0.07f, 0f),
				new Vector3(def.Width * 0.5f, def.Height + 0.07f, 0f)
			};
			foreach (Vector3 localPosition in array)
			{
				GameObject val = new GameObject("_snappoint");
				val.transform.SetParent(prefab.transform, false);
				val.transform.localPosition = localPosition;
				try
				{
					val.tag = "snappoint";
				}
				catch (UnityException)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		private static void RegisterLate(GameObject prefab)
		{
			if (Object.op_Implicit((Object)(object)ZNetScene.instance) && Object.op_Implicit((Object)(object)ObjectDB.instance))
			{
				if (!Object.op_Implicit((Object)(object)ZNetScene.instance.GetPrefab(((Object)prefab).name)))
				{
					PrefabManager.Instance.RegisterToZNetScene(prefab);
				}
				PieceTable pieceTable = PieceManager.Instance.GetPieceTable("Hammer");
				if (Object.op_Implicit((Object)(object)pieceTable) && !pieceTable.m_pieces.Contains(prefab))
				{
					PieceManager.Instance.RegisterPieceInPieceTable(prefab, "Hammer", "Curtains");
				}
			}
		}

		private static void Strip(GameObject prefab)
		{
			for (int num = prefab.transform.childCount - 1; num >= 0; num--)
			{
				Object.DestroyImmediate((Object)(object)((Component)prefab.transform.GetChild(num)).gameObject);
			}
			Component[] components = prefab.GetComponents<Component>();
			foreach (Component val in components)
			{
				if (!(val is Transform) && !(val is ZNetView) && !(val is Piece) && !(val is BoxCollider))
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		public static bool IsFirstRelease(CurtainDef def)
		{
			return FirstReleaseFabrics.Contains(def.Fabric.Id);
		}

		public static IEnumerable<string> RegisteredNames()
		{
			foreach (Piece item in Registered)
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					yield return ((Object)((Component)item).gameObject).name;
				}
			}
		}

		public static void UpdateGate(bool forceAll, ManualLogSource log)
		{
			int num = ServerHandshake.State * 2 + (forceAll ? 1 : 0);
			if (_lastGateKey == num || Registered.Count == 0)
			{
				return;
			}
			_lastGateKey = num;
			int num2 = 0;
			foreach (Piece p in Registered)
			{
				if (Object.op_Implicit((Object)(object)p))
				{
					CurtainDef curtainDef = Defs.FirstOrDefault((CurtainDef d) => d.Prefab == ((Object)((Component)p).gameObject).name);
					bool flag = forceAll || ServerHandshake.Allows(((Object)((Component)p).gameObject).name, curtainDef != null && IsFirstRelease(curtainDef));
					p.m_enabled = flag;
					num2 += (flag ? 1 : 0);
				}
			}
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				AccessTools.Method(typeof(Player), "UpdateAvailablePiecesList", (Type[])null, (Type[])null)?.Invoke(Player.m_localPlayer, null);
			}
			if (Object.op_Implicit((Object)(object)ZNet.instance))
			{
				log.LogInfo((object)((num2 == Registered.Count) ? "Curtains: all pieces enabled (the server runs this version of CogaCurtains, or you are the server)." : ((num2 > 0) ? $"Curtains: {num2} of {Registered.Count} pieces enabled - the server runs an older CogaCurtains, so the newer fabrics stay hidden (it would delete them)." : "Curtains: pieces hidden - the server has not confirmed it runs CogaCurtains (a server without it deletes placed pieces).")));
			}
		}

		public static void Shutdown(ManualLogSource log)
		{
			if (PieceManager.Instance == null)
			{
				return;
			}
			foreach (CurtainDef def in Defs)
			{
				try
				{
					PieceManager.Instance.RemovePiece(def.Prefab);
				}
				catch (Exception ex)
				{
					log.LogDebug((object)("Curtains: RemovePiece " + def.Prefab + ": " + ex.Message));
				}
			}
			Registered.Clear();
			_registered = false;
		}
	}
	internal static class CurtainsConfig
	{
		private static ConfigEntry<bool> _clothPhysics;

		private static ConfigEntry<KeyCode> _wider;

		private static ConfigEntry<KeyCode> _narrower;

		public static bool ClothPhysics
		{
			get
			{
				if (_clothPhysics != null)
				{
					return _clothPhysics.Value;
				}
				return true;
			}
		}

		public static KeyCode Wider
		{
			get
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				if (_wider == null)
				{
					return (KeyCode)93;
				}
				return _wider.Value;
			}
		}

		public static KeyCode Narrower
		{
			get
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				if (_narrower == null)
				{
					return (KeyCode)91;
				}
				return _narrower.Value;
			}
		}

		public static void Bind(ConfigFile config)
		{
			_clothPhysics = config.Bind<bool>("Look", "ClothPhysics", true, "Unity cloth physics (wind via vanilla GlobalWind, pushed by players). Off = static drapes, cheapest.");
			CurtainPerf.Enabled = false;
			_wider = config.Bind<KeyCode>("Resize", "WiderKey", (KeyCode)93, "While aiming at a curtain: wider. Hold Shift for taller.");
			_narrower = config.Bind<KeyCode>("Resize", "NarrowerKey", (KeyCode)91, "While aiming at a curtain: narrower. Hold Shift for shorter.");
		}
	}
	[BepInPlugin("com.c0ga.curtains", "Coga Curtains", "0.2.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class CurtainsPlugin : BaseUnityPlugin
	{
		public const string Guid = "com.c0ga.curtains";

		public const string Name = "Coga Curtains";

		public const string Version = "0.2.1";

		private ConfigEntry<bool> _allowRemote;

		private float _nextGate;

		private void Awake()
		{
			ServerHandshake.LocalPieces = CurtainPieces.RegisteredNames;
			_allowRemote = ((BaseUnityPlugin)this).Config.Bind<bool>("Safety", "AllowOnRemoteServers", false, "Force the curtain pieces on even when the server has not confirmed it runs CogaCurtains. Normally leave this off: they appear automatically on servers that have it, and a server without it deletes placed pieces.");
			CurtainsConfig.Bind(((BaseUnityPlugin)this).Config);
			PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabs;
			if (Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				OnVanillaPrefabs();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Coga Curtains 0.2.1 loaded" + (CurtainAssets.Headless ? " (headless server)" : "") + "."));
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabs;
			ServerHandshake.Shutdown();
			CurtainPieces.Shutdown(((BaseUnityPlugin)this).Logger);
		}

		private void OnVanillaPrefabs()
		{
			try
			{
				CurtainPieces.Register(((BaseUnityPlugin)this).Logger);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Curtains registration failed: " + ex));
			}
		}

		private void Update()
		{
			CurtainPerf.Tick(((BaseUnityPlugin)this).Logger);
			if (Time.unscaledTime >= _nextGate)
			{
				_nextGate = Time.unscaledTime + 1f;
				if (!CurtainPieces.IsRegistered && Object.op_Implicit((Object)(object)ZNetScene.instance) && Object.op_Implicit((Object)(object)ObjectDB.instance))
				{
					OnVanillaPrefabs();
				}
				ServerHandshake.Tick();
				CurtainPieces.UpdateGate(_allowRemote.Value, ((BaseUnityPlugin)this).Logger);
			}
			if (!CurtainAssets.Headless)
			{
				HandleResizeKeys();
			}
		}

		private static void HandleResizeKeys()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || Typing())
			{
				return;
			}
			float num = (Input.GetKeyDown(CurtainsConfig.Wider) ? 0.25f : (Input.GetKeyDown(CurtainsConfig.Narrower) ? (-0.25f) : 0f));
			if (num == 0f)
			{
				return;
			}
			GameObject hoverObject = ((Humanoid)localPlayer).GetHoverObject();
			CurtainControl curtainControl = (Object.op_Implicit((Object)(object)hoverObject) ? hoverObject.GetComponentInParent<CurtainControl>() : null);
			if (Object.op_Implicit((Object)(object)curtainControl))
			{
				bool flag = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
				curtainControl.TryResize(flag ? 0f : num, flag ? num : 0f, out var message);
				if (message != null)
				{
					((Character)localPlayer).Message((MessageType)1, message, 0, (Sprite)null, false);
				}
			}
		}

		private static bool Typing()
		{
			if ((!Object.op_Implicit((Object)(object)Chat.instance) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Menu.IsVisible())
			{
				if (Object.op_Implicit((Object)(object)InventoryGui.instance))
				{
					return InventoryGui.IsVisible();
				}
				return false;
			}
			return true;
		}
	}
	internal static class ServerHandshake
	{
		private const string Ping = "CogaCurtains_Ping";

		private const string Pong = "CogaCurtains_Pong";

		private const string Hello = "CogaCurtains_Hello";

		private const string Pieces = "CogaCurtains_Pieces";

		private static ZRoutedRpc _registeredOn;

		private static float _nextPing;

		private static HashSet<int> _serverPieces;

		private static bool _serverAnswered;

		public static Func<IEnumerable<string>> LocalPieces;

		public static int State { get; private set; }

		public static bool ServerHasMod
		{
			get
			{
				if (!IsServer)
				{
					return _serverAnswered;
				}
				return true;
			}
		}

		private static bool IsServer
		{
			get
			{
				if (Object.op_Implicit((Object)(object)ZNet.instance))
				{
					return ZNet.instance.IsServer();
				}
				return false;
			}
		}

		public static bool Allows(string prefab, bool firstRelease)
		{
			if (IsServer)
			{
				return true;
			}
			if (_serverPieces != null)
			{
				return _serverPieces.Contains(StringExtensionMethods.GetStableHashCode(prefab));
			}
			return _serverAnswered && firstRelease;
		}

		public static void Tick()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance == null || !Object.op_Implicit((Object)(object)ZNet.instance))
			{
				if (_registeredOn != null || _serverAnswered)
				{
					Reset();
				}
				_registeredOn = null;
				return;
			}
			if (_registeredOn != instance)
			{
				Unregister(instance);
				instance.Register("CogaCurtains_Ping", (Action<long>)OnPing);
				instance.Register("CogaCurtains_Pong", (Action<long>)OnPong);
				instance.Register("CogaCurtains_Hello", (Action<long>)OnHello);
				instance.Register<ZPackage>("CogaCurtains_Pieces", (Action<long, ZPackage>)OnPieces);
				_registeredOn = instance;
				Reset();
				_nextPing = 0f;
			}
			if (IsServer || _serverPieces != null || !(Time.unscaledTime >= _nextPing))
			{
				return;
			}
			_nextPing = Time.unscaledTime + (_serverAnswered ? 15f : 5f);
			ZNetPeer serverPeer = ZNet.instance.GetServerPeer();
			if (serverPeer != null)
			{
				instance.InvokeRoutedRPC(serverPeer.m_uid, "CogaCurtains_Hello", Array.Empty<object>());
				if (!_serverAnswered)
				{
					instance.InvokeRoutedRPC(serverPeer.m_uid, "CogaCurtains_Ping", Array.Empty<object>());
				}
			}
		}

		public static void Shutdown()
		{
			if (_registeredOn != null)
			{
				Unregister(_registeredOn);
			}
			_registeredOn = null;
			Reset();
		}

		private static void Reset()
		{
			_serverAnswered = false;
			_serverPieces = null;
			State++;
		}

		private static void OnPing(long sender)
		{
			if (IsServer)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(sender, "CogaCurtains_Pong", Array.Empty<object>());
			}
		}

		private static void OnHello(long sender)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			if (!IsServer || LocalPieces == null)
			{
				return;
			}
			List<string> list = new List<string>(LocalPieces());
			ZPackage val = new ZPackage();
			val.Write(list.Count);
			foreach (string item in list)
			{
				val.Write(StringExtensionMethods.GetStableHashCode(item));
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, "CogaCurtains_Pieces", new object[1] { val });
		}

		private static void OnPong(long sender)
		{
			if (!_serverAnswered)
			{
				_serverAnswered = true;
				State++;
			}
		}

		private static void OnPieces(long sender, ZPackage pkg)
		{
			int num = pkg.ReadInt();
			HashSet<int> hashSet = new HashSet<int>();
			for (int i = 0; i < num; i++)
			{
				hashSet.Add(pkg.ReadInt());
			}
			_serverPieces = hashSet;
			_serverAnswered = true;
			State++;
		}

		private static void Unregister(ZRoutedRpc rpc)
		{
			if (AccessTools.Field(typeof(ZRoutedRpc), "m_functions")?.GetValue(rpc) is IDictionary dictionary)
			{
				string[] array = new string[4] { "CogaCurtains_Ping", "CogaCurtains_Pong", "CogaCurtains_Hello", "CogaCurtains_Pieces" };
				foreach (string text in array)
				{
					dictionary.Remove(StringExtensionMethods.GetStableHashCode(text));
				}
			}
		}
	}
}
namespace CogaCurtains.Procedural
{
	public sealed class Drape
	{
		public float Anchor;

		public float Width;

		public bool FromLeft = true;

		public float Top = 2.73f;

		public float Bottom = 0.08f;

		public Col Base;

		public Col Sheen;

		public float Gloss = 60f;

		public float Diffuse = 1f;

		public float Opacity = 1f;

		public float Folds = 7f;

		public float Depth = 0.11f;

		public float TieV = -1f;

		public float TieWidth = 1f;

		public float Flare = 0.12f;

		public int Seed = 1;

		public bool Embroidery;

		public bool RibbonBow;

		public int Lace;

		public Col Ribbon = Col.Hex("D6C3A2");
	}
	public sealed class Room
	{
		public bool Night = true;

		public bool Bright;
	}
	public static class DrapeRender
	{
		private const float WX = 4f;

		private const float WY = 3f;

		private const float WinX0 = 1.15f;

		private const float WinX1 = 2.85f;

		private const float WinY0 = 0.95f;

		private const float WinY1 = 2.5f;

		public const float EmbroideryTile = 1f;

		public const int TexelsPerMeter = 32;

		public const int LaceTexelsPerMeter = 64;

		private const int FloralTile = 64;

		private const int FloralHem = 16;

		private static readonly (float X, float Y, float R)[] Roses = new(float, float, float)[2]
		{
			(17f, 45f, 10f),
			(49f, 13f, 9f)
		};

		private static readonly (float X, float Y, float R)[] Flowers = new(float, float, float)[5]
		{
			(50f, 41f, 4.8f),
			(34f, 28f, 4.2f),
			(4f, 20f, 4.2f),
			(31f, 61f, 4.4f),
			(62f, 33f, 3.6f)
		};

		private static readonly (float X, float Y, float Ang, float Len, float W)[] Leaves =