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.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using REPOLib.Modules;
using Strobotnik.Klattersynth;
using UnityEngine;
[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("tongue")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1+0616cb263e2b8da20975f29505302f335ec69195")]
[assembly: AssemblyProduct("Tongue")]
[assembly: AssemblyTitle("tongue")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.1.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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace tongue
{
[BepInPlugin("sane.tongue", "Tongue", "1.0.0")]
[BepInProcess("REPO.exe")]
[BepInIncompatibility("Lavighju.espeakTTS")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[HarmonyPatch]
public class Tongue : BaseUnityPlugin
{
internal static ManualLogSource Logger;
public static NetworkedEvent LanguageChangeEvent;
private ConfigEntry<string> languageSetting;
private const int AUDIO_OUTPUT_SYNCHRONOUS = 0;
private const int espeakCHARS_UTF8 = 1;
private const int PHONEME_MODE_ASCII = 0;
private string currentSpeaker = "";
private Dictionary<string, string> languagePerPlayer = new Dictionary<string, string>();
public static readonly string[] language_list = new string[128]
{
"af", "am", "an", "ar", "as", "az", "ba", "be", "bg", "bn",
"bpy", "bs", "ca", "chr", "cmn", "cs", "cu", "cy", "da", "de",
"el", "en", "en-029", "en-gb-scotland", "en-gb-x-gbclan", "en-gb-x-gbcwmd", "en-gb-x-rp", "en-us", "eo", "es",
"es-419", "et", "eu", "fa", "fa-latn", "fi", "fr", "fr-be", "fr-ch", "ga",
"gd", "gn", "grc", "gu", "hak", "haw", "he", "hi", "hr", "ht",
"hu", "hy", "hyw", "ia", "id", "io", "is", "it", "ja", "jbo",
"ka", "kk", "kl", "kn", "ko", "kok", "ku", "ky", "la", "lb",
"lfn", "lt", "ltg", "lv", "mi", "mk", "ml", "mr", "ms", "mt",
"my", "nb", "nci", "ne", "nl", "nog", "om", "or", "pa", "pap",
"piqd", "pl", "pt", "pt-br", "py", "qdb", "qu", "quc", "qya", "ro",
"ru", "ru-lv", "sd", "shn", "si", "sjn", "sk", "sl", "smj", "sq",
"sr", "sv", "sw", "ta", "te", "th", "tk", "tn", "tr", "tt",
"ug", "uk", "ur", "uz", "vi", "vi-vn-x-central", "vi-vn-x-south", "yue"
};
public static Tongue Instance { get; private set; }
[DllImport("libespeak-ng.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int espeak_Initialize(int output, int buflength, string path, int options);
[DllImport("libespeak-ng.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int espeak_SetVoiceByName(string name);
[DllImport("libespeak-ng.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr espeak_TextToPhonemes(ref IntPtr textPtr, int textMode, int phonemeMode);
public static string phoneticize(string text, string language)
{
if (language == "en")
{
return text;
}
espeak_SetVoiceByName(language);
byte[] bytes = Encoding.UTF8.GetBytes(text + "\0");
IntPtr intPtr = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, intPtr, bytes.Length);
IntPtr textPtr = intPtr;
IntPtr intPtr2 = espeak_TextToPhonemes(ref textPtr, 1, 0);
if (intPtr2 != IntPtr.Zero)
{
string text2 = Marshal.PtrToStringAnsi(intPtr2);
Marshal.FreeHGlobal(intPtr);
return "[" + text2 + "]";
}
Marshal.FreeHGlobal(intPtr);
return "";
}
private void Awake()
{
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Expected O, but got Unknown
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Expected O, but got Unknown
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Expected O, but got Unknown
Instance = this;
((Object)((Component)Instance).gameObject).hideFlags = (HideFlags)61;
Logger = ((BaseUnityPlugin)this).Logger;
LanguageChangeEvent = new NetworkedEvent("LanguageChangeEvent", (Action<EventData>)HandleLanguageChangeEvent);
languageSetting = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Language", "de", new ConfigDescription("What language should the TTS emulate?", (AcceptableValueBase)(object)new AcceptableValueList<string>(language_list), Array.Empty<object>()));
string text;
try
{
text = Directory.GetFiles(Paths.PluginPath, "phondata-manifest", SearchOption.AllDirectories)[0].Replace("phondata-manifest", "");
}
catch
{
Logger.LogError((object)"espeak-ng-data not found!");
return;
}
Logger.LogInfo((object)("Attempting to load eSpeak data from " + text));
int num = espeak_Initialize(0, 0, text, 0);
if (num == -1)
{
Logger.LogError((object)("eSpeak failed to initialize from " + text + "! Not patching!"));
return;
}
Logger.LogInfo((object)"eSpeak loaded successfully! Patching Speak Method...");
Harmony val = new Harmony("sane.tongue");
val.PatchAll();
}
private static void HandleLanguageChangeEvent(EventData eventData)
{
string[] array = (string[])eventData.CustomData;
string key = array[0];
string value = array[1];
Instance.languagePerPlayer[key] = value;
}
[HarmonyPatch(typeof(WorldSpaceUIParent), "TTS")]
[HarmonyPrefix]
private static void TTSPrefix(PlayerAvatar _player, string _text, float _time)
{
string text = (string)typeof(PlayerAvatar).GetField("steamID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(_player);
Logger.LogDebug((object)("Current Speaker: " + text));
Instance.currentSpeaker = text;
}
public void ChangeTTSLanguageForSteamID(string steamID, string language)
{
if (!language_list.Contains(language))
{
Logger.LogError((object)("Language " + language + " is not valid. Perhaps someone is using a different version of Tongue."));
return;
}
PlayerAvatar val = SemiFunc.PlayerAvatarGetFromSteamID(steamID);
if ((Object)(object)val == (Object)null)
{
Logger.LogError((object)"Someone wants to change language but provided an invalid steamID!");
}
else if (languagePerPlayer.ContainsKey(steamID))
{
languagePerPlayer[steamID] = language;
}
else
{
languagePerPlayer.Add(steamID, language);
}
}
[HarmonyPatch(typeof(PlayerAvatar), "ChatMessageSend")]
[HarmonyPrefix]
private static void ChatMessageSendPrefix(PlayerAvatar __instance)
{
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
string text = (string)typeof(PlayerAvatar).GetField("steamID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(__instance);
string[] array = new string[2]
{
text,
Instance.languageSetting.Value
};
LanguageChangeEvent.RaiseEvent((object)array, NetworkingEvents.RaiseAll, SendOptions.SendReliable);
}
[HarmonyPatch(typeof(SpeechSynth), "speak", new Type[]
{
typeof(StringBuilder),
typeof(int),
typeof(VoicingSource),
typeof(bool)
})]
[HarmonyPrefix]
private static void SpeakPrefix(ref StringBuilder text, int voiceFundamentalFreq, VoicingSource voicingSource, ref bool bracketsAsPhonemes)
{
bracketsAsPhonemes = true;
string text2 = text.ToString();
text.Length = 0;
string valueOrDefault = Instance.languagePerPlayer.GetValueOrDefault(Instance.currentSpeaker, Instance.languageSetting.Value);
text.Append(phoneticize(text2, valueOrDefault));
if (valueOrDefault == "en")
{
return;
}
while (text.ToString().IndexOf(':') != -1)
{
int num = text.ToString().IndexOf(':');
text[num] = text[num - 1];
}
Dictionary<char, char> dictionary = new Dictionary<char, char>
{
{ 'C', 'S' },
{ 'Y', '3' },
{ 'E', 'e' },
{ 'a', 'A' },
{ 'W', '3' }
};
foreach (var (oldChar, newChar) in dictionary)
{
text.Replace(oldChar, newChar);
}
text2 = Regex.Replace(text.ToString(), "\\([^)]*\\)", "").Trim();
text.Length = 0;
text.Append(text2);
Logger.LogDebug((object)$"Saying word: {text}");
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "tongue";
public const string PLUGIN_NAME = "Tongue";
public const string PLUGIN_VERSION = "0.1.1";
}
}