using System;
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;
using System.Security.Permissions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CoconutKlonk;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.Networking;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.Jackstermax.CoconutKlonk")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.6.0")]
[assembly: AssemblyInformationalVersion("1.0.6")]
[assembly: AssemblyProduct("com.github.Jackstermax.CoconutKlonk")]
[assembly: AssemblyTitle("CoconutKlonk")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.6.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;
}
}
}
public class BonkSync : MonoBehaviourPun, IOnEventCallback
{
public void OnEnable()
{
PhotonNetwork.AddCallbackTarget((object)this);
}
public void OnDisable()
{
PhotonNetwork.RemoveCallbackTarget((object)this);
}
public void OnEvent(EventData photonEvent)
{
//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)
if (photonEvent.Code == Plugin.ModEventCodes.BonkSoundEvent)
{
Vector3 position = (Vector3)photonEvent.CustomData;
PlayBonkSound(position);
}
}
private void PlayBonkSound(Vector3 position)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
ManualLogSource? log = Plugin.Log;
if (log != null)
{
log.LogWarning((object)"Playing Klonk Sound Via Event");
}
SFX_Instance? klonkSFX = Plugin.klonkSFX;
if (klonkSFX != null)
{
klonkSFX.Play(position);
}
}
}
public class MyModConfig
{
public readonly ConfigEntry<bool> removeKlonkSound;
public readonly ConfigEntry<float> _SFXVolume;
public readonly ConfigEntry<float> _SFXRange;
public MyModConfig(ConfigFile cfg)
{
cfg.SaveOnConfigSet = false;
removeKlonkSound = cfg.Bind<bool>("General", "Removes the Klonk! Sound", false, "If enabled, removes the Klonk! sound (only affects the host).");
_SFXVolume = cfg.Bind<float>("General", "Klonk Volume", 1f, "Volume of Coconut Klonks.");
_SFXRange = cfg.Bind<float>("General", "Klonk Sound Range", 95f, "Maximum distance a Coconut Klonk! can be heard from.");
ClearOrphanedEntries(cfg);
cfg.Save();
cfg.SaveOnConfigSet = true;
}
private static void ClearOrphanedEntries(ConfigFile cfg)
{
PropertyInfo propertyInfo = AccessTools.Property(typeof(ConfigFile), "OrphanedEntries");
Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)propertyInfo.GetValue(cfg);
dictionary.Clear();
}
}
namespace BepInEx
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class BepInAutoPluginAttribute : Attribute
{
public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace BepInEx.Preloader.Core.Patching
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class PatcherAutoPluginAttribute : Attribute
{
public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace CoconutKlonk
{
[BepInPlugin("com.Jackstermax.peak.CoconutKlonk", "CoconutKlonk", "1.0.6")]
public class Plugin : BaseUnityPlugin
{
[HarmonyPatch(typeof(Bonkable), "Awake")]
private static class BonkableAwake
{
[HarmonyPostfix]
private static void ReplaceBonkSFX(Bonkable __instance, ref SFX_Instance[] ___bonk)
{
__instance.item = ((Component)__instance).gameObject.GetComponent<Item>();
if (__instance?.item?.itemID != 36)
{
return;
}
SFX_Instance? klonkSFX = Plugin.klonkSFX;
if ((klonkSFX != null && klonkSFX.clips?.Length <= 0) || BoundConfig == null)
{
return;
}
if ((Object)(object)sync_Instance == (Object)null)
{
Get_SyncInstance();
}
if (BoundConfig.removeKlonkSound.Value)
{
ManualLogSource? log = Log;
if (log != null)
{
log.LogWarning((object)"Removing Klonk Sound");
}
___bonk = Array.Empty<SFX_Instance>();
}
else if ((Object)(object)Plugin.klonkSFX != (Object)null)
{
List<SFX_Instance> list = new List<SFX_Instance> { Plugin.klonkSFX };
__instance.bonk = list.ToArray();
}
}
}
[HarmonyPatch(typeof(Bonkable), "Bonk", new Type[] { typeof(Collision) })]
private static class BonkableBonk
{
[HarmonyPrefix]
private static void ReplaceBonkSFX(Bonkable __instance, Collision coll)
{
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_0114: Expected O, but got Unknown
if (PhotonNetwork.OfflineMode)
{
return;
}
SFX_Instance? klonkSFX = Plugin.klonkSFX;
if ((klonkSFX == null || !(klonkSFX.clips?.Length <= 0)) && !((Object)(object)__instance == (Object)null) && __instance?.item?.itemID == 36)
{
Character componentInParent = coll.gameObject.GetComponentInParent<Character>();
if (Object.op_Implicit((Object)(object)componentInParent) && Time.time > __instance.lastBonkedTime + __instance.bonkCooldown)
{
PhotonNetwork.RaiseEvent(ModEventCodes.BonkSoundEvent, (object)((Component)__instance).gameObject.transform.position, new RaiseEventOptions
{
Receivers = (ReceiverGroup)0
}, SendOptions.SendReliable);
}
}
}
}
internal static class ModEventCodes
{
internal static readonly byte BonkSoundEvent = 36;
}
public const string Id = "com.Jackstermax.peak.CoconutKlonk";
private readonly Harmony _harmony = new Harmony("com.Jackstermax.peak.CoconutKlonk");
internal static SFX_Instance? klonkSFX;
internal static Plugin? instance;
internal static BonkSync? sync_Instance;
private static readonly string _SFXFolderName = "Coconut_SFX";
private readonly int _SFXLimit = 10;
private const ushort coconutItem_ID = 36;
private CancellationTokenSource? _SFXLoad_CTS;
public static string Name => "CoconutKlonk";
public static string Version => "1.0.6";
internal static ManualLogSource? Log { get; private set; }
internal static MyModConfig? BoundConfig { get; private set; }
internal static BonkSync Get_SyncInstance()
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)sync_Instance != (Object)null)
{
return sync_Instance;
}
sync_Instance = Object.FindFirstObjectByType<BonkSync>();
if ((Object)(object)sync_Instance == (Object)null)
{
sync_Instance = new GameObject("BonkSync Listener Instance").AddComponent<BonkSync>();
Object.DontDestroyOnLoad((Object)(object)((Component)sync_Instance).gameObject);
ManualLogSource? log = Log;
if (log != null)
{
log.LogWarning((object)"New BonkSync Instance Created!");
}
}
return sync_Instance;
}
private void Awake()
{
Run_Setup();
}
private async Task Run_Setup()
{
bool _OK_Setup = false;
try
{
_OK_Setup = await Setup_Async();
}
catch (Exception ex)
{
ManualLogSource? log = Log;
if (log != null)
{
log.LogError((object)("Setup ERROR: " + ex.Message));
}
}
if (_OK_Setup)
{
ManualLogSource? log2 = Log;
if (log2 != null)
{
log2.LogWarning((object)("Plugin " + Name + " loaded successfully!"));
}
}
else
{
ManualLogSource? log3 = Log;
if (log3 != null)
{
log3.LogError((object)("ERROR: Plugin " + Name + " loading failed!"));
}
}
await Task.Yield();
}
private async Task<bool> Setup_Async()
{
if ((Object)(object)instance != (Object)null && (Object)(object)instance != (Object)(object)this)
{
Object.Destroy((Object)(object)this);
return false;
}
instance = this;
Log = ((BaseUnityPlugin)this).Logger;
BoundConfig = new MyModConfig(((BaseUnityPlugin)this).Config);
Harmony val = new Harmony(Name ?? "");
val.PatchAll();
return await Kickoff_LoadKlonkSFX_Async();
}
private async Task<bool> Kickoff_LoadKlonkSFX_Async()
{
string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string text = Path.Combine(directoryName, _SFXFolderName);
if (!Directory.Exists(text))
{
ManualLogSource? log = Log;
if (log != null)
{
log.LogError((object)("Coconut_SFX Sound file directory not found: " + text));
}
Directory.CreateDirectory(text);
return false;
}
Cancel_SFXLoad_Task();
_SFXLoad_CTS = new CancellationTokenSource();
try
{
List<AudioClip> list = await LoadSFX_Task(text, _SFXLoad_CTS.Token);
if (list.Count <= 0)
{
return false;
}
Init_SFXClips(list);
SFX_Instance? obj = klonkSFX;
return obj != null && obj.clips.Length != 0;
}
catch (Exception ex)
{
ManualLogSource? log2 = Log;
if (log2 != null)
{
log2.LogError((object)("Loading Catch: " + ex.Message));
}
}
return false;
}
private void Cancel_SFXLoad_Task()
{
if (_SFXLoad_CTS != null && !_SFXLoad_CTS.IsCancellationRequested)
{
_SFXLoad_CTS.Cancel();
_SFXLoad_CTS.Dispose();
_SFXLoad_CTS = null;
}
}
private async Task<List<AudioClip>> LoadSFX_Task(string directoryPath, CancellationToken token)
{
List<AudioClip> result = new List<AudioClip>();
List<string> list = Directory.GetFiles(directoryPath, "*.wav").ToList();
if (list.Count <= 0)
{
ManualLogSource? log = Log;
if (log != null)
{
log.LogInfo((object)("No valid sound files present in: " + directoryPath));
}
return result;
}
ManualLogSource? log2 = Log;
if (log2 != null)
{
log2.LogInfo((object)("Valid Files Found: " + list.Count));
}
int num = Math.Min(list.Count, _SFXLimit);
List<Task<AudioClip>> list2 = new List<Task<AudioClip>>();
for (int i = 0; i < num; i++)
{
string fileName = list[i];
list2.Add(LoadAudioClip_Single_Async(fileName, token));
}
token.ThrowIfCancellationRequested();
try
{
result = (await Task.WhenAll(list2)).OfType<AudioClip>().ToList();
}
catch (Exception ex)
{
ManualLogSource? log3 = Log;
if (log3 != null)
{
log3.LogError((object)("Parallel SFX Load Error: " + ex.Message));
}
result = new List<AudioClip>();
}
ManualLogSource? log4 = Log;
if (log4 != null)
{
log4.LogInfo((object)("Clips found: " + result.Count));
}
return result;
}
private async Task<AudioClip?> LoadAudioClip_Single_Async(string fileName, CancellationToken token)
{
token.ThrowIfCancellationRequested();
string absoluteUri = new Uri(fileName).AbsoluteUri;
UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(absoluteUri, (AudioType)20);
try
{
Awaiter val = AsyncOperationAwaitableExtensions.GetAwaiter((AsyncOperation)(object)req.SendWebRequest());
if (!((Awaiter)(ref val)).IsCompleted)
{
await val;
Awaiter val2 = default(Awaiter);
val = val2;
}
((Awaiter)(ref val)).GetResult();
if ((int)req.result == 2 || (int)req.result == 3)
{
ManualLogSource? log = Log;
if (log != null)
{
log.LogError((object)("Error loading: " + fileName + " | " + req.error));
}
return null;
}
return DownloadHandlerAudioClip.GetContent(req);
}
finally
{
((IDisposable)req)?.Dispose();
}
}
private void Init_SFXClips(List<AudioClip> clips)
{
//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_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Expected O, but got Unknown
if (clips != null && clips.Count <= 0)
{
ManualLogSource? log = Log;
if (log != null)
{
log.LogInfo((object)"Aborting load, no audio clips in load list!");
}
return;
}
klonkSFX = ScriptableObject.CreateInstance<SFX_Instance>();
klonkSFX.clips = clips?.ToArray();
klonkSFX.settings = new SFX_Settings
{
volume = ((BoundConfig != null) ? BoundConfig._SFXVolume.Value : 1f),
range = ((BoundConfig != null) ? BoundConfig._SFXRange.Value : 75f)
};
ManualLogSource? log2 = Log;
if (log2 != null)
{
log2.LogInfo((object)$"Created SO: {(Object)(object)klonkSFX != (Object)null} | Clips Count: {klonkSFX?.clips?.Count()}");
}
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}