using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("IcarusModelReplacement")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+2dd13133085a24341e5edad1e8f497dfec2a7318")]
[assembly: AssemblyProduct("IcarusModelReplacement")]
[assembly: AssemblyTitle("IcarusModelReplacement")]
[assembly: AssemblyVersion("1.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 IcarusModelReplacement
{
internal sealed class Model : IDisposable
{
private readonly PackInfo info;
private readonly Transform[] bones;
private readonly Vector3[] rest;
private readonly Vector3[] positions;
private readonly Vector3[] rotations;
private readonly MaterialPropertyBlock lighting = new MaterialPropertyBlock();
private readonly SphericalHarmonicsL2[] probe = (SphericalHarmonicsL2[])(object)new SphericalHarmonicsL2[1];
private Material material;
private Mesh mesh;
private Texture2D texture;
private SkinnedMeshRenderer renderer;
private static readonly int Ambient0 = Shader.PropertyToID("_Global_AmbientColor0");
private static readonly int Ambient1 = Shader.PropertyToID("_Global_AmbientColor1");
private static readonly int Ambient2 = Shader.PropertyToID("_Global_AmbientColor2");
public GameObject Root { get; }
public Model(ModelPack pack, Transform parent, int layer)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Expected O, but got Unknown
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0132: 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)
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
//IL_0196: Unknown result type (might be due to invalid IL or missing references)
//IL_026e: Unknown result type (might be due to invalid IL or missing references)
//IL_0273: Unknown result type (might be due to invalid IL or missing references)
//IL_0290: Unknown result type (might be due to invalid IL or missing references)
//IL_0295: Unknown result type (might be due to invalid IL or missing references)
//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
//IL_0332: Unknown result type (might be due to invalid IL or missing references)
//IL_0334: Unknown result type (might be due to invalid IL or missing references)
//IL_034a: Unknown result type (might be due to invalid IL or missing references)
//IL_034f: Unknown result type (might be due to invalid IL or missing references)
//IL_0360: Unknown result type (might be due to invalid IL or missing references)
//IL_036c: Expected O, but got Unknown
//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
//IL_0400: Expected O, but got Unknown
//IL_01c1: 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_0421: Unknown result type (might be due to invalid IL or missing references)
//IL_0426: Unknown result type (might be due to invalid IL or missing references)
//IL_0437: Unknown result type (might be due to invalid IL or missing references)
//IL_0443: Unknown result type (might be due to invalid IL or missing references)
//IL_0444: Unknown result type (might be due to invalid IL or missing references)
//IL_0453: Expected O, but got Unknown
//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
//IL_01ee: 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_01f5: Unknown result type (might be due to invalid IL or missing references)
//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
//IL_05b1: Unknown result type (might be due to invalid IL or missing references)
//IL_05b6: Unknown result type (might be due to invalid IL or missing references)
//IL_05d6: Unknown result type (might be due to invalid IL or missing references)
//IL_052f: Unknown result type (might be due to invalid IL or missing references)
Shader val = Shader.Find("Standard");
if ((Object)(object)val == (Object)null || !val.isSupported)
{
throw new InvalidOperationException("The game's Standard shader is unavailable.");
}
info = pack.Info;
bones = (Transform[])(object)new Transform[info.Bones.Length];
rest = (Vector3[])(object)new Vector3[bones.Length];
positions = (Vector3[])(object)new Vector3[bones.Length + 1];
rotations = (Vector3[])(object)new Vector3[bones.Length + 1];
Root = new GameObject(info.Name)
{
layer = layer
};
Root.SetActive(false);
Root.transform.SetParent(parent, false);
Root.transform.localScale = Vector3.one * info.Scale;
try
{
Matrix4x4[] array = (Matrix4x4[])(object)new Matrix4x4[bones.Length];
for (int i = 0; i < bones.Length; i++)
{
BoneInfo boneInfo = info.Bones[i];
Vector3 val2 = Vector(boneInfo.Position);
bones[i] = new GameObject(boneInfo.Name)
{
layer = layer
}.transform;
bones[i].SetParent((boneInfo.Parent < 0) ? Root.transform : bones[boneInfo.Parent], false);
rest[i] = val2 - ((boneInfo.Parent < 0) ? Vector3.zero : Vector(info.Bones[boneInfo.Parent].Position));
bones[i].localPosition = rest[i];
array[i] = Matrix4x4.Translate(-val2);
}
Vector3[] array2 = (Vector3[])(object)new Vector3[pack.Vertices.Length];
Vector3[] array3 = (Vector3[])(object)new Vector3[array2.Length];
Vector2[] array4 = (Vector2[])(object)new Vector2[array2.Length];
BoneWeight[] array5 = (BoneWeight[])(object)new BoneWeight[array2.Length];
for (int j = 0; j < array2.Length; j++)
{
Vertex vertex = pack.Vertices[j];
array2[j] = new Vector3(vertex.X, vertex.Y, vertex.Z);
array3[j] = new Vector3(vertex.Nx, vertex.Ny, vertex.Nz);
array4[j] = new Vector2(vertex.U, vertex.V);
int num = j;
BoneWeight val3 = default(BoneWeight);
((BoneWeight)(ref val3)).boneIndex0 = vertex.B0;
((BoneWeight)(ref val3)).boneIndex1 = vertex.B1;
((BoneWeight)(ref val3)).boneIndex2 = vertex.B2;
((BoneWeight)(ref val3)).boneIndex3 = vertex.B3;
((BoneWeight)(ref val3)).weight0 = vertex.W0;
((BoneWeight)(ref val3)).weight1 = vertex.W1;
((BoneWeight)(ref val3)).weight2 = vertex.W2;
((BoneWeight)(ref val3)).weight3 = vertex.W3;
array5[num] = val3;
}
mesh = new Mesh
{
name = info.Name,
indexFormat = (IndexFormat)1
};
mesh.vertices = array2;
mesh.normals = array3;
mesh.uv = array4;
mesh.boneWeights = array5;
mesh.bindposes = array;
mesh.triangles = pack.Indices;
mesh.RecalculateBounds();
mesh.UploadMeshData(true);
texture = new Texture2D(2, 2, (TextureFormat)4, true)
{
name = info.Name,
filterMode = (FilterMode)2,
wrapMode = (TextureWrapMode)1
};
if (!ImageConversion.LoadImage(texture, pack.Texture, true))
{
throw new InvalidOperationException("Cannot decode model texture.");
}
material = new Material(val)
{
name = info.Name,
mainTexture = (Texture)(object)texture,
color = Color.white
};
material.SetFloat("_Metallic", info.Material.Metallic);
material.SetFloat("_Glossiness", info.Material.Smoothness);
if (!info.Material.SpecularHighlights)
{
material.SetFloat("_SpecularHighlights", 0f);
material.EnableKeyword("_SPECULARHIGHLIGHTS_OFF");
}
if (info.Material.Emission > 0f)
{
material.EnableKeyword("_EMISSION");
material.SetTexture("_EmissionMap", (Texture)(object)texture);
float emission = info.Material.Emission;
material.SetVector("_EmissionColor", new Vector4(emission, emission, emission, 1f));
}
renderer = Root.AddComponent<SkinnedMeshRenderer>();
renderer.sharedMesh = mesh;
((Renderer)renderer).sharedMaterial = material;
renderer.bones = bones;
renderer.rootBone = Root.transform;
renderer.quality = (SkinQuality)4;
((Renderer)renderer).lightProbeUsage = (LightProbeUsage)4;
Bounds bounds = mesh.bounds;
((Bounds)(ref bounds)).Expand(info.BoundsPadding * 2f);
((Renderer)renderer).localBounds = bounds;
Animate(Motion.Sample(0.0, 0f, 0f, 0f));
}
catch
{
Dispose();
throw;
}
}
private static Vector3 Vector(float[] v)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
return new Vector3(v[0], v[1], v[2]);
}
public void UpdateLighting()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: 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_0095: Unknown result type (might be due to invalid IL or missing references)
Color val = (Shader.GetGlobalColor(Ambient0) + Shader.GetGlobalColor(Ambient1) + Shader.GetGlobalColor(Ambient2)) / 3f;
val.r = Mathf.Max(0.12f, val.r);
val.g = Mathf.Max(0.12f, val.g);
val.b = Mathf.Max(0.12f, val.b);
probe[0] = RenderSettings.ambientProbe;
((SphericalHarmonicsL2)(ref probe[0])).AddAmbientLight(val);
lighting.CopySHCoefficientArraysFrom(probe);
((Renderer)renderer).SetPropertyBlock(lighting);
}
public void Animate(Motion state)
{
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: 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_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0182: 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_018c: Unknown result type (might be due to invalid IL or missing references)
Array.Clear(positions, 0, positions.Length);
Array.Clear(rotations, 0, rotations.Length);
MotionInfo[] motions = info.Motions;
foreach (MotionInfo motionInfo in motions)
{
float num = state.Get(motionInfo.Kind);
ref Vector3 reference = ref positions[motionInfo.Index];
reference += Vector(motionInfo.Position) * num;
ref Vector3 reference2 = ref rotations[motionInfo.Index];
reference2 += Vector(motionInfo.Rotation) * num;
}
for (int j = 0; j < bones.Length; j++)
{
bones[j].localPosition = rest[j] + positions[j];
bones[j].localRotation = Quaternion.Euler(rotations[j]);
}
Root.transform.localPosition = Vector(info.Offset) + positions[bones.Length];
Root.transform.localRotation = Quaternion.Euler(Vector(info.Rotation)) * Quaternion.Euler(rotations[bones.Length]);
}
public void Dispose()
{
if ((Object)(object)Root != (Object)null)
{
Root.SetActive(false);
Object.Destroy((Object)(object)Root);
}
if ((Object)(object)mesh != (Object)null)
{
Object.Destroy((Object)(object)mesh);
}
if ((Object)(object)material != (Object)null)
{
Object.Destroy((Object)(object)material);
}
if ((Object)(object)texture != (Object)null)
{
Object.Destroy((Object)(object)texture);
}
}
}
[DataContract]
internal sealed class PackInfo
{
[DataMember(Name = "format", IsRequired = true)]
public int Format { get; set; }
[DataMember(Name = "name", IsRequired = true)]
public string Name { get; set; }
[DataMember(Name = "author", IsRequired = true)]
public string Author { get; set; }
[DataMember(Name = "license", IsRequired = true)]
public string License { get; set; }
[DataMember(Name = "source")]
public string Source { get; set; }
[DataMember(Name = "scale", IsRequired = true)]
public float Scale { get; set; }
[DataMember(Name = "offset")]
public float[] Offset { get; set; }
[DataMember(Name = "rotation")]
public float[] Rotation { get; set; }
[DataMember(Name = "boundsPadding")]
public float BoundsPadding { get; set; }
[DataMember(Name = "material")]
public MaterialInfo Material { get; set; }
[DataMember(Name = "bones", IsRequired = true)]
public BoneInfo[] Bones { get; set; }
[DataMember(Name = "motions")]
public MotionInfo[] Motions { get; set; }
}
[DataContract]
internal sealed class BoneInfo
{
[DataMember(Name = "name", IsRequired = true)]
public string Name { get; set; }
[DataMember(Name = "parent", IsRequired = true)]
public int Parent { get; set; }
[DataMember(Name = "position", IsRequired = true)]
public float[] Position { get; set; }
}
[DataContract]
internal sealed class MaterialInfo
{
[DataMember(Name = "smoothness")]
public float Smoothness { get; set; }
[DataMember(Name = "metallic")]
public float Metallic { get; set; }
[DataMember(Name = "emission")]
public float Emission { get; set; }
[DataMember(Name = "specularHighlights")]
public bool SpecularHighlights { get; set; }
}
[DataContract]
internal sealed class MotionInfo
{
public int Index;
public Signal Kind;
[DataMember(Name = "target", IsRequired = true)]
public string Target { get; set; }
[DataMember(Name = "signal", IsRequired = true)]
public string Signal { get; set; }
[DataMember(Name = "position")]
public float[] Position { get; set; }
[DataMember(Name = "rotation")]
public float[] Rotation { get; set; }
}
internal struct Vertex
{
public float X;
public float Y;
public float Z;
public float Nx;
public float Ny;
public float Nz;
public float U;
public float V;
public byte B0;
public byte B1;
public byte B2;
public byte B3;
public float W0;
public float W1;
public float W2;
public float W3;
}
internal sealed class ModelPack
{
public PackInfo Info;
public Vertex[] Vertices;
public int[] Indices;
public byte[] Texture;
public static ModelPack Load(string directory)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Expected O, but got Unknown
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
ModelPack modelPack = new ModelPack();
using (FileStream fileStream = Open(directory, "model.json", 1048576L))
{
modelPack.Info = (PackInfo)((XmlObjectSerializer)new DataContractJsonSerializer(typeof(PackInfo), new DataContractJsonSerializerSettings
{
MaxItemsInObjectGraph = 20000
})).ReadObject((Stream)fileStream);
}
modelPack.ValidateInfo();
using (FileStream stream = Open(directory, "mesh.bin.gz", 33554432L))
{
using GZipStream input = new GZipStream(stream, CompressionMode.Decompress);
using BinaryReader reader = new BinaryReader(input);
modelPack.ReadMesh(reader);
}
using (FileStream fileStream2 = Open(directory, "texture.png", 67108864L))
{
using BinaryReader binaryReader = new BinaryReader(fileStream2);
modelPack.Texture = binaryReader.ReadBytes((int)fileStream2.Length);
}
modelPack.ValidateTexture();
return modelPack;
}
private static FileStream Open(string directory, string name, long limit)
{
string path = Path.Combine(directory, name);
Require((File.GetAttributes(path) & FileAttributes.ReparsePoint) == 0, "Asset must be a regular file: " + name);
FileStream fileStream = File.OpenRead(path);
if (fileStream.Length > 0 && fileStream.Length <= limit)
{
return fileStream;
}
fileStream.Dispose();
throw new InvalidDataException("Asset size limit exceeded or empty: " + name);
}
private static void Require(bool condition, string message)
{
if (!condition)
{
throw new InvalidDataException(message);
}
}
private static bool Finite(float value)
{
if (!float.IsNaN(value))
{
return !float.IsInfinity(value);
}
return false;
}
private static void Range(float value, float min, float max, string name)
{
Require(Finite(value) && value >= min && value <= max, "Invalid " + name);
}
private static float[] Vector(float[] value, bool required = false)
{
if (value == null && !required)
{
return new float[3];
}
Require(value != null && value.Length == 3, "Expected a three-component vector");
for (int i = 0; i < value.Length; i++)
{
Range(value[i], -1000f, 1000f, "vector component");
}
return value;
}
private void ValidateInfo()
{
Require(Info != null && Info.Format == 1, "Unsupported model format");
Require(!string.IsNullOrWhiteSpace(Info.Name) && !string.IsNullOrWhiteSpace(Info.Author) && !string.IsNullOrWhiteSpace(Info.License), "Model name, author and license are required");
Range(Info.Scale, 0.001f, 100f, "scale");
Range(Info.BoundsPadding, 0f, 100f, "bounds padding");
Info.Offset = Vector(Info.Offset);
Info.Rotation = Vector(Info.Rotation);
Info.Material = Info.Material ?? new MaterialInfo();
Range(Info.Material.Smoothness, 0f, 1f, "smoothness");
Range(Info.Material.Metallic, 0f, 1f, "metallic");
Range(Info.Material.Emission, 0f, 2f, "emission");
Require(Info.Bones != null && Info.Bones.Length >= 1 && Info.Bones.Length <= 256, "Bone count must be 1..256");
Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal);
for (int i = 0; i < Info.Bones.Length; i++)
{
BoneInfo boneInfo = Info.Bones[i];
Require(boneInfo != null && !string.IsNullOrWhiteSpace(boneInfo.Name) && boneInfo.Name.Length <= 128 && boneInfo.Name != "$root" && !dictionary.ContainsKey(boneInfo.Name), "Invalid or duplicate bone name");
Require(boneInfo.Parent >= -1 && boneInfo.Parent < i, "Bone parents must precede children");
boneInfo.Position = Vector(boneInfo.Position, required: true);
dictionary.Add(boneInfo.Name, i);
}
dictionary.Add("$root", Info.Bones.Length);
Info.Motions = Info.Motions ?? Array.Empty<MotionInfo>();
Require(Info.Motions.Length <= 1024, "Too many motion bindings");
MotionInfo[] motions = Info.Motions;
foreach (MotionInfo motionInfo in motions)
{
Require(motionInfo != null && motionInfo.Target != null && dictionary.TryGetValue(motionInfo.Target, out motionInfo.Index), "Unknown motion target");
Require(Enum.TryParse<Signal>(motionInfo.Signal, out motionInfo.Kind) && Enum.GetName(typeof(Signal), motionInfo.Kind) == motionInfo.Signal, "Unknown motion signal");
motionInfo.Position = Vector(motionInfo.Position);
motionInfo.Rotation = Vector(motionInfo.Rotation);
}
}
private static float ReadFloat(BinaryReader reader)
{
float num = reader.ReadSingle();
Require(Finite(num), "Non-finite mesh value");
return num;
}
private void ReadMesh(BinaryReader reader)
{
Require(reader.ReadUInt32() == 1145918025 && reader.ReadInt32() == 1, "Unsupported mesh format");
int num = reader.ReadInt32();
int num2 = reader.ReadInt32();
Require(num >= 3 && num <= 250000 && num2 >= 3 && num2 <= 1500000 && num2 % 3 == 0, "Mesh size limit exceeded");
Vertices = new Vertex[num];
for (int i = 0; i < num; i++)
{
Vertex vertex = new Vertex
{
X = ReadFloat(reader),
Y = ReadFloat(reader),
Z = ReadFloat(reader),
Nx = ReadFloat(reader),
Ny = ReadFloat(reader),
Nz = ReadFloat(reader),
U = ReadFloat(reader),
V = ReadFloat(reader),
B0 = reader.ReadByte(),
B1 = reader.ReadByte(),
B2 = reader.ReadByte(),
B3 = reader.ReadByte(),
W0 = ReadFloat(reader),
W1 = ReadFloat(reader),
W2 = ReadFloat(reader),
W3 = ReadFloat(reader)
};
Require(Math.Abs(vertex.X) <= 1000f && Math.Abs(vertex.Y) <= 1000f && Math.Abs(vertex.Z) <= 1000f, "Mesh coordinate out of range");
Require(Math.Abs(vertex.Nx * vertex.Nx + vertex.Ny * vertex.Ny + vertex.Nz * vertex.Nz - 1f) < 0.01f, "Mesh normals must be unit length");
Require(vertex.U >= 0f && vertex.U <= 1f && vertex.V >= 0f && vertex.V <= 1f, "Atlas UV out of range");
Require(vertex.B0 < Info.Bones.Length && vertex.B1 < Info.Bones.Length && vertex.B2 < Info.Bones.Length && vertex.B3 < Info.Bones.Length, "Mesh bone index out of range");
Require(vertex.W0 >= vertex.W1 && vertex.W1 >= vertex.W2 && vertex.W2 >= vertex.W3 && vertex.W3 >= 0f && Math.Abs(vertex.W0 + vertex.W1 + vertex.W2 + vertex.W3 - 1f) < 1E-05f, "Skin weights must be sorted and normalized");
Vertices[i] = vertex;
}
Indices = new int[num2];
for (int j = 0; j < num2; j++)
{
Indices[j] = reader.ReadInt32();
Require(Indices[j] >= 0 && Indices[j] < num, "Triangle index out of range");
}
Require(reader.BaseStream.ReadByte() == -1, "Unexpected trailing mesh data");
}
private void ValidateTexture()
{
byte[] array = new byte[16]
{
137, 80, 78, 71, 13, 10, 26, 10, 0, 0,
0, 13, 73, 72, 68, 82
};
Require(Texture.Length >= 33, "Truncated PNG");
for (int i = 0; i < array.Length; i++)
{
Require(Texture[i] == array[i], "Expected PNG with IHDR");
}
uint num = BigEndian(16);
uint num2 = BigEndian(20);
Require(num != 0 && num2 != 0 && num <= 8192 && num2 <= 8192 && (ulong)((long)num * (long)num2) <= 16777216uL, "Texture exceeds 16 megapixels");
}
private uint BigEndian(int at)
{
return (uint)((Texture[at] << 24) | (Texture[at + 1] << 16) | (Texture[at + 2] << 8) | Texture[at + 3]);
}
}
internal enum Signal
{
Constant,
Stride,
Step,
LeftStep,
RightStep,
Air,
Sail
}
internal struct Motion
{
private float stride;
private float air;
private float sail;
public static Motion Sample(double phase, float run, float air, float sail)
{
return new Motion
{
stride = (float)Math.Sin(phase) * run * (1f - air),
air = air,
sail = sail
};
}
public float Get(Signal signal)
{
return signal switch
{
Signal.Constant => 1f,
Signal.Stride => stride,
Signal.Step => Math.Abs(stride),
Signal.LeftStep => Math.Max(0f, stride),
Signal.RightStep => Math.Max(0f, 0f - stride),
Signal.Air => air,
Signal.Sail => sail,
_ => throw new ArgumentOutOfRangeException("signal"),
};
}
}
[BepInPlugin("org.fyyy.icarusmodelreplacement", "Icarus Model Replacement", "1.0.0")]
public sealed class Plugin : BaseUnityPlugin
{
private struct HiddenRenderer
{
private Renderer renderer;
private bool wasHidden;
public void Set(Renderer next)
{
if (!((Object)(object)renderer == (Object)(object)next))
{
if ((Object)(object)renderer != (Object)null)
{
renderer.forceRenderingOff = wasHidden;
}
renderer = next;
if ((Object)(object)renderer != (Object)null)
{
wasHidden = renderer.forceRenderingOff;
renderer.forceRenderingOff = true;
}
}
}
}
private const string Builtin = "builtin";
private MechaArmorModel armor;
private Model model;
private ConfigEntry<string> modelDirectory;
private string selected;
private HiddenRenderer[] parts = Array.Empty<HiddenRenderer>();
private HiddenRenderer[] bones = Array.Empty<HiddenRenderer>();
private HiddenRenderer[] wrecks = Array.Empty<HiddenRenderer>();
private GameObject wreckageGroup;
private void Awake()
{
modelDirectory = ((BaseUnityPlugin)this).Config.Bind<string>("Model", "Directory", "builtin", "builtin uses the included Gugugaga. Otherwise, a model folder relative to BepInEx/plugins or absolute. Empty keeps vanilla Icarus. Changes apply in game.");
}
private void LateUpdate()
{
Player val = (GameMain.isRunning ? GameMain.mainPlayer : null);
MechaArmorModel val2 = ((val != null) ? val.mechaArmorModel : null);
if ((Object)(object)val2 != (Object)null && !((ManualBehaviour)val2).inited)
{
val2 = null;
}
string text = modelDirectory.Value.Trim();
if (armor != val2 || selected != text)
{
Clear();
armor = val2;
selected = text;
if ((Object)(object)armor != (Object)null && text.Length != 0)
{
try
{
SkinnedMeshRenderer[] componentsInChildren = ((Component)armor).GetComponentsInChildren<SkinnedMeshRenderer>(true);
ModelPack modelPack = ModelPack.Load((text == "builtin") ? Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "model") : Path.Combine(Paths.PluginPath, text));
model = new Model(modelPack, val.controller.model, ((Component)armor).gameObject.layer);
Renderer[] renderers = (Renderer[])(object)componentsInChildren;
parts = Hide(renderers);
bones = new HiddenRenderer[armor.boneModels.Length];
((BaseUnityPlugin)this).Logger.LogInfo((object)("Model attached: " + modelPack.Info.Name + " by " + modelPack.Info.Author + " (" + modelPack.Info.License + ")."));
}
catch (Exception arg)
{
Clear();
((BaseUnityPlugin)this).Logger.LogError((object)$"Cannot load model '{text}'; keeping Icarus. {arg}");
return;
}
}
}
if ((Object)(object)armor == (Object)null || model == null)
{
return;
}
for (int i = 0; i < bones.Length; i++)
{
bones[i].Set((Renderer)(object)armor.boneModels[i]?.meshRenderer);
}
if ((Object)(object)wreckageGroup != (Object)(object)armor.wreckageGroup)
{
Restore(wrecks);
wreckageGroup = armor.wreckageGroup;
HiddenRenderer[] array;
if (!((Object)(object)wreckageGroup != (Object)null))
{
array = Array.Empty<HiddenRenderer>();
}
else
{
Renderer[] renderers = (Renderer[])(object)wreckageGroup.GetComponentsInChildren<MeshRenderer>(true);
array = Hide(renderers);
}
wrecks = array;
}
model.Root.SetActive(((ManualBehaviour)armor).active && val.isAlive);
model.UpdateLighting();
PlayerAnimator animator = val.animator;
if (!((TrackedReference)(object)animator.run_slow == (TrackedReference)null))
{
float air = Mathf.Clamp01(animator.driftWeight + animator.flyWeight + animator.sailWeight);
Motion state = Motion.Sample((double)animator.run_slow.normalizedTime * Math.PI * 2.0, Mathf.Clamp01(animator.runWeight), air, Mathf.Clamp01(animator.sailWeight));
model.Animate(state);
}
}
private static HiddenRenderer[] Hide(Renderer[] renderers)
{
HiddenRenderer[] array = new HiddenRenderer[renderers.Length];
for (int i = 0; i < array.Length; i++)
{
array[i].Set(renderers[i]);
}
return array;
}
private static void Restore(HiddenRenderer[] renderers)
{
for (int i = 0; i < renderers.Length; i++)
{
renderers[i].Set(null);
}
}
private void OnDisable()
{
Clear();
armor = null;
}
private void Clear()
{
Restore(parts);
Restore(bones);
Restore(wrecks);
parts = (bones = (wrecks = Array.Empty<HiddenRenderer>()));
model?.Dispose();
model = null;
wreckageGroup = null;
}
}
}