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<bool> CfgEnabled;
internal static ConfigEntry<string> CfgTarget;
internal static ConfigEntry<float> CfgScale;
internal static ConfigEntry<bool> CfgFlipForward;
internal static ConfigEntry<bool> CfgFlipUp;
internal static ConfigEntry<float> CfgRotateX;
internal static ConfigEntry<float> CfgRotateY;
internal static ConfigEntry<float> CfgRotateZ;
internal static ConfigEntry<bool> CfgTexture;
internal static ConfigEntry<bool> CfgPreview;
internal static ConfigEntry<bool> CfgHideExtras;
internal static ConfigEntry<float> CfgBodyThreshold;
internal static ConfigEntry<bool> 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<bool>("General", "Enabled", true, "Master switch. Off leaves every model stock.");
CfgTarget = ((BaseUnityPlugin)this).Config.Bind<string>("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<float>("Placement", "Scale", 1f, new ConfigDescription("Multiplier on the automatic fit. 1 matches the original fish's length exactly.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
CfgFlipForward = ((BaseUnityPlugin)this).Config.Bind<bool>("Placement", "FlipForward", false, "Turn him around if he ends up swimming backwards.");
CfgFlipUp = ((BaseUnityPlugin)this).Config.Bind<bool>("Placement", "FlipUp", false, "Turn him over if he ends up upside down.");
CfgRotateX = ((BaseUnityPlugin)this).Config.Bind<float>("Placement", "RotateX", 0f, new ConfigDescription("Extra rotation in degrees, applied on top of the automatic fit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-180f, 180f), Array.Empty<object>()));
CfgRotateY = ((BaseUnityPlugin)this).Config.Bind<float>("Placement", "RotateY", 0f, new ConfigDescription("Extra rotation in degrees, applied on top of the automatic fit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-180f, 180f), Array.Empty<object>()));
CfgRotateZ = ((BaseUnityPlugin)this).Config.Bind<float>("Placement", "RotateZ", 0f, new ConfigDescription("Extra rotation in degrees, applied on top of the automatic fit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-180f, 180f), Array.Empty<object>()));
CfgTexture = ((BaseUnityPlugin)this).Config.Bind<bool>("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<bool>("Appearance", "ReplaceInventoryPreview", true, "Also replace the small preview model in the inventory bar, the journal and the shop.");
CfgHideExtras = ((BaseUnityPlugin)this).Config.Bind<bool>("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<float>("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<float>(0.05f, 1f), Array.Empty<object>()));
CfgVerbose = ((BaseUnityPlugin)this).Config.Bind<bool>("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<Runner>();
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<Tracked> Live = new List<Tracked>();
private static readonly HashSet<int> Handled = new HashSet<int>();
private static readonly Dictionary<int, Mesh> FitCache = new Dictionary<int, Mesh>();
private static FieldInfo _fMesh;
private static FieldInfo _fDripMesh;
private static Item _prefab;
private static readonly Dictionary<string, Mesh> PrefabOriginals = new Dictionary<string, Mesh>();
private static bool _prefabDone;
private static readonly Dictionary<int, Texture> OriginalSlotTex = new Dictionary<int, Texture>();
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<Candidate> 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<Candidate> Collect(GameObject root)
{
List<Candidate> list = new List<Candidate>();
SkinnedMeshRenderer[] componentsInChildren = root.GetComponentsInChildren<SkinnedMeshRenderer>(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<MeshFilter>(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<Renderer>();
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<string, Mesh> 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<MeshFilter>(true);
foreach (MeshFilter val in componentsInChildren)
{
Renderer component = ((Component)val).GetComponent<Renderer>();
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);
}
}
}
}
}