Decompiled source of Rubber Ducks over Gups v1.0.0

RubberDucksOverGups.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using RoR2;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[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 RubberDucksOverGups
{
	[BepInPlugin("com.chaz.rubberducksovergups", "RubberDucksOverGups", "1.0.0")]
	public class RubberDucksOverGupsPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.chaz.rubberducksovergups";

		public const string PluginName = "RubberDucksOverGups";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		private static readonly (string body, string tag)[] Ducks = new(string, string)[3]
		{
			("GupBody", "gup"),
			("GeepBody", "geep"),
			("GipBody", "gip")
		};

		private static readonly FieldInfo runtimeSkinField = typeof(SkinDef).GetField("_runtimeSkin", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, (Action)delegate
			{
				Texture2D val = null;
				(string, string)[] ducks = Ducks;
				for (int i = 0; i < ducks.Length; i++)
				{
					var (text, tag) = ducks[i];
					try
					{
						if (!Object.op_Implicit((Object)(object)val))
						{
							val = Assets.ReadTexture("duck_emission.png");
						}
						Duckify(text, tag, val);
					}
					catch (Exception arg)
					{
						((BaseUnityPlugin)this).Logger.LogError((object)$"Couldn't turn {text} into a rubber duck: {arg}");
					}
				}
			});
		}

		private static void Duckify(string bodyName, string tag, Texture2D emission)
		{
			//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_0054: Expected O, but got Unknown
			//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)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: 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_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = BodyCatalog.FindBodyPrefab(bodyName);
			if (!Object.op_Implicit((Object)(object)obj))
			{
				throw new Exception("body not found");
			}
			SkinDef[] skins = ((Component)obj.GetComponent<ModelLocator>().modelTransform).GetComponent<ModelSkinController>().skins;
			Texture2D albedo = Assets.ReadTexture("duck_" + tag + ".png");
			Mesh mesh = new Mesh
			{
				name = "RubberDuckEmpty"
			};
			int num = 0;
			SkinDef[] array = skins;
			foreach (SkinDef val in array)
			{
				SkinDefParams val2 = (Object.op_Implicit((Object)(object)val.skinDefParams) ? val.skinDefParams : Load<SkinDefParams>(val.skinDefParamsAddress));
				if (!Object.op_Implicit((Object)(object)val2))
				{
					Log.LogWarning((object)(((Object)val).name + " has no params"));
					continue;
				}
				val.skinDefParams = val2;
				val.skinDefParamsAddress = new AssetReferenceT<SkinDefParams>("");
				for (int j = 0; j < val2.meshReplacements.Length; j++)
				{
					MeshReplacement val3 = val2.meshReplacements[j];
					Renderer renderer = val3.renderer;
					SkinnedMeshRenderer val4 = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
					if (val4 != null)
					{
						if (((Object)val4).name == "mdlGup")
						{
							Mesh val5 = (Object.op_Implicit((Object)(object)val3.mesh) ? val3.mesh : Load<Mesh>(val3.meshAddress));
							val3.mesh = Assets.ReadSkinnedMesh("duck_" + tag + ".hkm", val4, Object.op_Implicit((Object)(object)val5) ? val5.bindposes : null);
						}
						else
						{
							val3.mesh = mesh;
						}
						val3.meshAddress = new AssetReferenceT<Mesh>("");
						val2.meshReplacements[j] = val3;
					}
				}
				for (int k = 0; k < val2.rendererInfos.Length; k++)
				{
					RendererInfo val6 = val2.rendererInfos[k];
					if (Object.op_Implicit((Object)(object)val6.renderer) && !(((Object)val6.renderer).name != "mdlGup"))
					{
						Material gupMat = (Object.op_Implicit((Object)(object)val6.defaultMaterial) ? val6.defaultMaterial : Load<Material>(val6.defaultMaterialAddress));
						val6.defaultMaterial = DuckMaterial(gupMat, albedo, emission, "matRubberDuck_" + tag);
						val6.defaultMaterialAddress = new AssetReferenceT<Material>("");
						val2.rendererInfos[k] = val6;
					}
				}
				Rebake(val);
				num++;
			}
			Log.LogInfo((object)$"{bodyName}: {num} skin(s) are now rubber ducks");
		}

		private static Material DuckMaterial(Material gupMat, Texture2D albedo, Texture2D emission, string name)
		{
			//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_000d: 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_0025: 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_0042: Expected O, but got Unknown
			Material val = new Material(gupMat)
			{
				name = name
			};
			val.SetTexture("_MainTex", (Texture)(object)albedo);
			val.SetTexture("_NormalTex", (Texture)null);
			val.SetFloat("_NormalStrength", 0f);
			val.SetTexture("_EmTex", (Texture)(object)emission);
			return val;
		}

		private static void Rebake(SkinDef skin)
		{
			if (runtimeSkinField == null)
			{
				throw new MissingFieldException("SkinDef._runtimeSkin");
			}
			runtimeSkinField.SetValue(skin, null);
			skin.Bake();
		}

		private static T Load<T>(AssetReferenceT<T> r) where T : Object
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (r == null || !((AssetReference)r).RuntimeKeyIsValid())
			{
				return default(T);
			}
			return Addressables.LoadAssetAsync<T>((object)r).WaitForCompletion();
		}
	}
	internal static class Assets
	{
		private static Stream Open(string name)
		{
			return typeof(Assets).Assembly.GetManifestResourceStream(name) ?? throw new FileNotFoundException("Embedded resource missing: " + name);
		}

		public static Mesh ReadSkinnedMesh(string name, SkinnedMeshRenderer target, Matrix4x4[] bindposes)
		{
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: 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_0337: Expected O, but got Unknown
			Transform[] bones = target.bones;
			if (bindposes == null || bindposes.Length != bones.Length)
			{
				throw new InvalidDataException($"{name}: gup bind poses ({bindposes?.Length}) don't match {((Object)target).name}'s {bones.Length} bones");
			}
			using BinaryReader binaryReader = new BinaryReader(Open(name));
			if (new string(binaryReader.ReadChars(4)) != "HKM1")
			{
				throw new InvalidDataException(name);
			}
			int num = binaryReader.ReadInt32();
			string[] array = new string[num];
			for (int i = 0; i < num; i++)
			{
				array[i] = Encoding.UTF8.GetString(binaryReader.ReadBytes(binaryReader.ReadInt32()));
			}
			Dictionary<string, int> byName = new Dictionary<string, int>();
			for (int j = 0; j < bones.Length; j++)
			{
				if (Object.op_Implicit((Object)(object)bones[j]) && !byName.ContainsKey(((Object)bones[j]).name))
				{
					byName[((Object)bones[j]).name] = j;
				}
			}
			int[] array2 = array.Select(delegate(string b)
			{
				if (!byName.TryGetValue(b, out var value))
				{
					throw new Exception(name + ": bone " + b + " not on " + ((Object)target).name);
				}
				return value;
			}).ToArray();
			int num2 = binaryReader.ReadInt32();
			Vector3[] array3 = (Vector3[])(object)new Vector3[num2];
			Vector3[] array4 = (Vector3[])(object)new Vector3[num2];
			Vector2[] array5 = (Vector2[])(object)new Vector2[num2];
			for (int num3 = 0; num3 < num2; num3++)
			{
				array3[num3] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
			}
			for (int num4 = 0; num4 < num2; num4++)
			{
				array4[num4] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
			}
			for (int num5 = 0; num5 < num2; num5++)
			{
				array5[num5] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
			}
			int[] array6 = new int[num2 * 4];
			for (int num6 = 0; num6 < array6.Length; num6++)
			{
				array6[num6] = array2[binaryReader.ReadInt32()];
			}
			BoneWeight[] array7 = (BoneWeight[])(object)new BoneWeight[num2];
			for (int num7 = 0; num7 < num2; num7++)
			{
				float weight = binaryReader.ReadSingle();
				float weight2 = binaryReader.ReadSingle();
				float weight3 = binaryReader.ReadSingle();
				float weight4 = binaryReader.ReadSingle();
				int num8 = num7;
				BoneWeight val = default(BoneWeight);
				((BoneWeight)(ref val)).boneIndex0 = array6[num7 * 4];
				((BoneWeight)(ref val)).boneIndex1 = array6[num7 * 4 + 1];
				((BoneWeight)(ref val)).boneIndex2 = array6[num7 * 4 + 2];
				((BoneWeight)(ref val)).boneIndex3 = array6[num7 * 4 + 3];
				((BoneWeight)(ref val)).weight0 = weight;
				((BoneWeight)(ref val)).weight1 = weight2;
				((BoneWeight)(ref val)).weight2 = weight3;
				((BoneWeight)(ref val)).weight3 = weight4;
				array7[num8] = val;
			}
			int num9 = binaryReader.ReadInt32();
			int[] array8 = new int[num9];
			for (int num10 = 0; num10 < num9; num10++)
			{
				array8[num10] = binaryReader.ReadInt32();
			}
			Mesh val2 = new Mesh
			{
				name = Path.GetFileNameWithoutExtension(name)
			};
			if (num2 > 65535)
			{
				val2.indexFormat = (IndexFormat)1;
			}
			val2.vertices = array3;
			val2.normals = array4;
			val2.uv = array5;
			val2.SetIndices(array8, (MeshTopology)0, 0);
			val2.boneWeights = array7;
			val2.bindposes = bindposes;
			val2.RecalculateTangents();
			val2.RecalculateBounds();
			return val2;
		}

		public static Texture2D ReadTexture(string name)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			using Stream stream = Open(name);
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true)
			{
				name = Path.GetFileNameWithoutExtension(name)
			};
			ImageConversion.LoadImage(val, memoryStream.ToArray());
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)2;
			val.Apply(true, true);
			return val;
		}
	}
}