using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BoneLib;
using BoneLib.BoneMenu;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Bonelab;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Warehouse;
using Il2CppSLZ.VRMK;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using MelonLoader;
using Microsoft.CodeAnalysis;
using Timeline.WorldRecording.Recorders;
using TimelineScaleFix;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Main), "TimelineScaleFix", "1.2.0", "You", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonAdditionalDependencies(new string[] { "Timeline", "BoneLib" })]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("TimelineResizer")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("TimelineResizer")]
[assembly: AssemblyTitle("TimelineResizer")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[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 TimelineScaleFix
{
internal static class AvatarResizer
{
public static bool Enabled = true;
private static float _scale = 1f;
private static float _applied = 1f;
private static bool _applyPending;
private static bool _forceJump;
private static float _retryAt;
private static float _bodyResetAt;
private static bool _applying;
private static float _lastOwnSwap = -10f;
private static bool _loading;
private static float _loadStarted;
private static bool _inputBroken;
private static FloatElement _slider;
public static void Init()
{
//IL_000b: 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_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: 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)
Page val = Page.Root.CreatePage("Timeline Resizer", Color.cyan, 0, true);
val.CreateBool("Resizer Enabled", Color.green, Enabled, (Action<bool>)delegate(bool v)
{
Enabled = v;
if (!v)
{
_applyPending = true;
}
});
_slider = val.CreateFloat("Avatar Scale", Color.white, 1f, 0.1f, 0.1f, 5f, (Action<float>)delegate(float v)
{
_scale = Mathf.Round(v * 100f) / 100f;
});
val.CreateFunction("Apply", Color.green, (Action)delegate
{
_applyPending = true;
});
val.CreateFunction("Reset to 1.0 (F12)", Color.yellow, (Action)EmergencyReset);
Hooking.OnLevelLoaded += delegate
{
ResetState();
};
Hooking.OnSwitchAvatarPostfix += delegate
{
if (!_applying && !(Time.realtimeSinceStartup - _lastOwnSwap < 0.5f))
{
ResetState();
}
};
MelonLogger.Msg("Timeline Resizer menu created (v1.5)");
}
private static void ResetState()
{
_scale = 1f;
_applied = 1f;
_forceJump = false;
_applyPending = false;
_bodyResetAt = Time.realtimeSinceStartup + 0.25f;
if (_slider != null)
{
_slider.Value = 1f;
}
}
private static void EmergencyReset()
{
_scale = 1f;
_forceJump = true;
_applyPending = false;
if (_slider != null)
{
_slider.Value = 1f;
}
MelonLogger.Msg("Resizer: reset requested");
}
private static void CheckHotkey()
{
if (_inputBroken)
{
return;
}
try
{
if (Input.GetKeyDown((KeyCode)293))
{
MelonLogger.Msg("Resizer: F12 pressed");
EmergencyReset();
}
}
catch (Exception ex)
{
_inputBroken = true;
MelonLogger.Error("F12 hotkey unavailable: " + ex.Message);
}
}
private static void ApplyBodyScale(RigManager rigManager, float s)
{
//IL_0020: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
PullCordDevice componentInChildren = ((Component)Player.GetPhysicsRig()).GetComponentInChildren<PullCordDevice>();
if ((Object)(object)componentInChildren != (Object)null)
{
((Component)componentInChildren).transform.localScale = new Vector3(s, s, s);
}
foreach (SlotContainer item in (Il2CppArrayBase<SlotContainer>)(object)rigManager.inventory.bodySlots)
{
((Component)item).transform.localScale = new Vector3(s, s, s);
if (!((Object)item).name.Equals("BeltLf1"))
{
continue;
}
InventoryAmmoReceiver componentInChildren2 = ((Component)item).GetComponentInChildren<InventoryAmmoReceiver>();
if (!((Object)(object)componentInChildren2 == (Object)null))
{
Enumerator<Magazine> enumerator2 = componentInChildren2._magazineArts.GetEnumerator();
while (enumerator2.MoveNext())
{
Magazine current2 = enumerator2.Current;
((Component)current2).transform.localScale = new Vector3(s, s, s);
}
}
}
}
public static void Tick()
{
CheckHotkey();
if (_loading)
{
if (Time.realtimeSinceStartup - _loadStarted < 5f)
{
return;
}
_loading = false;
}
if (_bodyResetAt > 0f && Time.realtimeSinceStartup >= _bodyResetAt)
{
RigManager rigManager = Player.RigManager;
if ((Object)(object)rigManager == (Object)null)
{
_bodyResetAt = Time.realtimeSinceStartup + 0.5f;
}
else
{
_bodyResetAt = 0f;
if (Mathf.Abs(_applied - 1f) < 0.001f)
{
try
{
ApplyBodyScale(rigManager, 1f);
}
catch (Exception value)
{
MelonLogger.Error($"Body reset failed: {value}");
}
}
}
}
if (_forceJump)
{
if (ScaleTo(1f))
{
_forceJump = false;
}
}
else if (_applyPending && !(Time.realtimeSinceStartup < _retryAt))
{
float num = (Enabled ? _scale : 1f);
if (Mathf.Abs(num - _applied) < 0.001f)
{
_applyPending = false;
}
else if (ScaleTo(num))
{
_applyPending = false;
}
}
}
private static bool ScaleTo(float s)
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected O, but got Unknown
RigManager rigManager = Player.RigManager;
if ((Object)(object)rigManager == (Object)null)
{
return false;
}
Barcode val = new Barcode(((ScannableReference)rigManager._avatarCrate).Barcode.ID);
if (!AssetWarehouse.Instance._crateRegistry.ContainsKey(val))
{
return false;
}
AvatarCrate val2 = ((Il2CppObjectBase)AssetWarehouse.Instance._crateRegistry[val]).TryCast<AvatarCrate>();
if ((Object)(object)val2 == (Object)null)
{
return false;
}
_loading = true;
_loadStarted = Time.realtimeSinceStartup;
Action<GameObject> action = delegate(GameObject obj)
{
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
_applying = true;
_lastOwnSwap = Time.realtimeSinceStartup;
try
{
RigManager rigManager2 = Player.RigManager;
if (!((Object)(object)rigManager2 == (Object)null))
{
GameObject val3 = Object.Instantiate<GameObject>(obj);
val3.transform.localScale = new Vector3(s, s, s);
val3.transform.parent = ((Component)rigManager2).transform;
val3.transform.localPosition = Vector3.zero;
Avatar componentInChildren = val3.GetComponentInChildren<Avatar>();
foreach (SkinnedMeshRenderer item in (Il2CppArrayBase<SkinnedMeshRenderer>)(object)componentInChildren.hairMeshes)
{
((Renderer)item).enabled = false;
}
componentInChildren.PrecomputeAvatar();
componentInChildren.RefreshBodyMeasurements();
rigManager2.SwitchAvatar(componentInChildren);
PlayerRefs.Instance._bodyVitals.PROPEGATE();
ApplyBodyScale(rigManager2, s);
_applied = s;
_bodyResetAt = 0f;
}
}
catch (Exception value)
{
MelonLogger.Error($"Resize failed: {value}");
_retryAt = Time.realtimeSinceStartup + 2f;
}
finally
{
_lastOwnSwap = Time.realtimeSinceStartup;
_applying = false;
_loading = false;
}
};
((CrateT<GameObject>)(object)val2).LoadAsset(Action<GameObject>.op_Implicit(action));
return true;
}
}
public class Main : MelonMod
{
internal const string MetaKey = "avatarscale";
internal static readonly ConditionalWeakTable<RigmanagerRecorder, ScaleTrack> Tracks = new ConditionalWeakTable<RigmanagerRecorder, ScaleTrack>();
internal static Instance Log;
public override void OnInitializeMelon()
{
Log = ((MelonBase)this).LoggerInstance;
AvatarResizer.Init();
}
public override void OnUpdate()
{
AvatarResizer.Tick();
}
}
internal class ScaleTrack
{
public readonly List<float> Times = new List<float>();
public readonly List<float> Values = new List<float>();
public bool LoadAttempted;
public void Add(float t, float v)
{
if (Times.Count <= 0 || (!(t <= Times[Times.Count - 1]) && !(Mathf.Abs(Values[Values.Count - 1] - v) < 0.001f)))
{
Times.Add(t);
Values.Add(v);
}
}
public bool TryEvaluate(float t, out float v)
{
v = 1f;
if (Times.Count == 0)
{
return false;
}
int num = Times.BinarySearch(t);
if (num < 0)
{
num = ~num - 1;
}
if (num < 0)
{
num = 0;
}
v = Values[num];
return true;
}
public string Encode()
{
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < Times.Count; i++)
{
if (i > 0)
{
stringBuilder.Append(';');
}
stringBuilder.Append(Times[i].ToString("0.000", CultureInfo.InvariantCulture)).Append(':').Append(Values[i].ToString("0.0000", CultureInfo.InvariantCulture));
}
return stringBuilder.ToString();
}
public void Decode(string s)
{
Times.Clear();
Values.Clear();
string[] array = s.Split(';');
foreach (string text in array)
{
string[] array2 = text.Split(':');
if (array2.Length == 2 && float.TryParse(array2[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array2[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
{
Times.Add(result);
Values.Add(result2);
}
}
}
}
internal static class Meta
{
private static readonly MethodInfo GetM = AccessTools.Method(typeof(RigmanagerRecorder), "TryGetMetadata", (Type[])null, (Type[])null);
private static readonly MethodInfo SetM = AccessTools.Method(typeof(RigmanagerRecorder), "SetMetadata", (Type[])null, (Type[])null);
public static bool TryGet(RigmanagerRecorder r, string key, out string value)
{
value = null;
if (GetM == null)
{
return false;
}
object[] array = new object[2] { key, null };
GetM.Invoke(r, array);
value = array[1] as string;
return !string.IsNullOrEmpty(value) && value != "NONE";
}
public static void Set(RigmanagerRecorder r, string key, string value)
{
if (SetM == null)
{
Instance log = Main.Log;
if (log != null)
{
log.Error("SetMetadata not found");
}
}
else
{
SetM.Invoke(r, new object[2] { key, value });
}
}
}
[HarmonyPatch(typeof(RigmanagerRecorder), "Capture")]
internal static class CapturePatch
{
private static void Prefix(RigmanagerRecorder __instance)
{
try
{
RigManager recordingRigManager = __instance.recordingRigManager;
if ((Object)(object)recordingRigManager == (Object)null)
{
return;
}
Avatar avatar = recordingRigManager.avatar;
if (Object.op_Implicit((Object)(object)avatar))
{
Avatar currentRecordingAvatar = __instance.currentRecordingAvatar;
IntPtr intPtr = (((Object)(object)currentRecordingAvatar != (Object)null) ? ((Il2CppObjectBase)currentRecordingAvatar).Pointer : IntPtr.Zero);
if (!(((Il2CppObjectBase)avatar).Pointer == intPtr))
{
__instance.AssignAvatarBones(avatar);
__instance.currentRecordingAvatar = avatar;
Main.Log.Msg("Avatar instance changed mid-recording, retargeted bones");
}
}
}
catch (Exception value)
{
Main.Log.Error($"Retarget failed: {value}");
}
}
private static void Postfix(RigmanagerRecorder __instance, float sceneTime)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
RigManager recordingRigManager = __instance.recordingRigManager;
if ((Object)(object)recordingRigManager == (Object)null)
{
return;
}
Avatar avatar = recordingRigManager.avatar;
if (!Object.op_Implicit((Object)(object)avatar))
{
return;
}
float x = ((Component)avatar).transform.lossyScale.x;
if (!(x <= 0.0001f))
{
Main.Tracks.GetValue(__instance, (RigmanagerRecorder _) => new ScaleTrack()).Add(sceneTime, x);
}
}
}
[HarmonyPatch(typeof(RigmanagerRecorder), "OnSave")]
internal static class SavePatch
{
private static void Postfix(RigmanagerRecorder __instance)
{
if (Main.Tracks.TryGetValue(__instance, out var value) && value.Times.Count > 0)
{
Meta.Set(__instance, "avatarscale", value.Encode());
}
}
}
[HarmonyPatch(typeof(RigmanagerRecorder), "Playback")]
internal static class PlaybackPatch
{
private static void Prefix(RigmanagerRecorder __instance, float sceneTime)
{
//IL_00bd: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
Avatar currentPlaybackAvatar = __instance.currentPlaybackAvatar;
if (!Object.op_Implicit((Object)(object)currentPlaybackAvatar))
{
return;
}
ScaleTrack value = Main.Tracks.GetValue(__instance, (RigmanagerRecorder _) => new ScaleTrack());
if (!value.LoadAttempted)
{
value.LoadAttempted = true;
if (Meta.TryGet(__instance, "avatarscale", out var value2))
{
value.Decode(value2);
}
}
if (value.TryEvaluate(sceneTime, out var v) && !(v <= 0.0001f))
{
Transform transform = ((Component)currentPlaybackAvatar).transform;
float num = (Object.op_Implicit((Object)(object)transform.parent) ? transform.parent.lossyScale.x : 1f);
if (num <= 0.0001f)
{
num = 1f;
}
transform.localScale = Vector3.one * (v / num);
}
}
}
}