using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("TrailMarks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+3b197a541a29b5ef51c2838292d047ccd265ab1f")]
[assembly: AssemblyProduct("TrailMarks")]
[assembly: AssemblyTitle("TrailMarks")]
[assembly: AssemblyVersion("0.2.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 TrailMarks
{
internal struct SurfaceAnchor
{
public Vector3 Position;
public Vector3 Normal;
public BoneWeight Weight;
public Color Color;
}
internal sealed class AttachmentSurface
{
private struct Triangle
{
public SurfaceAnchor A;
public SurfaceAnchor B;
public SurfaceAnchor C;
public bool Seed;
}
public readonly List<SurfaceSite> Sites = new List<SurfaceSite>();
public readonly List<SurfaceAnchor> Anchors = new List<SurfaceAnchor>();
private static readonly Dictionary<string, AttachmentSurface> cache = new Dictionary<string, AttachmentSurface>();
public static void Clear()
{
cache.Clear();
}
public static AttachmentSurface Build(SkinnedMeshRenderer main, IEnumerable<Renderer> parts)
{
//IL_0170: 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_018f: Unknown result type (might be due to invalid IL or missing references)
//IL_0194: 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_06d6: Unknown result type (might be due to invalid IL or missing references)
//IL_06e2: Unknown result type (might be due to invalid IL or missing references)
//IL_06e7: Unknown result type (might be due to invalid IL or missing references)
//IL_06f3: Unknown result type (might be due to invalid IL or missing references)
//IL_06ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0704: Unknown result type (might be due to invalid IL or missing references)
//IL_0709: Unknown result type (might be due to invalid IL or missing references)
//IL_070e: Unknown result type (might be due to invalid IL or missing references)
//IL_0405: Unknown result type (might be due to invalid IL or missing references)
//IL_040a: Unknown result type (might be due to invalid IL or missing references)
//IL_040c: Unknown result type (might be due to invalid IL or missing references)
//IL_0411: Unknown result type (might be due to invalid IL or missing references)
//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
//IL_01de: Unknown result type (might be due to invalid IL or missing references)
//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
//IL_01ec: 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_0210: Unknown result type (might be due to invalid IL or missing references)
//IL_0212: Unknown result type (might be due to invalid IL or missing references)
//IL_022e: Unknown result type (might be due to invalid IL or missing references)
//IL_0223: Unknown result type (might be due to invalid IL or missing references)
//IL_0745: Unknown result type (might be due to invalid IL or missing references)
//IL_0233: Unknown result type (might be due to invalid IL or missing references)
//IL_0515: Unknown result type (might be due to invalid IL or missing references)
//IL_0519: Unknown result type (might be due to invalid IL or missing references)
//IL_051e: Unknown result type (might be due to invalid IL or missing references)
//IL_0527: Unknown result type (might be due to invalid IL or missing references)
//IL_052c: Unknown result type (might be due to invalid IL or missing references)
//IL_0535: Unknown result type (might be due to invalid IL or missing references)
//IL_053a: Unknown result type (might be due to invalid IL or missing references)
//IL_0556: Unknown result type (might be due to invalid IL or missing references)
//IL_054b: Unknown result type (might be due to invalid IL or missing references)
//IL_077a: Unknown result type (might be due to invalid IL or missing references)
//IL_0781: Unknown result type (might be due to invalid IL or missing references)
//IL_078b: Unknown result type (might be due to invalid IL or missing references)
//IL_0790: Unknown result type (might be due to invalid IL or missing references)
//IL_0797: Unknown result type (might be due to invalid IL or missing references)
//IL_055b: Unknown result type (might be due to invalid IL or missing references)
//IL_0809: Unknown result type (might be due to invalid IL or missing references)
//IL_080e: Unknown result type (might be due to invalid IL or missing references)
//IL_0838: Unknown result type (might be due to invalid IL or missing references)
//IL_0844: Unknown result type (might be due to invalid IL or missing references)
//IL_0850: Unknown result type (might be due to invalid IL or missing references)
//IL_0861: Unknown result type (might be due to invalid IL or missing references)
//IL_086d: Unknown result type (might be due to invalid IL or missing references)
//IL_0879: Unknown result type (might be due to invalid IL or missing references)
//IL_0475: Unknown result type (might be due to invalid IL or missing references)
//IL_047e: Unknown result type (might be due to invalid IL or missing references)
//IL_0483: Unknown result type (might be due to invalid IL or missing references)
//IL_0488: Unknown result type (might be due to invalid IL or missing references)
//IL_048a: Unknown result type (might be due to invalid IL or missing references)
//IL_0492: Unknown result type (might be due to invalid IL or missing references)
//IL_0497: Unknown result type (might be due to invalid IL or missing references)
//IL_049e: Unknown result type (might be due to invalid IL or missing references)
//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
//IL_04b2: Unknown result type (might be due to invalid IL or missing references)
//IL_04b7: Unknown result type (might be due to invalid IL or missing references)
//IL_04be: Unknown result type (might be due to invalid IL or missing references)
//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
Renderer[] array = parts.ToArray();
string key = ((Object)main).GetInstanceID() + "|" + string.Join(";", array.Select((Renderer r) => ((Object)r).GetInstanceID() + ":" + ((Object)TrailVisual.MeshOf(r)).GetInstanceID()));
if (cache.TryGetValue(key, out var value))
{
return value;
}
AttachmentSurface attachmentSurface = new AttachmentSurface();
List<Triangle> list = new List<Triangle>();
Mesh obj = MeshCache.Get(main.sharedMesh);
Transform[] mainBones = main.bones;
Matrix4x4[] bindposes = obj.bindposes;
string[] array2 = mainBones.Select((Transform b) => (!Object.op_Implicit((Object)(object)b)) ? "" : ((Object)b).name).ToArray();
Renderer[] array3 = array;
Vector3 val6;
foreach (Renderer val in array3)
{
Mesh val2 = MeshCache.Get(TrailVisual.MeshOf(val));
Vector3[] vertices = val2.vertices;
Vector3[] normals = val2.normals;
BoneWeight[] boneWeights = val2.boneWeights;
Color[] colors = val2.colors;
Matrix4x4[] bindposes2 = val2.bindposes;
SkinnedMeshRenderer val3 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null);
if (!Object.op_Implicit((Object)(object)val3))
{
Transform val4 = ((Component)val).transform;
int num2 = -1;
while (Object.op_Implicit((Object)(object)val4) && num2 < 0)
{
num2 = Array.IndexOf(mainBones, val4);
if (num2 < 0)
{
val4 = val4.parent;
}
}
if (num2 < 0)
{
continue;
}
Matrix4x4 val5 = ((Matrix4x4)(ref bindposes[num2])).inverse * mainBones[num2].worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix;
SurfaceAnchor[] array4 = new SurfaceAnchor[vertices.Length];
for (int num3 = 0; num3 < vertices.Length; num3++)
{
int num4 = num3;
SurfaceAnchor surfaceAnchor = new SurfaceAnchor
{
Position = ((Matrix4x4)(ref val5)).MultiplyPoint3x4(vertices[num3])
};
val6 = ((Matrix4x4)(ref val5)).MultiplyVector(normals[num3]);
surfaceAnchor.Normal = ((Vector3)(ref val6)).normalized;
BoneWeight weight = default(BoneWeight);
((BoneWeight)(ref weight)).boneIndex0 = num2;
((BoneWeight)(ref weight)).weight0 = 1f;
surfaceAnchor.Weight = weight;
surfaceAnchor.Color = ((colors.Length == vertices.Length) ? colors[num3] : Color.white);
array4[num4] = surfaceAnchor;
}
for (int num5 = 0; num5 < val2.subMeshCount; num5++)
{
int[] triangles = val2.GetTriangles(num5);
for (int num6 = 0; num6 < triangles.Length; num6 += 3)
{
list.Add(new Triangle
{
A = array4[triangles[num6]],
B = array4[triangles[num6 + 1]],
C = array4[triangles[num6 + 2]],
Seed = ((Object)val).name.ToLowerInvariant().Contains("head")
});
}
}
}
else
{
if (boneWeights.Length != vertices.Length || normals.Length != vertices.Length)
{
continue;
}
int[] array5 = val3.bones.Select((Transform b) => Array.FindIndex(mainBones, (Transform m) => Object.op_Implicit((Object)(object)m) && Object.op_Implicit((Object)(object)b) && ((Object)m).name == ((Object)b).name)).ToArray();
SurfaceAnchor[] array6 = new SurfaceAnchor[vertices.Length];
bool[] array7 = new bool[vertices.Length];
for (int num7 = 0; num7 < vertices.Length; num7++)
{
int[] array8 = new int[4]
{
((BoneWeight)(ref boneWeights[num7])).boneIndex0,
((BoneWeight)(ref boneWeights[num7])).boneIndex1,
((BoneWeight)(ref boneWeights[num7])).boneIndex2,
((BoneWeight)(ref boneWeights[num7])).boneIndex3
};
float[] array9 = new float[4]
{
((BoneWeight)(ref boneWeights[num7])).weight0,
((BoneWeight)(ref boneWeights[num7])).weight1,
((BoneWeight)(ref boneWeights[num7])).weight2,
((BoneWeight)(ref boneWeights[num7])).weight3
};
Dictionary<int, float> dictionary = new Dictionary<int, float>();
Vector3 val7 = Vector3.zero;
Vector3 val8 = Vector3.zero;
float num8 = 0f;
for (int num9 = 0; num9 < 4; num9++)
{
int num10 = array8[num9];
float num11 = array9[num9];
if (!(num11 <= 0f) && num10 < array5.Length && num10 < bindposes2.Length)
{
int num12 = array5[num10];
if (num12 >= 0 && num12 < bindposes.Length)
{
Matrix4x4 val9 = ((Matrix4x4)(ref bindposes[num12])).inverse * bindposes2[num10];
val7 += ((Matrix4x4)(ref val9)).MultiplyPoint3x4(vertices[num7]) * num11;
val8 += ((Matrix4x4)(ref val9)).MultiplyVector(normals[num7]) * num11;
dictionary[num12] = (dictionary.TryGetValue(num12, out var value2) ? (value2 + num11) : num11);
num8 += num11;
}
}
}
if (!(num8 < 0.99f))
{
array6[num7] = new SurfaceAnchor
{
Position = val7 / num8,
Normal = ((Vector3)(ref val8)).normalized,
Weight = Weights(dictionary),
Color = ((colors.Length == vertices.Length) ? colors[num7] : Color.white)
};
array7[num7] = true;
}
}
bool seed = (Object)(object)val == (Object)(object)main || ((Object)val).name.ToLowerInvariant().Contains("head");
for (int num13 = 0; num13 < val2.subMeshCount; num13++)
{
int[] triangles2 = val2.GetTriangles(num13);
for (int num14 = 0; num14 < triangles2.Length; num14 += 3)
{
int num15 = triangles2[num14];
int num16 = triangles2[num14 + 1];
int num17 = triangles2[num14 + 2];
if (array7[num15] && array7[num16] && array7[num17])
{
list.Add(new Triangle
{
A = array6[num15],
B = array6[num16],
C = array6[num17],
Seed = seed
});
}
}
}
}
}
foreach (Triangle item2 in list.Where((Triangle t) => t.Seed))
{
SurfaceAnchor surfaceAnchor2 = Blend(item2.A, item2.B, item2.C, 1f / 3f, 1f / 3f, 1f / 3f);
val6 = Vector3.Cross(item2.B.Position - item2.A.Position, item2.C.Position - item2.A.Position);
if (((Vector3)(ref val6)).sqrMagnitude < 1E-07f)
{
continue;
}
int num18 = Region(array2[((BoneWeight)(ref surfaceAnchor2.Weight)).boneIndex0]);
if (num18 < 0 || (num18 == 0 && surfaceAnchor2.Normal.y < 0.15f))
{
continue;
}
float num19 = 0.002f;
SurfaceAnchor item = surfaceAnchor2;
foreach (Triangle item3 in list)
{
if (Hit(surfaceAnchor2.Position + surfaceAnchor2.Normal * 0.002f, surfaceAnchor2.Normal, item3, out var distance, out var u, out var v) && distance > num19 && distance < 0.65f)
{
num19 = distance;
item = Blend(item3.A, item3.B, item3.C, 1f - u - v, u, v);
}
}
item.Normal = surfaceAnchor2.Normal;
int count = attachmentSurface.Anchors.Count;
attachmentSurface.Anchors.Add(item);
attachmentSurface.Sites.Add(new SurfaceSite(new Vector3(item.Position.x, item.Position.y, item.Position.z), new Vector3(item.Normal.x, item.Normal.y, item.Normal.z), num18, count));
}
if (cache.Count > 16)
{
cache.Clear();
}
cache[key] = attachmentSurface;
return attachmentSurface;
}
internal static int Region(string name)
{
switch (name)
{
case "Head":
case "Face":
return 0;
case "Arm_L":
case "S_Shoulder_L":
case "ShirtArm_L":
return 1;
case "Arm_R":
case "S_Shoulder_R":
case "ShirtArm_R":
return 2;
case "Elbow_L":
return 3;
case "Elbow_R":
return 4;
case "ChestF":
case "Torso":
case "Collar":
return 5;
case "ChestB":
case "CollarB":
return 6;
case "WaistF1":
return 7;
case "WaistB1":
return 8;
case "Leg_L":
case "PantWeight_L":
return 9;
case "Leg_R":
case "PantWeight_R":
return 10;
case "Knee_L":
return 11;
case "Knee_R":
return 12;
case "WaistL1":
return 13;
case "WaistR1":
return 14;
default:
return -1;
}
}
private static bool Hit(Vector3 origin, Vector3 direction, Triangle t, out float distance, out float u, out float v)
{
//IL_001d: 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_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_0039: 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_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: 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_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: 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_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
distance = (u = (v = 0f));
Vector3 val = t.B.Position - t.A.Position;
Vector3 val2 = t.C.Position - t.A.Position;
Vector3 val3 = Vector3.Cross(direction, val2);
float num = Vector3.Dot(val, val3);
if (Mathf.Abs(num) < 1E-07f)
{
return false;
}
Vector3 val4 = origin - t.A.Position;
u = Vector3.Dot(val4, val3) / num;
if (u < 0f || u > 1f)
{
return false;
}
Vector3 val5 = Vector3.Cross(val4, val);
v = Vector3.Dot(direction, val5) / num;
if (v < 0f || u + v > 1f)
{
return false;
}
distance = Vector3.Dot(val2, val5) / num;
return distance > 0f;
}
private static BoneWeight Weights(Dictionary<int, float> values)
{
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
KeyValuePair<int, float>[] array = (from p in values
orderby p.Value descending, p.Key
select p).Take(4).ToArray();
float num = array.Sum((KeyValuePair<int, float> p) => p.Value);
BoneWeight result = default(BoneWeight);
for (int num2 = 0; num2 < array.Length; num2++)
{
switch (num2)
{
case 0:
((BoneWeight)(ref result)).boneIndex0 = array[num2].Key;
((BoneWeight)(ref result)).weight0 = array[num2].Value / num;
break;
case 1:
((BoneWeight)(ref result)).boneIndex1 = array[num2].Key;
((BoneWeight)(ref result)).weight1 = array[num2].Value / num;
break;
case 2:
((BoneWeight)(ref result)).boneIndex2 = array[num2].Key;
((BoneWeight)(ref result)).weight2 = array[num2].Value / num;
break;
case 3:
((BoneWeight)(ref result)).boneIndex3 = array[num2].Key;
((BoneWeight)(ref result)).weight3 = array[num2].Value / num;
break;
}
}
return result;
}
private static SurfaceAnchor Blend(SurfaceAnchor a, SurfaceAnchor b, SurfaceAnchor c, float x, float y, float z)
{
//IL_000d: 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)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: 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_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_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
Dictionary<int, float> values = new Dictionary<int, float>();
Add(a.Weight, x);
Add(b.Weight, y);
Add(c.Weight, z);
SurfaceAnchor result = new SurfaceAnchor
{
Position = a.Position * x + b.Position * y + c.Position * z
};
Vector3 val = a.Normal * x + b.Normal * y + c.Normal * z;
result.Normal = ((Vector3)(ref val)).normalized;
result.Weight = Weights(values);
result.Color = a.Color * x + b.Color * y + c.Color * z;
return result;
void Add(BoneWeight w, float amount)
{
int[] array = new int[4]
{
((BoneWeight)(ref w)).boneIndex0,
((BoneWeight)(ref w)).boneIndex1,
((BoneWeight)(ref w)).boneIndex2,
((BoneWeight)(ref w)).boneIndex3
};
float[] array2 = new float[4]
{
((BoneWeight)(ref w)).weight0,
((BoneWeight)(ref w)).weight1,
((BoneWeight)(ref w)).weight2,
((BoneWeight)(ref w)).weight3
};
for (int i = 0; i < 4; i++)
{
if (array2[i] > 0f)
{
values[array[i]] = (values.TryGetValue(array[i], out var value) ? (value + array2[i] * amount) : (array2[i] * amount));
}
}
}
}
}
public readonly struct SurfaceSite
{
public readonly Vector3 Position;
public readonly Vector3 Normal;
public readonly int Region;
public readonly int Index;
public SurfaceSite(Vector3 position, Vector3 normal, int region, int index)
{
Position = position;
Normal = normal;
Region = region;
Index = index;
}
}
public readonly struct GrowthSite
{
public readonly SurfaceSite Surface;
public readonly float Scale;
public readonly float Angle;
public GrowthSite(SurfaceSite s, float scale, float angle)
{
Surface = s;
Scale = scale;
Angle = angle;
}
}
public static class GrowthLayout
{
public static uint Hash(int seed, int value)
{
int num = seed ^ (value * 747796405);
int num2 = (num ^ (num >>> 16)) * -2048144777;
int num3 = (num2 ^ (num2 >>> 13)) * -1028477379;
return (uint)(num3 ^ (num3 >>> 16));
}
public static List<GrowthSite> Build(IReadOnlyList<SurfaceSite> source, int seed)
{
List<GrowthSite> list = new List<GrowthSite>();
int[] array = (from r in source.Select((SurfaceSite s) => s.Region).Distinct()
orderby Hash(seed, r + 101)
select r).ToArray();
HashSet<int> hashSet = new HashSet<int>();
Dictionary<int, int> dictionary = new Dictionary<int, int>();
int step;
for (step = 0; step < 48; step++)
{
bool flag = false;
for (int num = 0; num < array.Length; num++)
{
if (flag)
{
break;
}
int region = array[(step + num) % array.Length];
int num2 = ((region == 0) ? 3 : 4);
if (dictionary.TryGetValue(region, out var value) && value >= num2)
{
continue;
}
foreach (SurfaceSite site in from s in source
where s.Region == region
orderby Hash(seed + step * 31, s.Index)
select s)
{
if (!hashSet.Contains(site.Index))
{
float scale = 0.9f + (float)(Hash(seed, site.Index + 911) % 1000) / 1000f * 0.2f;
if (!list.Any((GrowthSite other) => (double)Vector3.DistanceSquared(other.Surface.Position, site.Position) < Math.Pow(0.49f * Math.Max(scale, other.Scale), 2.0)))
{
list.Add(new GrowthSite(site, scale, (float)(Hash(seed, site.Index + 211) % 360) * (MathF.PI / 180f)));
hashSet.Add(site.Index);
dictionary[region] = value + 1;
flag = true;
break;
}
}
}
}
if (!flag)
{
break;
}
}
return list;
}
}
public readonly struct History : IEquatable<History>
{
public readonly float Burn;
public readonly float Spores;
public readonly float Cold;
public readonly float Poison;
public readonly int Seed;
public readonly string Order;
public const int TotalLimit = 48;
public const int KindLimit = 32;
public bool IsEmpty => (Order ?? "").Length == 0;
public string VisualKey => Seed + ":" + Order;
public History(float burn, float spores, float cold, float poison, int seed = 1729, string order = null)
{
Burn = Clamp(burn);
Spores = Clamp(spores);
Cold = Clamp(cold);
Poison = Clamp(poison);
Seed = seed;
Order = order ?? BuildOrder(Burn, Spores, Cold, Poison);
}
private static float Clamp(float v)
{
if (!float.IsNaN(v) && !float.IsInfinity(v))
{
return Math.Max(0f, Math.Min(300f, v));
}
return 0f;
}
public static float Threshold(int index)
{
return (float)(2.5 + 2.8 * (double)index + 0.137 * (double)index * (double)index);
}
public static int Count(float amount)
{
int i;
for (i = 0; i < 32 && amount + 0.0001f >= Threshold(i); i++)
{
}
return i;
}
public float Value(int channel)
{
return channel switch
{
2 => Cold,
1 => Spores,
0 => Burn,
_ => Poison,
};
}
private static string BuildOrder(params float[] values)
{
int[] array = new int[4];
StringBuilder stringBuilder = new StringBuilder();
while (stringBuilder.Length < 48)
{
int num = -1;
float num2 = float.MaxValue;
for (int i = 0; i < 4; i++)
{
if (array[i] < Count(values[i]))
{
float num3 = Threshold(array[i]) / values[i];
if (num3 < num2)
{
num2 = num3;
num = i;
}
}
}
if (num < 0)
{
break;
}
stringBuilder.Append((char)(48 + num));
array[num]++;
}
return stringBuilder.ToString();
}
public History Add(int channel, float amount)
{
if (channel < 0 || channel > 3 || float.IsNaN(amount) || float.IsInfinity(amount) || amount <= 0f)
{
return this;
}
float num = Burn;
float num2 = Spores;
float num3 = Cold;
float num4 = Poison;
switch (channel)
{
case 0:
num = Clamp(num + amount);
break;
case 1:
num2 = Clamp(num2 + amount);
break;
case 2:
num3 = Clamp(num3 + amount);
break;
case 3:
num4 = Clamp(num4 + amount);
break;
}
string text = Order ?? "";
int val = Count(channel switch
{
2 => num3,
1 => num2,
0 => num,
_ => num4,
}) - Count(Value(channel));
text += new string((char)(48 + channel), Math.Min(Math.Max(0, val), 48 - text.Length));
return new History(num, num2, num3, num4, (Seed == 0) ? 1729 : Seed, text);
}
public History WithSeed(int seed)
{
return new History(Burn, Spores, Cold, Poison, seed, Order ?? "");
}
public bool Equals(History h)
{
if (Burn == h.Burn && Spores == h.Spores && Cold == h.Cold && Poison == h.Poison && Seed == h.Seed)
{
return (Order ?? "") == (h.Order ?? "");
}
return false;
}
public string Encode(string run)
{
return string.Join("|", "2", run, Burn.ToString("R", CultureInfo.InvariantCulture), Spores.ToString("R", CultureInfo.InvariantCulture), Cold.ToString("R", CultureInfo.InvariantCulture), Poison.ToString("R", CultureInfo.InvariantCulture), Seed.ToString(CultureInfo.InvariantCulture), Order ?? "");
}
public static bool TryDecode(string text, string run, out History history)
{
history = default(History);
if (text == null || text.Length > 320)
{
return false;
}
string[] array = text.Split('|');
if (array.Length != 8 || array[0] != "2" || array[1] != run)
{
return false;
}
float[] array2 = new float[4];
for (int i = 0; i < 4; i++)
{
if (!float.TryParse(array[i + 2], NumberStyles.Float, CultureInfo.InvariantCulture, out array2[i]) || float.IsNaN(array2[i]) || float.IsInfinity(array2[i]) || array2[i] < 0f || array2[i] > 300f)
{
return false;
}
}
if (!int.TryParse(array[6], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || array[7].Length > 48)
{
return false;
}
int[] array3 = new int[4];
string text2 = array[7];
foreach (char c in text2)
{
if (c < '0' || c > '3')
{
return false;
}
if (++array3[c - 48] > Count(array2[c - 48]))
{
return false;
}
}
int num = Math.Min(48, Count(array2[0]) + Count(array2[1]) + Count(array2[2]) + Count(array2[3]));
if (array[7].Length != num)
{
return false;
}
history = new History(array2[0], array2[1], array2[2], array2[3], result, array[7]);
return true;
}
public static int StableSeed(string text)
{
uint num = 2166136261u;
string text2 = text ?? "";
foreach (char c in text2)
{
num ^= c;
num *= 16777619;
}
return (int)num;
}
public override string ToString()
{
return string.Format("Heat {0:0.#} | Spores {1:0.#} | Cold {2:0.#} | Poison {3:0.#} | Growth {4}/{5}", Burn, Spores, Cold, Poison, (Order ?? "").Length, 48);
}
}
internal static class MeshCache
{
private static readonly Dictionary<Mesh, Mesh> cache = new Dictionary<Mesh, Mesh>();
public static Mesh Get(Mesh mesh)
{
if (cache.TryGetValue(mesh, out var value))
{
return value;
}
Mesh[] array = cache.Keys.Where((Mesh k) => !Object.op_Implicit((Object)(object)k)).ToArray();
foreach (Mesh key in array)
{
if (Object.op_Implicit((Object)(object)cache[key]))
{
Object.Destroy((Object)(object)cache[key]);
}
cache.Remove(key);
}
value = ReadableMesh.Copy(mesh);
cache.Add(mesh, value);
return value;
}
public static void Clear()
{
foreach (KeyValuePair<Mesh, Mesh> item in cache)
{
if (Object.op_Implicit((Object)(object)item.Value) && (Object)(object)item.Value != (Object)(object)item.Key)
{
Object.Destroy((Object)(object)item.Value);
}
}
cache.Clear();
}
}
internal sealed class ModelTemplates
{
public Vector3[] Vertices;
public Vector3[] Normals;
public int[] Triangles;
public int[] Materials;
public Color[] Palette;
private static readonly Dictionary<string, ModelTemplates> loaded = new Dictionary<string, ModelTemplates>();
public static ModelTemplates Get(string name)
{
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_0157: Unknown result type (might be due to invalid IL or missing references)
//IL_015c: Unknown result type (might be due to invalid IL or missing references)
//IL_018f: Unknown result type (might be due to invalid IL or missing references)
//IL_0194: Unknown result type (might be due to invalid IL or missing references)
if (loaded.TryGetValue(name, out var value))
{
return value;
}
Assembly assembly = typeof(ModelTemplates).Assembly;
string name2 = assembly.GetManifestResourceNames().Single((string n) => n.EndsWith("." + name + ".tmsh", StringComparison.Ordinal));
using (Stream stream = assembly.GetManifestResourceStream(name2))
{
using BinaryReader binaryReader = new BinaryReader(stream);
if (binaryReader.ReadInt32() != 860705876)
{
throw new InvalidDataException("Unsupported TrailMarks mesh");
}
int num = binaryReader.ReadInt32();
int num2 = binaryReader.ReadInt32();
if (num <= 0 || num > 20000 || num2 <= 0 || num2 > 120000 || num2 % 3 != 0)
{
throw new InvalidDataException("Invalid mesh size");
}
value = new ModelTemplates
{
Vertices = (Vector3[])(object)new Vector3[num],
Normals = (Vector3[])(object)new Vector3[num],
Triangles = new int[num2],
Materials = new int[num2 / 3],
Palette = (Color[])(object)new Color[3]
};
for (int num3 = 0; num3 < 3; num3++)
{
value.Palette[num3] = new Color(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), 1f);
}
for (int num4 = 0; num4 < num; num4++)
{
value.Vertices[num4] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
}
for (int num5 = 0; num5 < num; num5++)
{
value.Normals[num5] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
}
for (int num6 = 0; num6 < num2; num6++)
{
int num7 = binaryReader.ReadInt32();
if (num7 < 0 || num7 >= num)
{
throw new InvalidDataException("Invalid mesh index");
}
value.Triangles[num6] = num7;
}
for (int num8 = 0; num8 < num2 / 3; num8++)
{
int num9 = binaryReader.ReadInt32();
if (num9 < 0 || num9 > 2)
{
throw new InvalidDataException("Invalid palette slot");
}
value.Materials[num8] = num9;
}
if (stream.Position != stream.Length)
{
throw new InvalidDataException("Trailing mesh data");
}
}
loaded.Add(name, value);
return value;
}
}
[BepInPlugin("trailmarks.core", "TrailMarks", "0.2.0")]
public sealed class Plugin : BaseUnityPlugin
{
private sealed class VisualEntry
{
public TrailVisual Visual;
public History History;
public Material Material;
public Color Skin;
}
private const string Property = "TrailMarks.v2";
private History preview;
private string run = "";
private string lastPublished = "";
private float nextRefresh;
private float nextPublish;
private bool dirty;
private ConfigEntry<float> growthCost;
private Harmony harmony;
private readonly Dictionary<int, VisualEntry> visuals = new Dictionary<int, VisualEntry>();
private readonly Dictionary<int, float> retryAfter = new Dictionary<int, float>();
public static Plugin Instance { get; private set; }
public History LocalHistory { get; private set; }
public bool PreviewEnabled { get; private set; }
public bool CanEditHistory
{
get
{
if (run.Length > 0 && Object.op_Implicit((Object)(object)Character.localCharacter))
{
return !Character.localCharacter.inAirport;
}
return false;
}
}
public string PreviewStatus { get; private set; } = "Waiting for character";
public History PreviewHistory
{
get
{
if (!PreviewEnabled)
{
return new History(0f, 0f, 0f, 0f, (LocalHistory.Seed == 0) ? 1729 : LocalHistory.Seed);
}
return preview;
}
}
private string SaveFile => Path.Combine(Paths.ConfigPath, "TrailMarks.v2.last-run.txt");
public void SetPreviewHistory(History h)
{
PreviewEnabled = true;
preview = h;
nextRefresh = 0f;
}
private void Awake()
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected O, but got Unknown
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
Instance = this;
growthCost = ((BaseUnityPlugin)this).Config.Bind<float>("Growth", "Exposure cost multiplier", 1f, new ConfigDescription("Lower = faster growth. Only affects future accepted exposure, not saved history.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
harmony = new Harmony("trailmarks.core");
harmony.PatchAll(typeof(Plugin).Assembly);
SceneManager.activeSceneChanged += OnScene;
((BaseUnityPlugin)this).Logger.LogInfo((object)"TrailMarks 0.2.0 ready. Automatic history enabled.");
}
private void OnScene(Scene previous, Scene current)
{
//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_0090: Expected O, but got Unknown
//IL_0097: Expected O, but got Unknown
ClearVisuals();
MeshCache.Clear();
AttachmentSurface.Clear();
retryAfter.Clear();
if (((Scene)(ref current)).name == "Airport" || ((Scene)(ref current)).name == "Title")
{
Save();
run = "";
LocalHistory = default(History);
PreviewEnabled = false;
lastPublished = "";
if (PhotonNetwork.LocalPlayer != null)
{
Player localPlayer = PhotonNetwork.LocalPlayer;
Hashtable val = new Hashtable();
((Dictionary<object, object>)val).Add((object)"TrailMarks.v2", (object)null);
localPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
}
}
nextRefresh = 0f;
}
private void RefreshRun()
{
if (!Object.op_Implicit((Object)(object)RunManager.Instance))
{
return;
}
Guid runId = RunManager.Instance.RunId;
if (runId == Guid.Empty || runId.ToString("N") == run)
{
return;
}
bool num = run.Length == 0;
run = runId.ToString("N");
if (!num)
{
LocalHistory = default(History);
}
bool flag = false;
try
{
if (File.Exists(SaveFile) && History.TryDecode(File.ReadAllText(SaveFile), run, out var history))
{
LocalHistory = history.Add(0, LocalHistory.Burn).Add(1, LocalHistory.Spores).Add(2, LocalHistory.Cold)
.Add(3, LocalHistory.Poison);
flag = true;
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("History restore: " + ex.Message));
}
if (!flag)
{
History localHistory = LocalHistory;
string text = run;
Player localPlayer = PhotonNetwork.LocalPlayer;
LocalHistory = localHistory.WithSeed(History.StableSeed(text + "|" + ((localPlayer != null) ? new int?(localPlayer.ActorNumber) : ((int?)null))));
}
dirty = true;
lastPublished = "";
ClearVisuals();
retryAfter.Clear();
}
public void SetPreview(bool enabled, float burn, float spores, float cold, float poison)
{
PreviewEnabled = enabled;
int num = ((LocalHistory.Seed == 0) ? 1729 : LocalHistory.Seed);
if (preview.Burn != burn || preview.Spores != spores || preview.Cold != cold || preview.Poison != poison || preview.Seed != num)
{
preview = new History(burn, spores, cold, poison, num);
}
nextRefresh = 0f;
}
public void SetLocalHistory(float burn, float spores, float cold, float poison)
{
if (CanEditHistory)
{
LocalHistory = ((PreviewEnabled && preview.Burn == burn && preview.Spores == spores && preview.Cold == cold && preview.Poison == poison) ? preview.WithSeed(LocalHistory.Seed) : new History(burn, spores, cold, poison, LocalHistory.Seed));
dirty = true;
nextRefresh = 0f;
}
}
internal void Record(CharacterAfflictions afflictions, STATUSTYPE type, float before)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Invalid comparison between Unknown and I4
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Invalid comparison between Unknown and I4
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Invalid comparison between Unknown and I4
//IL_0065: 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_003f: Invalid comparison between Unknown and I4
if (!Object.op_Implicit((Object)(object)Character.localCharacter) || Character.localCharacter.inAirport || (Object)(object)Character.localCharacter.refs.afflictions != (Object)(object)afflictions)
{
return;
}
int num = (((int)type != 8) ? (((int)type == 10) ? 1 : (((int)type == 2) ? 2 : (((int)type == 3) ? 3 : (-1)))) : 0);
if (num >= 0)
{
RefreshRun();
History localHistory = LocalHistory.Add(num, (afflictions.GetCurrentStatus(type) - before) * 100f / growthCost.Value);
if (!localHistory.Equals(LocalHistory))
{
LocalHistory = localHistory;
dirty = true;
}
}
}
private void Update()
{
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Expected O, but got Unknown
//IL_00a6: Expected O, but got Unknown
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_0230: Unknown result type (might be due to invalid IL or missing references)
//IL_022b: Unknown result type (might be due to invalid IL or missing references)
//IL_0317: Unknown result type (might be due to invalid IL or missing references)
//IL_0319: Unknown result type (might be due to invalid IL or missing references)
//IL_028c: Unknown result type (might be due to invalid IL or missing references)
//IL_0291: Unknown result type (might be due to invalid IL or missing references)
if (Time.unscaledTime < nextRefresh)
{
return;
}
nextRefresh = Time.unscaledTime + 0.5f;
RefreshRun();
if (Time.unscaledTime >= nextPublish)
{
nextPublish = Time.unscaledTime + 1f;
if (run.Length > 0 && PhotonNetwork.InRoom)
{
string text = LocalHistory.Encode(run);
if (text != lastPublished)
{
Player localPlayer = PhotonNetwork.LocalPlayer;
Hashtable val = new Hashtable();
((Dictionary<object, object>)val).Add((object)"TrailMarks.v2", (object)text);
if (localPlayer.SetCustomProperties(val, (Hashtable)null, (WebFlags)null))
{
lastPublished = text;
}
}
}
Save();
}
HashSet<int> live = new HashSet<int>();
int num = 0;
int num2 = 0;
CharacterCustomization[] array = Object.FindObjectsByType<CharacterCustomization>((FindObjectsSortMode)0);
foreach (CharacterCustomization val2 in array)
{
SkinnedMeshRenderer val3 = val2.refs?.mainRenderer;
if (!Object.op_Implicit((Object)(object)val3) || !Object.op_Implicit((Object)(object)val3.sharedMesh))
{
continue;
}
Character component = ((Component)val2).GetComponent<Character>();
Player val4 = val2.overridePhotonPlayer ?? (Object.op_Implicit((Object)(object)component) ? ((MonoBehaviourPun)component).photonView.Owner : null);
bool num3 = val4 != null && val4 == PhotonNetwork.LocalPlayer;
History history = default(History);
if (num3)
{
history = (PreviewEnabled ? preview : LocalHistory);
}
else if (val4 != null && run.Length > 0 && ((Dictionary<object, object>)(object)val4.CustomProperties).ContainsKey((object)"TrailMarks.v2"))
{
History.TryDecode(val4.CustomProperties[(object)"TrailMarks.v2"] as string, run, out history);
}
int instanceID = ((Object)val3).GetInstanceID();
if (history.IsEmpty)
{
continue;
}
live.Add(instanceID);
if (retryAfter.TryGetValue(instanceID, out var value) && Time.unscaledTime < value)
{
continue;
}
Material val5 = ((Renderer)val3).sharedMaterials.FirstOrDefault();
Color val6 = ((Object.op_Implicit((Object)(object)val5) && val5.HasProperty("_SkinColor")) ? val5.GetColor("_SkinColor") : Color.white);
if (visuals.TryGetValue(instanceID, out var value2) && (Object)(object)value2.Visual.OriginalMesh == (Object)(object)val3.sharedMesh && value2.History.VisualKey == history.VisualKey && (Object)(object)value2.Material == (Object)(object)val5 && value2.Skin == val6 && value2.Visual.CostumeSignature == TrailVisual.Signature(val2))
{
num++;
num2 += value2.Visual.GrowthCount;
continue;
}
value2?.Visual.Dispose();
visuals.Remove(instanceID);
try
{
visuals[instanceID] = new VisualEntry
{
Visual = TrailVisual.Create(val2, history),
History = history,
Material = val5,
Skin = val6
};
num++;
num2 += visuals[instanceID].Visual.GrowthCount;
}
catch (Exception ex)
{
retryAfter[instanceID] = Time.unscaledTime + 30f;
((BaseUnityPlugin)this).Logger.LogWarning((object)("Appearance skipped for " + ((Object)val3).name + ": " + ex.Message));
}
}
int[] array2 = visuals.Keys.Where((int k) => !live.Contains(k) || !Object.op_Implicit((Object)(object)visuals[k].Visual.Source)).ToArray();
foreach (int key in array2)
{
visuals[key].Visual.Dispose();
visuals.Remove(key);
}
PreviewStatus = ((!Object.op_Implicit((Object)(object)Character.localCharacter)) ? "Waiting for local character | " : "") + (PreviewEnabled ? "Preview (local only)" : "Natural history") + " | renderers: " + num + " | drawn growth units: " + num2 + "\n" + (PreviewEnabled ? preview : LocalHistory);
}
private void Save()
{
if (!dirty || run.Length == 0)
{
return;
}
try
{
File.WriteAllText(SaveFile, LocalHistory.Encode(run));
dirty = false;
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("History save: " + ex.Message));
}
}
private void ClearVisuals()
{
foreach (VisualEntry value in visuals.Values)
{
value.Visual.Dispose();
}
visuals.Clear();
}
private void OnDestroy()
{
Save();
SceneManager.activeSceneChanged -= OnScene;
Harmony obj = harmony;
if (obj != null)
{
obj.UnpatchSelf();
}
ClearVisuals();
MeshCache.Clear();
AttachmentSurface.Clear();
Instance = null;
}
}
[HarmonyPatch(typeof(CharacterAfflictions), "AddStatus")]
internal static class AcceptedStatusPatch
{
private static void Prefix(CharacterAfflictions __instance, STATUSTYPE statusType, out float __state)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
__state = __instance.GetCurrentStatus(statusType);
}
private static void Postfix(CharacterAfflictions __instance, STATUSTYPE statusType, float __state)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
Plugin.Instance?.Record(__instance, statusType, __state);
}
}
internal static class ReadableMesh
{
public static Mesh Copy(Mesh source)
{
//IL_000a: 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_0026: Expected O, but got Unknown
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
if (source.isReadable)
{
return source;
}
Mesh val = new Mesh
{
name = ((Object)source).name + "_TrailMarksReadable"
};
try
{
val.SetVertexBufferParams(source.vertexCount, source.GetVertexAttributes());
for (int i = 0; i < source.vertexBufferCount; i++)
{
GraphicsBuffer vertexBuffer = source.GetVertexBuffer(i);
try
{
if (vertexBuffer == null)
{
throw new InvalidOperationException("GPU vertex buffer unavailable");
}
byte[] array = new byte[vertexBuffer.count * vertexBuffer.stride];
vertexBuffer.GetData((Array)array);
val.SetVertexBufferData<byte>(array, 0, 0, array.Length, i, (MeshUpdateFlags)8);
}
finally
{
((IDisposable)vertexBuffer)?.Dispose();
}
}
GraphicsBuffer indexBuffer = source.GetIndexBuffer();
try
{
if (indexBuffer == null)
{
throw new InvalidOperationException("GPU index buffer unavailable");
}
int count = indexBuffer.count;
val.SetIndexBufferParams(count, source.indexFormat);
if ((int)source.indexFormat == 0)
{
ushort[] array2 = new ushort[count];
indexBuffer.GetData((Array)array2);
val.SetIndexBufferData<ushort>(array2, 0, 0, count, (MeshUpdateFlags)0);
}
else
{
uint[] array3 = new uint[count];
indexBuffer.GetData((Array)array3);
val.SetIndexBufferData<uint>(array3, 0, 0, count, (MeshUpdateFlags)0);
}
}
finally
{
((IDisposable)indexBuffer)?.Dispose();
}
val.subMeshCount = source.subMeshCount;
for (int j = 0; j < source.subMeshCount; j++)
{
val.SetSubMesh(j, source.GetSubMesh(j), (MeshUpdateFlags)8);
}
val.bindposes = source.bindposes;
BoneWeight[] boneWeights = source.boneWeights;
if (boneWeights.Length == source.vertexCount)
{
val.boneWeights = boneWeights;
}
val.bounds = source.bounds;
if (val.vertices.Length != source.vertexCount)
{
throw new InvalidOperationException("GPU copy lacks complete vertex/skin data");
}
return val;
}
catch
{
Object.Destroy((Object)(object)val);
throw;
}
}
}
internal sealed class TrailVisual : IDisposable
{
public SkinnedMeshRenderer Source;
public Mesh OriginalMesh;
public string CostumeSignature;
public int GrowthCount;
private GameObject root;
private readonly List<Object> owned = new List<Object>();
public static IEnumerable<Renderer> Parts(CharacterCustomization customization)
{
CustomizationRefs refs = customization.refs;
return (from r in ((IEnumerable<Renderer>)(object)new Renderer[4]
{
(Renderer)refs.mainRenderer,
refs.shorts,
refs.skirt,
refs.sashRenderer
}).Concat(refs.PlayerRenderers ?? Array.Empty<Renderer>())
where Object.op_Implicit((Object)(object)r) && ((Component)r).gameObject.activeInHierarchy && Object.op_Implicit((Object)(object)MeshOf(r)) && !((Object)r).name.ToLowerInvariant().Contains("shadow") && !((Object)r).name.ToLowerInvariant().Contains("eye") && !((Object)r).name.ToLowerInvariant().Contains("mouth")
select r).Distinct();
}
public static Mesh MeshOf(Renderer r)
{
SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((r is SkinnedMeshRenderer) ? r : null);
if (val == null)
{
MeshFilter component = ((Component)r).GetComponent<MeshFilter>();
if (component == null)
{
return null;
}
return component.sharedMesh;
}
return val.sharedMesh;
}
public static string Signature(CharacterCustomization c)
{
return string.Join(";", from r in Parts(c)
select ((Object)r).GetInstanceID() + ":" + ((Object)MeshOf(r)).GetInstanceID());
}
public static TrailVisual Create(CharacterCustomization customization, History history)
{
TrailVisual trailVisual = new TrailVisual
{
Source = customization.refs.mainRenderer
};
trailVisual.OriginalMesh = trailVisual.Source.sharedMesh;
trailVisual.CostumeSignature = Signature(customization);
try
{
trailVisual.Build(customization, history);
return trailVisual;
}
catch
{
trailVisual.Dispose();
throw;
}
}
private void Build(CharacterCustomization customization, History history)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Expected O, but got Unknown
//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0210: Unknown result type (might be due to invalid IL or missing references)
//IL_025e: Unknown result type (might be due to invalid IL or missing references)
AttachmentSurface attachmentSurface = AttachmentSurface.Build(Source, Parts(customization));
List<GrowthSite> list = GrowthLayout.Build(attachmentSurface.Sites, history.Seed);
root = new GameObject("TrailMarks_Growth");
root.transform.SetParent(((Component)Source).transform, false);
GrowthMesh[] array = new GrowthMesh[4]
{
new GrowthMesh(),
new GrowthMesh(),
new GrowthMesh(),
new GrowthMesh()
};
int[] array2 = new int[4];
string text = history.Order ?? "";
for (int i = 0; i < Math.Min(list.Count, text.Length); i++)
{
int num = text[i] - 48;
int num2 = array2[num]++;
GrowthSite growthSite = list[i];
SurfaceAnchor anchor = attachmentSurface.Anchors[growthSite.Surface.Index];
array[num].Append(ModelTemplates.Get(num switch
{
2 => "frost",
1 => (num2 < 5) ? "spore_small" : "spore_cluster",
0 => "lava",
_ => "toxin",
}), anchor, growthSite.Scale, growthSite.Angle);
GrowthCount++;
}
TrailVisibility trailVisibility = root.AddComponent<TrailVisibility>();
trailVisibility.Source = Source;
List<SkinnedMeshRenderer> list2 = new List<SkinnedMeshRenderer>();
for (int j = 0; j < 4; j++)
{
GrowthMesh growthMesh = array[j];
if (growthMesh.Count != 0)
{
Mesh val = growthMesh.ToMesh(MeshCache.Get(OriginalMesh).bindposes);
owned.Add((Object)(object)val);
GameObject val2 = new GameObject("TrailMarks_" + (new string[4] { "Lava", "Spores", "Frost", "Toxin" })[j]);
val2.transform.SetParent(root.transform, false);
val2.layer = ((Component)Source).gameObject.layer;
SkinnedMeshRenderer val3 = val2.AddComponent<SkinnedMeshRenderer>();
val3.sharedMesh = val;
val3.bones = Source.bones;
val3.rootBone = Source.rootBone;
((Renderer)val3).localBounds = val.bounds;
val3.updateWhenOffscreen = Source.updateWhenOffscreen;
((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0;
((Renderer)val3).sharedMaterials = growthMesh.Palette.Select((Color color) => MakeMaterial(color)).ToArray();
list2.Add(val3);
}
}
trailVisibility.Layers = list2.ToArray();
trailVisibility.Materials = owned.OfType<Material>().ToArray();
}
private Material MakeMaterial(Color color)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Expected O, but got Unknown
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
Material val = new Material(((Renderer)Source).sharedMaterials[0]);
owned.Add((Object)(object)val);
((Object)val).name = "TrailMarks_SolidGeometry";
if (val.HasProperty("_SkinColor"))
{
val.SetColor("_SkinColor", color);
}
if (val.HasProperty("_UseSkinTone"))
{
val.SetFloat("_UseSkinTone", 1f);
}
if (val.HasProperty("_MainTex"))
{
val.SetTexture("_MainTex", (Texture)(object)Texture2D.whiteTexture);
}
if (val.HasProperty("_UseRawVertexColor"))
{
val.SetFloat("_UseRawVertexColor", 0f);
}
return val;
}
public void Dispose()
{
if (Object.op_Implicit((Object)(object)root))
{
Object.Destroy((Object)(object)root);
}
foreach (Object item in owned)
{
if (Object.op_Implicit(item))
{
Object.Destroy(item);
}
}
owned.Clear();
}
}
public sealed class TrailVisibility : MonoBehaviour
{
public SkinnedMeshRenderer Source;
public SkinnedMeshRenderer[] Layers = Array.Empty<SkinnedMeshRenderer>();
public Material[] Materials = Array.Empty<Material>();
private static readonly string[] VisibilityProperties = new string[3] { "_VertexGhost", "_Opacity", "_Stepalphabyvertexcolor" };
private void LateUpdate()
{
SkinnedMeshRenderer[] layers = Layers;
foreach (SkinnedMeshRenderer val in layers)
{
if (Object.op_Implicit((Object)(object)val))
{
((Renderer)val).enabled = Object.op_Implicit((Object)(object)Source) && ((Renderer)Source).enabled;
if (Object.op_Implicit((Object)(object)Source))
{
((Renderer)val).forceRenderingOff = ((Renderer)Source).forceRenderingOff;
((Component)val).gameObject.layer = ((Component)Source).gameObject.layer;
}
}
}
Material val2 = (Object.op_Implicit((Object)(object)Source) ? ((Renderer)Source).sharedMaterial : null);
if (!Object.op_Implicit((Object)(object)val2))
{
return;
}
Material[] materials = Materials;
foreach (Material val3 in materials)
{
string[] visibilityProperties = VisibilityProperties;
foreach (string text in visibilityProperties)
{
if (val2.HasProperty(text) && val3.HasProperty(text))
{
val3.SetFloat(text, val2.GetFloat(text));
}
}
}
}
}
internal sealed class GrowthMesh
{
private readonly List<Vector3> points = new List<Vector3>();
private readonly List<Vector3> normals = new List<Vector3>();
private readonly List<BoneWeight> weights = new List<BoneWeight>();
private readonly List<Color> colors = new List<Color>();
private readonly List<int>[] triangles = new List<int>[3]
{
new List<int>(),
new List<int>(),
new List<int>()
};
public Color[] Palette;
public int Count => points.Count;
public void Append(ModelTemplates model, SurfaceAnchor anchor, float scale, float angle)
{
//IL_0013: 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_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: 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_002d: 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_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: 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_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: 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_00c5: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: 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_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: Unknown result type (might be due to invalid IL or missing references)
//IL_016e: Unknown result type (might be due to invalid IL or missing references)
//IL_0176: Unknown result type (might be due to invalid IL or missing references)
//IL_0177: 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_018c: Unknown result type (might be due to invalid IL or missing references)
//IL_0191: 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_0197: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: Unknown result type (might be due to invalid IL or missing references)
//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
Palette = model.Palette;
Vector3 normalized = ((Vector3)(ref anchor.Normal)).normalized;
Vector3 val = Vector3.Cross(normalized, Vector3.up);
Vector3 normalized2 = ((Vector3)(ref val)).normalized;
if (((Vector3)(ref normalized2)).sqrMagnitude < 0.1f)
{
val = Vector3.Cross(normalized, Vector3.right);
normalized2 = ((Vector3)(ref val)).normalized;
}
Vector3 val2 = Vector3.Cross(normalized, normalized2);
Vector3 val3 = normalized2 * Mathf.Cos(angle) + val2 * Mathf.Sin(angle);
Vector3 val4 = -normalized2 * Mathf.Sin(angle) + val2 * Mathf.Cos(angle);
int count = points.Count;
Vector3[] vertices = model.Vertices;
foreach (Vector3 val5 in vertices)
{
points.Add(anchor.Position + normalized * 0.025f + (val3 * val5.x + val4 * val5.y + normalized * val5.z) * scale);
weights.Add(anchor.Weight);
colors.Add(anchor.Color);
}
vertices = model.Normals;
foreach (Vector3 val6 in vertices)
{
List<Vector3> list = normals;
val = val3 * val6.x + val4 * val6.y + normalized * val6.z;
list.Add(((Vector3)(ref val)).normalized);
}
for (int j = 0; j < model.Triangles.Length; j++)
{
triangles[model.Materials[j / 3]].Add(count + model.Triangles[j]);
}
}
public Mesh ToMesh(Matrix4x4[] bindposes)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected O, but got Unknown
Mesh val = new Mesh
{
name = "TrailMarks_GrowthMesh",
indexFormat = (IndexFormat)(points.Count > 65535)
};
val.SetVertices(points);
val.subMeshCount = 3;
for (int i = 0; i < 3; i++)
{
val.SetTriangles(triangles[i], i);
}
val.boneWeights = weights.ToArray();
val.bindposes = bindposes;
val.colors = colors.ToArray();
val.uv = (Vector2[])(object)new Vector2[points.Count];
val.normals = normals.ToArray();
val.RecalculateBounds();
return val;
}
}
}