using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BoneLib;
using BoneLib.BoneMenu;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.VRMK;
using Il2CppSystem;
using MelonLoader;
using Microsoft.CodeAnalysis;
using OffsetRemover;
using UnityEngine;
using UnityEngine.Rendering;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "Head Offset Remover", "1.0.0", "Hiiiiii :3", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace OffsetRemover
{
internal sealed class BonePair
{
public Transform src;
public Transform dst;
public bool isHeadSubtree;
public Vector3 headRestLocal;
}
internal sealed class RendererPair
{
public Renderer src;
public Renderer dst;
public bool forceDisable;
}
public class Core : MelonMod
{
private enum CameraKind
{
Headset,
Spectator,
Other
}
public static GameObject headlessAvatarClone;
public static Animator headlessAvatarCloneAnimator;
public static bool IsEnabled = true;
public static bool ignoreSpectator = true;
private static BonePair[] bonePairsArr = new BonePair[0];
private static int bonePairCount = 0;
private static RendererPair[] rendererPairsArr = new RendererPair[0];
private static int rendererPairCount = 0;
private static readonly Dictionary<int, CameraKind> cameraKindCache = new Dictionary<int, CameraKind>();
private static Transform headBoneOnClone;
private static Transform headBoneOnSource;
private static Vector3 headLocalRestPosition;
private static Quaternion headLocalRestRotation;
private static bool hasHeadCorrection;
private static Dictionary<string, Vector3> headSubtreeLocalPositions = new Dictionary<string, Vector3>(StringComparer.OrdinalIgnoreCase);
private static List<Renderer> selfRenderers = new List<Renderer>(64);
private static List<Renderer> cloneAvatarRenderers = new List<Renderer>(64);
private static int cloneBuiltForAvatarId = 0;
private static volatile bool buildInProgress = false;
private static float lastBuildAttemptTime = -999f;
private const float RetryCooldownSeconds = 3f;
private const float MinAcceptableRendererFraction = 0.5f;
private static float lastErrorLogTime = -999f;
private const float ErrorLogCooldownSeconds = 5f;
private static readonly StringBuilder pathSb = new StringBuilder(256);
private static readonly string[] nameStack = new string[64];
private static int lastSyncedFrame = -1;
private static readonly HashSet<string> ExcludedBoneNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private static readonly HashSet<Transform> boneCollectScratch = new HashSet<Transform>();
private static CameraKind ClassifyCamera(Camera cam)
{
int instanceID = ((Object)cam).GetInstanceID();
if (cameraKindCache.TryGetValue(instanceID, out var value))
{
return value;
}
value = ((!(((Object)cam).name == "Headset")) ? ((((Object)cam).name == "Spectator Camera") ? CameraKind.Spectator : CameraKind.Other) : CameraKind.Headset);
cameraKindCache[instanceID] = value;
return value;
}
public override void OnInitializeMelon()
{
//IL_0067: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
MelonLogger.Msg("[OffsetRemover] Community Patch loaded.");
RenderPipelineManager.beginCameraRendering += Action<ScriptableRenderContext, Camera>.op_Implicit((Action<ScriptableRenderContext, Camera>)OnBeginCameraRendering);
Hooking.OnSwitchAvatarPostfix += delegate
{
if (IsEnabled)
{
MelonCoroutines.Start(RebuildClone(Player.RigManager));
}
};
Page obj = Page.Root.CreatePage("OffsetRemover", Color.green, 0, true);
obj.CreateBool("Enable OffsetRemover", Color.white, IsEnabled, (Action<bool>)delegate(bool v)
{
IsEnabled = v;
if (!v)
{
DisableAndCleanUp();
ApplyVisibilityToAllCameras();
}
else
{
ForceRebuild();
ApplyVisibilityToAllCameras();
}
});
obj.CreateBool("Don't Fix Spectator Camera", Color.yellow, ignoreSpectator, (Action<bool>)delegate(bool v)
{
ignoreSpectator = v;
ApplyVisibilityToAllCameras();
});
obj.CreateFunction("Rebuild Clone", Color.red, (Action)ForceRebuild);
MelonCoroutines.Start(SelfHealLoop());
}
private static void DisableAndCleanUp()
{
RigManager rigManager = Player.RigManager;
if ((Object)(object)rigManager != (Object)null && Object.op_Implicit((Object)(object)rigManager.avatar))
{
Il2CppArrayBase<Renderer> componentsInChildren = ((Component)rigManager.avatar).gameObject.GetComponentsInChildren<Renderer>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
if (!((Object)(object)componentsInChildren[i] == (Object)null))
{
try
{
componentsInChildren[i].forceRenderingOff = false;
}
catch
{
}
}
}
}
if ((Object)(object)headlessAvatarClone != (Object)null)
{
Object.DestroyImmediate((Object)(object)headlessAvatarClone);
}
ResetCloneState();
}
private static void ApplyVisibilityToAllCameras()
{
try
{
foreach (Camera item in (Il2CppArrayBase<Camera>)(object)Camera.allCameras)
{
if ((Object)(object)item != (Object)null)
{
CheckRenderLoop(ClassifyCamera(item));
}
}
}
catch
{
}
}
private static void OnBeginCameraRendering(ScriptableRenderContext ctx, Camera cam)
{
if (!IsEnabled)
{
return;
}
try
{
CameraKind num = ClassifyCamera(cam);
if (num != CameraKind.Headset)
{
SyncCloneIfNeeded();
}
CheckRenderLoop(num);
}
catch (Exception value)
{
if (Time.time - lastErrorLogTime > 5f)
{
lastErrorLogTime = Time.time;
MelonLogger.Error($"[OffsetRemover] Render hook error: {value}");
}
}
}
private static IEnumerator SelfHealLoop()
{
while (true)
{
yield return (object)new WaitForSeconds(2f);
if (!IsEnabled)
{
continue;
}
RigManager rigManager = Player.RigManager;
if (!((Object)(object)rigManager == (Object)null) && Object.op_Implicit((Object)(object)rigManager.avatar))
{
int instanceID = ((Object)rigManager.avatar).GetInstanceID();
if ((!((Object)(object)headlessAvatarClone != (Object)null) || cloneBuiltForAvatarId != instanceID) && !buildInProgress && Time.time - lastBuildAttemptTime > 3f)
{
MelonCoroutines.Start(RebuildClone(rigManager));
}
}
}
}
private static void SyncCloneIfNeeded()
{
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)headlessAvatarCloneAnimator == (Object)null || Time.frameCount == lastSyncedFrame)
{
return;
}
lastSyncedFrame = Time.frameCount;
try
{
BonePair[] array = bonePairsArr;
for (int i = 0; i < bonePairCount; i++)
{
BonePair bonePair = array[i];
Transform src = bonePair.src;
Transform dst = bonePair.dst;
if (!((Object)(object)src == (Object)null) && !((Object)(object)dst == (Object)null))
{
if (bonePair.isHeadSubtree)
{
dst.localPosition = bonePair.headRestLocal;
dst.localRotation = src.localRotation;
}
else
{
dst.SetPositionAndRotation(src.position, src.rotation);
}
}
}
RendererPair[] array2 = rendererPairsArr;
for (int j = 0; j < rendererPairCount; j++)
{
RendererPair rendererPair = array2[j];
Renderer src2 = rendererPair.src;
Renderer dst2 = rendererPair.dst;
if (!((Object)(object)src2 == (Object)null) && !((Object)(object)dst2 == (Object)null))
{
if (rendererPair.forceDisable)
{
dst2.forceRenderingOff = true;
continue;
}
dst2.forceRenderingOff = false;
dst2.enabled = src2.enabled && ((Component)src2).gameObject.activeInHierarchy;
}
}
if (hasHeadCorrection && (Object)(object)headBoneOnSource == (Object)null && (Object)(object)headBoneOnClone != (Object)null)
{
headBoneOnClone.localRotation = headLocalRestRotation;
}
}
catch (Exception ex)
{
if (Time.time - lastErrorLogTime > 5f)
{
lastErrorLogTime = Time.time;
MelonLogger.Warning("[OffsetRemover] Clone sync failed, rebuilding: " + ex.Message);
}
if ((Object)(object)headlessAvatarClone != (Object)null)
{
Object.DestroyImmediate((Object)(object)headlessAvatarClone);
}
ResetCloneState();
}
}
public static void ForceRebuild()
{
if (!IsEnabled)
{
MelonLogger.Msg("[OffsetRemover] Rebuild ignored -- disabled.");
return;
}
RigManager rigManager = Player.RigManager;
if ((Object)(object)rigManager == (Object)null)
{
MelonLogger.Warning("[OffsetRemover] Rebuild: no RigManager.");
}
else
{
MelonCoroutines.Start(RebuildClone(rigManager));
}
}
private static IEnumerator RebuildClone(RigManager manager)
{
if (buildInProgress)
{
yield break;
}
buildInProgress = true;
lastBuildAttemptTime = Time.time;
cameraKindCache.Clear();
if ((Object)(object)headlessAvatarClone != (Object)null)
{
Object.DestroyImmediate((Object)(object)headlessAvatarClone);
}
ResetCloneState();
float waitStart = Time.time;
while ((Object)(object)manager == (Object)null || !Object.op_Implicit((Object)(object)manager.avatar) || (Object)(object)manager.avatar.animator == (Object)null || ((Component)manager.avatar).gameObject.GetComponentsInChildren<SkinnedMeshRenderer>(true).Length == 0)
{
if (Time.time - waitStart > 5f)
{
buildInProgress = false;
yield break;
}
yield return null;
}
selfRenderers.Clear();
Il2CppArrayBase<Renderer> componentsInChildren = ((Component)manager.avatar).gameObject.GetComponentsInChildren<Renderer>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
selfRenderers.Add(componentsInChildren[i]);
}
GameObject val = null;
bool flag = true;
try
{
GameObject val2 = new GameObject("DISABLED CONTAINER");
val2.SetActive(false);
val = Object.Instantiate<GameObject>(((Component)manager.avatar).gameObject, val2.transform);
CleanClone(val);
val.transform.parent = null;
Object.Destroy((Object)(object)val2);
}
catch (Exception ex)
{
flag = false;
_ = "instantiate/clean: " + ex.Message;
}
if (!flag)
{
if ((Object)(object)val != (Object)null)
{
Object.DestroyImmediate((Object)(object)val);
}
ResetCloneState();
buildInProgress = false;
yield break;
}
cloneAvatarRenderers.Clear();
Il2CppArrayBase<Renderer> componentsInChildren2 = val.GetComponentsInChildren<Renderer>(true);
for (int j = 0; j < componentsInChildren2.Length; j++)
{
cloneAvatarRenderers.Add(componentsInChildren2[j]);
}
int length = componentsInChildren.Length;
Avatar componentInChildren = val.GetComponentInChildren<Avatar>();
Animator clnAnim = (((Object)(object)componentInChildren != (Object)null) ? componentInChildren.animator : null);
try
{
BuildPairings(manager.avatar.animator, clnAnim, ((Component)manager.avatar).gameObject, val);
}
catch (Exception ex2)
{
flag = false;
_ = "pairing: " + ex2.Message;
}
if (length > 0 && (float)cloneAvatarRenderers.Count < (float)length * 0.5f)
{
flag = false;
}
if (!flag)
{
if ((Object)(object)val != (Object)null)
{
Object.DestroyImmediate((Object)(object)val);
}
ResetCloneState();
buildInProgress = false;
yield break;
}
((Object)val).name = "HEADFIX DISPLAY CLONE";
headlessAvatarClone = val;
headlessAvatarCloneAnimator = clnAnim;
cloneBuiltForAvatarId = ((Object)manager.avatar).GetInstanceID();
buildInProgress = false;
ApplyVisibilityToAllCameras();
MelonLogger.Msg($"[OffsetRemover] Clone built -- bonePairs={bonePairCount}, renderers={cloneAvatarRenderers.Count}, headCorrection={(hasHeadCorrection ? "yes" : "no")}");
}
private static void BuildPairings(Animator srcAnim, Animator clnAnim, GameObject srcRoot, GameObject clnRoot)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: 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_01ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0206: Unknown result type (might be due to invalid IL or missing references)
//IL_020b: Unknown result type (might be due to invalid IL or missing references)
//IL_0313: Unknown result type (might be due to invalid IL or missing references)
//IL_0315: Unknown result type (might be due to invalid IL or missing references)
//IL_025b: Unknown result type (might be due to invalid IL or missing references)
//IL_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)
headBoneOnClone = null;
headBoneOnSource = null;
hasHeadCorrection = false;
headLocalRestPosition = Vector3.zero;
headLocalRestRotation = Quaternion.identity;
headSubtreeLocalPositions.Clear();
Transform[] array = CollectSkinnedBones(srcRoot);
Transform[] array2 = CollectSkinnedBones(clnRoot);
Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(StringComparer.OrdinalIgnoreCase);
Dictionary<string, Transform> dictionary2 = new Dictionary<string, Transform>(StringComparer.OrdinalIgnoreCase);
foreach (Transform val in array)
{
if (!((Object)(object)val == (Object)null))
{
string relativePathFast = GetRelativePathFast(val, srcRoot.transform);
if (!dictionary.ContainsKey(relativePathFast))
{
dictionary[relativePathFast] = val;
}
}
}
foreach (Transform val2 in array2)
{
if (!((Object)(object)val2 == (Object)null))
{
string relativePathFast2 = GetRelativePathFast(val2, clnRoot.transform);
if (!dictionary2.ContainsKey(relativePathFast2))
{
dictionary2[relativePathFast2] = val2;
}
}
}
Transform val3 = (((Object)(object)srcAnim != (Object)null && srcAnim.isHuman) ? srcAnim.GetBoneTransform((HumanBodyBones)10) : null);
Transform val4 = (((Object)(object)clnAnim != (Object)null && clnAnim.isHuman) ? clnAnim.GetBoneTransform((HumanBodyBones)10) : null);
if ((Object)(object)val4 == (Object)null)
{
foreach (KeyValuePair<string, Transform> item in dictionary2)
{
if (item.Key.IndexOf("head", StringComparison.OrdinalIgnoreCase) >= 0)
{
val4 = item.Value;
break;
}
}
}
if ((Object)(object)val3 == (Object)null)
{
foreach (KeyValuePair<string, Transform> item2 in dictionary)
{
if (item2.Key.IndexOf("head", StringComparison.OrdinalIgnoreCase) >= 0)
{
val3 = item2.Value;
break;
}
}
}
if ((Object)(object)val4 != (Object)null)
{
if (clnAnim != null)
{
clnAnim.Rebind();
}
if (clnAnim != null)
{
clnAnim.Update(0f);
}
headBoneOnClone = val4;
headBoneOnSource = val3;
headLocalRestPosition = val4.localPosition;
headLocalRestRotation = val4.localRotation;
hasHeadCorrection = true;
Il2CppArrayBase<Transform> componentsInChildren = ((Component)val4).GetComponentsInChildren<Transform>(true);
for (int k = 0; k < componentsInChildren.Length; k++)
{
Transform val5 = componentsInChildren[k];
if (!((Object)(object)val5 == (Object)null) && !headSubtreeLocalPositions.ContainsKey(((Object)val5).name))
{
headSubtreeLocalPositions[((Object)val5).name] = val5.localPosition;
}
}
}
EnsureBonePairCapacity(array.Length);
EnsureRendererPairCapacity(Math.Max(16, clnRendersCountEstimate(clnRoot)));
bonePairCount = 0;
rendererPairCount = 0;
HashSet<Transform> hashSet = new HashSet<Transform>();
foreach (KeyValuePair<string, Transform> item3 in dictionary)
{
if (dictionary2.TryGetValue(item3.Key, out var value))
{
BonePair bonePair = new BonePair
{
src = item3.Value,
dst = value,
isHeadSubtree = IsInHeadSubtreeCached(value)
};
if (bonePair.isHeadSubtree && headSubtreeLocalPositions.TryGetValue(((Object)value).name, out var value2))
{
bonePair.headRestLocal = value2;
}
bonePairsArr[bonePairCount++] = bonePair;
hashSet.Add(value);
}
}
Dictionary<string, List<Transform>> dictionary3 = BuildNameMap(array);
Dictionary<string, List<Transform>> dictionary4 = BuildNameMap(array2);
foreach (KeyValuePair<string, List<Transform>> item4 in dictionary3)
{
List<Transform> value3 = item4.Value;
if (!dictionary4.TryGetValue(item4.Key, out var value4) || value4.Count == 0)
{
continue;
}
for (int l = 0; l < value3.Count; l++)
{
Transform val6 = value3[l];
bool flag = false;
for (int m = 0; m < bonePairCount; m++)
{
if ((Object)(object)bonePairsArr[m].src == (Object)(object)val6)
{
flag = true;
break;
}
}
if (flag)
{
continue;
}
Transform val7 = null;
for (int n = 0; n < value4.Count; n++)
{
if (!hashSet.Contains(value4[n]))
{
val7 = value4[n];
break;
}
}
if ((Object)(object)val7 == (Object)null)
{
val7 = value4[0];
}
if (!((Object)(object)val7 == (Object)null))
{
BonePair bonePair2 = new BonePair
{
src = val6,
dst = val7,
isHeadSubtree = IsInHeadSubtreeCached(val7)
};
if (bonePair2.isHeadSubtree && headSubtreeLocalPositions.TryGetValue(((Object)val7).name, out var value5))
{
bonePair2.headRestLocal = value5;
}
bonePairsArr[bonePairCount++] = bonePair2;
hashSet.Add(val7);
}
}
}
Il2CppArrayBase<Renderer> componentsInChildren2 = srcRoot.GetComponentsInChildren<Renderer>(true);
Il2CppArrayBase<Renderer> componentsInChildren3 = clnRoot.GetComponentsInChildren<Renderer>(true);
Dictionary<string, List<Renderer>> dictionary5 = new Dictionary<string, List<Renderer>>(StringComparer.OrdinalIgnoreCase);
for (int num = 0; num < componentsInChildren3.Length; num++)
{
Renderer val8 = componentsInChildren3[num];
if (!((Object)(object)val8 == (Object)null))
{
if (!dictionary5.TryGetValue(((Object)val8).name, out var value6))
{
value6 = new List<Renderer>(2);
dictionary5[((Object)val8).name] = value6;
}
value6.Add(val8);
}
}
HashSet<Renderer> hashSet2 = new HashSet<Renderer>();
for (int num2 = 0; num2 < componentsInChildren2.Length; num2++)
{
Renderer val9 = componentsInChildren2[num2];
if ((Object)(object)val9 == (Object)null || string.IsNullOrEmpty(((Object)val9).name) || !dictionary5.TryGetValue(((Object)val9).name, out var value7) || value7.Count == 0)
{
continue;
}
Renderer val10 = null;
for (int num3 = 0; num3 < value7.Count; num3++)
{
if (!hashSet2.Contains(value7[num3]))
{
val10 = value7[num3];
break;
}
}
if ((Object)(object)val10 == (Object)null)
{
val10 = value7[0];
}
if (!((Object)(object)val10 == (Object)null))
{
try
{
val10.sharedMaterials = val9.sharedMaterials;
}
catch
{
}
RendererPair rendererPair = new RendererPair
{
src = val9,
dst = val10,
forceDisable = ((Object)(object)val9.sharedMaterial != (Object)null && (Object)(object)val9.sharedMaterial.shader != (Object)null && ((Object)val9.sharedMaterial.shader).name == "SLZ/Icon Billboard")
};
rendererPairsArr[rendererPairCount++] = rendererPair;
hashSet2.Add(val10);
}
}
}
private static Transform[] CollectSkinnedBones(GameObject root)
{
boneCollectScratch.Clear();
Il2CppArrayBase<SkinnedMeshRenderer> componentsInChildren = root.GetComponentsInChildren<SkinnedMeshRenderer>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
Il2CppReferenceArray<Transform> bones = componentsInChildren[i].bones;
if (bones == null)
{
continue;
}
for (int j = 0; j < ((Il2CppArrayBase<Transform>)(object)bones).Length; j++)
{
if ((Object)(object)((Il2CppArrayBase<Transform>)(object)bones)[j] != (Object)null)
{
boneCollectScratch.Add(((Il2CppArrayBase<Transform>)(object)bones)[j]);
}
}
}
Transform[] array = (Transform[])(object)new Transform[boneCollectScratch.Count];
boneCollectScratch.CopyTo(array);
return array;
}
private static int clnRendersCountEstimate(GameObject clnRoot)
{
return clnRoot.GetComponentsInChildren<Renderer>(true)?.Length ?? 0;
}
private static bool IsInHeadSubtreeCached(Transform t)
{
if (!hasHeadCorrection || (Object)(object)t == (Object)null || (Object)(object)headBoneOnClone == (Object)null)
{
return false;
}
Transform val = t;
while ((Object)(object)val != (Object)null)
{
if ((Object)(object)val == (Object)(object)headBoneOnClone)
{
return true;
}
val = val.parent;
}
return false;
}
private static Dictionary<string, List<Transform>> BuildNameMap(Transform[] arr)
{
Dictionary<string, List<Transform>> dictionary = new Dictionary<string, List<Transform>>(StringComparer.OrdinalIgnoreCase);
foreach (Transform val in arr)
{
if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((Object)val).name))
{
if (!dictionary.TryGetValue(((Object)val).name, out var value))
{
value = new List<Transform>(2);
dictionary[((Object)val).name] = value;
}
value.Add(val);
}
}
return dictionary;
}
private static void EnsureBonePairCapacity(int needed)
{
if (bonePairsArr.Length < needed)
{
BonePair[] array = new BonePair[Math.Max(needed, Math.Max(8, bonePairsArr.Length * 2))];
for (int i = 0; i < bonePairsArr.Length; i++)
{
array[i] = bonePairsArr[i];
}
bonePairsArr = array;
}
}
private static void EnsureRendererPairCapacity(int needed)
{
if (rendererPairsArr.Length < needed)
{
RendererPair[] array = new RendererPair[Math.Max(needed, Math.Max(8, rendererPairsArr.Length * 2))];
for (int i = 0; i < rendererPairsArr.Length; i++)
{
array[i] = rendererPairsArr[i];
}
rendererPairsArr = array;
}
}
private static void ResetCloneState()
{
//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_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)
headlessAvatarClone = null;
headlessAvatarCloneAnimator = null;
headBoneOnClone = null;
headBoneOnSource = null;
hasHeadCorrection = false;
headLocalRestPosition = Vector3.zero;
headLocalRestRotation = Quaternion.identity;
headSubtreeLocalPositions.Clear();
bonePairCount = 0;
rendererPairCount = 0;
selfRenderers.Clear();
cloneAvatarRenderers.Clear();
}
private static void CleanClone(GameObject clone)
{
try
{
SafeDestroyAll<ConfigurableJoint>(Il2CppArrayBase<ConfigurableJoint>.op_Implicit(clone.GetComponentsInChildren<ConfigurableJoint>(true)));
}
catch
{
}
try
{
SafeDestroyAll<Collider>(Il2CppArrayBase<Collider>.op_Implicit(clone.GetComponentsInChildren<Collider>(true)));
}
catch
{
}
try
{
SafeDestroyAll<Rigidbody>(Il2CppArrayBase<Rigidbody>.op_Implicit(clone.GetComponentsInChildren<Rigidbody>(true)));
}
catch
{
}
try
{
SafeDestroyAll<InteractableHost>(Il2CppArrayBase<InteractableHost>.op_Implicit(clone.GetComponentsInChildren<InteractableHost>(true)));
}
catch
{
}
Il2CppArrayBase<MonoBehaviour> componentsInChildren = clone.GetComponentsInChildren<MonoBehaviour>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
MonoBehaviour val = componentsInChildren[i];
if ((Object)(object)val == (Object)null || (Object)(object)((Il2CppObjectBase)val).TryCast<Avatar>() != (Object)null)
{
continue;
}
PlayerAvatarArt val2 = ((Il2CppObjectBase)val).TryCast<PlayerAvatarArt>();
if ((Object)(object)val2 != (Object)null)
{
((Behaviour)val2).enabled = false;
continue;
}
try
{
Object.DestroyImmediate((Object)(object)val);
}
catch
{
}
}
}
private static void SafeDestroyAll<T>(T[] comps) where T : Object
{
foreach (T val in comps)
{
if (!((Object)(object)val == (Object)null))
{
try
{
Object.DestroyImmediate((Object)(object)val);
}
catch
{
}
}
}
}
private static string GetRelativePathFast(Transform t, Transform root)
{
if ((Object)(object)t == (Object)(object)root)
{
return "";
}
int num = 0;
Transform val = t;
while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root && num < nameStack.Length)
{
nameStack[num++] = ((Object)val).name;
val = val.parent;
}
pathSb.Clear();
for (int num2 = num - 1; num2 >= 0; num2--)
{
pathSb.Append(nameStack[num2]);
if (num2 > 0)
{
pathSb.Append('/');
}
}
return pathSb.ToString();
}
private static void CheckRenderLoop(CameraKind kind)
{
if (!Player.HandsExist || !Object.op_Implicit((Object)(object)Player.Avatar))
{
return;
}
bool flag = kind switch
{
CameraKind.Headset => true,
CameraKind.Spectator => ignoreSpectator,
_ => false,
};
bool flag2 = (Object)(object)headlessAvatarClone != (Object)null && cloneAvatarRenderers.Count > 0;
if (flag || !flag2)
{
ToggleAvatarVisibility(selfRenderers, visible: true);
if ((Object)(object)headlessAvatarClone != (Object)null)
{
ToggleAvatarVisibility(cloneAvatarRenderers, visible: false);
}
}
else
{
ToggleAvatarVisibility(selfRenderers, visible: false);
ToggleAvatarVisibility(cloneAvatarRenderers, visible: true);
}
}
private static void ToggleAvatarVisibility(List<Renderer> renderers, bool visible)
{
for (int i = 0; i < renderers.Count; i++)
{
Renderer val = renderers[i];
if (!((Object)(object)val == (Object)null))
{
try
{
val.forceRenderingOff = !visible;
}
catch
{
}
}
}
}
}
}