using 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(); Source = ((Component)this).gameObject.AddComponent(); 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 list = new List(); long num = 0L; foreach (string item in Directory.GetFiles(folder).OrderBy((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(); private Task scan; private readonly CancellationTokenSource cancellation = new CancellationTokenSource(); private RadioState state = new RadioState(); private readonly Dictionary requestTimes = new Dictionary(); private readonly Dictionary helloTimes = new Dictionary(); private PhysGrabCart[] carts = Array.Empty(); 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 personalVolume; private ConfigEntry 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 noKeys = new List(); 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("Audio", "PersonalVolume", 0.8f, new ConfigDescription("Your local listening volume. 0 mutes the radio only for you.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); panelKey = ((BaseUnityPlugin)this).Config.Bind("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(); 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[] 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() : null); PlayerAvatar player = (Object.op_Implicit((Object)(object)GameDirector.instance) ? ((IEnumerable)GameDirector.instance.PlayerList).FirstOrDefault((Func)((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 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(); 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(); 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(); } 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(); 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(); 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(); 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()); GUILayout.Label("Wspólna muzyka • MP3 / OGG / WAV", labelStyle, Array.Empty()); 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()); GUILayout.Label(state.Playing ? "Odtwarzanie" : "Pauza / zatrzymano", labelStyle, Array.Empty()); GUILayout.BeginHorizontal(Array.Empty()); 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()); GUILayout.Label("Głośność radia: " + Mathf.RoundToInt(state.Volume * 100f) + "%", labelStyle, Array.Empty()); 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()); float num3 = GUILayout.HorizontalSlider(personalVolume.Value, 0f, 1f, Array.Empty()); if (Mathf.Abs(num3 - personalVolume.Value) > 0.015f) { personalVolume.Value = num3; } GUILayout.Space(8f); GUILayout.Label("Biblioteka: " + tracks.Length + " utworów", labelStyle, Array.Empty()); 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()); } GUILayout.EndScrollView(); GUILayout.Space(8f); GUILayout.Label((Time.unscaledTime < statusUntil) ? status : "Każdy gracz potrzebuje tych samych plików w Music.", labelStyle, Array.Empty()); 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(); 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().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(); component.enabled = false; Object.Destroy((Object)(object)component); ((Renderer)obj.GetComponent()).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; } } }