Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of SofaMod v1.3.0
SofaMod.dll
Decompiled 2 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.Json; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne; using Il2CppScheduleOne.Building; using Il2CppScheduleOne.Core.Items.Framework; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Dialogue; using Il2CppScheduleOne.EntityFramework; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.ObjectScripts; using Il2CppScheduleOne.Tiles; using Il2CppScheduleOne.UI.Shop; using Il2CppSystem.Collections.Generic; using MelonLoader; using Microsoft.CodeAnalysis; using SofaMod; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(Core), "SofaMod", "1.3.0", "Nicolassut", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("SofaMod")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SofaMod")] [assembly: AssemblyTitle("SofaMod")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace SofaMod { internal class FurnitureItemSpec { public string ID = ""; public string DisplayName = ""; public float Price = 800f; public string Description = ""; public string GlbFilename = ""; public string IconFilename = ""; public string MeshGOName = "Mesh"; public float Scale = 0.7125f; public Vector3 LocalEuler = Vector3.zero; public Mesh? Mesh; public List<GlbMaterialInfo> GlbMaterials = new List<GlbMaterialInfo>(); public Material[]? CachedMaterials; public float DonorFloorY; public StorableItemDefinition? Definition; } public class Core : MelonMod { internal static readonly FurnitureItemSpec Sofa = new FurnitureItemSpec { ID = "sofa", DisplayName = "Sofa", Price = 600f, Description = "A stylish sofa. Place it in your property.", GlbFilename = "vintage_sofa.glb", IconFilename = "sofa_icon.png", MeshGOName = "SofaMesh" }; internal static readonly FurnitureItemSpec FancySofa = new FurnitureItemSpec { ID = "fancy_sofa", DisplayName = "Fancy Sofa", Price = 3000f, Description = "A luxurious tartan-upholstered sofa, hand-finished with deep cushions in rich indigo and navy tones. A centrepiece worthy of any refined estate.", GlbFilename = "sofa.glb", IconFilename = "fancysofa.png", MeshGOName = "FancySofaMesh", LocalEuler = new Vector3(0f, 90f, 0f), Scale = 1.3225f }; internal static readonly HashSet<string> OwnedIDs = new HashSet<string> { "sofa", "fancy_sofa" }; internal static Registry? RegInstance; public override void OnInitializeMelon() { ((MelonBase)this).LoggerInstance.Msg("SofaMod loaded."); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { if (!(sceneName != "Main")) { if ((Object)(object)RegInstance != (Object)null) { ReRegister(Sofa); ReRegister(FancySofa); } MelonCoroutines.Start(InjectIntoShops()); } } private static void ReRegister(FurnitureItemSpec spec) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown if ((Object)(object)spec.Definition == (Object)null || (Object)(object)RegInstance == (Object)null) { return; } try { RegInstance.AddToRegistry((ItemDefinition)(object)spec.Definition); } catch { } try { ItemRegister val = new ItemRegister(); val.ID = spec.ID; val.Definition = ((Il2CppObjectBase)spec.Definition).TryCast<ItemDefinition>(); RegInstance.AddToItemDictionary(val); MelonLogger.Msg("[SofaMod] " + spec.ID + " re-registered for scene."); } catch (Exception ex) { MelonLogger.Warning("[SofaMod] " + spec.ID + " re-registration failed: " + ex.Message); } } private static IEnumerator InjectIntoShops() { MelonLogger.Msg($"[SofaMod] InjectIntoShops coroutine started (cap {20} x {1.5f:F1}s)."); int totalSofa = 0; int totalFancy = 0; int attempt = 0; yield return null; while (attempt < 20) { attempt++; bool usedFallback; ShopInterface[] allShops = GetAllShops(out usedFallback); int num = ((allShops != null) ? allShops.Length : 0); int num2 = 0; int num3 = 0; int num4 = 0; StringBuilder stringBuilder = new StringBuilder(); if (allShops != null) { for (int i = 0; i < allShops.Length; i++) { ShopInterface val = allShops[i]; if ((Object)(object)val == (Object)null) { continue; } GameObject gameObject = ((Component)val).gameObject; string text = ((gameObject != null) ? ((Object)gameObject).name : null) ?? "?"; if (i > 0) { stringBuilder.Append(", "); } stringBuilder.Append(text); if (text.IndexOf("hardware", StringComparison.OrdinalIgnoreCase) >= 0) { num2++; } if (text.IndexOf("boutique", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("bleuball", StringComparison.OrdinalIgnoreCase) >= 0) { num3++; } if (val.Listings == null) { continue; } for (int j = 0; j < val.Listings.Count; j++) { ShopListing obj = val.Listings[j]; object obj2; if (obj == null) { obj2 = null; } else { StorableItemDefinition item = obj.Item; obj2 = ((item != null) ? ((BaseItemDefinition)item).ID : null); } if ((string?)obj2 == "bed") { num4++; break; } } } } if (num == 0) { if (attempt == 1 || attempt % 5 == 0 || attempt == 20) { MelonLogger.Msg($"[SofaMod] Attempt {attempt}/{20}: source={(usedFallback ? "FindObjectsOfType" : "AllShops")} returned 0 shop(s) (likely client-side network sync); retrying in {1.5f:F1}s."); } yield return (object)new WaitForSeconds(1.5f); continue; } int num5 = 0; int num6 = 0; ShopInterface[] array = allShops; foreach (ShopInterface val2 in array) { if ((Object)(object)val2 == (Object)null || val2.Listings == null) { continue; } GameObject gameObject2 = ((Component)val2).gameObject; string text2 = ((gameObject2 != null) ? ((Object)gameObject2).name : null) ?? "?"; string shopName = ""; try { shopName = val2.ShopName ?? ""; } catch { } bool flag = false; bool flag2 = false; bool flag3 = false; for (int l = 0; l < val2.Listings.Count; l++) { ShopListing obj4 = val2.Listings[l]; object obj5; if (obj4 == null) { obj5 = null; } else { StorableItemDefinition item2 = obj4.Item; obj5 = ((item2 != null) ? ((BaseItemDefinition)item2).ID : null); } if ((string?)obj5 == "bed") { flag = true; } if ((string?)obj5 == "sofa") { flag2 = true; } if ((string?)obj5 == "fancy_sofa") { flag3 = true; } } bool flag4 = text2.IndexOf("hardware", StringComparison.OrdinalIgnoreCase) >= 0; if (flag && !flag2 && flag4 && (Object)(object)Sofa.Definition != (Object)null && AppendListing(val2, Sofa.Definition, Sofa.ID, Sofa.Price)) { num5++; } if (!flag3 && (Object)(object)FancySofa.Definition != (Object)null && LooksLikeFancyFurnitureStore(text2, shopName) && AppendListing(val2, FancySofa.Definition, FancySofa.ID, FancySofa.Price)) { num6++; } } totalSofa += num5; totalFancy += num6; bool num7 = totalSofa > 0 && totalFancy > 0; if (!num7 && (attempt == 1 || attempt % 5 == 0 || attempt == 20)) { MelonLogger.Msg($"[SofaMod] Attempt {attempt}/{20}: source={(usedFallback ? "FindObjectsOfType" : "AllShops")} shops={num} (hardware={num2}, boutique={num3}, bedSellers={num4}) injected_this_pass(sofa={num5}, fancy={num6}); shops=[{stringBuilder}]"); } if (num7) { MelonLogger.Msg($"[SofaMod] Shop injection complete: Sofa into {totalSofa} shop(s), Fancy Sofa into {totalFancy} shop(s) (attempt {attempt}/{20}, source={(usedFallback ? "FindObjectsOfType" : "AllShops")})."); yield break; } yield return (object)new WaitForSeconds(1.5f); } MelonLogger.Warning($"[SofaMod] Shop injection gave up after {20} attempts (~{30f:F0}s). Final: Sofa into {totalSofa} shop(s), Fancy Sofa into {totalFancy} shop(s). Possible causes: " + "MP client never received scene replication, network was unusually slow, or the donor (bed) / boutique is missing from the scene. Check the per-attempt diagnostic lines above for shop discovery state."); } private static ShopInterface[] GetAllShops(out bool usedFallback) { usedFallback = false; try { List<ShopInterface> allShops = ShopInterface.AllShops; if (allShops != null && allShops.Count > 0) { ShopInterface[] array = (ShopInterface[])(object)new ShopInterface[allShops.Count]; for (int i = 0; i < allShops.Count; i++) { array[i] = allShops[i]; } return array; } } catch { } usedFallback = true; return Il2CppArrayBase<ShopInterface>.op_Implicit(Object.FindObjectsOfType<ShopInterface>()); } private static bool AppendListing(ShopInterface shop, StorableItemDefinition def, string id, float price) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown try { ShopListing val = new ShopListing(); val.Item = def; val.name = id; val.OverridePrice = true; val.OverriddenPrice = price; val.CurrentStock = 999; val.CanBeDelivered = false; shop.Listings.Add(val); shop.CreateListingUI(val); DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(39, 3); defaultInterpolatedStringHandler.AppendLiteral("[SofaMod] "); defaultInterpolatedStringHandler.AppendFormatted(id); defaultInterpolatedStringHandler.AppendLiteral(" appended to "); GameObject gameObject = ((Component)shop).gameObject; defaultInterpolatedStringHandler.AppendFormatted(((gameObject != null) ? ((Object)gameObject).name : null) ?? "?"); defaultInterpolatedStringHandler.AppendLiteral(" "); defaultInterpolatedStringHandler.AppendLiteral("(now "); defaultInterpolatedStringHandler.AppendFormatted(shop.Listings.Count); defaultInterpolatedStringHandler.AppendLiteral(" listings)"); MelonLogger.Msg(defaultInterpolatedStringHandler.ToStringAndClear()); return true; } catch (Exception ex) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(29, 3); defaultInterpolatedStringHandler.AppendLiteral("[SofaMod] "); defaultInterpolatedStringHandler.AppendFormatted(id); defaultInterpolatedStringHandler.AppendLiteral(" inject failed ("); GameObject gameObject2 = ((Component)shop).gameObject; defaultInterpolatedStringHandler.AppendFormatted(((gameObject2 != null) ? ((Object)gameObject2).name : null) ?? "?"); defaultInterpolatedStringHandler.AppendLiteral("): "); defaultInterpolatedStringHandler.AppendFormatted(ex.Message); MelonLogger.Error(defaultInterpolatedStringHandler.ToStringAndClear()); return false; } } private static bool LooksLikeFancyFurnitureStore(string goName, string shopName) { string text = (goName ?? "").ToLowerInvariant(); string text2 = (shopName ?? "").ToLowerInvariant(); if (!text.Contains("boutique") && !text2.Contains("boutique") && !text.Contains("bleuball")) { return text2.Contains("bleuball"); } return true; } } [HarmonyPatch(typeof(Registry), "Start")] public static class Registry_Start_Patch { private static void Postfix(Registry __instance) { try { List<ItemRegister> itemRegistry = __instance.ItemRegistry; if (itemRegistry == null) { MelonLogger.Error("[SofaMod] ItemRegistry is null"); return; } BuildableItemDefinition val = null; for (int i = 0; i < itemRegistry.Count; i++) { ItemRegister val2 = itemRegistry[i]; if (val2 == null || val2.ID != "bed") { continue; } val = ((Il2CppObjectBase)val2).TryCast<BuildableItemDefinition>(); if ((Object)(object)val == (Object)null) { try { ItemDefinition definition = val2.Definition; val = ((definition != null) ? ((Il2CppObjectBase)definition).TryCast<BuildableItemDefinition>() : null); } catch { } } break; } if ((Object)(object)((val != null) ? val.BuiltItem : null) == (Object)null) { MelonLogger.Error("[SofaMod] Bed not found — cannot create furniture templates."); return; } MelonLogger.Msg("[SofaMod] Using 'bed' as BuiltItem FishNet base (3×5 footprint)."); RegisterFurniture(__instance, val, Core.Sofa); RegisterFurniture(__instance, val, Core.FancySofa); Core.RegInstance = __instance; } catch (Exception ex) { MelonLogger.Error("[SofaMod] Registry patch failed: " + ex); } } private static void RegisterFurniture(Registry registry, BuildableItemDefinition bedDef, FurnitureItemSpec spec) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown try { BuildableItemDefinition val = Object.Instantiate<BuildableItemDefinition>(bedDef); ((Object)val).name = spec.DisplayName; ((BaseItemDefinition)val).ID = spec.ID; ((BaseItemDefinition)val).Name = spec.DisplayName; ((StorableItemDefinition)val).BasePurchasePrice = spec.Price; BaseItemDefinition val2 = ((Il2CppObjectBase)val).TryCast<BaseItemDefinition>(); if ((Object)(object)val2 != (Object)null) { val2.Description = spec.Description; } StorableItemDefinition val3 = ((Il2CppObjectBase)val).TryCast<StorableItemDefinition>(); if ((Object)(object)val3 != (Object)null) { val3.StoredItem = null; } LoadIcon(spec, val2); if ((Object)(object)spec.Mesh == (Object)null) { LoadAssetsForSpec(bedDef, spec); } val.BuiltItem = bedDef.BuiltItem; registry.AddToRegistry((ItemDefinition)(object)val); try { ItemRegister val4 = new ItemRegister(); val4.ID = spec.ID; val4.Definition = ((Il2CppObjectBase)val).TryCast<ItemDefinition>(); registry.AddToItemDictionary(val4); } catch (Exception ex) { MelonLogger.Warning("[SofaMod] " + spec.ID + " AddToItemDictionary failed (non-fatal): " + ex.Message); } spec.Definition = ((Il2CppObjectBase)val).TryCast<StorableItemDefinition>(); MelonLogger.Msg("[SofaMod] " + spec.ID + " registered."); } catch (Exception ex2) { MelonLogger.Error("[SofaMod] " + spec.ID + " registration failed: " + ex2); } } private static void LoadIcon(FurnitureItemSpec spec, BaseItemDefinition? asBase) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_00b3: 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_00cc: Expected O, but got Unknown try { string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), spec.IconFilename); if (!File.Exists(path)) { MelonLogger.Warning("[SofaMod] " + spec.ID + " icon not found: " + spec.IconFilename); return; } byte[] array = File.ReadAllBytes(path); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, Il2CppStructArray<byte>.op_Implicit(array)); float num = 0.04f; float num2 = (float)((Texture)val).width * num; float num3 = (float)((Texture)val).height * num; float num4 = (float)((Texture)val).width * (1f - 2f * num); float num5 = (float)((Texture)val).height * (1f - 2f * num); Sprite icon = Sprite.Create(val, new Rect(num2, num3, num4, num5), new Vector2(0.5f, 0.5f)); if ((Object)(object)asBase != (Object)null) { asBase.Icon = icon; } MelonLogger.Msg("[SofaMod] " + spec.ID + " icon loaded: " + spec.IconFilename); } catch (Exception ex) { MelonLogger.Warning("[SofaMod] " + spec.ID + " icon load failed: " + ex.Message); } } private static void LoadAssetsForSpec(BuildableItemDefinition bedDef, FurnitureItemSpec spec) { //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Expected O, but got Unknown //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_0427: Unknown result type (might be due to invalid IL or missing references) //IL_042c: Unknown result type (might be due to invalid IL or missing references) //IL_0433: Unknown result type (might be due to invalid IL or missing references) //IL_0439: Expected O, but got Unknown //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_033b: 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_037c: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0133: 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_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: 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_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) GlbLoadResult glbLoadResult = GlbLoader.Load(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), spec.GlbFilename)); spec.Mesh = glbLoadResult.Mesh; spec.GlbMaterials = glbLoadResult.Materials ?? new List<GlbMaterialInfo>(); if ((Object)(object)spec.Mesh != (Object)null) { MelonLogger.Msg($"[SofaMod] {spec.ID} GLB loaded — {spec.Mesh.vertexCount} verts, {spec.GlbMaterials.Count} material(s)."); } float num = 0f; try { GameObject gameObject = ((Component)bedDef.BuiltItem).gameObject; foreach (MeshRenderer componentsInChild in gameObject.GetComponentsInChildren<MeshRenderer>(true)) { MeshFilter val = ((componentsInChild != null) ? ((Component)componentsInChild).GetComponent<MeshFilter>() : null); if (!((Object)(object)((val != null) ? val.sharedMesh : null) == (Object)null)) { Bounds bounds = val.sharedMesh.bounds; Vector3 val2 = ((Component)componentsInChild).transform.TransformPoint(new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).min.y, ((Bounds)(ref bounds)).center.z)); Vector3 val3 = gameObject.transform.InverseTransformPoint(val2); if (val3.y < num) { num = val3.y; } } } } catch (Exception ex) { MelonLogger.Warning("[SofaMod] " + spec.ID + " donor floor scan failed: " + ex.Message); } spec.DonorFloorY = num; MelonLogger.Msg($"[SofaMod] {spec.ID} donor floor reference Y = {num:F4}"); Shader val4 = Shader.Find("Universal Render Pipeline/Lit"); if ((Object)(object)val4 == (Object)null) { MelonLogger.Warning("[SofaMod] " + spec.ID + ": URP Lit shader not found — using Unity default materials."); spec.CachedMaterials = null; return; } if (spec.GlbMaterials.Count == 0) { MelonLogger.Warning("[SofaMod] " + spec.ID + ": no GLB materials."); spec.CachedMaterials = null; return; } Material[] array = (Material[])(object)new Material[spec.GlbMaterials.Count]; for (int i = 0; i < spec.GlbMaterials.Count; i++) { GlbMaterialInfo glbMaterialInfo = spec.GlbMaterials[i]; Material val5 = new Material(val4); val5.SetFloat("_Metallic", 0f); val5.SetFloat("_Smoothness", 0.15f); if ((Object)(object)glbMaterialInfo.BaseColorTexture != (Object)null) { val5.SetTexture("_BaseMap", (Texture)(object)glbMaterialInfo.BaseColorTexture); val5.SetTexture("_MainTex", (Texture)(object)glbMaterialInfo.BaseColorTexture); } Color baseColorFactor = glbMaterialInfo.BaseColorFactor; Color val6 = ((baseColorFactor.r > 0.95f && baseColorFactor.g > 0.95f && baseColorFactor.b > 0.95f) ? Color.white : baseColorFactor); if ((Object)(object)glbMaterialInfo.BaseColorTexture == (Object)null && val6 == Color.white) { ((Color)(ref val6))..ctor(0.72f, 0.58f, 0.44f, 1f); } val5.SetColor("_BaseColor", val6); val5.SetColor("_Color", val6); val5.color = val6; Object.DontDestroyOnLoad((Object)(object)val5); array[i] = val5; } spec.CachedMaterials = array; MelonLogger.Msg($"[SofaMod] {spec.ID} assets loaded ({array.Length} cached material(s))."); try { GameObject val7 = new GameObject("SofaMod_AssetHolder_" + spec.ID); val7.SetActive(false); Object.DontDestroyOnLoad((Object)val7); val7.AddComponent<MeshFilter>().sharedMesh = spec.Mesh; MeshRenderer val8 = val7.AddComponent<MeshRenderer>(); if (spec.CachedMaterials != null && spec.CachedMaterials.Length != 0) { ((Renderer)val8).sharedMaterials = Il2CppReferenceArray<Material>.op_Implicit(spec.CachedMaterials); } MelonLogger.Msg("[SofaMod] " + spec.ID + " asset holder created (DontDestroyOnLoad)."); } catch (Exception ex2) { MelonLogger.Warning("[SofaMod] " + spec.ID + " asset holder creation failed: " + ex2.Message); } } } internal static class SofaVisuals { public static void Apply(GameObject? target, FurnitureItemSpec spec) { //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_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_0207: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_021e: 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_0225: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0256: 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_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0268: 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_0275: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: 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_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0323: 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_032b: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_0352: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Unknown result type (might be due to invalid IL or missing references) //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_03d0: Unknown result type (might be due to invalid IL or missing references) //IL_03da: Unknown result type (might be due to invalid IL or missing references) //IL_03e0: Unknown result type (might be due to invalid IL or missing references) //IL_03e6: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Unknown result type (might be due to invalid IL or missing references) //IL_03fc: Unknown result type (might be due to invalid IL or missing references) //IL_0406: Unknown result type (might be due to invalid IL or missing references) //IL_0410: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target == (Object)null || (Object)(object)spec.Mesh == (Object)null) { MelonLogger.Warning($"[SofaMod] {spec.ID} Apply skipped: target={(((Object)(object)target == (Object)null) ? "null" : ((Object)target).name)}, mesh={(((Object)(object)spec.Mesh == (Object)null) ? "null" : "ok")}"); } else { if ((Object)(object)target.transform.Find(spec.MeshGOName) != (Object)null) { return; } try { foreach (MeshRenderer componentsInChild in target.GetComponentsInChildren<MeshRenderer>(true)) { if ((Object)(object)componentsInChild != (Object)null) { ((Renderer)componentsInChild).enabled = false; } } foreach (SkinnedMeshRenderer componentsInChild2 in target.GetComponentsInChildren<SkinnedMeshRenderer>(true)) { if ((Object)(object)componentsInChild2 != (Object)null) { ((Renderer)componentsInChild2).enabled = false; } } foreach (Light componentsInChild3 in target.GetComponentsInChildren<Light>(true)) { if ((Object)(object)componentsInChild3 != (Object)null) { ((Behaviour)componentsInChild3).enabled = false; } } } catch (Exception ex) { MelonLogger.Warning("[SofaMod] Renderer disable threw: " + ex.Message); } try { Il2CppArrayBase<FootprintTile> componentsInChildren = target.GetComponentsInChildren<FootprintTile>(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { componentsInChildren[i].RequiredOffset = 0f; } } } catch { } float scale = spec.Scale; Quaternion val = Quaternion.Euler(spec.LocalEuler); Bounds bounds = spec.Mesh.bounds; Vector3 min = ((Bounds)(ref bounds)).min; Vector3 max = ((Bounds)(ref bounds)).max; Vector3[] array = (Vector3[])(object)new Vector3[8] { val * new Vector3(min.x, min.y, min.z), val * new Vector3(max.x, min.y, min.z), val * new Vector3(min.x, max.y, min.z), val * new Vector3(max.x, max.y, min.z), val * new Vector3(min.x, min.y, max.z), val * new Vector3(max.x, min.y, max.z), val * new Vector3(min.x, max.y, max.z), val * new Vector3(max.x, max.y, max.z) }; Vector3 val2 = array[0]; Vector3 val3 = array[0]; for (int j = 1; j < array.Length; j++) { val2 = Vector3.Min(val2, array[j]); val3 = Vector3.Max(val3, array[j]); } Vector3 val4 = (val2 + val3) * 0.5f; GameObject val5 = new GameObject(spec.MeshGOName); val5.transform.SetParent(target.transform, false); val5.transform.localScale = new Vector3(scale, scale, scale); val5.transform.localRotation = val; val5.transform.localPosition = new Vector3((0f - val4.x) * scale, spec.DonorFloorY - val2.y * scale, (0f - val4.z) * scale); val5.AddComponent<MeshFilter>().sharedMesh = spec.Mesh; MeshRenderer val6 = val5.AddComponent<MeshRenderer>(); if (spec.CachedMaterials != null && spec.CachedMaterials.Length != 0) { ((Renderer)val6).sharedMaterials = Il2CppReferenceArray<Material>.op_Implicit(spec.CachedMaterials); } } } public static FurnitureItemSpec? SpecForID(string? id) { if (id == null) { return null; } if (id == Core.Sofa.ID) { return Core.Sofa; } if (id == Core.FancySofa.ID) { return Core.FancySofa; } return null; } } [HarmonyPatch(typeof(BuildStart_Grid), "StartBuilding")] public static class BuildStart_Grid_StartBuilding_Patch { private static void Postfix(BuildStart_Grid __instance, ItemInstance itemInstance) { try { object obj; if (itemInstance == null) { obj = null; } else { ItemDefinition definition = itemInstance.Definition; obj = ((definition != null) ? ((BaseItemDefinition)definition).ID : null); } string text = (string)obj; FurnitureItemSpec furnitureItemSpec = SofaVisuals.SpecForID(text); if (furnitureItemSpec == null) { return; } GridItem ghostModelClass = __instance.ghostModelClass; if ((Object)(object)ghostModelClass == (Object)null) { MelonLogger.Warning("[SofaMod] StartBuilding(" + text + "): ghostModelClass is NULL."); return; } SofaVisuals.Apply(((Component)ghostModelClass).gameObject, furnitureItemSpec); if (!((Component)ghostModelClass).gameObject.activeSelf) { ((Component)ghostModelClass).gameObject.SetActive(true); } BuildManager instance = NetworkSingleton<BuildManager>.Instance; if (!((Object)(object)instance != (Object)null) || !((Object)(object)instance.ghostMaterial_White != (Object)null)) { return; } instance.ApplyMaterial(((Component)ghostModelClass).gameObject, instance.ghostMaterial_White, true); try { ghostModelClass.CalculateFootprintTileIntersections(); ghostModelClass.SetFootprintTileVisiblity(true); } catch (Exception ex) { MelonLogger.Warning("[SofaMod] Footprint calc failed: " + ex.Message); } } catch (Exception ex2) { MelonLogger.Warning("[SofaMod] StartBuilding Postfix error: " + ex2.Message); } } } [HarmonyPatch(typeof(GridItem), "SetFootprintTileVisiblity")] public static class GridItem_SetFootprintTileVisiblity_Patch { private static Exception? Finalizer(Exception? __exception) { if (__exception != null) { MelonLogger.Warning("[SofaMod] SetFootprintTileVisiblity suppressed: " + __exception.GetType().Name); } return null; } } [HarmonyPatch(typeof(BuildManager), "StopBuilding")] public static class BuildManager_StopBuilding_Patch { private static Exception? Finalizer(Exception? __exception) { if (__exception != null) { MelonLogger.Warning("[SofaMod] StopBuilding exception suppressed: " + __exception.GetType().Name + ": " + __exception.Message); } return null; } } [HarmonyPatch(typeof(ShopInterface), "HandoverItems")] public static class ShopInterface_HandoverItems_Patch { private static Exception? Finalizer(Exception? __exception) { if (__exception != null) { MelonLogger.Error("[SofaMod] HandoverItems threw " + __exception.GetType().Name + ": " + __exception.Message); } return null; } } [HarmonyPatch(typeof(DialogueController_Dan), "ModifyDialogueText")] public static class DialogueController_Dan_Patch { private static Exception? Finalizer(string dialogueText, ref string __result, Exception? __exception) { if (__exception != null) { __result = dialogueText ?? ""; MelonLogger.Warning("[SofaMod] ModifyDialogueText threw (" + __exception.GetType().Name + "); falling back to unmodified text."); } return null; } } [HarmonyPatch(typeof(PlaceableStorageEntity), "InitializeGridItem")] public static class PlaceableStorageEntity_InitializeGridItem_Patch { private static void Postfix(PlaceableStorageEntity __instance, ItemInstance instance) { try { object id; if (instance == null) { id = null; } else { ItemDefinition definition = instance.Definition; id = ((definition != null) ? ((BaseItemDefinition)definition).ID : null); } FurnitureItemSpec furnitureItemSpec = SofaVisuals.SpecForID((string?)id); if (furnitureItemSpec != null) { SofaVisuals.Apply((__instance != null) ? ((Component)__instance).gameObject : null, furnitureItemSpec); } } catch (Exception ex) { MelonLogger.Warning("[SofaMod] PSE.InitializeGridItem Postfix failed: " + ex.Message); } } } internal struct GlbMaterialInfo { public Texture2D? BaseColorTexture; public Color BaseColorFactor; public string Name; } internal struct GlbLoadResult { public Mesh? Mesh; public List<GlbMaterialInfo> Materials; } internal static class GlbLoader { internal static GlbLoadResult Load(string path) { if (!File.Exists(path)) { MelonLogger.Warning("[SofaMod] GLB not found: " + path); return default(GlbLoadResult); } try { return Parse(File.ReadAllBytes(path)); } catch (Exception ex) { MelonLogger.Error("[SofaMod] GLB parse failed: " + ex); return default(GlbLoadResult); } } private static GlbLoadResult Parse(byte[] data) { //IL_013e: 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_0218: Expected O, but got Unknown //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_0468: Unknown result type (might be due to invalid IL or missing references) //IL_048c: Unknown result type (might be due to invalid IL or missing references) //IL_058f: Unknown result type (might be due to invalid IL or missing references) //IL_05b3: Unknown result type (might be due to invalid IL or missing references) //IL_05d7: Unknown result type (might be due to invalid IL or missing references) //IL_05fb: Unknown result type (might be due to invalid IL or missing references) if (BitConverter.ToUInt32(data, 0) != 1179937895) { throw new InvalidDataException("Not a GLB file"); } int num = (int)BitConverter.ToUInt32(data, 12); string @string = Encoding.UTF8.GetString(data, 20, num); int binStart = 20 + num + 8; List<Vector3> list = new List<Vector3>(); List<Vector3> list2 = new List<Vector3>(); List<Vector2> list3 = new List<Vector2>(); Dictionary<int, List<int>> dictionary = new Dictionary<int, List<int>>(); int baseVert = 0; List<GlbMaterialInfo> list4 = new List<GlbMaterialInfo>(); using JsonDocument jsonDocument = JsonDocument.Parse(@string); JsonElement rootElement = jsonDocument.RootElement; JsonElement property = rootElement.GetProperty("accessors"); JsonElement property2 = rootElement.GetProperty("bufferViews"); JsonElement property3 = rootElement.GetProperty("meshes"); JsonElement property4 = rootElement.GetProperty("nodes"); JsonElement value; int index = (rootElement.TryGetProperty("scene", out value) ? value.GetInt32() : 0); foreach (int item in from e in rootElement.GetProperty("scenes")[index].GetProperty("nodes").EnumerateArray() select e.GetInt32()) { TraverseNode(data, binStart, property4, property3, property, property2, item, Matrix4x4.identity, list, list2, list3, dictionary, ref baseVert); } foreach (List<int> value4 in dictionary.Values) { for (int i = 0; i < value4.Count; i += 3) { int value2 = value4[i + 1]; value4[i + 1] = value4[i + 2]; value4[i + 2] = value2; } } List<int> list5 = dictionary.Keys.OrderBy((int k) => k).ToList(); Mesh val = new Mesh(); val.indexFormat = (IndexFormat)1; val.vertices = Il2CppStructArray<Vector3>.op_Implicit(list.ToArray()); val.normals = Il2CppStructArray<Vector3>.op_Implicit(list2.ToArray()); if (list3.Count == list.Count) { val.uv = Il2CppStructArray<Vector2>.op_Implicit(list3.ToArray()); } val.subMeshCount = list5.Count; int num2 = 0; for (int j = 0; j < list5.Count; j++) { int num3 = list5[j]; int[] array = dictionary[num3].ToArray(); val.SetTriangles(Il2CppStructArray<int>.op_Implicit(array), j); list4.Add(ExtractMaterialAt(rootElement, data, binStart, num3)); num2 += array.Length / 3; } val.RecalculateBounds(); Bounds bounds = val.bounds; MelonLogger.Msg($"[SofaMod] GLB loaded — {list.Count} verts, {num2} tris, {list5.Count} submesh(es)/material(s), size {((Bounds)(ref bounds)).size.x:F3}×{((Bounds)(ref bounds)).size.y:F3}×{((Bounds)(ref bounds)).size.z:F3}, center ({((Bounds)(ref bounds)).center.x:F3},{((Bounds)(ref bounds)).center.y:F3},{((Bounds)(ref bounds)).center.z:F3}), min ({((Bounds)(ref bounds)).min.x:F3},{((Bounds)(ref bounds)).min.y:F3},{((Bounds)(ref bounds)).min.z:F3})"); for (int l = 0; l < list4.Count; l++) { GlbMaterialInfo glbMaterialInfo = list4[l]; string value3 = (((Object)(object)glbMaterialInfo.BaseColorTexture != (Object)null) ? $"{((Texture)glbMaterialInfo.BaseColorTexture).width}×{((Texture)glbMaterialInfo.BaseColorTexture).height}" : "no texture"); MelonLogger.Msg($"[SofaMod] submesh[{l}] '{glbMaterialInfo.Name}' tex={value3} factor=({glbMaterialInfo.BaseColorFactor.r:F2},{glbMaterialInfo.BaseColorFactor.g:F2},{glbMaterialInfo.BaseColorFactor.b:F2},{glbMaterialInfo.BaseColorFactor.a:F2})"); } GlbLoadResult result = default(GlbLoadResult); result.Mesh = val; result.Materials = list4; return result; } private static void TraverseNode(byte[] data, int binStart, JsonElement nodes, JsonElement meshes, JsonElement accessors, JsonElement bufferViews, int nodeIdx, Matrix4x4 parentTransform, List<Vector3> allVerts, List<Vector3> allNorms, List<Vector2> allUVs, Dictionary<int, List<int>> trisByMaterial, ref int baseVert) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) JsonElement node = nodes[nodeIdx]; Matrix4x4 val = GltfNodeMatrix(node); Matrix4x4 parentTransform2 = parentTransform * val; if (node.TryGetProperty("mesh", out var value)) { JsonElement property = meshes[value.GetInt32()].GetProperty("primitives"); for (int i = 0; i < property.GetArrayLength(); i++) { JsonElement jsonElement = property[i]; JsonElement property2 = jsonElement.GetProperty("attributes"); Vector3[] array = ReadVec3(data, binStart, accessors[property2.GetProperty("POSITION").GetInt32()], bufferViews); Vector3[] array2 = null; if (property2.TryGetProperty("NORMAL", out var value2)) { array2 = ReadVec3(data, binStart, accessors[value2.GetInt32()], bufferViews); } Vector2[] array3 = null; if (property2.TryGetProperty("TEXCOORD_0", out var value3)) { array3 = ReadVec2(data, binStart, accessors[value3.GetInt32()], bufferViews); } int[] array4 = ReadIndices(data, binStart, accessors[jsonElement.GetProperty("indices").GetInt32()], bufferViews); for (int j = 0; j < array.Length; j++) { Vector3 val2 = ((Matrix4x4)(ref parentTransform2)).MultiplyPoint3x4(array[j]); array[j] = new Vector3(0f - val2.x, val2.y, val2.z); } if (array2 != null) { for (int k = 0; k < array2.Length; k++) { Vector3 val3 = ((Matrix4x4)(ref parentTransform2)).MultiplyVector(array2[k]); array2[k] = new Vector3(0f - val3.x, val3.y, val3.z); } } JsonElement value4; int key = (jsonElement.TryGetProperty("material", out value4) ? value4.GetInt32() : (-1)); if (!trisByMaterial.TryGetValue(key, out List<int> value5)) { value5 = (trisByMaterial[key] = new List<int>()); } allVerts.AddRange(array); allNorms.AddRange((IEnumerable<Vector3>)(((object)array2) ?? ((object)new Vector3[array.Length]))); allUVs.AddRange((IEnumerable<Vector2>)(((object)array3) ?? ((object)new Vector2[array.Length]))); for (int l = 0; l < array4.Length; l++) { value5.Add(array4[l] + baseVert); } baseVert += array.Length; } } if (!node.TryGetProperty("children", out var value6)) { return; } foreach (JsonElement item in value6.EnumerateArray()) { TraverseNode(data, binStart, nodes, meshes, accessors, bufferViews, item.GetInt32(), parentTransform2, allVerts, allNorms, allUVs, trisByMaterial, ref baseVert); } } private static GlbMaterialInfo ExtractMaterialAt(JsonElement root, byte[] data, int binStart, int matIdx) { //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_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Expected O, but got Unknown GlbMaterialInfo glbMaterialInfo = default(GlbMaterialInfo); glbMaterialInfo.BaseColorFactor = Color.white; glbMaterialInfo.Name = ((matIdx < 0) ? "default" : $"mat{matIdx}"); glbMaterialInfo.BaseColorTexture = null; GlbMaterialInfo result = glbMaterialInfo; try { if (matIdx < 0) { return result; } if (!root.TryGetProperty("materials", out var value) || matIdx >= value.GetArrayLength()) { return result; } JsonElement jsonElement = value[matIdx]; if (jsonElement.TryGetProperty("name", out var value2)) { result.Name = value2.GetString() ?? result.Name; } if (!jsonElement.TryGetProperty("pbrMetallicRoughness", out var value3)) { return result; } if (value3.TryGetProperty("baseColorFactor", out var value4)) { float[] array = (from e in value4.EnumerateArray() select e.GetSingle()).ToArray(); result.BaseColorFactor = (Color)((array.Length >= 4) ? new Color(array[0], array[1], array[2], array[3]) : ((array.Length >= 3) ? new Color(array[0], array[1], array[2]) : Color.white)); } if (!value3.TryGetProperty("baseColorTexture", out var value5)) { return result; } int @int = value5.GetProperty("index").GetInt32(); if (!root.TryGetProperty("textures", out var value6) || @int >= value6.GetArrayLength()) { return result; } if (!value6[@int].TryGetProperty("source", out var value7)) { return result; } int int2 = value7.GetInt32(); if (!root.TryGetProperty("images", out var value8) || int2 >= value8.GetArrayLength()) { return result; } if (!value8[int2].TryGetProperty("bufferView", out var value9)) { return result; } if (!root.TryGetProperty("bufferViews", out var value10)) { return result; } JsonElement jsonElement2 = value10[value9.GetInt32()]; JsonElement value11; int num = (jsonElement2.TryGetProperty("byteOffset", out value11) ? value11.GetInt32() : 0); int int3 = jsonElement2.GetProperty("byteLength").GetInt32(); byte[] array2 = new byte[int3]; Array.Copy(data, binStart + num, array2, 0, int3); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, Il2CppStructArray<byte>.op_Implicit(array2)); result.BaseColorTexture = val; } catch (Exception ex) { MelonLogger.Warning($"[SofaMod] GLB material[{matIdx}] extraction failed: " + ex.Message); } return result; } private static Matrix4x4 GltfNodeMatrix(JsonElement node) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Unknown result type (might be due to invalid IL or missing references) if (node.TryGetProperty("matrix", out var value)) { float[] array = (from e in value.EnumerateArray() select e.GetSingle()).ToArray(); Matrix4x4 result = default(Matrix4x4); ((Matrix4x4)(ref result))[0, 0] = array[0]; ((Matrix4x4)(ref result))[1, 0] = array[1]; ((Matrix4x4)(ref result))[2, 0] = array[2]; ((Matrix4x4)(ref result))[3, 0] = array[3]; ((Matrix4x4)(ref result))[0, 1] = array[4]; ((Matrix4x4)(ref result))[1, 1] = array[5]; ((Matrix4x4)(ref result))[2, 1] = array[6]; ((Matrix4x4)(ref result))[3, 1] = array[7]; ((Matrix4x4)(ref result))[0, 2] = array[8]; ((Matrix4x4)(ref result))[1, 2] = array[9]; ((Matrix4x4)(ref result))[2, 2] = array[10]; ((Matrix4x4)(ref result))[3, 2] = array[11]; ((Matrix4x4)(ref result))[0, 3] = array[12]; ((Matrix4x4)(ref result))[1, 3] = array[13]; ((Matrix4x4)(ref result))[2, 3] = array[14]; ((Matrix4x4)(ref result))[3, 3] = array[15]; return result; } float[] array2 = new float[3]; float[] array3 = new float[4] { 0f, 0f, 0f, 1f }; float[] array4 = new float[3] { 1f, 1f, 1f }; if (node.TryGetProperty("translation", out var value2)) { array2 = (from e in value2.EnumerateArray() select e.GetSingle()).ToArray(); } if (node.TryGetProperty("rotation", out var value3)) { array3 = (from e in value3.EnumerateArray() select e.GetSingle()).ToArray(); } if (node.TryGetProperty("scale", out var value4)) { array4 = (from e in value4.EnumerateArray() select e.GetSingle()).ToArray(); } float num = array3[0]; float num2 = array3[1]; float num3 = array3[2]; float num4 = array3[3]; float num5 = 1f - 2f * (num2 * num2 + num3 * num3); float num6 = 2f * (num * num2 - num3 * num4); float num7 = 2f * (num * num3 + num2 * num4); float num8 = 2f * (num * num2 + num3 * num4); float num9 = 1f - 2f * (num * num + num3 * num3); float num10 = 2f * (num2 * num3 - num * num4); float num11 = 2f * (num * num3 - num2 * num4); float num12 = 2f * (num2 * num3 + num * num4); float num13 = 1f - 2f * (num * num + num2 * num2); Matrix4x4 result2 = default(Matrix4x4); ((Matrix4x4)(ref result2))[0, 0] = num5 * array4[0]; ((Matrix4x4)(ref result2))[0, 1] = num6 * array4[1]; ((Matrix4x4)(ref result2))[0, 2] = num7 * array4[2]; ((Matrix4x4)(ref result2))[0, 3] = array2[0]; ((Matrix4x4)(ref result2))[1, 0] = num8 * array4[0]; ((Matrix4x4)(ref result2))[1, 1] = num9 * array4[1]; ((Matrix4x4)(ref result2))[1, 2] = num10 * array4[2]; ((Matrix4x4)(ref result2))[1, 3] = array2[1]; ((Matrix4x4)(ref result2))[2, 0] = num11 * array4[0]; ((Matrix4x4)(ref result2))[2, 1] = num12 * array4[1]; ((Matrix4x4)(ref result2))[2, 2] = num13 * array4[2]; ((Matrix4x4)(ref result2))[2, 3] = array2[2]; ((Matrix4x4)(ref result2))[3, 0] = 0f; ((Matrix4x4)(ref result2))[3, 1] = 0f; ((Matrix4x4)(ref result2))[3, 2] = 0f; ((Matrix4x4)(ref result2))[3, 3] = 1f; return result2; } private static Vector3[] ReadVec3(byte[] data, int binStart, JsonElement accessor, JsonElement bufferViews) { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) int @int = accessor.GetProperty("count").GetInt32(); int int2 = accessor.GetProperty("bufferView").GetInt32(); JsonElement jsonElement = bufferViews[int2]; JsonElement value; int num = (jsonElement.TryGetProperty("byteOffset", out value) ? value.GetInt32() : 0); JsonElement value2; int num2 = (accessor.TryGetProperty("byteOffset", out value2) ? value2.GetInt32() : 0); JsonElement value3; int num3 = (jsonElement.TryGetProperty("byteStride", out value3) ? value3.GetInt32() : 12); int num4 = binStart + num + num2; Vector3[] array = (Vector3[])(object)new Vector3[@int]; for (int i = 0; i < @int; i++) { int num5 = num4 + i * num3; array[i] = new Vector3(BitConverter.ToSingle(data, num5), BitConverter.ToSingle(data, num5 + 4), BitConverter.ToSingle(data, num5 + 8)); } return array; } private static Vector2[] ReadVec2(byte[] data, int binStart, JsonElement accessor, JsonElement bufferViews) { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) int @int = accessor.GetProperty("count").GetInt32(); int int2 = accessor.GetProperty("bufferView").GetInt32(); JsonElement jsonElement = bufferViews[int2]; JsonElement value; int num = (jsonElement.TryGetProperty("byteOffset", out value) ? value.GetInt32() : 0); JsonElement value2; int num2 = (accessor.TryGetProperty("byteOffset", out value2) ? value2.GetInt32() : 0); JsonElement value3; int num3 = (jsonElement.TryGetProperty("byteStride", out value3) ? value3.GetInt32() : 8); int num4 = binStart + num + num2; Vector2[] array = (Vector2[])(object)new Vector2[@int]; for (int i = 0; i < @int; i++) { int num5 = num4 + i * num3; array[i] = new Vector2(BitConverter.ToSingle(data, num5), 1f - BitConverter.ToSingle(data, num5 + 4)); } return array; } private static int[] ReadIndices(byte[] data, int binStart, JsonElement accessor, JsonElement bufferViews) { int @int = accessor.GetProperty("count").GetInt32(); int int2 = accessor.GetProperty("bufferView").GetInt32(); JsonElement value; int num = (bufferViews[int2].TryGetProperty("byteOffset", out value) ? value.GetInt32() : 0); JsonElement value2; int num2 = (accessor.TryGetProperty("byteOffset", out value2) ? value2.GetInt32() : 0); int int3 = accessor.GetProperty("componentType").GetInt32(); int num3 = binStart + num + num2; int[] array = new int[@int]; switch (int3) { case 5125: { for (int j = 0; j < @int; j++) { array[j] = (int)BitConverter.ToUInt32(data, num3 + j * 4); } break; } case 5123: { for (int k = 0; k < @int; k++) { array[k] = BitConverter.ToUInt16(data, num3 + k * 2); } break; } default: { for (int i = 0; i < @int; i++) { array[i] = data[num3 + i]; } break; } } return array; } } }