using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BoneLib;
using BoneLib.BoneMenu;
using BoneLib.BoneMenu.UI;
using BoneLib.Notifications;
using Il2CppCysharp.Threading.Tasks;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Data;
using Il2CppSLZ.Marrow.Pool;
using Il2CppSLZ.Marrow.Warehouse;
using Il2CppSystem;
using LabFusion.Entities;
using LabFusion.Marrow.Extenders;
using LabFusion.Network;
using LabFusion.Player;
using LabFusion.RPC;
using LabFusion.SDK.Metadata;
using LabFusion.Scene;
using LabFusion.Utilities;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using PhasePosePlayback;
using PhasesPoses;
using UnityEngine;
using UnityEngine.Rendering;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(PosesTestMod), "SimplePoses", "0.1.8", "Phase", null)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SimplePoses")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SimplePoses")]
[assembly: AssemblyTitle("SimplePoses")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace PhasesPoses
{
public sealed class TransformData
{
public float[] Position { get; set; } = new float[3];
public float[] Rotation { get; set; } = new float[4] { 0f, 0f, 0f, 1f };
public float[] Scale { get; set; } = new float[3] { 1f, 1f, 1f };
public void Validate()
{
Check(Position, 3);
Check(Rotation, 4);
Check(Scale, 3);
double num = Rotation.Sum((float v) => (double)v * (double)v);
if (num < 0.9 || num > 1.1 || Scale.Any((float v) => v <= 0f))
{
throw new InvalidDataException("Invalid rotation or scale.");
}
}
private static void Check(float[] a, int length)
{
if (a == null || a.Length != length || a.Any((float v) => !float.IsFinite(v)))
{
throw new InvalidDataException("Invalid transform numbers.");
}
}
}
public sealed class PoseFile
{
public int Version { get; set; } = 1;
public string Id { get; set; } = Guid.NewGuid().ToString("N");
public string Name { get; set; } = "New pose";
public string SeatBarcode { get; set; } = "Doctor.BodyMallAndMore.Spawnable.PoseableSeat";
public string MapBarcode { get; set; } = "";
public string AvatarName { get; set; } = "";
public string SavedUtc { get; set; } = "";
public int RotationSnap { get; set; } = 15;
public bool Frozen { get; set; } = true;
public bool Visible { get; set; } = true;
public float? FloorHeight { get; set; }
public int FloorHeightMeasurementVersion { get; set; }
public TransformData LastWorldSeat { get; set; } = new TransformData();
public TransformData SeatAnchorLocal { get; set; } = new TransformData();
public TransformData LeftFootLocal { get; set; } = new TransformData
{
Position = new float[3] { -0.1433f, 0.047f, 0.566f }
};
public TransformData RightFootLocal { get; set; } = new TransformData
{
Position = new float[3] { 0.1432f, 0.047f, 0.566f }
};
public TransformData LeftTargetLocal { get; set; } = new TransformData
{
Position = new float[3] { 0f, 0f, 0.1083f }
};
public TransformData RightTargetLocal { get; set; } = new TransformData
{
Position = new float[3] { 0f, 0f, 0.1083f }
};
public float[] SpineLimits { get; set; } = new float[4] { 60f, 180f, 60f, 40f };
public float[] MinimumSeatBounds { get; set; } = new float[3] { 0.1f, 0.05f, 0.1f };
public float[] MaximumSeatBounds { get; set; } = new float[3] { 0.25f, 0.1f, 0.2f };
public void Validate()
{
if (Version != 1 || !Guid.TryParseExact(Id, "N", out var _) || string.IsNullOrWhiteSpace(Name) || Name.Length > 80)
{
throw new InvalidDataException("Unsupported pose format or invalid name/ID.");
}
if (SeatBarcode != "Doctor.BodyMallAndMore.Spawnable.PoseableSeat")
{
throw new InvalidDataException("Unsupported seat crate.");
}
TransformData[] array = new TransformData[6] { LastWorldSeat, SeatAnchorLocal, LeftFootLocal, RightFootLocal, LeftTargetLocal, RightTargetLocal };
int i;
for (i = 0; i < array.Length; i++)
{
(array[i] ?? throw new InvalidDataException("Missing transform.")).Validate();
}
if (!new int[5] { 5, 15, 30, 45, 90 }.Contains(RotationSnap))
{
throw new InvalidDataException("Invalid snap interval.");
}
if (FloorHeight.HasValue && !float.IsFinite(FloorHeight.Value))
{
throw new InvalidDataException("Invalid saved floor height.");
}
i = FloorHeightMeasurementVersion;
if ((i < 0 || i > 1) ? true : false)
{
throw new InvalidDataException("Unsupported floor height measurement version.");
}
CheckLimits(SpineLimits, 4);
CheckLimits(MinimumSeatBounds, 3);
CheckLimits(MaximumSeatBounds, 3);
}
private static void CheckLimits(float[] values, int count)
{
if (values == null || values.Length != count || values.Any((float v) => !float.IsFinite(v) || v < 0f))
{
throw new InvalidDataException("Invalid seat limits.");
}
}
}
public sealed class PoseStore
{
public static readonly JsonSerializerOptions Json = new JsonSerializerOptions
{
WriteIndented = true
};
public string DirectoryPath { get; }
public PoseStore(string directory)
{
DirectoryPath = directory;
Directory.CreateDirectory(directory);
}
private string PathFor(string id)
{
if (!Guid.TryParseExact(id, "N", out var _))
{
throw new InvalidDataException("Invalid pose ID.");
}
return Path.Combine(DirectoryPath, id + ".json");
}
public string Save(PoseFile pose)
{
pose.Validate();
pose.SavedUtc = DateTime.UtcNow.ToString("O");
string text = PathFor(pose.Id);
string text2 = text + ".tmp";
File.WriteAllText(text2, JsonSerializer.Serialize(pose, Json));
File.Move(text2, text, overwrite: true);
return text;
}
private static string CheckedName(string name)
{
name = name?.Trim();
if (string.IsNullOrEmpty(name) || name.Length > 80 || name.Any(char.IsControl))
{
throw new InvalidDataException("Enter a pose name between 1 and 80 characters.");
}
return name;
}
private List<PoseFile> Named(string name)
{
return (from p in List(null)
where string.Equals(p.Name.Trim(), name, StringComparison.OrdinalIgnoreCase)
select p).ToList();
}
public string SaveNamed(PoseFile draft)
{
draft.Validate();
string text = CheckedName(draft.Name);
List<PoseFile> list = Named(text);
if (list.Count > 1)
{
throw new InvalidDataException("Multiple saved poses have that name. Rename duplicates in Saved poses first.");
}
PoseFile poseFile = Copy(draft);
poseFile.Id = ((list.Count == 1) ? list[0].Id : Guid.NewGuid().ToString("N"));
poseFile.Name = ((list.Count == 1) ? list[0].Name : text);
string result = Save(poseFile);
draft.Id = poseFile.Id;
draft.Name = poseFile.Name;
draft.SavedUtc = poseFile.SavedUtc;
return result;
}
public PoseFile Clone(string id, string name)
{
name = CheckedName(name);
if (Named(name).Count != 0)
{
throw new InvalidDataException("Choose a new name for the clone; that name is already saved.");
}
PoseFile poseFile = Copy(Load(id));
poseFile.Id = Guid.NewGuid().ToString("N");
poseFile.Name = name;
poseFile.SavedUtc = "";
Save(poseFile);
return poseFile;
}
public void Rename(string id, string name)
{
name = CheckedName(name);
if (Named(name).Any((PoseFile p) => p.Id != id))
{
throw new InvalidDataException("Another pose already has that name. Choose a different name.");
}
PoseFile poseFile = Load(id);
poseFile.Name = name;
Save(poseFile);
}
public PoseFile Load(string id)
{
FileInfo fileInfo = new FileInfo(PathFor(id));
if (fileInfo.Length > 256000)
{
throw new InvalidDataException("Pose file is too large.");
}
PoseFile poseFile = JsonSerializer.Deserialize<PoseFile>(File.ReadAllText(fileInfo.FullName));
if (poseFile == null || poseFile.Id != id)
{
throw new InvalidDataException("Pose ID does not match its filename.");
}
poseFile.Validate();
return poseFile;
}
public List<PoseFile> List(Action<string> warning)
{
List<PoseFile> list = new List<PoseFile>();
foreach (string item in Directory.EnumerateFiles(DirectoryPath, "*.json"))
{
try
{
list.Add(Load(Path.GetFileNameWithoutExtension(item)));
}
catch (Exception ex)
{
warning?.Invoke(Path.GetFileName(item) + ": " + ex.Message);
}
}
return list.OrderBy<PoseFile, string>((PoseFile p) => p.Name, StringComparer.OrdinalIgnoreCase).ToList();
}
public void Delete(string id)
{
File.Delete(PathFor(id));
}
public static PoseFile Copy(PoseFile pose)
{
return JsonSerializer.Deserialize<PoseFile>(JsonSerializer.Serialize(pose, Json));
}
public static bool CanResumeHere(PoseFile p, string map)
{
if (!string.IsNullOrWhiteSpace(map))
{
return map == p.MapBarcode;
}
return false;
}
}
public enum EditorStage
{
Idle,
Loading,
Place,
Adjust,
Spawning,
Feet,
RemovingSeat
}
public enum PoseEditTarget
{
NativeGrips,
Seat,
LeftFoot,
RightFoot
}
public static class PoseMath
{
public static float PlacementAltitude(float surfaceY, float? floorHeight, float newPoseOffset)
{
return surfaceY + (floorHeight ?? newPoseOffset);
}
public static void RaySegmentParameters(double dot, double axisOffset, double rayOffset, double length, out double segment, out double ray)
{
if (!AxisParameter(dot, axisOffset, rayOffset, out segment))
{
segment = axisOffset;
}
segment = Math.Clamp(segment, 0.0, length);
ray = segment * dot - rayOffset;
if (ray < 0.0)
{
ray = 0.0;
segment = Math.Clamp(axisOffset, 0.0, length);
}
}
public static bool ConfirmPressed(bool blocked, bool held, ref bool armed)
{
if (blocked)
{
armed = false;
return false;
}
if (!held)
{
armed = true;
return false;
}
if (!armed)
{
return false;
}
armed = false;
return true;
}
public static double Snap(double degrees, int step)
{
return Math.Round(degrees / (double)step, MidpointRounding.AwayFromZero) * (double)step;
}
public static double Unwrap(double previous, double current)
{
double num = (current - previous) % 360.0;
if (num > 180.0)
{
num -= 360.0;
}
if (num < -180.0)
{
num += 360.0;
}
return num;
}
public static bool AxisParameter(double dot, double axisOffset, double rayOffset, out double parameter)
{
double num = 1.0 - dot * dot;
parameter = 0.0;
if (num < 0.0025)
{
return false;
}
parameter = (axisOffset - dot * rayOffset) / num;
return double.IsFinite(parameter);
}
public static EditorStage Previous(EditorStage stage)
{
return stage switch
{
EditorStage.Feet => EditorStage.Adjust,
EditorStage.Adjust => EditorStage.Place,
_ => stage,
};
}
}
}
namespace PhasePosePlayback
{
public sealed class PoseEntry
{
public string Name { get; set; }
public string Key { get; set; }
public string Label { get; set; }
public string Category { get; set; }
public bool LongLegs { get; set; }
public string Barcode { get; set; }
public float Height { get; set; }
public float[] Tilt { get; set; }
public PoseFile Pose { get; set; }
}
public sealed class PoseCatalog
{
public IReadOnlyList<PoseEntry> Entries { get; }
public IEnumerable<PoseEntry> MenuEntries => Entries.Where((PoseEntry p) => !p.LongLegs);
public PoseCatalog(PoseEntry[] entries)
{
if (entries == null || entries.Length == 0)
{
throw new InvalidDataException("Expected at least one authored pose crate.");
}
HashSet<(string, bool)> hashSet = new HashSet<(string, bool)>();
HashSet<string> hashSet2 = new HashSet<string>();
int num = 0;
while (num < entries.Length)
{
PoseEntry poseEntry = entries[num];
if (poseEntry != null && !string.IsNullOrWhiteSpace(poseEntry.Key) && !string.IsNullOrWhiteSpace(poseEntry.Label) && !(poseEntry.Barcode != "Phaseyy.Phasesposes.Spawnable." + poseEntry.Name) && hashSet2.Add(poseEntry.Barcode) && hashSet.Add((poseEntry.Key, poseEntry.LongLegs)) && float.IsFinite(poseEntry.Height))
{
float[] tilt = poseEntry.Tilt;
if (tilt != null && tilt.Length == 4 && !poseEntry.Tilt.Any((float v) => !float.IsFinite(v)) && !(Math.Abs(poseEntry.Tilt.Sum((float x) => (double)x * (double)x) - 1.0) > 0.001) && new string[4] { "Sit/Floor", "Sit/Ledge", "Lay", "Other" }.Contains(poseEntry.Category))
{
poseEntry.Pose?.Validate();
if (poseEntry.Pose == null)
{
throw new InvalidDataException("Missing authored pose.");
}
num++;
continue;
}
}
throw new InvalidDataException("Invalid pose catalog entry.");
}
foreach (PoseEntry item in entries.Where((PoseEntry p) => p.LongLegs))
{
if (!hashSet.Contains((item.Key, false)))
{
throw new InvalidDataException("LongLegs pose needs a regular variant.");
}
}
Entries = entries;
}
public PoseEntry Resolve(string key, bool tall)
{
return Entries.FirstOrDefault((PoseEntry p) => p.Key == key && p.LongLegs == tall) ?? Entries.FirstOrDefault((PoseEntry p) => p.Key == key && !p.LongLegs) ?? throw new InvalidDataException("Pose is not in the catalog: " + key);
}
public static PoseCatalog Load()
{
using Stream utf8Json = Assembly.GetExecutingAssembly().GetManifestResourceStream("PhasePosePlayback.Catalog.json") ?? throw new InvalidDataException("Pose catalog resource missing.");
return new PoseCatalog(JsonSerializer.Deserialize<PoseEntry[]>(utf8Json));
}
}
public enum OccupancyChange
{
None,
Entered,
Left,
EntryTimedOut
}
public sealed class OccupancyTracker
{
private readonly double _started;
private double _missingSince = double.NaN;
private bool _entered;
private bool _finished;
public OccupancyTracker(double started)
{
_started = started;
}
public OccupancyChange Observe(double now, bool seated)
{
if (_finished)
{
return OccupancyChange.None;
}
if (seated)
{
_missingSince = double.NaN;
if (!_entered)
{
_entered = true;
return OccupancyChange.Entered;
}
}
else if (_entered)
{
if (double.IsNaN(_missingSince))
{
_missingSince = now;
}
if (now - _missingSince >= 0.2)
{
_finished = true;
return OccupancyChange.Left;
}
}
else if (now - _started >= 8.0)
{
_finished = true;
return OccupancyChange.EntryTimedOut;
}
return OccupancyChange.None;
}
}
public sealed class PosesTestMod : MelonMod
{
private sealed class JoinDownload
{
public PlayerID Player;
public float ReadyAt = float.NaN;
public float Expires;
}
private sealed class TemporaryCylinder
{
public GameObject Root;
public int Id;
public float DeleteAt;
}
private enum Stage
{
Idle,
Preview,
Spawning,
Initializing,
Entering,
Seated,
Leaving,
Removing
}
private const string DownloadCylinderBarcode = "Phaseyy.Phasesposes.Spawnable.DownloadCylinder";
private readonly List<JoinDownload> _joinDownloads = new List<JoinDownload>();
private readonly List<TemporaryCylinder> _temporaryCylinders = new List<TemporaryCylinder>();
private float _nextJoinCheck;
private int _joinGeneration;
private bool _downloadPending;
private bool _manualDownload;
private int _downloadQueued;
private float _downloadAt;
private float _downloadDeadline;
private static readonly Color Accent = new Color(0.3f, 0.9f, 1f);
private readonly ConcurrentQueue<Action> _actions = new ConcurrentQueue<Action>();
private PoseCatalog _catalog;
private MelonPreferences_Category _preferences;
private MelonPreferences_Entry<bool> _tallPreference;
private Page _menu;
private FunctionElement _status;
private PoseEntry _entry;
private PoseEntry _pending;
private PlacementVisuals _visual;
private SpawnedSeat _seat;
private OccupancyTracker _occupancy;
private Stage _stage;
private bool _tall;
private bool _bodyYaw = true;
private bool _validSurface;
private bool _triggerArmed;
private bool _cancelSpawn;
private bool _shownControls;
private Vector3 _position;
private Quaternion _rotation = Quaternion.identity;
private Quaternion _heading = Quaternion.identity;
private int _generation;
private int _removalAttempts;
private float _inputAfter;
private float _nextTick;
private float _deadline;
private float _readyAt;
private string _lastNotification;
private float _lastNotificationAt;
private static Vector3 DownloadOrigin()
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
return ((Component)Player.RigManager).transform.position;
}
private static Vector3 ManualDownloadOrigin()
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
RigManager rigManager = Player.RigManager;
Vector3 val = (((Object)(object)rigManager.ControllerRig != (Object)null && (Object)(object)((Rig)rigManager.ControllerRig).m_head != (Object)null) ? ((Rig)rigManager.ControllerRig).m_head : ((Component)rigManager).transform).forward;
val.y = 0f;
val = ((((Vector3)(ref val)).sqrMagnitude < 0.001f) ? Vector3.forward : ((Vector3)(ref val)).normalized);
return (((Object)(object)rigManager.physicsRig != (Object)null && (Object)(object)((Rig)rigManager.physicsRig).m_chest != (Object)null) ? ((Component)((Rig)rigManager.physicsRig).m_chest).transform.position : (((Object)(object)rigManager.physicsRig != (Object)null && (Object)(object)((Rig)rigManager.physicsRig).m_pelvis != (Object)null) ? ((Component)((Rig)rigManager.physicsRig).m_pelvis).transform.position : ((Component)rigManager).transform.position)) + val * 2f;
}
private static bool IsDownloadCylinderLoaded()
{
//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_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
//IL_0020: Expected O, but got Unknown
try
{
return (Object)(object)((CrateReferenceT<SpawnableCrate>)new SpawnableCrateReference
{
_barcode = new Barcode
{
ID = "Phaseyy.Phasesposes.Spawnable.DownloadCylinder"
}
}).Crate != (Object)null;
}
catch
{
return false;
}
}
private bool TrySpawnDownloadCylinder(Vector3 position, Action<GameObject> callback = null)
{
//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_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
//IL_003a: Expected O, but got Unknown
//IL_003c: 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_0055: Expected O, but got Unknown
//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_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
if (!NetworkInfo.HasServer || !NetworkSceneManager.IsLevelNetworked)
{
return false;
}
try
{
SpawnableCrateReference crateRef = new SpawnableCrateReference
{
_barcode = new Barcode
{
ID = "Phaseyy.Phasesposes.Spawnable.DownloadCylinder"
}
};
NetworkAssetSpawner.Spawn(new SpawnRequestInfo
{
Spawnable = new Spawnable
{
crateRef = crateRef
},
Position = position,
Rotation = Quaternion.identity,
SpawnEffect = false,
SpawnCallback = ((callback == null) ? null : ((Action<SpawnCallbackInfo>)delegate(SpawnCallbackInfo info)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
callback(info.Spawned);
}))
});
return true;
}
catch (Exception ex)
{
((MelonBase)this).LoggerInstance.Warning("Download-cylinder request: " + ex.Message);
return false;
}
}
private void InitializeJoinDownloads()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
MultiplayerHooking.OnPlayerJoined += new PlayerUpdate(NewDownloadPlayer);
}
private void DisposeJoinDownloads()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
MultiplayerHooking.OnPlayerJoined -= new PlayerUpdate(NewDownloadPlayer);
}
private void NewDownloadPlayer(PlayerID id)
{
if (id == null || id.IsMe || !NetworkInfo.HasServer)
{
return;
}
foreach (JoinDownload joinDownload in _joinDownloads)
{
if (joinDownload.Player == id)
{
return;
}
}
_joinDownloads.Add(new JoinDownload
{
Player = id,
Expires = Time.unscaledTime + 600f
});
}
private static void QuietDeleteCylinder(GameObject root)
{
try
{
if (Object.op_Implicit((Object)(object)root) && root.activeInHierarchy)
{
Poolee component = root.GetComponent<Poolee>();
if (component != null)
{
component.Despawn();
}
}
}
catch
{
}
}
private void CancelJoinDownloads()
{
_joinGeneration++;
_joinDownloads.Clear();
foreach (TemporaryCylinder temporaryCylinder in _temporaryCylinders)
{
if (Object.op_Implicit((Object)(object)temporaryCylinder.Root) && ((Object)temporaryCylinder.Root).GetInstanceID() == temporaryCylinder.Id)
{
QuietDeleteCylinder(temporaryCylinder.Root);
}
}
_temporaryCylinders.Clear();
}
private void ProcessJoinDownloads()
{
//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
if (_joinDownloads.Count == 0 && _temporaryCylinders.Count == 0)
{
return;
}
float unscaledTime = Time.unscaledTime;
if (unscaledTime < _nextJoinCheck)
{
return;
}
_nextJoinCheck = unscaledTime + 0.5f;
if (!NetworkInfo.HasServer)
{
CancelJoinDownloads();
return;
}
for (int num = _temporaryCylinders.Count - 1; num >= 0; num--)
{
TemporaryCylinder temporaryCylinder = _temporaryCylinders[num];
if (!(unscaledTime < temporaryCylinder.DeleteAt))
{
if (Object.op_Implicit((Object)(object)temporaryCylinder.Root) && ((Object)temporaryCylinder.Root).GetInstanceID() == temporaryCylinder.Id)
{
QuietDeleteCylinder(temporaryCylinder.Root);
}
_temporaryCylinders.RemoveAt(num);
}
}
bool flag = NetworkSceneManager.IsLevelNetworked && !FusionSceneManager.IsLoading();
bool flag2 = false;
bool flag3 = false;
NetworkPlayer val = default(NetworkPlayer);
for (int num2 = _joinDownloads.Count - 1; num2 >= 0; num2--)
{
JoinDownload joinDownload = _joinDownloads[num2];
PlayerID player = joinDownload.Player;
if (!player.IsValid || unscaledTime > joinDownload.Expires)
{
_joinDownloads.RemoveAt(num2);
}
else if (!flag || !player.Metadata.IsValid || ((MetadataVariableT<bool>)(object)player.Metadata.Loading).GetValue() || !NetworkPlayerManager.TryGetPlayer(player.SmallID, ref val) || !val.HasRig)
{
joinDownload.ReadyAt = float.NaN;
}
else if (float.IsNaN(joinDownload.ReadyAt))
{
joinDownload.ReadyAt = unscaledTime + 15f;
}
else if (!(unscaledTime < joinDownload.ReadyAt) && !((Object)(object)Player.RigManager == (Object)null))
{
if (!flag2)
{
flag3 = IsDownloadCylinderLoaded();
flag2 = true;
}
if (flag3)
{
int generation = _joinGeneration;
if (TrySpawnDownloadCylinder(ManualDownloadOrigin() + new Vector3(50f, 20f, 50f), delegate(GameObject root)
{
Queue(delegate
{
if (Object.op_Implicit((Object)(object)root))
{
if (generation != _joinGeneration || !NetworkInfo.HasServer)
{
QuietDeleteCylinder(root);
}
else
{
_temporaryCylinders.Add(new TemporaryCylinder
{
Root = root,
Id = ((Object)root).GetInstanceID(),
DeleteAt = Time.unscaledTime + 10f
});
}
}
});
}))
{
_joinDownloads.RemoveAt(num2);
}
}
}
}
}
private void InitializeDownloads()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
MultiplayerHooking.OnStartedServer += new ServerEvent(ScheduleDownloads);
MultiplayerHooking.OnJoinedServer += new ServerEvent(ScheduleDownloads);
Hooking.OnLevelLoaded += DownloadLevelLoaded;
InitializeJoinDownloads();
ScheduleDownloads();
}
private void DisposeDownloads()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
MultiplayerHooking.OnStartedServer -= new ServerEvent(ScheduleDownloads);
MultiplayerHooking.OnJoinedServer -= new ServerEvent(ScheduleDownloads);
Hooking.OnLevelLoaded -= DownloadLevelLoaded;
DisposeJoinDownloads();
CancelDownloads();
}
private void DownloadLevelLoaded(LevelInfo _)
{
ScheduleDownloads();
}
private void ScheduleDownloads()
{
if (NetworkInfo.HasServer && !_downloadPending)
{
_downloadPending = true;
_downloadQueued = 0;
_downloadAt = Time.unscaledTime + 5f;
_downloadDeadline = _downloadAt + 60f;
}
}
private void RequestDownloads()
{
if (!NetworkInfo.HasServer)
{
Notify("Join a Fusion lobby before requesting the mod download.");
return;
}
_downloadPending = true;
_downloadQueued = 0;
_manualDownload = true;
_downloadAt = Time.unscaledTime;
_downloadDeadline = _downloadAt + 60f;
}
private void CancelDownloads()
{
_downloadPending = false;
_manualDownload = false;
_downloadQueued = 0;
CancelJoinDownloads();
}
private void ProcessDownloads()
{
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: 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_00cf: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
ProcessJoinDownloads();
if (!_downloadPending || Time.unscaledTime < _downloadAt)
{
return;
}
if (!NetworkInfo.HasServer)
{
CancelDownloads();
return;
}
if (Time.unscaledTime >= _downloadDeadline)
{
bool manualDownload = _manualDownload;
_downloadPending = false;
_manualDownload = false;
_downloadQueued = 0;
((MelonBase)this).LoggerInstance.Warning("Pose-pallet download preload timed out waiting for Fusion, the rig or the DownloadCylinder crate.");
if (manualDownload)
{
Notify("Download cylinders could not be requested. Check that the updated poses pallet is installed.", 4f);
}
return;
}
_downloadAt = Time.unscaledTime + 1f;
if (!NetworkSceneManager.IsLevelNetworked || (Object)(object)Player.RigManager == (Object)null || !IsDownloadCylinderLoaded())
{
return;
}
Vector3 val = (_manualDownload ? ManualDownloadOrigin() : (DownloadOrigin() + new Vector3(2000f, 200f, 2000f)));
while (_downloadQueued < (_manualDownload ? 1 : 2))
{
if (!TrySpawnDownloadCylinder(val + new Vector3((float)_downloadQueued * (_manualDownload ? 1.5f : 3f), 0f, 0f)))
{
return;
}
_downloadQueued++;
}
bool manualDownload2 = _manualDownload;
_downloadPending = false;
_manualDownload = false;
_downloadQueued = 0;
if (manualDownload2)
{
Notify("Download cylinders requested through Fusion.");
}
}
public override void OnLateInitializeMelon()
{
//IL_005d: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: 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_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
//IL_020d: Unknown result type (might be due to invalid IL or missing references)
//IL_022f: 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)
//IL_0268: Expected O, but got Unknown
try
{
_preferences = MelonPreferences.CreateCategory("PhasesPosesTest", "SimplePoses");
_tallPreference = _preferences.CreateEntry<bool>("SeatsForTallAvatars", false, "Seats for tall avatars", (string)null, false, false, (ValueValidator)null, (string)null);
_tall = _tallPreference.Value;
_catalog = PoseCatalog.Load();
_menu = Page.Root.CreatePage("SimplePoses", Accent, 0, true);
_status = _menu.CreateFunction("Idle", Color.gray, (Action)delegate
{
});
_menu.CreateBool("Seats for tall avatars", Accent, _tall, (Action<bool>)delegate(bool value)
{
Queue(delegate
{
SetTall(value);
});
});
Page val = _menu.CreatePage("Sit", Accent, 0, true);
Dictionary<string, Page> dictionary = new Dictionary<string, Page>
{
{
"Sit/Floor",
val.CreatePage("Floor", Accent, 0, true)
},
{
"Sit/Ledge",
val.CreatePage("Ledge", Accent, 0, true)
},
{
"Lay",
_menu.CreatePage("Lay", Accent, 0, true)
},
{
"Other",
_menu.CreatePage("Other", Accent, 0, true)
}
};
foreach (PoseEntry menuEntry in _catalog.MenuEntries)
{
string key = menuEntry.Key;
dictionary[menuEntry.Category].CreateFunction(menuEntry.Label, Accent, (Action)delegate
{
Queue(delegate
{
Choose(key);
});
});
}
_menu.CreateFunction("Cancel posing / leave seat (X)", Color.yellow, (Action)delegate
{
Queue(delegate
{
Stop(keepPending: false);
});
});
_menu.CreateFunction("Make everyone download the mod", Accent, (Action)delegate
{
Queue(RequestDownloads);
});
_menu.CreateFunction("Controls", Accent, (Action)delegate
{
Notify("Point with right hand. Y: body/left-hand yaw. Right trigger: place and sit. X: cancel or leave. Tall switch applies to the next pose or current hologram.", 12f);
});
Hooking.OnLevelLoading += LevelLoading;
MultiplayerHooking.OnDisconnected += new ServerEvent(Disconnected);
InitializeDownloads();
((MelonBase)this).LoggerInstance.Msg($"Loaded {_catalog.Entries.Count} prebuilt pose crates. Install the packed Phase's poses Unity pallet. No Doctor seat mod is required by this player.");
}
catch (Exception ex)
{
((MelonBase)this).LoggerInstance.Error(ex.ToString());
}
}
private void Queue(Action action)
{
_actions.Enqueue(action);
}
private void Status(Stage stage)
{
_stage = stage;
if (_status != null)
{
((Element)_status).ElementName = ((stage == Stage.Idle) ? "Idle" : ((_entry?.Label ?? "Pose") + ": " + stage));
}
}
private void Notify(string text, float seconds = 2f)
{
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: 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_0055: 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_005c: 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_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Expected O, but got Unknown
if (text == _lastNotification && Time.unscaledTime - _lastNotificationAt < 3f)
{
return;
}
_lastNotification = text;
_lastNotificationAt = Time.unscaledTime;
((MelonBase)this).LoggerInstance.Msg(text);
try
{
Notifier.Send(new Notification
{
Title = NotificationText.op_Implicit("SimplePoses"),
Message = NotificationText.op_Implicit(text),
ShowTitleOnPopup = true,
PopupLength = seconds,
Type = (NotificationType)0
});
}
catch (Exception ex)
{
((MelonBase)this).LoggerInstance.Warning("Notification: " + ex.Message);
}
}
private void Choose(string key)
{
if ((Object)(object)Player.RigManager == (Object)null)
{
throw new InvalidOperationException("Load into a level first.");
}
PoseEntry poseEntry = _catalog.Resolve(key, _tall);
Stage stage = _stage;
if ((uint)stage <= 1u)
{
StartPreview(poseEntry);
return;
}
_pending = poseEntry;
Stop(keepPending: true);
}
private void SetTall(bool value)
{
_tall = value;
if (_tallPreference.Value != value)
{
_tallPreference.Value = value;
try
{
_preferences.SaveToFile(false);
}
catch (Exception ex)
{
((MelonBase)this).LoggerInstance.Warning("Tall-avatar preference save: " + ex.Message);
Notify("Could not save the tall-avatar setting to disk.", 4f);
}
}
if (_stage == Stage.Preview && _entry != null)
{
StartPreview(_catalog.Resolve(_entry.Key, value));
}
}
private void StartPreview(PoseEntry entry)
{
if (_seat != null)
{
throw new InvalidOperationException("Wait for the previous seat to be removed.");
}
_visual?.Dispose();
_visual = null;
_entry = entry;
_validSurface = false;
_triggerArmed = false;
_visual = new PlacementVisuals(entry);
_inputAfter = Time.unscaledTime + 0.3f;
Status(Stage.Preview);
if (!_shownControls)
{
_shownControls = true;
Notify("Point: right hand. Y: body/left-hand yaw. Right trigger: place and sit. X: cancel or leave.", 12f);
}
}
public override void OnUpdate()
{
try
{
if (_actions.TryDequeue(out var result))
{
result();
}
ProcessDownloads();
if (_stage != Stage.Idle)
{
bool flag = (Object.op_Implicit((Object)(object)GUIMenu.Instance) && ((Component)GUIMenu.Instance).gameObject.activeInHierarchy) || Time.unscaledTime < _inputAfter;
BaseController leftController = Player.LeftController;
if (!flag && (Object)(object)leftController != (Object)null && leftController.GetAButtonDown())
{
Stop(keepPending: false);
}
else if (_stage == Stage.Preview)
{
UpdatePreview(flag);
}
else if (!(Time.unscaledTime < _nextTick))
{
_nextTick = Time.unscaledTime + 0.1f;
TickSeat();
}
}
}
catch (Exception ex)
{
Fail(ex);
}
}
private void UpdatePreview(bool blocked)
{
//IL_003d: 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_004d: 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_0058: 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_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: 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_010b: 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_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: 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_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_018b: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
//IL_01a2: 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_01ae: Unknown result type (might be due to invalid IL or missing references)
//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_0164: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)Player.RightHand == (Object)null || (Object)(object)Player.LeftHand == (Object)null || (Object)(object)Player.LeftController == (Object)null)
{
_triggerArmed = false;
return;
}
Transform transform = ((Component)Player.RightHand).transform;
Vector3 val = transform.position + transform.up * 0.04f + transform.forward * 0.08f;
Vector3 forward = transform.forward;
Ray ray = default(Ray);
((Ray)(ref ray))..ctor(val, ((Vector3)(ref forward)).normalized);
if (!blocked && Player.LeftController.GetBButtonDown())
{
_bodyYaw = !_bodyYaw;
Notify(_bodyYaw ? "Orientation: body yaw" : "Orientation: left-hand yaw", 0.65f);
}
_validSurface = Surface(ray, out var point);
object obj;
if (!_bodyYaw)
{
obj = ((Component)Player.LeftHand).transform;
}
else
{
PhysicsRig physicsRig = Player.PhysicsRig;
obj = ((physicsRig != null) ? ((Rig)physicsRig).m_pelvis : null);
}
Transform val2 = (Transform)obj;
Vector3 val3 = (Object.op_Implicit((Object)(object)val2) ? val2.forward : ((Component)Player.LeftHand).transform.forward);
val3.y = 0f;
if (((Vector3)(ref val3)).sqrMagnitude > 0.001f)
{
_heading = Quaternion.LookRotation(((Vector3)(ref val3)).normalized, Vector3.up);
}
if (_validSurface)
{
_position = new Vector3(point.x, point.y + _entry.Height, point.z);
}
_rotation = _heading * PlacementVisuals.Q(_entry.Tilt);
_visual.Update(_validSurface, _position, _rotation, _heading, ray, point);
bool held = !blocked && Player.RightHand.GetIndexButton();
if (PoseMath.ConfirmPressed(blocked, held, ref _triggerArmed))
{
if (!_validSurface)
{
Notify("Point at a surface within 25 metres.");
}
else
{
BeginSpawn();
}
}
}
private static bool Surface(Ray ray, out Vector3 point)
{
//IL_0001: 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_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: 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_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
point = default(Vector3);
RigManager rigManager = Player.RigManager;
Transform val = ((rigManager != null) ? ((Component)rigManager).transform : null);
Vector3 val2 = ((Ray)(ref ray)).origin;
float num = 25f;
RaycastHit val3 = default(RaycastHit);
for (int i = 0; i < 12; i++)
{
if (!(num > 0f))
{
break;
}
if (!Physics.Raycast(val2, ((Ray)(ref ray)).direction, ref val3, num, -5, (QueryTriggerInteraction)1))
{
return false;
}
Collider collider = ((RaycastHit)(ref val3)).collider;
if (!Object.op_Implicit((Object)(object)collider))
{
return false;
}
if (!Object.op_Implicit((Object)(object)val) || !((Component)collider).transform.IsChildOf(val))
{
point = ((RaycastHit)(ref val3)).point;
return true;
}
float num2 = Mathf.Max(0.05f, ((RaycastHit)(ref val3)).distance + 0.02f);
num -= num2;
val2 += ((Ray)(ref ray)).direction * num2;
}
return false;
}
private void BeginSpawn()
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
_cancelSpawn = false;
_pending = null;
int generation = ++_generation;
_deadline = Time.unscaledTime + 30f;
Status(Stage.Spawning);
SpawnedSeat.Spawn(_entry.Barcode, _position, _rotation, delegate(GameObject root)
{
Queue(delegate
{
if (generation != _generation)
{
if (Object.op_Implicit((Object)(object)root))
{
SpawnedSeat.Despawn(root);
}
}
else
{
if (!Object.op_Implicit((Object)(object)root))
{
throw new InvalidOperationException("Seat spawning failed.");
}
try
{
_seat = new SpawnedSeat(root);
}
catch
{
SpawnedSeat.Despawn(root);
throw;
}
if (_cancelSpawn)
{
BeginLeaving();
}
else
{
_readyAt = Time.unscaledTime + 1.3f;
Status(Stage.Initializing);
}
}
});
});
_visual?.Dispose();
_visual = null;
}
private void TickSeat()
{
float unscaledTime = Time.unscaledTime;
if (_stage == Stage.Spawning)
{
if (unscaledTime > _deadline)
{
_generation++;
FinishRemoval();
Notify("Seat spawn timed out. Any late result will be removed; check the pallet installation.", 4f);
}
return;
}
if (_seat == null || _seat.Removed)
{
FinishRemoval();
return;
}
switch (_stage)
{
case Stage.Initializing:
if (unscaledTime > _deadline)
{
throw new InvalidOperationException("Seat initialization/Fusion registration timed out.");
}
if (!(unscaledTime < _readyAt) && _seat.Ready)
{
_seat.Sit();
_occupancy = new OccupancyTracker(unscaledTime);
Status(Stage.Entering);
}
break;
case Stage.Entering:
case Stage.Seated:
switch (_occupancy.Observe(unscaledTime, (Object)(object)Player.RigManager != (Object)null && (Object)(object)Player.RigManager.activeSeat == (Object)(object)_seat.Seat))
{
case OccupancyChange.Entered:
Status(Stage.Seated);
break;
case OccupancyChange.Left:
BeginLeaving();
break;
case OccupancyChange.EntryTimedOut:
Notify("Native seat entry did not complete; removing the unused seat.", 4f);
BeginLeaving();
break;
}
break;
case Stage.Leaving:
if (!(unscaledTime < _readyAt))
{
LeaveSafely();
RequestRemoval();
}
break;
case Stage.Removing:
if (unscaledTime > _deadline)
{
if (_removalAttempts < 3)
{
RequestRemoval();
}
else
{
AbandonRemoval();
}
}
break;
}
}
private void Stop(bool keepPending)
{
if (!keepPending)
{
_pending = null;
}
_visual?.Dispose();
_visual = null;
if (_stage == Stage.Spawning)
{
_cancelSpawn = true;
}
else if (_seat == null || _seat.Removed)
{
FinishRemoval();
}
else if (_stage == Stage.Removing)
{
_removalAttempts = 0;
RequestRemoval();
}
else
{
BeginLeaving();
}
}
private void BeginLeaving()
{
LeaveSafely();
_visual?.Dispose();
_visual = null;
_readyAt = Time.unscaledTime + 0.35f;
_removalAttempts = 0;
Status(Stage.Leaving);
}
private void RequestRemoval()
{
_removalAttempts++;
_deadline = Time.unscaledTime + 3f;
Status(Stage.Removing);
try
{
_seat.Remove();
}
catch (Exception ex)
{
((MelonBase)this).LoggerInstance.Warning("Removal request: " + ex.Message);
}
}
private void LeaveSafely()
{
try
{
_seat?.Leave();
}
catch (Exception ex)
{
((MelonBase)this).LoggerInstance.Warning("Seat exit: " + ex.Message);
}
}
private void Fail(Exception ex)
{
((MelonBase)this).LoggerInstance.Error(ex.ToString());
Notify(ex.Message, 4f);
_pending = null;
try
{
if (_seat != null && !_seat.Removed)
{
BeginLeaving();
return;
}
_generation++;
FinishRemoval();
}
catch (Exception ex2)
{
((MelonBase)this).LoggerInstance.Error("Seat cleanup: " + ex2);
}
}
private void LevelLoading(LevelInfo _)
{
CancelDownloads();
Reset();
}
private void Disconnected()
{
CancelDownloads();
Reset();
}
private void Reset()
{
_generation++;
_pending = null;
_visual?.Dispose();
_visual = null;
if (_seat != null)
{
try
{
_seat.Leave();
_seat.Remove();
}
catch (Exception ex)
{
((MelonBase)this).LoggerInstance.Warning("Scene cleanup: " + ex.Message);
}
_seat.Dispose();
_seat = null;
}
_occupancy = null;
_entry = null;
Status(Stage.Idle);
}
public override void OnDeinitializeMelon()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
Hooking.OnLevelLoading -= LevelLoading;
MultiplayerHooking.OnDisconnected -= new ServerEvent(Disconnected);
DisposeDownloads();
Reset();
if (_menu != null)
{
Menu.DestroyPage(_menu);
}
}
private void AbandonRemoval()
{
Notify("The seat could not be despawned and may still be in the lobby. You can keep using other poses.", 5f);
FinishRemoval();
}
private void FinishRemoval()
{
_seat?.Dispose();
_seat = null;
_occupancy = null;
_entry = null;
_cancelSpawn = false;
_visual?.Dispose();
_visual = null;
Status(Stage.Idle);
PoseEntry pending = _pending;
_pending = null;
if (pending != null)
{
StartPreview(pending);
}
}
}
internal sealed class PlacementVisuals : IDisposable
{
private sealed class Box
{
public string Path { get; set; }
public float[] Position { get; set; }
public float[] Rotation { get; set; }
public float[] Scale { get; set; }
}
private static Box[] _boxes;
private bool _visible;
private readonly GameObject _root;
private readonly Transform _ghost;
private readonly LineRenderer _laser;
private readonly LineRenderer _arrow;
private readonly List<Material> _materials = new List<Material>();
private static Box[] PreviewBoxes()
{
if (_boxes != null)
{
return _boxes;
}
using Stream utf8Json = Assembly.GetExecutingAssembly().GetManifestResourceStream("PhasePosePlayback.Preview.json") ?? throw new InvalidDataException("Preview resource missing.");
Box[]? array = JsonSerializer.Deserialize<Box[]>(utf8Json);
if (array == null || array.Length != 7)
{
throw new InvalidDataException("Invalid preview geometry.");
}
_boxes = array;
return array;
}
public PlacementVisuals(PoseEntry entry)
{
//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_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_0200: Unknown result type (might be due to invalid IL or missing references)
//IL_0241: Unknown result type (might be due to invalid IL or missing references)
//IL_015f: Unknown result type (might be due to invalid IL or missing references)
_root = new GameObject("SimplePoses - local preview")
{
layer = 0,
hideFlags = (HideFlags)52
};
try
{
_ghost = Child(_root.transform, "Hologram").transform;
_ghost.localScale = V(entry.Pose.LastWorldSeat.Scale);
Box[] array = PreviewBoxes();
Material m = Material(new Color(0.12f, 0.9f, 1f, 0.7f));
Box[] array2 = array;
foreach (Box box in array2)
{
Transform obj = Path(_ghost, box.Path);
obj.localPosition = V(box.Position);
obj.localRotation = Q(box.Rotation);
obj.localScale = V(box.Scale);
LineRenderer val = Line(obj, m, 0.008f);
val.useWorldSpace = false;
int[] array3 = new int[16]
{
0, 1, 3, 2, 0, 4, 5, 1, 5, 7,
3, 7, 6, 2, 6, 4
};
val.positionCount = array3.Length;
for (int j = 0; j < array3.Length; j++)
{
int num = array3[j];
val.SetPosition(j, new Vector3(((num & 1) == 0) ? (-0.5f) : 0.5f, ((num & 2) == 0) ? (-0.5f) : 0.5f, ((num & 4) == 0) ? (-0.5f) : 0.5f));
}
}
Local(Path(_ghost, "Seat"), entry.Pose.SeatAnchorLocal);
Local(Path(_ghost, "Seat/FootLf"), entry.Pose.LeftFootLocal);
Local(Path(_ghost, "Seat/FootRt"), entry.Pose.RightFootLocal);
_laser = Line(Child(_root.transform, "Pointer").transform, Material(Color.white), 0.004f);
_laser.positionCount = 2;
_arrow = Line(Child(_root.transform, "Forward").transform, Material(Color.yellow), 0.012f);
_arrow.positionCount = 5;
_root.SetActive(false);
}
catch
{
Dispose();
throw;
}
}
public void Update(bool valid, Vector3 position, Quaternion rotation, Quaternion heading, Ray ray, Vector3 hit)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: 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_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_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: 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_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
if (_visible != valid)
{
_root.SetActive(valid);
_visible = valid;
}
if (valid)
{
_ghost.SetPositionAndRotation(position, rotation);
_laser.SetPosition(0, ((Ray)(ref ray)).origin);
_laser.SetPosition(1, hit);
Vector3 val = position + Vector3.up * 0.6f;
Vector3 val2 = val + heading * Vector3.forward * 0.5f;
_arrow.SetPosition(0, val);
_arrow.SetPosition(1, val2);
_arrow.SetPosition(2, val2 + heading * new Vector3(-0.1f, 0f, -0.13f));
_arrow.SetPosition(3, val2);
_arrow.SetPosition(4, val2 + heading * new Vector3(0.1f, 0f, -0.13f));
}
}
private Material Material(Color color)
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Expected O, but got Unknown
//IL_0057: 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)
Shader val = Shader.Find("Unlit/Color");
if (!Object.op_Implicit((Object)(object)val))
{
val = Shader.Find("Sprites/Default");
}
if (!Object.op_Implicit((Object)(object)val))
{
throw new InvalidOperationException("Supported preview shader unavailable.");
}
Material val2 = new Material(val);
_materials.Add(val2);
if (val2.HasProperty("_Color"))
{
val2.SetColor("_Color", color);
}
if (val2.HasProperty("_BaseColor"))
{
val2.SetColor("_BaseColor", color);
}
val2.renderQueue = 3000;
return val2;
}
private static GameObject Child(Transform parent, string name)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
GameObject val = new GameObject(name)
{
layer = 0
};
val.transform.SetParent(parent, false);
return val;
}
private static Transform Path(Transform root, string path)
{
string[] array = path.Split('/');
foreach (string text in array)
{
Transform val = root.Find(text);
root = (Object.op_Implicit((Object)(object)val) ? val : Child(root, text).transform);
}
return root;
}
private static LineRenderer Line(Transform t, Material m, float width)
{
LineRenderer obj = ((Component)t).gameObject.AddComponent<LineRenderer>();
((Renderer)obj).sharedMaterial = m;
obj.useWorldSpace = true;
float startWidth = (obj.endWidth = width);
obj.startWidth = startWidth;
((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
((Renderer)obj).receiveShadows = false;
return obj;
}
internal static Vector3 V(float[] a)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
return new Vector3(a[0], a[1], a[2]);
}
internal static Quaternion Q(float[] a)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
return new Quaternion(a[0], a[1], a[2], a[3]);
}
private static void Local(Transform t, TransformData a)
{
//IL_0007: 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_0029: Unknown result type (might be due to invalid IL or missing references)
t.localPosition = V(a.Position);
t.localRotation = Q(a.Rotation);
t.localScale = V(a.Scale);
}
public void Dispose()
{
if (Object.op_Implicit((Object)(object)_root))
{
Object.Destroy((Object)(object)_root);
}
foreach (Material material in _materials)
{
if (Object.op_Implicit((Object)(object)material))
{
Object.Destroy((Object)(object)material);
}
}
_materials.Clear();
}
}
internal sealed class SpawnedSeat : IDisposable
{
private readonly int _id;
private readonly Poolee _pool;
private bool _retired;
private bool _everActive;
private Action<GameObject> _onRetired;
public GameObject Root { get; }
public Seat Seat { get; }
public bool Removed
{
get
{
if (!_retired && Object.op_Implicit((Object)(object)Root) && ((Object)Root).GetInstanceID() == _id)
{
if (_everActive)
{
return !Root.activeInHierarchy;
}
return false;
}
return true;
}
}
public bool Ready
{
get
{
if (Removed || !Root.activeInHierarchy)
{
return false;
}
_everActive = true;
if (Object.op_Implicit((Object)(object)Seat) && Object.op_Implicit((Object)(object)Seat.seatRb))
{
if (NetworkInfo.HasServer)
{
if (NetworkSceneManager.IsLevelNetworked)
{
return SeatExtender.Cache.ContainsSource(Seat);
}
return false;
}
return true;
}
return false;
}
}
public SpawnedSeat(GameObject root)
{
Root = root;
_id = ((Object)root).GetInstanceID();
_everActive = root.activeInHierarchy;
Seat = root.GetComponentInChildren<Seat>(true);
_pool = root.GetComponent<Poolee>();
if (!Object.op_Implicit((Object)(object)Seat) || !Object.op_Implicit((Object)(object)_pool))
{
throw new InvalidOperationException("Spawned crate has no native Seat/Poolee.");
}
_onRetired = Action<GameObject>.op_Implicit((Action<GameObject>)delegate
{
_retired = true;
Dispose();
});
Poolee pool = _pool;
pool.OnDespawnDelegate += _onRetired;
Poolee pool2 = _pool;
pool2.OnRecycleDelegate += _onRetired;
}
public void Sit()
{
if (!Ready || (Object)(object)Player.RigManager == (Object)null)
{
throw new InvalidOperationException("The seat or player rig is not ready.");
}
if ((Object)(object)Seat.rigManager != (Object)null && (Object)(object)Seat.rigManager != (Object)(object)Player.RigManager)
{
throw new InvalidOperationException("Another player is using this seat.");
}
if (Object.op_Implicit((Object)(object)Player.RigManager.activeSeat) && (Object)(object)Player.RigManager.activeSeat != (Object)(object)Seat)
{
throw new InvalidOperationException("Leave your current seat before posing.");
}
Seat.IngressRig(Player.RigManager);
}
public void Leave()
{
if (!Removed && (Object)(object)Player.RigManager != (Object)null && ((Object)(object)Player.RigManager.activeSeat == (Object)(object)Seat || (Object)(object)Seat.rigManager == (Object)(object)Player.RigManager))
{
Seat.EgressRig(true);
}
}
public void Remove()
{
if (!Removed)
{
Despawn(Root);
}
}
public void Dispose()
{
if (!((Delegate)(object)_onRetired == (Delegate)null))
{
if (Object.op_Implicit((Object)(object)_pool))
{
Poolee pool = _pool;
pool.OnDespawnDelegate -= _onRetired;
Poolee pool2 = _pool;
pool2.OnRecycleDelegate -= _onRetired;
}
_onRetired = null;
}
}
public static void Despawn(GameObject root)
{
if (Object.op_Implicit((Object)(object)root) && root.activeInHierarchy)
{
Poolee component = root.GetComponent<Poolee>();
if (!Object.op_Implicit((Object)(object)component))
{
throw new InvalidOperationException("No native pool handle for seat cleanup.");
}
component.Despawn();
}
}
public static void Spawn(string barcode, Vector3 position, Quaternion rotation, Action<GameObject> callback)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//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_0024: Expected O, but got Unknown
//IL_0025: Expected O, but got Unknown
//IL_003e: 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_004b: Expected O, but got Unknown
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: 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_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: 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_009f: Unknown result type (might be due to invalid IL or missing references)
SpawnableCrateReference val = new SpawnableCrateReference
{
_barcode = new Barcode
{
ID = barcode
}
};
if (!((ScannableReference)val).IsValid())
{
throw new InvalidOperationException("Install the packed Phase's poses pallet first. Missing crate: " + barcode);
}
Spawnable val2 = new Spawnable
{
crateRef = val
};
if (NetworkInfo.HasServer)
{
if (!NetworkSceneManager.IsLevelNetworked)
{
throw new InvalidOperationException("Wait for the Fusion map to finish loading.");
}
NetworkAssetSpawner.Spawn(new SpawnRequestInfo
{
Spawnable = val2,
Position = position,
Rotation = rotation,
SpawnEffect = false,
SpawnCallback = delegate(SpawnCallbackInfo info)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
callback(info.Spawned);
}
});
return;
}
AssetSpawner.Register(val2);
Awaiter<Poolee> awaiter = AssetSpawner.SpawnAsync(val2, position, rotation, new Nullable<Vector3>(Vector3.zero)
{
hasValue = false
}, (Transform)null, false, new Nullable<int>(0)
{
hasValue = false
}, (Action<GameObject>)null, (Action<GameObject>)null, (Action<GameObject>)null).GetAwaiter();
awaiter.OnCompleted(Action.op_Implicit((Action)delegate
{
GameObject obj = null;
try
{
Poolee result = awaiter.GetResult();
obj = ((result != null) ? ((Component)result).gameObject : null);
}
finally
{
callback(obj);
}
}));
}
}
}