Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of False Son Skin Pack v0.2.1
BepInEx/plugins/FalseSonNativeSkins/Rodanius.FalseSon.NativeSkins.dll
Decompiled a week 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.Security.Cryptography; using System.Text; using BepInEx; using HG.Reflection; using R2API; using R2API.Utils; using RoR2; using RoR2.UI.MainMenu; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Rendering; using UnityEngine.ResourceManagement.AsyncOperations; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: OptIn] [assembly: AssemblyVersion("0.0.0.0")] namespace Rodanius.FalseSonNativeSkins; [BepInPlugin("rodanius.falseson.native-skins", "False Son - Native Skin Additions", "0.1.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class FalseSonNativeSkins : BaseUnityPlugin { [Serializable] public sealed class FileEntry { public string file; public string sha256; } [Serializable] public sealed class Surface { public FileEntry mesh; public FileEntry albedo; public FileEntry normal; } [Serializable] public sealed class Entry { public string skinId; public string name; public string revision; public Surface body; public Surface maul; public FileEntry icon; } [Serializable] public sealed class Manifest { public int schema; public Entry[] skins; } public const string Guid = "rodanius.falseson.native-skins"; public const string Version = "0.1.1"; private static FalseSonNativeSkins instance; private string folder; private float deadline; private bool registered; private ModelSkinController bodyController; private ModelSkinController displayController; private SkinDef[] originalBody; private SkinDef[] committedBody; private SkinDef[] originalDisplay; private SkinDef[] committedDisplay; private readonly List<AsyncOperationHandle> retained = new List<AsyncOperationHandle>(); private readonly List<SkinDef> ownedSkins = new List<SkinDef>(); private void Awake() { instance = this; folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(FalseSonNativeSkins)); RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplay)); MainMenuController.OnMainMenuInitialised += SyncDisplay; } [SystemInitializer(new Type[] { typeof(BodyCatalog), typeof(SurvivorCatalog) })] private static IEnumerator InitializeSkins() { if (!Object.op_Implicit((Object)(object)instance)) { return Empty(); } instance.deadline = Time.realtimeSinceStartup + 60f; return StartupGuard.Run(instance.Register, () => Time.realtimeSinceStartup > instance.deadline, delegate(Exception ex) { instance.Rollback(); ((BaseUnityPlugin)instance).Logger.LogError((object)("FALSESON_NATIVE_SKINS_DISABLED " + ex)); }); } private static IEnumerator Empty() { yield break; } private void Rollback() { registered = false; if (Object.op_Implicit((Object)(object)bodyController) && bodyController.skins == committedBody) { bodyController.skins = originalBody; } if (Object.op_Implicit((Object)(object)displayController) && displayController.skins == committedDisplay) { displayController.skins = originalDisplay; } } private byte[] Read(FileEntry entry) { if (entry == null || string.IsNullOrWhiteSpace(entry.file) || Path.GetFileName(entry.file) != entry.file || entry.file.Contains("..") || entry.sha256 == null || entry.sha256.Length != 64) { throw new InvalidDataException("Invalid asset entry"); } string text = Path.Combine(folder, entry.file); long length = new FileInfo(text).Length; if (length < 1 || length > 67108864) { throw new InvalidDataException("Asset size out of bounds: " + entry.file); } byte[] array = File.ReadAllBytes(text); using SHA256 sHA = SHA256.Create(); if (BitConverter.ToString(sHA.ComputeHash(array)).Replace("-", "").ToLowerInvariant() != entry.sha256) { throw new InvalidDataException("Asset hash mismatch: " + entry.file); } return array; } private IEnumerator Load<T>(object key, Action<T> assign) where T : Object { AsyncOperationHandle<T> handle = Addressables.LoadAssetAsync<T>(key); retained.Add(AsyncOperationHandle<T>.op_Implicit(handle)); while (!handle.IsDone) { yield return null; } if ((int)handle.Status != 1 || !Object.op_Implicit((Object)(object)handle.Result)) { throw new InvalidOperationException("Native asset unavailable: " + typeof(T).Name); } assign(handle.Result); } private IEnumerator Register() { Manifest manifest = JsonUtility.FromJson<Manifest>(File.ReadAllText(Path.Combine(folder, "false-son-native-assets.json"))); if (manifest == null || manifest.schema != 1 || manifest.skins == null || manifest.skins.Length < 1 || manifest.skins.Length > 7) { throw new InvalidDataException("Invalid False Son native manifest"); } if (manifest.skins.Any((Entry e) => e == null || string.IsNullOrWhiteSpace(e.skinId) || !e.skinId.StartsWith("RodaniusFalseSonE", StringComparison.Ordinal) || string.IsNullOrWhiteSpace(e.name) || string.IsNullOrWhiteSpace(e.revision)) || manifest.skins.Select((Entry e) => e.skinId).Distinct().Count() != manifest.skins.Length) { throw new InvalidDataException("Invalid or duplicate skin identity"); } GameObject body = BodyCatalog.FindBodyPrefab("FalseSonBody"); if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.GetComponent<ModelLocator>())) { throw new InvalidOperationException("False Son body unavailable"); } GameObject model = ((Component)body.GetComponent<ModelLocator>().modelTransform).gameObject; bodyController = model.GetComponent<ModelSkinController>(); if (!Object.op_Implicit((Object)(object)bodyController) || bodyController.skins == null || bodyController.skins.Length == 0) { throw new InvalidOperationException("Native skin list unavailable"); } originalBody = bodyController.skins; if (originalBody.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && manifest.skins.Any((Entry e) => e.skinId == ((Object)s).name))) { throw new InvalidOperationException("Duplicate native pack registration"); } SkinDef baseSkin = originalBody[0]; SkinDefParams native = baseSkin.skinDefParams; if (!Object.op_Implicit((Object)(object)native) && baseSkin.skinDefParamsAddress != null && ((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKeyIsValid()) { yield return Load<SkinDefParams>(((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKey, (Action<SkinDefParams>)delegate(SkinDefParams v) { native = v; }); } if (!Object.op_Implicit((Object)(object)native)) { throw new InvalidOperationException("Native parameters unavailable"); } SkinnedMeshRenderer[] skinRenderers = model.GetSkinRenderers<SkinnedMeshRenderer>(inactive: true, native); SkinnedMeshRenderer[] targets = (SkinnedMeshRenderer[])(object)new SkinnedMeshRenderer[2] { skinRenderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == "FalseSon_Body"), skinRenderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == "L_FalseSon_Weapon") }; SkinnedMeshRenderer cloth = skinRenderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == "FalseSon_Cloth"); Mesh[] references = (Mesh[])(object)new Mesh[2]; Material[] materials = (Material[])(object)new Material[2]; RendererInfo[] infos = (RendererInfo[])(object)new RendererInfo[2]; for (int i = 0; i < 2; i++) { int slot = i; SkinnedMeshRenderer target = targets[i]; MeshReplacement val = ((IEnumerable<MeshReplacement>)native.meshReplacements).FirstOrDefault((Func<MeshReplacement, bool>)((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)target)); references[i] = val.mesh; if (!Object.op_Implicit((Object)(object)references[i]) && val.meshAddress != null && ((AssetReference)val.meshAddress).RuntimeKeyIsValid()) { yield return Load<Mesh>(((AssetReference)val.meshAddress).RuntimeKey, (Action<Mesh>)delegate(Mesh v) { references[slot] = v; }); } if (!Object.op_Implicit((Object)(object)references[i])) { references[i] = target.sharedMesh; } infos[i] = native.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target); materials[i] = infos[i].defaultMaterial; if (!Object.op_Implicit((Object)(object)materials[i]) && infos[i].defaultMaterialAddress != null && ((AssetReference)infos[i].defaultMaterialAddress).RuntimeKeyIsValid()) { yield return Load<Material>(((AssetReference)infos[i].defaultMaterialAddress).RuntimeKey, (Action<Material>)delegate(Material v) { materials[slot] = v; }); } if (!Object.op_Implicit((Object)(object)materials[i])) { materials[i] = ((Renderer)target).sharedMaterial; } if (!Object.op_Implicit((Object)(object)references[i]) || !Object.op_Implicit((Object)(object)materials[i]) || !Object.op_Implicit((Object)(object)materials[i].shader) || target.bones.Length != 70 || references[i].bindposes.Length != 70) { throw new InvalidOperationException("Native renderer contract differs: " + ((Object)target).name); } } SurvivorDef val2 = SurvivorCatalog.FindSurvivorDefFromBody(body); if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val2.displayPrefab)) { throw new InvalidOperationException("False Son display unavailable"); } CharacterModel componentInChildren = val2.displayPrefab.GetComponentInChildren<CharacterModel>(true); if (!Object.op_Implicit((Object)(object)componentInChildren)) { throw new InvalidOperationException("False Son display model unavailable"); } SkinnedMeshRenderer[] array = targets; foreach (SkinnedMeshRenderer target2 in array) { SkinnedMeshRenderer val3 = ((Component)(object)componentInChildren).GetSkinRenderers<SkinnedMeshRenderer>(inactive: true, (SkinDefParams)null).Single((SkinnedMeshRenderer r) => ((Object)r).name == ((Object)target2).name); if (val3.bones.Length != 70 || !val3.bones.Select((Transform b) => (!Object.op_Implicit((Object)(object)b)) ? "" : ((Object)b).name).SequenceEqual(target2.bones.Select((Transform b) => (!Object.op_Implicit((Object)(object)b)) ? "" : ((Object)b).name))) { throw new InvalidOperationException("Display bone order differs: " + ((Object)target2).name); } } displayController = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>(); originalDisplay = displayController.skins; Entry[] skins = manifest.skins; foreach (Entry entry in skins) { Surface[] array2 = new Surface[2] { entry.body, entry.maul }; RendererInfo[] array3 = (RendererInfo[])(object)new RendererInfo[2]; List<MeshReplacement> list = new List<MeshReplacement>(); for (int num2 = 0; num2 < 2; num2++) { if (array2[num2] == null) { throw new InvalidDataException("Missing body or separate maul"); } Mesh val4 = ReadMesh(Read(array2[num2].mesh), targets[num2], references[num2]); ((Object)val4).name = entry.skinId + ((num2 == 0) ? "_Body" : "_Maul"); Material val5 = new Material(materials[num2]) { name = ((Object)val4).name + "_Material" }; val5.SetTexture("_MainTex", (Texture)(object)Texture(Read(array2[num2].albedo), linear: false)); val5.SetTexture("_NormalTex", (Texture)(object)Texture(Read(array2[num2].normal), linear: true)); val5.SetColor("_Color", Color.white); val5.SetFloat("_NormalStrength", 0.45f); val5.SetFloat("_Smoothness", 0.35f); val5.SetFloat("_SpecularStrength", 0.3f); val5.SetFloat("_SpecularExponent", 8f); val5.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture); val5.SetFloat("_EmPower", 0f); string[] array4 = new string[3] { "FLOWMAP", "FORCE_SPEC", "LIMBREMOVAL" }; foreach (string text in array4) { val5.DisableKeyword(text); } val5.SetFloat("_FlowmapOn", 0f); val5.SetFloat("_FlowEmissionStrength", 0f); val5.SetFloat("_ForceSpecOn", 0f); val5.SetFloat("_LimbRemovalOn", 0f); RendererInfo val6 = infos[num2]; val6.defaultMaterial = val5; val6.defaultMaterialAddress = new AssetReferenceT<Material>(""); array3[num2] = val6; list.Add(new MeshReplacement { renderer = (Renderer)(object)targets[num2], mesh = val4, meshAddress = new AssetReferenceT<Mesh>("") }); } Mesh val7 = new Mesh { name = entry.skinId + "_ReplacedCloth" }; val7.vertices = Array.Empty<Vector3>(); val7.triangles = Array.Empty<int>(); list.Add(new MeshReplacement { renderer = (Renderer)(object)cloth, mesh = val7, meshAddress = new AssetReferenceT<Mesh>("") }); SkinDefParams val8 = ScriptableObject.CreateInstance<SkinDefParams>(); val8.rendererInfos = array3; val8.meshReplacements = list.ToArray(); SkinDef skin = ScriptableObject.CreateInstance<SkinDef>(); ((Object)skin).name = entry.skinId; skin.nameToken = entry.skinId.ToUpperInvariant(); LanguageAPI.Add(skin.nameToken, entry.name + " (Playtest)"); skin.rootObject = model; skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin }; skin.skinDefParams = val8; skin.skinDefParamsAddress = new AssetReferenceT<SkinDefParams>(""); skin.unlockableDef = null; Texture2D val9 = Texture(Read(entry.icon), linear: false); skin.icon = Sprite.Create(val9, new Rect(0f, 0f, (float)((Texture)val9).width, (float)((Texture)val9).height), new Vector2(0.5f, 0.5f)); if (val8.gameObjectActivations == null || val8.lightReplacements == null || val8.projectileGhostReplacements == null || val8.minionSkinReplacements == null) { throw new InvalidOperationException("Native SkinDefParams collection defaults changed"); } yield return skin.BakeAsync(); if (skin.runtimeSkin == null) { throw new InvalidOperationException("Private bake failed: " + entry.skinId); } ownedSkins.Add(skin); ((BaseUnityPlugin)this).Logger.LogInfo((object)("FALSESON_NATIVE_SKIN_PREPARED id=" + entry.skinId + " revision=" + entry.revision + " separateMaul=true")); } if (bodyController.skins != originalBody) { throw new InvalidOperationException("Skin list changed during native-pack startup"); } committedBody = originalBody.Concat(ownedSkins).ToArray(); committedDisplay = (SkinDef[])committedBody.Clone(); bodyController.skins = committedBody; displayController.skins = committedDisplay; registered = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("FALSESON_NATIVE_SKINS_REGISTERED count=" + ownedSkins.Count + " nativeAnimatorRetained=true")); } private static Texture2D Texture(byte[] data, bool linear) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_002e: Expected O, but got Unknown Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, linear) { filterMode = (FilterMode)2, anisoLevel = 4 }; if (!ImageConversion.LoadImage(val, data, false)) { throw new InvalidDataException("Texture decode failed"); } return val; } private static bool Finite(float v) { if (!float.IsNaN(v)) { return !float.IsInfinity(v); } return false; } private static float Float(BinaryReader r) { float num = r.ReadSingle(); if (!Finite(num)) { throw new InvalidDataException("Non-finite mesh value"); } return num; } private static Mesh ReadMesh(byte[] bytes, SkinnedMeshRenderer renderer, Mesh reference) { //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: 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_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: 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_02ee: 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_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03e1: Unknown result type (might be due to invalid IL or missing references) //IL_03e9: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_03f9: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0417: Expected O, but got Unknown using BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes, writable: false)); if (Encoding.ASCII.GetString(binaryReader.ReadBytes(4)) != "PWE2") { throw new InvalidDataException("Mesh signature"); } int num = binaryReader.ReadInt32(); int num2 = binaryReader.ReadInt32(); int num3 = binaryReader.ReadInt32(); if (num < 3 || num > 100000 || num2 < 3 || num2 > 600000 || num2 % 3 != 0 || num3 != 70 || renderer.bones.Length != num3) { throw new InvalidDataException("Mesh dimensions"); } int[] array = new int[num3]; HashSet<int> hashSet = new HashSet<int>(); for (int i = 0; i < num3; i++) { int num4 = binaryReader.ReadInt32(); if (num4 < 1 || num4 > 128) { throw new InvalidDataException("Bone-name size"); } string name = Encoding.UTF8.GetString(binaryReader.ReadBytes(num4)); int num5 = Array.FindIndex(renderer.bones, (Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == name); if (num5 < 0 || !hashSet.Add(num5)) { throw new InvalidDataException("Bone-name mapping"); } array[i] = num5; } Matrix4x4[] array2 = (Matrix4x4[])(object)new Matrix4x4[num3]; Matrix4x4[] bindposes = reference.bindposes; for (int num6 = 0; num6 < num3; num6++) { Matrix4x4 val = default(Matrix4x4); for (int num7 = 0; num7 < 4; num7++) { for (int num8 = 0; num8 < 4; num8++) { ((Matrix4x4)(ref val))[num7, num8] = Float(binaryReader); if (Math.Abs(((Matrix4x4)(ref val))[num7, num8] - ((Matrix4x4)(ref bindposes[array[num6]]))[num7, num8]) > 0.001f) { throw new InvalidDataException("Native inverse-bind mismatch"); } } } array2[array[num6]] = val; } Vector3[] array3 = (Vector3[])(object)new Vector3[num]; Vector3[] array4 = (Vector3[])(object)new Vector3[num]; Vector2[] array5 = (Vector2[])(object)new Vector2[num]; BoneWeight[] array6 = (BoneWeight[])(object)new BoneWeight[num]; for (int num9 = 0; num9 < num; num9++) { array3[num9] = new Vector3(Float(binaryReader), Float(binaryReader), Float(binaryReader)); array4[num9] = new Vector3(Float(binaryReader), Float(binaryReader), Float(binaryReader)); array5[num9] = new Vector2(Float(binaryReader), Float(binaryReader)); int[] array7 = new int[4]; for (int num10 = 0; num10 < 4; num10++) { int num11 = binaryReader.ReadInt32(); if (num11 < 0 || num11 >= num3) { throw new InvalidDataException("Joint index"); } array7[num10] = array[num11]; } float[] array8 = new float[4]; for (int num12 = 0; num12 < 4; num12++) { array8[num12] = Float(binaryReader); if (array8[num12] < 0f) { throw new InvalidDataException("Negative weight"); } } if (Math.Abs(array8.Sum() - 1f) > 0.0001f) { throw new InvalidDataException("Weight sum"); } int num13 = num9; BoneWeight val2 = default(BoneWeight); ((BoneWeight)(ref val2)).boneIndex0 = array7[0]; ((BoneWeight)(ref val2)).boneIndex1 = array7[1]; ((BoneWeight)(ref val2)).boneIndex2 = array7[2]; ((BoneWeight)(ref val2)).boneIndex3 = array7[3]; ((BoneWeight)(ref val2)).weight0 = array8[0]; ((BoneWeight)(ref val2)).weight1 = array8[1]; ((BoneWeight)(ref val2)).weight2 = array8[2]; ((BoneWeight)(ref val2)).weight3 = array8[3]; array6[num13] = val2; } int[] array9 = new int[num2]; for (int num14 = 0; num14 < num2; num14++) { array9[num14] = binaryReader.ReadInt32(); if (array9[num14] < 0 || array9[num14] >= num) { throw new InvalidDataException("Triangle index"); } } if (binaryReader.BaseStream.Position != binaryReader.BaseStream.Length) { throw new InvalidDataException("Trailing mesh bytes"); } Mesh val3 = new Mesh { indexFormat = (IndexFormat)(num > 65535), vertices = array3, normals = array4, uv = array5, boneWeights = array6, bindposes = array2, triangles = array9 }; val3.RecalculateBounds(); val3.RecalculateTangents(); return val3; } private void SyncDisplay() { if (registered && Object.op_Implicit((Object)(object)bodyController) && Object.op_Implicit((Object)(object)displayController)) { displayController.skins = (SkinDef[])bodyController.skins.Clone(); } } private void OnDestroy() { RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(SyncDisplay)); MainMenuController.OnMainMenuInitialised -= SyncDisplay; if ((Object)(object)instance == (Object)(object)this) { instance = null; } } } internal static class NativeRenderers { private static readonly HashSet<string> NativePaths = new HashSet<string>(StringComparer.Ordinal) { "mdlLoader/PilotFemaleMesh", "mdlLoader/LoaderMechMesh", "mdlLoader/PilotFemaleFoldedOverJumpsuit", "mdlFalseSon/FalseSon_Body", "mdlFalseSon/FalseSon_Cloth", "mdlFalseSon/L_FalseSon_Weapon", "mdlSeeker/meshSeekerBody", "mdlSeeker/meshSeekerCloth", "mdlSeeker/meshSeekerGlass", "mdlChef/meshChef", "mdlChef/meshChefPizzaCutter", "mdlChef/meshlChefCleaver", "mdlChef/meshChefOven", "mdlChef/meshChefIceBox", "mdlCroco/CrocoMesh", "mdlCroco/CrocoSpineMesh", "mdlHuntress/HuntressMesh", "mdlHuntress/BowMesh", "mdlHuntress/HuntressScarfMesh", "mdlHuntress (1)/HuntressMesh", "mdlHuntress (1)/BowMesh", "mdlHuntress (1)/HuntressScarfMesh", "mdlMerc/MercMesh", "mdlMerc/MercSwordMesh", "mdlTreebot/TreebotBotMesh", "mdlTreebot/TreebotRootMesh", "mdlTreebot/TreebotLeafletMesh", "mdlTreebot/TreebotFlowerMesh", "mdlVoidSurvivor/mdlVoidSurvivorBody", "mdlVoidSurvivor/mdlVoidSurvivorHead", "mdlVoidSurvivor/mdlVoidSurvivorMetal", "mdlVoidSurvivor/metalcollar.001", "mdlBandit2/BanditArmature/ROOT/base/MainWeapon/BanditShotgunMesh", "mdlBandit2/BanditArmature/SideWeapon/SideWeaponSpinner/BanditPistolMesh", "mdlBandit2/Bandit2AccessoriesMesh" }; public static T[] GetSkinRenderers<T>(this Component owner, bool inactive = false, SkinDefParams parameters = null) where T : Renderer { return owner.gameObject.GetSkinRenderers<T>(inactive, parameters); } public static T[] GetSkinRenderers<T>(this GameObject owner, bool inactive = false, SkinDefParams parameters = null) where T : Renderer { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) T[] componentsInChildren = owner.GetComponentsInChildren<T>(inactive); CharacterModel val = owner.GetComponent<CharacterModel>() ?? owner.GetComponentInParent<CharacterModel>(); ModelSkinController val2 = owner.GetComponent<ModelSkinController>() ?? (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<ModelSkinController>() : null); HashSet<Renderer> skinRefs = new HashSet<Renderer>(); SkinDefParams val3 = parameters; if (!Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)val2) && val2.skins != null && val2.skins.Length != 0 && Object.op_Implicit((Object)(object)val2.skins[0])) { val3 = val2.skins[0].skinDefParams; } if (Object.op_Implicit((Object)(object)val3)) { if (val3.rendererInfos != null) { RendererInfo[] rendererInfos = val3.rendererInfos; foreach (RendererInfo val4 in rendererInfos) { if (Object.op_Implicit((Object)(object)val4.renderer)) { skinRefs.Add(val4.renderer); } } } if (val3.meshReplacements != null) { MeshReplacement[] meshReplacements = val3.meshReplacements; foreach (MeshReplacement val5 in meshReplacements) { if (Object.op_Implicit((Object)(object)val5.renderer)) { skinRefs.Add(val5.renderer); } } } } HashSet<Renderer> modelRefs = new HashSet<Renderer>(); if (Object.op_Implicit((Object)(object)val) && val.baseRendererInfos != null) { RendererInfo[] rendererInfos = val.baseRendererInfos; foreach (RendererInfo val6 in rendererInfos) { if (Object.op_Implicit((Object)(object)val6.renderer)) { modelRefs.Add(val6.renderer); } } } return Select(componentsInChildren, (T x) => ((Object)(object)x).name, (T x) => skinRefs.Contains((Renderer)(object)x), (T x) => modelRefs.Contains((Renderer)(object)x), (T x) => Path(((Component)(object)x).transform, owner.transform), (T x) => IsKnownNativePath(Path(((Component)(object)x).transform, owner.transform))); } internal static T[] Select<T>(T[] found, Func<T, string> name, Func<T, bool> skin, Func<T, bool> model, Func<T, string> path, Func<T, bool> contract = null) { HashSet<T> hashSet = new HashSet<T>(); if (contract == null) { contract = (T x) => false; } bool flag = found.Any(skin) || found.Any(model) || found.Any(contract); foreach (IGrouping<string, T> item in found.GroupBy(name)) { T[] array = item.ToArray(); if (array.Length == 1) { if (!flag || skin(array[0]) || model(array[0]) || contract(array[0])) { hashSet.Add(array[0]); } continue; } T[] array2 = array.Where(skin).ToArray(); T[] array3 = array.Where(model).ToArray(); T[] array4 = ((array2.Length == 1) ? ((array3.Length == 0 || array3.Contains(array2[0])) ? array2 : new T[0]) : ((array2.Length <= 1) ? array3 : array2.Where(((IEnumerable<T>)array3).Contains<T>).ToArray())); if (array2.Length == 0 && array3.Length == 0) { T[] array5 = array.Where(contract).ToArray(); if (array5.Length != 0) { if (array5.Length != 1) { throw new InvalidOperationException("ECLIPSE_RENDERER_PATH_AMBIGUOUS " + string.Join(";", array.Select(path))); } hashSet.Add(array5[0]); Debug.Log((object)("ECLIPSE_RENDERER_NATIVE_PATH name=" + item.Key + " native=" + path(array5[0]))); continue; } } if (array2.Length == 0 && array3.Length == 0 && flag) { Debug.Log((object)("ECLIPSE_RENDERER_FOREIGN_DUPLICATES name=" + item.Key + " ignored=" + array.Length)); continue; } if (array4.Length != 1) { throw new InvalidOperationException("ECLIPSE_RENDERER_AMBIGUOUS name=" + item.Key + " candidates=" + string.Join(";", array.Select(path)) + " skinRefs=" + array2.Length + " modelRefs=" + array3.Length); } hashSet.Add(array4[0]); Debug.Log((object)("ECLIPSE_RENDERER_RESOLVED name=" + item.Key + " native=" + path(array4[0]) + " ignoredDuplicates=" + (array.Length - 1))); } return found.Where(hashSet.Contains).ToArray(); } internal static bool IsKnownNativePath(string path) { if (path == null) { return false; } int num = path.IndexOf('/'); if (num < 0) { return false; } string text = path.Substring(0, num); if (text.EndsWith("(Clone)", StringComparison.Ordinal)) { text = text.Substring(0, text.Length - 7); } return NativePaths.Contains(text + path.Substring(num)); } private static string Path(Transform t, Transform root) { List<string> list = new List<string>(); Transform val = t; while (Object.op_Implicit((Object)(object)val)) { list.Add(((Object)val).name); if ((Object)(object)val == (Object)(object)root) { break; } val = val.parent; } list.Reverse(); return string.Join("/", list); } } internal static class StartupGuard { internal static IEnumerator Run(Func<IEnumerator> create, Func<bool> expired, Action<Exception> failed) { Stack<IEnumerator> stack = new Stack<IEnumerator>(); Exception failure = null; try { stack.Push(create()); } catch (Exception ex) { failure = ex; } try { while (failure == null && stack.Count > 0) { bool flag = false; object obj = null; try { if (expired()) { throw new TimeoutException("False Son native pack startup deadline exceeded."); } IEnumerator enumerator = stack.Peek(); flag = enumerator.MoveNext(); if (flag) { obj = enumerator.Current; } else { stack.Pop(); (enumerator as IDisposable)?.Dispose(); } } catch (Exception ex2) { failure = ex2; } if (failure != null) { break; } if (flag) { if (obj is IEnumerator item) { stack.Push(item); } else { yield return obj; } } } } finally { if (stack.Count > 0 && failure == null) { failure = new OperationCanceledException("False Son native pack startup iterator was cancelled."); } while (stack.Count > 0) { try { (stack.Pop() as IDisposable)?.Dispose(); } catch (Exception ex3) { if (failure == null) { failure = ex3; } } } if (failure != null) { try { failed(failure); } catch { } } } } }
BepInEx/plugins/FalseSonPenguin/Eclipse.FalseSon.E3.Penguin.dll
Decompiled a week 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.Security.Cryptography; using BepInEx; using Eclipse.AdvancedSkins; using EclipseSkinRuntimeFix; using EntityStates; using HG.Reflection; using R2API; using R2API.Utils; using RoR2; using RoR2.UI.MainMenu; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: OptIn] [assembly: AssemblyVersion("0.0.0.0")] namespace EclipseSkinRuntimeFix { internal static class NativeRenderers { private static readonly HashSet<string> NativePaths = new HashSet<string>(StringComparer.Ordinal) { "mdlLoader/PilotFemaleMesh", "mdlLoader/LoaderMechMesh", "mdlLoader/PilotFemaleFoldedOverJumpsuit", "mdlFalseSon/FalseSon_Body", "mdlFalseSon/FalseSon_Cloth", "mdlFalseSon/L_FalseSon_Weapon", "mdlSeeker/meshSeekerBody", "mdlSeeker/meshSeekerCloth", "mdlSeeker/meshSeekerGlass", "mdlChef/meshChef", "mdlChef/meshChefPizzaCutter", "mdlChef/meshlChefCleaver", "mdlChef/meshChefOven", "mdlChef/meshChefIceBox", "mdlCroco/CrocoMesh", "mdlCroco/CrocoSpineMesh", "mdlHuntress/HuntressMesh", "mdlHuntress/BowMesh", "mdlHuntress/HuntressScarfMesh", "mdlHuntress (1)/HuntressMesh", "mdlHuntress (1)/BowMesh", "mdlHuntress (1)/HuntressScarfMesh", "mdlMerc/MercMesh", "mdlMerc/MercSwordMesh", "mdlTreebot/TreebotBotMesh", "mdlTreebot/TreebotRootMesh", "mdlTreebot/TreebotLeafletMesh", "mdlTreebot/TreebotFlowerMesh", "mdlVoidSurvivor/mdlVoidSurvivorBody", "mdlVoidSurvivor/mdlVoidSurvivorHead", "mdlVoidSurvivor/mdlVoidSurvivorMetal", "mdlVoidSurvivor/metalcollar.001", "mdlBandit2/BanditArmature/ROOT/base/MainWeapon/BanditShotgunMesh", "mdlBandit2/BanditArmature/SideWeapon/SideWeaponSpinner/BanditPistolMesh", "mdlBandit2/Bandit2AccessoriesMesh" }; public static T[] GetSkinRenderers<T>(this Component owner, bool inactive = false, SkinDefParams parameters = null) where T : Renderer { return owner.gameObject.GetSkinRenderers<T>(inactive, parameters); } public static T[] GetSkinRenderers<T>(this GameObject owner, bool inactive = false, SkinDefParams parameters = null) where T : Renderer { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) T[] componentsInChildren = owner.GetComponentsInChildren<T>(inactive); CharacterModel val = owner.GetComponent<CharacterModel>() ?? owner.GetComponentInParent<CharacterModel>(); ModelSkinController val2 = owner.GetComponent<ModelSkinController>() ?? (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<ModelSkinController>() : null); HashSet<Renderer> skinRefs = new HashSet<Renderer>(); SkinDefParams val3 = parameters; if (!Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)val2) && val2.skins != null && val2.skins.Length != 0 && Object.op_Implicit((Object)(object)val2.skins[0])) { val3 = val2.skins[0].skinDefParams; } if (Object.op_Implicit((Object)(object)val3)) { if (val3.rendererInfos != null) { RendererInfo[] rendererInfos = val3.rendererInfos; foreach (RendererInfo val4 in rendererInfos) { if (Object.op_Implicit((Object)(object)val4.renderer)) { skinRefs.Add(val4.renderer); } } } if (val3.meshReplacements != null) { MeshReplacement[] meshReplacements = val3.meshReplacements; foreach (MeshReplacement val5 in meshReplacements) { if (Object.op_Implicit((Object)(object)val5.renderer)) { skinRefs.Add(val5.renderer); } } } } HashSet<Renderer> modelRefs = new HashSet<Renderer>(); if (Object.op_Implicit((Object)(object)val) && val.baseRendererInfos != null) { RendererInfo[] rendererInfos = val.baseRendererInfos; foreach (RendererInfo val6 in rendererInfos) { if (Object.op_Implicit((Object)(object)val6.renderer)) { modelRefs.Add(val6.renderer); } } } return Select(componentsInChildren, (T x) => ((Object)(object)x).name, (T x) => skinRefs.Contains((Renderer)(object)x), (T x) => modelRefs.Contains((Renderer)(object)x), (T x) => Path(((Component)(object)x).transform, owner.transform), (T x) => IsKnownNativePath(Path(((Component)(object)x).transform, owner.transform))); } internal static T[] Select<T>(T[] found, Func<T, string> name, Func<T, bool> skin, Func<T, bool> model, Func<T, string> path, Func<T, bool> contract = null) { HashSet<T> hashSet = new HashSet<T>(); if (contract == null) { contract = (T x) => false; } bool flag = found.Any(skin) || found.Any(model) || found.Any(contract); foreach (IGrouping<string, T> item in found.GroupBy(name)) { T[] array = item.ToArray(); if (array.Length == 1) { if (!flag || skin(array[0]) || model(array[0]) || contract(array[0])) { hashSet.Add(array[0]); } continue; } T[] array2 = array.Where(skin).ToArray(); T[] array3 = array.Where(model).ToArray(); T[] array4 = ((array2.Length == 1) ? ((array3.Length == 0 || array3.Contains(array2[0])) ? array2 : new T[0]) : ((array2.Length <= 1) ? array3 : array2.Where(((IEnumerable<T>)array3).Contains<T>).ToArray())); if (array2.Length == 0 && array3.Length == 0) { T[] array5 = array.Where(contract).ToArray(); if (array5.Length != 0) { if (array5.Length != 1) { throw new InvalidOperationException("ECLIPSE_RENDERER_PATH_AMBIGUOUS " + string.Join(";", array.Select(path))); } hashSet.Add(array5[0]); Debug.Log((object)("ECLIPSE_RENDERER_NATIVE_PATH name=" + item.Key + " native=" + path(array5[0]))); continue; } } if (array2.Length == 0 && array3.Length == 0 && flag) { Debug.Log((object)("ECLIPSE_RENDERER_FOREIGN_DUPLICATES name=" + item.Key + " ignored=" + array.Length)); continue; } if (array4.Length != 1) { throw new InvalidOperationException("ECLIPSE_RENDERER_AMBIGUOUS name=" + item.Key + " candidates=" + string.Join(";", array.Select(path)) + " skinRefs=" + array2.Length + " modelRefs=" + array3.Length); } hashSet.Add(array4[0]); Debug.Log((object)("ECLIPSE_RENDERER_RESOLVED name=" + item.Key + " native=" + path(array4[0]) + " ignoredDuplicates=" + (array.Length - 1))); } return found.Where(hashSet.Contains).ToArray(); } internal static bool IsKnownNativePath(string path) { if (path == null) { return false; } int num = path.IndexOf('/'); if (num < 0) { return false; } string text = path.Substring(0, num); if (text.EndsWith("(Clone)", StringComparison.Ordinal)) { text = text.Substring(0, text.Length - 7); } return NativePaths.Contains(text + path.Substring(num)); } private static string Path(Transform t, Transform root) { List<string> list = new List<string>(); Transform val = t; while (Object.op_Implicit((Object)(object)val)) { list.Add(((Object)val).name); if ((Object)(object)val == (Object)(object)root) { break; } val = val.parent; } list.Reverse(); return string.Join("/", list); } } } namespace EclipsePlaytestFalseSonE3 { [BepInPlugin("eclipseplaytest.false-son.e3", "False Son - Penguin (Playtest)", "0.1.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Penguin : BaseUnityPlugin { [Serializable] public sealed class AssetFile { public string file; public string sha256; } [Serializable] public sealed class AssetManifest { public int schema; public string skinId; public string revision; public AssetFile mesh; public AssetFile motion; public AssetFile albedo; public AssetFile attachments; public AssetFile icon; public string[] nativeBoneNames; } [Serializable] public sealed class AttachmentsFile { public int schema; public string skinId; public SkinItemAttachmentRule[] rules; } public const string Guid = "eclipseplaytest.false-son.e3"; public const string Version = "0.1.2"; public const string SkinId = "EclipsePlaytestFalseSonE3Penguin"; private static Penguin instance; private string folder; private float deadline; private bool registered; private GameObject modelPrefab; private GameObject displayModelPrefab; private Mesh nativeMesh; private Material nativeMaterial; private AssetManifest manifest; private IDisposable registration; private readonly List<AsyncOperationHandle> retainedAssets = new List<AsyncOperationHandle>(); private void Awake() { instance = this; folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(Penguin)); RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins)); MainMenuController.OnMainMenuInitialised += SyncDisplaySkins; } [SystemInitializer(new Type[] { typeof(BodyCatalog), typeof(SurvivorCatalog) })] private static IEnumerator InitializeSkin() { if (!Object.op_Implicit((Object)(object)instance)) { yield break; } instance.deadline = Time.realtimeSinceStartup + 45f; IEnumerator routine = instance.Register(); try { while (true) { bool flag; try { flag = routine.MoveNext(); } catch (Exception ex) { ((BaseUnityPlugin)instance).Logger.LogError((object)("FALSESON_E3_REGISTRATION_FAILED " + ex)); break; } if (flag) { yield return routine.Current; continue; } break; } } finally { IDisposable disposable = routine as IDisposable; if (disposable != null) { disposable.Dispose(); } } } private void CheckDeadline() { if (Time.realtimeSinceStartup > deadline) { throw new TimeoutException("Penguin asset loading timed out; other startup work continues."); } } private byte[] ReadAsset(AssetFile entry) { if (entry == null || string.IsNullOrWhiteSpace(entry.file) || Path.GetFileName(entry.file) != entry.file || entry.file.Contains("..") || entry.sha256 == null || entry.sha256.Length != 64) { throw new InvalidDataException("Invalid penguin asset manifest entry"); } string text = Path.Combine(folder, entry.file); if (new FileInfo(text).Length > 67108864) { throw new InvalidDataException("Penguin asset too large"); } byte[] array = File.ReadAllBytes(text); using SHA256 sHA = SHA256.Create(); if (BitConverter.ToString(sHA.ComputeHash(array)).Replace("-", "").ToLowerInvariant() != entry.sha256) { throw new InvalidDataException("Penguin asset hash mismatch: " + entry.file); } return array; } private void PrepareTemplate(GameObject model) { AdvancedSkinModel component = model.GetComponent<AdvancedSkinModel>(); if (Object.op_Implicit((Object)(object)component) && component.HasNativeSnapshot) { component.Prepare(); return; } SkinnedMeshRenderer val = model.GetSkinRenderers<SkinnedMeshRenderer>(inactive: true, (SkinDefParams)null).Single((SkinnedMeshRenderer r) => ((Object)r).name == "FalseSon_Body"); Animator component2 = model.GetComponent<Animator>(); if (!Object.op_Implicit((Object)(object)component2) || val.bones.Length != manifest.nativeBoneNames.Length) { throw new InvalidOperationException("Penguin requires the original FalseSon skeleton"); } for (int num = 0; num < val.bones.Length; num++) { if (!Object.op_Implicit((Object)(object)val.bones[num]) || ((Object)val.bones[num]).name != manifest.nativeBoneNames[num]) { throw new InvalidOperationException("Native bone slot mismatch " + num); } } AdvancedSkinModel val2 = model.GetComponent<AdvancedSkinModel>(); if (!Object.op_Implicit((Object)(object)val2)) { val2 = model.AddComponent<AdvancedSkinModel>(); } val2.CaptureNativeTemplate(val, component2, nativeMesh, (Material[])(object)new Material[1] { nativeMaterial }); val2.Prepare(); } private IEnumerator Register() { manifest = JsonUtility.FromJson<AssetManifest>(File.ReadAllText(Path.Combine(folder, "penguin-assets.json"))); if (manifest == null || manifest.schema != 1 || manifest.skinId != "EclipsePlaytestFalseSonE3Penguin" || string.IsNullOrWhiteSpace(manifest.revision) || manifest.nativeBoneNames == null || manifest.nativeBoneNames.Length != 70) { throw new InvalidDataException("Invalid penguin asset identity"); } MotionBank bank; using (MemoryStream memoryStream = new MemoryStream(ReadAsset(manifest.motion), writable: false)) { bank = MotionBank.Read((Stream)memoryStream); } if (bank.SkinId != "EclipsePlaytestFalseSonE3Penguin") { throw new InvalidDataException("Motion identity mismatch"); } bank.Find("idle"); bank.Find("death"); Mesh mesh; using (MemoryStream memoryStream2 = new MemoryStream(ReadAsset(manifest.mesh), writable: false)) { mesh = SkinMesh.Read((Stream)memoryStream2, bank); } Texture2D albedo = new Texture2D(2, 2, (TextureFormat)4, true, false) { name = "PenguinAlbedo", filterMode = (FilterMode)2, anisoLevel = 4 }; if (!ImageConversion.LoadImage(albedo, ReadAsset(manifest.albedo), false)) { throw new InvalidDataException("Invalid penguin albedo"); } Texture2D icon = new Texture2D(2, 2, (TextureFormat)4, false, false); if (!ImageConversion.LoadImage(icon, ReadAsset(manifest.icon), false)) { throw new InvalidDataException("Invalid penguin icon"); } GameObject body = BodyCatalog.FindBodyPrefab("FalseSonBody"); if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.GetComponent<ModelLocator>())) { throw new InvalidOperationException("FalseSon body unavailable"); } modelPrefab = ((Component)body.GetComponent<ModelLocator>().modelTransform).gameObject; ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>(); if (!Object.op_Implicit((Object)(object)controller) || controller.skins == null || controller.skins.Length == 0) { throw new InvalidOperationException("Native FalseSon skins unavailable"); } if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "EclipsePlaytestFalseSonE3Penguin")) { yield break; } SkinDef baseSkin = controller.skins[0]; SkinDefParams parameters = baseSkin.skinDefParams; if (!Object.op_Implicit((Object)(object)parameters) && baseSkin.skinDefParamsAddress != null && ((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKeyIsValid()) { AsyncOperationHandle<SkinDefParams> op = Addressables.LoadAssetAsync<SkinDefParams>(((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKey); retainedAssets.Add(AsyncOperationHandle<SkinDefParams>.op_Implicit(op)); while (!op.IsDone) { CheckDeadline(); yield return null; } parameters = op.Result; } if (!Object.op_Implicit((Object)(object)parameters)) { throw new InvalidOperationException("Native skin parameters unavailable"); } SkinnedMeshRenderer[] renderers = modelPrefab.GetSkinRenderers<SkinnedMeshRenderer>(inactive: true, parameters); SkinnedMeshRenderer target = renderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == "FalseSon_Body"); MeshReplacement val = ((IEnumerable<MeshReplacement>)parameters.meshReplacements).FirstOrDefault((Func<MeshReplacement, bool>)((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)target)); nativeMesh = val.mesh; if (!Object.op_Implicit((Object)(object)nativeMesh) && val.meshAddress != null && ((AssetReference)val.meshAddress).RuntimeKeyIsValid()) { AsyncOperationHandle<Mesh> op2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val.meshAddress).RuntimeKey); retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(op2)); while (!op2.IsDone) { CheckDeadline(); yield return null; } nativeMesh = op2.Result; } if (!Object.op_Implicit((Object)(object)nativeMesh)) { nativeMesh = target.sharedMesh; } if (!Object.op_Implicit((Object)(object)nativeMesh) || nativeMesh.bindposes.Length != 70) { throw new InvalidOperationException("Native fallback mesh invalid"); } RendererInfo info = parameters.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target); nativeMaterial = info.defaultMaterial; if (!Object.op_Implicit((Object)(object)nativeMaterial) && info.defaultMaterialAddress != null && ((AssetReference)info.defaultMaterialAddress).RuntimeKeyIsValid()) { AsyncOperationHandle<Material> op3 = Addressables.LoadAssetAsync<Material>(((AssetReference)info.defaultMaterialAddress).RuntimeKey); retainedAssets.Add(AsyncOperationHandle<Material>.op_Implicit(op3)); while (!op3.IsDone) { CheckDeadline(); yield return null; } nativeMaterial = op3.Result; } if (!Object.op_Implicit((Object)(object)nativeMaterial) || !Object.op_Implicit((Object)(object)nativeMaterial.shader)) { throw new InvalidOperationException("Native fallback material invalid"); } string[] companionNames = new string[2] { "FalseSon_Cloth", "L_FalseSon_Weapon" }; Mesh[] companionMeshes = (Mesh[])(object)new Mesh[companionNames.Length]; int i; for (i = 0; i < companionNames.Length; i++) { SkinnedMeshRenderer companion = renderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == companionNames[i]); MeshReplacement val2 = ((IEnumerable<MeshReplacement>)parameters.meshReplacements).FirstOrDefault((Func<MeshReplacement, bool>)((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)companion)); Mesh val3 = val2.mesh; if (!Object.op_Implicit((Object)(object)val3) && val2.meshAddress != null && ((AssetReference)val2.meshAddress).RuntimeKeyIsValid()) { AsyncOperationHandle<Mesh> op2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val2.meshAddress).RuntimeKey); retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(op2)); while (!op2.IsDone) { CheckDeadline(); yield return null; } val3 = op2.Result; } if (!Object.op_Implicit((Object)(object)val3)) { val3 = companion.sharedMesh; } if (!Object.op_Implicit((Object)(object)val3)) { throw new InvalidOperationException("Native companion fallback unavailable: " + companionNames[i]); } companionMeshes[i] = val3; } SurvivorDef val4 = SurvivorCatalog.FindSurvivorDefFromBody(body); if (!Object.op_Implicit((Object)(object)val4) || !Object.op_Implicit((Object)(object)val4.displayPrefab)) { throw new InvalidOperationException("FalseSon display unavailable"); } CharacterModel componentInChildren = val4.displayPrefab.GetComponentInChildren<CharacterModel>(true); if (!Object.op_Implicit((Object)(object)componentInChildren)) { throw new InvalidOperationException("FalseSon display model unavailable"); } displayModelPrefab = ((Component)componentInChildren).gameObject; PrepareTemplate(modelPrefab); PrepareTemplate(displayModelPrefab); ModelSkinController val5 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>(); Material val6 = new Material(nativeMaterial) { name = "matEclipseFalseSonE3Penguin" }; val6.SetTexture("_MainTex", (Texture)(object)albedo); val6.SetColor("_Color", Color.white); val6.SetFloat("_NormalStrength", 0f); val6.SetFloat("_Smoothness", 0.16f); val6.SetFloat("_SpecularStrength", 0.15f); val6.SetFloat("_SpecularExponent", 8f); val6.SetFloat("_EmPower", 0f); val6.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture); val6.DisableKeyword("FLOWMAP"); val6.SetFloat("_FlowmapOn", 0f); val6.SetFloat("_FlowEmissionStrength", 0f); val6.DisableKeyword("FORCE_SPEC"); val6.SetFloat("_ForceSpecOn", 0f); val6.DisableKeyword("LIMBREMOVAL"); val6.SetFloat("_LimbRemovalOn", 0f); AdvancedSkinDefinition val7 = new AdvancedSkinDefinition { Mesh = mesh, Motion = bank, FallbackClip = "idle", AirTransitionSeconds = 0.12f, CreateMotionSource = (Animator animator, MotionBank motion) => (ISkinMotionSource)(object)new PenguinStateObserver(animator, motion), CreateMotionTiming = (SkinnedMeshRenderer renderer, MotionBank motion) => (ISkinMotionTiming)(object)new PenguinGaitTiming(renderer) }; val7.NativeLayerPreference.Add("locomotion", new string[3] { "Body", "Base Layer", "Idle, Additive" }); val7.NativeLayerPreference.Add("primary", new string[3] { "FullBody, Override", "Gesture, Override", "Gesture, Additive" }); val7.NativeLayerPreference.Add("slam", new string[4] { "FullBody, Override", "Gesture, Override", "Gesture, Additive", "Body" }); val7.NativeLayerPreference.Add("secondary", new string[3] { "Gesture, RightArm, Override", "Gesture, Override", "Gesture, Additive" }); val7.NativeLayerPreference.Add("special", new string[6] { "FullBody, Override", "Gesture, Override", "Gesture, Head, Override", "Gesture, RightArm, Override", "Gesture, Head, Additive", "Gesture, Additive" }); val7.NativeLayerPreference.Add("alternate_special", new string[3] { "FullBody, Override", "Gesture, Override", "Gesture, RightArm, Override" }); val7.NativeLayerPreference.Add("utility", new string[2] { "Gesture, FullBody, No Arms, Override", "FullBody, Override" }); val7.NativeLayerPreference.Add("landing", new string[2] { "Impact", "ImpactRestricted" }); val7.NativeLayerPreference.Add("lobby", new string[1] { "Base Layer" }); val7.NativeLayerPreference.Add("lobby_look", new string[2] { "Looks", "VFX Sync Layer" }); AdvancedSkinRegistry.Register(val7); Mesh val8 = new Mesh { name = "EclipseFalseSonE3EmptyNativeClothAndClub" }; val8.vertices = Array.Empty<Vector3>(); val8.triangles = Array.Empty<int>(); GameObject[] array = (GameObject[])(object)new GameObject[2] { modelPrefab, displayModelPrefab }; foreach (GameObject val9 in array) { (val9.GetComponent<PenguinCompanions>() ?? val9.AddComponent<PenguinCompanions>()).Configure(nativeMesh, val8, companionNames, companionMeshes); } info.defaultMaterial = val6; info.defaultMaterialAddress = new AssetReferenceT<Material>(""); SkinDefParams val10 = ScriptableObject.CreateInstance<SkinDefParams>(); val10.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { info }; val10.meshReplacements = (MeshReplacement[])(object)new MeshReplacement[3] { new MeshReplacement { renderer = (Renderer)(object)target, mesh = mesh, meshAddress = new AssetReferenceT<Mesh>("") }, new MeshReplacement { renderer = (Renderer)(object)renderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == "FalseSon_Cloth"), mesh = val8, meshAddress = new AssetReferenceT<Mesh>("") }, new MeshReplacement { renderer = (Renderer)(object)renderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == "L_FalseSon_Weapon"), mesh = val8, meshAddress = new AssetReferenceT<Mesh>("") } }; SkinDef val11 = ScriptableObject.CreateInstance<SkinDef>(); ((Object)val11).name = "EclipsePlaytestFalseSonE3Penguin"; val11.nameToken = "ECLIPSE_PLAYTEST_FALSESON_E3_PENGUIN"; LanguageAPI.Add(val11.nameToken, "Penguin (Playtest)"); val11.unlockableDef = null; val11.rootObject = modelPrefab; val11.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin }; val11.skinDefParams = val10; val11.icon = Sprite.Create(icon, new Rect(0f, 0f, (float)((Texture)icon).width, (float)((Texture)icon).height), new Vector2(0.5f, 0.5f)); registration = AdvancedSkinApplications.Register(val11, mesh); val5.skins = (SkinDef[])(controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { val11 }).ToArray()).Clone(); registered = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("FALSESON_E3_REGISTERED revision=" + manifest.revision + " customBones=" + bank.Bones.Length + " unlocked=true audio=not_integrated items=native_fallback")); } private void SyncDisplaySkins() { if (!registered) { return; } try { if (!Object.op_Implicit((Object)(object)displayModelPrefab)) { throw new InvalidOperationException("Prepared penguin display was destroyed"); } PrepareTemplate(displayModelPrefab); ModelSkinController component = displayModelPrefab.GetComponent<ModelSkinController>(); if (!Object.op_Implicit((Object)(object)component)) { throw new InvalidOperationException("Prepared penguin display controller was removed"); } component.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("FALSESON_E3_DISPLAY_FAILED " + ex)); } } private void OnDestroy() { RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(SyncDisplaySkins)); MainMenuController.OnMainMenuInitialised -= SyncDisplaySkins; registration?.Dispose(); if ((Object)(object)instance == (Object)(object)this) { instance = null; } } } [DefaultExecutionOrder(32001)] public sealed class PenguinCompanions : MonoBehaviour { [SerializeField] private SkinnedMeshRenderer body; [SerializeField] private SkinnedMeshRenderer[] companions; [SerializeField] private Mesh nativeBody; [SerializeField] private Mesh empty; [SerializeField] private Mesh[] nativeMeshes; public void Configure(Mesh stockBody, Mesh ownedEmpty, string[] names, Mesh[] meshes) { SkinnedMeshRenderer[] renderers = ((Component)(object)this).GetSkinRenderers<SkinnedMeshRenderer>(inactive: true, (SkinDefParams)null); body = renderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == "FalseSon_Body"); companions = names.Select((string n) => renderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == n)).ToArray(); if (meshes.Length != names.Length || meshes.Any((Mesh m) => !Object.op_Implicit((Object)(object)m))) { throw new ArgumentException("Incomplete companion fallback"); } nativeBody = stockBody; empty = ownedEmpty; nativeMeshes = meshes; } private void LateUpdate() { if (!Object.op_Implicit((Object)(object)body) || (Object)(object)body.sharedMesh != (Object)(object)nativeBody || !Object.op_Implicit((Object)(object)empty) || companions == null) { return; } for (int i = 0; i < companions.Length; i++) { if (Object.op_Implicit((Object)(object)companions[i]) && (Object)(object)companions[i].sharedMesh == (Object)(object)empty) { companions[i].sharedMesh = nativeMeshes[i]; } } } } internal static class PenguinActor { public static CharacterBody Resolve(Component member) { if (!Object.op_Implicit((Object)(object)member)) { return null; } CharacterModel componentInParent = member.GetComponentInParent<CharacterModel>(); if (Object.op_Implicit((Object)(object)componentInParent) && Object.op_Implicit((Object)(object)componentInParent.body) && Object.op_Implicit((Object)(object)componentInParent.body.modelLocator) && (Object)(object)componentInParent.body.modelLocator.modelTransform == (Object)(object)((Component)componentInParent).transform) { return componentInParent.body; } AdvancedSkinModel componentInParent2 = member.GetComponentInParent<AdvancedSkinModel>(); if (!Object.op_Implicit((Object)(object)componentInParent2)) { return null; } return componentInParent2.AssociatedBody; } } public sealed class PenguinStateObserver : ISkinMotionSource, IDisposable { private readonly Animator animator; private readonly MotionBank bank; private CharacterBody actor; private EntityState death; private float began; private bool disposed; public PenguinStateObserver(Animator animator, MotionBank bank) { this.animator = animator; this.bank = bank; bank.Find("death"); } public void Observe(List<NativeMotionCandidate> candidates, HashSet<string> replaced) { //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Expected O, but got Unknown //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013a: 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_0146: 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_0175: 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_0198: Expected O, but got Unknown if (disposed) { return; } CharacterBody val = PenguinActor.Resolve((Component)(object)animator); if ((Object)(object)val != (Object)(object)actor) { actor = val; death = null; } if (!Object.op_Implicit((Object)(object)actor)) { return; } EntityState val2 = (from m in ((Component)actor).GetComponents<EntityStateMachine>() where Object.op_Implicit((Object)(object)m) select m.state).FirstOrDefault((Func<EntityState, bool>)((EntityState s) => s is GenericCharacterDeath)); if (val2 == null) { death = null; return; } if (val2 != death) { death = val2; began = Time.time; } MotionClip val3 = bank.Find("death"); NativeMotionCandidate val4 = new NativeMotionCandidate(); val4.SourceLayer = -100; val4.SourceRank = 1000; MotionLayer val5 = new MotionLayer(); val5.Group = "death"; val5.Priority = 1000; val5.Blend = (MotionBlend)0; val5.Samples = (WeightedMotion[])(object)new WeightedMotion[1] { new WeightedMotion { Clip = val3, Time = Math.Max(0f, Time.time - began) / val3.Duration, Weight = 1f, Token = "penguin-death:" + began, KnownEntry = true } }; val4.Motion = val5; candidates.Add(val4); } public void Dispose() { disposed = true; actor = null; death = null; } } public sealed class PenguinGaitTiming : ISkinMotionTiming, IDisposable { private readonly SkinnedMeshRenderer renderer; private readonly HashSet<string> gaits = new HashSet<string> { "run", "sprint", "backpedal", "strafe_left", "strafe_right" }; private CharacterMotor motor; private double phase; private float last = -1f; private float rate; private bool disposed; public PenguinGaitTiming(SkinnedMeshRenderer renderer) { this.renderer = renderer; } public void Retime(MotionLayer[] composed, IEnumerable<NativeMotionCandidate> observed) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_00d8: Unknown result type (might be due to invalid IL or missing references) if (disposed) { return; } CharacterBody val = PenguinActor.Resolve((Component)(object)renderer); CharacterMotor val2 = (Object.op_Implicit((Object)(object)val) ? val.characterMotor : null); if ((Object)(object)val2 != (Object)(object)motor) { motor = val2; last = -1f; phase = 0.0; rate = 0f; } if (!Object.op_Implicit((Object)(object)motor)) { return; } float time = Time.time; float num = ((last < 0f) ? 0f : (time - last)); last = time; if (num < 0f || num > 0.25f) { rate = 0f; return; } Vector3 velocity = motor.velocity; float num2 = Mathf.Sqrt(velocity.x * velocity.x + velocity.z * velocity.z); WeightedMotion val3 = (from w in composed.SelectMany((MotionLayer l) => l.Samples) where gaits.Contains(w.Clip.Id) orderby w.Weight descending select w).FirstOrDefault(); float num3 = ((val3 != null && val3.Clip.Id == "sprint") ? 0.64f : 0.48f); float num4 = ((motor.isGrounded && num2 > 0.05f) ? Mathf.Min(8f, num2 * 0.62f / num3) : 0f); rate = Mathf.MoveTowards(rate, num4, num * 24f); phase += num * rate; foreach (WeightedMotion item in composed.SelectMany((MotionLayer l) => l.Samples).Concat(observed.SelectMany((NativeMotionCandidate c) => c.Motion.Samples)).Distinct()) { if (gaits.Contains(item.Clip.Id)) { item.Time = phase; item.KnownEntry = false; } } } public bool OwnsCues(MotionClip clip) { return false; } public void AdvanceCues(Action<string> emit) { } public void Dispose() { disposed = true; motor = null; } } }