using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using I2.Loc;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace ChatPlus;
public enum QuickChatMenu
{
Automatic,
Treehouse,
BuildMode,
PlayMode
}
public enum PlusButtonMode
{
WhenChatOpen,
Always
}
[BepInPlugin("com.chatplus.uch", "Chat+", "1.1.2")]
public class ChatPlusPlugin : BaseUnityPlugin
{
public const string PluginGuid = "com.chatplus.uch";
public const string PluginName = "Chat+";
public const string PluginVersion = "1.1.2";
internal static ChatPlusPlugin Instance;
internal static ManualLogSource Log;
internal static ConfigEntry<bool> AutoHello;
internal static ConfigEntry<bool> AutoGoodbye;
internal static ConfigEntry<bool> AutoWellDone;
internal static ConfigEntry<bool> AutoSoClose;
internal static ConfigEntry<QuickChatMenu> QuickChat;
internal static ConfigEntry<PlusButtonMode> PlusMode;
internal static string HookStatus = "no hooks applied";
internal static bool HooksAllOk;
private int errUi;
private int errNet;
private int errAuto;
private int errMenu;
private static EmoteContext lastAutomatic = (EmoteContext)2;
private static EmoteContext lastApplied = (EmoteContext)2;
private static bool appliedOnce;
private void Awake()
{
Instance = this;
Log = ((BaseUnityPlugin)this).Logger;
AutoHello = ((BaseUnityPlugin)this).Config.Bind<bool>("1. Auto Chat", "Hello when someone joins treehouse", true, "Automatically say \"Hello!\" 0.5s after another player joins the treehouse.");
AutoGoodbye = ((BaseUnityPlugin)this).Config.Bind<bool>("1. Auto Chat", "Goodbye when someone leaves treehouse", true, "Automatically say \"Goodbye\" 0.5s after another player leaves the treehouse.");
AutoWellDone = ((BaseUnityPlugin)this).Config.Bind<bool>("1. Auto Chat", "Well done when someone finishes", true, "Automatically say \"Well done!\" when another player finishes.");
AutoSoClose = ((BaseUnityPlugin)this).Config.Bind<bool>("1. Auto Chat", "So close when someone dies on last life", true, "Automatically say \"So close!\" when another player dies on their last life.");
QuickChat = ((BaseUnityPlugin)this).Config.Bind<QuickChatMenu>("2. Quick Chat", "Quick chat menu", QuickChatMenu.Automatic, "Which quick chat (emote) menu is active: Automatic (switches by itself: treehouse, build mode, play mode), Treehouse, BuildMode or PlayMode.");
QuickChat.SettingChanged += delegate
{
ApplyQuickChatNow();
};
PlusMode = ((BaseUnityPlugin)this).Config.Bind<PlusButtonMode>("3. Misc", "Plus buttons", PlusButtonMode.WhenChatOpen, "WhenChatOpen: the + buttons only show while the chat box is open. Always: the + buttons are always visible.");
ApplyHooks();
Log.LogInfo((object)"Chat+ 1.1.2 loaded.");
}
private void ApplyHooks()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
Harmony val = new Harmony("com.chatplus.uch");
string[] array = new string[6] { "QuickChat", "ChatLines", "Death", "Finish", "PlusButton", "SelfJoin" };
Type[] array2 = new Type[6]
{
typeof(Patch_SetEmoteContext),
typeof(Patch_DisplayNewMessage),
typeof(Patch_SetupDeath),
typeof(Patch_PlayerSuccess),
typeof(Patch_SetChatUnitMessage),
typeof(Patch_SelfJoin)
};
Type[] array3 = new Type[6]
{
typeof(EmoteSystem),
typeof(ChatDisplay),
typeof(Character),
typeof(Character),
typeof(ChatUnit),
typeof(LobbyPlayer)
};
string[] array4 = new string[6] { "SetEmoteContext", "DisplayNewMessage", "setupDeath", "RpcSendPlayerSuccessEvent", "SetChatUnitMessage", "CallCmdSendJoinMessage" };
int num = 0;
List<string> list = new List<string>();
for (int i = 0; i < array2.Length; i++)
{
bool flag = false;
try
{
val.CreateClassProcessor(array2[i]).Patch();
MethodBase methodBase = AccessTools.Method(array3[i], array4[i], (Type[])null, (Type[])null);
if (methodBase == null)
{
Log.LogError((object)("Chat+ hook " + array[i] + ": game method " + array3[i].Name + "." + array4[i] + " was not found"));
}
else
{
Patches patchInfo = Harmony.GetPatchInfo(methodBase);
flag = patchInfo != null && (patchInfo.Prefixes.Any((Patch x) => x.owner == "com.chatplus.uch") || patchInfo.Postfixes.Any((Patch x) => x.owner == "com.chatplus.uch"));
if (!flag)
{
Log.LogError((object)("Chat+ hook " + array[i] + ": patch did not attach to " + array3[i].Name + "." + array4[i]));
}
}
}
catch (Exception ex)
{
Log.LogError((object)("Chat+ hook " + array[i] + " failed: " + ex));
}
if (flag)
{
num++;
Log.LogInfo((object)("Chat+ hook OK: " + array[i]));
}
else
{
list.Add(array[i]);
}
}
HooksAllOk = list.Count == 0;
HookStatus = ((!HooksAllOk) ? (num + "/" + array2.Length + " hooks OK, FAILED: " + string.Join(", ", list.ToArray())) : ("all " + array2.Length + " hooks OK"));
Log.LogInfo((object)("Chat+ status: " + HookStatus));
}
private void Update()
{
try
{
ChatPlusNet.Poll();
}
catch (Exception ex)
{
if (errNet++ < 5)
{
Log.LogError((object)("Chat+ network update error: " + ex));
}
}
try
{
ChatPlusUI.Tick();
}
catch (Exception ex2)
{
if (errUi++ < 5)
{
Log.LogError((object)("Chat+ UI update error: " + ex2));
}
}
try
{
AutoChat.Poll();
}
catch (Exception ex3)
{
if (errAuto++ < 5)
{
Log.LogError((object)("Chat+ auto chat update error: " + ex3));
}
}
try
{
TickAutomaticMenu();
}
catch (Exception ex4)
{
if (errMenu++ < 5)
{
Log.LogError((object)("Chat+ quick chat update error: " + ex4));
}
}
}
private static EmoteContext AutomaticContext()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Invalid comparison between Unknown and I4
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Invalid comparison between Unknown and I4
//IL_006e: 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_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Invalid comparison between Unknown and I4
LobbyManager instance = LobbyManager.instance;
if ((Object)(object)instance == (Object)null)
{
return lastAutomatic;
}
GameControl currentGameController = instance.CurrentGameController;
if ((Object)(object)currentGameController == (Object)null)
{
lastAutomatic = (EmoteContext)2;
return lastAutomatic;
}
GamePhase phase = currentGameController.Phase;
if ((int)phase != 3)
{
if ((int)phase == 2 || (int)phase == 4)
{
lastAutomatic = (EmoteContext)0;
}
}
else
{
lastAutomatic = (EmoteContext)1;
}
return lastAutomatic;
}
private static void TickAutomaticMenu()
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: 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)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
if (QuickChat.Value == QuickChatMenu.Automatic)
{
EmoteContext val = AutomaticContext();
if (!appliedOnce || val != lastApplied)
{
ApplyQuickChatNow();
}
}
}
internal static EmoteContext MappedContext()
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
return (EmoteContext)(QuickChat.Value switch
{
QuickChatMenu.Automatic => AutomaticContext(),
QuickChatMenu.BuildMode => 1,
QuickChatMenu.PlayMode => 0,
_ => 2,
});
}
private static void ApplyQuickChatNow()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: 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)
try
{
EmoteContext emoteContext = (lastApplied = MappedContext());
appliedOnce = true;
EmoteSystem[] array = Object.FindObjectsOfType<EmoteSystem>();
for (int i = 0; i < array.Length; i++)
{
array[i].SetEmoteContext(emoteContext);
}
}
catch (Exception ex)
{
Log.LogError((object)("Chat+ could not apply quick chat menu: " + ex));
}
}
}
[HarmonyPatch(typeof(EmoteSystem), "SetEmoteContext")]
internal static class Patch_SetEmoteContext
{
private static void Prefix(ref EmoteContext __0)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Expected I4, but got Unknown
try
{
__0 = (EmoteContext)(int)ChatPlusPlugin.MappedContext();
}
catch (Exception ex)
{
ChatPlusPlugin.Log.LogError((object)("Chat+ SetEmoteContext patch: " + ex));
}
}
}
[HarmonyPatch(typeof(LobbyPlayer), "CallCmdSendJoinMessage")]
internal static class Patch_SelfJoin
{
private static void Postfix()
{
try
{
AutoChat.OnSelfJoined();
}
catch (Exception ex)
{
ChatPlusPlugin.Log.LogError((object)("Chat+ self join patch: " + ex));
}
}
}
[HarmonyPatch(typeof(ChatDisplay), "DisplayNewMessage")]
internal static class Patch_DisplayNewMessage
{
private static void Postfix(ChatMessageDetails chatMessageDetails)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
try
{
AutoChat.OnChatLine(chatMessageDetails);
}
catch (Exception ex)
{
ChatPlusPlugin.Log.LogError((object)("Chat+ DisplayNewMessage patch: " + ex));
}
}
}
[HarmonyPatch(typeof(Character), "setupDeath")]
internal static class Patch_SetupDeath
{
private static void Postfix(Character __instance)
{
try
{
AutoChat.OnCharacterDied(__instance);
}
catch (Exception ex)
{
ChatPlusPlugin.Log.LogError((object)("Chat+ setupDeath patch: " + ex));
}
}
}
[HarmonyPatch(typeof(Character), "RpcSendPlayerSuccessEvent")]
internal static class Patch_PlayerSuccess
{
private static void Postfix(Character __instance)
{
try
{
AutoChat.OnCharacterFinished(__instance);
}
catch (Exception ex)
{
ChatPlusPlugin.Log.LogError((object)("Chat+ success patch: " + ex));
}
}
}
[HarmonyPatch(typeof(ChatUnit), "SetChatUnitMessage")]
internal static class Patch_SetChatUnitMessage
{
private static void Postfix(ChatUnit __instance, ChatMessageDetails chatMessage)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
try
{
ChatPlusUI.DecorateUnit(__instance, chatMessage);
}
catch (Exception ex)
{
ChatPlusPlugin.Log.LogError((object)("Chat+ SetChatUnitMessage patch: " + ex));
}
}
}
internal static class AutoChat
{
private const string TreehouseScene = "TreeHouseLobby";
private static readonly Dictionary<int, float> lastDeathSaid = new Dictionary<int, float>();
private static bool inLobby;
private static float settleUntil;
private static HashSet<int> known = new HashSet<int>();
private static readonly Dictionary<string, float> recentlySaid = new Dictionary<string, float>();
internal static bool InTreehouse()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
if (((Scene)(ref activeScene)).name == "TreeHouseLobby" || LobbyManagerManager.LastSceneLoaded == "TreeHouseLobby")
{
return true;
}
LobbyManager instance = LobbyManager.instance;
return (Object)(object)instance != (Object)null && (Object)(object)instance.CurrentLevelSelectController != (Object)null;
}
internal static bool IsLocal(int networkNumber)
{
return (Object)(object)LobbyManager.instance != (Object)null && LobbyManager.instance.IsLocalNetworkNumber(networkNumber);
}
internal static LobbyPlayer LocalLobbyPlayer()
{
if ((Object)(object)LobbyManager.instance == (Object)null)
{
return null;
}
foreach (LobbyPlayer lobbyPlayer in LobbyManager.instance.GetLobbyPlayers())
{
if ((Object)(object)lobbyPlayer != (Object)null && lobbyPlayer.Initialized && lobbyPlayer.IsLocalPlayer)
{
return lobbyPlayer;
}
}
return null;
}
internal static void Poll()
{
LobbyManager instance = LobbyManager.instance;
LobbyPlayer val = ((!((Object)(object)instance != (Object)null)) ? null : LocalLobbyPlayer());
if ((Object)(object)val == (Object)null)
{
inLobby = false;
known.Clear();
return;
}
if (!inLobby)
{
inLobby = true;
settleUntil = Time.unscaledTime + 3f;
known.Clear();
OnSelfJoined();
}
HashSet<int> hashSet = new HashSet<int>();
foreach (LobbyPlayer lobbyPlayer in instance.GetLobbyPlayers())
{
if ((Object)(object)lobbyPlayer != (Object)null && lobbyPlayer.Initialized && lobbyPlayer.LocalPlayer == null && !lobbyPlayer.IsLocalPlayer)
{
hashSet.Add(lobbyPlayer.networkNumber);
}
}
if (Time.unscaledTime >= settleUntil)
{
foreach (int item in hashSet)
{
if (!known.Contains(item) && ChatPlusPlugin.AutoHello.Value && InTreehouse())
{
ChatPlusPlugin.Log.LogInfo((object)("Chat+: player " + item + " joined (lobby watch), saying hello"));
Say((EmoteMeanings)17, 0.5f, treehouseOnly: true, item);
}
}
}
known = hashSet;
}
internal static void OnSelfJoined()
{
LobbyManager instance = LobbyManager.instance;
if (!((Object)(object)instance == (Object)null) && !instance.IsHost && ChatPlusPlugin.AutoHello.Value)
{
ChatPlusPlugin.Log.LogInfo((object)"Chat+: you joined a lobby, saying hello");
Say((EmoteMeanings)17, 0.5f, treehouseOnly: false, -1);
}
}
internal static void OnChatLine(ChatMessageDetails d)
{
if (!d.isChatMessage && !string.IsNullOrEmpty(d.Message))
{
bool flag = d.Message == Network.SomeoneJoined_lobby;
bool flag2 = d.Message == Network.Someone_left_lobby;
if ((flag || flag2) && !InTreehouse())
{
ChatPlusPlugin.Log.LogInfo((object)"Chat+: join/leave seen but not in the treehouse, ignoring");
}
else if (ChatPlusPlugin.AutoHello.Value && d.Message == Network.SomeoneJoined_lobby)
{
ChatPlusPlugin.Log.LogInfo((object)"Chat+: someone joined, saying hello");
Say((EmoteMeanings)17, 0.5f, treehouseOnly: true, d.NetworkNumber);
}
else if (ChatPlusPlugin.AutoGoodbye.Value && d.Message == Network.Someone_left_lobby)
{
ChatPlusPlugin.Log.LogInfo((object)"Chat+: someone left, saying goodbye");
Say((EmoteMeanings)12, 0.5f, treehouseOnly: true, d.NetworkNumber);
}
}
}
internal static void OnCharacterFinished(Character c)
{
if (!((Object)(object)c == (Object)null) && ChatPlusPlugin.AutoWellDone.Value && !IsLocal(c.networkNumber))
{
ChatPlusPlugin.Log.LogInfo((object)"Chat+: someone finished, saying well done");
Say((EmoteMeanings)38, 0f, treehouseOnly: false, c.networkNumber);
}
}
internal static void OnCharacterDied(Character c)
{
if (!((Object)(object)c == (Object)null) && ChatPlusPlugin.AutoSoClose.Value && !IsLocal(c.networkNumber))
{
GamePlayer associatedGamePlayer = c.AssociatedGamePlayer;
if (!((Object)(object)associatedGamePlayer == (Object)null) && associatedGamePlayer.lives <= 0 && (!lastDeathSaid.TryGetValue(c.networkNumber, out var value) || !(Time.unscaledTime - value < 2f)))
{
lastDeathSaid[c.networkNumber] = Time.unscaledTime;
ChatPlusPlugin.Log.LogInfo((object)"Chat+: someone died on their last life, saying so close");
Say((EmoteMeanings)31, 0f, treehouseOnly: false, c.networkNumber);
}
}
}
private static void Say(EmoteMeanings emote, float delay, bool treehouseOnly, int subject)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
ChatPlusPlugin instance = ChatPlusPlugin.Instance;
if (!((Object)(object)instance == (Object)null))
{
if (delay <= 0f)
{
TrySend(emote, treehouseOnly, subject);
}
else
{
((MonoBehaviour)instance).StartCoroutine(SayLater(emote, delay, treehouseOnly, subject));
}
}
}
private static IEnumerator SayLater(EmoteMeanings emote, float delay, bool treehouseOnly, int subject)
{
//IL_000e: 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)
yield return (object)new WaitForSecondsRealtime(delay);
TrySend(emote, treehouseOnly, subject);
}
private static void TrySend(EmoteMeanings emote, bool treehouseOnly, int subject)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Invalid comparison between Unknown and I4
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
try
{
string key = string.Concat(emote, ":", subject);
if (recentlySaid.TryGetValue(key, out var value) && Time.unscaledTime - value < 3f)
{
return;
}
if ((Object)(object)LobbyManager.instance == (Object)null)
{
ChatPlusPlugin.Log.LogInfo((object)"Chat+: auto chat skipped (no lobby manager)");
return;
}
if (treehouseOnly && !InTreehouse())
{
ChatPlusPlugin.Log.LogInfo((object)"Chat+: auto chat skipped (left the treehouse)");
return;
}
ChatDisplay chatSystem = GameState.ChatSystem;
if ((Object)(object)chatSystem == (Object)null || (int)GameSettings.GetInstance().OnlineChatEmotes == 2)
{
ChatPlusPlugin.Log.LogInfo((object)"Chat+: auto chat skipped (chat is off)");
return;
}
NetworkManager singleton = NetworkManager.singleton;
if ((Object)(object)singleton == (Object)null || singleton.client == null)
{
ChatPlusPlugin.Log.LogInfo((object)"Chat+: auto chat skipped (no network client)");
return;
}
LobbyPlayer val = LocalLobbyPlayer();
if ((Object)(object)val == (Object)null)
{
ChatPlusPlugin.Log.LogInfo((object)"Chat+: auto chat skipped (local player not found)");
return;
}
recentlySaid[key] = Time.unscaledTime;
chatSystem.NewChatMessage(string.Empty, emote, val.networkNumber);
}
catch (Exception ex)
{
ChatPlusPlugin.Log.LogError((object)("Chat+ auto chat failed: " + ex));
}
}
}
public class MsgChatPlusReaction : MessageBase
{
public int ReactorNumber;
public int TargetSpeaker;
public int Occurrence;
public int EmojiIndex;
public string TargetKey;
public override void Serialize(NetworkWriter writer)
{
writer.Write(ReactorNumber);
writer.Write(TargetSpeaker);
writer.Write(Occurrence);
writer.Write(EmojiIndex);
writer.Write(TargetKey ?? string.Empty);
}
public override void Deserialize(NetworkReader reader)
{
ReactorNumber = reader.ReadInt32();
TargetSpeaker = reader.ReadInt32();
Occurrence = reader.ReadInt32();
EmojiIndex = reader.ReadInt32();
TargetKey = reader.ReadString();
}
}
internal static class ChatPlusNet
{
internal const short ReactionMsgType = 3100;
private static NetworkClient registeredClient;
private static bool serverRegistered;
internal static void Poll()
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Expected O, but got Unknown
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Expected O, but got Unknown
if (NetworkServer.active)
{
if (!serverRegistered)
{
NetworkServer.RegisterHandler((short)3100, new NetworkMessageDelegate(OnServerMessage));
serverRegistered = true;
}
}
else
{
serverRegistered = false;
}
NetworkManager singleton = NetworkManager.singleton;
NetworkClient val = ((!((Object)(object)singleton != (Object)null)) ? null : singleton.client);
if (val != null && val.connection != null)
{
if (!object.ReferenceEquals(val, registeredClient))
{
val.RegisterHandler((short)3100, new NetworkMessageDelegate(OnClientMessage));
registeredClient = val;
}
}
else
{
registeredClient = null;
}
}
private static void OnServerMessage(NetworkMessage netMsg)
{
MsgChatPlusReaction msgChatPlusReaction = netMsg.ReadMessage<MsgChatPlusReaction>();
NetworkServer.SendToAll((short)3100, (MessageBase)(object)msgChatPlusReaction);
}
private static void OnClientMessage(NetworkMessage netMsg)
{
MsgChatPlusReaction msg = netMsg.ReadMessage<MsgChatPlusReaction>();
try
{
ChatPlusUI.ApplyReaction(msg);
}
catch (Exception ex)
{
ChatPlusPlugin.Log.LogError((object)("Chat+ could not show reaction: " + ex));
}
}
internal static void SendReaction(MsgChatPlusReaction msg)
{
NetworkManager singleton = NetworkManager.singleton;
if (!((Object)(object)singleton == (Object)null) && singleton.client != null && singleton.client.connection != null)
{
singleton.client.Send((short)3100, (MessageBase)(object)msg);
}
}
}
internal sealed class ChatPlusUnit : MonoBehaviour
{
internal ChatUnit Unit;
internal int Speaker;
internal string Key;
internal RectTransform Plus;
internal Image PlusImage;
internal CanvasGroup PlusGroup;
internal readonly Dictionary<int, GameObject> Reactions = new Dictionary<int, GameObject>();
private void OnDestroy()
{
ChatPlusUI.Live.Remove(this);
if ((Object)(object)ChatPlusUI.Selected == (Object)(object)this)
{
ChatPlusUI.Selected = null;
ChatPlusUI.NoteSelectionLost();
}
if ((Object)(object)ChatPlusUI.OpenFor == (Object)(object)this)
{
ChatPlusUI.ClosePicker();
}
}
}
internal static class ChatPlusUI
{
internal static readonly List<ChatPlusUnit> Live = new List<ChatPlusUnit>();
internal static ChatPlusUnit OpenFor;
internal static ChatPlusUnit Selected;
private static bool wasChatMode;
private static bool selectionLost;
private static int hoverIndex = -1;
private static Vector2 lastMouse;
private static string savedText = string.Empty;
private static int enforceFrames;
private static GameObject pickerRoot;
private static RectTransform pickerRect;
private static readonly List<RectTransform> cellRects = new List<RectTransform>();
private static readonly List<Image> cellImages = new List<Image>();
private static readonly Color PlusNormal = new Color(1f, 1f, 1f, 0.2f);
private static readonly Color PlusSelected = new Color(1f, 0.85f, 0.15f, 0.95f);
private const int Columns = 5;
private const int Rows = 2;
internal static void NoteSelectionLost()
{
selectionLost = true;
}
private static GameObject NewUI(string name, Transform parent, int layer, params Type[] components)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Expected O, but got Unknown
Type[] array = new Type[components.Length + 1];
array[0] = typeof(RectTransform);
Array.Copy(components, 0, array, 1, components.Length);
GameObject val = new GameObject(name, array);
val.layer = layer;
val.transform.SetParent(parent, false);
return val;
}
private static string MakeKey(ChatMessageDetails d)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Invalid comparison between Unknown and I4
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected I4, but got Unknown
bool flag = (int)d.EmoteType == 0 || (int)d.EmoteType == 10;
return (int)d.EmoteType + "|" + ((!flag) ? string.Empty : d.Message);
}
private static bool Contains(RectTransform rt, Vector2 screenPoint)
{
//IL_004a: 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)
Camera val = null;
Canvas componentInParent = ((Component)rt).GetComponentInParent<Canvas>();
if ((Object)(object)componentInParent != (Object)null)
{
componentInParent = componentInParent.rootCanvas;
if ((int)componentInParent.renderMode != 0)
{
val = ((!((Object)(object)componentInParent.worldCamera != (Object)null)) ? Camera.main : componentInParent.worldCamera);
}
}
return RectTransformUtility.RectangleContainsScreenPoint(rt, screenPoint, val);
}
private static void SetHighlight(ChatPlusUnit u, bool on)
{
//IL_0034: 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_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)u == (Object)null) && !((Object)(object)u.PlusImage == (Object)null))
{
((Graphic)u.PlusImage).color = ((!on) ? PlusNormal : PlusSelected);
((Transform)u.Plus).localScale = (Vector3)((!on) ? Vector3.one : new Vector3(1.25f, 1.25f, 1f));
}
}
private static void SelectUnit(ChatPlusUnit u)
{
if ((Object)(object)Selected != (Object)null && (Object)(object)Selected != (Object)(object)u)
{
SetHighlight(Selected, on: false);
}
Selected = u;
SetHighlight(u, on: true);
}
private static List<ChatPlusUnit> Ordered(ChatDisplay chat)
{
List<ChatPlusUnit> list = new List<ChatPlusUnit>();
List<ChatUnit> currentMessages = chat.currentMessages;
for (int i = 0; i < currentMessages.Count; i++)
{
ChatUnit val = currentMessages[i];
if (!((Object)(object)val == (Object)null))
{
ChatPlusUnit component = ((Component)val).GetComponent<ChatPlusUnit>();
if ((Object)(object)component != (Object)null && (Object)(object)component.Plus != (Object)null)
{
list.Add(component);
}
}
}
return list;
}
internal static void DecorateUnit(ChatUnit unit, ChatMessageDetails d)
{
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_0144: Unknown result type (might be due to invalid IL or missing references)
//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
//IL_022c: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)unit == (Object)null) && d.isChatMessage && !string.IsNullOrEmpty(d.UserName))
{
ChatPlusUnit chatPlusUnit = ((Component)unit).GetComponent<ChatPlusUnit>();
if ((Object)(object)chatPlusUnit == (Object)null)
{
chatPlusUnit = ((Component)unit).gameObject.AddComponent<ChatPlusUnit>();
}
if (!((Object)(object)chatPlusUnit.Plus != (Object)null))
{
chatPlusUnit.Unit = unit;
chatPlusUnit.Speaker = d.NetworkNumber;
chatPlusUnit.Key = MakeKey(d);
int chatMessageFontSize = GameSettings.GetInstance().ChatMessageFontSize;
int num = Mathf.Max(14, Mathf.RoundToInt((float)chatMessageFontSize * 1.6f));
int layer = ((Component)unit).gameObject.layer;
GameObject val = NewUI("ChatPlusButton", ((Component)unit).transform, layer, typeof(Image), typeof(LayoutElement), typeof(CanvasGroup));
Image component = val.GetComponent<Image>();
((Graphic)component).color = PlusNormal;
LayoutElement component2 = val.GetComponent<LayoutElement>();
component2.minWidth = num;
component2.preferredWidth = num;
component2.minHeight = num;
component2.preferredHeight = num;
component2.flexibleWidth = 0f;
RectTransform component3 = val.GetComponent<RectTransform>();
component3.sizeDelta = new Vector2((float)num, (float)num);
CanvasGroup component4 = val.GetComponent<CanvasGroup>();
component4.alpha = ((!PlusVisible(ChatIsOpen())) ? 0f : 1f);
GameObject val2 = NewUI("Plus", val.transform, layer, typeof(Text));
RectTransform component5 = val2.GetComponent<RectTransform>();
component5.anchorMin = Vector2.zero;
component5.anchorMax = Vector2.one;
component5.offsetMin = Vector2.zero;
component5.offsetMax = Vector2.zero;
Text component6 = val2.GetComponent<Text>();
component6.text = "+";
component6.font = ((!((Object)(object)unit.chatText != (Object)null)) ? null : unit.chatText.font);
component6.fontSize = chatMessageFontSize;
component6.alignment = (TextAnchor)4;
((Graphic)component6).color = Color.white;
((Graphic)component6).raycastTarget = false;
component6.horizontalOverflow = (HorizontalWrapMode)1;
component6.verticalOverflow = (VerticalWrapMode)1;
val.transform.SetAsLastSibling();
chatPlusUnit.Plus = component3;
chatPlusUnit.PlusImage = component;
chatPlusUnit.PlusGroup = component4;
Live.Add(chatPlusUnit);
}
}
}
private static bool PlusVisible(bool chatOpen)
{
return chatOpen || ChatPlusPlugin.PlusMode.Value == PlusButtonMode.Always;
}
private static bool ChatIsOpen()
{
ChatDisplay chatSystem = GameState.ChatSystem;
return (Object)(object)chatSystem != (Object)null && chatSystem.ChatMode;
}
private static void BuildPicker(Canvas rootCanvas, int layer)
{
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: 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_0171: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
int chatMessageFontSize = GameSettings.GetInstance().ChatMessageFontSize;
int num = Mathf.Max(36, chatMessageFontSize * 2);
int num2 = 6;
int num3 = 4;
pickerRoot = NewUI("ChatPlusPicker", ((Component)rootCanvas).transform, layer, typeof(Image));
((Graphic)pickerRoot.GetComponent<Image>()).color = new Color(0.07f, 0.07f, 0.1f, 0.93f);
pickerRect = pickerRoot.GetComponent<RectTransform>();
pickerRect.anchorMin = new Vector2(0.5f, 0.5f);
pickerRect.anchorMax = new Vector2(0.5f, 0.5f);
pickerRect.pivot = new Vector2(0f, 1f);
pickerRect.sizeDelta = new Vector2((float)(num2 * 2 + 5 * num + 4 * num3), (float)(num2 * 2 + 2 * num + num3));
cellRects.Clear();
cellImages.Clear();
for (int i = 0; i < 10; i++)
{
GameObject val = NewUI("Face" + i, pickerRoot.transform, layer, typeof(Image));
Image component = val.GetComponent<Image>();
component.sprite = Faces.Get(i);
component.preserveAspect = true;
((Graphic)component).color = new Color(0.7f, 0.7f, 0.7f, 1f);
RectTransform component2 = val.GetComponent<RectTransform>();
component2.anchorMin = new Vector2(0f, 1f);
component2.anchorMax = new Vector2(0f, 1f);
component2.pivot = new Vector2(0f, 1f);
component2.sizeDelta = new Vector2((float)num, (float)num);
int num4 = i % 5;
int num5 = i / 5;
component2.anchoredPosition = new Vector2((float)(num2 + num4 * (num + num3)), (float)(-(num2 + num5 * (num + num3))));
cellRects.Add(component2);
cellImages.Add(component);
}
}
private static void OpenPicker(ChatPlusUnit unit, bool byKeyboard)
{
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: 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_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_024c: Unknown result type (might be due to invalid IL or missing references)
//IL_0251: Unknown result type (might be due to invalid IL or missing references)
//IL_0253: Unknown result type (might be due to invalid IL or missing references)
ChatDisplay chatSystem = GameState.ChatSystem;
Canvas componentInParent = ((Component)chatSystem.ChatHolder).GetComponentInParent<Canvas>();
if (!((Object)(object)componentInParent == (Object)null))
{
componentInParent = componentInParent.rootCanvas;
if ((Object)(object)pickerRoot == (Object)null)
{
BuildPicker(componentInParent, ((Component)chatSystem.ChatHolder).gameObject.layer);
}
pickerRoot.transform.SetParent(((Component)componentInParent).transform, false);
pickerRoot.SetActive(true);
pickerRoot.transform.SetAsLastSibling();
OpenFor = unit;
hoverIndex = ((!byKeyboard) ? (-1) : 0);
lastMouse = Vector2.op_Implicit(Input.mousePosition);
InputField val = InputBox();
string text = ((!((Object)(object)val != (Object)null)) ? string.Empty : val.text);
savedText = ((!string.IsNullOrWhiteSpace(text)) ? text : string.Empty);
Vector3[] array = (Vector3[])(object)new Vector3[4];
unit.Plus.GetWorldCorners(array);
((Transform)pickerRect).position = array[0];
Vector3[] array2 = (Vector3[])(object)new Vector3[4];
Vector3[] array3 = (Vector3[])(object)new Vector3[4];
pickerRect.GetWorldCorners(array2);
((RectTransform)((Component)componentInParent).transform).GetWorldCorners(array3);
Vector3 zero = Vector3.zero;
if (array2[2].x > array3[2].x)
{
zero.x = array3[2].x - array2[2].x;
}
if (array2[0].x < array3[0].x)
{
zero.x = array3[0].x - array2[0].x;
}
if (array2[0].y < array3[0].y)
{
zero.y = array3[0].y - array2[0].y;
}
if (array2[1].y > array3[1].y)
{
zero.y = array3[1].y - array2[1].y;
}
RectTransform obj = pickerRect;
((Transform)obj).position = ((Transform)obj).position + zero;
ApplyHover();
}
}
internal static void ClosePicker()
{
bool flag = (Object)(object)pickerRoot != (Object)null && pickerRoot.activeSelf;
if ((Object)(object)pickerRoot != (Object)null)
{
pickerRoot.SetActive(false);
}
OpenFor = null;
hoverIndex = -1;
if (flag)
{
enforceFrames = 3;
}
}
private static InputField InputBox()
{
ChatDisplay chatSystem = GameState.ChatSystem;
if ((Object)(object)chatSystem == (Object)null || (Object)(object)chatSystem.currentChatInputField == (Object)null)
{
return null;
}
return chatSystem.currentChatInputField.inputField;
}
private static int HitCell(Vector2 mp)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < cellRects.Count; i++)
{
if ((Object)(object)cellRects[i] != (Object)null && Contains(cellRects[i], mp))
{
return i;
}
}
return -1;
}
private static void ApplyHover()
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
for (int i = 0; i < cellImages.Count; i++)
{
bool flag = i == hoverIndex;
float num = ((!flag) ? 0.7f : 1f);
((Graphic)cellImages[i]).color = new Color(num, num, num, 1f);
((Transform)cellRects[i]).localScale = (Vector3)((!flag) ? Vector3.one : new Vector3(1.2f, 1.2f, 1f));
}
}
internal static void Tick()
{
//IL_020a: Unknown result type (might be due to invalid IL or missing references)
//IL_020f: Unknown result type (might be due to invalid IL or missing references)
//IL_0214: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_021f: Unknown result type (might be due to invalid IL or missing references)
//IL_0224: Unknown result type (might be due to invalid IL or missing references)
//IL_0229: Unknown result type (might be due to invalid IL or missing references)
//IL_023b: Unknown result type (might be due to invalid IL or missing references)
//IL_023d: Unknown result type (might be due to invalid IL or missing references)
//IL_0249: Unknown result type (might be due to invalid IL or missing references)
//IL_0468: Unknown result type (might be due to invalid IL or missing references)
//IL_0486: 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)
ChatDisplay chatSystem = GameState.ChatSystem;
if ((Object)(object)chatSystem == (Object)null || (Object)(object)chatSystem.ChatHolder == (Object)null)
{
return;
}
bool chatMode = chatSystem.ChatMode;
if (chatMode != wasChatMode)
{
wasChatMode = chatMode;
if (chatMode)
{
List<ChatPlusUnit> list = Ordered(chatSystem);
selectionLost = false;
SelectUnit((list.Count <= 0) ? null : list[list.Count - 1]);
}
else
{
ClosePicker();
SelectUnit(null);
}
}
for (int num = Live.Count - 1; num >= 0; num--)
{
ChatPlusUnit chatPlusUnit = Live[num];
if ((Object)(object)chatPlusUnit == (Object)null)
{
Live.RemoveAt(num);
}
else if ((Object)(object)chatPlusUnit.PlusGroup != (Object)null)
{
chatPlusUnit.PlusGroup.alpha = ((!PlusVisible(chatMode)) ? 0f : 1f);
}
}
InputField val = InputBox();
bool flag = (Object)(object)pickerRoot != (Object)null && pickerRoot.activeSelf;
if ((Object)(object)val != (Object)null && (flag || enforceFrames > 0))
{
if (val.text != savedText)
{
val.text = savedText;
val.caretPosition = savedText.Length;
}
if (!flag)
{
enforceFrames--;
}
}
if (!chatMode)
{
return;
}
List<ChatPlusUnit> list2 = Ordered(chatSystem);
if ((Object)(object)Selected == (Object)null && list2.Count > 0)
{
SelectUnit((!selectionLost) ? list2[list2.Count - 1] : list2[0]);
selectionLost = false;
}
bool flag2 = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
Vector2 val2 = Vector2.op_Implicit(Input.mousePosition);
if (flag)
{
Vector2 val3 = val2 - lastMouse;
bool flag3 = ((Vector2)(ref val3)).sqrMagnitude > 1f;
lastMouse = val2;
if (flag3)
{
int num2 = HitCell(val2);
if (num2 >= 0)
{
hoverIndex = num2;
}
}
int num3 = ((hoverIndex >= 0) ? hoverIndex : 0);
if (Input.GetKeyDown((KeyCode)9))
{
hoverIndex = (num3 + ((!flag2) ? 1 : 9)) % 10;
}
else if (Input.GetKeyDown((KeyCode)275))
{
hoverIndex = Mathf.Min(num3 + 1, 9);
}
else if (Input.GetKeyDown((KeyCode)276))
{
hoverIndex = Mathf.Max(num3 - 1, 0);
}
else if (Input.GetKeyDown((KeyCode)274))
{
hoverIndex = ((num3 + 5 >= 10) ? num3 : (num3 + 5));
}
else if (Input.GetKeyDown((KeyCode)273))
{
hoverIndex = ((num3 - 5 < 0) ? num3 : (num3 - 5));
}
else
{
if (Input.GetKeyDown((KeyCode)32))
{
Choose(num3);
return;
}
if (Input.GetKeyDown((KeyCode)8))
{
ClosePicker();
return;
}
}
ApplyHover();
}
else if (Input.GetKeyDown((KeyCode)9) && list2.Count > 0)
{
int num4 = ((!((Object)(object)Selected != (Object)null)) ? (-1) : list2.IndexOf(Selected));
int index = ((num4 < 0) ? (list2.Count - 1) : ((!flag2) ? ((num4 + 1) % list2.Count) : ((num4 - 1 + list2.Count) % list2.Count)));
SelectUnit(list2[index]);
}
else if (Input.GetKeyDown((KeyCode)32) && (Object)(object)Selected != (Object)null && (Object)(object)val != (Object)null && string.IsNullOrWhiteSpace(val.text))
{
OpenPicker(Selected, byKeyboard: true);
return;
}
if (!Input.GetMouseButtonDown(0))
{
return;
}
if (flag)
{
int num5 = HitCell(val2);
if (num5 >= 0)
{
Choose(num5);
return;
}
bool flag4 = Contains(pickerRect, val2);
ClosePicker();
if (flag4)
{
return;
}
}
if ((Object)(object)chatSystem.ChatCanvasGroup != (Object)null && chatSystem.ChatCanvasGroup.alpha < 0.4f)
{
return;
}
for (int num6 = Live.Count - 1; num6 >= 0; num6--)
{
ChatPlusUnit chatPlusUnit2 = Live[num6];
if (!((Object)(object)chatPlusUnit2 == (Object)null) && !((Object)(object)chatPlusUnit2.Plus == (Object)null) && ((Component)chatPlusUnit2.Plus).gameObject.activeInHierarchy && Contains(chatPlusUnit2.Plus, val2))
{
SelectUnit(chatPlusUnit2);
OpenPicker(chatPlusUnit2, byKeyboard: false);
break;
}
}
}
private static void Choose(int emojiIndex)
{
ChatPlusUnit openFor = OpenFor;
ClosePicker();
if ((Object)(object)openFor == (Object)null || (Object)(object)openFor.Unit == (Object)null)
{
return;
}
LobbyPlayer val = AutoChat.LocalLobbyPlayer();
ChatDisplay chatSystem = GameState.ChatSystem;
if ((Object)(object)val == (Object)null || (Object)(object)chatSystem == (Object)null)
{
return;
}
int num = 0;
List<ChatUnit> currentMessages = chatSystem.currentMessages;
for (int num2 = currentMessages.Count - 1; num2 >= 0; num2--)
{
ChatUnit val2 = currentMessages[num2];
if (!((Object)(object)val2 == (Object)null))
{
if ((Object)(object)val2 == (Object)(object)openFor.Unit)
{
break;
}
ChatPlusUnit component = ((Component)val2).GetComponent<ChatPlusUnit>();
if ((Object)(object)component != (Object)null && component.Speaker == openFor.Speaker && component.Key == openFor.Key)
{
num++;
}
}
}
MsgChatPlusReaction msgChatPlusReaction = new MsgChatPlusReaction();
msgChatPlusReaction.ReactorNumber = val.networkNumber;
msgChatPlusReaction.TargetSpeaker = openFor.Speaker;
msgChatPlusReaction.Occurrence = num;
msgChatPlusReaction.EmojiIndex = emojiIndex;
msgChatPlusReaction.TargetKey = openFor.Key;
ChatPlusNet.SendReaction(msgChatPlusReaction);
}
internal static void ApplyReaction(MsgChatPlusReaction msg)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Invalid comparison between Unknown and I4
//IL_013d: Unknown result type (might be due to invalid IL or missing references)
if (msg == null || msg.EmojiIndex < 0 || msg.EmojiIndex >= 10 || (int)GameSettings.GetInstance().OnlineChatEmotes == 2)
{
return;
}
LobbyManager instance = LobbyManager.instance;
ChatDisplay chatSystem = GameState.ChatSystem;
if ((Object)(object)instance == (Object)null || (Object)(object)chatSystem == (Object)null)
{
return;
}
LobbyPlayer lobbyPlayer = instance.GetLobbyPlayer(msg.ReactorNumber);
if ((Object)(object)lobbyPlayer == (Object)null || lobbyPlayer.Muted)
{
return;
}
ChatPlusUnit chatPlusUnit = null;
int num = 0;
List<ChatUnit> currentMessages = chatSystem.currentMessages;
for (int num2 = currentMessages.Count - 1; num2 >= 0; num2--)
{
ChatUnit val = currentMessages[num2];
if (!((Object)(object)val == (Object)null))
{
ChatPlusUnit component = ((Component)val).GetComponent<ChatPlusUnit>();
if (!((Object)(object)component == (Object)null) && component.Speaker == msg.TargetSpeaker && !(component.Key != msg.TargetKey))
{
if (num == msg.Occurrence)
{
chatPlusUnit = component;
break;
}
num++;
}
}
}
if (!((Object)(object)chatPlusUnit == (Object)null))
{
AddReaction(chatPlusUnit, msg.ReactorNumber, lobbyPlayer.playerName, lobbyPlayer.PlayerColor, msg.EmojiIndex);
}
}
private static void AddReaction(ChatPlusUnit cpu, int reactorNumber, string reactorName, Color reactorColor, int emojiIndex)
{
//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
//IL_023f: Unknown result type (might be due to invalid IL or missing references)
//IL_0249: Expected O, but got Unknown
if (cpu.Reactions.TryGetValue(reactorNumber, out var value) && (Object)(object)value != (Object)null)
{
Object.Destroy((Object)(object)value);
}
ChatUnit unit = cpu.Unit;
int chatMessageFontSize = GameSettings.GetInstance().ChatMessageFontSize;
int num = Mathf.Max(14, Mathf.RoundToInt((float)chatMessageFontSize * 1.6f));
int layer = ((Component)unit).gameObject.layer;
GameObject val = NewUI("ChatPlusReaction", ((Component)unit).transform, layer, typeof(HorizontalLayoutGroup), typeof(ContentSizeFitter));
HorizontalLayoutGroup component = val.GetComponent<HorizontalLayoutGroup>();
((HorizontalOrVerticalLayoutGroup)component).spacing = 3f;
((LayoutGroup)component).childAlignment = (TextAnchor)3;
((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true;
((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true;
((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false;
((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false;
ContentSizeFitter component2 = val.GetComponent<ContentSizeFitter>();
component2.horizontalFit = (FitMode)2;
component2.verticalFit = (FitMode)2;
GameObject val2 = NewUI("Face", val.transform, layer, typeof(Image), typeof(LayoutElement));
Image component3 = val2.GetComponent<Image>();
component3.sprite = Faces.Get(emojiIndex);
component3.preserveAspect = true;
((Graphic)component3).raycastTarget = false;
LayoutElement component4 = val2.GetComponent<LayoutElement>();
component4.minWidth = num;
component4.preferredWidth = num;
component4.minHeight = num;
component4.preferredHeight = num;
GameObject val3 = NewUI("Name", val.transform, layer, typeof(Text));
Text component5 = val3.GetComponent<Text>();
component5.text = reactorName;
component5.font = ((!((Object)(object)unit.chatText != (Object)null)) ? null : unit.chatText.font);
component5.fontSize = chatMessageFontSize;
((Graphic)component5).color = reactorColor;
component5.alignment = (TextAnchor)3;
((Graphic)component5).raycastTarget = false;
component5.horizontalOverflow = (HorizontalWrapMode)1;
component5.verticalOverflow = (VerticalWrapMode)1;
val.transform.SetAsLastSibling();
cpu.Reactions[reactorNumber] = val;
RectTransform component6 = ((Component)unit).GetComponent<RectTransform>();
LayoutRebuilder.MarkLayoutForRebuild(component6);
if (((Transform)component6).parent is RectTransform)
{
LayoutRebuilder.MarkLayoutForRebuild((RectTransform)((Transform)component6).parent);
}
}
}
internal static class Faces
{
internal const int Count = 10;
private static Sprite[] sprites;
internal static Sprite Get(int index)
{
if (sprites == null)
{
sprites = (Sprite[])(object)new Sprite[10];
for (int i = 0; i < 10; i++)
{
sprites[i] = MakeFace(i);
}
}
return sprites[Mathf.Clamp(index, 0, 9)];
}
private static Sprite MakeFace(int i)
{
//IL_004a: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
//IL_020c: Unknown result type (might be due to invalid IL or missing references)
//IL_022b: Unknown result type (might be due to invalid IL or missing references)
//IL_0247: Unknown result type (might be due to invalid IL or missing references)
//IL_0263: Unknown result type (might be due to invalid IL or missing references)
//IL_027a: Unknown result type (might be due to invalid IL or missing references)
//IL_0291: Unknown result type (might be due to invalid IL or missing references)
//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
//IL_0302: Unknown result type (might be due to invalid IL or missing references)
//IL_031d: Unknown result type (might be due to invalid IL or missing references)
//IL_0333: Unknown result type (might be due to invalid IL or missing references)
//IL_0353: Unknown result type (might be due to invalid IL or missing references)
//IL_0373: Unknown result type (might be due to invalid IL or missing references)
//IL_0398: Unknown result type (might be due to invalid IL or missing references)
//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
//IL_040f: Unknown result type (might be due to invalid IL or missing references)
//IL_0425: Unknown result type (might be due to invalid IL or missing references)
//IL_044a: Unknown result type (might be due to invalid IL or missing references)
//IL_0465: Unknown result type (might be due to invalid IL or missing references)
//IL_047c: Unknown result type (might be due to invalid IL or missing references)
//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
//IL_04bd: Unknown result type (might be due to invalid IL or missing references)
//IL_04d3: Unknown result type (might be due to invalid IL or missing references)
//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
//IL_0513: Unknown result type (might be due to invalid IL or missing references)
//IL_0533: Unknown result type (might be due to invalid IL or missing references)
//IL_0549: Unknown result type (might be due to invalid IL or missing references)
//IL_056e: Unknown result type (might be due to invalid IL or missing references)
//IL_0592: Unknown result type (might be due to invalid IL or missing references)
//IL_05ae: Unknown result type (might be due to invalid IL or missing references)
//IL_05cf: Unknown result type (might be due to invalid IL or missing references)
//IL_0604: Unknown result type (might be due to invalid IL or missing references)
//IL_062d: Unknown result type (might be due to invalid IL or missing references)
//IL_0657: Unknown result type (might be due to invalid IL or missing references)
//IL_066d: Unknown result type (might be due to invalid IL or missing references)
//IL_0692: Unknown result type (might be due to invalid IL or missing references)
//IL_0767: Unknown result type (might be due to invalid IL or missing references)
//IL_0776: Unknown result type (might be due to invalid IL or missing references)
//IL_06bc: Unknown result type (might be due to invalid IL or missing references)
//IL_06e1: Unknown result type (might be due to invalid IL or missing references)
//IL_06fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0718: Unknown result type (might be due to invalid IL or missing references)
//IL_073e: Unknown result type (might be due to invalid IL or missing references)
Painter painter = new Painter(64);
Color val = default(Color);
((Color)(ref val))..ctor(1f, 0.83f, 0.22f);
Color c = default(Color);
((Color)(ref c))..ctor(0.35f, 0.2f, 0.05f);
Color c2 = default(Color);
((Color)(ref c2))..ctor(0.22f, 0.12f, 0.05f);
Color white = Color.white;
Color c3 = default(Color);
((Color)(ref c3))..ctor(0.35f, 0.7f, 1f);
Color c4 = default(Color);
((Color)(ref c4))..ctor(0.9f, 0.1f, 0.2f);
Color c5 = default(Color);
((Color)(ref c5))..ctor(1f, 0.45f, 0.5f, 0.75f);
Color c6 = default(Color);
((Color)(ref c6))..ctor(0.06f, 0.06f, 0.08f);
Color c7 = (Color)((i != 4) ? val : new Color(0.96f, 0.36f, 0.2f));
painter.Circle(32f, 32f, 30.5f, c);
painter.Circle(32f, 32f, 28f, c7);
switch (i)
{
case 0:
painter.Circle(22f, 40f, 3.6f, c2);
painter.Circle(42f, 40f, 3.6f, c2);
painter.Arc(32f, 36f, 16f, 205f, 335f, 3.2f, c2);
break;
case 1:
painter.Arc(21f, 40f, 5.5f, 25f, 155f, 3f, c2);
painter.Arc(43f, 40f, 5.5f, 25f, 155f, 3f, c2);
painter.Ellipse(32f, 25f, 13f, 9f, c2);
painter.Ellipse(32f, 19.5f, 7f, 4f, new Color(0.95f, 0.4f, 0.45f));
painter.Ellipse(12f, 32f, 3f, 4.5f, c3);
painter.Ellipse(52f, 32f, 3f, 4.5f, c3);
break;
case 2:
painter.Circle(22f, 41f, 5.5f, white);
painter.Circle(42f, 41f, 5.5f, white);
painter.Circle(22f, 41f, 2.6f, c2);
painter.Circle(42f, 41f, 2.6f, c2);
painter.Line(15f, 51f, 28f, 53f, 2.6f, c2);
painter.Line(36f, 53f, 49f, 51f, 2.6f, c2);
painter.Ellipse(32f, 19f, 5.5f, 8f, c2);
break;
case 3:
painter.Circle(22f, 38f, 3.3f, c2);
painter.Circle(42f, 38f, 3.3f, c2);
painter.Line(15f, 45f, 27f, 49f, 2.6f, c2);
painter.Line(49f, 45f, 37f, 49f, 2.6f, c2);
painter.Arc(32f, 14f, 13f, 45f, 135f, 3f, c2);
painter.Ellipse(21f, 30f, 2.6f, 4f, c3);
break;
case 4:
painter.Line(14f, 48f, 28f, 41f, 3.4f, c2);
painter.Line(50f, 48f, 36f, 41f, 3.4f, c2);
painter.Circle(22f, 36f, 3.3f, c2);
painter.Circle(42f, 36f, 3.3f, c2);
painter.Arc(32f, 12f, 13f, 50f, 130f, 3.2f, c2);
break;
case 5:
painter.Heart(22f, 40f, 3.6f, c4);
painter.Heart(42f, 40f, 3.6f, c4);
painter.Arc(32f, 36f, 16f, 205f, 335f, 3.2f, c2);
break;
case 6:
painter.Circle(22f, 39f, 3.2f, c2);
painter.Circle(42f, 39f, 3.2f, c2);
painter.Line(15f, 45f, 28f, 46.5f, 2.4f, c2);
painter.Line(36f, 50f, 49f, 48f, 2.4f, c2);
painter.Line(22f, 24f, 38f, 27f, 3f, c2);
painter.Circle(44f, 14f, 8.5f, c);
painter.Circle(44f, 14f, 7f, new Color(1f, 0.7f, 0.2f));
break;
case 7:
painter.Ellipse(21f, 40f, 9f, 6.5f, c6);
painter.Ellipse(43f, 40f, 9f, 6.5f, c6);
painter.Line(29f, 41f, 35f, 41f, 2.4f, c6);
painter.Line(17f, 43f, 21f, 43f, 1.6f, new Color(1f, 1f, 1f, 0.5f));
painter.Arc(32f, 34f, 16f, 205f, 335f, 3.2f, c2);
break;
case 8:
painter.Arc(21f, 40f, 5.5f, 25f, 155f, 3f, c2);
painter.Circle(43f, 40f, 3.6f, c2);
painter.Arc(32f, 36f, 16f, 205f, 335f, 3.2f, c2);
break;
default:
painter.Arc(21f, 40f, 5.5f, 25f, 155f, 3f, c2);
painter.Arc(43f, 40f, 5.5f, 25f, 155f, 3f, c2);
painter.Ellipse(14f, 29f, 5.5f, 3.2f, c5);
painter.Ellipse(50f, 29f, 5.5f, 3.2f, c5);
painter.Arc(32f, 33f, 11f, 210f, 330f, 3f, c2);
break;
}
Texture2D val2 = painter.ToTexture();
return Sprite.Create(val2, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f);
}
}
internal sealed class Painter
{
private readonly int size;
private readonly Color[] px;
internal Painter(int size)
{
this.size = size;
px = (Color[])(object)new Color[size * size];
}
internal Texture2D ToTexture()
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Expected O, but got Unknown
Texture2D val = new Texture2D(size, size, (TextureFormat)4, false);
val.SetPixels(px);
((Texture)val).filterMode = (FilterMode)1;
((Texture)val).wrapMode = (TextureWrapMode)1;
val.Apply();
return val;
}
private void Blend(int x, int y, Color c, float coverage)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
coverage = Mathf.Clamp01(coverage) * c.a;
if (!(coverage <= 0f))
{
int num = y * size + x;
Color val = px[num];
float num2 = coverage + val.a * (1f - coverage);
if (!(num2 <= 0f))
{
ref Color reference = ref px[num];
reference = new Color((c.r * coverage + val.r * val.a * (1f - coverage)) / num2, (c.g * coverage + val.g * val.a * (1f - coverage)) / num2, (c.b * coverage + val.b * val.a * (1f - coverage)) / num2, num2);
}
}
}
private void Fill(float minX, float minY, float maxX, float maxY, Func<float, float, float> signedDistance, Color c)
{
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
int num = Mathf.Max(0, Mathf.FloorToInt(minX));
int num2 = Mathf.Max(0, Mathf.FloorToInt(minY));
int num3 = Mathf.Min(size - 1, Mathf.CeilToInt(maxX));
int num4 = Mathf.Min(size - 1, Mathf.CeilToInt(maxY));
for (int i = num2; i <= num4; i++)
{
for (int j = num; j <= num3; j++)
{
float num5 = signedDistance((float)j + 0.5f, (float)i + 0.5f);
if (num5 > -0.5f)
{
Blend(j, i, c, num5 + 0.5f);
}
}
}
}
internal void Circle(float cx, float cy, float r, Color c)
{
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
Fill(cx - r - 1f, cy - r - 1f, cx + r + 1f, cy + r + 1f, (float x, float y) => r - Mathf.Sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy)), c);
}
internal void Ellipse(float cx, float cy, float rx, float ry, Color c)
{
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
float m = Mathf.Min(rx, ry);
Fill(cx - rx - 1f, cy - ry - 1f, cx + rx + 1f, cy + ry + 1f, delegate(float x, float y)
{
float num = (x - cx) / rx;
float num2 = (y - cy) / ry;
return (1f - Mathf.Sqrt(num * num + num2 * num2)) * m;
}, c);
}
internal void Line(float x0, float y0, float x1, float y1, float thickness, Color c)
{
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
float h = thickness * 0.5f;
Fill(Mathf.Min(x0, x1) - h - 1f, Mathf.Min(y0, y1) - h - 1f, Mathf.Max(x0, x1) + h + 1f, Mathf.Max(y0, y1) + h + 1f, (float num, float py) => h - DistToSegment(num, py, x0, y0, x1, y1), c);
}
internal void Arc(float cx, float cy, float r, float a0, float a1, float thickness, Color c)
{
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
float h = thickness * 0.5f;
float e0x = cx + r * Mathf.Cos(a0 * ((float)Math.PI / 180f));
float e0y = cy + r * Mathf.Sin(a0 * ((float)Math.PI / 180f));
float e1x = cx + r * Mathf.Cos(a1 * ((float)Math.PI / 180f));
float e1y = cy + r * Mathf.Sin(a1 * ((float)Math.PI / 180f));
Fill(cx - r - h - 1f, cy - r - h - 1f, cx + r + h + 1f, cy + r + h + 1f, delegate(float x, float y)
{
float num = x - cx;
float num2 = y - cy;
float num3 = Mathf.Atan2(num2, num) * 57.29578f;
if (num3 < 0f)
{
num3 += 360f;
}
if (num3 >= a0 && num3 <= a1)
{
return h - Mathf.Abs(Mathf.Sqrt(num * num + num2 * num2) - r);
}
float num4 = Mathf.Sqrt((x - e0x) * (x - e0x) + (y - e0y) * (y - e0y));
float num5 = Mathf.Sqrt((x - e1x) * (x - e1x) + (y - e1y) * (y - e1y));
return h - Mathf.Min(num4, num5);
}, c);
}
internal void Heart(float cx, float cy, float s, Color c)
{
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
int num = Mathf.Max(0, Mathf.FloorToInt(cx - s * 1.6f));
int num2 = Mathf.Min(size - 1, Mathf.CeilToInt(cx + s * 1.6f));
int num3 = Mathf.Max(0, Mathf.FloorToInt(cy - s * 1.4f));
int num4 = Mathf.Min(size - 1, Mathf.CeilToInt(cy + s * 1.6f));
for (int i = num3; i <= num4; i++)
{
for (int j = num; j <= num2; j++)
{
int num5 = 0;
for (int k = 0; k < 3; k++)
{
for (int l = 0; l < 3; l++)
{
float num6 = ((float)j + ((float)l + 0.5f) / 3f - cx) / s;
float num7 = ((float)i + ((float)k + 0.5f) / 3f - cy) / s;
float num8 = num6 * num6 + num7 * num7 - 1f;
if (num8 * num8 * num8 - num6 * num6 * num7 * num7 * num7 <= 0f)
{
num5++;
}
}
}
if (num5 > 0)
{
Blend(j, i, c, (float)num5 / 9f);
}
}
}
}
private static float DistToSegment(float px, float py, float ax, float ay, float bx, float by)
{
float num = bx - ax;
float num2 = by - ay;
float num3 = num * num + num2 * num2;
float num4 = ((!(num3 <= 0f)) ? Mathf.Clamp01(((px - ax) * num + (py - ay) * num2) / num3) : 0f);
float num5 = ax + num * num4;
float num6 = ay + num2 * num4;
return Mathf.Sqrt((px - num5) * (px - num5) + (py - num6) * (py - num6));
}
}