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 CartRadio v1.0.0
plugins/CartRadio/CartRadio.dll
Decompiled 10 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Networking; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("CartRadio")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CartRadio")] [assembly: AssemblyTitle("CartRadio")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CartRadio { public sealed class CartSpeaker : MonoBehaviour { public AudioSource Source { get; private set; } public PhysGrabCart Cart { get; private set; } private void Awake() { Cart = ((Component)this).GetComponentInParent<PhysGrabCart>(); Source = ((Component)this).gameObject.AddComponent<AudioSource>(); Source.playOnAwake = false; Source.spatialBlend = 1f; Source.dopplerLevel = 0f; Source.rolloffMode = (AudioRolloffMode)1; Source.minDistance = 1.5f; Source.maxDistance = 22f; Source.loop = false; Source.priority = 160; Source.volume = 0.55f; } public void ApplyTimeline(RadioState state, double clock, bool forceSeek) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 Source.volume = state.Volume; if (!Object.op_Implicit((Object)(object)Source.clip) || (int)Source.clip.loadState != 2) { return; } float num = (float)state.PositionAt(clock); if (num >= Source.clip.length) { Source.Stop(); return; } if (forceSeek || Mathf.Abs(Source.time - num) > 0.35f) { Source.time = Mathf.Clamp(num, 0f, Mathf.Max(0f, Source.clip.length - 0.02f)); } if (state.Playing && !Source.isPlaying) { Source.Play(); } else if (!state.Playing && Source.isPlaying) { Source.Pause(); } } } public sealed class Track { public string Id; public string Name; public string Path; } public static class MusicLibrary { public static Track[] Scan(string folder, CancellationToken cancellation) { Directory.CreateDirectory(folder); List<Track> list = new List<Track>(); long num = 0L; foreach (string item in Directory.GetFiles(folder).OrderBy<string, string>((string p) => p, StringComparer.Ordinal)) { cancellation.ThrowIfCancellationRequested(); string text = Path.GetExtension(item).ToLowerInvariant(); if (text != ".wav" && text != ".mp3" && text != ".ogg") { continue; } FileInfo fileInfo = new FileInfo(item); if ((fileInfo.Attributes & FileAttributes.ReparsePoint) != FileAttributes.None || fileInfo.Length == 0L || fileInfo.Length > 20971520) { continue; } if (list.Count >= 64 || num + fileInfo.Length > 268435456) { break; } num += fileInfo.Length; using FileStream inputStream = File.OpenRead(item); using SHA256 sHA = SHA256.Create(); string id = BitConverter.ToString(sHA.ComputeHash(inputStream)).Replace("-", "").ToLowerInvariant(); if (!list.Any((Track t) => t.Id == id)) { list.Add(new Track { Id = id, Name = Path.GetFileNameWithoutExtension(item), Path = fileInfo.FullName }); } } return list.ToArray(); } } [BepInPlugin("pl.cart.radio", "Cart Radio", "1.0.0")] public sealed class Plugin : BaseUnityPlugin, IOnEventCallback { private Track[] tracks = Array.Empty<Track>(); private Task<Track[]> scan; private readonly CancellationTokenSource cancellation = new CancellationTokenSource(); private RadioState state = new RadioState(); private readonly Dictionary<int, float> requestTimes = new Dictionary<int, float>(); private readonly Dictionary<int, float> helloTimes = new Dictionary<int, float>(); private PhysGrabCart[] carts = Array.Empty<PhysGrabCart>(); private PhysGrabCart nearest; private PhysGrabCart panelCart; private PhysGrabCart soloCart; private CartSpeaker activeSpeaker; private AudioClip clip; private string loadedId = ""; private string loadingId = ""; private string failedId = ""; private Coroutine loader; private float cartScanAt; private float syncAt; private float broadcastAt; private float requestAt; private float statusUntil; private Room room; private int masterId; private bool haveSnapshot; private ConfigEntry<float> personalVolume; private ConfigEntry<Key> panelKey; private string status = "Wczytywanie biblioteki muzyki..."; private bool disposed; private static readonly FieldInfo DisabledField = AccessTools.Field(typeof(PlayerAvatar), "isDisabled"); private static readonly FieldInfo MenuStateField = AccessTools.Field(typeof(MenuManager), "currentMenuState"); private bool panelOpen; private CursorLockMode oldLock; private bool oldVisible; private Vector2 scroll; private float lastButtonAt = -1f; private readonly List<InputKey> noKeys = new List<InputKey>(); private GUIStyle titleStyle; private GUIStyle labelStyle; private bool Networked { get { if (Object.op_Implicit((Object)(object)GameManager.instance) && PhotonNetwork.InRoom) { return SemiFunc.IsMultiplayer(); } return false; } } private bool IsHost { get { if (Networked) { return PhotonNetwork.IsMasterClient; } return true; } } private double Clock { get { if (!Networked) { return Time.realtimeSinceStartupAsDouble; } return PhotonNetwork.Time; } } private bool InGameplay { get { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 if (Object.op_Implicit((Object)(object)GameDirector.instance)) { return (int)GameDirector.instance.currentState == 2; } return false; } } private bool OtherMenuOpen { get { if (SemiFunc.NoTextInputsActive()) { if (Object.op_Implicit((Object)(object)MenuManager.instance) && MenuStateField != null) { return (int)MenuStateField.GetValue(MenuManager.instance) == 0; } return false; } return true; } } private void Awake() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown personalVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "PersonalVolume", 0.8f, new ConfigDescription("Your local listening volume. 0 mutes the radio only for you.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); panelKey = ((BaseUnityPlugin)this).Config.Bind<Key>("Controls", "PanelKey", (Key)99, "Open radio controls near a cart."); string folder = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "Music"); scan = Task.Run(() => MusicLibrary.Scan(folder, cancellation.Token)); PhotonNetwork.AddCallbackTarget((object)this); SceneManager.activeSceneChanged += SceneChanged; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Cart Radio loaded. Music folder: " + folder)); } private void SceneChanged(Scene oldScene, Scene nextScene) { ClosePanel(); if (Object.op_Implicit((Object)(object)activeSpeaker)) { activeSpeaker.Source.Stop(); } activeSpeaker = null; soloCart = null; carts = Array.Empty<PhysGrabCart>(); nearest = null; cartScanAt = 0f; if (IsHost) { state.Playing = false; state.CartViewId = 0; state.PositionSeconds = 0.0; state.ServerTime = Clock; state.Revision++; Broadcast(); } haveSnapshot = IsHost; } private static bool Alive(PlayerAvatar player) { if (Object.op_Implicit((Object)(object)player) && DisabledField != null) { return !(bool)DisabledField.GetValue(player); } return false; } private void Update() { if (disposed) { return; } if (scan != null && scan.IsCompleted) { if (scan.Status == TaskStatus.RanToCompletion) { tracks = scan.Result; SetStatus("Wczytano utworów: " + tracks.Length); } else { ((BaseUnityPlugin)this).Logger.LogError((object)scan.Exception); SetStatus("Nie udało się odczytać folderu Music."); } scan = null; } UpdateRoom(); if (Time.unscaledTime >= cartScanAt) { carts = Object.FindObjectsOfType<PhysGrabCart>(); PhysGrabCart[] array = carts; foreach (PhysGrabCart cart in array) { EnsureSpeaker(cart); } cartScanAt = Time.unscaledTime + 0.5f; } PlayerAvatar local = PlayerAvatar.instance; nearest = ((InGameplay && Alive(local)) ? (from c in carts where Object.op_Implicit((Object)(object)c) && ((Component)c).gameObject.activeInHierarchy && Distance(local, c) <= 3f orderby Distance(local, c) select c).FirstOrDefault() : null); UpdatePanel(); if (Time.unscaledTime >= syncAt) { syncAt = Time.unscaledTime + 0.2f; SyncAudio(force: false); } if (IsHost && state.Playing && Object.op_Implicit((Object)(object)clip) && loadedId == state.TrackId && state.PositionAt(Clock) >= (double)clip.length) { Advance(1); } } private static float Distance(PlayerAvatar player, PhysGrabCart cart) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) return Vector3.Distance(((Component)player).transform.position, ((Component)cart).transform.position); } private void UpdateRoom() { Room val = (Networked ? PhotonNetwork.CurrentRoom : null); if (room != val) { room = val; masterId = 0; state = new RadioState(); haveSnapshot = IsHost; requestTimes.Clear(); helloTimes.Clear(); if (Object.op_Implicit((Object)(object)activeSpeaker)) { activeSpeaker.Source.Stop(); } activeSpeaker = null; soloCart = null; } if (!Networked) { return; } int actorNumber = PhotonNetwork.MasterClient.ActorNumber; if (masterId != actorNumber) { masterId = actorNumber; requestTimes.Clear(); helloTimes.Clear(); if (IsHost) { state.Revision++; Broadcast(); } else { haveSnapshot = false; } } if (IsHost && Time.unscaledTime >= broadcastAt) { broadcastAt = Time.unscaledTime + 3f; Broadcast(); } else if (!IsHost && !haveSnapshot && Time.unscaledTime >= requestAt) { requestAt = Time.unscaledTime + 3f; Send(new object[2] { "pl.cart-radio.v1", "hello" }, (ReceiverGroup)2); } } private void Send(object[] payload, ReceiverGroup receivers) { //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) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown if (Networked) { PhotonNetwork.RaiseEvent((byte)178, (object)payload, new RaiseEventOptions { Receivers = receivers }, SendOptions.SendReliable); } } private void Broadcast(int targetActor = 0) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0014: 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_001b: 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 (Networked && PhotonNetwork.IsMasterClient) { object obj; if (targetActor <= 0) { obj = (object)new RaiseEventOptions { Receivers = (ReceiverGroup)0 }; } else { RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { targetActor }; obj = val; } RaiseEventOptions val2 = (RaiseEventOptions)obj; PhotonNetwork.RaiseEvent((byte)178, (object)RadioProtocol.Encode(state), val2, SendOptions.SendReliable); } } public void OnEvent(EventData incoming) { if (!Networked || incoming.Code != 178 || !(incoming.CustomData is object[] array) || array.Length < 2 || !(array[0] is string text) || text != "pl.cart-radio.v1" || !(array[1] is string text2)) { return; } if (text2 == "state") { if (incoming.Sender == PhotonNetwork.MasterClient.ActorNumber && !IsHost && RadioProtocol.TryDecode(array, out var radioState) && (!haveSnapshot || radioState.Revision >= state.Revision)) { bool num = !haveSnapshot || radioState.Revision != state.Revision; state = radioState; haveSnapshot = true; if (num) { SyncAudio(force: true); } } } else if (text2 == "hello" && array.Length == 2 && IsHost) { if (!Limited(helloTimes, incoming.Sender, 2f)) { Broadcast(incoming.Sender); } } else if (text2 == "request" && IsHost && array.Length == 6 && array[2] is string operation && array[3] is int num2 && array[4] is string { Length: <=128 } text3 && array[5] is float volume && !Limited(requestTimes, incoming.Sender, 0.2f)) { PhotonView val = PhotonView.Find(num2); PhysGrabCart val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<PhysGrabCart>() : null); PlayerAvatar player = (Object.op_Implicit((Object)(object)GameDirector.instance) ? ((IEnumerable<PlayerAvatar>)GameDirector.instance.PlayerList).FirstOrDefault((Func<PlayerAvatar, bool>)((PlayerAvatar p) => Object.op_Implicit((Object)(object)p) && Object.op_Implicit((Object)(object)p.photonView) && p.photonView.OwnerActorNr == incoming.Sender)) : null); if (InGameplay && Object.op_Implicit((Object)(object)val2) && Alive(player) && !(Distance(player, val2) > 3.75f)) { Handle(operation, val2, text3, volume); } } } private bool Limited(Dictionary<int, float> times, int actor, float delay) { if (times.TryGetValue(actor, out var value) && Time.unscaledTime - value < delay) { return true; } if (times.Count > 64) { times.Clear(); } times[actor] = Time.unscaledTime; return false; } private void Request(string operation, string trackId = "", float volume = 0f) { if (!Object.op_Implicit((Object)(object)panelCart) || !Alive(PlayerAvatar.instance) || Distance(PlayerAvatar.instance, panelCart) > 3f || Time.unscaledTime - lastButtonAt < 0.25f) { return; } lastButtonAt = Time.unscaledTime; if (IsHost) { Handle(operation, panelCart, trackId, volume); return; } PhotonView component = ((Component)panelCart).GetComponent<PhotonView>(); if (!Object.op_Implicit((Object)(object)component)) { SetStatus("Wózek nie ma identyfikatora sieciowego."); return; } Send(new object[6] { "pl.cart-radio.v1", "request", operation, component.ViewID, trackId, volume }, (ReceiverGroup)2); SetStatus("Wysłano polecenie do hosta."); } private void Handle(string operation, PhysGrabCart cart, string trackId, float volume) { if ((operation != "play" && operation != "pause" && operation != "stop" && operation != "next" && operation != "previous" && operation != "select" && operation != "volume") || (operation == "select" && !tracks.Any((Track t) => t.Id == trackId)) || (operation == "volume" && (float.IsNaN(volume) || float.IsInfinity(volume)))) { return; } if (tracks.Length == 0 && operation != "stop") { SetStatus("Folder Music jest pusty albo jeszcze się wczytuje."); return; } RadioState next = state.Copy(); next.PositionSeconds = state.PositionAt(Clock); next.ServerTime = Clock; PhotonView component = ((Component)cart).GetComponent<PhotonView>(); next.CartViewId = ((Networked && Object.op_Implicit((Object)(object)component)) ? component.ViewID : 0); soloCart = cart; if (operation == "select") { next.TrackId = trackId; next.PositionSeconds = 0.0; next.Playing = true; } if (operation == "next" || operation == "previous") { int num = Array.FindIndex(tracks, (Track t) => t.Id == next.TrackId); int num2 = ((operation == "next") ? 1 : (-1)); int num3 = ((num >= 0) ? ((num + num2 + tracks.Length) % tracks.Length) : 0); next.TrackId = tracks[num3].Id; next.PositionSeconds = 0.0; next.Playing = true; } if (operation == "play") { if (!tracks.Any((Track t) => t.Id == next.TrackId)) { next.TrackId = tracks[0].Id; next.PositionSeconds = 0.0; } if (Object.op_Implicit((Object)(object)clip) && loadedId == next.TrackId && next.PositionSeconds >= (double)clip.length) { next.PositionSeconds = 0.0; } next.Playing = true; } if (operation == "pause") { next.Playing = false; } if (operation == "stop") { next.Playing = false; next.PositionSeconds = 0.0; } if (operation == "volume") { next.Volume = Mathf.Clamp01(volume); } next.Revision++; state = next; failedId = ""; SyncAudio(force: true); Broadcast(); } private void Advance(int direction) { PhysGrabCart val = ResolveCart(); if (Object.op_Implicit((Object)(object)val)) { Handle((direction > 0) ? "next" : "previous", val, "", 0f); return; } state.Playing = false; state.Revision++; Broadcast(); } private PhysGrabCart ResolveCart() { if (!Networked) { return soloCart; } if (state.CartViewId <= 0) { return null; } PhotonView val = PhotonView.Find(state.CartViewId); if (!Object.op_Implicit((Object)(object)val)) { return null; } return ((Component)val).GetComponent<PhysGrabCart>(); } private CartSpeaker EnsureSpeaker(PhysGrabCart cart) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0046: 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_0067: Unknown result type (might be due to invalid IL or missing references) CartSpeaker componentInChildren = ((Component)cart).GetComponentInChildren<CartSpeaker>(); if (Object.op_Implicit((Object)(object)componentInChildren)) { return componentInChildren; } GameObject val = new GameObject("Cart Radio Speaker"); val.transform.SetParent(((Component)cart).transform, false); val.transform.position = (Object.op_Implicit((Object)(object)cart.handlePoint) ? cart.handlePoint.position : (((Component)cart).transform.position + Vector3.up)); componentInChildren = val.AddComponent<CartSpeaker>(); RadioModel.Build(val.transform, cart); return componentInChildren; } private void SyncAudio(bool force) { if (!InGameplay) { if (Object.op_Implicit((Object)(object)activeSpeaker)) { activeSpeaker.Source.Pause(); } return; } PhysGrabCart val = ResolveCart(); if (!Object.op_Implicit((Object)(object)val)) { if (Object.op_Implicit((Object)(object)activeSpeaker)) { activeSpeaker.Source.Stop(); } activeSpeaker = null; return; } if (!Object.op_Implicit((Object)(object)activeSpeaker) || (Object)(object)activeSpeaker.Cart != (Object)(object)val) { if (Object.op_Implicit((Object)(object)activeSpeaker)) { activeSpeaker.Source.Stop(); } activeSpeaker = EnsureSpeaker(val); force = true; } if (string.IsNullOrEmpty(state.TrackId)) { activeSpeaker.Source.Stop(); return; } Track track = tracks.FirstOrDefault((Track t) => t.Id == state.TrackId); if (track == null) { activeSpeaker.Source.Stop(); if (scan == null && failedId != state.TrackId) { failedId = state.TrackId; SetStatus("Brakuje pliku aktualnego utworu. Skopiuj ten sam plik od hosta do Music."); } } else if (loadedId != state.TrackId) { activeSpeaker.Source.Stop(); if (loadingId != state.TrackId && failedId != state.TrackId) { if (loader != null) { ((MonoBehaviour)this).StopCoroutine(loader); } loadingId = state.TrackId; loader = ((MonoBehaviour)this).StartCoroutine(LoadTrack(track)); } } else { if ((Object)(object)activeSpeaker.Source.clip != (Object)(object)clip) { activeSpeaker.Source.clip = clip; force = true; } activeSpeaker.ApplyTimeline(state, Clock, force); activeSpeaker.Source.volume = state.Volume * personalVolume.Value; } } private IEnumerator LoadTrack(Track track) { SetStatus("Wczytywanie: " + track.Name); string text = Path.GetExtension(track.Path).ToLowerInvariant(); AudioType val = (AudioType)((text == ".ogg") ? 14 : ((text == ".mp3") ? 13 : 20)); UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(track.Path).AbsoluteUri, val); try { request.timeout = 25; yield return request.SendWebRequest(); loadingId = ""; loader = null; if ((int)request.result != 1) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Audio decode failed for " + track.Name + ": " + request.error)); FailTrack(track, "Nie można odtworzyć pliku: " + track.Name); yield break; } AudioClip content = DownloadHandlerAudioClip.GetContent(request); if (!Object.op_Implicit((Object)(object)content) || content.length <= 0f || content.length > 900f || (long)content.samples * (long)content.channels > 32000000) { if (Object.op_Implicit((Object)(object)content)) { Object.Destroy((Object)(object)content); } FailTrack(track, "Plik jest niepoprawny lub przekracza limit długości / pamięci."); yield break; } if (state.TrackId != track.Id) { Object.Destroy((Object)(object)content); yield break; } if (Object.op_Implicit((Object)(object)activeSpeaker)) { activeSpeaker.Source.Stop(); activeSpeaker.Source.clip = null; } if (Object.op_Implicit((Object)(object)clip)) { Object.Destroy((Object)(object)clip); } clip = content; loadedId = track.Id; failedId = ""; SyncAudio(force: true); SetStatus("Gotowe: " + track.Name); } finally { ((IDisposable)request)?.Dispose(); } } private void SetStatus(string text) { status = text; statusUntil = Time.unscaledTime + 10f; } private void FailTrack(Track track, string message) { failedId = track.Id; SetStatus(message); if (IsHost && state.TrackId == track.Id) { state.Playing = false; state.PositionSeconds = 0.0; state.ServerTime = Clock; state.Revision++; Broadcast(); } } private void OnDestroy() { disposed = true; ClosePanel(); cancellation.Cancel(); PhotonNetwork.RemoveCallbackTarget((object)this); SceneManager.activeSceneChanged -= SceneChanged; if (loader != null) { ((MonoBehaviour)this).StopCoroutine(loader); } CartSpeaker[] array = Object.FindObjectsOfType<CartSpeaker>(); for (int i = 0; i < array.Length; i++) { Object.Destroy((Object)(object)((Component)array[i]).gameObject); } if (Object.op_Implicit((Object)(object)clip)) { Object.Destroy((Object)(object)clip); } } private void UpdatePanel() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; if (panelOpen && (!Object.op_Implicit((Object)(object)panelCart) || !InGameplay || !Alive(PlayerAvatar.instance) || Distance(PlayerAvatar.instance, panelCart) > 3f || OtherMenuOpen || !Application.isFocused)) { ClosePanel(); } if (current != null && (int)panelKey.Value != 0 && ((ButtonControl)current[panelKey.Value]).wasPressedThisFrame) { if (panelOpen) { ClosePanel(); } else if (Object.op_Implicit((Object)(object)nearest) && !OtherMenuOpen && Application.isFocused) { panelCart = nearest; oldLock = Cursor.lockState; oldVisible = Cursor.visible; panelOpen = true; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } } if (panelOpen && current != null && ((ButtonControl)current.escapeKey).wasPressedThisFrame) { ClosePanel(); } if (panelOpen && Object.op_Implicit((Object)(object)InputManager.instance)) { InputManager.instance.DisableMovement(0.1f); InputManager.instance.DisableAiming(0.1f); InputManager.instance.DisableControlsExcept(0.1f, noKeys); } } private void LateUpdate() { if (panelOpen) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } } private void ClosePanel() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (panelOpen) { panelOpen = false; panelCart = null; bool otherMenuOpen = OtherMenuOpen; Cursor.lockState = (CursorLockMode)((!otherMenuOpen) ? ((int)oldLock) : 0); Cursor.visible = otherMenuOpen || oldVisible; } } private void OnDisable() { ClosePanel(); } private void OnGUI() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_0048: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_04cd: Unknown result type (might be due to invalid IL or missing references) //IL_04f1: Unknown result type (might be due to invalid IL or missing references) //IL_04f6: Unknown result type (might be due to invalid IL or missing references) //IL_05bc: Unknown result type (might be due to invalid IL or missing references) //IL_05c1: Unknown result type (might be due to invalid IL or missing references) if (!InGameplay || !Alive(PlayerAvatar.instance)) { return; } if (titleStyle == null) { titleStyle = new GUIStyle(GUI.skin.label) { fontSize = 23, fontStyle = (FontStyle)1, richText = false }; labelStyle = new GUIStyle(GUI.skin.label) { wordWrap = true, richText = false, fontSize = 14 }; } if (!panelOpen) { if (Object.op_Implicit((Object)(object)nearest) && !OtherMenuOpen) { GUI.Box(new Rect((float)Screen.width / 2f - 170f, (float)(Screen.height - 115), 340f, 35f), "[" + ((object)panelKey.Value/*cast due to .constrained prefix*/).ToString() + "] Radio w wózku"); } return; } float num = Mathf.Min(540, Screen.width - 24); float num2 = Mathf.Min(610, Screen.height - 24); Rect val = default(Rect); ((Rect)(ref val))..ctor(((float)Screen.width - num) / 2f, ((float)Screen.height - num2) / 2f, num, num2); GUI.Box(val, ""); GUILayout.BeginArea(new Rect(((Rect)(ref val)).x + 18f, ((Rect)(ref val)).y + 12f, ((Rect)(ref val)).width - 36f, ((Rect)(ref val)).height - 24f)); GUILayout.Label("RADIO W WÓZKU", titleStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label("Wspólna muzyka • MP3 / OGG / WAV", labelStyle, Array.Empty<GUILayoutOption>()); GUILayout.Space(10f); Track track = tracks.FirstOrDefault((Track t) => t.Id == state.TrackId); GUILayout.Label((track != null) ? track.Name : (string.IsNullOrEmpty(state.TrackId) ? "Wybierz utwór" : "Brak pliku utworu u Ciebie"), labelStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label(state.Playing ? "Odtwarzanie" : "Pauza / zatrzymano", labelStyle, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Poprzedni", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) })) { Request("previous"); } if (GUILayout.Button(state.Playing ? "Pauza" : "Odtwórz", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) })) { Request(state.Playing ? "pause" : "play"); } if (GUILayout.Button("Następny", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) })) { Request("next"); } if (GUILayout.Button("Stop", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) })) { Request("stop"); } GUILayout.EndHorizontal(); GUILayout.Space(8f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Głośność radia: " + Mathf.RoundToInt(state.Volume * 100f) + "%", labelStyle, Array.Empty<GUILayoutOption>()); if (GUILayout.Button("−", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(42f) })) { Request("volume", "", state.Volume - 0.1f); } if (GUILayout.Button("+", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(42f) })) { Request("volume", "", state.Volume + 0.1f); } GUILayout.EndHorizontal(); GUILayout.Label("Twoja głośność: " + Mathf.RoundToInt(personalVolume.Value * 100f) + "%", labelStyle, Array.Empty<GUILayoutOption>()); float num3 = GUILayout.HorizontalSlider(personalVolume.Value, 0f, 1f, Array.Empty<GUILayoutOption>()); if (Mathf.Abs(num3 - personalVolume.Value) > 0.015f) { personalVolume.Value = num3; } GUILayout.Space(8f); GUILayout.Label("Biblioteka: " + tracks.Length + " utworów", labelStyle, Array.Empty<GUILayoutOption>()); scroll = GUILayout.BeginScrollView(scroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(Mathf.Max(70f, num2 - 380f)) }); Track[] array = tracks; foreach (Track track2 in array) { if (GUILayout.Button(track2.Name, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(29f) })) { Request("select", track2.Id); } } if (tracks.Length == 0) { GUILayout.Label("Dodaj pliki do CartRadio/Music i uruchom grę ponownie.", labelStyle, Array.Empty<GUILayoutOption>()); } GUILayout.EndScrollView(); GUILayout.Space(8f); GUILayout.Label((Time.unscaledTime < statusUntil) ? status : "Każdy gracz potrzebuje tych samych plików w Music.", labelStyle, Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); if (GUILayout.Button("Zamknij [" + ((object)panelKey.Value/*cast due to .constrained prefix*/).ToString() + "]", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { ClosePanel(); } GUILayout.EndArea(); } } internal static class RadioModel { public static void Build(Transform root, PhysGrabCart cart) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) MeshRenderer componentInChildren = ((Component)cart).GetComponentInChildren<MeshRenderer>(); if (Object.op_Implicit((Object)(object)componentInChildren) && Object.op_Implicit((Object)(object)((Renderer)componentInChildren).sharedMaterial)) { Material val = new Material(((Renderer)componentInChildren).sharedMaterial); if (val.HasProperty("_MainTex")) { val.SetTexture("_MainTex", (Texture)null); } if (val.HasProperty("_Color")) { val.color = new Color(0.3f, 0.36f, 0.3f); } Material val2 = new Material(val); if (val2.HasProperty("_Color")) { val2.color = new Color(0.07f, 0.09f, 0.08f); } Material val3 = new Material(val); if (val3.HasProperty("_Color")) { val3.color = new Color(0.56f, 0.7f, 0.43f); } ((Component)root).gameObject.AddComponent<RadioMaterialOwner>().Materials = (Material[])(object)new Material[3] { val, val2, val3 }; Part(root, new Vector3(0f, 0.12f, 0f), new Vector3(0.3f, 0.19f, 0.1f), val, ((Component)componentInChildren).gameObject.layer); for (int i = 0; i < 6; i++) { Part(root, new Vector3(-0.065f + (float)i * 0.021f, 0.105f, -0.055f), new Vector3(0.009f, 0.1f, 0.01f), val2, ((Component)componentInChildren).gameObject.layer); } Part(root, new Vector3(0.098f, 0.15f, -0.055f), new Vector3(0.065f, 0.035f, 0.01f), val3, ((Component)componentInChildren).gameObject.layer); Part(root, new Vector3(0.1f, 0.09f, -0.06f), new Vector3(0.035f, 0.035f, 0.025f), val2, ((Component)componentInChildren).gameObject.layer); Part(root, new Vector3(-0.1f, 0.27f, 0.025f), new Vector3(0.008f, 0.18f, 0.008f), val2, ((Component)componentInChildren).gameObject.layer); } } private static void Part(Transform parent, Vector3 position, Vector3 scale, Material material, int layer) { //IL_0024: 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) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)obj).name = "Cart Radio Housing"; obj.transform.SetParent(parent, false); obj.transform.localPosition = position; obj.transform.localScale = scale; obj.layer = layer; Collider component = obj.GetComponent<Collider>(); component.enabled = false; Object.Destroy((Object)(object)component); ((Renderer)obj.GetComponent<MeshRenderer>()).sharedMaterial = material; } } public sealed class RadioMaterialOwner : MonoBehaviour { public Material[] Materials; private void OnDestroy() { if (Materials == null) { return; } Material[] materials = Materials; foreach (Material val in materials) { if (Object.op_Implicit((Object)(object)val)) { Object.Destroy((Object)(object)val); } } } } public sealed class RadioState { public int Revision; public int CartViewId; public string TrackId = ""; public bool Playing; public double PositionSeconds; public double ServerTime; public float Volume = 0.55f; public double PositionAt(double now) { return Math.Max(0.0, PositionSeconds + (Playing ? Math.Max(0.0, now - ServerTime) : 0.0)); } public RadioState Copy() { return (RadioState)MemberwiseClone(); } public bool IsValid() { if (Revision >= 0 && CartViewId >= 0 && TrackId != null && TrackId.Length <= 128 && !double.IsNaN(PositionSeconds) && !double.IsInfinity(PositionSeconds) && PositionSeconds >= 0.0 && PositionSeconds <= 86400.0 && !double.IsNaN(ServerTime) && !double.IsInfinity(ServerTime) && !float.IsNaN(Volume) && Volume >= 0f) { return Volume <= 1f; } return false; } } public static class RadioProtocol { public const byte EventCode = 178; public const string Signature = "pl.cart-radio.v1"; public static object[] Encode(RadioState state) { return new object[9] { "pl.cart-radio.v1", "state", state.Revision, state.CartViewId, state.TrackId, state.Playing, state.PositionSeconds, state.ServerTime, state.Volume }; } public static bool TryDecode(object payload, out RadioState state) { state = null; if (!(payload is object[] array) || array.Length != 9 || !(array[0] is string text) || text != "pl.cart-radio.v1" || !(array[1] is string text2) || text2 != "state" || !(array[2] is int revision) || !(array[3] is int cartViewId) || !(array[4] is string trackId) || !(array[5] is bool playing) || !(array[6] is double positionSeconds) || !(array[7] is double serverTime) || !(array[8] is float volume)) { return false; } RadioState radioState = new RadioState { Revision = revision, CartViewId = cartViewId, TrackId = trackId, Playing = playing, PositionSeconds = positionSeconds, ServerTime = serverTime, Volume = volume }; if (!radioState.IsValid()) { return false; } state = radioState; return true; } } }