Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of HachimiMusic v0.5.2
BepInEx/plugins/HJM-HachimiMusic/HJM.BoomboxPlaylist.dll
Decompiled 16 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Security.Cryptography; using BepInEx; using BepInEx.Configuration; using CustomBoomboxMusic; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using Microsoft.CodeAnalysis; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace HJM.BoomboxPlaylist { [BepInPlugin("hjm.boomboxplaylist", "HachimiMusic / 基米音乐汇", "0.5.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { internal sealed class Playback { internal bool Armed; internal AudioClip Clip; internal double EndsAt; internal int Cursor = -1; internal uint Revision; internal uint SessionSeed; internal bool HasSession; } public const string Id = "hjm.boomboxplaylist"; internal static Plugin Instance; private static readonly ConditionalWeakTable<BoomboxItem, Playback> States = new ConditionalWeakTable<BoomboxItem, Playback>(); private static readonly MethodInfo StartTrack = AccessTools.Method(typeof(BoomboxItem), "StartMusic", (Type[])null, (Type[])null); private static readonly MethodInfo NextClip = AccessTools.Method(typeof(CustomBoomboxMusic).GetNestedType("BoomboxPlayPatch", BindingFlags.NonPublic), "GetNextClip", (Type[])null, (Type[])null); private static readonly MethodInfo LocalPlay = AccessTools.Method(typeof(ModNetworkBehaviour), "Play", (Type[])null, (Type[])null); internal BoomboxKeys Keys; private Harmony harmony; private void Awake() { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Expected O, but got Unknown //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Expected O, but got Unknown //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Expected O, but got Unknown //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Expected O, but got Unknown //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Expected O, but got Unknown //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Expected O, but got Unknown //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Expected O, but got Unknown //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Expected O, but got Unknown //IL_0313: Expected O, but got Unknown //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Expected O, but got Unknown Instance = this; Keys = new BoomboxKeys(); Keys.Previous.performed += PreviousPressed; Keys.Next.performed += NextPressed; Keys.Random.performed += RandomPressed; ((LcInputActions)Keys).Enable(); harmony = new Harmony("hjm.boomboxplaylist"); BoomboxWeight.Install(harmony); VolumeCompat.Install(harmony); string[] array = new string[3] { "StartHost", "StartServer", "StartClient" }; foreach (string text in array) { harmony.Patch((MethodBase)AccessTools.Method(typeof(NetworkManager), text, (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SessionPlaylist), "NetworkStarted", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } harmony.Patch((MethodBase)AccessTools.Method(typeof(NetworkManager), "Shutdown", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SessionPlaylist), "NetworkStopping", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(StartOfRound), "OnShipLandedMiscEvents", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SessionPlaylist), "Landed", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(ModNetworkBehaviour), "Play", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "Started", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(ModNetworkBehaviour), "IsInBoomboxRange", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "SafeRange", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(CustomBoomboxMusic), "AnnouncePlaying", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "Announce", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(NextClip.DeclaringType, "Prefix", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "CorePower", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)StartTrack, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "AfterStart", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(BoomboxItem), "PocketItem", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "KeepPocketMusic", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(BoomboxItem), "Update", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "Refill", (Type[])null), new HarmonyMethod(typeof(Plugin), "Tick", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(BoomboxItem), "UseUpBatteries", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "KeepPowered", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"0.5.2 HachimiMusic: 5 lb boombox; aimed world-boombox controls, held/utility-slot volume, shared landing playlist and pocket playback."); } private void Update() { SessionPlaylist.Poll(); } internal void LogPlaylist(string message) { ((BaseUnityPlugin)this).Logger.LogInfo((object)message); } private void OnDestroy() { SessionPlaylist.Reset(); if (Keys != null) { Keys.Previous.performed -= PreviousPressed; Keys.Next.performed -= NextPressed; Keys.Random.performed -= RandomPressed; ((LcInputActions)Keys).Disable(); } if (harmony != null) { harmony.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void PreviousPressed(CallbackContext context) { HandleKey(-1); } private void NextPressed(CallbackContext context) { HandleKey(1); } private void RandomPressed(CallbackContext context) { HandleKey(0); } internal static bool CanControl(PlayerControllerB p) { if ((Object)(object)p != (Object)null && ((NetworkBehaviour)p).IsOwner && p.isPlayerControlled && !p.isPlayerDead && !p.inTerminalMenu && !p.isTypingChat && !p.inSpecialMenu && !p.inSpecialInteractAnimation && !p.isGrabbingObjectAnimation) { if (!((Object)(object)p.quickMenuManager == (Object)null)) { return !p.quickMenuManager.isMenuOpen; } return true; } return false; } private static void HandleKey(int direction) { WorldControls.Control(((Object)(object)GameNetworkManager.Instance == (Object)null) ? null : GameNetworkManager.Instance.localPlayerController, direction); } internal static BoomboxItem HeldBox(PlayerControllerB p) { if (!((Object)(object)p == (Object)null)) { GrabbableObject currentlyHeldObjectServer = p.currentlyHeldObjectServer; return (BoomboxItem)(object)((currentlyHeldObjectServer is BoomboxItem) ? currentlyHeldObjectServer : null); } return null; } internal static BoomboxItem CarriedBox(PlayerControllerB p) { if ((Object)(object)p == (Object)null) { return null; } GrabbableObject currentlyHeldObjectServer = p.currentlyHeldObjectServer; BoomboxItem val = (BoomboxItem)(object)((currentlyHeldObjectServer is BoomboxItem) ? currentlyHeldObjectServer : null); if ((Object)(object)val != (Object)null) { return val; } GrabbableObject itemOnlySlot = p.ItemOnlySlot; BoomboxItem val2 = (BoomboxItem)(object)((itemOnlySlot is BoomboxItem) ? itemOnlySlot : null); BoomboxItem val3 = val2; if ((Object)(object)val2 != (Object)null && val2.isPlayingMusic) { return val2; } if (p.ItemSlots != null) { GrabbableObject[] itemSlots = p.ItemSlots; foreach (GrabbableObject obj in itemSlots) { BoomboxItem val4 = (BoomboxItem)(object)((obj is BoomboxItem) ? obj : null); if (!((Object)(object)val4 == (Object)null)) { if (val4.isPlayingMusic) { return val4; } if ((Object)(object)val3 == (Object)null) { val3 = val4; } } } } return val3; } internal static IEnumerable<CodeInstruction> KeepPocketMusic(IEnumerable<CodeInstruction> instructions) { int replaced = 0; foreach (CodeInstruction instruction in instructions) { if (CodeInstructionExtensions.Calls(instruction, StartTrack)) { instruction.opcode = OpCodes.Call; instruction.operand = AccessTools.Method(typeof(Plugin), "PocketPower", (Type[])null, (Type[])null); replaced++; } yield return instruction; } if (replaced != 1) { throw new InvalidOperationException("Unexpected boombox PocketItem layout: " + replaced); } } private static void PocketPower(BoomboxItem box, bool startMusic, bool pitchDown) { } internal static bool CorePower(BoomboxItem __0, bool __1, ref bool __result) { if (!__1) { return true; } PowerStart(__0, startMusic: true); __result = false; return false; } internal static bool PowerStart(BoomboxItem __instance, bool startMusic) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown if (!startMusic) { return true; } if (!((NetworkBehaviour)__instance).IsOwner) { return false; } Playback playback = State(__instance); AudioFile clip; if (AudioManager.AudioClips.Count == 0) { clip = (AudioFile)NextClip.Invoke(null, new object[1] { __instance }); } else { if (!PlaylistReady()) { return false; } Align(playback, __instance); if (SessionPlaylist.Order.Count == 0) { return false; } clip = SessionPlaylist.Order[(playback.Cursor >= 0) ? playback.Cursor : 0]; } Play(__instance, clip); return false; } internal static void Navigate(BoomboxItem box, int direction) { if (!((Object)(object)box == (Object)null) && ((NetworkBehaviour)box).IsSpawned && ((NetworkBehaviour)box).IsOwner && box.isPlayingMusic) { Select(box, direction); } } internal static void WorldSelect(BoomboxItem box, int command) { if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer && WorldControls.IsWorld(box) && box.isPlayingMusic) { Select(box, command); } } private static void Select(BoomboxItem box, int direction) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (AudioManager.AudioClips.Count == 0) { Play(box, (AudioFile)NextClip.Invoke(null, new object[1] { box })); } else if (PlaylistReady()) { Playback playback = State(box); Align(playback, box); int count = SessionPlaylist.Order.Count; if (count != 0) { int index = ((direction == 0) ? SessionPlaylist.RandomIndex(box, playback.Cursor, playback.Revision) : ((Math.Max(0, playback.Cursor) + ((direction >= 0) ? 1 : (-1)) + count) % count)); Play(box, SessionPlaylist.Order[index]); } } } internal static void RandomTrack(BoomboxItem box) { if (!((Object)(object)box == (Object)null) && ((NetworkBehaviour)box).IsSpawned && ((NetworkBehaviour)box).IsOwner && box.isPlayingMusic && PlaylistReady()) { Select(box, 0); } } private static bool PlaylistReady() { if (SessionPlaylist.Ready) { return true; } if ((Object)(object)HUDManager.Instance != (Object)null) { HUDManager.Instance.DisplayTip("音箱歌单", "正在等待房主同步歌单,请稍后再试。", false, false, "LC_Tip1"); } return false; } private static void Align(Playback state, BoomboxItem box) { if (!state.HasSession || state.SessionSeed != SessionPlaylist.Seed) { state.HasSession = true; state.SessionSeed = SessionPlaylist.Seed; state.Cursor = -1; state.Revision = 0u; } if ((Object)(object)box.boomboxAudio != (Object)null) { state.Cursor = SessionPlaylist.Index(box.boomboxAudio.clip); } } private static void Play(BoomboxItem box, AudioFile clip) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ModNetworkBehaviour.Instance != (Object)null) { if (clip.Crc.HasValue) { ModNetworkBehaviour.Instance.StartPlayingMusicServerRpc(NetworkObjectReference.op_Implicit(((NetworkBehaviour)box).NetworkObject), clip.Crc.Value, clip.Name); } else if (clip.VanillaId.HasValue) { ModNetworkBehaviour.Instance.StartPlayingVanillaMusicServerRpc(NetworkObjectReference.op_Implicit(((NetworkBehaviour)box).NetworkObject), clip.VanillaId.Value); } } else { LocalPlay.Invoke(null, new object[2] { box, clip }); } } internal static Playback State(BoomboxItem box) { return States.GetOrCreateValue(box); } internal static void Refill(BoomboxItem __instance) { if ((Object)(object)__instance != (Object)null && ((GrabbableObject)__instance).insertedBattery != null) { ((GrabbableObject)__instance).insertedBattery.charge = 1f; ((GrabbableObject)__instance).insertedBattery.empty = false; } } internal static bool KeepPowered(BoomboxItem __instance) { Refill(__instance); return false; } internal static void Arm(BoomboxItem box) { if (!((Object)(object)box == (Object)null) && !((Object)(object)box.boomboxAudio == (Object)null) && !((Object)(object)box.boomboxAudio.clip == (Object)null)) { box.boomboxAudio.loop = false; Playback playback = State(box); playback.Clip = box.boomboxAudio.clip; playback.EndsAt = Time.realtimeSinceStartupAsDouble + (double)playback.Clip.length; playback.Armed = true; } } internal static void Started(BoomboxItem boombox, AudioFile clip) { Playback playback = State(boombox); if (SessionPlaylist.Ready) { Align(playback, boombox); playback.Cursor = SessionPlaylist.Index(clip.AudioClip); playback.Revision++; } Arm(boombox); } internal static void AfterStart(BoomboxItem __instance, bool startMusic) { if (!startMusic) { State(__instance).Armed = false; } else if ((Object)(object)ModNetworkBehaviour.Instance == (Object)null && __instance.isPlayingMusic) { Arm(__instance); } } internal static void Tick(BoomboxItem __instance) { if ((Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsSpawned || !((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayingMusic || !((GrabbableObject)__instance).isBeingUsed || AudioListener.pause || !((Component)__instance).gameObject.activeInHierarchy) { return; } AudioSource boomboxAudio = __instance.boomboxAudio; if (!((Object)(object)boomboxAudio == (Object)null) && ((Behaviour)boomboxAudio).enabled && !((Object)(object)boomboxAudio.clip == (Object)null) && !boomboxAudio.isPlaying) { Playback playback = State(__instance); if (playback.Armed && !((Object)(object)playback.Clip != (Object)(object)boomboxAudio.clip) && !(Time.realtimeSinceStartupAsDouble < playback.EndsAt)) { playback.Armed = false; ((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Track ended; requesting the next song in the session playlist."); Navigate(__instance, 1); } } } internal static bool SafeRange(BoomboxItem boombox, ref bool __result) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) __result = false; PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance == (Object)null) ? null : GameNetworkManager.Instance.localPlayerController); if ((Object)(object)val == (Object)null && (Object)(object)StartOfRound.Instance != (Object)null) { val = StartOfRound.Instance.localPlayerController; } if ((Object)(object)val == (Object)null || (Object)(object)boombox == (Object)null || (Object)(object)boombox.boomboxAudio == (Object)null) { return false; } PlayerControllerB val2 = (val.isPlayerDead ? val.spectatedPlayerScript : val); if ((Object)(object)val2 == (Object)null) { return false; } __result = Vector3.Distance(((Component)boombox.boomboxAudio).transform.position, ((Component)val2).transform.position) <= boombox.boomboxAudio.maxDistance || (((NetworkBehaviour)boombox).IsSpawned && (((NetworkBehaviour)boombox).IsOwner || ((NetworkBehaviour)boombox).OwnerClientId == val2.actualClientId)); return false; } internal static bool Announce(AudioFile audioFile) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)("正在播放:" + audioFile.Name)); if (CustomBoomboxMusic.Instance.DisplayNowPlaying && (Object)(object)HUDManager.Instance != (Object)null) { HUDManager.Instance.DisplayTip("正在播放", audioFile.Name, false, false, "LC_Tip1"); } return false; } } public sealed class BoomboxKeys : LcInputActions { [InputAction("<Keyboard>/pageUp", Name = "音箱:上一首 / Previous track")] public InputAction Previous { get; set; } [InputAction("<Keyboard>/pageDown", Name = "音箱:下一首 / Next track")] public InputAction Next { get; set; } [InputAction("<Keyboard>/r", Name = "音箱:随机切歌 / Random track")] public InputAction Random { get; set; } public BoomboxKeys() : base(new BepInPlugin("hjm.boomboxplaylist", "HachimiMusic / 基米音乐汇", "0.5.0")) { }//IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown } internal static class SessionPlaylist { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__Requested; public static HandleNamedMessageDelegate <1>__Received; public static Action<ulong> <2>__Connected; } private const string RequestMessage = "hjm.boomboxplaylist.seed.request.v1"; private const string SeedMessage = "hjm.boomboxplaylist.seed.v1"; private const int Protocol = 1; private static NetworkManager network; private static List<AudioFile> order; private static double nextRequest; internal static uint Seed { get; private set; } internal static bool Ready { get; private set; } internal static IReadOnlyList<AudioFile> Order => order; internal static void NetworkStarted(NetworkManager __instance, bool __result) { if (__result) { Bind(__instance); } } internal static void NetworkStopping(NetworkManager __instance) { if ((Object)(object)network == (Object)(object)__instance) { Reset(); } } internal static void Bind(NetworkManager manager) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown if (!((Object)(object)network == (Object)(object)manager)) { Reset(); network = manager; WorldControls.Bind(manager); CustomMessagingManager customMessagingManager = manager.CustomMessagingManager; object obj = <>O.<0>__Requested; if (obj == null) { HandleNamedMessageDelegate val = Requested; <>O.<0>__Requested = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("hjm.boomboxplaylist.seed.request.v1", (HandleNamedMessageDelegate)obj); CustomMessagingManager customMessagingManager2 = manager.CustomMessagingManager; object obj2 = <>O.<1>__Received; if (obj2 == null) { HandleNamedMessageDelegate val2 = Received; <>O.<1>__Received = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("hjm.boomboxplaylist.seed.v1", (HandleNamedMessageDelegate)obj2); manager.OnClientConnectedCallback += Connected; if (manager.IsServer) { Accept(NewSeed()); } else if (manager.IsConnectedClient) { Request(); } } } private static uint NewSeed() { byte[] array = new byte[4]; uint num; using (RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create()) { do { randomNumberGenerator.GetBytes(array); num = BitConverter.ToUInt32(array, 0); } while (Ready && num == Seed); } return num; } internal static void Landed() { if ((Object)(object)network == (Object)null || !network.IsListening || !network.IsServer) { return; } Accept(NewSeed()); foreach (ulong connectedClientsId in network.ConnectedClientsIds) { if (connectedClientsId != 0L) { SendSeed(connectedClientsId); } } } internal static void Poll() { if ((Object)(object)network != (Object)null && !network.IsServer && !Ready && network.IsConnectedClient && Time.realtimeSinceStartupAsDouble >= nextRequest) { Request(); } } internal static void Reset() { WorldControls.Reset(); if ((Object)(object)network != (Object)null) { network.OnClientConnectedCallback -= Connected; if (network.CustomMessagingManager != null) { network.CustomMessagingManager.UnregisterNamedMessageHandler("hjm.boomboxplaylist.seed.request.v1"); network.CustomMessagingManager.UnregisterNamedMessageHandler("hjm.boomboxplaylist.seed.v1"); } } network = null; order = null; Ready = false; Seed = 0u; nextRequest = 0.0; } private static void Connected(ulong id) { if ((Object)(object)network != (Object)null && !network.IsServer && id == network.LocalClientId) { Request(); } } private unsafe static void Request() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) nextRequest = Time.realtimeSinceStartupAsDouble + 2.0; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); try { int num = 1; ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); network.CustomMessagingManager.SendNamedMessage("hjm.boomboxplaylist.seed.request.v1", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void Requested(ulong sender, FastBufferReader reader) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)network == (Object)null) && network.IsServer && ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position >= 4) { int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); if (num == 1) { SendSeed(sender); } } } private unsafe static void SendSeed(ulong client) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(16, (Allocator)2, -1); try { int num = 1; ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); uint seed = Seed; ((FastBufferWriter)(ref val)).WriteValueSafe<uint>(ref seed, default(ForPrimitives)); num = Catalog().Count; ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); seed = CatalogHash(); ((FastBufferWriter)(ref val)).WriteValueSafe<uint>(ref seed, default(ForPrimitives)); network.CustomMessagingManager.SendNamedMessage("hjm.boomboxplaylist.seed.v1", client, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void Received(ulong sender, FastBufferReader reader) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)network == (Object)null || network.IsServer || sender != 0L || ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position < 16) { return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); uint num2 = default(uint); ((FastBufferReader)(ref reader)).ReadValueSafe<uint>(ref num2, default(ForPrimitives)); int num3 = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num3, default(ForPrimitives)); uint num4 = default(uint); ((FastBufferReader)(ref reader)).ReadValueSafe<uint>(ref num4, default(ForPrimitives)); if (num != 1 || num3 != Catalog().Count || num4 != CatalogHash()) { if ((Object)(object)Plugin.Instance != (Object)null) { Plugin.Instance.LogPlaylist("房主与本机歌曲文件或音箱设置不一致;请安装相同版本的歌单。"); } nextRequest = Time.realtimeSinceStartupAsDouble + 30.0; } else if (!Ready || Seed != num2) { Accept(num2); } } private static void Accept(uint seed) { Seed = seed; order = Shuffle(Catalog(), seed); Ready = true; if ((Object)(object)Plugin.Instance != (Object)null) { Plugin.Instance.LogPlaylist("Session playlist seed=" + seed + ", songs=" + order.Count + ", order=" + string.Join(",", order.Select((AudioFile f) => f.Crc.Value.ToString("x8")))); } } private static List<AudioFile> Catalog() { return (from f in AudioManager.AudioClips where f.Crc.HasValue group f by f.Crc.Value into g select g.First() into f orderby f.Crc.Value select f).ToList(); } private static uint CatalogHash() { uint num = 2166136261u; foreach (AudioFile item in Catalog()) { for (int i = 0; i < 4; i++) { num = (num ^ (byte)(item.Crc.Value >> i * 8)) * 16777619; } } return num; } internal static List<AudioFile> Shuffle(IEnumerable<AudioFile> files, uint seed) { List<AudioFile> list = files.OrderBy((AudioFile f) => f.Crc.Value).ToList(); uint state = ((seed == 0) ? 1831565813u : seed); for (int num = list.Count - 1; num > 0; num--) { int index = (int)(Next(ref state) % (uint)(num + 1)); AudioFile value = list[num]; list[num] = list[index]; list[index] = value; } return list; } private static uint Next(ref uint state) { state ^= state << 13; state ^= state >> 17; state ^= state << 5; return state; } internal static int Index(AudioClip clip) { if (order != null) { return order.FindIndex((AudioFile f) => (Object)(object)f.AudioClip == (Object)(object)clip); } return -1; } internal static int RandomIndex(BoomboxItem box, int current, uint revision) { if (order.Count < 2) { return 0; } uint state = Seed ^ (uint)(int)((NetworkBehaviour)box).NetworkObjectId ^ (uint)(int)(((NetworkBehaviour)box).NetworkObjectId >> 32) ^ (uint)((int)(revision + 1) * -1640531527); if (state == 0) { state = 1831565813u; } return (Math.Max(0, current) + 1 + (int)(Next(ref state) % (uint)(order.Count - 1))) % order.Count; } } internal static class WorldControls { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__Receive; } private const string Message = "hjm.hachimimusic.world-control.v1"; private static NetworkManager network; private static readonly FieldInfo InteractionMask = AccessTools.Field(typeof(PlayerControllerB), "interactableObjectsMask"); private static int Mask(PlayerControllerB player) { return (int)InteractionMask.GetValue(player); } internal static void Bind(NetworkManager manager) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown network = manager; CustomMessagingManager customMessagingManager = manager.CustomMessagingManager; object obj = <>O.<0>__Receive; if (obj == null) { HandleNamedMessageDelegate val = Receive; <>O.<0>__Receive = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("hjm.hachimimusic.world-control.v1", (HandleNamedMessageDelegate)obj); } internal static void Reset() { if ((Object)(object)network != (Object)null && network.CustomMessagingManager != null) { network.CustomMessagingManager.UnregisterNamedMessageHandler("hjm.hachimimusic.world-control.v1"); } network = null; } internal static bool IsWorld(BoomboxItem box) { if ((Object)(object)box != (Object)null && ((NetworkBehaviour)box).IsSpawned && !((GrabbableObject)box).isHeld && !((GrabbableObject)box).isPocketed) { return (Object)(object)((GrabbableObject)box).playerHeldBy == (Object)null; } return false; } internal static float Range(PlayerControllerB player) { return Mathf.Clamp(player.grabDistance, 1f, 5f); } internal static BoomboxItem AimedBox(PlayerControllerB player) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)player.gameplayCamera == (Object)null) { return null; } Transform transform = ((Component)player.gameplayCamera).transform; RaycastHit val = default(RaycastHit); if (!Physics.Raycast(transform.position, transform.forward, ref val, Range(player), Mask(player), (QueryTriggerInteraction)0)) { return null; } BoomboxItem componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<BoomboxItem>(); if (!IsWorld(componentInParent)) { return null; } return componentInParent; } internal static BoomboxItem Target(PlayerControllerB player, bool random) { BoomboxItem val = AimedBox(player); if ((Object)(object)val != (Object)null) { return val; } if (!random) { return Plugin.CarriedBox(player); } return Plugin.HeldBox(player); } internal static void Control(PlayerControllerB player, int command) { if (!Plugin.CanControl(player)) { return; } BoomboxItem val = Target(player, command == 0); if (!((Object)(object)val == (Object)null) && val.isPlayingMusic) { if (IsWorld(val)) { Request(val, command); } else if (command == 0) { Plugin.RandomTrack(val); } else { Plugin.Navigate(val, command); } } } internal unsafe static void Request(BoomboxItem box, int command) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)network == (Object)null || !network.IsListening || (Object)(object)box == (Object)null || !((NetworkBehaviour)box).IsSpawned || command < -1 || command > 1) { return; } if (network.IsServer) { Apply(network.LocalClientId, ((NetworkBehaviour)box).NetworkObjectId, command); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(12, (Allocator)2, -1); try { ulong networkObjectId = ((NetworkBehaviour)box).NetworkObjectId; ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref command, default(ForPrimitives)); network.CustomMessagingManager.SendNamedMessage("hjm.hachimimusic.world-control.v1", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void Receive(ulong sender, FastBufferReader reader) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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) if (!((Object)(object)network == (Object)null) && network.IsServer && ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position >= 12) { ulong id = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref id, default(ForPrimitives)); int command = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref command, default(ForPrimitives)); Apply(sender, id, command); } } internal static bool Apply(ulong sender, ulong id, int command) { if ((Object)(object)network == (Object)null || !network.IsServer || command < -1 || command > 1) { return false; } if (!network.SpawnManager.SpawnedObjects.TryGetValue(id, out var value)) { return false; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null) { return false; } PlayerControllerB player = null; PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if ((Object)(object)val != (Object)null && val.actualClientId == sender) { player = val; break; } } BoomboxItem component = ((Component)value).GetComponent<BoomboxItem>(); if (!CanReach(player, component) || !component.isPlayingMusic) { return false; } Plugin.WorldSelect(component, command); return true; } internal static bool CanReach(PlayerControllerB player, BoomboxItem box) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || !player.isPlayerControlled || player.isPlayerDead || !IsWorld(box)) { return false; } Vector3 val = (((Object)(object)player.gameplayCamera == (Object)null) ? (((Component)player).transform.position + Vector3.up * 1.6f) : ((Component)player.gameplayCamera).transform.position); Collider componentInChildren = ((Component)box).GetComponentInChildren<Collider>(); Vector3 val2; if (!((Object)(object)componentInChildren == (Object)null)) { Bounds bounds = componentInChildren.bounds; val2 = ((Bounds)(ref bounds)).center; } else { val2 = ((Component)box).transform.position; } Vector3 val3 = val2; if (Vector3.Distance(val, val3) > Range(player) + 0.25f) { return false; } RaycastHit val4 = default(RaycastHit); if (Physics.Linecast(val, val3, ref val4, Mask(player), (QueryTriggerInteraction)0)) { return (Object)(object)((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<BoomboxItem>() == (Object)(object)box; } return true; } } internal static class VolumeCompat { private static FieldInfo looking; private static FieldInfo grabbing; private static FieldInfo boombox; private static FieldInfo enabled; private static FieldInfo multiplier; internal static void Install(Harmony harmony) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00b2: Expected O, but got Unknown Type type = Type.GetType("ObjectVolumeController.Patcher.ObjectsManager, ObjectVolumeController", throwOnError: true); Type? type2 = Type.GetType("ObjectVolumeController.Config.ConfigSettings, ObjectVolumeController", throwOnError: true); Type type3 = Type.GetType("ObjectVolumeController.AudioPlayers.AudioPlayerTypeBase, ObjectVolumeController", throwOnError: true); looking = AccessTools.Field(type, "lookingAtObjectType"); grabbing = AccessTools.Field(type, "grabbingObjectType"); boombox = AccessTools.Field(type, "boomboxItems"); enabled = AccessTools.Field(type2, "enableVolumeControllerBoombox"); multiplier = AccessTools.Field(type3, "currentVolumeMultiplier"); harmony.Patch((MethodBase)AccessTools.Method(type, "OnPressVolumeKey", (Type[])null, (Type[])null), new HarmonyMethod(typeof(VolumeCompat), "Prepare", (Type[])null), new HarmonyMethod(typeof(VolumeCompat), "Feedback", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static bool Prepare(out float __state) { __state = float.NaN; PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance == (Object)null) ? null : GameNetworkManager.Instance.localPlayerController); if ((Object)(object)val == (Object)null && (Object)(object)StartOfRound.Instance != (Object)null) { val = StartOfRound.Instance.localPlayerController; } if ((Object)(object)Plugin.HeldBox(val) == (Object)null) { return true; } if (!Plugin.CanControl(val)) { return false; } if (!((ConfigEntry<bool>)enabled.GetValue(null)).Value) { return true; } object value = boombox.GetValue(null); if (value == null) { return true; } looking.SetValue(null, null); grabbing.SetValue(null, value); __state = (float)multiplier.GetValue(value); return true; } private static void Feedback(float __state) { if (float.IsNaN(__state)) { return; } object value = boombox.GetValue(null); if (value != null) { float num = (float)multiplier.GetValue(value); if (num != __state && (Object)(object)HUDManager.Instance != (Object)null) { HUDManager.Instance.DisplayTip("音箱音量", Mathf.RoundToInt(num * 100f) + "%", false, false, "LC_Tip1"); } } } } internal static class BoomboxWeight { private const float ItemWeight = 1.0476191f; internal static void Install(Harmony harmony) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown harmony.Patch((MethodBase)AccessTools.Method(typeof(StartOfRound), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(BoomboxWeight), "CatalogReady", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(BoomboxItem), "Start", (Type[])null, (Type[])null), new HarmonyMethod(typeof(BoomboxWeight), "Spawned", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static void CatalogReady(StartOfRound __instance) { if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.allItemsList == (Object)null || __instance.allItemsList.itemsList == null) { return; } foreach (Item items in __instance.allItemsList.itemsList) { if ((Object)(object)items != (Object)null && (Object)(object)items.spawnPrefab != (Object)null && (Object)(object)items.spawnPrefab.GetComponent<BoomboxItem>() != (Object)null) { items.weight = 1.0476191f; } } } private static void Spawned(BoomboxItem __instance) { if ((Object)(object)__instance != (Object)null && (Object)(object)((GrabbableObject)__instance).itemProperties != (Object)null) { ((GrabbableObject)__instance).itemProperties.weight = 1.0476191f; } } } }