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 TrainTunes v0.2.1
BepInEx/plugins/TrainTunes/TrainTunes.dll
Decompiled 4 days agousing System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using Blackforge; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace TrainTunes; [BepInPlugin("local.traintunes", "Train Tunes", "0.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class TrainTunesPlugin : BaseUnityPlugin { public const string PluginGuid = "local.traintunes"; private ConfigEntry<bool> _enabled; private ConfigEntry<float> _volume; private ConfigEntry<float> _minDistance; private ConfigEntry<float> _maxDistance; private ConfigEntry<float> _speedThreshold; private float _nextScan; private AudioClip[] _clips = (AudioClip[])(object)new AudioClip[0]; internal int TrackCount => _clips.Length; internal bool Enabled => _enabled.Value; internal float Volume => Mathf.Clamp01(_volume.Value); internal float MinDistance => Mathf.Max(0.1f, _minDistance.Value); internal float MaxDistance => Mathf.Max(MinDistance + 1f, _maxDistance.Value); internal float SpeedThreshold => Mathf.Max(0f, _speedThreshold.Value); internal AudioClip GetTrack(int index) { return _clips[index]; } private void Awake() { _enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable train-mounted music."); _volume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "Volume", 0.6f, "Volume from 0.0 to 1.0."); _minDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "MinDistance", 8f, "Distance in meters at which music is full volume."); _maxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "MaxDistance", 75f, "Distance in meters at which music is inaudible."); _speedThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SpeedThreshold", 0.1f, "Absolute Railroads locomotive speed (m/s) above which music plays."); string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = Path.Combine(directoryName, "Music"); Directory.CreateDirectory(text); ((MonoBehaviour)this).StartCoroutine(LoadPlaylist(text)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Train Tunes v0.2.0 loaded: train-mounted shuffled playlists (local audio only)."); } private IEnumerator LoadPlaylist(string folder) { List<string> paths = new List<string>(); string[] files = Directory.GetFiles(folder, "*", SearchOption.TopDirectoryOnly); foreach (string text in files) { string extension = Path.GetExtension(text); if (string.Equals(extension, ".mp3", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".ogg", StringComparison.OrdinalIgnoreCase)) { paths.Add(text); } } paths.Sort(StringComparer.OrdinalIgnoreCase); if (paths.Count == 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Train Tunes: no MP3 or OGG files found in " + folder)); yield break; } List<AudioClip> loaded = new List<AudioClip>(); foreach (string path in paths) { string ext = Path.GetExtension(path); AudioType type = (AudioType)(string.Equals(ext, ".mp3", StringComparison.OrdinalIgnoreCase) ? 13 : 14); string uri = new Uri(Path.GetFullPath(path)).AbsoluteUri; UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(uri, type); try { yield return request.SendWebRequest(); if ((int)request.result != 1) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Train Tunes: skipping " + Path.GetFileName(path) + ": " + request.error)); continue; } AudioClip clip = DownloadHandlerAudioClip.GetContent(request); if ((Object)(object)clip == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Train Tunes: Unity could not load " + Path.GetFileName(path))); continue; } ((Object)clip).name = Path.GetFileNameWithoutExtension(path); loaded.Add(clip); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Train Tunes: loaded " + Path.GetFileName(path))); } finally { ((IDisposable)request)?.Dispose(); } } _clips = loaded.ToArray(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Train Tunes: ready with " + _clips.Length + " song(s).")); } private void Update() { if (Time.unscaledTime < _nextScan) { return; } _nextScan = Time.unscaledTime + 1f; RailLocomotive[] array = Object.FindObjectsOfType<RailLocomotive>(); foreach (RailLocomotive val in array) { if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy) { TrainTunesEmitter component = ((Component)val).GetComponent<TrainTunesEmitter>(); if ((Object)(object)component == (Object)null) { component = ((Component)val).gameObject.AddComponent<TrainTunesEmitter>(); component.Initialize(this); } } } } private void OnDestroy() { AudioClip[] clips = _clips; foreach (AudioClip val in clips) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } } } internal sealed class TrainTunesEmitter : MonoBehaviour { private TrainTunesPlugin _plugin; private ZNetView _networkView; private AudioSource _source; private readonly List<int> _shuffleBag = new List<int>(); private int _nextInBag; private int _lastTrack = -1; private bool _trackStarted; private void Awake() { _networkView = ((Component)this).GetComponent<ZNetView>(); _source = ((Component)this).gameObject.AddComponent<AudioSource>(); _source.playOnAwake = false; _source.loop = false; _source.spatialBlend = 1f; _source.rolloffMode = (AudioRolloffMode)1; _source.dopplerLevel = 0f; } internal void Initialize(TrainTunesPlugin plugin) { _plugin = plugin; } private void Update() { if ((Object)(object)_plugin == (Object)null || !_plugin.Enabled || _plugin.TrackCount == 0 || (Object)(object)_networkView == (Object)null || !_networkView.IsValid()) { StopMusic(); return; } _source.volume = _plugin.Volume; _source.minDistance = _plugin.MinDistance; _source.maxDistance = _plugin.MaxDistance; ZDO zDO = _networkView.GetZDO(); if (zDO == null) { StopMusic(); return; } float num = Mathf.Abs(zDO.GetFloat("bf_speed", 0f)); if (num <= _plugin.SpeedThreshold) { StopMusic(); } else if (!_trackStarted || !_source.isPlaying) { PlayNextTrack(); } } private void PlayNextTrack() { int trackCount = _plugin.TrackCount; if (trackCount >= 1) { int index = DrawTrack(trackCount); _source.Stop(); _source.clip = _plugin.GetTrack(index); _source.loop = trackCount == 1; _source.Play(); _trackStarted = true; } } private int DrawTrack(int count) { if (_shuffleBag.Count != count || _nextInBag >= _shuffleBag.Count) { _shuffleBag.Clear(); for (int i = 0; i < count; i++) { _shuffleBag.Add(i); } for (int num = count - 1; num > 0; num--) { int index = Random.Range(0, num + 1); int value = _shuffleBag[num]; _shuffleBag[num] = _shuffleBag[index]; _shuffleBag[index] = value; } if (count > 1 && _shuffleBag[0] == _lastTrack) { int index2 = Random.Range(1, count); int value2 = _shuffleBag[0]; _shuffleBag[0] = _shuffleBag[index2]; _shuffleBag[index2] = value2; } _nextInBag = 0; } return _lastTrack = _shuffleBag[_nextInBag++]; } private void StopMusic() { if ((Object)(object)_source != (Object)null && _source.isPlaying) { _source.Stop(); } _trackStarted = false; } private void OnDisable() { StopMusic(); } }