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 XandIMod v1.0.2
RepoXandIMod.dll
Decompiled 12 months agousing 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.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using BepInEx; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Photon.Pun; 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("XandImmersion")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+cbe3960eb2e020714dd18782bb9665520294abed")] [assembly: AssemblyProduct("RepoXandIMod")] [assembly: AssemblyTitle("RepoXandIMod")] [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; } } } [Serializable] public class ArielSound { public AudioSource Source; public List<AudioClip> Sounds = new List<AudioClip>(); private AudioLowPassLogic LowPassLogic; private bool HasLowPassLogic; public AudioType Type; [Range(0f, 1f)] public float Volume = 0.5f; [Range(0f, 1f)] public float VolumeRandom = 0.1f; [Range(0f, 5f)] public float Pitch = 1f; [Range(0f, 2f)] public float PitchRandom = 0.1f; [Range(0f, 1f)] public float SpatialBlend = 1f; [Range(0f, 5f)] public float Doppler = 1f; [Range(0f, 1f)] public float ReverbMix = 1f; [Range(0f, 5f)] public float FalloffMultiplier = 1f; [Space] [Range(0f, 1f)] public float OffscreenVolume = 1f; [Range(0f, 1f)] public float OffscreenFalloff = 1f; [Space] public List<Collider> LowPassIgnoreColliders = new List<Collider>(); private AudioClip LoopClip; internal float LoopVolume; internal float LoopVolumeCurrent; internal float LoopVolumeFinal; internal float LoopPitch; internal float LoopFalloff; internal float LoopFalloffFinal; private float LoopOffScreenTime = 0.25f; private float LoopOffScreenTimer; private bool LoopOffScreen; private float LoopOffScreenVolume; private float LoopOffScreenFalloff; internal float StartTimeOverride = 999999f; private bool AudioInfoFetched; public AudioSource Play(AudioSource audioSource, float volumeMultiplier = 1f, float falloffMultiplier = 1f, float offscreenVolumeMultiplier = 1f, float offscreenFalloffMultiplier = 1f) { //IL_0065: 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) //IL_006c: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected I4, but got Unknown //IL_01fb: Unknown result type (might be due to invalid IL or missing references) int index = 0; if (Sounds.Count == 0) { return null; } AudioClip val = Sounds[index]; float pitch = Pitch + Random.Range(0f - PitchRandom, PitchRandom); if (!Object.op_Implicit((Object)(object)audioSource)) { GameObject audioDefault = AudioManager.instance.AudioDefault; AudioType type = Type; AudioType val2 = type; switch (val2 - 1) { case 0: audioDefault = AudioManager.instance.AudioHighFalloff; break; case 1: audioDefault = AudioManager.instance.AudioFootstep; break; case 2: audioDefault = AudioManager.instance.AudioMaterialImpact; break; case 3: audioDefault = AudioManager.instance.AudioCutscene; break; case 4: audioDefault = AudioManager.instance.AudioAmbienceBreaker; break; case 5: audioDefault = AudioManager.instance.AudioLowFalloff; break; case 6: audioDefault = AudioManager.instance.AudioGlobal; break; case 7: audioDefault = AudioManager.instance.AudioHigherFalloff; break; case 8: audioDefault = AudioManager.instance.AudioAttack; break; case 9: audioDefault = AudioManager.instance.AudioPersistent; break; } } else if (!((Behaviour)audioSource).enabled) { return null; } audioSource.minDistance *= FalloffMultiplier; audioSource.minDistance *= falloffMultiplier; audioSource.maxDistance *= FalloffMultiplier; audioSource.maxDistance *= falloffMultiplier; audioSource.clip = Sounds[index]; audioSource.volume = (Volume + Random.Range(0f - VolumeRandom, VolumeRandom)) * volumeMultiplier; if (SpatialBlend > 0f && (OffscreenVolume * offscreenVolumeMultiplier < 1f || OffscreenFalloff * offscreenFalloffMultiplier < 1f) && !SemiFunc.OnScreen(((Component)audioSource).transform.position, 0.1f, 0.1f)) { audioSource.volume *= OffscreenVolume * offscreenVolumeMultiplier; audioSource.minDistance *= OffscreenFalloff * offscreenFalloffMultiplier; audioSource.maxDistance *= OffscreenFalloff * offscreenFalloffMultiplier; } audioSource.spatialBlend = SpatialBlend; audioSource.reverbZoneMix = ReverbMix; audioSource.dopplerLevel = Doppler; audioSource.pitch = pitch; audioSource.loop = false; audioSource.volume = 2f; if (SpatialBlend > 0f) { StartLowPass(audioSource); } audioSource.Play(); return audioSource; } public void Stop() { Source.Stop(); } private void StartLowPass(AudioSource source) { LowPassLogic = ((Component)source).GetComponent<AudioLowPassLogic>(); if (Object.op_Implicit((Object)(object)LowPassLogic)) { if (LowPassIgnoreColliders.Count > 0) { LowPassLogic.LowPassIgnoreColliders.AddRange(LowPassIgnoreColliders); } LowPassLogic.Setup(); HasLowPassLogic = true; } } public void PlayLoop(bool playing, float fadeInSpeed, float fadeOutSpeed, float pitchMultiplier = 1f) { if (!AudioInfoFetched) { LoopClip = Sounds[Random.Range(0, Sounds.Count)]; Source.clip = LoopClip; } if (!playing) { if (Source.isPlaying) { LoopVolumeCurrent -= fadeOutSpeed * Time.deltaTime; LoopVolumeCurrent = Mathf.Clamp(LoopVolumeCurrent, 0f, LoopVolume); LoopOffScreenLogic(); Source.pitch = LoopPitch * pitchMultiplier; if (HasLowPassLogic) { LowPassLogic.Volume = LoopVolumeFinal; } else { Source.volume = LoopVolumeFinal; } if (LoopVolumeFinal <= 0f) { Source.Stop(); } } } else if (!Source.isPlaying) { LoopVolume = Volume + Random.Range(0f - VolumeRandom, VolumeRandom); LoopPitch = Pitch + Random.Range(0f - PitchRandom, PitchRandom); LoopVolumeCurrent = 0f; LoopVolumeFinal = LoopVolumeCurrent; Source.volume = LoopVolumeCurrent; Source.pitch = LoopPitch * pitchMultiplier; Source.spatialBlend = SpatialBlend; Source.reverbZoneMix = ReverbMix; Source.dopplerLevel = Doppler; AudioSource source = Source; source.minDistance *= FalloffMultiplier; AudioSource source2 = Source; source2.maxDistance *= FalloffMultiplier; LoopFalloff = Source.maxDistance; Source.time = Random.Range(0f, Source.clip.length); if (StartTimeOverride != 999999f) { Source.time = StartTimeOverride; } Source.loop = true; StartLowPass(Source); Source.Play(); } else { LoopVolumeCurrent += fadeInSpeed * Time.deltaTime; LoopVolumeCurrent = Mathf.Clamp(LoopVolumeCurrent, 0f, LoopVolume); LoopOffScreenLogic(); Source.pitch = LoopPitch * pitchMultiplier; if (HasLowPassLogic) { LowPassLogic.Volume = LoopVolumeFinal; } else { Source.volume = LoopVolumeFinal; } } } private void LoopOffScreenLogic() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) LoopVolumeFinal = LoopVolumeCurrent; if (!(SpatialBlend > 0f) || (!(OffscreenVolume < 1f) && !(OffscreenFalloff < 1f))) { return; } if (LoopOffScreenTimer <= 0f) { LoopOffScreenTimer = LoopOffScreenTime; LoopOffScreen = !SemiFunc.OnScreen(((Component)Source).transform.position, 0.1f, 0.1f); } else { LoopOffScreenTimer -= Time.deltaTime; } if (OffscreenVolume < 1f) { if (LoopOffScreen) { LoopOffScreenVolume = Mathf.Lerp(LoopOffScreenVolume, OffscreenVolume, 15f * Time.deltaTime); } else { LoopOffScreenVolume = Mathf.Lerp(LoopOffScreenVolume, 1f, 15f * Time.deltaTime); } LoopVolumeFinal *= LoopOffScreenVolume; } if (OffscreenFalloff < 1f) { if (LoopOffScreen) { LoopFalloffFinal = Mathf.Lerp(LoopFalloffFinal, LoopFalloff * OffscreenFalloff, 15f * Time.deltaTime); } else { LoopFalloffFinal = Mathf.Lerp(LoopFalloffFinal, LoopFalloff, 15f * Time.deltaTime); } if (HasLowPassLogic) { LowPassLogic.Falloff = LoopFalloffFinal; } else { Source.maxDistance = LoopFalloffFinal; } } } public static void CopySound(Sound from, Sound to) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) to.Source = from.Source; to.Sounds = from.Sounds; to.Type = from.Type; to.Volume = from.Volume; to.VolumeRandom = from.VolumeRandom; to.Pitch = from.Pitch; to.PitchRandom = from.PitchRandom; to.SpatialBlend = from.SpatialBlend; to.ReverbMix = from.ReverbMix; to.Doppler = from.Doppler; } } public static class SettingsLoader { public static Root Load(string filePath) { string text = File.ReadAllText(filePath); return JsonConvert.DeserializeObject<Root>(text); } } public class Assets { public List<Valuable> valuables { get; set; } } public class Keys { public string diagen { get; set; } public string ariel { get; set; } } public class Root { public Keys keys { get; set; } public Assets assets { get; set; } } public class Valuable { public string asset { get; set; } public string name { get; set; } [JsonProperty("use_stt")] public bool useSTT { get; set; } public string personality { get; set; } [JsonProperty("talkingTime")] public float talkingTime { get; set; } [JsonProperty("ariel_speaker")] public string arielSpeaker { get; set; } public Valuable(string asset, string name, bool useSTT, string personality, float talkingTime, string arielSpeaker) { this.asset = asset; this.name = name; this.useSTT = useSTT; this.personality = personality; this.talkingTime = talkingTime; this.arielSpeaker = arielSpeaker; } } public class ValuableInteraction : MonoBehaviourPunCallbacks { public class Message { public string message; public AudioClip? audio; public bool played; public Message(string msg) { message = msg; audio = null; played = false; } } public struct DiagenResponse { public string StatusMessage; public readonly bool Error; public readonly string? ErrorMessage; public DiagenResponse(string errorMessage, bool isError) { StatusMessage = (isError ? errorMessage : ""); Error = isError; ErrorMessage = (isError ? errorMessage : null); } public DiagenResponse(string statusMessage) { StatusMessage = statusMessage; Error = false; ErrorMessage = null; } } private struct DiagenRequestData { public string npc_name; public string player_name; public string core_description; public object llama_generation_params; public int history_length; public string[] history; } public struct ArielResponse { public AudioClip? audioClip; public readonly bool Error; public readonly string? StatusMessage; public ArielResponse(string statusMessage, bool isError = false) { audioClip = null; Error = isError; StatusMessage = statusMessage; } public ArielResponse(AudioClip audioClip, string statusMessage) { Error = false; this.audioClip = audioClip; StatusMessage = statusMessage; } } public struct ArielRequestData { public string sentence; public string audio_stream; public float temperature; public bool static_save; } private PhysGrabObject? physGrabObject; private AudioSource? audioSource; public ArielSound? voiceMessage; private PhotonView photonView; private Task? diagenTask = null; private Task? arielTask = null; private Root settings; private Valuable valuable; [Header("API Keys & Settings")] public string DiagenApiKey = "dd82386c-8ea9-4cd3-85b0-9dbad5216be7"; public string ArielApiKey = "8a58d8c8-6a61-438b-8d95-6723b3d8aa1b"; private int apiErrorCount = 0; public string ArielSpeaker = "Kid 3"; public float talkingTime = 15f; public string Personality = "You are a weird Vodoo Doll that is super annoyed by the player that it is being disturbed."; private string Instruction = "You try to be as annoying as possible to the player."; public string PlayerName = "Player"; public string NpcName = "Alan"; private const int HistoryLength = 10; public List<Message> messages = new List<Message>(); private bool isSpeakingSessionActive = false; private float currentSessionTimeRemaining = 0f; private int nextMessageToPlayIndex = 0; private void Start() { photonView = ((Component)this).GetComponent<PhotonView>(); if ((Object)(object)photonView == (Object)null) { Debug.LogError((object)"ValuableInteraction is missing a PhotonView component. Please add one."); ((Behaviour)this).enabled = false; return; } if ((Object)(object)((Component)this).GetComponent<AudioSource>() == (Object)null) { audioSource = ((Component)this).gameObject.AddComponent<AudioSource>(); } else { audioSource = ((Component)this).GetComponent<AudioSource>(); } string filePath = Path.Combine(Paths.PluginPath, "XandImmersion-RepoXandIMod", "settings.json"); settings = SettingsLoader.Load(filePath); DiagenApiKey = settings.keys.diagen; ArielApiKey = settings.keys.ariel; valuable = settings.assets.valuables.FirstOrDefault((Valuable v) => ((Object)this).name.Contains(v.asset, StringComparison.OrdinalIgnoreCase)); if (valuable == null) { valuable = new Valuable(((Object)this).name, NpcName, useSTT: true, Personality, talkingTime, ArielSpeaker); } physGrabObject = ((Component)this).GetComponent<PhysGrabObject>(); if ((Object)(object)physGrabObject == (Object)null) { Debug.LogWarning((object)"PhysGrabObject not found on this GameObject."); } else { Debug.Log((object)"PhysGrabObject successfully accessed!"); } Debug.Log((object)"Listing all components on this GameObject:"); Component[] components = ((Component)this).GetComponents<Component>(); foreach (Component val in components) { Debug.Log((object)(" - " + ((object)val).GetType().Name)); } voiceMessage = new ArielSound(); } private void Update() { if (PhotonNetwork.IsMasterClient) { MasterClientUpdate(); } else if (isSpeakingSessionActive) { currentSessionTimeRemaining -= Time.deltaTime; if (currentSessionTimeRemaining < 0f) { currentSessionTimeRemaining = 0f; } } } private void MasterClientUpdate() { if (apiErrorCount > 10) { return; } int num = messages.Count((Message m) => !m.played); if (!isSpeakingSessionActive) { bool flag = false; PlayerAvatar[] array = Object.FindObjectsOfType<PlayerAvatar>(); PlayerAvatar[] array2 = array; foreach (PlayerAvatar playerAvatar in array2) { if (PlayerIsInSight(playerAvatar) && PlayerIsTalking(playerAvatar)) { flag = true; break; } } if (flag && ((Object)(object)audioSource == (Object)null || !audioSource.isPlaying) && num > 0) { photonView.RPC("StartSpeakingSessionRPC", (RpcTarget)0, new object[1] { valuable.talkingTime }); } } else { currentSessionTimeRemaining -= Time.deltaTime; if (currentSessionTimeRemaining <= 0f && ((Object)(object)audioSource == (Object)null || !audioSource.isPlaying)) { photonView.RPC("StopSpeakingSessionRPC", (RpcTarget)0, Array.Empty<object>()); } else if ((Object)(object)audioSource == (Object)null || !audioSource.isPlaying) { int num2 = FindNextUnplayedMessageIndex(-1); if (num2 < messages.Count) { Message message = messages[num2]; if ((Object)(object)message.audio != (Object)null && !message.played) { photonView.RPC("PlayMessageRPC", (RpcTarget)0, new object[1] { num2 }); } else if ((Object)(object)message.audio == (Object)null && !message.played && (arielTask == null || arielTask.IsCompleted)) { arielTask = HandleArielAsyncCall(num2, message.message); } } } } if (num <= 2 && (diagenTask == null || diagenTask.IsCompleted)) { diagenTask = HandleDiagenInteractionAsync(); } if (messages.Count <= 0 || (arielTask != null && !arielTask.IsCompleted)) { return; } for (int j = 0; j < messages.Count; j++) { if ((Object)(object)messages[j].audio == (Object)null && !messages[j].played) { arielTask = HandleArielAsyncCall(j, messages[j].message); break; } } } private void AttemptPlayMessageAtIndex(int messageIndex) { if (messageIndex >= messages.Count || messageIndex < 0) { return; } Message message = messages[messageIndex]; if (!((Object)(object)message.audio != (Object)null) || message.played) { return; } if (voiceMessage == null) { voiceMessage = new ArielSound(); } if ((Object)(object)physGrabObject != (Object)null) { voiceMessage.Sounds = new List<AudioClip> { message.audio }; Debug.Log((object)$"Time: [{Time.time}]AttemptPlayMessageAtIndex: Playing message {messageIndex} ('{message.message}') with physGrabObject context."); AudioSource val = voiceMessage.Play(audioSource); if ((Object)(object)val != (Object)null) { audioSource = val; } } else { Debug.LogWarning((object)$"AttemptPlayMessageAtIndex: physGrabObject is null for message {messageIndex}. Cannot determine play position."); audioSource.clip = message.audio; audioSource.Play(); } } [PunRPC] private void StartSpeakingSessionRPC(float duration) { isSpeakingSessionActive = true; currentSessionTimeRemaining = duration; Debug.Log((object)$"RPC: Speaking session started by Master. Duration: {duration}"); } [PunRPC] private void StopSpeakingSessionRPC() { isSpeakingSessionActive = false; currentSessionTimeRemaining = 0f; if ((Object)(object)audioSource != (Object)null && audioSource.isPlaying) { audioSource.Stop(); } Debug.Log((object)"RPC: Speaking session stopped by Master."); } [PunRPC] private void AddNewMessagesRPC(string[] newDialogues) { bool flag = false; foreach (string dialogue in newDialogues) { if (!string.IsNullOrWhiteSpace(dialogue) && !messages.Any((Message m) => m.message == dialogue.Trim())) { messages.Add(new Message(dialogue.Trim())); flag = true; } } if (flag) { Debug.Log((object)$"RPC: Added {newDialogues.Length} new message(s). Total messages: {messages.Count}"); } } [PunRPC] private async void PlayMessageRPC(int messageIndex) { if (messageIndex < 0 || messageIndex >= messages.Count) { Debug.LogError((object)$"PlayMessageRPC: Invalid index {messageIndex}. Total messages: {messages.Count}"); return; } Message messageToPlay = messages[messageIndex]; if (messageToPlay.played && !PhotonNetwork.IsMasterClient) { Debug.LogWarning((object)$"PlayMessageRPC: Client already marked message {messageIndex} as played. Will play again if audio source is free."); } if ((Object)(object)messageToPlay.audio == (Object)null) { Debug.Log((object)$"PlayMessageRPC: Message {messageIndex} ('{messageToPlay.message}') has no audio locally. Attempting to fetch."); AudioClip fetchedAudio = await CallAriel(messageToPlay.message); if (!((Object)(object)fetchedAudio != (Object)null)) { Debug.LogError((object)$"PlayMessageRPC: Failed to fetch audio for message {messageIndex} ('{messageToPlay.message}'). Cannot play."); return; } messageToPlay.audio = fetchedAudio; } AttemptPlayMessageAtIndex(messageIndex); if (!messageToPlay.played) { messageToPlay.played = true; Debug.Log((object)$"RPC: Message {messageIndex} ('{messageToPlay.message}') is now being played and marked as played."); } else { Debug.Log((object)$"RPC: Message {messageIndex} ('{messageToPlay.message}') was already marked played, re-playing."); } } private async Task HandleDiagenInteractionAsync() { if (!PhotonNetwork.IsMasterClient) { return; } try { int originalMessageCount = messages.Count; if (await CallDiagen() && messages.Count > originalMessageCount) { List<string> newTexts = new List<string>(); for (int i = originalMessageCount; i < messages.Count; i++) { newTexts.Add(messages[i].message); } PhotonView obj = photonView; object[] array = newTexts.ToArray(); obj.RPC("AddNewMessagesRPC", (RpcTarget)3, array); } } catch (Exception ex) { Debug.LogError((object)$"Master HandleDiagenInteractionAsync Exception: {ex}"); } } private async Task HandleArielAsyncCall(int index, string message) { if (PhotonNetwork.IsMasterClient && index >= 0 && index < messages.Count && (Object)(object)messages[index].audio == (Object)null) { AudioClip audioClip = await CallAriel(message); if ((Object)(object)audioClip != (Object)null) { messages[index].audio = audioClip; Debug.Log((object)$"Master HandleArielAsyncCall: Audio fetched for message index {index}."); } } } public async Task<AudioClip?> CallAriel(string sentence) { ArielResponse arielResponse = await TextToAudio(sentence, valuable.arielSpeaker, ArielApiKey); if (arielResponse.Error) { Debug.LogError((object)("CallAriel API Error: " + arielResponse.StatusMessage + " for sentence: " + sentence)); if (PhotonNetwork.IsMasterClient) { apiErrorCount++; } return null; } return arielResponse.audioClip; } private int FindNextUnplayedMessageIndex(int searchStartIndex) { for (int i = searchStartIndex + 1; i < messages.Count; i++) { if (!messages[i].played && (Object)(object)messages[i].audio != (Object)null) { return i; } if ((Object)(object)messages[i].audio == (Object)null && !messages[i].played) { return messages.Count; } } return messages.Count; } private bool PlayerIsInSight(PlayerAvatar playerAvatar) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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) Vector3 position = ((Component)this).transform.position; if ((Object)(object)playerAvatar == (Object)null || (Object)(object)((Component)playerAvatar).transform == (Object)null) { Debug.LogError((object)"[Interaction] PlayerAvatar is null or its transform is null."); return false; } Vector3 position2 = ((Component)playerAvatar).transform.position; RaycastHit val = default(RaycastHit); bool flag = Physics.Linecast(position, position2, ref val); float num = Vector3.Distance(position, position2); return num <= 6f && flag; } private bool PlayerIsTalking(PlayerAvatar playerAvatar, float volumeThreshold = 0.001f) { if ((Object)(object)playerAvatar == (Object)null) { return false; } if ((Object)(object)playerAvatar.voiceChat == (Object)null) { return false; } return playerAvatar.voiceChat.isTalking && playerAvatar.voiceChat.clipLoudness > volumeThreshold; } public async Task<bool> CallDiagen() { CleanupHistory(); DiagenResponse diagenResponse = await GenerateText(valuable.name, Instruction, valuable.personality, PlayerName, "Api-Key " + DiagenApiKey); if (diagenResponse.Error) { Debug.LogError((object)("Diagen API Error: " + diagenResponse.ErrorMessage)); return false; } return true; } private void CleanupHistory() { if (messages.Count > 10) { int count = messages.Count - 10; messages.RemoveRange(0, count); } } public async Task<DiagenResponse> GenerateText(string npc_name, string instruction, string core_description, string player_name = "Player", string apiKey = "") { if (string.IsNullOrEmpty(apiKey)) { Debug.LogError((object)"[PlayAriel] API Key is empty or null."); return new DiagenResponse("API Key is required.", isError: true); } string[] history = new string[0]; int index = 0; foreach (Message msg2 in this.messages) { history = ((index % 2 != 0) ? new string[0] : new string[1] { msg2.message }); index++; } DiagenRequestData requestData = new DiagenRequestData { npc_name = npc_name, player_name = player_name, core_description = core_description + " Answer in no more than 3 sentences.", llama_generation_params = new { max_tokens = 80, temperature = 1.243, stream = true }, history_length = 10, history = history }; string jsonBody = JsonConvert.SerializeObject((object)requestData); byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonBody); string url = "https://diagen-api.xandimmersion.com/generate-stream"; UnityWebRequest www = new UnityWebRequest(url, "POST"); try { www.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw); www.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); www.SetRequestHeader("Content-Type", "application/json"); www.SetRequestHeader("Authorization", apiKey); UnityWebRequestAsyncOperation operation = www.SendWebRequest(); while (!((AsyncOperation)operation).isDone) { await Task.Yield(); } if ((int)www.result == 1) { string responseText = www.downloadHandler.text; string[] messages = Regex.Replace(responseText, "\\s+", " ").Split(new char[3] { '.', '!', '?' }, StringSplitOptions.RemoveEmptyEntries); if (messages.Length == 0 && !string.IsNullOrEmpty(responseText)) { messages = new string[1] { responseText }; } string[] array = messages; foreach (string msg in array) { if (!string.IsNullOrWhiteSpace(msg)) { this.messages.Add(new Message(msg.Trim())); } } return new DiagenResponse("Stream processed successfully."); } Debug.LogError((object)("[PlayAriel] Diagen API Error: " + www.error)); Debug.LogError((object)$"[PlayAriel] Diagen API Response Code: {www.responseCode}"); string errorDetails = www.error ?? "Unknown error"; if (www.downloadHandler != null && !string.IsNullOrEmpty(www.downloadHandler.text)) { errorDetails = errorDetails + ". Body: " + www.downloadHandler.text; } apiErrorCount++; Debug.LogError((object)("[PlayAriel] Full Diagen API Error Details: " + errorDetails)); return new DiagenResponse($"Diagen API Error ({www.responseCode}): {www.error}", isError: true); } finally { ((IDisposable)www)?.Dispose(); } } public async Task<ArielResponse> TextToAudio(string sentence, string speaker, string apiKey = "") { string url = "https://ariel-api.xandimmersion.com/tts/" + Uri.EscapeDataString(speaker); ArielRequestData requestData = new ArielRequestData { sentence = sentence, audio_stream = "true", temperature = 0f, static_save = true }; string jsonBody = JsonConvert.SerializeObject((object)requestData); byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonBody); UnityWebRequest www = new UnityWebRequest(url, "POST"); try { www.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw); www.downloadHandler = (DownloadHandler)new DownloadHandlerAudioClip(www.uri, (AudioType)20); www.SetRequestHeader("Content-Type", "application/json"); www.SetRequestHeader("Authorization", "Api-Key " + apiKey); UnityWebRequestAsyncOperation operation = www.SendWebRequest(); while (!((AsyncOperation)operation).isDone) { await Task.Yield(); } if ((int)www.result != 1) { apiErrorCount++; return new ArielResponse("Error While Sending: " + www.error, isError: true); } AudioClip audioClip = DownloadHandlerAudioClip.GetContent(www); if ((Object)(object)audioClip != (Object)null) { return new ArielResponse(audioClip, "AudioClip created succesfully."); } return new ArielResponse("AudioClip creation failed"); } finally { ((IDisposable)www)?.Dispose(); } } } namespace RepoXandIMod { [BepInPlugin("XandImmersion.RepoXandIMod", "RepoXandIMod", "1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class RepoXandIMod : BaseUnityPlugin { private void Awake() { ((BaseUnityPlugin)this).Logger.LogInfo((object)"RepoXandIMod loaded!"); } } }