using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace HowToNemo { internal static class NemoModel { internal struct Fit { public Quaternion Rot; public float Scale; public Vector3 Centre; public string Describe; } private const string MeshResource = "nemo_mesh.bin"; private const string AtlasResource = "nemo_atlas.png"; private static Vector3[] _pos; private static Vector3[] _nrm; private static Vector2[] _uv; private static int[] _tri; private static Texture2D _atlas; private static bool _tried; private static bool _ok; internal static Texture2D Atlas => _atlas; internal static bool Load() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown if (_tried) { return _ok; } _tried = true; try { ReadMesh(GetResource("nemo_mesh.bin")); byte[] resource = GetResource("nemo_atlas.png"); _atlas = new Texture2D(2, 2, (TextureFormat)4, true, false); if (!ImageConversion.LoadImage(_atlas, resource)) { throw new Exception("atlas PNG failed to decode"); } ((Object)_atlas).name = "NemoAtlas"; ((Texture)_atlas).wrapMode = (TextureWrapMode)1; ((Texture)_atlas).filterMode = (FilterMode)1; _atlas.Apply(true, false); _ok = true; Plugin.Log.LogInfo((object)$"Model loaded: {_pos.Length} verts, {_tri.Length / 3} tris, atlas {((Texture)_atlas).width}x{((Texture)_atlas).height}."); } catch (Exception ex) { Plugin.Log.LogError((object)("Could not load the embedded Nemo assets: " + ex)); _ok = false; } return _ok; } private static byte[] GetResource(string suffix) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = null; string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); foreach (string text2 in manifestResourceNames) { if (text2.EndsWith(suffix, StringComparison.OrdinalIgnoreCase)) { text = text2; break; } } if (text == null) { throw new Exception("embedded resource not found: " + suffix); } using Stream stream = executingAssembly.GetManifestResourceStream(text); using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } private static void ReadMesh(byte[] data) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) using BinaryReader binaryReader = new BinaryReader(new MemoryStream(data)); if (new string(binaryReader.ReadChars(4)) != "NEMO") { throw new Exception("bad mesh magic"); } ushort num = binaryReader.ReadUInt16(); if (num != 1) { throw new Exception("unsupported mesh version " + num); } int num2 = (int)binaryReader.ReadUInt32(); int num3 = (int)binaryReader.ReadUInt32(); _pos = (Vector3[])(object)new Vector3[num2]; _nrm = (Vector3[])(object)new Vector3[num2]; _uv = (Vector2[])(object)new Vector2[num2]; for (int i = 0; i < num2; i++) { _pos[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); _nrm[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); _uv[i] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle()); } _tri = new int[num3]; for (int j = 0; j < num3; j++) { _tri[j] = binaryReader.ReadUInt16(); } } private static Vector3 Axis(int i) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) return (Vector3)(i switch { 1 => Vector3.up, 0 => Vector3.right, _ => Vector3.forward, }); } private static float Comp(Vector3 v, int i) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) return i switch { 1 => v.y, 0 => v.x, _ => v.z, }; } internal static Fit FitTo(Mesh original) { //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_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0226: 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_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0234: 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_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_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: 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_0156: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = original.bounds; Vector3 size = ((Bounds)(ref bounds)).size; int[] array = new int[3] { 0, 1, 2 }; for (int i = 0; i < 2; i++) { for (int j = i + 1; j < 3; j++) { if (Comp(size, array[j]) > Comp(size, array[i])) { int num = array[i]; array[i] = array[j]; array[j] = num; } } } int num2 = array[0]; int num3 = array[1]; int num4 = array[2]; float num5 = 1f; float num6 = 1f; Vector3[] vertices = original.vertices; if (vertices != null && vertices.Length != 0) { double num7 = 0.0; for (int k = 0; k < vertices.Length; k++) { num7 += (double)Comp(vertices[k], num2); } num5 = ((num7 / (double)vertices.Length >= (double)Comp(((Bounds)(ref bounds)).center, num2)) ? 1f : (-1f)); double num8 = 0.0; double num9 = 0.0; int num10 = 0; int num11 = 0; float num12 = Comp(((Bounds)(ref bounds)).center, num3); float num13 = Comp(((Bounds)(ref bounds)).center, num4); for (int l = 0; l < vertices.Length; l++) { float num14 = Mathf.Abs(Comp(vertices[l], num4) - num13); if (Comp(vertices[l], num3) >= num12) { num8 += (double)num14; num10++; } else { num9 += (double)num14; num11++; } } if (num10 > 0 && num11 > 0) { num6 = ((num9 / (double)num11 >= num8 / (double)num10) ? 1f : (-1f)); } } if (Plugin.CfgFlipForward.Value) { num5 = 0f - num5; } if (Plugin.CfgFlipUp.Value) { num6 = 0f - num6; } Vector3 val = Axis(num2) * num5; Vector3 val2 = Axis(num3) * num6; Fit result = default(Fit); result.Rot = Quaternion.Euler(Plugin.CfgRotateX.Value, Plugin.CfgRotateY.Value, Plugin.CfgRotateZ.Value) * Quaternion.LookRotation(val, val2); result.Scale = Comp(size, num2) * Plugin.CfgScale.Value; result.Centre = ((Bounds)(ref bounds)).center; result.Describe = string.Format("len=axis{0}{1} up=axis{2}{3} ", num2, (num5 > 0f) ? "+" : "-", num3, (num6 > 0f) ? "+" : "-") + $"wid=axis{num4} size={size} scale={result.Scale:0.###}"; return result; } internal static Mesh Build(Mesh original, out Fit fit) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown fit = FitTo(original); Vector3[] array = (Vector3[])(object)new Vector3[_pos.Length]; Vector3[] array2 = (Vector3[])(object)new Vector3[_nrm.Length]; for (int i = 0; i < array.Length; i++) { array[i] = fit.Rot * (_pos[i] * fit.Scale) + fit.Centre; array2[i] = fit.Rot * _nrm[i]; } Mesh val = new Mesh { name = "Nemo" }; if (array.Length > 65000) { val.indexFormat = (IndexFormat)1; } val.vertices = array; val.normals = array2; val.uv = (Vector2[])_uv.Clone(); val.triangles = (int[])_tri.Clone(); val.RecalculateBounds(); return val; } } internal static class Patches { [HarmonyPatch(typeof(Creature), "OnStartClient")] internal static class CreatureOnStartClient { [HarmonyPostfix] private static void Postfix(Creature __instance) { try { Swapper.Apply(__instance); } catch (Exception ex) { Plugin.Log.LogError((object)("OnStartClient swap failed: " + ex)); } } } [HarmonyPatch(typeof(InventorySlot), "SetItem")] internal static class InventorySlotSetItem { [HarmonyPostfix] private static void Postfix(InventorySlot __instance) { try { Swapper.SyncSlot((Component)(object)__instance); } catch (Exception ex) { Plugin.Log.LogError((object)("Inventory slot sync failed: " + ex)); } } } [HarmonyPatch(typeof(JournalSlot), "SetCreature")] internal static class JournalSlotSetCreature { [HarmonyPostfix] private static void Postfix(JournalSlot __instance) { try { Swapper.SyncSlot((Component)(object)__instance); } catch (Exception ex) { Plugin.Log.LogError((object)("Journal slot sync failed: " + ex)); } } } [HarmonyPatch(typeof(MachineSlot), "SetIndex")] internal static class MachineSlotSetIndex { [HarmonyPostfix] private static void Postfix(MachineSlot __instance) { try { Swapper.SyncSlot((Component)(object)__instance); } catch (Exception ex) { Plugin.Log.LogError((object)("Machine slot sync failed: " + ex)); } } } } [BepInPlugin("erwins.howtonemo", "How to Nemo", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "erwins.howtonemo"; internal static ManualLogSource Log; internal static ConfigEntry CfgEnabled; internal static ConfigEntry CfgTarget; internal static ConfigEntry CfgScale; internal static ConfigEntry CfgFlipForward; internal static ConfigEntry CfgFlipUp; internal static ConfigEntry CfgRotateX; internal static ConfigEntry CfgRotateY; internal static ConfigEntry CfgRotateZ; internal static ConfigEntry CfgTexture; internal static ConfigEntry CfgPreview; internal static ConfigEntry CfgHideExtras; internal static ConfigEntry CfgBodyThreshold; internal static ConfigEntry CfgVerbose; private Harmony _harmony; private void Awake() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Expected O, but got Unknown //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Expected O, but got Unknown //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; CfgEnabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Master switch. Off leaves every model stock."); CfgTarget = ((BaseUnityPlugin)this).Config.Bind("General", "TargetPrefab", "clownfish", "Which item gets the Nemo model, by prefab name (spaces and case ignored). Any fish works if you would rather put him somewhere else. Takes effect on the next spawn."); CfgScale = ((BaseUnityPlugin)this).Config.Bind("Placement", "Scale", 1f, new ConfigDescription("Multiplier on the automatic fit. 1 matches the original fish's length exactly.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 5f), Array.Empty())); CfgFlipForward = ((BaseUnityPlugin)this).Config.Bind("Placement", "FlipForward", false, "Turn him around if he ends up swimming backwards."); CfgFlipUp = ((BaseUnityPlugin)this).Config.Bind("Placement", "FlipUp", false, "Turn him over if he ends up upside down."); CfgRotateX = ((BaseUnityPlugin)this).Config.Bind("Placement", "RotateX", 0f, new ConfigDescription("Extra rotation in degrees, applied on top of the automatic fit.", (AcceptableValueBase)(object)new AcceptableValueRange(-180f, 180f), Array.Empty())); CfgRotateY = ((BaseUnityPlugin)this).Config.Bind("Placement", "RotateY", 0f, new ConfigDescription("Extra rotation in degrees, applied on top of the automatic fit.", (AcceptableValueBase)(object)new AcceptableValueRange(-180f, 180f), Array.Empty())); CfgRotateZ = ((BaseUnityPlugin)this).Config.Bind("Placement", "RotateZ", 0f, new ConfigDescription("Extra rotation in degrees, applied on top of the automatic fit.", (AcceptableValueBase)(object)new AcceptableValueRange(-180f, 180f), Array.Empty())); CfgTexture = ((BaseUnityPlugin)this).Config.Bind("Appearance", "ReplaceTexture", true, "Put Nemo's own texture on the model. Off keeps the game's clownfish texture, which will not line up with his UVs."); CfgPreview = ((BaseUnityPlugin)this).Config.Bind("Appearance", "ReplaceInventoryPreview", true, "Also replace the small preview model in the inventory bar, the journal and the shop."); CfgHideExtras = ((BaseUnityPlugin)this).Config.Bind("Appearance", "HideLeftoverParts", true, "Hide any small stock renderers left over after the body is replaced — stray fins or eyes that Nemo already brings his own of. Takes effect on the next spawn."); CfgBodyThreshold = ((BaseUnityPlugin)this).Config.Bind("Appearance", "BodyThreshold", 0.4f, new ConfigDescription("A renderer counts as a body (and gets replaced) when it is at least this fraction of the largest one. Lower catches more parts. Takes effect on the next spawn.", (AcceptableValueBase)(object)new AcceptableValueRange(0.05f, 1f), Array.Empty())); CfgVerbose = ((BaseUnityPlugin)this).Config.Bind("Debug", "VerboseLogging", false, "Log every renderer found on the fish and how the model was fitted to it. Turn this on before reporting a placement problem."); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { Runner.RefitWanted = true; }; _harmony = new Harmony("erwins.howtonemo"); _harmony.PatchAll(typeof(Patches.CreatureOnStartClient)); _harmony.PatchAll(typeof(Patches.InventorySlotSetItem)); _harmony.PatchAll(typeof(Patches.JournalSlotSetCreature)); _harmony.PatchAll(typeof(Patches.MachineSlotSetIndex)); ((Component)this).gameObject.AddComponent(); Log.LogInfo((object)"How to Nemo loaded. He is out there somewhere."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal class Runner : MonoBehaviour { internal static bool RefitWanted; private float _nextSweep; private void Update() { if (RefitWanted) { RefitWanted = false; try { Swapper.Refit(); } catch (Exception ex) { Plugin.Log.LogError((object)("Re-fit failed: " + ex)); } } if (!(Time.unscaledTime < _nextSweep)) { _nextSweep = Time.unscaledTime + 30f; Swapper.Sweep(); } } } internal static class Swapper { private struct Tracked { public Renderer Renderer; public SkinnedMeshRenderer Skinned; public MeshFilter Filter; public Mesh Original; } private struct Candidate { public Renderer Renderer; public SkinnedMeshRenderer Skinned; public MeshFilter Filter; public Mesh Mesh; public float Area; } private const string MeshName = "Nemo"; private static readonly List Live = new List(); private static readonly HashSet Handled = new HashSet(); private static readonly Dictionary FitCache = new Dictionary(); private static FieldInfo _fMesh; private static FieldInfo _fDripMesh; private static Item _prefab; private static readonly Dictionary PrefabOriginals = new Dictionary(); private static bool _prefabDone; private static readonly Dictionary OriginalSlotTex = new Dictionary(); internal static string TargetKey => Normalise(Plugin.CfgTarget.Value); internal static string Normalise(string s) { if (string.IsNullOrEmpty(s)) { return string.Empty; } return s.Replace("(Clone)", string.Empty).Replace(" ", string.Empty).ToLowerInvariant(); } internal static bool IsTarget(Item item) { if ((Object)(object)item == (Object)null) { return false; } return Normalise(((Object)((Component)item).gameObject).name) == TargetKey; } private static bool IsOurs(Mesh m) { if ((Object)(object)m != (Object)null && ((Object)m).name != null) { return ((Object)m).name.StartsWith("Nemo", StringComparison.Ordinal); } return false; } internal static void Apply(Creature creature) { if (!Plugin.CfgEnabled.Value || (Object)(object)creature == (Object)null || !IsTarget((Item)(object)creature) || !NemoModel.Load() || !Handled.Add(((Object)((Component)creature).gameObject).GetInstanceID())) { return; } PatchPrefabOnce(); List list = Collect(((Component)creature).gameObject); if (list.Count == 0) { Plugin.Log.LogWarning((object)(((Object)((Component)creature).gameObject).name + ": no renderer with a mesh found; nothing to replace.")); return; } float num = 0f; foreach (Candidate item in list) { num = Mathf.Max(num, item.Area); } int num2 = 0; int num3 = 0; foreach (Candidate item2 in list) { bool flag = item2.Area >= num * Plugin.CfgBodyThreshold.Value; if (Plugin.CfgVerbose.Value) { Plugin.Log.LogInfo((object)(" renderer '" + ((Object)item2.Renderer).name + "' mesh '" + ((Object)item2.Mesh).name + "' " + $"area={item2.Area:0.######} skinned={(Object)(object)item2.Skinned != (Object)null} body={flag}")); } if (flag) { Tracked tracked = new Tracked { Renderer = item2.Renderer, Skinned = item2.Skinned, Filter = item2.Filter, Original = item2.Mesh }; Live.Add(tracked); Fit(tracked); num2++; } else if (Plugin.CfgHideExtras.Value) { item2.Renderer.enabled = false; num3++; } } Plugin.Log.LogInfo((object)($"{((Object)((Component)creature).gameObject).name}: replaced {num2} renderer(s)" + ((num3 > 0) ? $", hid {num3} leftover(s)" : string.Empty) + ".")); } private static List Collect(GameObject root) { List list = new List(); SkinnedMeshRenderer[] componentsInChildren = root.GetComponentsInChildren(true); foreach (SkinnedMeshRenderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMesh == (Object)null) && !IsOurs(val.sharedMesh)) { list.Add(Make((Renderer)(object)val, val, null, val.sharedMesh)); } } MeshFilter[] componentsInChildren2 = root.GetComponentsInChildren(true); foreach (MeshFilter val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.sharedMesh == (Object)null) && !IsOurs(val2.sharedMesh)) { Renderer component = ((Component)val2).GetComponent(); if (!((Object)(object)component == (Object)null)) { list.Add(Make(component, null, val2, val2.sharedMesh)); } } } return list; } private static Candidate Make(Renderer r, SkinnedMeshRenderer smr, MeshFilter mf, Mesh mesh) { //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_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) Bounds bounds = mesh.bounds; Vector3 size = ((Bounds)(ref bounds)).size; return new Candidate { Renderer = r, Skinned = smr, Filter = mf, Mesh = mesh, Area = Mathf.Max(size.x * size.y, Mathf.Max(size.y * size.z, size.x * size.z)) }; } private static void Fit(Tracked t) { Mesh val = BuildCached(t.Original); if ((Object)(object)t.Skinned != (Object)null) { BindSkinned(t.Skinned, val, t.Original); } else { t.Filter.sharedMesh = val; } ApplyTexture(t.Renderer); } private static Mesh BuildCached(Mesh original) { int instanceID = ((Object)original).GetInstanceID(); if (FitCache.TryGetValue(instanceID, out var value) && (Object)(object)value != (Object)null) { return value; } NemoModel.Fit fit; Mesh val = NemoModel.Build(original, out fit); ((Object)val).name = "Nemo"; FitCache[instanceID] = val; if (Plugin.CfgVerbose.Value) { Plugin.Log.LogInfo((object)(" fit against '" + ((Object)original).name + "': " + fit.Describe)); } return val; } private static void BindSkinned(SkinnedMeshRenderer smr, Mesh nemo, Mesh original) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0193: 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) Matrix4x4[] bindposes = original.bindposes; Transform[] bones = smr.bones; if (bindposes == null || bindposes.Length == 0 || bones == null || bones.Length == 0) { smr.sharedMesh = nemo; ((Renderer)smr).localBounds = nemo.bounds; return; } if (nemo.boneWeights == null || nemo.boneWeights.Length != nemo.vertexCount) { int num = Mathf.Min(bindposes.Length, bones.Length); Vector3[] array = (Vector3[])(object)new Vector3[num]; for (int i = 0; i < num; i++) { int num2 = i; Matrix4x4 inverse = ((Matrix4x4)(ref bindposes[i])).inverse; array[num2] = ((Matrix4x4)(ref inverse)).MultiplyPoint3x4(Vector3.zero); } Vector3[] vertices = nemo.vertices; BoneWeight[] array2 = (BoneWeight[])(object)new BoneWeight[vertices.Length]; for (int j = 0; j < vertices.Length; j++) { int num3 = -1; int num4 = -1; float num5 = float.MaxValue; float num6 = float.MaxValue; for (int k = 0; k < num; k++) { Vector3 val = array[k] - vertices[j]; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < num5) { num6 = num5; num4 = num3; num5 = sqrMagnitude; num3 = k; } else if (sqrMagnitude < num6) { num6 = sqrMagnitude; num4 = k; } } BoneWeight val2 = default(BoneWeight); ((BoneWeight)(ref val2)).boneIndex0 = Mathf.Max(num3, 0); if (num4 < 0) { ((BoneWeight)(ref val2)).weight0 = 1f; } else { float num7 = Mathf.Sqrt(num5); float num8 = Mathf.Sqrt(num6); float num9 = num7 + num8; ((BoneWeight)(ref val2)).weight0 = ((num9 <= 1E-06f) ? 1f : (num8 / num9)); ((BoneWeight)(ref val2)).weight1 = 1f - ((BoneWeight)(ref val2)).weight0; ((BoneWeight)(ref val2)).boneIndex1 = num4; } array2[j] = val2; } nemo.bindposes = bindposes; nemo.boneWeights = array2; } smr.sharedMesh = nemo; ((Renderer)smr).localBounds = nemo.bounds; } internal static void ApplyTexture(Renderer r) { if (!((Object)(object)r == (Object)null) && Plugin.CfgTexture.Value) { ApplyTexture(r.material); } } internal static void ApplyTexture(Material m) { //IL_0064: 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) if (!((Object)(object)m == (Object)null) && !((Object)(object)NemoModel.Atlas == (Object)null)) { if (m.HasProperty("_BaseMap")) { m.SetTexture("_BaseMap", (Texture)(object)NemoModel.Atlas); } if (m.HasProperty("_MainTex")) { m.SetTexture("_MainTex", (Texture)(object)NemoModel.Atlas); } if (m.HasProperty("_BaseColor")) { m.SetColor("_BaseColor", Color.white); } if (m.HasProperty("_Color")) { m.SetColor("_Color", Color.white); } if (m.HasProperty("_Use_Skin")) { m.SetFloat("_Use_Skin", 0f); } } } internal static void Sweep() { Live.RemoveAll((Tracked t) => (Object)(object)t.Renderer == (Object)null || (Object)(object)t.Original == (Object)null); } internal static void Refit() { if (!NemoModel.Load()) { return; } FitCache.Clear(); Sweep(); foreach (Tracked item in Live) { Fit(item); } RefitPrefab(); if (Live.Count > 0 || PrefabOriginals.Count > 0) { Plugin.Log.LogInfo((object)$"Re-fitted {Live.Count} renderer(s) and the inventory preview."); } } internal static void PatchPrefabOnce() { if (_prefabDone) { return; } _prefabDone = true; try { _prefab = GameInfo.GetSpawnable(TargetKey); if ((Object)(object)_prefab == (Object)null) { Plugin.Log.LogWarning((object)("GameInfo has no spawnable named '" + TargetKey + "'; inventory preview left alone.")); return; } _fMesh = AccessTools.Field(typeof(Item), "_mesh"); _fDripMesh = AccessTools.Field(typeof(Creature), "_dripMesh"); Remember(_fMesh); if (_prefab is Creature) { Remember(_fDripMesh); } RefitPrefab(); } catch (Exception ex) { Plugin.Log.LogError((object)("Could not patch the preview mesh: " + ex)); } } private static void Remember(FieldInfo field) { if (!(field == null) && !((Object)(object)_prefab == (Object)null)) { object? value = field.GetValue(_prefab); Mesh val = (Mesh)((value is Mesh) ? value : null); if (val != null && !IsOurs(val)) { PrefabOriginals[field.Name] = val; } } } private static void RefitPrefab() { if ((Object)(object)_prefab == (Object)null) { return; } foreach (KeyValuePair prefabOriginal in PrefabOriginals) { FieldInfo fieldInfo = ((prefabOriginal.Key == "_mesh") ? _fMesh : _fDripMesh); if (!(fieldInfo == null) && !((Object)(object)prefabOriginal.Value == (Object)null)) { fieldInfo.SetValue(_prefab, Plugin.CfgPreview.Value ? BuildCached(prefabOriginal.Value) : prefabOriginal.Value); } } } internal static void SyncSlot(Component slot) { if ((Object)(object)slot == (Object)null || !Plugin.CfgPreview.Value || !Plugin.CfgTexture.Value || (Object)(object)NemoModel.Atlas == (Object)null) { return; } MeshFilter[] componentsInChildren = slot.GetComponentsInChildren(true); foreach (MeshFilter val in componentsInChildren) { Renderer component = ((Component)val).GetComponent(); if ((Object)(object)component == (Object)null) { continue; } Material material = component.material; if ((Object)(object)material == (Object)null) { continue; } int instanceID = ((Object)material).GetInstanceID(); Texture value; if (IsOurs(val.sharedMesh)) { if (!OriginalSlotTex.ContainsKey(instanceID)) { OriginalSlotTex[instanceID] = (material.HasProperty("_BaseMap") ? material.GetTexture("_BaseMap") : null); } ApplyTexture(material); } else if (OriginalSlotTex.TryGetValue(instanceID, out value)) { if (material.HasProperty("_BaseMap")) { material.SetTexture("_BaseMap", value); } if (material.HasProperty("_MainTex")) { material.SetTexture("_MainTex", value); } OriginalSlotTex.Remove(instanceID); } } } } }