Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CogaCurtains v0.2.1
plugins/CogaCurtains.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
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 =