Decompiled source of Fusion v1.8.0
Mods/LabFusion.dll
Decompiled 3 months 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.Http; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.X86; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; 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 FusionHelper.Network; using HarmonyLib; using Il2Cpp; using Il2CppCysharp.Threading.Tasks; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.Attributes; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppInterop.Runtime.InteropTypes.Fields; using Il2CppSLZ.Bonelab; using Il2CppSLZ.Data; using Il2CppSLZ.Interaction; using Il2CppSLZ.Marrow; using Il2CppSLZ.Marrow.AI; using Il2CppSLZ.Marrow.Audio; using Il2CppSLZ.Marrow.Combat; using Il2CppSLZ.Marrow.Data; using Il2CppSLZ.Marrow.Forklift; using Il2CppSLZ.Marrow.Forklift.Model; using Il2CppSLZ.Marrow.Input; using Il2CppSLZ.Marrow.Interaction; using Il2CppSLZ.Marrow.Pool; using Il2CppSLZ.Marrow.PuppetMasta; using Il2CppSLZ.Marrow.SceneStreaming; using Il2CppSLZ.Marrow.Utilities; using Il2CppSLZ.Marrow.VFX; using Il2CppSLZ.Marrow.VoidLogic; using Il2CppSLZ.Marrow.Warehouse; using Il2CppSLZ.Marrow.Zones; using Il2CppSLZ.Props; using Il2CppSLZ.UI; using Il2CppSLZ.VRMK; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppTMPro; using Il2CppUltEvents; using LabFusion; using LabFusion.BoneMenu; using LabFusion.Data; using LabFusion.Downloading; using LabFusion.Downloading.ModIO; using LabFusion.Entities; using LabFusion.Exceptions; using LabFusion.Extensions; using LabFusion.Grabbables; using LabFusion.Marrow; using LabFusion.Marrow.Integration; using LabFusion.Marrow.Zones; using LabFusion.MonoBehaviours; using LabFusion.Network; using LabFusion.Patching; using LabFusion.Player; using LabFusion.Preferences; using LabFusion.Preferences.Client; using LabFusion.RPC; using LabFusion.Representation; using LabFusion.SDK.Achievements; using LabFusion.SDK.Cosmetics; using LabFusion.SDK.Gamemodes; using LabFusion.SDK.Lobbies; using LabFusion.SDK.Metadata; using LabFusion.SDK.Modules; using LabFusion.SDK.Points; using LabFusion.SDK.Triggers; using LabFusion.Scene; using LabFusion.Senders; using LabFusion.Syncables; using LabFusion.UI; using LabFusion.Utilities; using LabFusion.Voice; using LabFusion.Voice.Unity; using LabFusion.XML; using LiteNetLib; using LiteNetLib.Layers; using LiteNetLib.Utils; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using Newtonsoft.Json.Linq; using Steamworks; using Steamworks.Data; using Steamworks.Ugc; using UnityEngine; using UnityEngine.Audio; using UnityEngine.EventSystems; using UnityEngine.Events; 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.8.0")] [assembly: MelonInfo(typeof(FusionMod), "LabFusion", "1.8.0", "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(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.8.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace FusionHelper.Network { internal enum MessageTypes { SteamID = 0, OnDisconnected = 1, OnMessage = 2, GetUsername = 3, UnreliableBroadcastToClients = 4, ReliableBroadcastToClients = 5, UnreliableBroadcastToServer = 6, ReliableBroadcastToServer = 7, OnConnectionDisconnected = 8, OnConnectionMessage = 9, JoinServer = 10, Disconnect = 11, Ping = 12, StartServer = 13, UnreliableSendFromServer = 14, ReliableSendFromServer = 15, LobbyIds = 16, LobbyMetadata = 17, UpdateConnectPresence = 18, SetLobbyMetadata = 20, SteamFriends = 21 } } namespace LabFusion { [StructLayout(LayoutKind.Sequential, Size = 1)] public struct FusionVersion { public const byte VersionMajor = 1; public const byte VersionMinor = 8; public const short VersionPatch = 0; public const string VersionString = "1.8.0"; } public class FusionMod : MelonMod { public const string ModName = "LabFusion"; public const string ModAuthor = "Lakatrazz"; public const string GameDeveloper = "Stress Level Zero"; public const string GameName = "BONELAB"; public static readonly Version Version = new Version(1, 8, 0); private static bool _hasAutoUpdater = false; private static int _nextSyncableSendRate = 1; private static bool _initializedBoneMenu = 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 = ((MelonBase)this).MelonAssembly.Assembly; ModDownloadManager.DeleteTemporaryDirectories(); PersistentData.OnPathInitialize(); SteamAPILoader.OnLoadSteamAPI(); ByteRetriever.PopulateInitial(); PDController.OnInitializeMelon(); ModuleHandler.Internal_HookAssemblies(); GamemodeRegistration.Internal_HookAssemblies(); PointItemManager.HookEvents(); VoteKickHelper.Internal_OnInitializeMelon(); } public override void OnInitializeMelon() { BoneMenuCreator.OnPrepareMainPage(); FusionFileLoader.OnInitializeMelon(); FusionBundleLoader.OnBundleLoad(); LevelDataHandler.OnInitializeMelon(); FusionMessageHandler.RegisterHandlersFromAssembly(FusionAssembly); GrabGroupHandler.RegisterHandlersFromAssembly(FusionAssembly); NetworkLayer.RegisterLayersFromAssembly(FusionAssembly); GamemodeRegistration.LoadGamemodes(FusionAssembly); PointItemManager.LoadItems(FusionAssembly); AchievementManager.LoadAchievements(FusionAssembly); EntityComponentManager.RegisterComponentsFromAssembly(FusionAssembly); LobbyFilterManager.LoadBuiltInFilters(); NetworkEntityManager.OnInitializeManager(); NetworkPlayerManager.OnInitializeManager(); FusionPopupManager.OnInitializeMelon(); AssetWarehouse.OnReady(Action.op_Implicit((Action)delegate { CosmeticLoader.OnAssetWarehouseReady(); ScannableEvents.OnAssetWarehouseReady(); })); FusionPreferences.OnInitializePreferences(); FusionSceneManager.Internal_OnInitializeMelon(); OnInitializeNetworking(); } public override void OnLateInitializeMelon() { InternalLayerHelpers.OnLateInitializeLayer(); PersistentAssetCreator.OnLateInitializeMelon(); PlayerAdditionsHelper.OnInitializeMelon(); _hasAutoUpdater = MelonTypeBase<MelonPlugin>.RegisteredMelons.Any((MelonPlugin p) => ((MelonBase)p).Info.Name.Contains("LabFusion Updater")); if (!_hasAutoUpdater && !PlatformHelper.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 static 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.UnhookEvents(); FusionBundleLoader.OnBundleUnloaded(); PlayerAdditionsHelper.OnDeinitializeMelon(); SteamAPILoader.OnFreeSteamAPI(); } public override void OnPreferencesLoaded() { FusionPreferences.OnPreferencesLoaded(); } public static void OnMainSceneInitialized() { if (!_initializedBoneMenu) { BoneMenuCreator.OnPopulateMainPage(); _initializedBoneMenu = true; } _ = ((Scannable)FusionSceneManager.Level).Title; NetworkEntityManager.OnCleanupIds(); RigData.OnCacheRigInfo(); PersistentAssetCreator.OnMainSceneInitialized(); ConstrainerUtilities.OnMainSceneInitialized(); MultiplayerHooking.Internal_OnMainSceneInitialized(); FusionPlayer.OnMainSceneInitialized(); if (NetworkInfo.IsServer && Gamemode.ActiveGamemode != null && Gamemode.ActiveGamemode.AutoStopOnSceneLoad) { Gamemode.ActiveGamemode.StopGamemode(); } } public static void OnMainSceneInitializeDelayed() { if (RigData.HasPlayer) { ((Il2CppObjectBase)RigData.Refs.RigManager.ControllerRig).TryCast<OpenControllerRig>().quickmenuEnabled = true; PlayerRefs.Instance.PlayerBodyVitals.quickmenuEnabled = true; } } public override void OnUpdate() { NetworkInfo.BytesDown = 0; NetworkInfo.BytesUp = 0; ModIODownloader.UpdateQueue(); TimeUtilities.OnEarlyUpdate(); FusionSceneManager.Internal_UpdateScene(); FusionPopupManager.OnUpdate(); float deltaTime = TimeUtilities.DeltaTime; NetworkPlayerManager.OnUpdate(deltaTime); if (TimeUtilities.IsMatchingFrame(_nextSyncableSendRate)) { int bytesUp = NetworkInfo.BytesUp; NetworkEntityManager.OnUpdate(deltaTime); _nextSyncableSendRate = SendRateTable.GetObjectSendRate(NetworkInfo.BytesUp - bytesUp); } FusionPlayer.OnUpdate(); VoiceHelper.OnVoiceChatUpdate(); InternalLayerHelpers.OnUpdateLayer(); MultiplayerHooking.Internal_OnUpdate(); GamemodeManager.Internal_OnUpdate(); DelayUtilities.Internal_OnUpdate(); } public override void OnFixedUpdate() { TimeUtilities.OnEarlyFixedUpdate(); PhysicsUtilities.OnUpdateTimescale(); PDController.OnFixedUpdate(); float fixedDeltaTime = TimeUtilities.FixedDeltaTime; NetworkPlayerManager.OnFixedUpdate(fixedDeltaTime); NetworkEntityManager.OnFixedUpdate(fixedDeltaTime); MultiplayerHooking.Internal_OnFixedUpdate(); GamemodeManager.Internal_OnFixedUpdate(); } public override void OnLateUpdate() { float deltaTime = TimeUtilities.DeltaTime; NetworkPlayerManager.OnLateUpdate(deltaTime); NetworkEntityManager.OnLateUpdate(deltaTime); InternalLayerHelpers.OnLateUpdateLayer(); MultiplayerHooking.Internal_OnLateUpdate(); GamemodeManager.Internal_OnLateUpdate(); } public override void OnGUI() { InternalLayerHelpers.OnGUILayer(); } } } namespace LabFusion.Voice { public interface IVoiceManager { List<IVoiceSpeaker> VoiceSpeakers { get; } bool CanTalk { get; } bool CanHear { get; } string[] InputDevices { get; } IVoiceSpeaker GetSpeaker(PlayerId id); void RemoveSpeaker(PlayerId id); IVoiceReceiver GetReceiver(); void Enable(); void Disable(); void UpdateManager(); void ClearManager(); } public abstract class VoiceManager : IVoiceManager { protected List<IVoiceSpeaker> _voiceSpeakers = new List<IVoiceSpeaker>(); private IVoiceReceiver _receiver; private bool _hasDisabledVoice = true; public List<IVoiceSpeaker> VoiceSpeakers => _voiceSpeakers; public virtual bool CanTalk => true; public virtual bool CanHear => true; public virtual string[] InputDevices => Array.Empty<string>(); public void Enable() { _receiver = OnCreateReceiverOrDefault(); _receiver?.Enable(); } public void Disable() { if (_receiver != null) { _receiver.Disable(); _receiver = null; } ClearManager(); } protected bool TryGetSpeaker(PlayerId id, out IVoiceSpeaker speaker) { speaker = null; for (int i = 0; i < VoiceSpeakers.Count; i++) { IVoiceSpeaker voiceSpeaker = VoiceSpeakers[i]; if (voiceSpeaker.ID == id) { speaker = voiceSpeaker; return true; } } return false; } protected abstract IVoiceSpeaker OnCreateSpeaker(PlayerId id); protected abstract IVoiceReceiver OnCreateReceiverOrDefault(); public IVoiceSpeaker GetSpeaker(PlayerId id) { if (TryGetSpeaker(id, out var speaker)) { return speaker; } IVoiceSpeaker voiceSpeaker = OnCreateSpeaker(id); VoiceSpeakers.Add(voiceSpeaker); return voiceSpeaker; } public IVoiceReceiver GetReceiver() { return _receiver; } public void UpdateManager() { UpdateSpeakers(); UpdateReceiver(); } private void UpdateSpeakers() { for (int i = 0; i < VoiceSpeakers.Count; i++) { VoiceSpeakers[i].Update(); } } private void UpdateReceiver() { if (_receiver != null && CanTalk) { if (NetworkInfo.HasServer && !VoiceInfo.IsMuted) { _receiver.UpdateVoice(enabled: true); _hasDisabledVoice = false; } else if (!_hasDisabledVoice) { _receiver.UpdateVoice(enabled: false); _hasDisabledVoice = true; } if (_receiver.HasVoiceActivity()) { PlayerSender.SendPlayerVoiceChat(_receiver.GetCompressedVoiceData()); } } } public void RemoveSpeaker(PlayerId id) { IVoiceSpeaker voiceSpeaker = null; foreach (IVoiceSpeaker voiceSpeaker2 in VoiceSpeakers) { if (voiceSpeaker2.ID == id) { voiceSpeaker = voiceSpeaker2; break; } } if (voiceSpeaker != null) { voiceSpeaker.Cleanup(); _voiceSpeakers.Remove(voiceSpeaker); } } public void ClearManager() { foreach (IVoiceSpeaker voiceSpeaker in VoiceSpeakers) { voiceSpeaker.Cleanup(); } _voiceSpeakers.Clear(); } } public interface IVoiceReceiver { float GetVoiceAmplitude(); bool HasVoiceActivity(); byte[] GetCompressedVoiceData(); void UpdateVoice(bool enabled); void Enable(); void Disable(); } public interface IVoiceSpeaker { PlayerId ID { get; } NetworkPlayer Player { get; } AudioSource Source { get; } bool IsDestroyed { get; } float Volume { get; set; } float GetVoiceAmplitude(); void CreateAudioSource(); void VerifyRep(); void OnVoiceDataReceived(byte[] data); void Cleanup(); void Update(); } public abstract class VoiceSpeaker : IVoiceSpeaker { protected PlayerId _id; protected NetworkPlayer _player; protected bool _hasPlayer; protected AudioSource _source; protected GameObject _sourceGo; protected bool _isDestroyed; protected float _volume = 1f; public PlayerId ID => _id; public NetworkPlayer Player => _player; public AudioSource Source => _source; public bool IsDestroyed => _isDestroyed; public float Volume { get { return _volume; } set { _volume = value; } } public bool MicrophoneDisabled { get { if (_hasPlayer) { return _player.MicrophoneDisabled; } return false; } } public virtual void CreateAudioSource() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown _sourceGo = new GameObject($"{ID.SmallId} Voice Source"); _source = _sourceGo.AddComponent<AudioSource>(); Object.DontDestroyOnLoad((Object)(object)_source); Object.DontDestroyOnLoad((Object)(object)_sourceGo); ((Object)_sourceGo).hideFlags = (HideFlags)32; _source.rolloffMode = (AudioRolloffMode)1; _source.loop = true; } public virtual void VerifyRep() { if (!_hasPlayer && ID != null && NetworkPlayerManager.TryGetPlayer((byte)ID, out _player)) { _player.InsertVoiceSource(this, Source); _hasPlayer = true; } } public virtual void Update() { } public virtual void Cleanup() { if ((Object)(object)_source != (Object)null) { if ((Object)(object)_source.clip != (Object)null) { Object.Destroy((Object)(object)_source.clip); } Object.Destroy((Object)(object)_sourceGo); } _isDestroyed = true; } public abstract void OnVoiceDataReceived(byte[] data); public abstract float GetVoiceAmplitude(); } public class JawFlapper { private float _voiceLoudness; private const float _sinAmplitude = 5f; private const float _sinOmega = 10f; public float GetAngle() { return _voiceLoudness * 20f; } public void ClearJaw() { _voiceLoudness = 0f; } public void UpdateJaw(float amplitude) { float num = amplitude; num *= 1000f; num = ManagedMathf.Clamp(num, 0f, 2f); float value = Math.Abs(5f * ManagedMathf.Sin(10f * TimeUtilities.TimeSinceStartup)); value = ManagedMathf.Clamp01(value); _voiceLoudness = ManagedMathf.LerpUnclamped(_voiceLoudness * value, num, TimeUtilities.DeltaTime * 12f); } } public static class VoiceCompressor { public static byte[] CompressVoiceData(byte[] data) { using MemoryStream memoryStream = new MemoryStream(); using DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress); deflateStream.Write(data, 0, data.Length); deflateStream.Close(); return memoryStream.ToArray(); } public static byte[] DecompressVoiceData(byte[] data) { using MemoryStream stream = new MemoryStream(data); using DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress); using MemoryStream memoryStream = new MemoryStream(); deflateStream.CopyTo(memoryStream); return memoryStream.ToArray(); } } public static class VoiceHelper { public static void OnVoiceChatUpdate() { VoiceInfo.VoiceManager?.UpdateManager(); } public static void OnVoiceDataReceived(PlayerId player, byte[] data) { if (!VoiceInfo.IsDeafened) { (VoiceInfo.VoiceManager?.GetSpeaker(player))?.OnVoiceDataReceived(data); } } } public static class VoiceInfo { public static IVoiceManager VoiceManager => NetworkInfo.CurrentNetworkLayer?.VoiceManager; public static bool CanTalk => (VoiceManager?.CanTalk).GetValueOrDefault(); public static bool CanHear => (VoiceManager?.CanHear).GetValueOrDefault(); public static string[] InputDevices { get { if (VoiceManager == null) { return Array.Empty<string>(); } return VoiceManager.InputDevices; } } public static bool ShowMuteIndicator { get { if (NetworkInfo.HasServer && ClientSettings.VoiceChat.Muted.Value) { return ClientSettings.VoiceChat.MutedIndicator.Value; } return false; } } public static float VoiceAmplitude => (VoiceManager?.GetReceiver()?.GetVoiceAmplitude()).GetValueOrDefault(); public static bool HasVoiceActivity => (VoiceManager?.GetReceiver()?.HasVoiceActivity()).GetValueOrDefault(); public static bool IsMuted { get { bool flag = false; if (RigData.HasPlayer) { flag = ((Health)RigData.Refs.Health).deathIsImminent; } if (!(ClientSettings.VoiceChat.Muted.Value || flag)) { return IsDeafened; } return true; } } public static bool IsDeafened { get { if (!ClientSettings.VoiceChat.Deafened.Value) { return !ServerVoiceEnabled; } return true; } } public static bool ServerVoiceEnabled => ServerSettingsManager.ActiveSettings.VoiceChatEnabled.Value; } public static class VoiceVolume { public const float DefaultSampleMultiplier = 10f; public const float MinimumVoiceVolume = 0.3f; public const float SilencingVolume = 0.1f; public const float TalkTimeoutTime = 1f; public static float GetGlobalVolumeMultiplier() { float num = ClientSettings.VoiceChat.GlobalVolume.Value; if (FusionSceneManager.IsLoading()) { num *= 0.25f; } return num; } } } namespace LabFusion.Voice.Unity { public static class UnityVoice { public const int SampleRate = 16000; public const int ClipLength = 1; private static bool _hasMicrophones; private static bool _checkedForMic; private static bool CheckForMicrophone() { try { _ = ((Il2CppArrayBase<string>)(object)Microphone.devices)[0]; return true; } catch { return false; } } public static bool IsSupported() { if (!_checkedForMic) { _hasMicrophones = CheckForMicrophone(); _checkedForMic = true; } return _hasMicrophones; } } public sealed class UnityVoiceManager : VoiceManager { public override bool CanTalk { get { if (!UnityVoice.IsSupported()) { return false; } return true; } } public override string[] InputDevices { get { if (!UnityVoice.IsSupported()) { return Array.Empty<string>(); } return Il2CppArrayBase<string>.op_Implicit((Il2CppArrayBase<string>)(object)Microphone.devices); } } protected override IVoiceReceiver OnCreateReceiverOrDefault() { return new UnityVoiceReceiver(); } protected override IVoiceSpeaker OnCreateSpeaker(PlayerId id) { return new UnityVoiceSpeaker(id); } } public sealed class UnityVoiceReceiver : IVoiceReceiver { private byte[] _uncompressedData; private bool _hasVoiceActivity; private AudioClip _voiceClip; private int _lastSample; private float _amplitude; private float _lastTalkTime; private bool _loopedData; private bool _wasTalking; public float GetVoiceAmplitude() { return _amplitude; } public byte[] GetCompressedVoiceData() { return VoiceCompressor.CompressVoiceData(_uncompressedData); } public bool HasVoiceActivity() { return _hasVoiceActivity; } public static string GetValidMicrophoneName() { return ClientSettings.VoiceChat.InputDevice.Value; } private void ClearData() { _uncompressedData = null; _hasVoiceActivity = false; _amplitude = 0f; } public unsafe void UpdateVoice(bool enabled) { if (!UnityVoice.IsSupported()) { ClearData(); return; } string validMicrophoneName = GetValidMicrophoneName(); bool flag = Microphone.IsRecording(validMicrophoneName); if (enabled && !flag) { _voiceClip = Microphone.Start(validMicrophoneName, true, 1, 16000); } else if (!enabled && flag) { Microphone.End(validMicrophoneName); } if (!enabled || (Object)(object)_voiceClip == (Object)null) { ClearData(); return; } int num = Microphone.GetPosition(validMicrophoneName); if (num < _lastSample) { _loopedData = true; num = 16000; } int num2 = num - _lastSample; Il2CppStructArray<float> val = new Il2CppStructArray<float>((long)num2); if (num2 > 0) { _voiceClip.GetData(val, _lastSample); } if (_loopedData) { _lastSample = 0; _loopedData = false; } else { _lastSample = num; } int num3 = 4; byte[] array = new byte[num2 * num3]; bool isTalking = false; _amplitude = 0f; for (int i = 0; i < num2; i++) { float num4 = ((Il2CppArrayBase<float>)(object)val)[i] * 10f; _amplitude += Mathf.Abs(num4); int num5 = i * num3; byte* ptr = (byte*)(&num4); for (int j = 0; j < num3; j++) { array[j + num5] = *(ptr++); } if (!isTalking) { isTalking = Math.Abs(num4) >= 0.3f; } } if (num2 > 0) { _amplitude /= num2; } CheckTalkingTimeout(ref isTalking); _wasTalking = isTalking; _uncompressedData = array; _hasVoiceActivity = isTalking; if (!isTalking) { _amplitude = 0f; } } private void CheckTalkingTimeout(ref bool isTalking) { if (isTalking) { _lastTalkTime = TimeUtilities.TimeSinceStartup; } else { isTalking = TimeUtilities.TimeSinceStartup - _lastTalkTime <= 1f; } } public void Enable() { } public void Disable() { _uncompressedData = null; _hasVoiceActivity = false; } } public class UnityVoiceSpeaker : VoiceSpeaker { private readonly Queue<float> _readingQueue = new Queue<float>(); private float _amplitude; private bool _clearedAudio; private bool _isReadyToRead; public UnityVoiceSpeaker(PlayerId id) { _id = id; OnContactUpdated(ContactsList.GetContact(id)); ContactsList.OnContactUpdated += OnContactUpdated; CreateAudioSource(); base.Source.clip = AudioClip.Create("UnityVoice", 16000, 1, 16000, true, PCMReaderCallback.op_Implicit((Action<Il2CppStructArray<float>>)PcmReaderCallback)); _source.Play(); VerifyRep(); } public override float GetVoiceAmplitude() { return _amplitude; } public override void Cleanup() { ContactsList.OnContactUpdated -= OnContactUpdated; base.Cleanup(); } private void OnContactUpdated(Contact contact) { base.Volume = contact.volume; } private void ClearVoiceData() { _readingQueue.Clear(); } public override void Update() { if (_readingQueue.Count >= 3200 && !_isReadyToRead) { _isReadyToRead = true; } else if (_readingQueue.Count <= 0) { _isReadyToRead = false; } if (!_clearedAudio && _amplitude <= 0.1f) { _clearedAudio = true; ClearVoiceData(); } else if (_clearedAudio && _amplitude >= 0.3f) { _clearedAudio = false; } } public override void OnVoiceDataReceived(byte[] data) { if (base.MicrophoneDisabled) { ClearVoiceData(); return; } VerifyRep(); byte[] array = VoiceCompressor.DecompressVoiceData(data); float voiceMultiplier = GetVoiceMultiplier(); for (int i = 0; i < array.Length; i += 4) { float item = BitConverter.ToSingle(array, i) * voiceMultiplier; _readingQueue.Enqueue(item); } } private float GetVoiceMultiplier() { float num = VoiceVolume.GetGlobalVolumeMultiplier(); if (_source.spatialBlend <= 0f) { num *= 0.25f; } return num; } private void PcmReaderCallback(Il2CppStructArray<float> data) { _amplitude = 0f; for (int i = 0; i < ((Il2CppArrayBase<float>)(object)data).Length; i++) { float num = 0f; if (_readingQueue.Count > 0 && _isReadyToRead) { num = _readingQueue.Dequeue(); } ((Il2CppArrayBase<float>)(object)data)[i] = num; _amplitude += Math.Abs(num); } _amplitude /= ((Il2CppArrayBase<float>)(object)data).Length; } } } 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 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 => ServerSettingsManager.ActiveSettings.PlayerConstraintsEnabled.Value; public static bool HasConstrainer => (Object)(object)GlobalConstrainer != (Object)null; public static Constrainer GlobalConstrainer { get; private set; } public static void OnMainSceneInitialized() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown SpawnableCrate crate = CrateFilterer.GetCrate<SpawnableCrate>(new Barcode("c1534c5a-3813-49d6-a98c-f595436f6e73")); if ((Object)(object)crate == (Object)null) { return; } if (!((Crate)crate).Pallet.IsInMarrowGame()) { ((Crate)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 class AchievementPair { public WeakAssetReference<Texture2D> Preview { get; private set; } = new WeakAssetReference<Texture2D>(); public static AchievementPair LoadFromBundle(AssetBundle bundle, string name) { AchievementPair pair = new AchievementPair(); bundle.LoadPersistentAssetAsync<Texture2D>("preview_" + name, (Action<Texture2D>)delegate(Texture2D v) { pair.Preview.SetAsset(v); }); return pair; } } 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>(); private static AssetBundleCreateRequest _achievementBundleRequest = null; public static WeakAssetReference<AssetBundle> AchievementBundle { get; private set; } = new WeakAssetReference<AssetBundle>(); private static void OnBundleCompleted(AsyncOperation operation) { AssetBundle assetBundle = _achievementBundleRequest.assetBundle; AchievementBundle.SetAsset(assetBundle); string[] achievementNames = _achievementNames; foreach (string text in achievementNames) { _achievementPairs.Add(text, AchievementPair.LoadFromBundle(assetBundle, text)); } } public static void OnBundleLoad() { _achievementBundleRequest = FusionBundleLoader.LoadAssetBundleAsync("achievement_bundle.fusion"); if (_achievementBundleRequest != null) { ((AsyncOperation)_achievementBundleRequest).completed += Action<AsyncOperation>.op_Implicit((Action<AsyncOperation>)OnBundleCompleted); } else { FusionLogger.Error("Achievement bundle failed to load!"); } } public static void OnBundleUnloaded() { if (AchievementBundle.HasAsset) { AchievementBundle.Asset.Unload(true); AchievementBundle.UnloadAsset(); } } public static AchievementPair GetPair(string name) { return _achievementPairs[name]; } } public static class FusionAudio { public static AudioSource Play2D(AudioClip clip, float volume = 1f) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) AudioSource obj = new GameObject("Fusion 2D Audio Source").AddComponent<AudioSource>(); obj.volume = volume; obj.clip = clip; obj.spatialBlend = 0f; obj.outputAudioMixerGroup = Audio3dManager.inHead; obj.Play(); return obj; } public static AudioSource Play3D(Vector3 position, AudioClip clip, float volume = 1f, bool loop = false) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Fusion 3D Audio Source"); AudioSource val2 = val.AddComponent<AudioSource>(); val.transform.position = position; val2.volume = volume; val2.clip = clip; val2.spatialBlend = 1f; val2.loop = loop; val2.outputAudioMixerGroup = Audio3dManager.hardInteraction; val2.Play(); return val2; } } 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 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 void LoadPersistentAssetAsync<T>(this AssetBundle bundle, string name, Action<T> onLoaded) where T : Object { AssetBundleRequest request = bundle.LoadAssetAsync<T>(name); ((AsyncOperation)request).completed += Action<AsyncOperation>.op_Implicit((Action<AsyncOperation>)delegate { if (!(request.asset == (Object)null)) { T val = ((Il2CppObjectBase)request.asset).TryCast<T>(); ((Object)val).hideFlags = (HideFlags)32; onLoaded(val); } }); } public static AssetBundle LoadAssetBundle(string name) { if (PlatformHelper.IsAndroid) { return EmbeddedAssetBundle.LoadFromAssembly(FusionMod.FusionAssembly, "LabFusion.dependencies.resources.bundles.Android." + name); } return EmbeddedAssetBundle.LoadFromAssembly(FusionMod.FusionAssembly, "LabFusion.dependencies.resources.bundles.StandaloneWindows64." + name); } public static AssetBundleCreateRequest LoadAssetBundleAsync(string name) { if (PlatformHelper.IsAndroid) { return EmbeddedAssetBundle.LoadFromAssemblyAsync(FusionMod.FusionAssembly, "LabFusion.dependencies.resources.bundles.Android." + name); } return EmbeddedAssetBundle.LoadFromAssemblyAsync(FusionMod.FusionAssembly, "LabFusion.dependencies.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 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 FusionContentLoader { private static AssetBundleCreateRequest _contentBundleRequest = null; public static WeakAssetReference<AssetBundle> ContentBundle { get; private set; } = new WeakAssetReference<AssetBundle>(); public static WeakAssetReference<GameObject> EntangledLinePrefab { get; private set; } = new WeakAssetReference<GameObject>(); public static WeakAssetReference<Texture2D> SabrelakeLogo { get; private set; } = new WeakAssetReference<Texture2D>(); public static WeakAssetReference<Texture2D> LavaGangLogo { get; private set; } = new WeakAssetReference<Texture2D>(); public static WeakAssetReference<AudioClip> BitGet { get; private set; } = new WeakAssetReference<AudioClip>(); public static WeakAssetReference<AudioClip> UISelect { get; private set; } = new WeakAssetReference<AudioClip>(); public static WeakAssetReference<AudioClip> UIDeny { get; private set; } = new WeakAssetReference<AudioClip>(); public static WeakAssetReference<AudioClip> UIConfirm { get; private set; } = new WeakAssetReference<AudioClip>(); public static WeakAssetReference<AudioClip> UITurnOff { get; private set; } = new WeakAssetReference<AudioClip>(); public static WeakAssetReference<AudioClip> UITurnOn { get; private set; } = new WeakAssetReference<AudioClip>(); public static WeakAssetReference<AudioClip> PurchaseFailure { get; private set; } = new WeakAssetReference<AudioClip>(); public static WeakAssetReference<AudioClip> PurchaseSuccess { get; private set; } = new WeakAssetReference<AudioClip>(); public static WeakAssetReference<AudioClip> EquipItem { get; private set; } = new WeakAssetReference<AudioClip>(); public static WeakAssetReference<AudioClip> UnequipItem { get; private set; } = new WeakAssetReference<AudioClip>(); public static WeakAssetReference<Texture2D> NotificationInformation { get; private set; } = new WeakAssetReference<Texture2D>(); public static WeakAssetReference<Texture2D> NotificationWarning { get; private set; } = new WeakAssetReference<Texture2D>(); public static WeakAssetReference<Texture2D> NotificationError { get; private set; } = new WeakAssetReference<Texture2D>(); public static WeakAssetReference<Texture2D> NotificationSuccess { get; private set; } = new WeakAssetReference<Texture2D>(); public static WeakAssetReference<GameObject> LaserCursor { get; private set; } = new WeakAssetReference<GameObject>(); public static WeakAssetReference<AudioClip> LaserPulseSound { get; private set; } = new WeakAssetReference<AudioClip>(); public static WeakAssetReference<AudioClip> LaserRaySpawn { get; private set; } = new WeakAssetReference<AudioClip>(); public static WeakAssetReference<AudioClip> LaserRayDespawn { get; private set; } = new WeakAssetReference<AudioClip>(); public static WeakAssetReference<AudioClip> LaserPrismaticSFX { get; private set; } = new WeakAssetReference<AudioClip>(); private static void OnBundleCompleted(AsyncOperation operation) { AssetBundle assetBundle = _contentBundleRequest.assetBundle; ContentBundle.SetAsset(assetBundle); assetBundle.LoadPersistentAssetAsync<GameObject>("renderer_EntangledLine", (Action<GameObject>)delegate(GameObject v) { EntangledLinePrefab.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<Texture2D>("tex_sabreLakeLogo", (Action<Texture2D>)delegate(Texture2D v) { SabrelakeLogo.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<Texture2D>("tex_lavaGangLogo", (Action<Texture2D>)delegate(Texture2D v) { LavaGangLogo.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<AudioClip>("stinger_BitGet", (Action<AudioClip>)delegate(AudioClip v) { BitGet.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<AudioClip>("UI_Beep_Bend_Short_stereo", (Action<AudioClip>)delegate(AudioClip v) { UISelect.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<AudioClip>("UI_Error_Double_Note_Down_Notch_stereo", (Action<AudioClip>)delegate(AudioClip v) { UIDeny.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<AudioClip>("UI_SCI-FI_Confirm_Dry_stereo", (Action<AudioClip>)delegate(AudioClip v) { UIConfirm.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<AudioClip>("UI_TurnOff", (Action<AudioClip>)delegate(AudioClip v) { UITurnOff.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<AudioClip>("UI_TurnOn", (Action<AudioClip>)delegate(AudioClip v) { UITurnOn.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<AudioClip>("stinger_FailPurchase", (Action<AudioClip>)delegate(AudioClip v) { PurchaseFailure.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<AudioClip>("stinger_SuccessPurchase", (Action<AudioClip>)delegate(AudioClip v) { PurchaseSuccess.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<AudioClip>("ui_EquipItem", (Action<AudioClip>)delegate(AudioClip v) { EquipItem.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<AudioClip>("ui_UnequipItem", (Action<AudioClip>)delegate(AudioClip v) { UnequipItem.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<Texture2D>("notification_Information", (Action<Texture2D>)delegate(Texture2D v) { NotificationInformation.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<Texture2D>("notification_Warning", (Action<Texture2D>)delegate(Texture2D v) { NotificationWarning.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<Texture2D>("notification_Error", (Action<Texture2D>)delegate(Texture2D v) { NotificationError.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<Texture2D>("notification_Success", (Action<Texture2D>)delegate(Texture2D v) { NotificationSuccess.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<GameObject>("laser_Cursor", (Action<GameObject>)delegate(GameObject v) { LaserCursor.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<AudioClip>("laser_PulseSound", (Action<AudioClip>)delegate(AudioClip v) { LaserPulseSound.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<AudioClip>("laser_RaySpawn", (Action<AudioClip>)delegate(AudioClip v) { LaserRaySpawn.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<AudioClip>("laser_RayDespawn", (Action<AudioClip>)delegate(AudioClip v) { LaserRayDespawn.SetAsset(v); }); assetBundle.LoadPersistentAssetAsync<AudioClip>("laser_PrismaticSFX", (Action<AudioClip>)delegate(AudioClip v) { LaserPrismaticSFX.SetAsset(v); }); } public static void OnBundleLoad() { _contentBundleRequest = FusionBundleLoader.LoadAssetBundleAsync("content_bundle.fusion"); if (_contentBundleRequest != null) { ((AsyncOperation)_contentBundleRequest).completed += Action<AsyncOperation>.op_Implicit((Action<AsyncOperation>)OnBundleCompleted); } else { FusionLogger.Error("Content Bundle failed to load!"); } } public static void OnBundleUnloaded() { if (ContentBundle.HasAsset) { ContentBundle.Asset.Unload(true); ContentBundle.UnloadAsset(); } } } public static class FusionDevTools { public static bool DespawnConstrainer(PlayerId id) { FusionPermissions.FetchPermissionLevel(id, out var level, out var _); if (!FusionPermissions.HasSufficientPermissions(level, ServerSettingsManager.ActiveSettings.ConstrainerAllowed.Value)) { 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, ServerSettingsManager.ActiveSettings.DevToolsAllowed.Value)) { 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, ServerSettingsManager.ActiveSettings.DevToolsAllowed.Value)) { return true; } return false; } } 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}"); } } 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 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 OnUpdate() { if (!FusionSceneManager.IsLoading() && RigData.HasPlayer) { CheckFloatingPoint(); } } private static void CheckFloatingPoint() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (RigData.Refs.RigManager.physicsRig.feet.transform.position.IsNanOrInf()) { if (NetworkInfo.HasServer && !NetworkInfo.IsServer) { NetworkHelper.Disconnect("Game Crash"); } SceneStreamer.Reload(); FusionNotifier.Send(new FusionNotification { isPopup = true, showTitleOnPopup = true, title = "Whoops! Sorry about that!", type = NotificationType.WARNING, message = "The scene was reloaded due to a physics crash.", popupLength = 6f }); } } internal static void Internal_OnAvatarChanged(RigManager rigManager, Avatar avatar, string barcode) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown 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.IsInMarrowGame() && PlayerIdManager.LocalId != null && PlayerIdManager.LocalId.TryGetPermissionLevel(out level)) { PermissionLevel value = ServerSettingsManager.ActiveSettings.CustomAvatarsAllowed.Value; if (!FusionPermissions.HasSufficientPermissions(level, value)) { rigManager.SwapAvatarCrate(new Barcode("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.Refs.RigManager; } public static void SetAmmo(int count) { AmmoInventory instance = AmmoInventory.Instance; if (!((Object)(object)instance == (Object)null)) { instance.ClearAmmo(); instance.AddCartridge(instance.lightAmmoGroup, count); instance.AddCartridge(instance.heavyAmmoGroup, count); instance.AddCartridge(instance.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.Refs.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(CommonPreferences.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.Refs.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() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown if (!RigData.HasPlayer || !AssetWarehouse.ready || AvatarOverride == null) { return; } if ((Object)(object)CrateFilterer.GetCrate<AvatarCrate>(new Barcode(AvatarOverride)) == (Object)null) { return; } RigManager rm = RigData.Refs.RigManager; rm.SwapAvatarCrate(new Barcode(AvatarOverride), true, Action<bool>.op_Implicit((Action<bool>)delegate(bool success) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown if (!success) { rm.SwapAvatarCrate(new Barcode("c3534c5a-94b2-40a4-912a-24a8506f6c79"), true, (Action<bool>)null); } })); } private static void Internal_ChangePlayerHealth() { if (RigData.HasPlayer) { RigManager rigManager = RigData.Refs.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 class ItemPair { public WeakAssetReference<GameObject> GameObject { get; private set; } = new WeakAssetReference<GameObject>(); public WeakAssetReference<Texture2D> Preview { get; private set; } = new WeakAssetReference<Texture2D>(); public static ItemPair LoadFromBundle(AssetBundle bundle, string name) { ItemPair itemPair = new ItemPair(); bundle.LoadPersistentAssetAsync<GameObject>("item_" + name, (Action<GameObject>)delegate(GameObject v) { itemPair.GameObject.SetAsset(v); }); bundle.LoadPersistentAssetAsync<Texture2D>("preview_" + name, (Action<Texture2D>)delegate(Texture2D v) { itemPair.Preview.SetAsset(v); }); return itemPair; } } public static class FusionPointItemLoader { private static readonly ItemPair _nullItemPair = new ItemPair(); private static readonly string[] _itemNames = new string[1] { "BitMiner" }; private static readonly Dictionary<string, ItemPair> _itemPairs = new Dictionary<string, ItemPair>(); private static AssetBundleCreateRequest _itemBundleRequest = null; public static WeakAssetReference<AssetBundle> ItemBundle { get; private set; } = new WeakAssetReference<AssetBundle>(); private static void OnBundleCompleted(AsyncOperation operation) { AssetBundle assetBundle = _itemBundleRequest.assetBundle; ItemBundle.SetAsset(assetBundle); string[] itemNames = _itemNames; foreach (string text in itemNames) { _itemPairs.Add(text, ItemPair.LoadFromBundle(assetBundle, text)); } } public static void OnBundleLoad() { _itemBundleRequest = FusionBundleLoader.LoadAssetBundleAsync("item_bundle.fusion"); if (_itemBundleRequest != null) { ((AsyncOperation)_itemBundleRequest).completed += Action<AsyncOperation>.op_Implicit((Action<AsyncOperation>)OnBundleCompleted); } else { FusionLogger.Error("Item bundle failed to load!"); } } public static void OnBundleUnloaded() { if (ItemBundle.HasAsset) { ItemBundle.Asset.Unload(true); ItemBundle.UnloadAsset(); } } public static ItemPair GetPair(string name) { if (_itemPairs.TryGetValue(name, out var value)) { return value; } return _nullItemPair; } } 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 LobbyMenuAction(Page page, 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 PlayerUpdate OnPlayerCatchup; public static event LobbyMenuAction OnLobbyCategoryCreated; 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(PlayerId playerId) { MultiplayerHooking.OnPlayerCatchup.InvokeSafe(playerId, "executing OnPlayerCatchup hook"); } internal static void Internal_OnLobbyCategoryCreated(Page page, INetworkLobby lobby) { MultiplayerHooking.OnLobbyCategoryCreated.InvokeSafe<LobbyMenuAction, Page, INetworkLobby>(page, lobby, "executing OnLobbyCategoryCreated"); } internal static void Internal_OnServerSettingsChanged() { MultiplayerHooking.OnServerSettingsChanged.InvokeSafe("executing server settings changed hook"); } internal static void Internal_OnUpdate() { MultiplayerHooking.OnUpdate?.Invoke(); } internal static void Internal_OnFixedUpdate() { MultiplayerHooking.OnFixedUpdate?.Invoke(); } internal static void Internal_OnLateUpdate() { MultiplayerHooking.OnLateUpdate?.Invoke(); } internal static void Internal_OnMainSceneInitialized() { MultiplayerHooking.OnMainSceneInitialized.InvokeSafe("executing OnMainSceneInitialized hook"); } internal static void Internal_OnLoadingBegin() { MultiplayerHooking.OnLoadingBegin.InvokeSafe("executing OnLoadingBegin hook"); } } 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown _timeOfPopup = TimeUtilities.TimeSinceStartup; LabFusion.SDK.Achievements.Achievement achievement = _queuedAchievements.Dequeue(); Transform camera = ((Rig)RigData.Refs.ControllerRig).m_head; Spawnable val = new Spawnable { crateRef = FusionSpawnableReferences.AchievementPopupReference, policyData = null }; AssetSpawner.Register(val); SafeAssetSpawner.Spawn(val, Vector3.zero, Quaternion.identity, delegate(Poolee poolee) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)poolee).transform; transform.parent = camera; UIMachineUtilities.OverrideFonts(((Component)transform).transform); transform.localPosition = LocalPosition; transform.localRotation = Quaternion.identity; Transform val2 = transform.Find("Offset/Canvas"); if ((Object)(object)achievement.PreviewImage != (Object)null) { ((Component)val2.Find("icon")).GetComponent<RawImage>().texture = (Texture)(object)achievement.PreviewImage; } ((Component)val2.Find("title")).GetComponent<TMP_Text>().text = achievement.Title; ((Component)val2.Find("description")).GetComponent<TMP_Text>().text = achievement.Description; FusionAudio.Play2D(FusionContentLoader.UITurnOn.Asset); PooleeHelper.DespawnDelayed(poolee, 5.1f); }); } internal static bool IsPlayingPopup() { return TimeUtilities.TimeSinceStartup - _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 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown int amount = _bitQueue.Dequeue(); Transform camera = ((Rig)RigData.Refs.ControllerRig).m_head; Spawnable val = new Spawnable { crateRef = FusionSpawnableReferences.BitPopupReference, policyData = null }; AssetSpawner.Register(val); SafeAssetSpawner.Spawn(val, Vector3.zero, Quaternion.identity, delegate(Poolee poolee) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)poolee).transform; transform.parent = camera; UIMachineUtilities.OverrideFonts(transform); transform.SetLocalPositionAndRotation(LocalPosition, LocalRotation); Transform val2 = transform.Find("Offset/Canvas"); string text = ((amount < 0) ? $"{amount}" : $"+{amount}"); ((Component)val2.Find("text_shadow")).GetComponent<TMP_Text>().text = text; TMP_Text component = ((Component)val2.Find("amount")).GetComponent<TMP_Text>(); component.text = text; if (amount < 0) { ((Graphic)component).color = Color.red; ((Graphic)((Component)val2.Find("bit")).GetComponent<RawImage>()).color = Color.red; } FusionAudio.Play2D(FusionContentLoader.BitGet.Asset); PooleeHelper.DespawnDelayed(poolee, 1.1f); }); } } 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<Page> onCreateCategory; } public static class FusionNotifier { public const float DefaultDuration = 2f; public const float DefaultScaleTime = 0.4f; 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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}"; Page val = BoneMenuCreator.NotificationCategory.CreatePage(text, fusionNotification.title.color, 0, false); PageLinkElement pageLink = BoneMenuCreator.NotificationCategory.CreatePageLink(val); val.Name = fusionNotification.title.text; _notificationNumber++; if (!string.IsNullOrWhiteSpace(fusionNotification.message.text)) { val.CreateFunction(fusionNotification.message.text, fusionNotification.message.color, (Action)null); } val.CreateFunction("Mark as Read", Color.red, (Action)delegate { BoneMenuCreator.RemoveNotification((Element)(object)pageLink); }); fusionNotification.onCreateCategory.InvokeSafe<Action<Page>, Page>(val, "executing Notification.OnCreateCategory"); } RigManager rigManager = RigData.Refs.RigManager; if (fusionNotification.isPopup && !((Object)(object)rigManager).IsNOC()) { HeadTitles headTitles = TutorialRig.Instance.headTitles; EnableTutorialRig(); string text2 = "New Notification"; if (fusionNotification.showTitleOnPopup) { text2 = fusionNotification.title.text; } string text3 = fusionNotification.message.text; Sprite popupSprite = GetPopupSprite(fusionNotification); float popupLength = fusionNotification.popupLength; float timeToScale = Mathf.Lerp(0.05f, 0.4f, Mathf.Clamp01(popupLength - 1f)); headTitles.timeToScale = timeToScale; headTitles.CUSTOMDISPLAY(text2, text3, popupSprite, popupLength, (AudioClip)null, false, (Sprite)null, (Sprite)null, (Sprite)null, (Sprite)null); headTitles.sr_element.sprite = popupSprite; } } private static Sprite GetPopupSprite(FusionNotification notification) { //IL_0073: 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) Texture2D val = (Texture2D)(notification.type switch { NotificationType.WARNING => FusionContentLoader.NotificationWarning.Asset, NotificationType.ERROR => FusionContentLoader.NotificationError.Asset, NotificationType.SUCCESS => FusionContentLoader.NotificationSuccess.Asset, _ => FusionContentLoader.NotificationInformation.Asset, }); if ((Object)(object)val != (Object)null) { return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } return null; } internal static void EnableTutorialRig() { if (!((Object)(object)RigData.Refs.RigManager).IsNOC()) { TutorialRig instance = TutorialRig.Instance; HeadTitles headTitles = instance.headTitles; ((Component)instance).gameObject.SetActive(true); ((Component)headTitles).gameObject.SetActive(true); } } internal static bool IsPlayingNotification() { if (!((Object)(object)RigData.Refs.RigManager).IsNOC()) { return ((Component)TutorialRig.Instance.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; } } } public static class FusionPopupManager { internal static void OnInitializeMelon() { FusionAchievementPopup.OnInitializeMelon(); } internal static void OnUpdate() { FusionNotifier.OnUpdate(); FusionAchievementPopup.OnUpdate(); FusionBitPopup.OnUpdate(); } } 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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) try { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(0, 4); Scene scene = go.scene; defaultInterpolatedStringHandler.AppendFormatted(((Scene)(ref scene)).name); defaultInterpolatedStringHandler.AppendFormatted('¬'); defaultInterpolatedStringHandler.AppendFormatted(((Component)go.transform.root).gameObject.GetRootIndex()); defaultInterpolatedStringHandler.AppendFormatted(go.transform.GetBasePath()); return defaultInterpolatedStringHandler.ToStringAndClear(); } catch { } return "INVALID_PATH"; } public static GameObject GetGameObject(string path) { string[] array = path.Split('¬'); 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; } } public static class ImpactUtilities { public static void OnHitRigidbody(Rigidbody rb) { GameObject gameObject = ((Component)rb).gameObject; MarrowBody marrowBody = MarrowBody.Cache.Get(gameObject); if ((Object)(object)marrowBody == (Object)null) { return; } if (MarrowBodyExtender.Cache.TryGet(marrowBody, out var value)) { GripExtender extender = value.GetExtender<GripExtender>(); if (extender == null || !extender.CheckHeld()) { NetworkEntityManager.TakeOwnership(value); } } else if (gameObject.IsSyncWhitelisted()) { DelayUtilities.Delay(delegate { PropSender.SendPropCreation(marrowBody.Entity); }, 4); } } } 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 ManagedMathf { [StructLayout(LayoutKind.Sequential, Size = 1)] private struct MathfInternal { public static volatile float FloatMinNormal = 1.1754944E-38f; public static volatile float FloatMinDenormal = float.Epsilon; public static bool IsFlushToZeroEnabled = FloatMinDenormal == 0f; } public static readonly float Epsilon = (MathfInternal.IsFlushToZeroEnabled ? MathfInternal.FloatMinNormal : MathfInternal.FloatMinDenormal); public const float Rad2Deg = 57.29578f; public const float Deg2Rad = (float)Math.PI / 180f; public static float Sin(float f) { return (float)Math.Sin(f); } public static float Acos(float f) { return (float)Math.Acos(f); } public static float Clamp(float value, float min, float max) { if (value < min) { value = min; } else if (value > max) { value = max; } return value; } public static int Clamp(int value, int min, int max) { if (value < min) { value = min; } else if (value > max) { value = max; } return value; } public static float Clamp01(float value) { if (value < 0f) { return 0f; } if (value > 1f) { return 1f; } return value; } public static float Lerp(float a, float b, float t) { return a + (b - a) * Clamp01(t); } public static float LerpUnclamped(float a, float b, float t) { return a + (b - a) * t; } public static int FloorToInt(float f) { return (int)Math.Floor(f); } public static int CeilToInt(float f) { return (int)Math.Ceiling(f); } public static bool Approximately(float a, float b) { return Math.Abs(b - a) < Math.Max(1E-06f * Math.Max(Math.Abs(a), Math.Abs(b)), Epsilon * 8f); } } internal static class PersistentAssetCreator { private const string _targetFont = "arlon-medium"; private static Action<HandPose> _onSoftGrabLoaded; internal static TMP_FontAsset Font { get; private set; } internal static HandPose SoftGrabPose { get; private set; } internal static void OnLateInitializeMelon() { CreateTextFont(); } internal static void OnMainSceneInitialized() { GetHandPose(); } private static void GetHandPose() { SoftGrabPose = RigData.Refs.RigManager.worldGripHandPose; if ((Object)(object)SoftGrabPose != (Object)null) { _onSoftGrabLoaded?.Invoke(SoftGrabPose); } _onSoftGrabLoaded = null; } 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]; } } internal static void SetupImpactProperties(RigManager rig) { PhysicsRig physicsRig = rig.physicsRig; Il2CppArrayBase<Rigidbody> componentsInChildren = ((Component)physicsRig).GetComponentsInChildren<Rigidbody>(true); DataCardReference<SurfaceDataCard> surfaceDataCard = new DataCardReference<SurfaceDataCard>("SLZ.Backlot.SurfaceDataCard.Blood"); for (int i = 0; i < componentsInChildren.Length; i++) { Rigidbody obj = componentsInChildren[i]; GameObject gameObject = ((Component)obj).gameObject; if (!Object.op_Implicit((Object)(object)((Component)obj).GetComponent<ImpactProperties>()) && !((Object)(object)gameObject == (Object)(object)physicsRig.knee) && !((Object)(object)gameObject == (Object)(object)physicsRig.feet)) { ImpactProperties obj2 = gameObject.AddComponent<ImpactProperties>(); obj2.SurfaceDataCard = surfaceDataCard; obj2.decalType = (DecalType)(-1); } } } } internal static class PhysicsUtilities { internal static void OnUpdateTimescale() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (!NetworkInfo.HasServer) { return; } TimeScaleMode timeScaleMode = CommonPreferences.TimeScaleMode; RigManager rigManager = RigData.Refs.RigManager; if (timeScaleMode != TimeScaleMode.LOW_GRAVITY || !RigData.HasPlayer || TimeManager.cur_intensity <= 0f) { return; } float num = 1f - 1f / TimeManager.cur_intensity; Vector3 val = -Physics.gravity * num; Enumerator<Rigidbody> enumerator = rigManager.physicsRig.selfRbs.GetEnumerator(); while (enumerator.MoveNext()) { Rigidbody current = enumerator.Current; if (current.useGravity) { current.AddForce(val, (ForceMode)5); } } } } 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); } } } } internal static class TimeUtilities { private static float _deltaTime = 1f; private static float _fixedDeltaTime = 0.02f; private static float _timeSinceStartup = 0f; private static float _timeScale = 1f; private static int _frameCount = 0; public static float DeltaTime => _deltaTime; public static float FixedDeltaTime => _fixedDeltaTime; public static float TimeSinceStartup => _timeSinceStartup; public static float TimeScale => _timeScale; public static int FrameCount => _frameCount; internal static void OnEarlyUpdate() { _timeScale = Time.timeScale; _deltaTime = Time.deltaTime; _timeSinceStartup += _deltaTime; _frameCount++; } internal static void OnEarlyFixedUpdate() { _fixedDeltaTime = Time.fixedDeltaTime; } public static bool IsMatchingFrame(int interval) { return FrameCount % interval == 0; } public static bool IsMatchingFrame(int interval, int offset) { return (FrameCount + offset) % interval == 0; } } public static class MagazineUtilities { public static void ClaimMagazine(Magazine magazine, InventoryAmmoReceiver ammoReceiver) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) CartridgeData val = ammoReceiver.defaultLightCart; if ((Object)(object)ammoReceiver._selectedCartridgeData != (Object)null) { val = ammoReceiver._selectedCartridgeData; } magazine.Initialize(val, AmmoInventory.Instance.GetCartridgeCount(val)); magazine.Claim(); SafeAudio3dPlayer.PlayAtPoint(Il2CppArrayBase<AudioClip>.op_Implicit((Il2CppArrayBase<AudioClip>)(object)ammoReceiver.grabClips), ((Component)ammoReceiver).transform.position, Audio3dManager.softInteraction, 0.2f); } public static void GrabMagazine(Magazine magazine, NetworkPlayer player, Handedness handedness) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 RigManager rigManager = player.RigRefs.RigManager; InventoryAmmoReceiverExtender extender = player.NetworkEntity.GetExtender<InventoryAmmoReceiverExtender>(); if (extender != null) { ClaimMagazine(magazine, extender.Component); } Grip grip = magazine.grip; Hand found = (((int)handedness == 1) ? rigManager.physicsRig.leftHand : rigManager.physicsRig.rightHand); if (Object.op_Implicit((Object)(object)found)) { DelayUtilities.Delay(delegate { grip.MoveIntoHand(found); grip.TryAttach(found, isInstant: true); }, 1); } } } public static class MuteUIHelper { private static PageItem _mutePage; private static Poolee _indicatorPoolee; private static GameObject _indicatorGameObject; private static Renderer _indicatorRenderer; private static Camera _headsetCamera; public static void OnInitializeMelon() { FusionPref<bool> muted = ClientSettings.VoiceChat.Muted; muted.OnValueChanged = (Action<bool>)Delegate.Combine(muted.OnValueChanged, new Action<bool>(OnMutedChanged)); FusionPref<bool> mutedIndicator = ClientSettings.VoiceChat.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 = ClientSettings.VoiceChat.Muted; muted.OnValueChanged = (Action<bool>)Delegate.Remove(muted.OnValueChanged, new Action<bool>(OnMutedChanged)); FusionPref<bool> mutedIndicator = ClientSettings.VoiceChat.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)_headsetCamera) && !((Object)(object)_indicatorRenderer == (Object)null)) { _indicatorRenderer.enabled = true; } } private static void OnEndCameraRendering(ScriptableRenderContext context, Camera camera) { if (!((Object)(object)camera != (Object)(object)_headsetCamera) && !((Object)(object)_indicatorRenderer == (Object)null)) { _indicatorRenderer.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)_indicatorGameObject == (Object)null)) { _indicatorGameObject.SetActive(VoiceInfo.ShowMuteIndicator); } } public static void OnCreateMuteUI(RigManager manager) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_009a: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown if (!VoiceInfo.CanTalk) { return; } PopUpMenuView popUpMenu = UIRig.Instance.popUpMenu; Page homePage = popUpMenu.radialPageView.m_HomePage; FusionPref<bool> mutedPref = ClientSettings.VoiceChat.Muted; _mutePage = new PageItem(mutedPref.Value ? "Quick Unmute" : "Quick Mute", (Directions)3, Action.op_Implicit((Action)delegate { mutedPref.Value = !mutedPref.Value; popUpMenu.Deactivate(); FusionNotifier.Send(new FusionNotification { isPopup = true, isMenuItem = false, message = (mutedPref.Value ? "Muted" : "Unmuted") }); })); homePage.items.Add(_mutePage); OpenControllerRig val = ((Il2CppObjectBase)manager.ControllerRig).TryCast<OpenControllerRig>(); Transform headset = val.headset; Spawnable val2 = new Spawnable { crateRef = FusionSpawnableReferences.MuteIndicatorReference, policyData = null }; AssetSpawner.Register(val2); SafeAssetSpawner.Spawn(val2, Vector3.zero, Quaternion.identity, delegate(Poolee poolee) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) _indicatorPoolee = poolee; _indicatorGameObject = ((Component)poolee).gameObject; _indicatorGameObject.SetActive(false); ((Object)_indicatorGameObject).name = "Mute Icon [FUSION]"; _indicatorRenderer = _indicatorGameObject.GetComponentInChildren<Renderer>(); _indicatorRenderer.enabled = false; if (!((Object)(object)headset == (Object)null)) { _headsetCamera = ((Component)headset).GetComponent<Camera>(); Transform transform = _indicatorGameObject.transform; transform.parent = headset; transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); UpdateMuteIcon(); } }); } public static void OnDestroyMuteUI() { if (_mutePage != null) { PopUpMenuView popUpMenu = UIRig.Instance.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)_indicatorPoolee).IsNOC()) { _indicatorPoolee.Despawn(); _indicatorPoolee = null; _indicatorGameObject = null; _indicatorRenderer = null; } } } public static class PlatformHelper { private static readonly bool _isAndroidCached = (int)MelonUtils.CurrentPlatform == 3; public const string AndroidName = "QUEST"; public const string WindowsName = "PC"; public static bool IsAndroid => _isAndroidCached; public static string GetPlatformName() { if (IsAndroid) { return "QUEST"; } return "PC"; } } public static class PlayerAdditionsHelper { public static void OnInitializeMelon() { MultiplayerHooking.OnJoinServer += delegate { OnEnterServer(RigData.Refs.RigManager); }; MultiplayerHooking.OnStartServer += delegate { OnEnterServer(RigData.Refs.RigManager); }; MultiplayerHooking.OnDisconnect += delegate { OnExitServer(RigData.Refs.RigManager); }; LocalPlayer.OnLocalRigCreated = (Action<RigManager>)Delegate.Combine(LocalPlayer.OnLocalRigCreated, (Action<RigManager>)delegate(RigManager rig) { OnCreatedLocalPlayer(rig); if (NetworkInfo.HasServer) { OnEnterServer(rig); } }); MuteUIHelper.OnInitializeMelon(); } public static void OnDeinitializeMelon() { MuteUIHelper.OnDeinitializeMelon(); } public static void OnAvatarChanged(RigManager manager) { } public static void OnCreatedLocalPlayer(RigManager manager) { OnCreatedRig(manager); } public static void OnCreatedRig(RigManager manager) { OnAvatarChanged(manager); } public static void OnEnterServer(RigManager manager) { if (!((Object)(object)manager).IsNOC()) { MuteUIHelper.OnCreateMuteUI(manager); PersistentAssetCreator.SetupImpactProperties(manager); manager.health._testRagdollOnDeath = true; manager.health._testVisualDamage = true; Player_Health obj = ((Il2CppObjectBase)manager.health).TryCast<Player_Health>(); obj.reloadLevelOnDeath = false; obj.slowMoOnDeath = false; PhysicsRig physicsRig = manager.physicsRig; ((Component)((Rig)physicsRig).m_handLf).gameObject.AddComponent<CollisionSyncer>(); ((Component)((Rig)physicsRig).m_elbowLf).gameObject.AddComponent<CollisionSyncer>(); ((Component)((Rig)physicsRig).m_shoulderLf).gameObject.AddComponent<CollisionSyncer>(); ((Component)((Rig)physicsRig).m_handRt).gameObject.AddComponent<CollisionSyncer>(); ((Component)((Rig)physicsRig).m_elbowRt).gameObject.AddComponent<CollisionSyncer>(); ((Component)((Rig)physicsRig).m_shoulderRt).gameObject.AddComponent<CollisionSyncer>(); physicsRig.feet.gameObject.AddComponent<CollisionSyncer>(); ((Component)((Rig)physicsRig).m_head).gameObject.AddComponent<CollisionSyncer>(); FusionPlayer.ResetMortality(); } } public static void OnExitServer(RigManager manager) { if (((Object)(object)manager).IsNOC()) { return; } MuteUIHelper.OnDestroyMuteUI(); foreach (ImpactProperties componentsInChild in ((Component)manager).GetComponentsInChildren<ImpactProperties>(true)) { Object.Destroy((Object)(object)componentsInChild); } foreach (CollisionSyncer componentsInChild2 in ((Component)manager).GetComponentsInChildren<CollisionSyncer>(true)) { Object.Destroy((Object)(object)componentsInChild2); } manager.health._testRagdollOnDeath = false; manager.health._testVisualDamage = false; ((Il2CppObjectBase)manager.health).TryCast<Player_Health>().slowMoOnDeath = true; } } public static class PooleeUtilities { internal static bool CanDespawn; public static void D
Plugins/LabFusionUpdater.dll
Decompiled 3 months agousing System; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using LabFusionUpdater; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Utils; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("LabFusion Updater")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany(null)] [assembly: AssemblyProduct("LabFusion Updater")] [assembly: AssemblyCopyright("Created by Lakatrazz")] [assembly: AssemblyTrademark(null)] [assembly: ComVisible(false)] [assembly: AssemblyFileVersion("1.0.0")] [assembly: NeutralResourcesLanguage("en")] [assembly: MelonInfo(typeof(FusionUpdaterPlugin), "LabFusion Updater", "1.0.0", "Lakatrazz", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyVersion("1.0.0.0")] namespace LabFusionUpdater; [StructLayout(LayoutKind.Sequential, Size = 1)] public struct FusionUpdaterVersion { public const byte versionMajor = 1; public const byte versionMinor = 0; public const short versionPatch = 0; } public class FusionUpdaterPlugin : MelonPlugin { public const string Name = "LabFusion Updater"; public const string Author = "Lakatrazz"; public static readonly Version Version = new Version(1, 0, 0); private MelonPreferences_Category _prefCategory = MelonPreferences.CreateCategory("LabFusionUpdater"); private MelonPreferences_Entry<bool> _offlineModePref; public const string ModName = "LabFusion"; public const string PluginName = "LabFusionUpdater"; public const string FileExtension = ".dll"; public static readonly string ModAssemblyPath = Path.Combine(MelonEnvironment.ModsDirectory, "LabFusion.dll"); public static readonly string PluginAssemblyPath = Path.Combine(MelonEnvironment.PluginsDirectory, "LabFusionUpdater.dll"); public static FusionUpdaterPlugin Instance { get; private set; } public static Instance Logger { get; private set; } public static Assembly UpdaterAssembly { get; private set; } public bool IsOffline => _offlineModePref.Value; public override void OnPreInitialization() { Instance = this; Logger = ((MelonBase)this).LoggerInstance; UpdaterAssembly = ((MelonBase)this).MelonAssembly.Assembly; _offlineModePref = _prefCategory.CreateEntry<bool>("OfflineMode", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); _prefCategory.SaveToFile(false); ((MelonBase)this).LoggerInstance.Msg(IsOffline ? Color.Yellow : Color.Green, IsOffline ? "Fusion Auto-Updater is OFFLINE." : "Fusion Auto-Updater is ONLINE."); if (IsOffline) { if (!File.Exists(ModAssemblyPath)) { ((MelonBase)this).LoggerInstance.Warning("LabFusion.dll was not found in the Mods folder!"); ((MelonBase)this).LoggerInstance.Warning("Download it from the Github or switch to ONLINE mode."); ((MelonBase)this).LoggerInstance.Warning("https://github.com/Lakatrazz/BONELAB-Fusion/releases"); } } else { Updater.UpdateMod(); } } public override void OnApplicationQuit() { Updater.UpdatePlugin(); } } internal static class Updater { private static readonly string _dataDir = Path.Combine(MelonEnvironment.UserDataDirectory, "LabFusionUpdater"); private static readonly string _updaterAppName = "updater.exe"; private static bool pluginNeedsUpdating = false; public static void UpdateMod() { Version value = new Version(0, 0, 0); if (File.Exists(FusionUpdaterPlugin.ModAssemblyPath)) { AssemblyName assemblyName = AssemblyName.GetAssemblyName(FusionUpdaterPlugin.ModAssemblyPath); value = new Version(assemblyName.Version.Major, assemblyName.Version.Minor, assemblyName.Version.Build); FusionUpdaterPlugin.Logger.Msg($"{"LabFusion"}{".dll"} found in Mods folder. Version: {value}"); } try { Directory.CreateDirectory(_dataDir); string text = Path.Combine(_dataDir, _updaterAppName); Assembly updaterAssembly = FusionUpdaterPlugin.UpdaterAssembly; string name = updaterAssembly.GetManifestResourceNames().First((string x) => x.Contains(_updaterAppName)); using (Stream stream = updaterAssembly.GetManifestResourceStream(name)) { using FileStream destination = File.Create(text); stream.CopyTo(destination); } Process process = new Process(); process.StartInfo.FileName = text; process.StartInfo.Arguments = $"{value} \"{FusionUpdaterPlugin.ModAssemblyPath}\" \"{FusionUpdaterPlugin.PluginAssemblyPath}\" \"false\""; process.Start(); process.WaitForExit(); switch ((ExitCode)process.ExitCode) { case ExitCode.Success: ((MelonBase)FusionUpdaterPlugin.Instance).LoggerInstance.Msg("LabFusion.dll updated successfully!"); pluginNeedsUpdating = true; break; case ExitCode.UpToDate: ((MelonBase)FusionUpdaterPlugin.Instance).LoggerInstance.Msg("LabFusion.dll is already up to date."); break; case ExitCode.Error: ((MelonBase)FusionUpdaterPlugin.Instance).LoggerInstance.Error("LabFusion.dll failed to update!"); break; } } catch (Exception ex) { FusionUpdaterPlugin.Logger.Error("Exception caught while running LabFusion updater!"); FusionUpdaterPlugin.Logger.Error(ex.ToString()); } } public static void UpdatePlugin() { if (!pluginNeedsUpdating) { return; } Directory.CreateDirectory(_dataDir); string text = Path.Combine(_dataDir, _updaterAppName); Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = executingAssembly.GetManifestResourceNames().First((string x) => x.Contains(_updaterAppName)); using (Stream stream = executingAssembly.GetManifestResourceStream(name)) { using FileStream destination = File.Create(text); stream.CopyTo(destination); } Process process = new Process(); process.StartInfo.FileName = text; process.StartInfo.Arguments = $"{new Version(0, 0, 0)} \"{FusionUpdaterPlugin.ModAssemblyPath}\" \"{FusionUpdaterPlugin.PluginAssemblyPath}\" true"; process.Start(); } } internal enum ExitCode { Success, UpToDate, Error }