using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Networking;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("xiaohai")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("REPO_CustomLastSong")]
[assembly: AssemblyTitle("REPO_CustomLastSong")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 REPO_CustomLastSong
{
[BepInPlugin("xiaohai.REPO_CustomLastSong", "REPO_CustomLastSong", "1.0")]
public class REPO_CustomLastSong : BaseUnityPlugin
{
internal static ConfigEntry<float>? EvacVolume;
private static GameObject? _controllerObject;
internal static REPO_CustomLastSong Instance { get; private set; }
internal static ManualLogSource Logger => Instance._logger;
private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;
internal Harmony? Harmony { get; set; }
private void Awake()
{
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Expected O, but got Unknown
Instance = this;
((Component)this).transform.parent = null;
((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
EvacVolume = ((BaseUnityPlugin)this).Config.Bind<float>("通用", "Volume", 1f, "撤离BGM音量 / Evac BGM volume (0-1)");
BgmManager.Initialize(((BaseUnityPlugin)this).Config, Logger);
((MonoBehaviour)this).StartCoroutine(BgmManager.LoadAllClipsCoroutine());
if ((Object)(object)_controllerObject == (Object)null)
{
_controllerObject = new GameObject("CustomLastSongController");
Object.DontDestroyOnLoad((Object)(object)_controllerObject);
((Object)_controllerObject).hideFlags = (HideFlags)61;
_controllerObject.AddComponent<EvacMusicController>();
}
Patch();
Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
}
internal void Patch()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
//IL_0026: Expected O, but got Unknown
if (Harmony == null)
{
Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
Harmony val2 = val;
Harmony = val;
}
Harmony.PatchAll();
}
internal void Unpatch()
{
Harmony? harmony = Harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
}
internal class EvacMusicController : MonoBehaviour
{
internal static EvacMusicController? Instance;
private AudioSource? _source;
internal static bool Active { get; private set; }
private void Awake()
{
Instance = this;
_source = ((Component)this).gameObject.AddComponent<AudioSource>();
_source.playOnAwake = false;
_source.loop = true;
_source.spatialBlend = 0f;
}
private void Update()
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Invalid comparison between Unknown and I4
if (!Active)
{
return;
}
if ((Object)(object)GameDirector.instance != (Object)null && (int)GameDirector.instance.currentState != 2)
{
StopEvacMusic();
}
else if ((Object)(object)MusicEnemyNear.instance != (Object)null)
{
AudioSource source = MusicEnemyNear.instance.Source;
if ((Object)(object)source != (Object)null && source.isPlaying)
{
source.Stop();
}
MusicEnemyNear.instance.Volume = 0f;
}
}
internal void StartEvacMusic()
{
if (Active)
{
return;
}
EnsureSource();
AudioClip val = BgmManager.GetRandomClipForCurrentLevel();
if ((Object)(object)val == (Object)null && (Object)(object)LevelMusic.instance != (Object)null)
{
AudioSource component = ((Component)LevelMusic.instance).GetComponent<AudioSource>();
if ((Object)(object)component != (Object)null && (Object)(object)component.clip != (Object)null)
{
val = component.clip;
}
}
if ((Object)(object)_source != (Object)null && (Object)(object)val != (Object)null)
{
_source.clip = val;
float volume = ((REPO_CustomLastSong.EvacVolume != null) ? Mathf.Clamp01(REPO_CustomLastSong.EvacVolume.Value) : 1f);
_source.volume = volume;
_source.Play();
Active = true;
}
}
internal void StopEvacMusic()
{
if (Active)
{
Active = false;
if ((Object)(object)_source != (Object)null && _source.isPlaying)
{
_source.Stop();
}
}
}
private void EnsureSource()
{
if ((Object)(object)_source == (Object)null)
{
_source = ((Component)this).gameObject.AddComponent<AudioSource>();
_source.playOnAwake = false;
_source.loop = true;
_source.spatialBlend = 0f;
}
}
}
internal static class BgmManager
{
internal sealed class Track
{
internal string FileName = string.Empty;
internal string FullPath = string.Empty;
internal ConfigEntry<int> MinLevel = null;
internal ConfigEntry<int> MaxLevel = null;
internal AudioClip? Clip;
}
[CompilerGenerated]
private sealed class <LoadAllClipsCoroutine>d__6 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
private Dictionary<string, Track>.ValueCollection.Enumerator <>s__1;
private Track <track>5__2;
private AudioType <type>5__3;
private string <url>5__4;
private UnityWebRequest <req>5__5;
private AudioClip <clip>5__6;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <LoadAllClipsCoroutine>d__6(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if ((uint)(num - -4) <= 1u || num == 1)
{
try
{
if (num == -4 || num == 1)
{
try
{
}
finally
{
<>m__Finally2();
}
}
}
finally
{
<>m__Finally1();
}
}
<>s__1 = default(Dictionary<string, Track>.ValueCollection.Enumerator);
<track>5__2 = null;
<url>5__4 = null;
<req>5__5 = null;
<clip>5__6 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Invalid comparison between Unknown and I4
//IL_00a2: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Invalid comparison between Unknown and I4
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
try
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
if (Tracks.Count == 0)
{
return false;
}
<>s__1 = Tracks.Values.GetEnumerator();
<>1__state = -3;
break;
case 1:
<>1__state = -4;
if ((int)<req>5__5.result != 1)
{
if (_logger != null)
{
_logger.LogWarning((object)("Failed to load BGM " + <track>5__2.FileName + " from " + <track>5__2.FullPath + ": " + <req>5__5.error));
}
}
else
{
<clip>5__6 = DownloadHandlerAudioClip.GetContent(<req>5__5);
if (!((Object)(object)<clip>5__6 == (Object)null))
{
((Object)<clip>5__6).name = <track>5__2.FileName;
<track>5__2.Clip = <clip>5__6;
<clip>5__6 = null;
<>m__Finally2();
<req>5__5 = null;
<url>5__4 = null;
<track>5__2 = null;
break;
}
}
<>m__Finally2();
break;
}
while (<>s__1.MoveNext())
{
<track>5__2 = <>s__1.Current;
if (!((Object)(object)<track>5__2.Clip != (Object)null))
{
<type>5__3 = GetAudioTypeFromExtension(Path.GetExtension(<track>5__2.FullPath));
if ((int)<type>5__3 != 0)
{
<url>5__4 = "file:///" + <track>5__2.FullPath.Replace("\\", "/");
<req>5__5 = UnityWebRequestMultimedia.GetAudioClip(<url>5__4, <type>5__3);
<>1__state = -4;
<>2__current = <req>5__5.SendWebRequest();
<>1__state = 1;
return true;
}
}
}
<>m__Finally1();
<>s__1 = default(Dictionary<string, Track>.ValueCollection.Enumerator);
return false;
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
((IDisposable)<>s__1).Dispose();
}
private void <>m__Finally2()
{
<>1__state = -3;
if (<req>5__5 != null)
{
((IDisposable)<req>5__5).Dispose();
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static readonly Dictionary<string, Track> Tracks = new Dictionary<string, Track>(StringComparer.OrdinalIgnoreCase);
private static ConfigFile? _config;
private static ManualLogSource? _logger;
internal static void Initialize(ConfigFile config, ManualLogSource logger)
{
_config = config;
_logger = logger;
ReloadFromDisk();
}
internal static void ReloadFromDisk()
{
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Expected O, but got Unknown
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
//IL_0161: Expected O, but got Unknown
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Expected O, but got Unknown
//IL_0194: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: Expected O, but got Unknown
if (_config == null)
{
return;
}
Tracks.Clear();
string location = Assembly.GetExecutingAssembly().Location;
string text = Path.GetDirectoryName(location) ?? string.Empty;
if (text.Length == 0)
{
return;
}
string path = Path.Combine(text, "BGM");
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string[] files = Directory.GetFiles(path, "*.*", SearchOption.TopDirectoryOnly);
HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".wav", ".ogg", ".mp3", ".aiff", ".aif", ".flac", ".xm", ".mod", ".it", ".s3m" };
HashSet<ConfigDefinition> hashSet2 = new HashSet<ConfigDefinition>();
foreach (string text2 in files)
{
string extension = Path.GetExtension(text2);
if (hashSet.Contains(extension))
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text2);
ConfigDefinition val = new ConfigDefinition(fileNameWithoutExtension, "MinLevel");
ConfigDefinition val2 = new ConfigDefinition(fileNameWithoutExtension, "MaxLevel");
ConfigEntry<int> val3 = _config.Bind<int>(val, 1, new ConfigDescription("最小使用关卡数 / Min level index (integer > 0)", (AcceptableValueBase)null, Array.Empty<object>()));
ConfigEntry<int> val4 = _config.Bind<int>(val2, 99, new ConfigDescription("最大使用关卡数 / Max level index (integer > 0)", (AcceptableValueBase)null, Array.Empty<object>()));
if (val3.Value < 1)
{
val3.Value = 1;
}
if (val4.Value < 1)
{
val4.Value = 1;
}
if (val4.Value < val3.Value)
{
val4.Value = val3.Value;
}
hashSet2.Add(val);
hashSet2.Add(val2);
Track value = new Track
{
FileName = fileNameWithoutExtension,
FullPath = text2,
MinLevel = val3,
MaxLevel = val4
};
Tracks[fileNameWithoutExtension] = value;
}
}
List<ConfigDefinition> list = new List<ConfigDefinition>();
foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in _config)
{
ConfigDefinition key = item.Key;
if (!(key.Section == "通用") && (!(key.Key != "MinLevel") || !(key.Key != "MaxLevel")) && !hashSet2.Contains(key))
{
list.Add(key);
}
}
for (int j = 0; j < list.Count; j++)
{
_config.Remove(list[j]);
}
}
[IteratorStateMachine(typeof(<LoadAllClipsCoroutine>d__6))]
internal static IEnumerator LoadAllClipsCoroutine()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LoadAllClipsCoroutine>d__6(0);
}
internal static AudioClip? GetRandomClipForCurrentLevel()
{
if (Tracks.Count == 0)
{
return null;
}
int num = 1;
if ((Object)(object)RunManager.instance != (Object)null)
{
num = Mathf.Max(1, RunManager.instance.levelsCompleted + 1);
}
List<AudioClip> list = new List<AudioClip>();
foreach (Track value3 in Tracks.Values)
{
if (!((Object)(object)value3.Clip == (Object)null))
{
int value = value3.MinLevel.Value;
int value2 = value3.MaxLevel.Value;
if (num >= value && num <= value2)
{
list.Add(value3.Clip);
}
}
}
if (list.Count == 0)
{
return null;
}
int index = Random.Range(0, list.Count);
return list[index];
}
private static AudioType GetAudioTypeFromExtension(string ext)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Unknown result type (might be due to invalid IL or missing references)
//IL_015d: Unknown result type (might be due to invalid IL or missing references)
//IL_0179: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_0161: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: 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)
if (string.IsNullOrEmpty(ext))
{
return (AudioType)0;
}
switch (ext.ToLowerInvariant())
{
case ".wav":
return (AudioType)20;
case ".ogg":
return (AudioType)14;
case ".mp3":
return (AudioType)13;
case ".aif":
case ".aiff":
return (AudioType)2;
case ".mod":
return (AudioType)12;
case ".it":
return (AudioType)10;
case ".s3m":
return (AudioType)17;
case ".xm":
return (AudioType)21;
default:
return (AudioType)0;
}
}
}
[HarmonyPatch(typeof(RoundDirector))]
internal static class RoundDirector_ExtractionCompletedAllRPC_Patch
{
[HarmonyPostfix]
[HarmonyPatch("ExtractionCompletedAllRPC")]
private static void Postfix()
{
if ((Object)(object)EvacMusicController.Instance != (Object)null)
{
EvacMusicController.Instance.StartEvacMusic();
}
}
}
[HarmonyPatch(typeof(LevelMusic))]
internal static class LevelMusic_Update_Patch
{
[HarmonyPrefix]
[HarmonyPatch("Update")]
private static bool Prefix(LevelMusic __instance)
{
if (!EvacMusicController.Active)
{
return true;
}
AudioSource component = ((Component)__instance).GetComponent<AudioSource>();
if ((Object)(object)component != (Object)null && component.isPlaying)
{
component.Stop();
}
return false;
}
}
[HarmonyPatch(typeof(ConstantMusic))]
internal static class ConstantMusic_Update_Patch
{
[HarmonyPrefix]
[HarmonyPatch("Update")]
private static bool Prefix(ConstantMusic __instance)
{
if (!EvacMusicController.Active)
{
return true;
}
AudioSource component = ((Component)__instance).GetComponent<AudioSource>();
if ((Object)(object)component != (Object)null && component.isPlaying)
{
component.Stop();
}
return false;
}
}
}