using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
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 CodeTalker;
using CodeTalker.Networking;
using CodeTalker.Packets;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Nessie.ATLYSS.EasySettings;
using Steamworks;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Events;
[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: AssemblyCompany("com.VCLYSS.sftwre")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+dd51c6b67c3ae15f202b303bb926a1a33079baf7")]
[assembly: AssemblyProduct("VCLYSS")]
[assembly: AssemblyTitle("VCLYSS")]
[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 VCLYSS
{
[BepInPlugin("com.VCLYSS.sftwre", "VCLYSS", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Main : BaseUnityPlugin
{
public enum MicMode
{
PushToTalk,
Toggle,
AlwaysOn
}
public static Main Instance;
internal static ManualLogSource Log;
private Harmony _harmony;
public static ConfigEntry<bool> CfgEnabled;
public static ConfigEntry<float> CfgMasterVolume;
public static ConfigEntry<bool> CfgMuteAll;
public static ConfigEntry<MicMode> CfgMicMode;
public static ConfigEntry<KeyCode> CfgPushToTalk;
public static ConfigEntry<float> CfgMicThreshold;
public static ConfigEntry<bool> CfgMicTest;
public static ConfigEntry<float> CfgMinDistance;
public static ConfigEntry<float> CfgMaxDistance;
public static ConfigEntry<bool> CfgSpatialBlending;
public static ConfigEntry<bool> CfgShowOverlay;
public static ConfigEntry<bool> CfgShowHeadIcons;
public static ConfigEntry<bool> CfgLipSync;
public static ConfigEntry<bool> CfgDebugMode;
private void Awake()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Expected O, but got Unknown
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Expected O, but got Unknown
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Expected O, but got Unknown
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
InitConfig();
Settings.OnInitialized.AddListener(new UnityAction(AddSettings));
Settings.OnApplySettings.AddListener((UnityAction)delegate
{
((BaseUnityPlugin)this).Config.Save();
VoiceSystem.ApplySettingsToAll();
});
_harmony = new Harmony("com.VCLYSS.sftwre");
_harmony.PatchAll();
((MonoBehaviour)this).StartCoroutine(RegisterPacketDelayed());
GameObject val = new GameObject("VCLYSS_System");
Object.DontDestroyOnLoad((Object)(object)val);
val.AddComponent<VoiceSystem>();
val.AddComponent<VoiceOverlay>();
((BaseUnityPlugin)this).Logger.LogInfo((object)"[VCLYSS] Loaded. Voice System Started.");
}
private IEnumerator RegisterPacketDelayed()
{
yield return (object)new WaitForSeconds(2f);
CodeTalkerNetwork.RegisterBinaryListener<VoicePacket>(new BinaryPacketListener(OnVoicePacketReceived));
if (CfgDebugMode.Value)
{
Log.LogInfo((object)"Voice packet listener registered");
}
}
private void OnVoicePacketReceived(PacketHeader header, BinaryPacketBase packet)
{
if (!(packet is VoicePacket voicePacket) || voicePacket.VoiceData == null || voicePacket.VoiceData.Length == 0)
{
return;
}
if (voicePacket.VoiceData.Length > 65535)
{
if (CfgDebugMode.Value)
{
Log.LogWarning((object)$"[Security] Dropped oversized packet from {header.SenderID} ({voicePacket.VoiceData.Length} bytes)");
}
return;
}
if (CfgDebugMode.Value)
{
Log.LogDebug((object)$"[Flow] Recv Voice Packet | Sender: {header.SenderID} | Size: {voicePacket.VoiceData.Length}");
}
VoiceSystem.Instance.RoutePacket(header.SenderID, voicePacket.VoiceData);
}
private void InitConfig()
{
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Expected O, but got Unknown
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Expected O, but got Unknown
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Expected O, but got Unknown
//IL_0187: Unknown result type (might be due to invalid IL or missing references)
//IL_0191: Expected O, but got Unknown
CfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "Voice Chat Active", true, "Master Switch");
CfgMasterVolume = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "Master Volume", 1f, new ConfigDescription("Incoming Voice Volume Boost (0 = Mute)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
CfgMuteAll = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "Mute Everyone (Panic)", false, "Panic button to silence all incoming voice");
CfgMicMode = ((BaseUnityPlugin)this).Config.Bind<MicMode>("2. Input", "Input Mode", MicMode.PushToTalk, "Input Method");
CfgPushToTalk = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("2. Input", "Push To Talk Key", (KeyCode)116, "Bind for PTT/Toggle");
CfgMicThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("2. Input", "Mic Activation Threshold", 0.05f, new ConfigDescription("Gate threshold", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>()));
CfgMicTest = ((BaseUnityPlugin)this).Config.Bind<bool>("2. Input", "Mic Test (Loopback)", false, "Hear your own voice to test settings");
CfgMinDistance = ((BaseUnityPlugin)this).Config.Bind<float>("3. Spatial", "Min Distance", 5f, new ConfigDescription("Distance where audio is 100% volume", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
CfgMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("3. Spatial", "Max Distance", 40f, new ConfigDescription("Distance where audio becomes silent", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 256f), Array.Empty<object>()));
CfgSpatialBlending = ((BaseUnityPlugin)this).Config.Bind<bool>("3. Spatial", "3D Spatial Audio", true, "Enable 3D Directional Audio");
CfgShowOverlay = ((BaseUnityPlugin)this).Config.Bind<bool>("4. Visuals", "Show Voice Overlay", true, "Show list of speakers in top right");
CfgShowHeadIcons = ((BaseUnityPlugin)this).Config.Bind<bool>("4. Visuals", "Show Head Icons (Bubble)", true, "Show GMod-style bubble");
CfgLipSync = ((BaseUnityPlugin)this).Config.Bind<bool>("4. Visuals", "Enable Lip Sync", true, "Animate mouths when talking");
CfgDebugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("5. Advanced", "Debug Mode (Verbose)", false, "Enable traffic flow logs and detailed status updates. Warning: Spams console.");
}
private void AddSettings()
{
SettingsTab modTab = Settings.ModTab;
modTab.AddHeader("General");
modTab.AddToggle(CfgEnabled);
modTab.AddToggle(CfgMuteAll);
modTab.AddSlider(CfgMasterVolume, false);
modTab.AddHeader("Microphone");
modTab.AddDropdown<MicMode>(CfgMicMode);
modTab.AddKeyButton(CfgPushToTalk);
modTab.AddSlider(CfgMicThreshold, false);
modTab.AddToggle(CfgMicTest);
modTab.AddHeader("Spatial / Earmuffs");
modTab.AddToggle(CfgSpatialBlending);
modTab.AddSlider(CfgMinDistance, false);
modTab.AddSlider(CfgMaxDistance, false);
modTab.AddHeader("Visuals");
modTab.AddToggle(CfgShowOverlay);
modTab.AddToggle(CfgShowHeadIcons);
modTab.AddToggle(CfgLipSync);
modTab.AddHeader("Advanced");
modTab.AddToggle(CfgDebugMode);
}
}
public static class VoiceAPI
{
public static event Action<Player> OnPlayerStartSpeaking;
public static event Action<Player> OnPlayerStopSpeaking;
public static bool IsPlayerSpeaking(Player player)
{
VoiceManager managerForPlayer = VoiceSystem.Instance.GetManagerForPlayer(player);
return (Object)(object)managerForPlayer != (Object)null && managerForPlayer.IsSpeaking();
}
public static void SetPlayerMute(Player player, bool isMuted)
{
VoiceManager managerForPlayer = VoiceSystem.Instance.GetManagerForPlayer(player);
if ((Object)(object)managerForPlayer != (Object)null)
{
managerForPlayer.SetExternalMute(isMuted);
}
}
public static void SetPlayerVolume(Player player, float volumeMultiplier)
{
VoiceManager managerForPlayer = VoiceSystem.Instance.GetManagerForPlayer(player);
if ((Object)(object)managerForPlayer != (Object)null)
{
managerForPlayer.SetExternalGain(volumeMultiplier);
}
}
public static void SetPlayerSpatialOverride(Player player, bool? forceSpatial)
{
VoiceManager managerForPlayer = VoiceSystem.Instance.GetManagerForPlayer(player);
if ((Object)(object)managerForPlayer != (Object)null)
{
managerForPlayer.SetSpatialOverride(forceSpatial);
}
}
internal static void TriggerStartSpeaking(Player p)
{
VoiceAPI.OnPlayerStartSpeaking?.Invoke(p);
}
internal static void TriggerStopSpeaking(Player p)
{
VoiceAPI.OnPlayerStopSpeaking?.Invoke(p);
}
}
public class VoicePacket : BinaryPacketBase
{
public byte[] VoiceData;
public override string PacketSignature => "VCLYSS_VOICE";
public VoicePacket()
{
}
public VoicePacket(byte[] data)
{
VoiceData = data;
}
public override byte[] Serialize()
{
return VoiceData ?? new byte[0];
}
public override void Deserialize(byte[] data)
{
VoiceData = data;
}
}
public class VoiceSystem : MonoBehaviour
{
public static VoiceSystem Instance;
public static List<VoiceManager> ActiveManagers = new List<VoiceManager>();
public static bool IsVoiceAllowedInLobby = false;
private void Awake()
{
Instance = this;
((MonoBehaviour)this).StartCoroutine(PlayerScanner());
}
private IEnumerator PlayerScanner()
{
WaitForSeconds wait = new WaitForSeconds(2f);
while (true)
{
try
{
Player[] allPlayers = Object.FindObjectsOfType<Player>();
Player[] array = allPlayers;
foreach (Player p in array)
{
if ((Object)(object)p != (Object)null && (Object)(object)((Component)p).GetComponent<VoiceManager>() == (Object)null)
{
if (Main.CfgDebugMode.Value)
{
Main.Log.LogDebug((object)("[Scanner] Attaching VoiceManager to " + p._nickname));
}
((Component)p).gameObject.AddComponent<VoiceManager>();
}
}
}
catch (Exception ex)
{
Exception e = ex;
Main.Log.LogWarning((object)("Scanner error: " + e.Message));
}
yield return wait;
}
}
public void RoutePacket(ulong senderID, byte[] data)
{
if (Main.CfgEnabled.Value && !Main.CfgMuteAll.Value && IsVoiceAllowedInLobby && senderID != GetSteamIDFromPlayer(Player._mainPlayer))
{
VoiceManager voiceManager = FindManager(senderID);
if ((Object)(object)voiceManager != (Object)null && voiceManager.OwnerID == senderID)
{
voiceManager.ReceiveNetworkData(data);
}
}
}
public VoiceManager GetManagerForPlayer(Player p)
{
if ((Object)(object)p == (Object)null)
{
return null;
}
return ((Component)p).GetComponent<VoiceManager>();
}
private VoiceManager FindManager(ulong steamID)
{
for (int i = 0; i < ActiveManagers.Count; i++)
{
if (ActiveManagers[i].OwnerID == steamID)
{
return ActiveManagers[i];
}
}
Player[] array = Object.FindObjectsOfType<Player>();
Player[] array2 = array;
foreach (Player val in array2)
{
if (GetSteamIDFromPlayer(val) == steamID)
{
VoiceManager voiceManager = ((Component)val).GetComponent<VoiceManager>();
if ((Object)(object)voiceManager == (Object)null)
{
voiceManager = ((Component)val).gameObject.AddComponent<VoiceManager>();
}
return voiceManager;
}
}
return null;
}
public static ulong GetSteamIDFromPlayer(Player p)
{
if ((Object)(object)p == (Object)null)
{
return 0uL;
}
if (ulong.TryParse(p._steamID, out var result))
{
return result;
}
return 0uL;
}
public static void ApplySettingsToAll()
{
foreach (VoiceManager activeManager in ActiveManagers)
{
activeManager.ApplyAudioSettings();
}
}
}
[HarmonyPatch]
public class LobbyPatches
{
private const string LOBBY_KEY = "vclyss_version";
[HarmonyPatch(typeof(SteamMatchmaking), "JoinLobby")]
[HarmonyPostfix]
public static void OnJoinLobby(CSteamID steamIDLobby)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
((MonoBehaviour)Main.Instance).StartCoroutine(CheckLobbyStatus(steamIDLobby));
}
[HarmonyPatch(typeof(SteamMatchmaking), "CreateLobby")]
[HarmonyPostfix]
public static void OnCreateLobby()
{
((MonoBehaviour)Main.Instance).StartCoroutine(SetLobbyStatus());
}
private static IEnumerator SetLobbyStatus()
{
yield return (object)new WaitForSeconds(1f);
CSteamID currentLobby = new CSteamID(SteamLobby._current._currentLobbyID);
if (currentLobby.m_SteamID != 0L && Main.CfgEnabled.Value)
{
SteamMatchmaking.SetLobbyData(currentLobby, "vclyss_version", "1.0.0");
VoiceSystem.IsVoiceAllowedInLobby = true;
Main.Log.LogInfo((object)"Host Lobby Created: Voice Chat ENABLED.");
}
}
private static IEnumerator CheckLobbyStatus(CSteamID lobbyId)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
yield return (object)new WaitForSeconds(2f);
string value = SteamMatchmaking.GetLobbyData(lobbyId, "vclyss_version");
if (!string.IsNullOrEmpty(value) && Main.CfgEnabled.Value)
{
VoiceSystem.IsVoiceAllowedInLobby = true;
Main.Log.LogInfo((object)("Joined Modded Lobby (Host Ver: " + value + "): Voice Chat ENABLED."));
}
else
{
VoiceSystem.IsVoiceAllowedInLobby = false;
SteamUser.StopVoiceRecording();
Main.Log.LogInfo((object)"Voice Chat DISABLED (Host does not have the mod).");
}
}
}
public class VoiceManager : MonoBehaviour
{
public Player AttachedPlayer;
public ulong OwnerID;
public bool IsLocalPlayer = false;
private float _externalGain = 1f;
private bool _externalMute = false;
private bool? _spatialOverride = null;
private AudioSource _audioSource;
private GameObject _bubbleObject;
private SpriteRenderer _bubbleRenderer;
private LipSync _lipSync;
private static AudioMixerGroup _cachedVoiceMixer;
private byte[] _compressedBuffer = new byte[8192];
private byte[] _decompressedBuffer = new byte[65536];
private float[] _floatBuffer;
private int _writePos = 0;
private int _bufferLength;
private AudioClip _streamingClip;
private int _sampleRate;
private bool _isRecording = false;
private float _lastVolume = 0f;
private bool _isToggleOn = false;
private bool _wasKeyDown = false;
private float _lastPacketTime = 0f;
private bool _isPlaying = false;
private bool _audioInitialized = false;
private bool _eventIsSpeaking = false;
private void Awake()
{
AttachedPlayer = ((Component)this).GetComponent<Player>();
if ((Object)(object)AttachedPlayer == (Object)null)
{
Object.Destroy((Object)(object)this);
}
else
{
((MonoBehaviour)this).StartCoroutine(WaitForSteamID());
}
}
private IEnumerator WaitForSteamID()
{
while (VoiceSystem.GetSteamIDFromPlayer(AttachedPlayer) == 0)
{
yield return (object)new WaitForSeconds(0.5f);
}
OwnerID = VoiceSystem.GetSteamIDFromPlayer(AttachedPlayer);
VoiceSystem.ActiveManagers.Add(this);
InitializeAudio();
InitializeBubble();
_lipSync = ((Component)this).gameObject.AddComponent<LipSync>();
_lipSync.Initialize(AttachedPlayer);
_audioInitialized = true;
CheckLocalPlayerStatus();
}
private void Start()
{
if (_audioInitialized)
{
CheckLocalPlayerStatus();
}
}
private void OnDestroy()
{
VoiceSystem.ActiveManagers.Remove(this);
if (IsLocalPlayer && _isRecording)
{
SteamUser.StopVoiceRecording();
}
}
public void SetExternalGain(float gain)
{
_externalGain = gain;
}
public void SetExternalMute(bool mute)
{
_externalMute = mute;
}
public void SetSpatialOverride(bool? spatial)
{
_spatialOverride = spatial;
ApplyAudioSettings();
}
private void InitializeAudio()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("VoiceEmitter");
val.transform.SetParent(((Component)this).transform, false);
val.transform.localPosition = new Vector3(0f, 1.7f, 0f);
_audioSource = val.AddComponent<AudioSource>();
_audioSource.loop = true;
_audioSource.playOnAwake = false;
_audioSource.dopplerLevel = 0f;
if ((Object)(object)_cachedVoiceMixer == (Object)null)
{
AudioMixerGroup[] array = Resources.FindObjectsOfTypeAll<AudioMixerGroup>();
AudioMixerGroup[] array2 = array;
foreach (AudioMixerGroup val2 in array2)
{
if (((Object)val2).name.IndexOf("Voice", StringComparison.OrdinalIgnoreCase) >= 0)
{
_cachedVoiceMixer = val2;
break;
}
}
}
if ((Object)(object)_cachedVoiceMixer != (Object)null)
{
_audioSource.outputAudioMixerGroup = _cachedVoiceMixer;
}
_sampleRate = (int)SteamUser.GetVoiceOptimalSampleRate();
int num = 88200;
_floatBuffer = new float[num];
_bufferLength = num;
_streamingClip = AudioClip.Create($"Voice_{OwnerID}", num, 1, _sampleRate, false);
_streamingClip.SetData(_floatBuffer, 0);
_audioSource.clip = _streamingClip;
_audioSource.Play();
ApplyAudioSettings();
}
private void InitializeBubble()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
_bubbleObject = new GameObject("VoiceBubble");
_bubbleObject.transform.SetParent(((Component)this).transform, false);
_bubbleObject.transform.localPosition = new Vector3(0f, 3.8f, 0f);
_bubbleRenderer = _bubbleObject.AddComponent<SpriteRenderer>();
_bubbleRenderer.sprite = LoadVoiceSprite();
_bubbleRenderer.color = Color.white;
_bubbleObject.SetActive(false);
}
private Sprite LoadVoiceSprite()
{
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Expected O, but got Unknown
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
try
{
Assembly executingAssembly = Assembly.GetExecutingAssembly();
string name = "VCLYSS.Icons.Voice.png";
using Stream stream = executingAssembly.GetManifestResourceStream(name);
if (stream != null)
{
byte[] array = new byte[stream.Length];
stream.Read(array, 0, array.Length);
Texture2D val = new Texture2D(2, 2);
if (ImageConversion.LoadImage(val, array))
{
return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
}
}
}
catch (Exception)
{
}
return CreateCircleSprite();
}
public void ApplyAudioSettings()
{
if (!((Object)(object)_audioSource == (Object)null))
{
_audioSource.volume = 1f;
if (IsLocalPlayer)
{
_audioSource.spatialBlend = 0f;
return;
}
bool flag = (_spatialOverride.HasValue ? _spatialOverride.Value : Main.CfgSpatialBlending.Value);
_audioSource.spatialBlend = (flag ? 1f : 0f);
_audioSource.minDistance = Main.CfgMinDistance.Value;
_audioSource.maxDistance = Main.CfgMaxDistance.Value;
_audioSource.rolloffMode = (AudioRolloffMode)1;
}
}
private void Update()
{
if (!Main.CfgEnabled.Value || !_audioInitialized)
{
return;
}
if (!IsLocalPlayer)
{
CheckLocalPlayerStatus();
}
if (!VoiceSystem.IsVoiceAllowedInLobby && !Main.CfgMicTest.Value)
{
return;
}
if (IsLocalPlayer)
{
HandleMicInput();
}
if (_isPlaying && Time.time - _lastPacketTime > 0.3f)
{
_audioSource.Stop();
FlushBuffer();
_isPlaying = false;
_lastVolume = 0f;
}
bool flag = IsSpeaking();
if (flag != _eventIsSpeaking)
{
_eventIsSpeaking = flag;
if (flag)
{
VoiceAPI.TriggerStartSpeaking(AttachedPlayer);
}
else
{
VoiceAPI.TriggerStopSpeaking(AttachedPlayer);
}
}
UpdateVisuals();
}
private void FlushBuffer()
{
Array.Clear(_floatBuffer, 0, _floatBuffer.Length);
_streamingClip.SetData(_floatBuffer, 0);
_writePos = 0;
}
private void HandleMicInput()
{
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: 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_00af: Unknown result type (might be due to invalid IL or missing references)
bool flag = CheckInputKeys();
if (flag && !_isRecording)
{
SteamUser.StartVoiceRecording();
_isRecording = true;
if (Main.CfgDebugMode.Value)
{
Main.Log.LogDebug((object)"Mic Recording Started");
}
}
else if (!flag && _isRecording)
{
SteamUser.StopVoiceRecording();
_isRecording = false;
}
if (!_isRecording)
{
return;
}
uint num = default(uint);
uint num2 = default(uint);
while (true)
{
SteamUser.GetAvailableVoice(ref num);
if (num == 0)
{
break;
}
EVoiceResult voice = SteamUser.GetVoice(true, _compressedBuffer, (uint)_compressedBuffer.Length, ref num2);
if ((int)voice != 0 || num2 == 0)
{
continue;
}
byte[] array = new byte[num2];
Array.Copy(_compressedBuffer, array, num2);
if (Main.CfgMicTest.Value)
{
ReceiveNetworkData(array);
continue;
}
VoicePacket voicePacket = new VoicePacket(array);
foreach (VoiceManager activeManager in VoiceSystem.ActiveManagers)
{
if ((Object)(object)activeManager != (Object)(object)this && (Object)(object)activeManager.AttachedPlayer != (Object)null)
{
CodeTalkerNetwork.SendNetworkPacket(activeManager.AttachedPlayer, (BinaryPacketBase)(object)voicePacket, (CompressionType)4, CompressionLevel.Fastest);
}
}
_lastVolume = Mathf.Lerp(_lastVolume, 0.8f, Time.deltaTime * 20f);
if ((Object)(object)_lipSync != (Object)null)
{
_lipSync.SetSpeaking();
}
_lastPacketTime = Time.time;
if (!_isPlaying)
{
_isPlaying = true;
}
}
}
public void ReceiveNetworkData(byte[] compressedData)
{
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
if (_externalMute || (IsLocalPlayer && !Main.CfgMicTest.Value))
{
return;
}
try
{
uint num = default(uint);
EVoiceResult val = SteamUser.DecompressVoice(compressedData, (uint)compressedData.Length, _decompressedBuffer, (uint)_decompressedBuffer.Length, ref num, (uint)_sampleRate);
if ((int)val == 0 && num != 0)
{
ProcessPCMData(_decompressedBuffer, (int)num);
if ((Object)(object)_lipSync != (Object)null)
{
_lipSync.SetSpeaking();
}
_lastPacketTime = Time.time;
}
}
catch (Exception ex)
{
if (Main.CfgDebugMode.Value)
{
Main.Log.LogWarning((object)$"[Security] Error processing voice packet for {OwnerID}: {ex.Message}");
}
}
}
private void ProcessPCMData(byte[] rawBytes, int length)
{
if (length > rawBytes.Length)
{
length = rawBytes.Length;
}
int num = length / 2;
float num2 = 0f;
float num3 = Main.CfgMasterVolume.Value * _externalGain;
for (int i = 0; i < num; i++)
{
short num4 = BitConverter.ToInt16(rawBytes, i * 2);
float num5 = (float)num4 / 32768f * num3;
if (num5 > 1f)
{
num5 = 1f;
}
if (num5 < -1f)
{
num5 = -1f;
}
_floatBuffer[_writePos] = num5;
_writePos = (_writePos + 1) % _bufferLength;
float num6 = Mathf.Abs(num5);
if (num6 > num2)
{
num2 = num6;
}
}
int num7 = _sampleRate / 2;
int writePos = _writePos;
for (int j = 0; j < num7; j++)
{
_floatBuffer[(writePos + j) % _bufferLength] = 0f;
}
_lastVolume = Mathf.Lerp(_lastVolume, num2, Time.deltaTime * 10f);
_streamingClip.SetData(_floatBuffer, 0);
if (!_audioSource.isPlaying)
{
_audioSource.Play();
_isPlaying = true;
}
int timeSamples = _audioSource.timeSamples;
int num8 = (_writePos - timeSamples + _bufferLength) % _bufferLength;
if (num8 > _sampleRate / 5)
{
int num9 = _writePos - _sampleRate / 20;
if (num9 < 0)
{
num9 += _bufferLength;
}
_audioSource.timeSamples = num9;
}
}
private void UpdateVisuals()
{
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_bubbleObject == (Object)null)
{
return;
}
if (!Main.CfgShowHeadIcons.Value)
{
_bubbleObject.SetActive(false);
return;
}
_lastVolume = Mathf.Lerp(_lastVolume, 0f, Time.deltaTime * 5f);
if (_lastVolume > 0.01f)
{
_bubbleObject.SetActive(true);
if ((Object)(object)Camera.main != (Object)null)
{
_bubbleObject.transform.LookAt(((Component)Camera.main).transform);
}
_bubbleObject.transform.Rotate(Vector3.up, 180f * Time.deltaTime);
float num = 0.5f + _lastVolume * 0.5f;
_bubbleObject.transform.localScale = Vector3.one * num;
}
else
{
_bubbleObject.SetActive(false);
}
}
public bool IsSpeaking()
{
return _lastVolume > 0.01f;
}
private void CheckLocalPlayerStatus()
{
if (!IsLocalPlayer && (Object)(object)Player._mainPlayer != (Object)null && (Object)(object)AttachedPlayer == (Object)(object)Player._mainPlayer)
{
IsLocalPlayer = true;
ApplyAudioSettings();
}
}
private bool CheckInputKeys()
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
if (Main.CfgMicTest.Value)
{
return true;
}
if (Main.CfgMicMode.Value == Main.MicMode.AlwaysOn)
{
return true;
}
if (Main.CfgMicMode.Value == Main.MicMode.PushToTalk)
{
return Input.GetKey(Main.CfgPushToTalk.Value);
}
if (Main.CfgMicMode.Value == Main.MicMode.Toggle)
{
bool key = Input.GetKey(Main.CfgPushToTalk.Value);
if (key && !_wasKeyDown)
{
_isToggleOn = !_isToggleOn;
}
_wasKeyDown = key;
return _isToggleOn;
}
return false;
}
private Sprite CreateCircleSprite()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: 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)
int num = 64;
Texture2D val = new Texture2D(num, num);
Color[] array = (Color[])(object)new Color[num * num];
float num2 = (float)num / 2f;
Vector2 val2 = default(Vector2);
((Vector2)(ref val2))..ctor(num2, num2);
for (int i = 0; i < num; i++)
{
for (int j = 0; j < num; j++)
{
float num3 = Vector2.Distance(new Vector2((float)j, (float)i), val2);
array[i * num + j] = ((num3 < num2) ? Color.white : Color.clear);
}
}
val.SetPixels(array);
val.Apply();
return Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num), new Vector2(0.5f, 0.5f));
}
}
public class LipSync : MonoBehaviour
{
public enum MouthCondition
{
Closed,
Open
}
private PlayerRaceModel _playerRaceModel;
private bool _initialized = false;
private Coroutine _mouthResetCoroutine;
public void Initialize(Player player)
{
try
{
if (!((Object)(object)player == (Object)null))
{
_playerRaceModel = ((Component)player).GetComponentInChildren<PlayerRaceModel>(true);
if ((Object)(object)_playerRaceModel == (Object)null && (Object)(object)player._pVisual != (Object)null)
{
_playerRaceModel = player._pVisual._playerRaceModel;
}
if (!((Object)(object)_playerRaceModel == (Object)null))
{
_initialized = true;
}
}
}
catch (Exception)
{
}
}
public void SetSpeaking()
{
if (!Main.CfgLipSync.Value || !_initialized || (Object)(object)_playerRaceModel == (Object)null)
{
return;
}
try
{
_playerRaceModel.Set_MouthCondition((MouthCondition)1, 0.15f);
if (_mouthResetCoroutine != null)
{
((MonoBehaviour)this).StopCoroutine(_mouthResetCoroutine);
}
_mouthResetCoroutine = ((MonoBehaviour)this).StartCoroutine(ResetMouthAfterDelay());
}
catch
{
}
}
private IEnumerator ResetMouthAfterDelay()
{
yield return (object)new WaitForSeconds(0.2f);
if ((Object)(object)_playerRaceModel != (Object)null)
{
_playerRaceModel.Set_MouthCondition((MouthCondition)0, 0f);
}
}
}
public class VoiceOverlay : MonoBehaviour
{
private GUIStyle _style;
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_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Expected O, but got Unknown
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Expected O, but got Unknown
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
if (!Main.CfgShowOverlay.Value)
{
return;
}
if (Main.CfgMicTest.Value)
{
GUIStyle val = new GUIStyle
{
fontSize = 20,
alignment = (TextAnchor)5,
fontStyle = (FontStyle)1
};
val.normal.textColor = Color.yellow;
GUI.Label(new Rect((float)(Screen.width - 320), 100f, 300f, 40f), "MIC TEST ACTIVE", val);
}
if (_style == null)
{
_style = new GUIStyle(GUI.skin.label);
_style.fontSize = 20;
_style.normal.textColor = Color.white;
_style.alignment = (TextAnchor)5;
_style.fontStyle = (FontStyle)1;
}
float num = 30f;
float num2 = (float)Screen.width - 270f;
float num3 = 20f;
GUILayout.BeginArea(new Rect(num2, num3, 250f, (float)Screen.height));
foreach (VoiceManager activeManager in VoiceSystem.ActiveManagers)
{
if (activeManager.IsSpeaking())
{
string text = (activeManager.IsLocalPlayer ? "Me" : (((Object)(object)activeManager.AttachedPlayer != (Object)null) ? activeManager.AttachedPlayer._nickname : "Unknown"));
GUILayout.Box(text, _style, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(num) });
}
}
GUILayout.EndArea();
}
}
internal static class ModInfo
{
public const string GUID = "com.VCLYSS.sftwre";
public const string NAME = "VCLYSS";
public const string VERSION = "1.0.0";
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}