using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BingBong_FR")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BingBong_FR")]
[assembly: AssemblyTitle("BingBong_FR")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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 BingBongFR
{
[BepInPlugin("fr.bingbong.standalone", "BingBong_FR", "1.0.0")]
public sealed class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "fr.bingbong.standalone";
public const string PluginName = "BingBong_FR";
public const string PluginVersion = "1.0.0";
internal static Plugin Instance;
internal static ManualLogSource ModLog;
internal static string PluginDirectory;
internal static ConfigEntry<bool> TwitchInteractionEnabled;
internal static ConfigEntry<string> TwitchChannel;
internal static ConfigEntry<string> TwitchBannedWords;
internal static ConfigEntry<int> TwitchUserCooldownSeconds;
private Harmony _harmony;
private void Awake()
{
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Expected O, but got Unknown
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_00e8: Expected O, but got Unknown
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Expected O, but got Unknown
Instance = this;
ModLog = ((BaseUnityPlugin)this).Logger;
PluginDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
TwitchInteractionEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Twitch", "Interaction du chat", false, "Active la commande !bingbong dans le chat Twitch.");
TwitchChannel = ((BaseUnityPlugin)this).Config.Bind<string>("Twitch", "Chaine", string.Empty, "Nom de la chaine Twitch a lire, sans # ni URL.");
TwitchBannedWords = ((BaseUnityPlugin)this).Config.Bind<string>("Twitch", "Mots bannis", string.Empty, "Mots ou expressions interdits, separes par des virgules.");
TwitchUserCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("Twitch", "Delai par spectateur (secondes)", 15, new ConfigDescription("Temps d'attente avant qu'un meme spectateur puisse reutiliser !bingbong. Mettre 0 pour desactiver.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 300), Array.Empty<object>()));
GameObject val = new GameObject("BingBong_FR_Runtime");
val.AddComponent<SoundPackRuntime>();
val.AddComponent<TwitchRuntime>();
val.AddComponent<TwitchMenu>();
Object.DontDestroyOnLoad((Object)val);
_harmony = new Harmony("fr.bingbong.standalone");
_harmony.PatchAll(typeof(InstantiatePatch));
_harmony.PatchAll(typeof(AddComponentPatch));
_harmony.PatchAll(typeof(BingBongUsedPatch));
_harmony.PatchAll(typeof(BingBongAnswerPatch));
_harmony.PatchAll(typeof(TwitchMenuCursorPatch));
_harmony.PatchAll(typeof(ItemInstanceDataPatch));
ModLog.LogInfo((object)"BingBong_FR 1.0.0 charge.");
}
private void OnDestroy()
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
internal static void SaveConfiguration()
{
Plugin instance = Instance;
if (instance != null)
{
((BaseUnityPlugin)instance).Config.Save();
}
}
}
[Serializable]
public sealed class SoundPackConfig
{
public string name = string.Empty;
public SoundPackEntry[] entries = Array.Empty<SoundPackEntry>();
}
[Serializable]
public sealed class SoundPackEntry
{
public string file = string.Empty;
public string subtitle = string.Empty;
}
public sealed class SoundPackRuntime : MonoBehaviour
{
private sealed class LoadedResponse
{
internal readonly int Index;
internal readonly SoundPackEntry Entry;
internal readonly AudioClip Clip;
internal LoadedResponse(int index, SoundPackEntry entry, AudioClip clip)
{
Index = index;
Entry = entry;
Clip = clip;
}
}
private static SoundPackRuntime _instance;
private readonly List<LoadedResponse> _responses = new List<LoadedResponse>();
private bool _loaded;
private void Awake()
{
if ((Object)(object)_instance != (Object)null && (Object)(object)_instance != (Object)(object)this)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
return;
}
_instance = this;
((MonoBehaviour)this).StartCoroutine(LoadSoundPack());
}
private IEnumerator LoadSoundPack()
{
string path = Path.Combine(Plugin.PluginDirectory, "response_sound_pack.json");
if (!File.Exists(path))
{
Plugin.ModLog.LogError((object)"response_sound_pack.json est introuvable a cote de BingBong_FR.dll.");
yield break;
}
SoundPackConfig config;
try
{
config = JsonConvert.DeserializeObject<SoundPackConfig>(File.ReadAllText(path));
}
catch (Exception ex)
{
Plugin.ModLog.LogError((object)("Impossible de lire response_sound_pack.json : " + ex));
yield break;
}
if (config == null || config.entries == null || config.entries.Length == 0)
{
Plugin.ModLog.LogError((object)"Le pack de sons ne contient aucune replique.");
yield break;
}
Plugin.ModLog.LogInfo((object)("Pack '" + (config.name ?? "sans nom") + "' lu : " + config.entries.Length + " repliques declarees."));
Array.Sort(config.entries, (SoundPackEntry left, SoundPackEntry right) => string.Compare(left?.file ?? string.Empty, right?.file ?? string.Empty, StringComparison.Ordinal));
for (int index = 0; index < config.entries.Length; index++)
{
SoundPackEntry entry = config.entries[index];
string text = Path.Combine(Plugin.PluginDirectory, entry.file);
if (!File.Exists(text))
{
Plugin.ModLog.LogError((object)("Fichier audio introuvable : " + entry.file));
continue;
}
string absoluteUri = new Uri(text).AbsoluteUri;
UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(absoluteUri, (AudioType)20);
try
{
yield return request.SendWebRequest();
if ((int)request.result != 1)
{
Plugin.ModLog.LogError((object)("Impossible de charger " + entry.file + " : " + request.error));
continue;
}
AudioClip content = DownloadHandlerAudioClip.GetContent(request);
if ((Object)(object)content == (Object)null)
{
Plugin.ModLog.LogError((object)("Le fichier audio est invalide : " + entry.file));
}
else
{
_responses.Add(new LoadedResponse(index, entry, content));
}
}
finally
{
((IDisposable)request)?.Dispose();
}
}
if (_responses.Count != config.entries.Length)
{
Plugin.ModLog.LogError((object)("Le pack est incomplet : " + _responses.Count + "/" + config.entries.Length + " repliques chargees. Le remplacement est annule pour conserver une synchronisation coherente."));
}
else
{
_loaded = true;
Plugin.ModLog.LogInfo((object)(_responses.Count + " repliques francaises chargees."));
ApplyToExistingBingBongs();
}
}
private void ApplyToExistingBingBongs()
{
Action_AskBingBong[] array = Resources.FindObjectsOfTypeAll<Action_AskBingBong>();
foreach (Action_AskBingBong action in array)
{
ApplyResponses(action);
}
}
private void ApplyResponses(Action_AskBingBong action)
{
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Expected O, but got Unknown
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Expected O, but got Unknown
if (_loaded && !((Object)(object)action == (Object)null) && (action.responses == null || action.responses.Length != _responses.Count || action.responses.Length == 0 || !(action.responses[0].subtitleID == "BINGBONG_FR_00")))
{
BingBongResponse[] array = (BingBongResponse[])(object)new BingBongResponse[_responses.Count];
for (int i = 0; i < _responses.Count; i++)
{
LoadedResponse loadedResponse = _responses[i];
string text = "BINGBONG_FR_" + loadedResponse.Index.ToString("D2");
AddSubtitle(text, loadedResponse.Entry.subtitle ?? string.Empty);
SFX_Instance val = ScriptableObject.CreateInstance<SFX_Instance>();
val.clips = (AudioClip[])(object)new AudioClip[1] { loadedResponse.Clip };
array[i] = new BingBongResponse
{
subtitleID = text,
sfx = val,
mouthCurve = new AnimationCurve(),
mouthCurveTime = 1f
};
}
action.responses = array;
Plugin.ModLog.LogInfo((object)("Repliques de Bing Bong remplacees sur l'instance " + ((Object)action).GetInstanceID() + "."));
}
}
private static void AddSubtitle(string id, string text)
{
LocalizedText.TryInitTables();
List<string> list = new List<string>();
for (int i = 0; i < 14; i++)
{
list.Add(text);
}
LocalizedText.mainTable[id] = list;
}
internal static void TryApplyToCreatedObject(Object created)
{
if ((Object)(object)_instance == (Object)null || !_instance._loaded || created == (Object)null)
{
return;
}
GameObject val = (GameObject)(object)((created is GameObject) ? created : null);
Component val2 = (Component)(object)((created is Component) ? created : null);
if ((Object)(object)val == (Object)null && (Object)(object)val2 != (Object)null)
{
val = val2.gameObject;
}
if (!((Object)(object)val == (Object)null))
{
Action_AskBingBong val3 = val.GetComponent<Action_AskBingBong>() ?? val.GetComponentInChildren<Action_AskBingBong>(true);
if ((Object)(object)val3 != (Object)null)
{
_instance.ApplyResponses(val3);
}
}
}
}
[HarmonyPatch(typeof(Object))]
internal static class InstantiatePatch
{
[HarmonyPostfix]
[HarmonyPatch("Instantiate", new Type[] { typeof(Object) })]
private static void Postfix(Object __result)
{
SoundPackRuntime.TryApplyToCreatedObject(__result);
}
}
[HarmonyPatch(typeof(GameObject))]
internal static class AddComponentPatch
{
[HarmonyPostfix]
[HarmonyPatch("AddComponent", new Type[] { typeof(Type) })]
private static void Postfix(Component __result)
{
SoundPackRuntime.TryApplyToCreatedObject((Object)(object)__result);
}
}
[HarmonyPatch(typeof(Action_AskBingBong), "RunAction")]
internal static class BingBongUsedPatch
{
[HarmonyPostfix]
private static void Postfix(Action_AskBingBong __instance)
{
TwitchRuntime.RecordUsedBingBong(__instance);
}
}
[HarmonyPatch(typeof(Action_AskBingBong), "Ask")]
internal static class BingBongAnswerPatch
{
[HarmonyPrefix]
private static void Prefix(Action_AskBingBong __instance)
{
TwitchRuntime.StopTwitchPresentation(__instance);
}
}
[HarmonyPatch(typeof(GUIManager), "UpdateWindowStatus")]
internal static class TwitchMenuCursorPatch
{
[HarmonyPostfix]
private static void Postfix(GUIManager __instance)
{
if (TwitchMenu.IsOpen)
{
TwitchMenu.ApplyGameUiState(__instance);
}
}
}
[HarmonyPatch(typeof(Item), "SetItemInstanceDataRPC")]
internal static class ItemInstanceDataPatch
{
[HarmonyPostfix]
private static void Postfix(Item __instance)
{
TwitchRuntime.TrackRecreatedItem(__instance);
}
}
internal static class ToySpeechEngine
{
private sealed class SynthesisResult
{
internal readonly string VoiceName;
internal readonly string Error;
private SynthesisResult(string voiceName, string error)
{
VoiceName = voiceName;
Error = error;
}
internal static SynthesisResult Succeeded(string voiceName)
{
return new SynthesisResult(voiceName, null);
}
internal static SynthesisResult Failed(string error)
{
return new SynthesisResult(null, error);
}
}
internal static IEnumerator Synthesize(string text, Action<string, string> completed)
{
string scriptPath = Path.Combine(Plugin.PluginDirectory, "BingBongFR-TTS.ps1");
if (!File.Exists(scriptPath))
{
completed(null, "Le moteur vocal BingBongFR-TTS.ps1 est introuvable.");
yield break;
}
string path = Path.Combine(Paths.CachePath, "BingBong_FR", "TTS");
string outputPath = Path.Combine(path, "bingbong-" + Guid.NewGuid().ToString("N") + ".wav");
Task<SynthesisResult> synthesisTask;
try
{
synthesisTask = Task.Run(() => SynthesizeInBackground(text, scriptPath, outputPath));
}
catch (Exception ex)
{
completed(null, "Impossible de lancer la synthese vocale : " + ex.Message);
yield break;
}
while (!synthesisTask.IsCompleted)
{
yield return null;
}
if (synthesisTask.IsCanceled)
{
SafeDelete(outputPath);
completed(null, "La synthese vocale a ete annulee.");
yield break;
}
if (synthesisTask.IsFaulted)
{
SafeDelete(outputPath);
completed(null, "Echec de la voix francaise : " + ShortError((synthesisTask.Exception?.GetBaseException())?.Message));
yield break;
}
SynthesisResult result = synthesisTask.Result;
if (!string.IsNullOrWhiteSpace(result.Error))
{
SafeDelete(outputPath);
completed(null, result.Error);
yield break;
}
if (!string.IsNullOrWhiteSpace(result.VoiceName))
{
Plugin.ModLog.LogDebug((object)("Voix TTS : " + result.VoiceName));
}
completed(outputPath, null);
}
private static SynthesisResult SynthesizeInBackground(string text, string scriptPath, string outputPath)
{
try
{
Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
string text2 = Convert.ToBase64String(Encoding.UTF8.GetBytes(text));
string text3 = Convert.ToBase64String(Encoding.UTF8.GetBytes(scriptPath));
string text4 = Convert.ToBase64String(Encoding.UTF8.GetBytes(outputPath));
string s = "$script=[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('" + text3 + "'));& $script -TextBase64 '" + text2 + "' -OutputBase64 '" + text4 + "'";
string text5 = Convert.ToBase64String(Encoding.Unicode.GetBytes(s));
string text6 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "WindowsPowerShell", "v1.0", "powershell.exe");
if (!File.Exists(text6))
{
text6 = "powershell.exe";
}
using Process process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = text6,
Arguments = "-NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand " + text5,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
}
};
process.Start();
if (!process.WaitForExit(25000))
{
try
{
process.Kill();
}
catch
{
}
SafeDelete(outputPath);
return SynthesisResult.Failed("La synthese vocale a depasse 25 secondes.");
}
string text7 = process.StandardOutput.ReadToEnd().Trim();
string text8 = process.StandardError.ReadToEnd().Trim();
if (process.ExitCode != 0 || !File.Exists(outputPath))
{
SafeDelete(outputPath);
string message = (string.IsNullOrWhiteSpace(text8) ? text7 : text8);
return SynthesisResult.Failed("Echec de la voix francaise : " + ShortError(message));
}
return SynthesisResult.Succeeded(text7);
}
catch (Exception ex)
{
SafeDelete(outputPath);
return SynthesisResult.Failed("Impossible de demarrer la voix Windows : " + ShortError(ex.Message));
}
}
internal static void SafeDelete(string path)
{
if (string.IsNullOrEmpty(path))
{
return;
}
try
{
if (File.Exists(path))
{
File.Delete(path);
}
}
catch (Exception ex)
{
Plugin.ModLog.LogDebug((object)("Nettoyage TTS impossible : " + ex.Message));
}
}
private static string ShortError(string message)
{
if (string.IsNullOrWhiteSpace(message))
{
return "aucun detail disponible";
}
string text = message.Replace('\r', ' ').Replace('\n', ' ').Trim();
if (text.Length > 180)
{
return text.Substring(0, 180) + "...";
}
return text;
}
}
internal sealed class TwitchChatMessage
{
internal readonly string Id;
internal readonly string UserId;
internal readonly string DisplayName;
internal readonly string Text;
internal TwitchChatMessage(string id, string userId, string displayName, string text)
{
Id = id;
UserId = userId;
DisplayName = displayName;
Text = text;
}
}
internal sealed class TwitchIrcClient : IDisposable
{
private const string Host = "irc.chat.twitch.tv";
private const int Port = 6697;
private readonly Action<TwitchChatMessage> _messageHandler;
private readonly object _stateLock = new object();
private CancellationTokenSource _cancellation;
private TcpClient _tcpClient;
private string _status = "Deconnecte";
private string _channel = string.Empty;
internal string Channel
{
get
{
lock (_stateLock)
{
return _channel;
}
}
}
internal string Status
{
get
{
lock (_stateLock)
{
return _status;
}
}
}
internal bool IsRunning
{
get
{
lock (_stateLock)
{
return _cancellation != null && !_cancellation.IsCancellationRequested;
}
}
}
internal TwitchIrcClient(Action<TwitchChatMessage> messageHandler)
{
_messageHandler = messageHandler;
}
internal void Connect(string channel)
{
Disconnect();
CancellationTokenSource cancellation = new CancellationTokenSource();
lock (_stateLock)
{
_channel = channel;
_status = "Connexion a #" + channel + "...";
_cancellation = cancellation;
}
Task.Run(() => RunConnectionLoop(channel, cancellation.Token));
}
internal void Disconnect(string status = "Deconnecte")
{
CancellationTokenSource cancellation;
TcpClient tcpClient;
lock (_stateLock)
{
cancellation = _cancellation;
tcpClient = _tcpClient;
_cancellation = null;
_tcpClient = null;
_channel = string.Empty;
_status = status;
}
try
{
cancellation?.Cancel();
tcpClient?.Close();
}
catch
{
}
finally
{
cancellation?.Dispose();
}
}
public void Dispose()
{
Disconnect();
}
private async Task RunConnectionLoop(string channel, CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
await RunSingleConnection(channel, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
}
catch (OperationCanceledException)
{
break;
}
catch (Exception ex2)
{
if (!cancellationToken.IsCancellationRequested)
{
SetStatus("Connexion perdue : " + ShortError(ex2.Message));
Plugin.ModLog.LogWarning((object)("Twitch IRC : " + ex2.Message));
}
}
if (cancellationToken.IsCancellationRequested)
{
break;
}
SetStatus("Reconnexion a #" + channel + " dans 5 s...");
try
{
await Task.Delay(5000, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
}
catch (OperationCanceledException)
{
break;
}
}
}
private async Task RunSingleConnection(string channel, CancellationToken cancellationToken)
{
TcpClient client = new TcpClient();
lock (_stateLock)
{
if (_cancellation == null || cancellationToken.IsCancellationRequested)
{
client.Dispose();
return;
}
_tcpClient = client;
}
await client.ConnectAsync("irc.chat.twitch.tv", 6697).ConfigureAwait(continueOnCapturedContext: false);
cancellationToken.ThrowIfCancellationRequested();
using SslStream sslStream = new SslStream(client.GetStream(), leaveInnerStreamOpen: false);
await sslStream.AuthenticateAsClientAsync("irc.chat.twitch.tv").ConfigureAwait(continueOnCapturedContext: false);
cancellationToken.ThrowIfCancellationRequested();
using StreamReader reader = new StreamReader(sslStream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
using StreamWriter writer = new StreamWriter(sslStream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false))
{
AutoFlush = true,
NewLine = "\r\n"
};
string anonymousNick = "justinfan" + (uint)Guid.NewGuid().GetHashCode();
await writer.WriteLineAsync("PASS SCHMOOPIIE").ConfigureAwait(continueOnCapturedContext: false);
await writer.WriteLineAsync("NICK " + anonymousNick).ConfigureAwait(continueOnCapturedContext: false);
await writer.WriteLineAsync("CAP REQ :twitch.tv/tags twitch.tv/commands").ConfigureAwait(continueOnCapturedContext: false);
await writer.WriteLineAsync("JOIN #" + channel).ConfigureAwait(continueOnCapturedContext: false);
SetStatus("Connexion a #" + channel + "...");
while (!cancellationToken.IsCancellationRequested)
{
string text = await reader.ReadLineAsync().ConfigureAwait(continueOnCapturedContext: false);
if (text == null)
{
throw new IOException("Twitch a ferme la connexion.");
}
if (text.StartsWith("PING", StringComparison.Ordinal))
{
await writer.WriteLineAsync("PONG" + text.Substring(4)).ConfigureAwait(continueOnCapturedContext: false);
continue;
}
if (text.IndexOf(" 001 ", StringComparison.Ordinal) >= 0 || text.IndexOf(" JOIN #" + channel, StringComparison.OrdinalIgnoreCase) >= 0)
{
SetStatus("Connecte a #" + channel);
}
TwitchChatMessage twitchChatMessage = TryParsePrivateMessage(text);
if (twitchChatMessage != null)
{
_messageHandler(twitchChatMessage);
}
}
}
internal static TwitchChatMessage TryParsePrivateMessage(string line)
{
int num = line.IndexOf(" PRIVMSG #", StringComparison.Ordinal);
if (num < 0)
{
return null;
}
int num2 = line.IndexOf(" :", num + 10, StringComparison.Ordinal);
if (num2 < 0 || num2 + 2 >= line.Length)
{
return null;
}
Dictionary<string, string> dictionary = ParseTags(line);
string text = ((line[0] == '@') ? line.Substring(line.IndexOf(' ') + 1, num - line.IndexOf(' ') - 1) : line.Substring(0, num));
int num3 = text.IndexOf(':');
int num4 = text.IndexOf('!');
string text2 = ((num4 > num3) ? text.Substring(num3 + 1, num4 - num3 - 1) : "spectateur");
if (!dictionary.TryGetValue("display-name", out var value) || string.IsNullOrWhiteSpace(value))
{
value = text2;
}
if (!dictionary.TryGetValue("id", out var value2))
{
value2 = string.Empty;
}
if (!dictionary.TryGetValue("user-id", out var value3))
{
value3 = string.Empty;
}
string text3 = line.Substring(num2 + 2);
return new TwitchChatMessage(value2, value3, value, text3);
}
private static Dictionary<string, string> ParseTags(string line)
{
Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
if (string.IsNullOrEmpty(line) || line[0] != '@')
{
return dictionary;
}
int num = line.IndexOf(' ');
if (num <= 1)
{
return dictionary;
}
string[] array = line.Substring(1, num - 1).Split(';');
foreach (string text in array)
{
int num2 = text.IndexOf('=');
if (num2 < 0)
{
dictionary[text] = string.Empty;
}
else
{
dictionary[text.Substring(0, num2)] = UnescapeTag(text.Substring(num2 + 1));
}
}
return dictionary;
}
private static string UnescapeTag(string value)
{
StringBuilder stringBuilder = new StringBuilder(value.Length);
for (int i = 0; i < value.Length; i++)
{
if (value[i] != '\\' || i + 1 >= value.Length)
{
stringBuilder.Append(value[i]);
continue;
}
char c = value[++i];
switch (c)
{
case 's':
stringBuilder.Append(' ');
break;
case ':':
stringBuilder.Append(';');
break;
case 'r':
stringBuilder.Append('\r');
break;
case 'n':
stringBuilder.Append('\n');
break;
case '\\':
stringBuilder.Append('\\');
break;
default:
stringBuilder.Append(c);
break;
}
}
return stringBuilder.ToString();
}
private void SetStatus(string status)
{
lock (_stateLock)
{
if (_cancellation != null && !_cancellation.IsCancellationRequested)
{
_status = status;
}
}
}
private static string ShortError(string message)
{
if (string.IsNullOrWhiteSpace(message))
{
return "erreur inconnue";
}
if (message.Length > 80)
{
return message.Substring(0, 80) + "...";
}
return message;
}
}
public sealed class TwitchMenu : MonoBehaviour
{
private static TwitchMenu _instance;
private static readonly FieldInfo WindowShowingCursorField = typeof(GUIManager).GetField("<windowShowingCursor>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo WindowBlockingInputField = typeof(GUIManager).GetField("<windowBlockingInput>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);
private bool _isOpen;
private bool _enabledDraft;
private string _channelDraft = string.Empty;
private string _bannedWordsDraft = string.Empty;
private int _userCooldownDraft;
private Vector2 _bannedWordsScroll;
private CursorLockMode _previousCursorLock;
private bool _previousCursorVisible;
private Texture2D _overlayTexture;
private Texture2D _shadowTexture;
private Texture2D _panelTexture;
private Texture2D _headerTexture;
private Texture2D _fieldTexture;
private Texture2D _greenTexture;
private Texture2D _orangeTexture;
private Texture2D _mutedTexture;
private GUIStyle _titleStyle;
private GUIStyle _versionStyle;
private GUIStyle _subtitleStyle;
private GUIStyle _labelStyle;
private GUIStyle _smallStyle;
private GUIStyle _fieldStyle;
private GUIStyle _areaStyle;
private GUIStyle _primaryButtonStyle;
private GUIStyle _secondaryButtonStyle;
private GUIStyle _toggleOnStyle;
private GUIStyle _toggleOffStyle;
private GUIStyle _statusStyle;
private GUIStyle _counterStyle;
internal static bool IsOpen
{
get
{
if ((Object)(object)_instance != (Object)null)
{
return _instance._isOpen;
}
return false;
}
}
private void Awake()
{
_instance = this;
LoadDrafts();
CreateTextures();
}
private void Update()
{
if (Input.GetKeyDown((KeyCode)291))
{
SetOpen(!_isOpen);
}
else if (_isOpen && Input.GetKeyDown((KeyCode)27))
{
SetOpen(open: false);
}
if (_isOpen)
{
ForceMenuInputState();
}
}
private void LateUpdate()
{
if (_isOpen)
{
ForceMenuInputState();
}
}
private void OnGUI()
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_0173: Unknown result type (might be due to invalid IL or missing references)
//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0240: Unknown result type (might be due to invalid IL or missing references)
//IL_0297: Unknown result type (might be due to invalid IL or missing references)
//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
//IL_032b: Unknown result type (might be due to invalid IL or missing references)
//IL_0354: Unknown result type (might be due to invalid IL or missing references)
//IL_037d: Unknown result type (might be due to invalid IL or missing references)
//IL_039a: Unknown result type (might be due to invalid IL or missing references)
//IL_0411: Unknown result type (might be due to invalid IL or missing references)
//IL_0439: Unknown result type (might be due to invalid IL or missing references)
//IL_0482: Unknown result type (might be due to invalid IL or missing references)
//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
//IL_0500: Unknown result type (might be due to invalid IL or missing references)
//IL_0512: Expected O, but got Unknown
//IL_051d: Unknown result type (might be due to invalid IL or missing references)
//IL_0520: Unknown result type (might be due to invalid IL or missing references)
//IL_0525: Unknown result type (might be due to invalid IL or missing references)
//IL_0529: Unknown result type (might be due to invalid IL or missing references)
//IL_052e: Unknown result type (might be due to invalid IL or missing references)
//IL_054c: Unknown result type (might be due to invalid IL or missing references)
//IL_058b: Unknown result type (might be due to invalid IL or missing references)
//IL_05c8: Unknown result type (might be due to invalid IL or missing references)
//IL_060b: Unknown result type (might be due to invalid IL or missing references)
//IL_066a: Unknown result type (might be due to invalid IL or missing references)
//IL_06e0: Unknown result type (might be due to invalid IL or missing references)
//IL_072c: Unknown result type (might be due to invalid IL or missing references)
if (_isOpen)
{
ForceMenuInputState();
if (_titleStyle == null)
{
CreateStyles();
}
GUI.depth = -1000;
GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)_overlayTexture);
float num = Mathf.Min(700f, (float)Screen.width - 32f);
float num2 = Mathf.Min(700f, (float)Screen.height - 24f);
Rect val = default(Rect);
((Rect)(ref val))..ctor(Mathf.Round(((float)Screen.width - num) * 0.5f), Mathf.Round(((float)Screen.height - num2) * 0.5f), num, num2);
GUI.DrawTexture(new Rect(((Rect)(ref val)).x + 9f, ((Rect)(ref val)).y + 11f, ((Rect)(ref val)).width, ((Rect)(ref val)).height), (Texture)(object)_shadowTexture);
GUI.DrawTexture(val, (Texture)(object)_panelTexture);
GUI.DrawTexture(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width, 102f), (Texture)(object)_headerTexture);
GUI.DrawTexture(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 102f, ((Rect)(ref val)).width, 4f), (Texture)(object)_greenTexture);
GUI.Label(new Rect(((Rect)(ref val)).x + 34f, ((Rect)(ref val)).y + 20f, ((Rect)(ref val)).width - 220f, 38f), "BINGBONG_FR / TWITCH LINK", _titleStyle);
GUI.Label(new Rect(((Rect)(ref val)).x + ((Rect)(ref val)).width - 180f, ((Rect)(ref val)).y + 22f, 146f, 34f), "VERSION 1.0.0", _versionStyle);
GUI.Label(new Rect(((Rect)(ref val)).x + 35f, ((Rect)(ref val)).y + 61f, ((Rect)(ref val)).width - 70f, 28f), "Chaque joueur relie son tchat. Bing Bong parle pour toute la partie.", _subtitleStyle);
float num3 = ((Rect)(ref val)).x + 36f;
float num4 = ((Rect)(ref val)).width - 72f;
float num5 = ((Rect)(ref val)).y + 128f;
GUI.Label(new Rect(num3, num5, num4, 24f), "INTERACTION DU TCHAT", _labelStyle);
num5 += 30f;
GUIStyle val2 = (_enabledDraft ? _toggleOnStyle : _toggleOffStyle);
string text = (_enabledDraft ? "● ACTIVE - !bingbong est autorise" : "○ DESACTIVE - les messages sont ignores");
if (GUI.Button(new Rect(num3, num5, num4, 44f), text, val2))
{
_enabledDraft = !_enabledDraft;
}
num5 += 65f;
GUI.Label(new Rect(num3, num5, num4, 24f), "CHAINE TWITCH", _labelStyle);
num5 += 29f;
_channelDraft = GUI.TextField(new Rect(num3, num5, num4, 42f), _channelDraft, 80, _fieldStyle);
num5 += 47f;
GUI.Label(new Rect(num3 + 3f, num5, num4, 22f), "Nom de la chaine, lien Twitch ou #chaine", _smallStyle);
num5 += 38f;
GUI.Label(new Rect(num3, num5, num4, 24f), "DELAI PAR SPECTATEUR", _labelStyle);
num5 += 29f;
GUI.DrawTexture(new Rect(num3, num5, num4, 42f), (Texture)(object)_fieldTexture);
if (GUI.Button(new Rect(num3, num5, 52f, 42f), "-", _secondaryButtonStyle))
{
_userCooldownDraft = Mathf.Max(0, _userCooldownDraft - 1);
}
string text2 = ((_userCooldownDraft == 0) ? "DESACTIVE" : (_userCooldownDraft + ((_userCooldownDraft == 1) ? " SECONDE" : " SECONDES")));
GUI.Label(new Rect(num3 + 58f, num5, num4 - 116f, 42f), text2, _counterStyle);
if (GUI.Button(new Rect(num3 + num4 - 52f, num5, 52f, 42f), "+", _secondaryButtonStyle))
{
_userCooldownDraft = Mathf.Min(300, _userCooldownDraft + 1);
}
num5 += 47f;
GUI.Label(new Rect(num3 + 3f, num5, num4, 22f), "Attente imposee a chaque utilisateur entre deux commandes", _smallStyle);
num5 += 38f;
GUI.Label(new Rect(num3, num5, num4, 24f), "LISTE DE MOTS BANNIS", _labelStyle);
num5 += 29f;
Rect val3 = default(Rect);
((Rect)(ref val3))..ctor(num3, num5, num4, 84f);
Rect val4 = default(Rect);
((Rect)(ref val4))..ctor(0f, 0f, num4 - 22f, Mathf.Max(78f, _areaStyle.CalcHeight(new GUIContent(_bannedWordsDraft), num4 - 28f)));
_bannedWordsScroll = GUI.BeginScrollView(val3, _bannedWordsScroll, val4, false, true);
_bannedWordsDraft = GUI.TextArea(new Rect(0f, 0f, ((Rect)(ref val4)).width, ((Rect)(ref val4)).height), _bannedWordsDraft, 2000, _areaStyle);
GUI.EndScrollView();
num5 += 90f;
GUI.Label(new Rect(num3 + 3f, num5, num4, 22f), "Un mot par ligne, ou separes par des virgules", _smallStyle);
float num6 = ((Rect)(ref val)).y + ((Rect)(ref val)).height - 100f;
float num7 = 164f;
if (GUI.Button(new Rect(num3, num6, num7, 46f), "TESTER LA VOIX", _secondaryButtonStyle))
{
TwitchRuntime.Instance?.TestVoice();
}
if (GUI.Button(new Rect(num3 + num7 + 14f, num6, num4 - num7 - 14f, 46f), "ENREGISTRER ET CONNECTER", _primaryButtonStyle))
{
SaveDrafts();
}
Rect val5 = default(Rect);
((Rect)(ref val5))..ctor(num3, ((Rect)(ref val)).y + ((Rect)(ref val)).height - 42f, num4, 25f);
GUI.DrawTexture(new Rect(((Rect)(ref val5)).x, ((Rect)(ref val5)).y + 2f, 8f, 8f), (Texture)(object)StatusColorTexture());
string text3 = TwitchRuntime.Instance?.ConnectionStatus ?? "Initialisation...";
string text4 = TwitchRuntime.Instance?.ActivityStatus ?? string.Empty;
GUI.Label(new Rect(((Rect)(ref val5)).x + 16f, ((Rect)(ref val5)).y - 3f, ((Rect)(ref val5)).width - 120f, ((Rect)(ref val5)).height), text3 + " | " + text4, _statusStyle);
GUI.Label(new Rect(((Rect)(ref val5)).x + ((Rect)(ref val5)).width - 92f, ((Rect)(ref val5)).y - 3f, 92f, ((Rect)(ref val5)).height), "F10 FERMER", _smallStyle);
}
}
private void SetOpen(bool open)
{
//IL_0037: 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)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
if (_isOpen != open)
{
_isOpen = open;
if (open)
{
LoadDrafts();
_previousCursorLock = Cursor.lockState;
_previousCursorVisible = Cursor.visible;
ForceMenuInputState();
}
else
{
Cursor.lockState = _previousCursorLock;
Cursor.visible = _previousCursorVisible;
}
}
}
private static void ForceMenuInputState()
{
Cursor.lockState = (CursorLockMode)0;
Cursor.visible = true;
ApplyGameUiState(GUIManager.instance);
}
internal static void ApplyGameUiState(GUIManager manager)
{
if (!((Object)(object)manager == (Object)null))
{
WindowShowingCursorField?.SetValue(manager, true);
WindowBlockingInputField?.SetValue(manager, true);
}
}
private void LoadDrafts()
{
_enabledDraft = Plugin.TwitchInteractionEnabled.Value;
_channelDraft = Plugin.TwitchChannel.Value;
_bannedWordsDraft = string.Join("\n", TwitchRuntime.ParseBannedWords(Plugin.TwitchBannedWords.Value));
_userCooldownDraft = Plugin.TwitchUserCooldownSeconds.Value;
}
private void SaveDrafts()
{
string text = TwitchRuntime.NormalizeChannel(_channelDraft);
string[] value = TwitchRuntime.ParseBannedWords(_bannedWordsDraft);
Plugin.TwitchInteractionEnabled.Value = _enabledDraft;
Plugin.TwitchChannel.Value = text;
Plugin.TwitchBannedWords.Value = string.Join(", ", value);
Plugin.TwitchUserCooldownSeconds.Value = Mathf.Clamp(_userCooldownDraft, 0, 300);
Plugin.SaveConfiguration();
_channelDraft = text;
_bannedWordsDraft = string.Join("\n", value);
TwitchRuntime.Instance?.ApplyConfiguration();
}
private Texture2D StatusColorTexture()
{
string text = TwitchRuntime.Instance?.ConnectionStatus ?? string.Empty;
if (text.StartsWith("Connecte", StringComparison.OrdinalIgnoreCase))
{
return _greenTexture;
}
if (text.IndexOf("Connexion", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Reconnexion", StringComparison.OrdinalIgnoreCase) >= 0)
{
return _orangeTexture;
}
return _mutedTexture;
}
private void CreateTextures()
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
_overlayTexture = MakeTexture(new Color(0.015f, 0.027f, 0.032f, 0.78f));
_shadowTexture = MakeTexture(new Color(0f, 0f, 0f, 0.55f));
_panelTexture = MakeTexture(new Color(0.055f, 0.082f, 0.088f, 0.99f));
_headerTexture = MakeTexture(new Color(0.075f, 0.13f, 0.13f, 1f));
_fieldTexture = MakeTexture(new Color(0.025f, 0.045f, 0.048f, 1f));
_greenTexture = MakeTexture(new Color(0.52f, 0.78f, 0.24f, 1f));
_orangeTexture = MakeTexture(new Color(0.96f, 0.58f, 0.17f, 1f));
_mutedTexture = MakeTexture(new Color(0.42f, 0.49f, 0.48f, 1f));
}
private void CreateStyles()
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: 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_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Expected O, but got Unknown
//IL_0055: 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_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Expected O, but got Unknown
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Expected O, but got Unknown
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Expected O, but got Unknown
//IL_0131: Unknown result type (might be due to invalid IL or missing references)
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_014c: 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_0170: Expected O, but got Unknown
//IL_0177: 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_0184: Unknown result type (might be due to invalid IL or missing references)
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
//IL_01a8: Expected O, but got Unknown
//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0211: Unknown result type (might be due to invalid IL or missing references)
//IL_0220: Expected O, but got Unknown
//IL_0236: Unknown result type (might be due to invalid IL or missing references)
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_0284: Unknown result type (might be due to invalid IL or missing references)
//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
//IL_02b7: Expected O, but got Unknown
//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
//IL_0300: Expected O, but got Unknown
GUIStyle val = new GUIStyle(GUI.skin.label)
{
fontSize = 25,
fontStyle = (FontStyle)1,
alignment = (TextAnchor)3
};
val.normal.textColor = new Color(0.91f, 0.98f, 0.83f);
_titleStyle = val;
GUIStyle val2 = new GUIStyle(GUI.skin.label)
{
fontSize = 14,
alignment = (TextAnchor)3
};
val2.normal.textColor = new Color(0.66f, 0.76f, 0.72f);
_subtitleStyle = val2;
GUIStyle val3 = new GUIStyle(GUI.skin.label)
{
fontSize = 12,
fontStyle = (FontStyle)1,
alignment = (TextAnchor)5
};
val3.normal.textColor = new Color(0.52f, 0.78f, 0.24f, 1f);
_versionStyle = val3;
GUIStyle val4 = new GUIStyle(GUI.skin.label)
{
fontSize = 12,
fontStyle = (FontStyle)1,
alignment = (TextAnchor)3
};
val4.normal.textColor = new Color(0.72f, 0.85f, 0.48f);
_labelStyle = val4;
GUIStyle val5 = new GUIStyle(GUI.skin.label)
{
fontSize = 11,
alignment = (TextAnchor)3,
clipping = (TextClipping)1
};
val5.normal.textColor = new Color(0.5f, 0.59f, 0.58f);
_smallStyle = val5;
GUIStyle val6 = new GUIStyle(_smallStyle)
{
fontSize = 11
};
val6.normal.textColor = new Color(0.72f, 0.8f, 0.77f);
_statusStyle = val6;
_fieldStyle = CreateFieldStyle(16, 12, (TextAnchor)3);
_areaStyle = CreateFieldStyle(14, 10, (TextAnchor)0);
_areaStyle.wordWrap = true;
GUIStyle val7 = new GUIStyle(GUI.skin.label)
{
fontSize = 14,
fontStyle = (FontStyle)1,
alignment = (TextAnchor)4
};
val7.normal.textColor = new Color(0.9f, 0.94f, 0.9f);
_counterStyle = val7;
_primaryButtonStyle = CreateButtonStyle(_greenTexture, new Color(0.07f, 0.12f, 0.08f), 13);
_secondaryButtonStyle = CreateButtonStyle(_fieldTexture, new Color(0.76f, 0.84f, 0.79f), 12);
_toggleOnStyle = CreateButtonStyle(_greenTexture, new Color(0.07f, 0.12f, 0.08f), 13);
_toggleOnStyle.alignment = (TextAnchor)3;
_toggleOnStyle.padding = new RectOffset(18, 12, 0, 0);
_toggleOffStyle = CreateButtonStyle(_fieldTexture, new Color(0.66f, 0.7f, 0.68f), 13);
_toggleOffStyle.alignment = (TextAnchor)3;
_toggleOffStyle.padding = new RectOffset(18, 12, 0, 0);
}
private GUIStyle CreateFieldStyle(int fontSize, int padding, TextAnchor alignment)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: 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_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Expected O, but got Unknown
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00b4: Expected O, but got Unknown
//IL_00b5: Expected O, but got Unknown
GUIStyle val = new GUIStyle(GUI.skin.textField)
{
fontSize = fontSize,
alignment = alignment,
wordWrap = false
};
val.normal.background = _fieldTexture;
val.normal.textColor = new Color(0.9f, 0.94f, 0.9f);
val.focused.background = _fieldTexture;
val.focused.textColor = Color.white;
val.hover.background = _fieldTexture;
val.hover.textColor = Color.white;
val.border = new RectOffset(0, 0, 0, 0);
val.padding = new RectOffset(padding, padding, padding, padding);
return val;
}
private static GUIStyle CreateButtonStyle(Texture2D background, Color textColor, int fontSize)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: 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_003c: 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_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: 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_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Expected O, but got Unknown
//IL_0084: Expected O, but got Unknown
GUIStyle val = new GUIStyle(GUI.skin.button)
{
fontSize = fontSize,
fontStyle = (FontStyle)1,
alignment = (TextAnchor)4
};
val.normal.background = background;
val.normal.textColor = textColor;
val.hover.background = background;
val.hover.textColor = Color.white;
val.active.background = background;
val.active.textColor = Color.white;
val.border = new RectOffset(0, 0, 0, 0);
return val;
}
private static Texture2D MakeTexture(Color color)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: 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)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Expected O, but got Unknown
Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false)
{
hideFlags = (HideFlags)61,
wrapMode = (TextureWrapMode)1
};
val.SetPixel(0, 0, color);
val.Apply(false, true);
return val;
}
private void OnDestroy()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_instance == (Object)(object)this)
{
_instance = null;
}
if (_isOpen)
{
Cursor.lockState = _previousCursorLock;
Cursor.visible = _previousCursorVisible;
}
Texture2D[] array = (Texture2D[])(object)new Texture2D[8] { _overlayTexture, _shadowTexture, _panelTexture, _headerTexture, _fieldTexture, _greenTexture, _orangeTexture, _mutedTexture };
foreach (Texture2D val in array)
{
if ((Object)(object)val != (Object)null)
{
Object.Destroy((Object)(object)val);
}
}
}
}
public sealed class TwitchRuntime : MonoBehaviour
{
private sealed class TwitchSpeechRequest
{
internal readonly int ViewId;
internal readonly string Spectator;
internal readonly string Text;
internal TwitchSpeechRequest(int viewId, string spectator, string text)
{
ViewId = viewId;
Spectator = spectator;
Text = text;
}
}
private const byte SpeechRequestEventCode = 197;
private const byte SpeechEventCode = 198;
private const string SpeechEventSignature = "BINGBONG_FR_TTS_V2";
private const string Command = "!bingbong";
private const float SpeechHearingDistance = 32f;
private const float SubtitleReferenceDistance = 7f;
private const float SubtitleMinimumScale = 0.22f;
private static TwitchRuntime _instance;
private static Action_AskBingBong _lastUsedBingBong;
private readonly ConcurrentQueue<TwitchChatMessage> _incomingChat = new ConcurrentQueue<TwitchChatMessage>();
private readonly ConcurrentQueue<TwitchSpeechRequest> _speechQueue = new ConcurrentQueue<TwitchSpeechRequest>();
private readonly HashSet<string> _recentMessageIds = new HashSet<string>(StringComparer.Ordinal);
private readonly Queue<string> _recentMessageOrder = new Queue<string>();
private readonly Dictionary<string, float> _lastCommandByUser = new Dictionary<string, float>(StringComparer.Ordinal);
private TwitchIrcClient _twitchClient;
private string[] _bannedWords = Array.Empty<string>();
private float _nextConnectionCheck;
private bool _speaking;
private bool _photonEventsSubscribed;
private int _speechGeneration;
private Action_AskBingBong _activeSpeechAction;
private GameObject _activeVoiceObject;
private AudioClip _activeClip;
private int _activeViewId;
private Guid _activeItemGuid;
private string _activeSubtitleText = string.Empty;
private Vector3 _activeWorldPosition;
private Vector3 _activeSubtitleWorldPosition;
private GUIStyle _subtitleStyle;
private GUIStyle _subtitleShadowStyle;
private string _activityStatus = "En attente d'une commande !bingbong";
internal static TwitchRuntime Instance => _instance;
internal string ConnectionStatus
{
get
{
if (!Plugin.TwitchInteractionEnabled.Value)
{
return "Interaction du tchat desactivee";
}
if (string.IsNullOrEmpty(NormalizeChannel(Plugin.TwitchChannel.Value)))
{
return "Aucune chaine configuree";
}
return _twitchClient?.Status ?? "Deconnecte";
}
}
internal string ActivityStatus => _activityStatus;
private void Awake()
{
if ((Object)(object)_instance != (Object)null && (Object)(object)_instance != (Object)(object)this)
{
Object.Destroy((Object)(object)this);
return;
}
_instance = this;
_twitchClient = new TwitchIrcClient(delegate(TwitchChatMessage message)
{
_incomingChat.Enqueue(message);
});
_bannedWords = ParseBannedWords(Plugin.TwitchBannedWords.Value);
TrySubscribePhotonEvents();
MaintainTwitchConnection(forceRestart: true);
}
private void OnDestroy()
{
if ((Object)(object)_instance == (Object)(object)this)
{
if (_photonEventsSubscribed && PhotonNetwork.NetworkingClient != null)
{
PhotonNetwork.NetworkingClient.EventReceived -= OnPhotonEvent;
}
_twitchClient?.Dispose();
_instance = null;
}
}
private void Update()
{
TrySubscribePhotonEvents();
if (Time.unscaledTime >= _nextConnectionCheck)
{
_nextConnectionCheck = Time.unscaledTime + 1f;
MaintainTwitchConnection(forceRestart: false);
}
ProcessIncomingChat();
if (!_speaking && _speechQueue.TryDequeue(out var result))
{
((MonoBehaviour)this).StartCoroutine(SpeakMessage(result));
}
}
private void LateUpdate()
{
UpdateActivePresentationPosition();
}
internal void ApplyConfiguration()
{
_bannedWords = ParseBannedWords(Plugin.TwitchBannedWords.Value);
_lastCommandByUser.Clear();
MaintainTwitchConnection(forceRestart: true);
}
internal void TestVoice()
{
Action_AskBingBong val = FindBestBingBong();
if ((Object)(object)val == (Object)null)
{
_activityStatus = "Aucun Bing Bong actif pour tester la voix";
return;
}
int viewId = GetViewId(val);
_speechQueue.Enqueue(new TwitchSpeechRequest(viewId, "Bing Bong", "Connexion au tchat prete."));
_activityStatus = "Test de la voix en cours...";
}
internal static void RecordUsedBingBong(Action_AskBingBong action)
{
if ((Object)(object)action != (Object)null)
{
_lastUsedBingBong = action;
}
}
internal static void StopTwitchPresentation(Action_AskBingBong action)
{
_instance?.StopActiveTwitchPresentation(action);
}
internal static void TrackRecreatedItem(Item item)
{
_instance?.AdoptTrackedItem(item);
}
internal static string NormalizeChannel(string rawChannel)
{
if (string.IsNullOrWhiteSpace(rawChannel))
{
return string.Empty;
}
string text = rawChannel.Trim();
if (Uri.TryCreate(text, UriKind.Absolute, out Uri result))
{
string[] array = result.AbsolutePath.Split(new char[1] { '/' }, StringSplitOptions.RemoveEmptyEntries);
text = ((array.Length != 0) ? array[0] : string.Empty);
}
text = text.Trim().TrimStart('#').ToLowerInvariant();
StringBuilder stringBuilder = new StringBuilder(text.Length);
string text2 = text;
foreach (char c in text2)
{
if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_')
{
stringBuilder.Append(c);
}
}
if (stringBuilder.Length > 25)
{
return stringBuilder.ToString(0, 25);
}
return stringBuilder.ToString();
}
internal static string[] ParseBannedWords(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
return Array.Empty<string>();
}
return (from word in value.Split(new char[4] { ',', ';', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
select word.Trim() into word
where word.Length > 0
select word).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToArray();
}
private void MaintainTwitchConnection(bool forceRestart)
{
bool value = Plugin.TwitchInteractionEnabled.Value;
string text = NormalizeChannel(Plugin.TwitchChannel.Value);
if (!value || text.Length <= 0)
{
if (_twitchClient.IsRunning)
{
string status = ((!value) ? "Interaction du tchat desactivee" : "Aucune chaine configuree");
_twitchClient.Disconnect(status);
}
}
else if (forceRestart || !_twitchClient.IsRunning || !string.Equals(_twitchClient.Channel, text, StringComparison.Ordinal))
{
_twitchClient.Connect(text);
}
}
private void TrySubscribePhotonEvents()
{
if (!_photonEventsSubscribed && PhotonNetwork.NetworkingClient != null)
{
PhotonNetwork.NetworkingClient.EventReceived += OnPhotonEvent;
_photonEventsSubscribed = true;
}
}
private void ProcessIncomingChat()
{
TwitchChatMessage result;
while (_incomingChat.TryDequeue(out result))
{
if (!Plugin.TwitchInteractionEnabled.Value || !TryExtractCommand(result.Text, out var spokenText) || !RememberMessage(result.Id))
{
continue;
}
spokenText = SanitizeForGame(spokenText);
string text = SanitizeForGame(result.DisplayName, 32);
if (spokenText.Length == 0 || ContainsBannedWord(spokenText) || ContainsBannedWord(text))
{
_activityStatus = "Message bloque par la liste de mots bannis";
continue;
}
int value = Plugin.TwitchUserCooldownSeconds.Value;
string userKey = GetUserKey(result);
if (value > 0 && _lastCommandByUser.TryGetValue(userKey, out var value2))
{
float num = Time.unscaledTime - value2;
if (num < (float)value)
{
_activityStatus = text + " doit attendre encore " + Mathf.CeilToInt((float)value - num) + " s";
continue;
}
}
Action_AskBingBong val = FindBestBingBong();
if ((Object)(object)val == (Object)null)
{
_activityStatus = "Commande ignoree : aucun Bing Bong actif";
continue;
}
_lastCommandByUser[userKey] = Time.unscaledTime;
BroadcastSpeech(GetViewId(val), text, spokenText);
}
}
private void BroadcastSpeech(int viewId, string spectator, string text)
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Expected O, but got Unknown
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
if (!PhotonNetwork.InRoom)
{
_speechQueue.Enqueue(new TwitchSpeechRequest(viewId, spectator, text));
return;
}
object[] array = new object[4] { "BINGBONG_FR_TTS_V2", viewId, spectator, text };
bool isMasterClient = PhotonNetwork.IsMasterClient;
int num = (isMasterClient ? 198 : 197);
RaiseEventOptions val = new RaiseEventOptions
{
Receivers = (ReceiverGroup)(isMasterClient ? 1 : 2)
};
if (!PhotonNetwork.RaiseEvent((byte)num, (object)array, val, SendOptions.SendReliable))
{
_activityStatus = "Impossible de synchroniser le message avec la partie";
Plugin.ModLog.LogWarning((object)"L'evenement Twitch n'a pas pu etre envoye par Photon.");
}
else
{
_activityStatus = (isMasterClient ? (spectator + " : " + text) : "Commande envoyee a l'hote pour synchronisation");
}
}
private void OnPhotonEvent(EventData eventData)
{
if ((eventData.Code != 197 && eventData.Code != 198) || !(eventData.CustomData is object[] array) || array.Length != 4 || !string.Equals(array[0] as string, "BINGBONG_FR_TTS_V2", StringComparison.Ordinal))
{
return;
}
if (!IsCurrentPartyMember(eventData.Sender))
{
Plugin.ModLog.LogWarning((object)"Evenement Twitch ignore car son emetteur n'est pas dans la partie.");
return;
}
int viewId;
try
{
viewId = Convert.ToInt32(array[1]);
}
catch
{
return;
}
string text = SanitizeForGame((array[2] as string) ?? "spectateur", 32);
string text2 = SanitizeForGame((array[3] as string) ?? string.Empty);
if (text2.Length == 0)
{
return;
}
if (eventData.Code == 197)
{
if (PhotonNetwork.IsMasterClient)
{
BroadcastSpeech(viewId, text, text2);
}
}
else if (PhotonNetwork.InRoom && PhotonNetwork.MasterClient != null && eventData.Sender != PhotonNetwork.MasterClient.ActorNumber)
{
Plugin.ModLog.LogWarning((object)"Message vocal ignore car il n'a pas ete relaye par l'hote.");
}
else
{
_speechQueue.Enqueue(new TwitchSpeechRequest(viewId, text, text2));
_activityStatus = text + " : " + text2;
}
}
private static bool IsCurrentPartyMember(int actorNumber)
{
if (PhotonNetwork.InRoom)
{
if (PhotonNetwork.CurrentRoom != null && actorNumber > 0)
{
return PhotonNetwork.CurrentRoom.Players.ContainsKey(actorNumber);
}
return false;
}
return true;
}
private IEnumerator SpeakMessage(TwitchSpeechRequest request)
{
_speaking = true;
int generation = ++_speechGeneration;
Action_AskBingBong action = FindBingBongByViewId(request.ViewId) ?? FindBestBingBong();
if ((Object)(object)action == (Object)null)
{
_activityStatus = "Lecture annulee : Bing Bong est introuvable";
_speaking = false;
yield break;
}
_activeSpeechAction = action;
_activeViewId = request.ViewId;
Item speechItem = FindPresentationItem(action, request.ViewId, Guid.Empty);
_activeItemGuid = (((Object)(object)speechItem != (Object)null && speechItem.data != null) ? speechItem.data.guid : Guid.Empty);
string wavPath = null;
string synthesisError = null;
yield return ToySpeechEngine.Synthesize(request.Text, delegate(string path, string error)
{
wavPath = path;
synthesisError = error;
});
if (generation != _speechGeneration)
{
ToySpeechEngine.SafeDelete(wavPath);
_speaking = false;
yield break;
}
if (!string.IsNullOrEmpty(synthesisError))
{
_activityStatus = synthesisError;
Plugin.ModLog.LogError((object)synthesisError);
_speaking = false;
yield break;
}
AudioClip clip = null;
UnityWebRequest audioRequest = UnityWebRequestMultimedia.GetAudioClip(new Uri(wavPath).AbsoluteUri, (AudioType)20);
try
{
yield return audioRequest.SendWebRequest();
if ((int)audioRequest.result == 1)
{
clip = DownloadHandlerAudioClip.GetContent(audioRequest);
}
else
{
_activityStatus = "Impossible de charger la voix generee";
Plugin.ModLog.LogError((object)("Chargement TTS impossible : " + audioRequest.error));
}
}
finally
{
((IDisposable)audioRequest)?.Dispose();
}
ToySpeechEngine.SafeDelete(wavPath);
if (generation != _speechGeneration)
{
if ((Object)(object)clip != (Object)null)
{
Object.Destroy((Object)(object)clip);
}
_speaking = false;
yield break;
}
if ((Object)(object)clip == (Object)null)
{
_speaking = false;
yield break;
}
_activeClip = clip;
string activeSubtitleText = request.Spectator + " : " + request.Text;
_activeSubtitleText = activeSubtitleText;
if ((Object)(object)action.squishAnim != (Object)null)
{
action.squishAnim.SetTrigger("Squish");
}
GameObject voiceObject = new GameObject("BingBong_FR_TwitchVoice");
if (!TryGetPresentationPosition(speechItem, action, out _activeWorldPosition))
{
_activeWorldPosition = ((Component)action).transform.position;
}
if (!TryGetSubtitleAnchorPosition(speechItem, action, out _activeSubtitleWorldPosition))
{
_activeSubtitleWorldPosition = _activeWorldPosition + Vector3.up * 0.55f;
}
voiceObject.transform.position = _activeWorldPosition;
AudioSource source = voiceObject.AddComponent<AudioSource>();
source.clip = clip;
source.playOnAwake = false;
source.loop = false;
source.spatialBlend = 1f;
source.minDistance = 1.2f;
source.maxDistance = 32f;
source.rolloffMode = (AudioRolloffMode)0;
source.pitch = 0.88f;
source.volume = 0.9f;
if ((Object)(object)action.source != (Object)null)
{
source.outputAudioMixerGroup = action.source.outputAudioMixerGroup;
}
_activeVoiceObject = voiceObject;
GameObject val = new GameObject("BingBong_FR_MetalLayer");
val.transform.SetParent(voiceObject.transform, false);
AudioSource obj = val.AddComponent<AudioSource>();
obj.clip = clip;
obj.playOnAwake = false;
obj.loop = false;
obj.spatialBlend = 1f;
obj.minDistance = source.minDistance;
obj.maxDistance = source.maxDistance;
obj.rolloffMode = source.rolloffMode;
obj.pitch = 0.92f;
obj.volume = 0.26f;
obj.outputAudioMixerGroup = source.outputAudioMixerGroup;
AudioHighPassFilter obj2 = voiceObject.AddComponent<AudioHighPassFilter>();
obj2.cutoffFrequency = 220f;
obj2.highpassResonanceQ = 1.45f;
voiceObject.AddComponent<AudioDistortionFilter>().distortionLevel = 0.24f;
AudioChorusFilter obj3 = voiceObject.AddComponent<AudioChorusFilter>();
obj3.dryMix = 0.68f;
obj3.wetMix1 = 0.38f;
obj3.wetMix2 = 0.16f;
obj3.wetMix3 = 0.07f;
obj3.delay = 12f;
obj3.rate = 0.6f;
obj3.depth = 0.65f;
AudioLowPassFilter obj4 = voiceObject.AddComponent<AudioLowPassFilter>();
obj4.cutoffFrequency = 4800f;
obj4.lowpassResonanceQ = 1.3f;
AudioEchoFilter obj5 = voiceObject.AddComponent<AudioEchoFilter>();
obj5.delay = 31f;
obj5.decayRatio = 0.12f;
obj5.dryMix = 0.84f;
obj5.wetMix = 0.22f;
source.Play();
obj.Play();
_activityStatus = request.Spectator + " fait parler Bing Bong";
while (generation == _speechGeneration && (Object)(object)source != (Object)null && source.isPlaying)
{
Action_AskBingBong activeSpeechAction = _activeSpeechAction;
if ((Object)(object)activeSpeechAction != (Object)null && (Object)(object)activeSpeechAction.anim != (Object)null)
{
float num = 0.2f + Mathf.PingPong(Time.unscaledTime * 10f, 0.75f);
activeSpeechAction.anim.SetFloat(Action_AskBingBong.MOUTHBLENDID, num);
}
yield return null;
}
if ((Object)(object)_activeSpeechAction != (Object)null && (Object)(object)_activeSpeechAction.anim != (Object)null)
{
_activeSpeechAction.anim.SetFloat(Action_AskBingBong.MOUTHBLENDID, 0f);
}
if ((Object)(object)voiceObject != (Object)null)
{
Object.Destroy((Object)(object)voiceObject);
}
Object.Destroy((Object)(object)clip);
ClearActivePresentationReferences(generation);
if (generation == _speechGeneration)
{
_activityStatus = "En attente d'une commande !bingbong";
}
_speaking = false;
}
private void StopActiveTwitchPresentation(Action_AskBingBong action)
{
Item val = (((Object)(object)action != (Object)null) ? ((Component)action).GetComponentInParent<Item>() : null);
if (!((Object)(object)action != (Object)null) || (!((Object)(object)_activeSpeechAction == (Object)(object)action) && (!(_activeItemGuid != Guid.Empty) || !((Object)(object)val != (Object)null) || val.data == null || !(val.data.guid == _activeItemGuid))))
{
return;
}
_speechGeneration++;
if ((Object)(object)_activeVoiceObject != (Object)null)
{
AudioSource component = _activeVoiceObject.GetComponent<AudioSource>();
if (component != null)
{
component.Stop();
}
Object.Destroy((Object)(object)_activeVoiceObject);
}
if ((Object)(object)_activeClip != (Object)null)
{
Object.Destroy((Object)(object)_activeClip);
}
if ((Object)(object)action.anim != (Object)null)
{
action.anim.SetFloat(Action_AskBingBong.MOUTHBLENDID, 0f);
}
_activeSpeechAction = null;
_activeVoiceObject = null;
_activeClip = null;
_activeViewId = 0;
_activeItemGuid = Guid.Empty;
_activeSubtitleText = string.Empty;
_activityStatus = "Activation manuelle : repliques preenregistrees";
}
private void ClearActivePresentationReferences(int generation)
{
if (generation == _speechGeneration)
{
_activeSpeechAction = null;
_activeVoiceObject = null;
_activeClip = null;
_activeViewId = 0;
_activeItemGuid = Guid.Empty;
_activeSubtitleText = string.Empty;
}
}
private void UpdateActivePresentationPosition()
{
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_activeVoiceObject == (Object)null)
{
return;
}
Item val = FindPresentationItem(_activeSpeechAction, _activeViewId, _activeItemGuid);
if (!TryGetPresentationPosition(val, _activeSpeechAction, out var position))
{
return;
}
if ((Object)(object)val != (Object)null)
{
Action_AskBingBong componentInChildren = ((Component)val).GetComponentInChildren<Action_AskBingBong>(true);
if ((Object)(object)componentInChildren != (Object)null)
{
_activeSpeechAction = componentInChildren;
}
PhotonView val2 = ((Component)val).GetComponent<PhotonView>() ?? ((Component)val).GetComponentInParent<PhotonView>();
if ((Object)(object)val2 != (Object)null)
{
_activeViewId = val2.ViewID;
}
}
_activeWorldPosition = position;
_activeVoiceObject.transform.position = position;
if (!TryGetSubtitleAnchorPosition(val, _activeSpeechAction, out _activeSubtitleWorldPosition))
{
_activeSubtitleWorldPosition = position + Vector3.up * 0.55f;
}
}
private void AdoptTrackedItem(Item item)
{
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_activeVoiceObject == (Object)null) && !(_activeItemGuid == Guid.Empty) && !((Object)(object)item == (Object)null) && item.data != null && !(item.data.guid != _activeItemGuid))
{
Action_AskBingBong componentInChildren = ((Component)item).GetComponentInChildren<Action_AskBingBong>(true);
if ((Object)(object)componentInChildren != (Object)null)
{
_activeSpeechAction = componentInChildren;
}
PhotonView val = ((Component)item).GetComponent<PhotonView>() ?? ((Component)item).GetComponentInParent<PhotonView>();
if ((Object)(object)val != (Object)null)
{
_activeViewId = val.ViewID;
}
if (TryGetPresentationPosition(item, _activeSpeechAction, out var position))
{
_activeWorldPosition = position;
_activeVoiceObject.transform.position = position;
}
if (!TryGetSubtitleAnchorPosition(item, _activeSpeechAction, out _activeSubtitleWorldPosition))
{
_activeSubtitleWorldPosition = _activeWorldPosition + Vector3.up * 0.55f;
}
}
}
private void OnGUI()
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
//IL_01f4: Expected O, but got Unknown
//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0213: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0113: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Expected O, but got Unknown
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: 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_017f: Expected O, but got Unknown
//IL_0257: Unknown result type (might be due to invalid IL or missing references)
//IL_026d: Unknown result type (might be due to invalid IL or missing references)
//IL_0299: Unknown result type (might be due to invalid IL or missing references)
//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
if (string.IsNullOrEmpty(_activeSubtitleText) || (Object)(object)_activeVoiceObject == (Object)null)
{
return;
}
Camera val = Camera.main ?? Camera.current;
if ((Object)(object)val == (Object)null)
{
return;
}
AudioSource component = _activeVoiceObject.GetComponent<AudioSource>();
float num = (((Object)(object)component != (Object)null) ? component.maxDistance : 32f);
float num2 = Vector3.Distance(((Component)val).transform.position, _activeWorldPosition);
if (num2 >= num)
{
return;
}
float num3 = num * 0.75f;
float num4 = 1f - Mathf.InverseLerp(num3, num, num2);
Vector3 val2 = val.WorldToScreenPoint(_activeSubtitleWorldPosition);
if (!(val2.z <= 0f))
{
float num5 = (val.orthographic ? 1f : Mathf.Clamp(7f / Mathf.Max(val2.z, 0.01f), 0.22f, 1f));
if (_subtitleStyle == null)
{
GUIStyle val3 = new GUIStyle(GUI.skin.label)
{
alignment = (TextAnchor)4,
fontSize = 18,
fontStyle = (FontStyle)1,
wordWrap = true,
richText = false
};
val3.normal.textColor = new Color(0.86f, 1f, 0.68f, 1f);
_subtitleStyle = val3;
GUIStyle val4 = new GUIStyle(_subtitleStyle);
val4.normal.textColor = new Color(0f, 0f, 0f, 0.92f);
_subtitleShadowStyle = val4;
}
int fontSize = Mathf.Max(6, Mathf.RoundToInt(18f * num5));
_subtitleStyle.fontSize = fontSize;
_subtitleShadowStyle.fontSize = fontSize;
float num6 = Mathf.Min(540f, (float)Screen.width - 32f);
float num7 = Mathf.Max(80f, num6 * num5);
float num8 = Mathf.Max(14f, _subtitleStyle.CalcHeight(new GUIContent(_activeSubtitleText), num7));
float num9 = val2.x - num7 * 0.5f;
float num10 = (float)Screen.height - val2.y - num8;
if (!(num9 + num7 < 0f) && !(num9 > (float)Screen.width) && !(num10 + num8 < 0f) && !(num10 > (float)Screen.height))
{
GUI.depth = -900;
Color color = GUI.color;
GUI.color = new Color(1f, 1f, 1f, num4);
float num11 = Mathf.Max(1f, 2f * num5);
GUI.Label(new Rect(num9 + num11, num10 + num11, num7, num8), _activeSubtitleText, _subtitleShadowStyle);
GUI.Label(new Rect(num9, num10, num7, num8), _activeSubtitleText, _subtitleStyle);
GUI.color = color;
}
}
}
private static string GetUserKey(TwitchChatMessage chatMessage)
{
if (!string.IsNullOrWhiteSpace(chatMessage.UserId))
{
return "id:" + chatMessage.UserId;
}
return "name:" + (chatMessage.DisplayName ?? "spectateur").Trim().ToLowerInvariant();
}
private bool ContainsBannedWord(string text)
{
string[] bannedWords = _bannedWords;
foreach (string value in bannedWords)
{
if (text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
{
return true;
}
}
return false;
}
private bool RememberMessage(string messageId)
{
if (string.IsNullOrEmpty(messageId))
{
return true;
}
if (!_recentMessageIds.Add(messageId))
{
return false;
}
_recentMessageOrder.Enqueue(messageId);
while (_recentMessageOrder.Count > 256)
{
_recentMessageIds.Remove(_recentMessageOrder.Dequeue());
}
return true;
}
private static bool TryExtractCommand(string chatText, out string spokenText)
{
spokenText = string.Empty;
if (string.IsNullOrWhiteSpace(chatText) || !chatText.StartsWith("!bingbong", StringComparison.OrdinalIgnoreCase))
{
return false;
}
if (chatText.Length > "!bingbong".Length && !char.IsWhiteSpace(chatText["!bingbong".Length]))
{
return false;
}
spokenText = ((chatText.Length == "!bingbong".Length) ? string.Empty : chatText.Substring("!bingbong".Length).Trim());
return spokenText.Length > 0;
}
private static string SanitizeForGame(string value, int maximumLength = 0)
{
if (string.IsNullOrWhiteSpace(value))
{
return string.Empty;
}
StringBuilder stringBuilder = new StringBuilder((maximumLength > 0) ? Math.Min(value.Length, maximumLength) : value.Length);
bool flag = false;
string text = value.Trim();
foreach (char c in text)
{
char c2 = c switch
{
'>' => '›',
'<' => '‹',
_ => c,
};
if (char.IsControl(c2))
{
c2 = ' ';
}
if (char.IsWhiteSpace(c2))
{
if (flag)
{
continue;
}
c2 = ' ';
flag = true;
}
else
{
flag = false;
}
stringBuilder.Append(c2);
if (maximumLength > 0 && stringBuilder.Length >= maximumLength)
{
break;
}
}
return stringBuilder.ToString().Trim();
}
private static Action_AskBingBong FindBestBingBong()
{
if (IsUsableBingBong(_lastUsedBingBong))
{
return _lastUsedBingBong;
}
Action_AskBingBong val = null;
Action_AskBingBong[] array = Resources.FindObjectsOfTypeAll<Action_AskBingBong>();
foreach (Action_AskBingBong val2 in array)
{
if (IsUsableBingBong(val2))
{
Item componentInParent = ((Component)val2).GetComponentInParent<Item>();
if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.holderCharacter != (Object)null)
{
return val2;
}
if ((Object)(object)val == (Object)null)
{
val = val2;
}
}
}
return val;
}
private static Action_AskBingBong FindBingBongByViewId(int viewId)
{
if (viewId <= 0)
{
return null;
}
PhotonView val = PhotonView.Find(viewId);
if ((Object)(object)val == (Object)null)
{
return null;
}
return ((Component)val).GetComponentInChildren<Action_AskBingBong>(true) ?? ((Component)val).GetComponentInParent<Action_AskBingBong>();
}
private static int GetViewId(Action_AskBingBong action)
{
Item componentInParent = ((Component)action).GetComponentInParent<Item>();
PhotonView val = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).GetComponent<PhotonView>() : ((Component)action).GetComponentInParent<PhotonView>());
if (!((Object)(object)val != (Object)null))
{
return 0;
}
return val.ViewID;
}
private static Item FindPresentationItem(Action_AskBingBong action, int viewId, Guid preferredGuid)
{
Item val = null;
if (preferredGuid != Guid.Empty)
{
val = FindItemByGuid(Item.ALL_ACTIVE_ITEMS, preferredGuid) ?? FindItemByGuid(Item.ALL_ITEMS, preferredGuid);
if ((Object)(object)val != (Object)null)
{
return val;
}
}
if (viewId > 0)
{
PhotonView val2 = PhotonView.Find(viewId);
if ((Object)(object)val2 != (Object)null)
{
val = ((Component)val2).GetComponent<Item>() ?? ((Component)val2).GetComponentInParent<Item>() ?? ((Component)val2).GetComponentInChildren<Item>(true);
}
}
if ((Object)(object)val == (Object)null && (Object)(object)action != (Object)null)
{
val = ((Component)action).GetComponentInParent<Item>();
}
return val;
}
private static Item FindItemByGuid(IEnumerable<Item> items, Guid guid)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
if (items == null)
{
return null;
}
foreach (Item item in items)
{
if ((Object)(object)item != (Object)null && item.data != null && item.data.guid == guid)
{
Scene scene = ((Component)item).gameObject.scene;
if (((Scene)(ref scene)).IsValid())
{
return item;
}
}
}
return null;
}
private static bool TryGetPresentationPosition(Item item, Action_AskBingBong action, out Vector3 position)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: 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_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)item != (Object)null && (Object)(object)item.mainRenderer != (Object)null)
{
Bounds bounds = item.mainRenderer.bounds;
position = ((Bounds)(ref bounds)).center;
return true;
}
if ((Object)(object)item != (Object)null && (Object)(object)item.rig != (Object)null)
{
position = item.rig.worldCenterOfMass;
return true;
}
if ((Object)(object)item != (Object)null)
{
position = item.transform.position;
return true;
}
if ((Object)(object)action != (Object)null)
{
position = ((Component)action).transform.position;
return true;
}
position = default(Vector3);
return false;
}
private static bool TryGetSubtitleAnchorPosition(Item item, Action_AskBingBong action, out Vector3 position)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: 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)
if ((Object)(object)item != (Object)null && (Object)(object)item.mainRenderer != (Object)null)
{
Bounds bounds = item.mainRenderer.bounds;
float num = Mathf.Max(0.12f, ((Bounds)(ref bounds)).extents.y * 0.2f);
position = new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).max.y + num, ((Bounds)(ref bounds)).center.z);
return true;
}
if ((Object)(object)item != (Object)null && (Object)(object)item.rig != (Object)null)
{
position = item.rig.worldCenterOfMass + Vector3.up * 0.65f;
return true;
}
if ((Object)(object)item != (Object)null)
{
position = item.transform.position + Vector3.up * 0.65f;
return true;
}
if ((Object)(object)action != (Object)null)
{
position = ((Component)action).transform.position + Vector3.up * 0.65f;
return true;
}
position = default(Vector3);
return false;
}
private static bool IsUsableBingBong(Action_AskBingBong action)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)action != (Object)null && (Object)(object)((Component)action).gameObject != (Object)null)
{
Scene scene = ((Component)action).gameObject.scene;
if (((Scene)(ref scene)).IsValid())
{
return ((Component)action).gameObject.activeInHierarchy;
}
}
return false;
}
}
}