Decompiled source of TideFusion v1.1.1
Mods/LabFusion.dll
Decompiled a year ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using System.Xml.Linq; using BoneLib; using BoneLib.BoneMenu; using BoneLib.BoneMenu.Elements; using BoneLib.BoneMenu.UI; using BoneLib.Nullables; using FusionHelper.Network; using HarmonyLib; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using LabFusion; using LabFusion.BoneMenu; using LabFusion.Data; using LabFusion.Exceptions; using LabFusion.Extensions; using LabFusion.Grabbables; using LabFusion.MarrowIntegration; using LabFusion.MonoBehaviours; using LabFusion.NativeStructs; using LabFusion.Network; using LabFusion.Patching; using LabFusion.Preferences; using LabFusion.Representation; using LabFusion.Riptide.BoneMenu; using LabFusion.Riptide.Messages; using LabFusion.Riptide.Preferences; using LabFusion.Riptide.Utilities; using LabFusion.Riptide.Voice; using LabFusion.SDK.Achievements; using LabFusion.SDK.Gamemodes; using LabFusion.SDK.Modules; using LabFusion.SDK.Points; using LabFusion.Senders; using LabFusion.Syncables; using LabFusion.UI; using LabFusion.Utilities; using LabFusion.XML; using LiteNetLib; using LiteNetLib.Layers; using LiteNetLib.Utils; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using Oculus.Platform; using Oculus.Platform.Models; using PuppetMasta; using Riptide; using SLZ; using SLZ.AI; using SLZ.Bonelab; using SLZ.Combat; using SLZ.Data; using SLZ.Interaction; using SLZ.Marrow; using SLZ.Marrow.Data; using SLZ.Marrow.Input; using SLZ.Marrow.Pool; using SLZ.Marrow.SceneStreaming; using SLZ.Marrow.Utilities; using SLZ.Marrow.Warehouse; using SLZ.Player; using SLZ.Props; using SLZ.Props.Weapons; using SLZ.Rig; using SLZ.SFX; using SLZ.SaveData; using SLZ.UI; using SLZ.Utilities; using SLZ.VFX; using SLZ.VRMK; using SLZ.Vehicle; using SLZ.Zones; using Steamworks; using Steamworks.Data; using Steamworks.Ugc; using TMPro; using UltEvents; using UnhollowerBaseLib; using UnhollowerBaseLib.Attributes; using UnhollowerRuntimeLib; using UnityEngine; using UnityEngine.Audio; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: Guid("490e160d-251d-4ab4-a3bb-f473961ff8a1")] [assembly: AssemblyTitle("LabFusion")] [assembly: AssemblyFileVersion("1.5.1")] [assembly: MelonInfo(typeof(FusionMod), "LabFusion", "1.5.1", "Lakatrazz", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: MelonPriority(-10000)] [assembly: MelonOptionalDependencies(new string[] { "System.Windows.Forms" })] [assembly: MelonIncompatibleAssemblies(new string[] { "BonelabMultiplayerMockup", "Junction" })] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.5.1.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsUnmanagedAttribute : Attribute { } } namespace LabFusion { [StructLayout(LayoutKind.Sequential, Size = 1)] public struct FusionVersion { public const byte versionMajor = 1; public const byte versionMinor = 5; public const short versionPatch = 1; } public class FusionMod : MelonMod { public const string Name = "LabFusion"; public const string Author = "Lakatrazz"; public static readonly Version Version = new Version(1, 5, 1); private static int _nextSyncableSendRate = 1; private static bool _hasAutoUpdater = false; public static string Changelog { get; internal set; } = null; public static string[] Credits { get; internal set; } = null; public static FusionMod Instance { get; private set; } public static Assembly FusionAssembly { get; private set; } public override void OnEarlyInitializeMelon() { Instance = this; FusionAssembly = Assembly.GetExecutingAssembly(); PersistentData.OnPathInitialize(); SteamAPILoader.OnLoadSteamAPI(); ByteRetriever.PopulateInitial(); PDController.OnInitializeMelon(); ModuleHandler.Internal_HookAssemblies(); GamemodeRegistration.Internal_HookAssemblies(); PointItemManager.Internal_HookAssemblies(); VoteKickHelper.Internal_OnInitializeMelon(); } public override void OnInitializeMelon() { FusionPreferences.OnPrepareBoneMenuCategory(); FusionFileLoader.OnInitializeMelon(); FusionBundleLoader.OnBundleLoad(); LevelDataHandler.OnInitializeMelon(); FusionMessageHandler.RegisterHandlersFromAssembly(FusionAssembly); GrabGroupHandler.RegisterHandlersFromAssembly(FusionAssembly); PropExtenderManager.RegisterExtendersFromAssembly(FusionAssembly); NetworkLayer.RegisterLayersFromAssembly(FusionAssembly); GamemodeRegistration.LoadGamemodes(FusionAssembly); PointItemManager.LoadItems(FusionAssembly); AchievementManager.LoadAchievements(FusionAssembly); SyncManager.OnInitializeMelon(); FusionPopupManager.OnInitializeMelon(); FusionPreferences.OnInitializePreferences(); FusionSceneManager.Internal_OnInitializeMelon(); OnInitializeNetworking(); } public override void OnLateInitializeMelon() { ManualPatcher.PatchAll(); InternalLayerHelpers.OnLateInitializeLayer(); PersistentAssetCreator.OnLateInitializeMelon(); PlayerAdditionsHelper.OnInitializeMelon(); FusionPreferences.OnCreateBoneMenu(); _hasAutoUpdater = MelonTypeBase<MelonPlugin>.RegisteredMelons.Any((MelonPlugin p) => ((MelonBase)p).Info.Name.Contains("LabFusion Updater")); if (!_hasAutoUpdater && !HelperMethods.IsAndroid()) { FusionNotifier.Send(new FusionNotification { isMenuItem = false, isPopup = true, message = "You do not have the Fusion AutoUpdater installed in your plugins folder!\nIt is recommended to install it in order to stay up to date.", type = NotificationType.WARNING }); } } protected void OnInitializeNetworking() { if (NetworkInfo.CurrentNetworkLayer != null) { FusionLogger.Warn("Cannot initialize new network layer because a previous one is active!"); return; } NetworkLayerDeterminer.LoadLayer(); if (NetworkLayerDeterminer.LoadedLayer == null) { FusionLogger.Error("The target network layer is null!"); } else { InternalLayerHelpers.SetLayer(NetworkLayerDeterminer.LoadedLayer); } } public override void OnDeinitializeMelon() { InternalLayerHelpers.OnCleanupLayer(); VoteKickHelper.Internal_OnDeinitializeMelon(); FusionFileLoader.OnDeinitializeMelon(); ModuleHandler.Internal_UnhookAssemblies(); GamemodeRegistration.Internal_UnhookAssemblies(); PointItemManager.Internal_UnhookAssemblies(); FusionBundleLoader.OnBundleUnloaded(); PlayerAdditionsHelper.OnDeinitializeMelon(); SteamAPILoader.OnFreeSteamAPI(); } public override void OnPreferencesLoaded() { FusionPreferences.OnPreferencesLoaded(); } public static void OnMainSceneInitialized() { _ = ((Scannable)FusionSceneManager.Level).Title; StaticGripFixer.OnMainSceneInitialized(); SyncManager.OnCleanup(); RigData.OnCacheRigInfo(); PersistentAssetCreator.OnMainSceneInitialized(); ConstrainerUtilities.OnMainSceneInitialized(); PlayerRep.OnRecreateReps(); MultiplayerHooking.Internal_OnMainSceneInitialized(); FusionPlayer.OnMainSceneInitialized(); if (NetworkInfo.IsServer && Gamemode.ActiveGamemode != null && Gamemode.ActiveGamemode.AutoStopOnSceneLoad) { Gamemode.ActiveGamemode.StopGamemode(); } } public static void OnMainSceneInitializeDelayed() { if (RigData.HasPlayer) { RigData.RigReferences.RigManager.bodyVitals.quickmenuEnabled = true; ((ControllerRig)RigData.RigReferences.RigManager.openControllerRig).quickmenuEnabled = true; } } public override void OnUpdate() { NetworkInfo.BytesDown = 0; NetworkInfo.BytesUp = 0; ThreadingUtilities.Internal_OnUpdate(); PhysicsUtilities.OnCacheValues(); FusionSceneManager.Internal_UpdateScene(); RigData.OnRigUpdate(); FusionPopupManager.OnUpdate(); int playerSendRate = SendRateTable.GetPlayerSendRate(); if (Time.frameCount % playerSendRate == 0) { PlayerRep.OnSyncRep(); } if (Time.frameCount % _nextSyncableSendRate == 0) { int bytesUp = NetworkInfo.BytesUp; SyncManager.OnUpdate(); _nextSyncableSendRate = SendRateTable.GetObjectSendRate(NetworkInfo.BytesUp - bytesUp); } PhysicsUtilities.OnSendPhysicsInformation(); PlayerRep.OnUpdate(); InternalLayerHelpers.OnVoiceChatUpdate(); InternalLayerHelpers.OnUpdateLayer(); MultiplayerHooking.Internal_OnUpdate(); GamemodeManager.Internal_OnUpdate(); DelayUtilities.Internal_OnUpdate(); } public override void OnFixedUpdate() { PhysicsUtilities.OnUpdateTimescale(); PDController.OnFixedUpdate(); PlayerRep.OnFixedUpdate(); SyncManager.OnFixedUpdate(); MultiplayerHooking.Internal_OnFixedUpdate(); GamemodeManager.Internal_OnFixedUpdate(); } public override void OnLateUpdate() { PlayerRep.OnLateUpdate(); InternalLayerHelpers.OnLateUpdateLayer(); MultiplayerHooking.Internal_OnLateUpdate(); GamemodeManager.Internal_OnLateUpdate(); } public override void OnGUI() { InternalLayerHelpers.OnGUILayer(); } } } namespace LabFusion.Preferences { public enum PrefUpdateMode { IGNORE, SERVER_UPDATE, CLIENT_UPDATE, LOCAL_UPDATE } public interface IFusionPref<T> { Action<T> OnValueChanged { get; set; } void SetValue(T value); T GetValue(); } public class ReadonlyFusionPrev<T> : IFusionPref<T> { private readonly T _value; public Action<T> OnValueChanged { get; set; } public ReadonlyFusionPrev(T value) { _value = value; } public void SetValue(T value) { } public T GetValue() { return _value; } } public class FusionPref<T> : IFusionPref<T> { private readonly MelonPreferences_Category _category; private readonly MelonPreferences_Entry<T> _entry; private readonly PrefUpdateMode _mode; public Action<T> OnValueChanged { get; set; } public FusionPref(MelonPreferences_Category category, string name, T defaultValue, PrefUpdateMode mode = PrefUpdateMode.IGNORE) { _category = category; _entry = category.CreateEntry<T>(name, defaultValue, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); _mode = mode; FusionPreferences.OnFusionPreferencesLoaded = (Action)Delegate.Combine(FusionPreferences.OnFusionPreferencesLoaded, new Action(OnPreferencesLoaded)); } public void SetValue(T value) { _entry.Value = value; OnValueChanged?.Invoke(value); _category.SaveToFile(false); PushUpdate(); } public void OnPreferencesLoaded() { OnValueChanged?.Invoke(GetValue()); PushUpdate(); } private void PushUpdate() { switch (_mode) { case PrefUpdateMode.SERVER_UPDATE: FusionPreferences.SendServerSettings(); MultiplayerHooking.Internal_OnServerSettingsChanged(); break; case PrefUpdateMode.CLIENT_UPDATE: FusionPreferences.SendClientSettings(); break; case PrefUpdateMode.LOCAL_UPDATE: MultiplayerHooking.Internal_OnServerSettingsChanged(); break; case PrefUpdateMode.IGNORE: break; } } public T GetValue() { return _entry.Value; } public static implicit operator T(FusionPref<T> pref) { return pref.GetValue(); } } public static class FusionPreferences { public class ServerSettings { public IFusionPref<bool> NametagsEnabled; public IFusionPref<bool> VoicechatEnabled; public IFusionPref<bool> PlayerConstraintsEnabled; public IFusionPref<bool> VoteKickingEnabled; public IFusionPref<ServerPrivacy> Privacy; public IFusionPref<bool> AllowQuestUsers; public IFusionPref<bool> AllowPCUsers; public IFusionPref<TimeScaleMode> TimeScaleMode; public IFusionPref<byte> MaxPlayers; public IFusionPref<string> ServerName; public IFusionPref<List<string>> ServerTags; public IFusionPref<bool> ServerMortality; public IFusionPref<PermissionLevel> StatChangersAllowed; public IFusionPref<float> StatChangerLeeway; public IFusionPref<PermissionLevel> DevToolsAllowed; public IFusionPref<PermissionLevel> ConstrainerAllowed; public IFusionPref<PermissionLevel> CustomAvatarsAllowed; public IFusionPref<PermissionLevel> KickingAllowed; public IFusionPref<PermissionLevel> BanningAllowed; public IFusionPref<PermissionLevel> Teleportation; public static ServerSettings CreateMelonPrefs() { return new ServerSettings { NametagsEnabled = new FusionPref<bool>(prefCategory, "Server Nametags Enabled", defaultValue: true, PrefUpdateMode.SERVER_UPDATE), VoicechatEnabled = new FusionPref<bool>(prefCategory, "Server Voicechat Enabled", defaultValue: true, PrefUpdateMode.SERVER_UPDATE), PlayerConstraintsEnabled = new FusionPref<bool>(prefCategory, "Server Player Constraints Enabled", defaultValue: false, PrefUpdateMode.SERVER_UPDATE), VoteKickingEnabled = new FusionPref<bool>(prefCategory, "Server Vote Kicking Enabled", defaultValue: true, PrefUpdateMode.SERVER_UPDATE), Privacy = new FusionPref<ServerPrivacy>(prefCategory, "Server Privacy", ServerPrivacy.PUBLIC, PrefUpdateMode.LOCAL_UPDATE), AllowQuestUsers = new FusionPref<bool>(prefCategory, "Allow Quest Users", defaultValue: true, PrefUpdateMode.SERVER_UPDATE), AllowPCUsers = new FusionPref<bool>(prefCategory, "Allow PC Users", defaultValue: true, PrefUpdateMode.SERVER_UPDATE), TimeScaleMode = new FusionPref<TimeScaleMode>(prefCategory, "Time Scale Mode", LabFusion.Senders.TimeScaleMode.LOW_GRAVITY, PrefUpdateMode.SERVER_UPDATE), MaxPlayers = new FusionPref<byte>(prefCategory, "Max Players", 10, PrefUpdateMode.SERVER_UPDATE), ServerName = new FusionPref<string>(prefCategory, "Server Name", "", PrefUpdateMode.LOCAL_UPDATE), ServerTags = new FusionPref<List<string>>(prefCategory, "Server Tags", new List<string>(), PrefUpdateMode.LOCAL_UPDATE), ServerMortality = new FusionPref<bool>(prefCategory, "Server Mortality", defaultValue: true, PrefUpdateMode.SERVER_UPDATE), StatChangersAllowed = new FusionPref<PermissionLevel>(prefCategory, "Stat Changers Allowed", PermissionLevel.OPERATOR, PrefUpdateMode.SERVER_UPDATE), StatChangerLeeway = new FusionPref<float>(prefCategory, "Stat Changer Leeway", 0f, PrefUpdateMode.SERVER_UPDATE), DevToolsAllowed = new FusionPref<PermissionLevel>(prefCategory, "Dev Tools Allowed", PermissionLevel.DEFAULT, PrefUpdateMode.SERVER_UPDATE), ConstrainerAllowed = new FusionPref<PermissionLevel>(prefCategory, "Constrainer Allowed", PermissionLevel.DEFAULT, PrefUpdateMode.SERVER_UPDATE), CustomAvatarsAllowed = new FusionPref<PermissionLevel>(prefCategory, "Custom Avatars Allowed", PermissionLevel.DEFAULT, PrefUpdateMode.SERVER_UPDATE), KickingAllowed = new FusionPref<PermissionLevel>(prefCategory, "Kicking Allowed", PermissionLevel.OPERATOR, PrefUpdateMode.SERVER_UPDATE), BanningAllowed = new FusionPref<PermissionLevel>(prefCategory, "Banning Allowed", PermissionLevel.OPERATOR, PrefUpdateMode.SERVER_UPDATE), Teleportation = new FusionPref<PermissionLevel>(prefCategory, "Teleportation", PermissionLevel.OPERATOR, PrefUpdateMode.SERVER_UPDATE) }; } } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct ClientSettings { public static FusionPref<string> NetworkLayerTitle { get; internal set; } public static FusionPref<int> ProxyPort { get; internal set; } public static FusionPref<bool> NametagsEnabled { get; internal set; } public static FusionPref<Color> NametagColor { get; internal set; } public static FusionPref<string> Nickname { get; internal set; } public static FusionPref<NicknameVisibility> NicknameVisibility { get; internal set; } public static FusionPref<bool> Muted { get; internal set; } public static FusionPref<bool> MutedIndicator { get; internal set; } public static FusionPref<bool> Deafened { get; internal set; } public static FusionPref<float> GlobalVolume { get; internal set; } public static FusionPref<bool> GamemodeMusic { get; internal set; } public static FusionPref<bool> GamemodeLateJoining { get; internal set; } } internal static ServerSettings LocalServerSettings; internal static MenuCategory fusionCategory; internal static MelonPreferences_Category prefCategory; internal static Action OnFusionPreferencesLoaded; private static int _lastIndex; internal static ServerSettings ReceivedServerSettings { get; set; } internal static ServerSettings ActiveServerSettings => ReceivedServerSettings ?? LocalServerSettings; internal static bool NametagsEnabled { get { if (ActiveServerSettings.NametagsEnabled.GetValue()) { return ClientSettings.NametagsEnabled; } return false; } } internal static bool IsMortal => ActiveServerSettings.ServerMortality.GetValue(); internal static TimeScaleMode TimeScaleMode => ActiveServerSettings.TimeScaleMode.GetValue(); internal static void SendServerSettings() { if (!NetworkInfo.HasServer || !NetworkInfo.IsServer) { return; } using FusionWriter fusionWriter = FusionWriter.Create(); using ServerSettingsData value = ServerSettingsData.Create(SerializedServerSettings.Create()); fusionWriter.Write(value); using LabFusion.Network.FusionMessage message = LabFusion.Network.FusionMessage.Create(NativeMessageTag.ServerSettings, fusionWriter); MessageSender.BroadcastMessageExceptSelf(NetworkChannel.Reliable, message); } internal static void SendServerSettings(ulong longId) { if (!NetworkInfo.HasServer || !NetworkInfo.IsServer) { return; } using FusionWriter fusionWriter = FusionWriter.Create(13); using ServerSettingsData value = ServerSettingsData.Create(SerializedServerSettings.Create()); fusionWriter.Write(value); using LabFusion.Network.FusionMessage message = LabFusion.Network.FusionMessage.Create(NativeMessageTag.ServerSettings, fusionWriter); MessageSender.SendFromServer(longId, NetworkChannel.Reliable, message); } internal static void SendClientSettings() { if (!NetworkInfo.HasServer) { return; } using FusionWriter fusionWriter = FusionWriter.Create(17); using PlayerSettingsData value = PlayerSettingsData.Create(PlayerIdManager.LocalSmallId, SerializedPlayerSettings.Create()); fusionWriter.Write(value); using LabFusion.Network.FusionMessage message = LabFusion.Network.FusionMessage.Create(NativeMessageTag.PlayerSettings, fusionWriter); MessageSender.SendToServer(NetworkChannel.Reliable, message); } internal static void OnInitializePreferences() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) prefCategory = MelonPreferences.CreateCategory("BONELAB Fusion"); LocalServerSettings = ServerSettings.CreateMelonPrefs(); ClientSettings.NetworkLayerTitle = new FusionPref<string>(prefCategory, "Network Layer Title", NetworkLayerDeterminer.GetDefaultLayer().Title); ClientSettings.ProxyPort = new FusionPref<int>(prefCategory, "Proxy Port", 28340); ClientSettings.NametagsEnabled = new FusionPref<bool>(prefCategory, "Client Nametags Enabled", defaultValue: true, PrefUpdateMode.LOCAL_UPDATE); ClientSettings.NametagColor = new FusionPref<Color>(prefCategory, "Nametag Color", Color.white, PrefUpdateMode.CLIENT_UPDATE); ClientSettings.Nickname = new FusionPref<string>(prefCategory, "Nickname", ""); ClientSettings.NicknameVisibility = new FusionPref<NicknameVisibility>(prefCategory, "Nickname Visibility", NicknameVisibility.SHOW_WITH_PREFIX, PrefUpdateMode.LOCAL_UPDATE); ClientSettings.Muted = new FusionPref<bool>(prefCategory, "Muted", defaultValue: false); ClientSettings.MutedIndicator = new FusionPref<bool>(prefCategory, "Muted Indicator", defaultValue: true); ClientSettings.Deafened = new FusionPref<bool>(prefCategory, "Deafened", defaultValue: false); ClientSettings.GlobalVolume = new FusionPref<float>(prefCategory, "GlobalMicVolume", 1f); ClientSettings.GamemodeMusic = new FusionPref<bool>(prefCategory, "Gamemode Music", defaultValue: true); ClientSettings.GamemodeLateJoining = new FusionPref<bool>(prefCategory, "Gamemode Late Joining", defaultValue: true); prefCategory.SaveToFile(false); } internal static void OnPrepareBoneMenuCategory() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) fusionCategory = MenuManager.CreateCategory("BONELAB Fusion", Color.white); } internal static void OnCreateBoneMenu() { //IL_0010: 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_0051: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) MenuCategory val = fusionCategory.CreateCategory("Network Layer Manager", Color.yellow); val.CreateFunctionElement("Players need to be on the same layer!", Color.yellow, (Action)null); _lastIndex = NetworkLayer.SupportedLayers.IndexOf(NetworkLayerDeterminer.LoadedLayer); val.CreateFunctionElement("Active Layer: " + NetworkLayerDeterminer.LoadedTitle, Color.white, (Action)null); SubPanelElement targetPanel = val.CreateSubPanel("Target Layer: " + ClientSettings.NetworkLayerTitle.GetValue(), Color.white); targetPanel.CreateFunctionElement("Cycle", Color.white, (Action)delegate { int count = NetworkLayer.SupportedLayers.Count; if (count > 0) { _lastIndex++; if (count <= _lastIndex) { _lastIndex = 0; } ClientSettings.NetworkLayerTitle.SetValue(NetworkLayer.SupportedLayers[_lastIndex].Title); } }); FusionPref<string> networkLayerTitle = ClientSettings.NetworkLayerTitle; networkLayerTitle.OnValueChanged = (Action<string>)Delegate.Combine(networkLayerTitle.OnValueChanged, (Action<string>)delegate(string v) { ((MenuElement)targetPanel).SetName("Target Layer: " + v); }); targetPanel.CreateFunctionElement("Changing this setting requires a game restart!", Color.red, (Action)null); InternalLayerHelpers.OnSetupBoneMenuLayer(fusionCategory); } internal static void OnPreferencesLoaded() { OnFusionPreferencesLoaded?.Invoke(); } } } namespace LabFusion.Utilities { public static class AssemblyUtilities { public static void LoadAllValid<T>(Assembly assembly, Action<Type> runOnValid) { if (assembly.FullName.Contains("System")) { return; } Type[] types = assembly.GetTypes(); foreach (Type type in types) { if ((!type.Name.Contains("Mono") || !type.Name.Contains("Security")) && typeof(T).IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface) { try { runOnValid(type); } catch (Exception ex) { FusionLogger.Error(ex.Message); } } } } } public static class ByteRetriever { public const int DefaultSize = 16; private static FusionArrayPool<byte> _arrayPool; public static void PopulateInitial() { _arrayPool = new FusionArrayPool<byte>(); } public static byte[] Rent(int size = 16) { return _arrayPool.Rent(size); } public static void Return(byte[] array) { _arrayPool.Return(array); } } public static class CommonBarcodes { public const string FADE_OUT_BARCODE = "c1534c5a-dac0-44a1-b656-6c235646584c"; public const string BOARD_BARCODE = "c1534c5a-7b2a-41d7-bf2e-af9544657374"; public const string CONSTRAINER_BARCODE = "c1534c5a-3813-49d6-a98c-f595436f6e73"; public const string CONSTRAINER_ASSET_GUID = "bf9c97bf88c22dc4f981578e75d9aa12"; public const string INVALID_AVATAR_BARCODE = "BONELABFUSION.NONE"; public const string STRONG_BARCODE = "fa534c5a83ee4ec6bd641fec424c4142.Avatar.Strong"; } public static class ConstrainerUtilities { public static bool PlayerConstraintsEnabled => FusionPreferences.ActiveServerSettings.PlayerConstraintsEnabled.GetValue(); public static bool HasConstrainer => (Object)(object)GlobalConstrainer != (Object)null; public static Constrainer GlobalConstrainer { get; private set; } public static void OnMainSceneInitialized() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown SpawnableCrate crate = AssetWarehouse.Instance.GetCrate<SpawnableCrate>("c1534c5a-3813-49d6-a98c-f595436f6e73"); if (!((Object)(object)crate != (Object)null)) { return; } if (!((Crate)crate).Pallet.Internal) { ((GameObjectCrate)crate).MainAsset = new MarrowAsset("bf9c97bf88c22dc4f981578e75d9aa12"); } ((CrateT<GameObject>)(object)crate).LoadAsset(Action<GameObject>.op_Implicit((Action<GameObject>)delegate(GameObject go) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)go == (Object)null)) { GameObject obj = Object.Instantiate<GameObject>(go, new Vector3(1000f, 1000f, 1000f), QuaternionExtensions.identity); GlobalConstrainer = obj.GetComponent<Constrainer>(); obj.SetActive(false); } })); } } public static class DelayUtilities { private class FrameDelayInfo { public Action action; public int counter; } private static readonly List<FrameDelayInfo> _delays = new List<FrameDelayInfo>(); public static void Delay(Action action, int frames) { _delays.Add(new FrameDelayInfo { action = action, counter = frames }); } internal static void Internal_OnUpdate() { for (int num = _delays.Count - 1; num >= 0; num--) { FrameDelayInfo frameDelayInfo = _delays[num]; if (frameDelayInfo.counter <= 0) { try { frameDelayInfo.action(); } catch (Exception ex) { FusionLogger.Error(ex.ToString()); } _delays.RemoveAt(num); } else { frameDelayInfo.counter--; } } } } public static class DllTools { [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)] public static extern IntPtr LoadLibrary(string lpLibFileName); [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] public static extern bool FreeLibrary(IntPtr hModule); [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] public static extern uint GetLastError(); } public static class FusionBitPopup { private static readonly Queue<int> _bitQueue = new Queue<int>(); public const float DefaultDuration = 1f; public static readonly Vector3 LocalPosition = new Vector3(0.319f, -0.198f, 0.783f); public static readonly Quaternion LocalRotation = Quaternion.Euler(0f, 17.252f, 0f); internal static void OnUpdate() { if (FusionSceneManager.HasTargetLoaded() && !FusionSceneManager.IsDelayedLoading() && RigData.HasPlayer && _bitQueue.Count > 0) { DequeueBit(); } } public static void Send(int amount) { _bitQueue.Enqueue(amount); } private static void DequeueBit() { //IL_0037: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) int num = _bitQueue.Dequeue(); Transform head = ((Rig)RigData.RigReferences.ControllerRig).m_head; GameObject obj = Object.Instantiate<GameObject>(FusionContentLoader.BitPopupPrefab, head); UIMachineUtilities.OverrideFonts(obj.transform); obj.transform.localPosition = LocalPosition; obj.transform.localRotation = LocalRotation; Transform val = obj.transform.Find("Offset/Canvas"); string text = ((num < 0) ? $"{num}" : $"+{num}"); ((Component)val.Find("text_shadow")).GetComponent<TMP_Text>().text = text; TMP_Text component = ((Component)val.Find("amount")).GetComponent<TMP_Text>(); component.text = text; if (num < 0) { component.color = Color.red; ((Graphic)((Component)val.Find("bit")).GetComponent<RawImage>()).color = Color.red; } FusionAudio.Play2D(FusionContentLoader.BitGet); Object.Destroy((Object)(object)obj, 1.1f); } } public static class FusionAchievementPopup { public const float DefaultDuration = 5f; public static readonly Vector3 LocalPosition = new Vector3(0f, -0.06f, 0.9f); private static Queue<LabFusion.SDK.Achievements.Achievement> _queuedAchievements = new Queue<LabFusion.SDK.Achievements.Achievement>(); private static float _timeOfPopup = 0f; public static void Send(LabFusion.SDK.Achievements.Achievement achievement) { QueueAchievement(achievement); } private static void QueueAchievement(LabFusion.SDK.Achievements.Achievement achievement) { _queuedAchievements.Enqueue(achievement); } private static void DequeueAchievement() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) _timeOfPopup = Time.realtimeSinceStartup; LabFusion.SDK.Achievements.Achievement achievement = _queuedAchievements.Dequeue(); Transform head = ((Rig)RigData.RigReferences.ControllerRig).m_head; GameObject obj = Object.Instantiate<GameObject>(FusionContentLoader.AchievementPopupPrefab, head); UIMachineUtilities.OverrideFonts(obj.transform); obj.transform.localPosition = LocalPosition; Transform val = obj.transform.Find("Offset/Canvas"); if ((Object)(object)achievement.PreviewImage != (Object)null) { ((Component)val.Find("icon")).GetComponent<RawImage>().texture = (Texture)(object)achievement.PreviewImage; } ((Component)val.Find("title")).GetComponent<TMP_Text>().text = achievement.Title; ((Component)val.Find("description")).GetComponent<TMP_Text>().text = achievement.Description; FusionAudio.Play2D(FusionContentLoader.UITurnOn); Object.Destroy((Object)(object)obj, 5.1f); } internal static bool IsPlayingPopup() { return Time.realtimeSinceStartup - _timeOfPopup <= 5.1f; } internal static void OnInitializeMelon() { LabFusion.SDK.Achievements.Achievement.OnAchievementCompleted += Send; } internal static void OnUpdate() { if (_queuedAchievements.Count > 0 && FusionSceneManager.HasTargetLoaded() && !FusionSceneManager.IsDelayedLoading() && RigData.HasPlayer && !IsPlayingPopup()) { DequeueAchievement(); } } } public static class FusionAvatar { public const string POLY_BLANK_BARCODE = "c3534c5a-94b2-40a4-912a-24a8506f6c79"; public const string POLY_BLANK_NAME = "char_marrow1_polyBlank"; public static bool IsMatchingAvatar(string barcode, string target) { if (!(barcode == target)) { return barcode == "c3534c5a-94b2-40a4-912a-24a8506f6c79"; } return true; } } public delegate bool UserOverride(PlayerId id); public static class FusionOverrides { private static UserOverride _onValidateNametag; public static event UserOverride OnValidateNametag { add { _onValidateNametag = (UserOverride)Delegate.Combine(_onValidateNametag, value); ForceUpdateOverrides(); } remove { _onValidateNametag = (UserOverride)Delegate.Remove(_onValidateNametag, value); ForceUpdateOverrides(); } } public static event Action OnOverridesChanged; public static bool ValidateNametag(PlayerId id) { if (_onValidateNametag == null) { return true; } Delegate[] invocationList = _onValidateNametag.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { if (!((UserOverride)invocationList[i])(id)) { return false; } } return true; } public static void ForceUpdateOverrides() { FusionOverrides.OnOverridesChanged.InvokeSafe("executing OnOverridesChanged"); } } public class AchievementPair { public Texture2D Preview { get; private set; } public static AchievementPair LoadFromBundle(AssetBundle bundle, string name) { return new AchievementPair { Preview = bundle.LoadPersistentAsset<Texture2D>("preview_" + name) }; } } public static class FusionAchievementLoader { private static readonly string[] _achievementNames = new string[20] { "ExperiencedExecutioner", "MediocreMarksman", "RookieAssassin", "Rampage", "StyleAddict", "StyleBaby", "StyleMan", "Betrayal", "OneMoreTime", "HeadOfHouse", "WarmWelcome", "BouncingStrong", "LavaGang", "CleanupCrew", "ClassStruggle", "GuardianAngel", "HighwayMan", "DaycareAttendant", "AroundTheWorld", "HelloThere" }; private static readonly Dictionary<string, AchievementPair> _achievementPairs = new Dictionary<string, AchievementPair>(); public static AssetBundle AchievementBundle { get; private set; } public static void OnBundleLoad() { AchievementBundle = FusionBundleLoader.LoadAssetBundle("achievement_bundle.fusion"); if ((Object)(object)AchievementBundle != (Object)null) { string[] achievementNames = _achievementNames; foreach (string text in achievementNames) { _achievementPairs.Add(text, AchievementPair.LoadFromBundle(AchievementBundle, text)); } } else { FusionLogger.Error("Achievement bundle failed to load!"); } } public static void OnBundleUnloaded() { if ((Object)(object)AchievementBundle != (Object)null) { AchievementBundle.Unload(true); } } public static AchievementPair GetPair(string name) { return _achievementPairs[name]; } } public class ItemPair { public GameObject GameObject { get; private set; } public Texture2D Preview { get; private set; } public static ItemPair LoadFromBundle(AssetBundle bundle, string name) { return new ItemPair { GameObject = bundle.LoadPersistentAsset<GameObject>("item_" + name), Preview = bundle.LoadPersistentAsset<Texture2D>("preview_" + name) }; } } public static class FusionPointItemLoader { private static readonly string[] _itemNames = new string[73] { "Gemstone", "GloopTrail", "Junktion", "PulsatingMass", "RubixCube", "BitsTrail", "CardboardTophat", "Glasses3D", "AdventureHat", "WaistRing", "BodyPillow", "BritishHelm", "CardboardDisguise", "CatBeanie", "CheeseHat", "ConstructionHat", "Cooler", "EltonGlasses", "EnaHat", "Fez", "Firework", "Fren", "FryCookHat", "Gearhead", "GuardHelmet", "KickMeSign", "KnollHat", "LaytonHat", "LegoHead", "LightningHead", "Monocle", "NyanTrail", "PartyHat", "PieceOfResistance", "SorcererHat", "StormyHead", "TestItem", "TheBeacon", "WeirdShades", "BitMiner", "AncientTablet", "BitBackpack", "Briefcase", "CirclingBit", "Floatie", "Headset", "HotHead", "Jetpack", "NESGuitar", "OctoSpecs", "Potion", "PsychicPerception", "RetroMind", "SignalingSpiral", "Speaker", "VioletVortex", "VictoryTrophy", "ArrowHead", "BucketHat", "CBRNGasMask", "Crown", "Fedoral", "FlinchsJinjle", "GP5", "JesterHat", "MissedAWideGlasses", "MissedAWideHat", "OldTimeyPipe", "RiotHelmet", "Smitty", "VirtuallyInsane", "Wonker", "ZestySwagShades" }; private static readonly Dictionary<string, ItemPair> _itemPairs = new Dictionary<string, ItemPair>(); public static AssetBundle ItemBundle { get; private set; } public static void OnBundleLoad() { ItemBundle = FusionBundleLoader.LoadAssetBundle("item_bundle.fusion"); if ((Object)(object)ItemBundle != (Object)null) { string[] itemNames = _itemNames; foreach (string text in itemNames) { _itemPairs.Add(text, ItemPair.LoadFromBundle(ItemBundle, text)); } } else { FusionLogger.Error("Item bundle failed to load!"); } } public static void OnBundleUnloaded() { if ((Object)(object)ItemBundle != (Object)null) { ItemBundle.Unload(true); } } public static ItemPair GetPair(string name) { return _itemPairs[name]; } } public static class FusionContentLoader { private static readonly string[] _combatSongNames = new string[6] { "music_FreqCreepInModulationBuggyPhysics", "music_SicklyBugInitiative", "music_SyntheticCavernsRemix", "music_WWWonderlan", "music_SmigglesInDespair", "music_AppenBeyuge" }; private static readonly List<AudioClip> _combatPlaylist = new List<AudioClip>(); public static AssetBundle ContentBundle { get; private set; } public static GameObject PointShopPrefab { get; private set; } public static GameObject InfoBoxPrefab { get; private set; } public static GameObject CupBoardPrefab { get; private set; } public static GameObject EntangledLinePrefab { get; private set; } public static GameObject AchievementPopupPrefab { get; private set; } public static GameObject BitPopupPrefab { get; private set; } public static GameObject MutePopupPrefab { get; private set; } public static Texture2D SabrelakeLogo { get; private set; } public static Texture2D LavaGangLogo { get; private set; } public static AudioClip GeoGrpFellDownTheStairs { get; private set; } public static AudioClip BouncingStrong { get; private set; } public static AudioClip LavaGangVictory { get; private set; } public static AudioClip SabrelakeVictory { get; private set; } public static AudioClip LavaGangFailure { get; private set; } public static AudioClip SabrelakeFailure { get; private set; } public static AudioClip DMTie { get; private set; } public static AudioClip BitGet { get; private set; } public static AudioClip UISelect { get; private set; } public static AudioClip UIDeny { get; private set; } public static AudioClip UIConfirm { get; private set; } public static AudioClip UITurnOff { get; private set; } public static AudioClip UITurnOn { get; private set; } public static AudioClip PurchaseFailure { get; private set; } public static AudioClip PurchaseSuccess { get; private set; } public static AudioClip EquipItem { get; private set; } public static AudioClip UnequipItem { get; private set; } public static Texture2D NotificationInformation { get; private set; } public static Texture2D NotificationWarning { get; private set; } public static Texture2D NotificationError { get; private set; } public static Texture2D NotificationSuccess { get; private set; } public static GameObject LaserCursor { get; private set; } public static AudioClip LaserPulseSound { get; private set; } public static AudioClip LaserRaySpawn { get; private set; } public static AudioClip LaserRayDespawn { get; private set; } public static AudioClip LaserPrismaticSFX { get; private set; } public static AudioClip[] CombatPlaylist => _combatPlaylist.ToArray(); public static void OnBundleLoad() { ContentBundle = FusionBundleLoader.LoadAssetBundle("content_bundle.fusion"); if ((Object)(object)ContentBundle != (Object)null) { PointShopPrefab = ContentBundle.LoadPersistentAsset<GameObject>("machine_PointShop"); InfoBoxPrefab = ContentBundle.LoadPersistentAsset<GameObject>("machine_InfoBox"); CupBoardPrefab = ContentBundle.LoadPersistentAsset<GameObject>("machine_CupBoard"); EntangledLinePrefab = ContentBundle.LoadPersistentAsset<GameObject>("renderer_EntangledLine"); AchievementPopupPrefab = ContentBundle.LoadPersistentAsset<GameObject>("achievement_Popup"); BitPopupPrefab = ContentBundle.LoadPersistentAsset<GameObject>("bit_Popup"); MutePopupPrefab = ContentBundle.LoadPersistentAsset<GameObject>("mute_Popup"); SabrelakeLogo = ContentBundle.LoadPersistentAsset<Texture2D>("tex_sabreLakeLogo"); LavaGangLogo = ContentBundle.LoadPersistentAsset<Texture2D>("tex_lavaGangLogo"); string[] combatSongNames = _combatSongNames; foreach (string name in combatSongNames) { _combatPlaylist.Add(ContentBundle.LoadPersistentAsset<AudioClip>(name)); } GeoGrpFellDownTheStairs = ContentBundle.LoadPersistentAsset<AudioClip>("music_GeoGrpFellDownTheStairs"); BouncingStrong = ContentBundle.LoadPersistentAsset<AudioClip>("music_BouncingStrong"); LavaGangVictory = ContentBundle.LoadPersistentAsset<AudioClip>("sting_LavaGangVictory"); SabrelakeVictory = ContentBundle.LoadPersistentAsset<AudioClip>("sting_sabrelakeVictory"); LavaGangFailure = ContentBundle.LoadPersistentAsset<AudioClip>("sting_LavaGangFailure"); SabrelakeFailure = ContentBundle.LoadPersistentAsset<AudioClip>("sting_sabrelakeFailure"); DMTie = ContentBundle.LoadPersistentAsset<AudioClip>("sting_DMTie"); BitGet = ContentBundle.LoadPersistentAsset<AudioClip>("stinger_BitGet"); UISelect = ContentBundle.LoadPersistentAsset<AudioClip>("UI_Beep_Bend_Short_stereo"); UIDeny = ContentBundle.LoadPersistentAsset<AudioClip>("UI_Error_Double_Note_Down_Notch_stereo"); UIConfirm = ContentBundle.LoadPersistentAsset<AudioClip>("UI_SCI-FI_Confirm_Dry_stereo"); UITurnOff = ContentBundle.LoadPersistentAsset<AudioClip>("UI_TurnOff"); UITurnOn = ContentBundle.LoadPersistentAsset<AudioClip>("UI_TurnOn"); PurchaseFailure = ContentBundle.LoadPersistentAsset<AudioClip>("stinger_FailPurchase"); PurchaseSuccess = ContentBundle.LoadPersistentAsset<AudioClip>("stinger_SuccessPurchase"); EquipItem = ContentBundle.LoadPersistentAsset<AudioClip>("ui_EquipItem"); UnequipItem = ContentBundle.LoadPersistentAsset<AudioClip>("ui_UnequipItem"); NotificationInformation = ContentBundle.LoadPersistentAsset<Texture2D>("notification_Information"); NotificationWarning = ContentBundle.LoadPersistentAsset<Texture2D>("notification_Warning"); NotificationError = ContentBundle.LoadPersistentAsset<Texture2D>("notification_Error"); NotificationSuccess = ContentBundle.LoadPersistentAsset<Texture2D>("notification_Success"); LaserCursor = ContentBundle.LoadPersistentAsset<GameObject>("laser_Cursor"); LaserPulseSound = ContentBundle.LoadPersistentAsset<AudioClip>("laser_PulseSound"); LaserRaySpawn = ContentBundle.LoadPersistentAsset<AudioClip>("laser_RaySpawn"); LaserRayDespawn = ContentBundle.LoadPersistentAsset<AudioClip>("laser_RayDespawn"); LaserPrismaticSFX = ContentBundle.LoadPersistentAsset<AudioClip>("laser_PrismaticSFX"); } else { FusionLogger.Error("Content Bundle failed to load!"); } } public static void OnBundleUnloaded() { if ((Object)(object)ContentBundle != (Object)null) { ContentBundle.Unload(true); } } } public class FusionComponentCache<TSource, TComponent> where TSource : Object where TComponent : class { private readonly FusionDictionary<TSource, TComponent> _Cache = new FusionDictionary<TSource, TComponent>((IEqualityComparer<TSource>)new UnityComparer()); private readonly HashSet<TSource> _HashTable = new HashSet<TSource>((IEqualityComparer<TSource>?)new UnityComparer()); public ICollection<TComponent> Components => _Cache.Values; public TComponent Get(TSource source) { if (_HashTable.ContainsIL2CPP(source)) { return _Cache[source]; } return null; } public bool TryGet(TSource source, out TComponent value) { if (!_HashTable.ContainsIL2CPP(source)) { value = null; return false; } value = _Cache[source]; return true; } public bool ContainsSource(TSource source) { return _HashTable.ContainsIL2CPP(source); } public void Add(TSource source, TComponent component) { if (_Cache.ContainsKey(source)) { _Cache[source] = component; return; } _HashTable.Add(source); _Cache.Add(source, component); } public void Remove(TSource source) { _HashTable.RemoveIL2CPP(source); _Cache.Remove(source); } } public static class FusionDevTools { public static bool DespawnConstrainer(PlayerId id) { FusionPermissions.FetchPermissionLevel(id, out var level, out var _); if (!FusionPermissions.HasSufficientPermissions(level, FusionPreferences.ActiveServerSettings.ConstrainerAllowed.GetValue())) { return true; } return false; } public static bool DespawnDevTool(PlayerId id) { if (Gamemode.ActiveGamemode != null && Gamemode.ActiveGamemode.DisableDevTools) { return true; } FusionPermissions.FetchPermissionLevel(id, out var level, out var _); if (!FusionPermissions.HasSufficientPermissions(level, FusionPreferences.ActiveServerSettings.DevToolsAllowed.GetValue())) { return true; } return false; } public static bool PreventSpawnGun(PlayerId id) { if (Gamemode.ActiveGamemode != null && Gamemode.ActiveGamemode.DisableSpawnGun) { return true; } FusionPermissions.FetchPermissionLevel(id, out var level, out var _); if (!FusionPermissions.HasSufficientPermissions(level, FusionPreferences.ActiveServerSettings.DevToolsAllowed.GetValue())) { return true; } return false; } } public static class FusionAudio { public static AudioSource Play2D(AudioClip clip, float volume = 1f) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown GameObject val = new GameObject("Fusion 2D Audio Source"); AudioSource source = val.AddComponent<AudioSource>(); source.volume = volume; source.clip = clip; source.spatialBlend = 0f; PersistentAssetCreator.HookOnSFXMixerLoaded(delegate(AudioMixerGroup m) { if ((Object)(object)source != (Object)null) { source.outputAudioMixerGroup = m; } }); source.Play(); return source; } public static AudioSource Play3D(Vector3 position, AudioClip clip, float volume = 1f, bool loop = false) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Fusion 3D Audio Source"); AudioSource source = val.AddComponent<AudioSource>(); val.transform.position = position; source.volume = volume; source.clip = clip; source.spatialBlend = 1f; source.loop = loop; PersistentAssetCreator.HookOnSFXMixerLoaded(delegate(AudioMixerGroup m) { if ((Object)(object)source != (Object)null) { source.outputAudioMixerGroup = m; } }); source.Play(); return source; } } public static class FusionPlayer { public static readonly List<Transform> SpawnPoints = new List<Transform>(); public static byte? LastAttacker { get; internal set; } public static float? VitalityOverride { get; internal set; } = null; public static string AvatarOverride { get; internal set; } = null; internal static void OnMainSceneInitialized() { LastAttacker = null; } internal static void Internal_OnAvatarChanged(RigManager rigManager, Avatar avatar, string barcode) { RigData.RigAvatarStats = new SerializedAvatarStats(avatar); RigData.RigAvatarId = barcode; PlayerSender.SendPlayerAvatar(RigData.RigAvatarStats, barcode); if (VitalityOverride.HasValue) { Internal_ChangePlayerHealth(); } AvatarCrate crate = ((CrateReferenceT<AvatarCrate>)(object)rigManager.AvatarCrate).Crate; PermissionLevel level; if (AvatarOverride != null && !FusionAvatar.IsMatchingAvatar(barcode, AvatarOverride)) { Internal_ChangeAvatar(); } else if ((Object)(object)crate != (Object)null && !((Crate)crate).Pallet.Internal && PlayerIdManager.LocalId != null && PlayerIdManager.LocalId.TryGetPermissionLevel(out level)) { PermissionLevel value = FusionPreferences.ActiveServerSettings.CustomAvatarsAllowed.GetValue(); if (!FusionPermissions.HasSufficientPermissions(level, value)) { rigManager.SwapAvatarCrate("c3534c5a-94b2-40a4-912a-24a8506f6c79", true, (Action<bool>)null); } } PlayerAdditionsHelper.OnAvatarChanged(rigManager); } public static bool TryGetLastAttacker(out PlayerId id) { id = null; if (!LastAttacker.HasValue) { return false; } id = PlayerIdManager.GetPlayerId(LastAttacker.Value); return id != null; } public static bool IsSelf(this RigManager rigManager) { if (!RigData.HasPlayer) { return true; } return (Object)(object)rigManager == (Object)(object)RigData.RigReferences.RigManager; } public static void SetAmmo(int count) { RigManager rigManager = RigData.RigReferences.RigManager; if (!((Object)(object)rigManager).IsNOC()) { AmmoInventory ammoInventory = rigManager.AmmoInventory; ammoInventory.ClearAmmo(); ammoInventory.AddCartridge(ammoInventory.lightAmmoGroup, count); ammoInventory.AddCartridge(ammoInventory.heavyAmmoGroup, count); ammoInventory.AddCartridge(ammoInventory.mediumAmmoGroup, count); } } public static bool CanUnragdoll() { if (Gamemode.ActiveGamemode != null && Gamemode.ActiveGamemode.DisableManualUnragdoll) { return false; } return true; } public static void SetMortality(bool isMortal) { RigManager rigManager = RigData.RigReferences.RigManager; if (!((Object)(object)rigManager).IsNOC()) { Player_Health val = ((Il2CppObjectBase)rigManager.health).TryCast<Player_Health>(); if (isMortal) { ((Health)val).healthMode = (HealthMode)1; } else { ((Health)val).healthMode = (HealthMode)0; } } } public static void ResetMortality() { if (NetworkInfo.HasServer) { SetMortality(FusionPreferences.IsMortal); } } public static void Teleport(Vector3 position, Vector3 fwdSnap, bool zeroVelocity = true) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (RigData.HasPlayer) { RigManager rigManager = RigData.RigReferences.RigManager; rigManager.Teleport(position, fwdSnap, zeroVelocity); rigManager.physicsRig.ResetHands((Handedness)3); } } public static void SetSpawnPoints(params Transform[] points) { SpawnPoints.Clear(); SpawnPoints.AddRange(points); } public static void ResetSpawnPoints() { SpawnPoints.Clear(); } public static void SetAvatarOverride(string barcode) { AvatarOverride = barcode; Internal_ChangeAvatar(); } public static void ClearAvatarOverride() { AvatarOverride = null; } public static void SetPlayerVitality(float vitality) { VitalityOverride = vitality; Internal_ChangePlayerHealth(); } public static void ClearPlayerVitality() { VitalityOverride = null; Internal_ChangePlayerHealth(); } private static void Internal_ChangeAvatar() { if (!RigData.HasPlayer || !AssetWarehouse.ready || AvatarOverride == null || !((Object)(object)AssetWarehouse.Instance.GetCrate<AvatarCrate>(AvatarOverride) != (Object)null)) { return; } RigManager rm = RigData.RigReferences.RigManager; rm.SwapAvatarCrate(AvatarOverride, true, Action<bool>.op_Implicit((Action<bool>)delegate(bool success) { if (!success) { rm.SwapAvatarCrate("c3534c5a-94b2-40a4-912a-24a8506f6c79", true, (Action<bool>)null); } })); } private static void Internal_ChangePlayerHealth() { if (RigData.HasPlayer) { RigManager rigManager = RigData.RigReferences.RigManager; Avatar avatar = rigManager._avatar; if (VitalityOverride.HasValue) { avatar._vitality = VitalityOverride.Value; rigManager.health.SetAvatar(avatar); } else { avatar.RefreshBodyMeasurements(); rigManager.health.SetAvatar(avatar); } } } public static bool TryGetSpawnPoint(out Transform point) { point = null; SpawnPoints.RemoveAll((Transform t) => (Object)(object)t == (Object)null); if (SpawnPoints.Count > 0) { point = Extensions.GetRandom<Transform>(SpawnPoints); return true; } return false; } } public static class FusionPopupManager { internal static void OnInitializeMelon() { FusionAchievementPopup.OnInitializeMelon(); } internal static void OnUpdate() { FusionNotifier.OnUpdate(); FusionAchievementPopup.OnUpdate(); FusionBitPopup.OnUpdate(); } } public static class FusionSceneManager { private static Action _onTargetLevelLoad = null; private static Action _onLevelLoad = null; private static Action _onDelayedLevelLoad = null; private static bool _isLoading = false; private static bool _wasLoading = false; private static string _prevLevelBarcode = "NONE"; public const float LEVEL_LOAD_WINDOW = 0.5f; private static bool _isDelayedLoading = false; private static float _loadingTimer = 0f; private static string _targetServerScene = null; private static bool _hasStartedLoadingTarget = false; private static bool _hasEnteredTargetLoadingScreen = false; public static LevelCrate Level => SceneStreamer.Session.Level; public static string Barcode { get { if (!((Object)(object)Level != (Object)null)) { return ""; } return Barcode.op_Implicit(((Scannable)Level).Barcode); } } public static string Title { get { if (!((Object)(object)Level != (Object)null)) { return ""; } return ((Scannable)Level).Title; } } internal static void Internal_OnInitializeMelon() { MultiplayerHooking.OnStartServer += Internal_OnCleanup; MultiplayerHooking.OnDisconnect += Internal_OnCleanup; } private static void Internal_OnCleanup() { _targetServerScene = null; _hasStartedLoadingTarget = false; _hasEnteredTargetLoadingScreen = false; } private static void Internal_SetServerScene(string barcode) { _targetServerScene = barcode; _hasStartedLoadingTarget = false; _hasEnteredTargetLoadingScreen = false; } private static void Internal_UpdateLoadStatus() { if (IsLoading_Internal()) { _prevLevelBarcode = null; _isLoading = true; if (!_wasLoading) { LoadSender.SendLoadingState(isLoading: true); if (NetworkInfo.IsServer) { LoadSender.SendLevelLoad(Barcode); } MultiplayerHooking.Internal_OnLoadingBegin(); } } else if (_prevLevelBarcode == null) { _isLoading = false; FusionMod.OnMainSceneInitialized(); _prevLevelBarcode = Barcode; LoadSender.SendLoadingState(isLoading: false); _onLevelLoad?.Invoke(); _onLevelLoad = null; if (HasTargetLoaded()) { _onTargetLevelLoad?.Invoke(); _onTargetLevelLoad = null; } } _wasLoading = _isLoading; } private static void Internal_UpdateDelayedLoadStatus() { if (_isLoading) { _loadingTimer = 0f; _isDelayedLoading = true; } else if (_loadingTimer <= 0.5f) { _loadingTimer += Time.deltaTime; _isDelayedLoading = true; } else if (_isDelayedLoading) { _isDelayedLoading = false; FusionMod.OnMainSceneInitializeDelayed(); _onDelayedLevelLoad?.Invoke(); _onDelayedLevelLoad = null; } } private static void Internal_UpdateTargetScene() { if (NetworkInfo.IsClient) { if (_hasStartedLoadingTarget && IsLoading()) { _hasEnteredTargetLoadingScreen = true; } if (IsDelayedLoadDone() && !_hasStartedLoadingTarget && !string.IsNullOrEmpty(_targetServerScene)) { SceneLoadPatch.IgnorePatches = true; SceneStreamer.Load(_targetServerScene, ""); SceneLoadPatch.IgnorePatches = false; _hasStartedLoadingTarget = true; } } } internal static void Internal_UpdateScene() { Internal_UpdateLoadStatus(); Internal_UpdateDelayedLoadStatus(); Internal_UpdateTargetScene(); } public static void SetTargetScene(string barcode) { Internal_SetServerScene(barcode); } public static void HookOnTargetLevelLoad(Action action) { if (!HasTargetLoaded()) { _onTargetLevelLoad = (Action)Delegate.Combine(_onTargetLevelLoad, action); } else { action?.Invoke(); } } public static void HookOnLevelLoad(Action action) { if (IsLoading()) { _onLevelLoad = (Action)Delegate.Combine(_onLevelLoad, action); } else { action?.Invoke(); } } public static void HookOnDelayedLevelLoad(Action action) { if (IsDelayedLoading()) { _onDelayedLevelLoad = (Action)Delegate.Combine(_onDelayedLevelLoad, action); } else { action?.Invoke(); } } public static bool HasLevel(string barcode) { if ((Object)(object)AssetWarehouse.Instance.GetCrate<LevelCrate>(barcode) != (Object)null) { return true; } return false; } public static bool IsLoading() { return _isLoading; } public static bool IsDelayedLoading() { return _isDelayedLoading; } public static bool IsLoadDone() { return !_isLoading; } public static bool IsDelayedLoadDone() { return !_isDelayedLoading; } public static bool HasTargetLoaded() { if (!NetworkInfo.HasServer || NetworkInfo.IsServer) { return IsLoadDone(); } if (_hasStartedLoadingTarget && _hasEnteredTargetLoadingScreen) { return IsLoadDone(); } return false; } private static bool IsLoading_Internal() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 return (int)SceneStreamer.Session.Status == 1; } } public static class GameObjectUtilities { private static readonly List<GameObject> _rootObjectBuffer = new List<GameObject>(); internal static List<GameObject> FindRootsWithName(string scene, string name) { //IL_000e: 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) Scene sceneByName = SceneManager.GetSceneByName(scene); if (!((Scene)(ref sceneByName)).IsValid()) { return null; } _rootObjectBuffer.Capacity = ((Scene)(ref sceneByName)).rootCount; ((Scene)(ref sceneByName)).GetRootGameObjects(_rootObjectBuffer); _rootObjectBuffer.RemoveAll(Predicate<GameObject>.op_Implicit((Func<GameObject, bool>)((GameObject g) => ((Object)g).name != name))); return _rootObjectBuffer; } internal static int GetRootIndex(this GameObject go) { //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) Scene scene = go.scene; return FindRootsWithName(((Scene)(ref scene)).name, ((Object)go).name).FindIndex(Predicate<GameObject>.op_Implicit((Func<GameObject, bool>)((GameObject g) => (Object)(object)g == (Object)(object)go))); } internal static GameObject GetRootByIndex(string scene, int index, string name) { List<GameObject> val = FindRootsWithName(scene, name); if (val == null || val.Count == 0) { return GameObject.Find("/" + name); } if (val.Count <= index) { return val[val.Count - 1]; } return val[index]; } public static string GetFullPath(this GameObject go) { //IL_000e: 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) try { object[] array = new object[4]; Scene scene = go.scene; array[0] = ((Scene)(ref scene)).name; array[1] = '¬'; array[2] = ((Component)go.transform.root).gameObject.GetRootIndex(); array[3] = go.transform.GetBasePath(); return string.Format("{0}{1}{2}{3}", array); } catch { } return "INVALID_PATH"; } public static GameObject GetGameObject(string path) { string[] array = path.Split(new char[1] { '¬' }); string scene = array[0]; int index = int.Parse(array[1]); string name = array[2]; try { GameObject rootByIndex = GetRootByIndex(scene, index, name); if ((Object)(object)rootByIndex != (Object)null) { Transform val = rootByIndex.transform; for (int i = 3; i < array.Length; i++) { val = val.GetTransformByIndex(int.Parse(array[i++]), array[i]); } return ((Component)val).gameObject; } } catch (Exception) { } return null; } internal static async Task<List<GameObject>> FindRootsWithNameAsync(string scene, string name) { await Task.Delay(16); Scene sceneAsset = default(Scene); bool isFinished = false; ThreadingUtilities.RunSynchronously(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) sceneAsset = SceneManager.GetSceneByName(scene); isFinished = true; }); while (!isFinished) { await Task.Delay(16); } ThreadingUtilities.IL2PrepareThread(); List<GameObject> buffer = new List<GameObject>(); isFinished = false; if (!((Scene)(ref sceneAsset)).IsValid()) { return buffer; } ThreadingUtilities.RunSynchronously(delegate { buffer.Capacity = ((Scene)(ref sceneAsset)).rootCount; ((Scene)(ref sceneAsset)).GetRootGameObjects(buffer); isFinished = true; }); while (!isFinished) { await Task.Delay(16); } ThreadingUtilities.IL2PrepareThread(); buffer.RemoveAll(Predicate<GameObject>.op_Implicit((Func<GameObject, bool>)((GameObject g) => ((Object)g).name != name))); return buffer; } internal static async Task<int> GetRootIndexAsync(this GameObject go) { await Task.Delay(16); ThreadingUtilities.IL2PrepareThread(); Scene scene = go.scene; string name = ((Scene)(ref scene)).name; string name2 = ((Object)go).name; List<GameObject> obj = await FindRootsWithNameAsync(name, name2); ThreadingUtilities.IL2PrepareThread(); return obj.FindIndex(Predicate<GameObject>.op_Implicit((Func<GameObject, bool>)((GameObject g) => (Object)(object)g == (Object)(object)go))); } internal static async Task<GameObject> GetRootByIndexAsync(string scene, int index, string name) { await Task.Delay(16); List<GameObject> val = await FindRootsWithNameAsync(scene, name); ThreadingUtilities.IL2PrepareThread(); return (val == null || val.Count == 0) ? GameObject.Find("/" + name) : ((val.Count > index) ? val[index] : val[val.Count - 1]); } public static async Task<string> GetFullPathAsync(this GameObject go, Action<string> onComplete = null) { await Task.Delay(16); string path = null; ThreadingUtilities.IL2PrepareThread(); try { Transform transform = go.transform; int num = await ((Component)transform.root).gameObject.GetRootIndexAsync(); ThreadingUtilities.IL2PrepareThread(); object[] array = new object[4]; Scene scene = go.scene; array[0] = ((Scene)(ref scene)).name; array[1] = '¬'; array[2] = num; array[3] = transform.GetBasePath(); path = string.Format("{0}{1}{2}{3}", array); } catch { } if (onComplete != null) { ThreadingUtilities.RunSynchronously(delegate { onComplete(path); }); } return path; } public static async Task<GameObject> GetGameObjectAsync(string path, Action<GameObject> onComplete = null) { await Task.Delay(16); string[] parts = path.Split(new char[1] { '¬' }); string scene = parts[0]; int index = int.Parse(parts[1]); string name = parts[2]; ThreadingUtilities.IL2PrepareThread(); GameObject result = null; try { GameObject val = await GetRootByIndexAsync(scene, index, name); ThreadingUtilities.IL2PrepareThread(); if ((Object)(object)val != (Object)null) { Transform val2 = val.transform; for (int i = 3; i < parts.Length; i++) { val2 = val2.GetTransformByIndex(int.Parse(parts[i++]), parts[i]); } result = ((Component)val2).gameObject; if (onComplete != null) { ThreadingUtilities.RunSynchronously(delegate { onComplete(result); }); } } } catch (Exception) { } return result; } } public static class ImpactUtilities { public static void OnHitRigidbody(Rigidbody rb) { GameObject go = ((Component)rb).gameObject; if (PropSyncable.HostCache.TryGet(go, out var value)) { if (!value.IsHeld && !value.IsVehicle) { PropSender.SendOwnershipTransfer(value); } } else if (go.IsSyncWhitelisted()) { DelayUtilities.Delay(delegate { PropSender.SendPropCreation(go); }, 4); } } } internal static class FusionBundleLoader { public static T LoadPersistentAsset<T>(this AssetBundle bundle, string name) where T : Object { Object val = bundle.LoadAsset(name); if (val != (Object)null) { val.hideFlags = (HideFlags)32; return ((Il2CppObjectBase)val).TryCast<T>(); } return default(T); } public static AssetBundle LoadAssetBundle(string name) { if (HelperMethods.IsAndroid()) { return EmbeddedAssetBundle.LoadFromAssembly(FusionMod.FusionAssembly, "LabFusion.Core.resources.bundles.Android." + name); } return EmbeddedAssetBundle.LoadFromAssembly(FusionMod.FusionAssembly, "LabFusion.Core.resources.bundles.StandaloneWindows64." + name); } public static void OnBundleLoad() { FusionContentLoader.OnBundleLoad(); FusionPointItemLoader.OnBundleLoad(); FusionAchievementLoader.OnBundleLoad(); } public static void OnBundleUnloaded() { FusionContentLoader.OnBundleUnloaded(); FusionPointItemLoader.OnBundleUnloaded(); FusionAchievementLoader.OnBundleUnloaded(); } } public enum NotificationType { INFORMATION, WARNING, ERROR, SUCCESS } public struct NotificationText { public string text; public Color color; public bool richText; public NotificationText(string text) : this(text, Color.white) { }//IL_0002: Unknown result type (might be due to invalid IL or missing references) public NotificationText(string text, Color color, bool richText = false) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!richText) { text = text.RemoveRichText(); } this.text = text; this.color = color; this.richText = richText; } public static implicit operator NotificationText(string text) { return new NotificationText(text); } } public class FusionNotification { public NotificationText title; public NotificationText message; public bool showTitleOnPopup; public bool isPopup = true; public float popupLength = 2f; public NotificationType type; public bool isMenuItem = true; public Action<MenuCategory> onCreateCategory; } public static class FusionNotifier { public const float DefaultDuration = 2f; private static readonly Queue<FusionNotification> _queuedNotifications = new Queue<FusionNotification>(); private static ulong _notificationNumber = 0uL; private static bool _hasEnabledTutorialRig = false; public static void Send(FusionNotification notification) { QueueNotification(notification); } private static void QueueNotification(FusionNotification notification) { _queuedNotifications.Enqueue(notification); } private static void DequeueNotification() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) FusionNotification fusionNotification = _queuedNotifications.Dequeue(); if (fusionNotification.isMenuItem) { string text = $"Internal_Notification_Generated_{_notificationNumber}"; MenuCategory category = BoneMenuCreator.NotificationCategory.CreateCategory(text, fusionNotification.title.color); ((MenuElement)category).SetName(fusionNotification.title.text); _notificationNumber++; if (!string.IsNullOrWhiteSpace(fusionNotification.message.text)) { category.CreateFunctionElement(fusionNotification.message.text, fusionNotification.message.color, (Action)null); } category.CreateFunctionElement("Mark as Read", Color.red, (Action)delegate { BoneMenuCreator.RemoveNotification((MenuElement)(object)category); }); fusionNotification.onCreateCategory.InvokeSafe<Action<MenuCategory>, MenuCategory>(category, "executing Notification.OnCreateCategory"); } RigManager rigManager = RigData.RigReferences.RigManager; if (fusionNotification.isPopup && !((Object)(object)rigManager).IsNOC()) { HeadTitles headTitles = rigManager.tutorialRig.headTitles; EnableTutorialRig(); string text2 = "New Notification"; if (fusionNotification.showTitleOnPopup) { text2 = fusionNotification.title.text; } string text3 = fusionNotification.message.text; Texture2D val = (Texture2D)(fusionNotification.type switch { NotificationType.WARNING => FusionContentLoader.NotificationWarning, NotificationType.ERROR => FusionContentLoader.NotificationError, NotificationType.SUCCESS => FusionContentLoader.NotificationSuccess, _ => FusionContentLoader.NotificationInformation, }); Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); float popupLength = fusionNotification.popupLength; headTitles.CUSTOMDISPLAY(text2, text3, val2, popupLength, (AudioClip)null, false, (Sprite)null, (Sprite)null, (Sprite)null, (Sprite)null); headTitles.sr_element.sprite = val2; } } internal static void EnableTutorialRig() { RigManager rigManager = RigData.RigReferences.RigManager; if (!((Object)(object)rigManager).IsNOC()) { TutorialRig tutorialRig = rigManager.tutorialRig; HeadTitles headTitles = tutorialRig.headTitles; ((Component)tutorialRig).gameObject.SetActive(true); ((Component)headTitles).gameObject.SetActive(true); } } internal static bool IsPlayingNotification() { RigManager rigManager = RigData.RigReferences.RigManager; if (!((Object)(object)rigManager).IsNOC()) { return ((Component)rigManager.tutorialRig.headTitles.headFollower).gameObject.activeInHierarchy; } return false; } internal static void OnUpdate() { if (_queuedNotifications.Count > 0 && !FusionSceneManager.IsLoading() && RigData.HasPlayer) { if (!_hasEnabledTutorialRig) { EnableTutorialRig(); _hasEnabledTutorialRig = true; } else if (_queuedNotifications.Count > 0 && !IsPlayingNotification()) { DequeueNotification(); } } else { _hasEnabledTutorialRig = false; } } } internal static class NativeUtilities { internal unsafe static IntPtr GetNativePtr<T>(string name) { return *(IntPtr*)(void*)(IntPtr)typeof(T).GetField(name, AccessTools.all).GetValue(null); } internal static IntPtr GetDestPtr<TDelegate>(TDelegate destination) where TDelegate : Delegate { return destination.Method.MethodHandle.GetFunctionPointer(); } internal static TDelegate GetOriginal<TDelegate>(IntPtr nativePtr) { return Marshal.GetDelegateForFunctionPointer<TDelegate>(nativePtr); } } internal class PooleePusher { private readonly List<AssetPoolee> _list = new List<AssetPoolee>(); public void Push(AssetPoolee poolee) { if (!((IEnumerable<AssetPoolee>)_list).Has<AssetPoolee>(poolee)) { _list.Add(poolee); } } public bool Pull(AssetPoolee poolee) { for (int i = 0; i < _list.Count; i++) { if ((Object)(object)_list[i] == (Object)(object)poolee) { _list.RemoveAt(i); return true; } } return false; } public bool Contains(AssetPoolee poolee) { for (int i = 0; i < _list.Count; i++) { if ((Object)(object)_list[i] == (Object)(object)poolee) { return true; } } return false; } } internal static class SafeEvents { internal static void InvokeSafe<T>(this T action, string task) where T : Delegate { if ((Delegate?)action == (Delegate?)null) { return; } Delegate[] invocationList = action.GetInvocationList(); foreach (Delegate @delegate in invocationList) { try { @delegate.DynamicInvoke(); } catch (Exception e) { FusionLogger.LogException(task, e); } } } internal static void InvokeSafe<T, T1>(this T action, T1 param, string task) where T : Delegate { if ((Delegate?)action == (Delegate?)null) { return; } Delegate[] invocationList = action.GetInvocationList(); foreach (Delegate @delegate in invocationList) { try { @delegate.DynamicInvoke(param); } catch (Exception e) { FusionLogger.LogException(task, e); } } } internal static void InvokeSafe<T, T1, T2>(this T action, T1 param1, T2 param2, string task) where T : Delegate { if ((Delegate?)action == (Delegate?)null) { return; } Delegate[] invocationList = action.GetInvocationList(); foreach (Delegate @delegate in invocationList) { try { @delegate.DynamicInvoke(param1, param2); } catch (Exception e) { FusionLogger.LogException(task, e); } } } internal static void InvokeSafe<T, T1, T2, T3>(this T action, T1 param1, T2 param2, T3 param3, string task) where T : Delegate { if ((Delegate?)action == (Delegate?)null) { return; } Delegate[] invocationList = action.GetInvocationList(); foreach (Delegate @delegate in invocationList) { try { @delegate.DynamicInvoke(param1, param2, param3); } catch (Exception e) { FusionLogger.LogException(task, e); } } } } public delegate bool UserAccessEvent(PlayerId playerId, out string reason); public delegate void ServerEvent(); public delegate void UpdateEvent(); public delegate void PlayerUpdate(PlayerId playerId); public delegate void PlayerAction(PlayerId playerId, PlayerActionType type, PlayerId otherPlayer = null); public delegate void RigManagerEvent(RigManager rig); public delegate void CatchupAction(ulong longId); public delegate void LobbyMenuAction(MenuCategory category, INetworkLobby lobby); public static class MultiplayerHooking { public static event UserAccessEvent OnShouldAllowConnection; public static event ServerEvent OnStartServer; public static event ServerEvent OnJoinServer; public static event ServerEvent OnDisconnect; public static event PlayerUpdate OnPlayerJoin; public static event PlayerUpdate OnPlayerLeave; public static event PlayerAction OnPlayerAction; public static event CatchupAction OnPlayerCatchup; public static event LobbyMenuAction OnLobbyCategoryCreated; public static event RigManagerEvent OnLocalPlayerCreated; public static event RigManagerEvent OnPlayerRepCreated; public static event ServerEvent OnServerSettingsChanged; public static event UpdateEvent OnUpdate; public static event UpdateEvent OnFixedUpdate; public static event UpdateEvent OnLateUpdate; public static event UpdateEvent OnMainSceneInitialized; public static event UpdateEvent OnLoadingBegin; internal static bool Internal_OnShouldAllowConnection(PlayerId playerId, out string reason) { reason = ""; if (MultiplayerHooking.OnShouldAllowConnection == null) { return true; } Delegate[] invocationList = MultiplayerHooking.OnShouldAllowConnection.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { if (!((UserAccessEvent)invocationList[i])(playerId, out reason)) { return false; } } return true; } internal static void Internal_OnStartServer() { MultiplayerHooking.OnStartServer.InvokeSafe("executing OnStartServer hook"); } internal static void Internal_OnJoinServer() { MultiplayerHooking.OnJoinServer.InvokeSafe("executing OnJoinServer hook"); } internal static void Internal_OnDisconnect() { MultiplayerHooking.OnDisconnect.InvokeSafe("executing OnDisconnect hook"); } internal static void Internal_OnPlayerJoin(PlayerId id) { MultiplayerHooking.OnPlayerJoin.InvokeSafe(id, "executing OnPlayerJoin hook"); } internal static void Internal_OnPlayerLeave(PlayerId id) { MultiplayerHooking.OnPlayerLeave.InvokeSafe(id, "executing OnPlayerLeave hook"); } internal static void Internal_OnPlayerAction(PlayerId id, PlayerActionType type, PlayerId otherPlayer = null) { MultiplayerHooking.OnPlayerAction.InvokeSafe(id, type, otherPlayer, "executing OnPlayerAction hook"); } internal static void Internal_OnPlayerCatchup(ulong longId) { MultiplayerHooking.OnPlayerCatchup.InvokeSafe(longId, "executing OnPlayerCatchup hook"); } internal static void Internal_OnLobbyCategoryCreated(MenuCategory category, INetworkLobby lobby) { MultiplayerHooking.OnLobbyCategoryCreated.InvokeSafe<LobbyMenuAction, MenuCategory, INetworkLobby>(category, lobby, "executing OnLobbyCategoryCreated"); } internal static void Internal_OnLocalPlayerCreated(RigManager rig) { MultiplayerHooking.OnLocalPlayerCreated.InvokeSafe<RigManagerEvent, RigManager>(rig, "executing OnLocalPlayerCreated hook"); } internal static void Internal_OnPlayerRepCreated(RigManager rig) { MultiplayerHooking.OnPlayerRepCreated.InvokeSafe<RigManagerEvent, RigManager>(rig, "executing OnPlayerRepCreated hook"); } internal static void Internal_OnServerSettingsChanged() { MultiplayerHooking.OnServerSettingsChanged.InvokeSafe("executing server settings changed hook"); } internal static void Internal_OnUpdate() { MultiplayerHooking.OnUpdate.InvokeSafe("executing OnUpdate hook"); } internal static void Internal_OnFixedUpdate() { MultiplayerHooking.OnFixedUpdate.InvokeSafe("executing OnFixedUpdate hook"); } internal static void Internal_OnLateUpdate() { MultiplayerHooking.OnLateUpdate.InvokeSafe("executing OnLateUpdate hook"); } internal static void Internal_OnMainSceneInitialized() { MultiplayerHooking.OnMainSceneInitialized.InvokeSafe("executing OnMainSceneInitialized hook"); } internal static void Internal_OnLoadingBegin() { MultiplayerHooking.OnLoadingBegin.InvokeSafe("executing OnLoadingBegin hook"); } } internal static class BigEndianHelper { internal static void WriteBytes(byte[] destination, int offset, short value) { destination[offset] = (byte)(value >> 8); destination[offset + 1] = (byte)value; } internal static void WriteBytes(byte[] destination, int offset, ushort value) { destination[offset] = (byte)(value >> 8); destination[offset + 1] = (byte)value; } internal static void WriteBytes(byte[] destination, int offset, int value) { destination[offset] = (byte)(value >> 24); destination[offset + 1] = (byte)(value >> 16); destination[offset + 2] = (byte)(value >> 8); destination[offset + 3] = (byte)value; } internal static void WriteBytes(byte[] destination, int offset, uint value) { destination[offset] = (byte)(value >> 24); destination[offset + 1] = (byte)(value >> 16); destination[offset + 2] = (byte)(value >> 8); destination[offset + 3] = (byte)value; } internal static void WriteBytes(byte[] destination, int offset, long value) { destination[offset] = (byte)(value >> 56); destination[offset + 1] = (byte)(value >> 48); destination[offset + 2] = (byte)(value >> 40); destination[offset + 3] = (byte)(value >> 32); destination[offset + 4] = (byte)(value >> 24); destination[offset + 5] = (byte)(value >> 16); destination[offset + 6] = (byte)(value >> 8); destination[offset + 7] = (byte)value; } internal static void WriteBytes(byte[] destination, int offset, ulong value) { destination[offset] = (byte)(value >> 56); destination[offset + 1] = (byte)(value >> 48); destination[offset + 2] = (byte)(value >> 40); destination[offset + 3] = (byte)(value >> 32); destination[offset + 4] = (byte)(value >> 24); destination[offset + 5] = (byte)(value >> 16); destination[offset + 6] = (byte)(value >> 8); destination[offset + 7] = (byte)value; } internal unsafe static void WriteBytes(byte[] destination, int offset, float value) { uint value2 = *(uint*)(&value); WriteBytes(destination, offset, value2); } internal unsafe static void WriteBytes(byte[] destination, int offset, double value) { ulong value2 = *(ulong*)(&value); WriteBytes(destination, offset, value2); } internal static short ReadInt16(byte[] source, int offset) { return (short)((source[offset] << 8) | source[offset + 1]); } internal static ushort ReadUInt16(byte[] source, int offset) { return (ushort)((source[offset] << 8) | source[offset + 1]); } internal static int ReadInt32(byte[] source, int offset) { return (source[offset] << 24) | (source[offset + 1] << 16) | (source[offset + 2] << 8) | source[offset + 3]; } internal static uint ReadUInt32(byte[] source, int offset) { return (uint)((source[offset] << 24) | (source[offset + 1] << 16) | (source[offset + 2] << 8) | source[offset + 3]); } internal static long ReadInt64(byte[] source, int offset) { return (long)(((ulong)source[offset] << 56) | ((ulong)source[offset + 1] << 48) | ((ulong)source[offset + 2] << 40) | ((ulong)source[offset + 3] << 32) | ((ulong)source[offset + 4] << 24) | ((ulong)source[offset + 5] << 16) | ((ulong)source[offset + 6] << 8) | source[offset + 7]); } internal static ulong ReadUInt64(byte[] source, int offset) { return ((ulong)source[offset] << 56) | ((ulong)source[offset + 1] << 48) | ((ulong)source[offset + 2] << 40) | ((ulong)source[offset + 3] << 32) | ((ulong)source[offset + 4] << 24) | ((ulong)source[offset + 5] << 16) | ((ulong)source[offset + 6] << 8) | source[offset + 7]; } internal unsafe static float ReadSingle(byte[] source, int offset) { uint num = ReadUInt32(source, offset); return *(float*)(&num); } internal unsafe static double ReadDouble(byte[] source, int offset) { ulong num = ReadUInt64(source, offset); return *(double*)(&num); } internal static ushort SwapBytes(ushort value) { return (ushort)(((value & 0xFF) << 8) | ((value & 0xFF00) >> 8)); } internal static uint SwapBytes(uint value) { return ((value & 0xFF) << 24) | ((value & 0xFF00) << 8) | ((value & 0xFF0000) >> 8) | ((value & 0xFF000000u) >> 24); } internal static ulong SwapBytes(ulong value) { return ((value & 0xFF) << 56) | ((value & 0xFF00) << 40) | ((value & 0xFF0000) << 24) | ((value & 0xFF000000u) << 8) | ((value & 0xFF00000000L) >> 8) | ((value & 0xFF0000000000L) >> 24) | ((value & 0xFF000000000000L) >> 40) | ((value & 0xFF00000000000000uL) >> 56); } } internal static class FusionLogger { internal static void LogLine([CallerLineNumber] int lineNumber = 0) { Log($"FusionLogger.LogLine is only for debugging! Please remove from line {lineNumber}", ConsoleColor.Red); } internal static void Log(string txt, ConsoleColor txt_color = ConsoleColor.White) { ((MelonBase)FusionMod.Instance).LoggerInstance.Msg(txt_color, txt); } internal static void Log(object obj, ConsoleColor txt_color = ConsoleColor.White) { ((MelonBase)FusionMod.Instance).LoggerInstance.Msg(txt_color, obj); } internal static void Warn(string txt) { ((MelonBase)FusionMod.Instance).LoggerInstance.Warning(txt); } internal static void Warn(object obj) { ((MelonBase)FusionMod.Instance).LoggerInstance.Warning(obj); } internal static void Error(string txt) { ((MelonBase)FusionMod.Instance).LoggerInstance.Error(txt); } internal static void ErrorLine(string txt, [CallerLineNumber] int lineNumber = 0) { ((MelonBase)FusionMod.Instance).LoggerInstance.Error($"{txt} - Line: {lineNumber}"); } internal static void Error(object obj) { ((MelonBase)FusionMod.Instance).LoggerInstance.Error(obj); } internal static void LogException(string task, Exception e) { if (e.InnerException != null) { e = e.InnerException; } Error("Failed " + task + " with reason: " + e.Message + "\nTrace:" + e.StackTrace); } } internal static class PersistentAssetCreator { private const string _targetFont = "arlon-medium"; private static Action<AudioMixerGroup> _onMusicMixerLoaded; private static Action<AudioMixerGroup> _onSFXMixerLoaded; private static Action<HandPose> _onSoftGrabLoaded; internal static SurfaceData BloodSurfaceData { get; private set; } internal static TMP_FontAsset Font { get; private set; } internal static HandPose SoftGrabPose { get; private set; } internal static AudioMixerGroup MusicMixer { get; private set; } internal static AudioMixerGroup SFXMixer { get; private set; } internal static void OnLateInitializeMelon() { CreateSurfaceData(); CreateTextFont(); } internal static void OnMainSceneInitialized() { GetAllMixers(); GetHandPose(); } private static void GetAllMixers() { if ((Object)(object)SFXMixer != (Object)null && (Object)(object)MusicMixer != (Object)null) { return; } AudioMixerGroup[] array = Il2CppArrayBase<AudioMixerGroup>.op_Implicit(Resources.FindObjectsOfTypeAll<AudioMixerGroup>()); foreach (AudioMixerGroup val in array) { string name = ((Object)val).name; if (!(name == "Music")) { if (name == "SFX") { SFXMixer = val; } } else { MusicMixer = val; } } if ((Object)(object)MusicMixer != (Object)null) { _onMusicMixerLoaded?.Invoke(MusicMixer); } if ((Object)(object)SFXMixer != (Object)null) { _onSFXMixerLoaded?.Invoke(SFXMixer); } _onMusicMixerLoaded = null; _onSFXMixerLoaded = null; } private static void GetHandPose() { SoftGrabPose = RigData.RigReferences.RigManager.worldGripHandPose; if ((Object)(object)SoftGrabPose != (Object)null) { _onSoftGrabLoaded?.Invoke(SoftGrabPose); } _onSoftGrabLoaded = null; } public static void HookOnMusicMixerLoaded(Action<AudioMixerGroup> action) { if ((Object)(object)MusicMixer != (Object)null) { action?.Invoke(MusicMixer); } else { _onMusicMixerLoaded = (Action<AudioMixerGroup>)Delegate.Combine(_onMusicMixerLoaded, action); } } public static void HookOnSFXMixerLoaded(Action<AudioMixerGroup> action) { if ((Object)(object)SFXMixer != (Object)null) { action?.Invoke(SFXMixer); } else { _onSFXMixerLoaded = (Action<AudioMixerGroup>)Delegate.Combine(_onSFXMixerLoaded, action); } } public static void HookOnSoftGrabLoaded(Action<HandPose> action) { if ((Object)(object)SoftGrabPose != (Object)null) { action?.Invoke(SoftGrabPose); } else { _onSoftGrabLoaded = (Action<HandPose>)Delegate.Combine(_onSoftGrabLoaded, action); } } private static void CreateTextFont() { Il2CppArrayBase<TMP_FontAsset> val = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); foreach (TMP_FontAsset item in val) { if (((Object)item).name.ToLower().Contains("arlon-medium")) { Font = item; break; } } if ((Object)(object)Font == (Object)null) { Font = val[0]; } } private static void CreateSurfaceData() { //IL_006a: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown BloodSurfaceData = ScriptableObject.CreateInstance<SurfaceData>(); ((Object)BloodSurfaceData).name = "Fusion Blood Surface"; BloodSurfaceData.PenetrationResistance = 0.59f; BloodSurfaceData.megaPascal = 4f; BloodSurfaceData.isFlammable = false; BloodSurfaceData.fireResistance = 0f; BloodSurfaceData.ParicleColorTint = new Color(0.1686275f, 0.003372546f, 0.003372546f, 1f); PhysicMaterial physicMaterial = new PhysicMaterial("Fusion Physic Material") { dynamicFriction = 0.45f, staticFriction = 0.63f, bounciness = 0.35f, frictionCombine = (PhysicMaterialCombine)1, bounceCombine = (PhysicMaterialCombine)1 }; BloodSurfaceData.physicMaterial = physicMaterial; } internal static void SetupImpactProperties(RigManager rig) { PhysicsRig physicsRig = rig.physicsRig; Il2CppArrayBase<Rigidbody> componentsInChildren = ((Component)physicsRig).GetComponentsInChildren<Rigidbody>(true); for (int i = 0; i < componentsInChildren.Length; i++) { GameObject gameObject = ((Component)componentsInChildren[i]).gameObject; if (!((Object)(object)gameObject == (Object)(object)physicsRig.knee) && !((Object)(object)gameObject == (Object)(object)physicsRig.feet)) { if (i == 0) { ImpactPropertiesManager obj = gameObject.AddComponent<ImpactPropertiesManager>(); ((ImpactPropertiesVariables)obj).surfaceData = BloodSurfaceData; ((ImpactPropertiesVariables)obj).DecalMeshObj = null; ((ImpactPropertiesVariables)obj).decalType = (DecalType)2; } ImpactProperties obj2 = gameObject.AddComponent<ImpactProperties>(); ((ImpactPropertiesVariables)obj2).surfaceData = BloodSurfaceData; ((ImpactPropertiesVariables)obj2).DecalMeshObj = null; ((ImpactPropertiesVariables)obj2).decalType = (DecalType)2; } } } } internal static class PhysicsUtilities { internal static bool CanModifyGravity; public static Vector3 Gravity; internal static void OnCacheValues() { //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) Gravity = Physics.gravity; } internal static void OnUpdateTimescale() { //IL_0071: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) if (!NetworkInfo.HasServer) { return; } TimeScaleMode timeScaleMode = FusionPreferences.TimeScaleMode; RigReferenceCollection rigReferences = RigData.RigReferences; RigManager rigManager = rigReferences.RigManager; switch (timeScaleMode) { case TimeScaleMode.DISABLED: Time.timeScale = 1f; break; case TimeScaleMode.LOW_GRAVITY: { Time.timeScale = 1f; if (!RigData.HasPlayer) { break; } Control_GlobalTime globalTimeControl = rigManager.openControllerRig.globalTimeControl; if (globalTimeControl.cur_intensity <= 0f) { break; } float num = 1f - 1f / globalTimeControl.cur_intensity; Vector3 val = -Gravity * num; if (rigReferences.RigRigidbodies == null) { rigReferences.GetRigidbodies(); } Rigidbody[] rigRigidbodies = rigReferences.RigRigidbodies; foreach (Rigidbody val2 in rigRigidbodies) { if (!((Object)(object)val2 == (Object)null) && val2.useGravity) { val2.AddForce(val, (ForceMode)5); } } break; } } } internal static void OnSendPhysicsInformation() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (Time.frameCount % 40 != 0 || !NetworkInfo.IsServer) { return; } using FusionWriter fusionWriter = FusionWriter.Create(12); using WorldGravityMessageData value = WorldGravityMessageData.Create(Gravity); fusionWriter.Write(value); using LabFusion.Network.FusionMessage message = LabFusion.Network.FusionMessage.Create(NativeMessageTag.WorldGravity, fusionWriter); MessageSender.BroadcastMessageExceptSelf(NetworkChannel.Unreliable, message); } } internal static class StaticGripFixer { internal static void OnMainSceneInitialized() { foreach (AmmoDispenser item in Object.FindObjectsOfType<AmmoDispenser>()) { ((Component)item).gameObject.AddComponent<InteractableHost>(); } } } public static class MuteUIHelper { private static PageItem _mutePage; private static GameObject _muteIcon; private static Renderer _muteRenderer; private static Camera _muteCamera; public static void OnInitializeMelon() { FusionPref<bool> muted = FusionPreferences.ClientSettings.Muted; muted.OnValueChanged = (Action<bool>)Delegate.Combine(muted.OnValueChanged, new Action<bool>(OnMutedChanged)); FusionPref<bool> mutedIndicator = FusionPreferences.ClientSettings.MutedIndicator; mutedIndicator.OnValueChanged = (Action<bool>)Delegate.Combine(mutedIndicator.OnValueChanged, new Action<bool>(OnIndicatorChanged)); RenderPipelineManager.beginCameraRendering += Action<ScriptableRenderContext, Camera>.op_Implicit((Action<ScriptableRenderContext, Camera>)OnBeginCameraRendering); RenderPipelineManager.endCameraRendering += Action<ScriptableRenderContext, Camera>.op_Implicit((Action<ScriptableRenderContext, Camera>)OnEndCameraRendering); } public static void OnDeinitializeMelon() { FusionPref<bool> muted = FusionPreferences.ClientSettings.Muted; muted.OnValueChanged = (Action<bool>)Delegate.Remove(muted.OnValueChanged, new Action<bool>(OnMutedChanged)); FusionPref<bool> mutedIndicator = FusionPreferences.ClientSettings.MutedIndicator; mutedIndicator.OnValueChanged = (Action<bool>)Delegate.Remove(mutedIndicator.OnValueChanged, new Action<bool>(OnIndicatorChanged)); RenderPipelineManager.beginCameraRendering -= Action<ScriptableRenderContext, Camera>.op_Implicit((Action<ScriptableRenderContext, Camera>)OnBeginCameraRendering); RenderPipelineManager.endCameraRendering -= Action<ScriptableRenderContext, Camera>.op_Implicit((Action<ScriptableRenderContext, Camera>)OnEndCameraRendering); } private static void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) { if ((Object)(object)camera == (Object)(object)_muteCamera && (Object)(object)_muteRenderer != (Object)null) { _muteRenderer.enabled = true; } } private static void OnEndCameraRendering(ScriptableRenderContext context, Camera camera) { if ((Object)(object)camera == (Object)(object)_muteCamera && (Object)(object)_muteRenderer != (Object)null) { _muteRenderer.enabled = false; } } private static void OnMutedChanged(bool value) { if (_mutePage != null) { _mutePage.name = (value ? "Quick Unmute" : "Quick Mute"); } UpdateMuteIcon(); } private static void OnIndicatorChanged(bool value) { UpdateMuteIcon(); } private static void UpdateMuteIcon() { if ((Object)(object)_muteIcon != (Object)null) { _muteIcon.SetActive(VoiceHelper.ShowIndicator); } } public static void OnCreateMuteUI(RigManager manager) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown if (VoiceHelper.CanTalk) { PopUpMenuView popUpMenu = manager.uiRig.popUpMenu; Page homePage = popUpMenu.radialPageView.m_HomePage; FusionPref<bool> mutedPref = FusionPreferences.ClientSettings.Muted; _mutePage = new PageItem(mutedPref.GetValue() ? "Quick Unmute" : "Quick Mute", (Directions)3, Action.op_Implicit((Action)delegate { mutedPref.SetValue(!mutedPref.GetValue()); popUpMenu.Deactivate(); FusionNotifier.Send(new FusionNotification { isPopup = true, isMenuItem = false, message = (mutedPref.GetValue() ? "Muted" : "Unmuted") }); })); homePage.items.Add(_mutePage); Transform head = ((Rig)manager.openControllerRig).m_head; _muteIcon = Object.Instantiate<GameObject>(FusionContentLoader.MutePopupPrefab, head); ((Object)_muteIcon).name = "Mute Icon [FUSION]"; _muteRenderer = _muteIcon.GetComponentInChildren<Renderer>(); _muteRenderer.enabled = false; _muteCamera = _muteIcon.GetComponent<Camera>(); ((Component)head).GetComponent<UniversalAdditionalCameraData>().cameraStack.Add(_muteCamera); _muteIcon.SetActive(VoiceHelper.ShowIndicator); } } public static void OnDestroyMuteUI(RigManager manager) { if (_mutePage != null) { PopUpMenuView popUpMenu = manager.uiRig.popUpMenu; Page homePage = popUpMenu.radialPageView.m_HomePage; homePage.items.RemoveAll(Predicate<PageItem>.op_Implicit((Func<PageItem, bool>)((PageItem i) => i.name == _mutePage.name))); popUpMenu.radialPageView.Render(homePage); _mutePage = null; } if (!((Object)(object)_muteIcon).IsNOC()) { Object.Destroy((Object)(object)_muteIcon); _muteIcon = null; } } } public static class LaserCursorUtilities { public static LaserCursor CreateLaserCursor(Action<LaserCursor> onSetupRegions = null) { //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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown GameObject obj = Object.Instantiate<GameObject>(FusionContentLoader.LaserCursor); Transform transform = obj.transform; obj.SetActive(false); LaserCursor val = obj.AddComponent<LaserCursor>(); PageElementView val2 = transform.Find("Arrow").SetupPageElementView(); PageElementView val3 = transform.Find("ray_start").SetupPageElementView(); PageElementView val4 = transform.Find("ray_mid").SetupPageElementView(); PageElementView val5 = transform.Find("ray_mid2").SetupPageElementView(); PageElementView val6 = transform.Find("ray_bez").SetupPageElementView(); PageElementView val7 = transform.Find("ray_end").SetupPageElementView(); PageElementView rayPulse = transform.Find("ray_pulse").SetupPageElementView(); PageElementView val8 = transform.Find("SFX").SetupPageElementView(); AnimationCurve blipCurve = (val5.blipCurve = (val4.blipCurve = (val3.blipCurve = new AnimationCurve(Il2CppStructArray<Keyframe>.op_Implicit((Keyframe[])(object)new Keyframe[4] { new Keyframe(0f, 1f), new Keyframe(0.1271991f, 1.953225f), new Keyframe(0.724905f, 0.9818711f), new Keyframe(1f, 1f) }))))); val7.blipCurve = blipCurve; DrawBezierCurve val12 = ((Component)val2).gameObject.AddComponent<DrawBezierCurve>(); val12.Point1 = ((Component)val7).gameObject; val12.Point2 = ((Component)val6).gameObject; val12.Point3 = ((Component)val4).gameObject; val12.Point4 = ((Component)val3).gameObject; val12.lineSteps = 12; val12.linePercentageFill = 0.73f; PrismaticSFX val13 = ((Component)val8).gameObject.AddComponent<PrismaticSFX>(); val13.velocityTran = ((Component)val8).transform; val13.sourceTran = ((Component)val8).transform; val13.minSpeed = 0.2f; val13.maxSpeed = 4f; val13.sourceMinDistance = 1f; val13.pitchMod = 1f; val13.enableModulatedAudio = true; val13.loopClips = true; val13.modulatedClips = Il2CppReferenceArray<AudioClip>.op_Implicit((AudioClip[])(object)new AudioClip[1] { FusionContentLoader.LaserPrismaticSFX }); val13.SpatialBlend = 0.98f; val.cursorStart = val3; val.cursorEnd = val7; val.cursorMid = val4; val.cursorMid2 = val5; val.cursorBez = val6; val.rayPulse = rayPulse; val.lineEnd = val2; val.cursorLine = ((Component)val2).GetComponent<LineRenderer>(); val.bezCurve = val12; val.pulseLength = 0.2f; val.pulseAceleration = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); val.pulseSound = Il2CppReferenceArray<AudioClip>.op_Implicit((AudioClip[])(object)new AudioClip[1] { FusionContentLoader.LaserPulseSound }); val.raySpawn = Il2CppReferenceArray<AudioClip>.op_Implicit((AudioClip[])(object)new AudioClip[1] { FusionContentLoader.LaserRaySpawn }); val.rayDespawn = Il2CppReferenceArray<AudioClip>.op