Decompiled source of DiscordBot v1.0.0
DiscordBot.dll
Decompiled 4 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using LocalizationManager; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using ServerSync; using Splatform; using TMPro; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; [assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyProduct("DiscordBot")] [assembly: AssemblyCompany("RustyMods")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyDescription("")] [assembly: AssemblyTitle("DiscordBot")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyFileVersion("1.0.0")] [assembly: AssemblyConfiguration("")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [<1863e386-205e-4925-b386-c4d06fe873e9>Embedded] internal sealed class <1863e386-205e-4925-b386-c4d06fe873e9>EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [<1863e386-205e-4925-b386-c4d06fe873e9>Embedded] [CompilerGenerated] internal sealed class <0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>NullableAttribute : Attribute { public readonly byte[] NullableFlags; public <0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public <0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [<1863e386-205e-4925-b386-c4d06fe873e9>Embedded] [CompilerGenerated] internal sealed class <2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContextAttribute : Attribute { public readonly byte Flag; public <2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace DiscordBot { [BepInPlugin("RustyMods.DiscordBot", "DiscordBot", "1.0.0")] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] public class DiscordBotPlugin : BaseUnityPlugin { [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] public enum Toggle { On = 1, Off = 0 } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] public enum Webhook { Notifications, Chat, Commands } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] public enum Channel { Chat, Commands } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] public enum ChatDisplay { Player, Bot } [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] public class StringListConfig { public readonly List<string> list; public StringListConfig(List<string> items) { list = items; } public StringListConfig(string items) { list = items.Split(new char[1] { ',' }).ToList(); } public static void Draw(ConfigEntryBase cfg) { //IL_00e8: 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_0103: Expected O, but got Unknown //IL_0132: 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_014d: Expected O, but got Unknown bool valueOrDefault = cfg.Description.Tags.Select([<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] (object a) => (a.GetType().Name == "ConfigurationManagerAttributes") ? ((bool?)a.GetType().GetField("ReadOnly")?.GetValue(a)) : null).FirstOrDefault((bool? v) => v.HasValue).GetValueOrDefault(); bool flag = false; List<string> list = new List<string>(); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); foreach (string item2 in new StringListConfig((string)cfg.BoxedValue).list) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); string item = item2; string text = GUILayout.TextField(item2, Array.Empty<GUILayoutOption>()); if (text != item2 && !valueOrDefault) { flag = true; item = text; } if (GUILayout.Button("x", new GUIStyle(GUI.skin.button) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>()) && !valueOrDefault) { flag = true; } else { list.Add(item); } if (GUILayout.Button("+", new GUIStyle(GUI.skin.button) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>()) && !valueOrDefault) { list.Add(""); flag = true; } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); if (flag) { cfg.BoxedValue = new StringListConfig(list).ToString(); } } public override string ToString() { return string.Join(",", list); } } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] public class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order = null; [UsedImplicitly] public bool? Browsable = null; [UsedImplicitly] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(2)] public string Category = null; [UsedImplicitly] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public Action<ConfigEntryBase> CustomDrawer = null; } internal const string ModName = "DiscordBot"; internal const string ModVersion = "1.0.0"; internal const string Author = "RustyMods"; private const string ModGUID = "RustyMods.DiscordBot"; private static readonly string ConfigFileName = "RustyMods.DiscordBot.cfg"; private static readonly string ConfigFileFullPath; internal static string ConnectionError; private readonly Harmony _harmony = new Harmony("RustyMods.DiscordBot"); public static readonly ManualLogSource DiscordBotLogger; private static readonly ConfigSync ConfigSync; private static ConfigEntry<Toggle> _serverConfigLocked; public static DiscordBotPlugin m_instance; public static ConfigEntry<string> m_notificationWebhookURL; public static ConfigEntry<Toggle> m_serverStartNotice; public static ConfigEntry<Toggle> m_serverStopNotice; public static ConfigEntry<Toggle> m_serverSaveNotice; public static ConfigEntry<Toggle> m_deathNotice; public static ConfigEntry<Toggle> m_loginNotice; public static ConfigEntry<Toggle> m_logoutNotice; public static ConfigEntry<string> m_chatWebhookURL; public static ConfigEntry<string> m_chatChannelID; public static ConfigEntry<Toggle> m_chatEnabled; public static ConfigEntry<ChatDisplay> m_chatType; public static ConfigEntry<string> m_commandWebhookURL; public static ConfigEntry<string> m_commandChannelID; public static ConfigEntry<int> m_pollInterval; public static ConfigEntry<string> m_discordAdmins; public static ConfigEntry<Toggle> m_logErrors; public static ConfigEntry<string> m_botToken; public static string GetWebhookURL(Webhook type) { if (1 == 0) { } string result = type switch { Webhook.Chat => m_chatWebhookURL.Value, Webhook.Notifications => m_notificationWebhookURL.Value, Webhook.Commands => m_commandWebhookURL.Value, _ => m_chatWebhookURL.Value, }; if (1 == 0) { } return result; } public static string GetChannelID(Channel type) { if (1 == 0) { } string result = type switch { Channel.Chat => m_chatChannelID.Value, Channel.Commands => m_commandChannelID.Value, _ => m_chatChannelID.Value, }; if (1 == 0) { } return result; } public void Awake() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Expected O, but got Unknown Localizer.Load(); m_instance = this; _serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only."); ConfigSync.AddLockingConfigEntry<Toggle>(_serverConfigLocked); m_pollInterval = config("1 - General", "Poll Interval", 5, new ConfigDescription("Set interval between check for messages in discord, in seconds", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 300), Array.Empty<object>())); m_logErrors = config("1 - General", "Log Errors", Toggle.Off, "If on, errors will log to console as warnings"); m_notificationWebhookURL = config("2 - Notifications", "Webhook URL", "", "Set webhook to receive notifications, like server start, stop, save etc..."); m_serverStartNotice = config("2 - Notifications", "Startup", Toggle.On, "If on, bot will send message when server is starting"); m_serverStopNotice = config("2 - Notifications", "Shutdown", Toggle.On, "If on, bot will send message when server is shutting down"); m_serverSaveNotice = config("2 - Notifications", "Saving", Toggle.On, "If on, bot will send message when server is saving"); m_deathNotice = config("2 - Notifications", "On Death", Toggle.On, "If on, bot will send message when player dies"); m_loginNotice = config("2 - Notifications", "Login", Toggle.On, "If on, bot will send message when player logs in"); m_logoutNotice = config("2 - Notifications", "Logout", Toggle.On, "If on, bot will send message when player logs out"); m_chatWebhookURL = config("3 - Chat", "Webhook URL", "", "Set discord webhook to display chat messages"); m_chatChannelID = config("3 - Chat", "Channel ID", "", "Set channel ID to monitor for messages"); m_chatEnabled = config("3 - Chat", "Enabled", Toggle.On, "If on, bot will send message when player shouts and monitor discord for messages"); m_chatType = config("3 - Chat", "Display As", ChatDisplay.Player, "Set how chat messages appear, if Player, message sent by player, else sent by bot with a prefix that player is saying"); m_commandWebhookURL = config("4 - Commands", "Webhook URL", "", "Set discord webhook to display feedback messages from commands"); m_commandChannelID = config("4 - Commands", "Channel ID", "", "Set channel ID to monitor for input commands"); m_discordAdmins = config("4 - Commands", "Discord Admin", "", new ConfigDescription("List of discord admins, who can run commands", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = StringListConfig.Draw } })); m_botToken = config("5 - Setup", "BOT TOKEN", "", "Add bot token here, server only", synchronizedSetting: false); DiscordCommands.Setup(); Assembly executingAssembly = Assembly.GetExecutingAssembly(); _harmony.PatchAll(executingAssembly); SetupWatcher(); } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); } private void SetupWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); fileSystemWatcher.Changed += ReadConfigValues; fileSystemWatcher.Created += ReadConfigValues; fileSystemWatcher.Renamed += ReadConfigValues; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { if (!File.Exists(ConfigFileFullPath)) { return; } try { DiscordBotLogger.LogDebug((object)"ReadConfigValues called"); ((BaseUnityPlugin)this).Config.Reload(); } catch { DiscordBotLogger.LogError((object)("There was an issue loading your " + ConfigFileName)); DiscordBotLogger.LogError((object)"Please check your config entries for spelling and format!"); } } private ConfigEntry<T> config<[<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val); SyncedConfigEntry<T> syncedConfigEntry = ConfigSync.AddConfigEntry<T>(val2); syncedConfigEntry.SynchronizedConfig = synchronizedSetting; return val2; } public ConfigEntry<T> config<[<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(2)] T>(string group, string name, T value, string description, bool synchronizedSetting = true) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } static DiscordBotPlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; ConnectionError = ""; DiscordBotLogger = Logger.CreateLogSource("DiscordBot"); ConfigSync = new ConfigSync("RustyMods.DiscordBot") { DisplayName = "DiscordBot", CurrentVersion = "1.0.0", MinimumRequiredVersion = "1.0.0" }; _serverConfigLocked = null; m_instance = null; m_notificationWebhookURL = null; m_serverStartNotice = null; m_serverStopNotice = null; m_serverSaveNotice = null; m_deathNotice = null; m_loginNotice = null; m_logoutNotice = null; m_chatWebhookURL = null; m_chatChannelID = null; m_chatEnabled = null; m_chatType = null; m_commandWebhookURL = null; m_commandChannelID = null; m_pollInterval = null; m_discordAdmins = null; m_logErrors = null; m_botToken = null; } } [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(2)] public class ImageHud : MonoBehaviour { [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] [HarmonyPatch(typeof(Tutorial), "Awake")] private static class Tutorial_Awake_Patch { [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] [UsedImplicitly] private static void Postfix(Tutorial __instance) { if (!m_loaded) { GameObject val = Object.Instantiate<GameObject>(((Component)((Component)__instance).transform.Find("Tutorial_wnd")).gameObject, ((Component)__instance).transform.parent); ((Object)val).name = "DiscordImage"; val.AddComponent<ImageHud>(); Canvas val2 = val.AddComponent<Canvas>(); val2.renderMode = (RenderMode)0; val.SetActive(true); m_loaded = true; } } } private static bool m_loaded; public static ImageHud instance; public RectTransform m_rect; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(1)] public Image m_bkg = null; public TMP_Text m_topic; public TMP_Text m_text; public TMP_Text m_closedText; private readonly float m_fadeDuration = 0.5f; private bool m_fading = false; private Color m_currentColor = Color.clear; private Color m_targetColor = Color.clear; public void Awake() { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) instance = this; m_rect = ((Component)this).GetComponent<RectTransform>(); m_bkg = ((Component)((Component)this).transform.Find("bkg")).GetComponent<Image>(); m_topic = ((Component)((Component)this).transform.Find("Topic")).GetComponent<TMP_Text>(); m_text = ((Component)((Component)this).transform.Find("Text")).GetComponent<TMP_Text>(); m_closedText = ((Component)((Component)this).transform.Find("CloseText")).GetComponent<TMP_Text>(); ((Component)m_topic).gameObject.SetActive(false); ((Component)m_text).gameObject.SetActive(false); ((Component)m_closedText).gameObject.SetActive(false); m_bkg.preserveAspect = true; m_bkg.type = (Type)0; ((Graphic)m_bkg).color = Color.clear; } public void Update() { //IL_0015: 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_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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_00a3: Unknown result type (might be due to invalid IL or missing references) if (!m_fading) { return; } m_currentColor = Color.Lerp(m_currentColor, m_targetColor, Time.deltaTime / m_fadeDuration); ((Graphic)m_bkg).color = m_currentColor; if (Mathf.Abs(m_currentColor.a - m_targetColor.a) < 0.01f) { m_currentColor = m_targetColor; ((Graphic)m_bkg).color = m_targetColor; m_targetColor = Color.clear; if (m_currentColor == Color.clear) { m_fading = false; } } } public void OnDestroy() { instance = null; } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public void ShowInstant(Sprite image) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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) m_bkg.sprite = image; m_currentColor = Color.white; ((Graphic)m_bkg).color = Color.white; ((MonoBehaviour)this).Invoke("StartFadeOut", 0.5f); } private void StartFadeOut() { //IL_0002: 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) m_targetColor = Color.clear; m_fading = true; } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public void Show(Sprite image) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) m_bkg.sprite = image; m_targetColor = Color.white; m_fading = true; } public void Hide() { //IL_0002: 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) m_targetColor = Color.clear; m_fading = true; } } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] public static class DiscordCommands { [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class ZNet_OnNewConnection_Patch { [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] private static void Postfix(ZNetPeer peer) { peer.m_rpc.Register<ZPackage>("RPC_BotToClient", (Action<ZRpc, ZPackage>)RPC_BotToClient); } } [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] public class DiscordCommand { [Description("Action runs when Discord component receives a new command")] private readonly Action<string[]> m_action; [Description("Action runs when player receives package from RPC_BotToClient")] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] private readonly Action<ZPackage> m_reaction; [Description("If only discord admins are allowed to run command")] private readonly bool m_adminOnly; [Description("Register a new discord command")] public DiscordCommand(string command, string description, Action<string[]> action, [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] Action<ZPackage> reaction = null, bool adminOnly = false, bool isSecret = false, string emoji = "") { m_action = action; m_reaction = reaction; m_adminOnly = adminOnly; m_commands[command] = this; if (!isSecret) { CommandTooltip commandTooltip = new CommandTooltip(command, description, adminOnly, emoji); } } public bool IsAllowed(string discordUserName) { return !m_adminOnly || new DiscordBotPlugin.StringListConfig(DiscordBotPlugin.m_discordAdmins.Value).list.Contains(discordUserName); } public void Run(string[] args) { m_action(args); } public void Run(ZPackage pkg) { m_reaction?.Invoke(pkg); } } [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] public class CommandTooltip { public readonly string m_command; public readonly string m_description; public readonly bool m_adminOnly; public CommandTooltip(string command, string description, bool adminOnly, string emoji) { m_command = BuildCommandKey(command, emoji); m_description = description; m_adminOnly = adminOnly; m_tooltips.Add(this); } private static string BuildCommandKey(string command, string emoji) { string text = (string.IsNullOrEmpty(emoji) ? "" : (EmojiHelper.Emoji(emoji) + " ")); return text + "`" + command + "`"; } } public static readonly Dictionary<string, DiscordCommand> m_commands = new Dictionary<string, DiscordCommand>(); private static readonly List<CommandTooltip> m_tooltips = new List<CommandTooltip>(); public static void Setup() { DiscordCommand discordCommand = new DiscordCommand("!help", "List of commands", delegate { List<CommandTooltip> list = new List<CommandTooltip>(); List<CommandTooltip> list2 = new List<CommandTooltip>(); foreach (CommandTooltip tooltip in m_tooltips) { if (tooltip.m_adminOnly) { list.Add(tooltip); } else { list2.Add(tooltip); } } if (list.Count > 25) { int num9 = (int)Math.Ceiling((double)list.Count / 25.0); for (int i = 0; i < num9; i++) { Dictionary<string, string> tableData = list.Skip(i * 25).Take(25).ToDictionary([<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] (CommandTooltip command) => command.m_command, [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] (CommandTooltip command) => command.m_description); string title = ((num9 == 1) ? "List of admin commands" : $"List of admin commands (Part {i + 1} of {num9}"); Discord.instance.SendTableEmbed(DiscordBotPlugin.Webhook.Commands, title, tableData); } } else { Discord.instance.SendTableEmbed(DiscordBotPlugin.Webhook.Commands, "List of admin commands", list.ToDictionary([<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] (CommandTooltip command) => command.m_command, [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] (CommandTooltip command) => command.m_description)); } if (list2.Count > 25) { int num10 = (int)Math.Ceiling((double)list2.Count / 25.0); for (int j = 0; j < num10; j++) { Dictionary<string, string> tableData2 = list2.Skip(j * 25).Take(25).ToDictionary([<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] (CommandTooltip command) => command.m_command, [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] (CommandTooltip command) => command.m_description); string title2 = ((num10 == 1) ? "List of commands" : $"List of commands (Part {j + 1} of {num10}"); Discord.instance.SendTableEmbed(DiscordBotPlugin.Webhook.Commands, title2, tableData2); } } else { Discord.instance.SendTableEmbed(DiscordBotPlugin.Webhook.Commands, "List of commands", list2.ToDictionary([<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] (CommandTooltip command) => command.m_command, [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] (CommandTooltip command) => command.m_description)); } }, null, adminOnly: false, isSecret: false, "question"); DiscordCommand listAdmins = new DiscordCommand("!listadmins", "List of discord admins registered to plugin", delegate { StringBuilder stringBuilder13 = new StringBuilder(); foreach (string item3 in new DiscordBotPlugin.StringListConfig(DiscordBotPlugin.m_discordAdmins.Value).list) { stringBuilder13.Append("`" + item3 + "`\n"); } Discord.instance.SendEmbedMessage(DiscordBotPlugin.Webhook.Commands, "List of discord usernames who can use commands:", stringBuilder13.ToString()); }, null, adminOnly: false, isSecret: false, "warning"); DiscordCommand discordCommand2 = new DiscordCommand("!addadmin", "Adds discord username to admin list, to enable using commands, `username`", delegate(string[] args) { if (args.Length >= 2) { string item2 = args[1].Trim(); DiscordBotPlugin.StringListConfig stringListConfig2 = new DiscordBotPlugin.StringListConfig(DiscordBotPlugin.m_discordAdmins.Value) { list = { item2 } }; DiscordBotPlugin.m_discordAdmins.Value = stringListConfig2.ToString(); listAdmins.Run(new string[1] { "listadmins" }); } }, null, adminOnly: true, isSecret: false, "key"); DiscordCommand discordCommand3 = new DiscordCommand("!removeadmin", "Remove discord username from admin list, to disable using commands, `username`", delegate(string[] args) { string item = args[1].Trim(); DiscordBotPlugin.StringListConfig stringListConfig = new DiscordBotPlugin.StringListConfig(DiscordBotPlugin.m_discordAdmins.Value); stringListConfig.list.Remove(item); DiscordBotPlugin.m_discordAdmins.Value = stringListConfig.ToString(); listAdmins.Run(new string[1] { "listadmins" }); }, null, adminOnly: true, isSecret: false, "lock"); DiscordCommand discordCommand4 = new DiscordCommand("!listenv", "List of available environments", delegate { StringBuilder stringBuilder12 = new StringBuilder(); foreach (EnvSetup environment in EnvMan.instance.m_environments) { stringBuilder12.Append("`" + environment.m_name + "`\n"); } Discord.instance.SendEmbedMessage(DiscordBotPlugin.Webhook.Commands, "List of available environments:", stringBuilder12.ToString()); }, null, adminOnly: false, isSecret: false, "tornado"); DiscordCommand discordCommand5 = new DiscordCommand("!env", "Force environment on all players", delegate(string[] args) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown if (args.Length >= 2) { string text28 = args[1].Trim(); EnvSetup env = EnvMan.instance.GetEnv(text28); if (env != null) { ZPackage val21 = new ZPackage(); val21.Write("!env"); val21.Write(text28); foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { peer.m_rpc.Invoke("RPC_BotToClient", new object[1] { val21 }); } if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { EnvMan.instance.m_debugEnv = text28; } } else { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find environment: " + text28); } } }, delegate(ZPackage pkg) { string debugEnv = pkg.ReadString(); EnvMan.instance.m_debugEnv = debugEnv; }, adminOnly: true, isSecret: false, "sparkle"); DiscordCommand discordCommand6 = new DiscordCommand("!resetenv", "Reset environment on all players", delegate { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ZPackage val20 = new ZPackage(); val20.Write("!resetenv"); foreach (ZNetPeer peer2 in ZNet.instance.GetPeers()) { peer2.m_rpc.Invoke("RPC_BotToClient", new object[1] { val20 }); } if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { EnvMan.instance.m_debugEnv = ""; } }, delegate { EnvMan.instance.m_debugEnv = ""; }, adminOnly: true, isSecret: false, "sparkle"); DiscordCommand discordCommand7 = new DiscordCommand("!listplayers", "List of active players", delegate { //IL_001c: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0050: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (PlayerInfo player in ZNet.instance.m_players) { dictionary[player.m_name] = $"Position: `{player.m_position.x} {player.m_position.y} {player.m_position.z}`"; } Discord.instance.SendTableEmbed(DiscordBotPlugin.Webhook.Commands, "List of active players", dictionary); }, null, adminOnly: true, isSecret: false, "dragon"); DiscordCommand discordCommand8 = new DiscordCommand("!kick", "Kicks player from server, `playername`", delegate(string[] args) { if (args.Length >= 2) { string text27 = args[1].Trim(); ZNetPeer peerByPlayerName14 = ZNet.instance.GetPeerByPlayerName(text27); if (peerByPlayerName14 == null) { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find " + text27); } else { ZNet.instance.Disconnect(peerByPlayerName14); Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Kicked " + text27 + " from server !"); } } }, null, adminOnly: true, isSecret: false, "x"); DiscordCommand discordCommand9 = new DiscordCommand("!give", "Adds item directly into player inventory, `player name` `item name` `amount` `quality?` `variant?`", delegate(string[] args) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown if (args.Length >= 4) { string text25 = args[1].Trim(); string text26 = args[2].Trim(); int result16; int num6 = ((!int.TryParse(args[3].Trim(), out result16)) ? 1 : result16); int result17; int num7 = ((args.Length <= 4) ? 1 : ((!int.TryParse(args[4].Trim(), out result17)) ? 1 : result17)); int result18; int num8 = ((args.Length > 5) ? (int.TryParse(args[5].Trim(), out result18) ? result18 : 0) : 0); if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName() == text25) { GiveItem(text26, num6, num7, num8); } else { ZNetPeer peerByPlayerName13 = ZNet.instance.GetPeerByPlayerName(text25); if (peerByPlayerName13 != null) { ZPackage val19 = new ZPackage(); val19.Write("!give"); val19.Write(text26); val19.Write(num6); val19.Write(num7); val19.Write(num8); peerByPlayerName13.m_rpc.Invoke("RPC_BotToClient", new object[1] { val19 }); } else { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find " + text25); } } } }, delegate(ZPackage pkg) { string itemName = pkg.ReadString(); int amount = pkg.ReadInt(); int quality = pkg.ReadInt(); int variant = pkg.ReadInt(); GiveItem(itemName, amount, quality, variant); }, adminOnly: true, isSecret: false, "gift"); DiscordCommand discordCommand10 = new DiscordCommand("!teleportall", "Teleports all players to location, `x` `y` `z`", delegate(string[] args) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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) if (args.Length == 4) { if (float.TryParse(args[1].Trim(), out var result13) && float.TryParse(args[2].Trim(), out var result14) && float.TryParse(args[3].Trim(), out var result15)) { Vector3 val17 = default(Vector3); ((Vector3)(ref val17))..ctor(result13, result14, result15); ZPackage val18 = new ZPackage(); val18.Write("!teleport"); val18.Write("vector"); val18.Write(val17); foreach (ZNetPeer peer3 in ZNet.instance.GetPeers()) { peer3.m_rpc.Invoke("RPC_BotToClient", new object[1] { val18 }); } if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { ((Character)Player.m_localPlayer).TeleportTo(val17, Quaternion.identity, true); } } else { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Incorrect teleport all command format"); } } }, null, adminOnly: true, isSecret: false, "golf"); DiscordCommand discordCommand11 = new DiscordCommand("!teleport", "Teleport player to location, `player name` `bed` or `other player name` or `x` `y` `z`", delegate(string[] args) { //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Expected O, but got Unknown //IL_0241: Unknown result type (might be due to invalid IL or missing references) if (args.Length >= 5) { string text23 = args[1].Trim(); string text24 = args[2].Trim(); if (text24 == "bed") { if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName() == text23) { ((Character)Player.m_localPlayer).TeleportTo(Game.instance.GetPlayerProfile().GetCustomSpawnPoint(), Quaternion.identity, true); } else { ZNetPeer peerByPlayerName10 = ZNet.instance.GetPeerByPlayerName(text23); if (peerByPlayerName10 != null) { ZPackage val14 = new ZPackage(); val14.Write("!teleport"); val14.Write("bed"); peerByPlayerName10.m_rpc.Invoke("RPC_BotToClient", new object[1] { val14 }); } else { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find " + text23); } } } else { Vector3 val15 = default(Vector3); if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName() == text24) { val15 = ((Component)Player.m_localPlayer).transform.position; } else { ZNetPeer peerByPlayerName11 = ZNet.instance.GetPeerByPlayerName(text24); if (peerByPlayerName11 != null) { val15 = peerByPlayerName11.m_refPos; } else { if (!float.TryParse(args[2].Trim(), out var result10) || !float.TryParse(args[3].Trim(), out var result11) || !float.TryParse(args[4].Trim(), out var result12)) { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Incorrect teleport command format"); return; } ((Vector3)(ref val15))..ctor(result10, result11, result12); } } if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName() == text23) { ((Character)Player.m_localPlayer).TeleportTo(val15, Quaternion.identity, true); } else { ZNetPeer peerByPlayerName12 = ZNet.instance.GetPeerByPlayerName(text23); if (peerByPlayerName12 != null) { ZPackage val16 = new ZPackage(); val16.Write("!teleport"); val16.Write("vector"); val16.Write(val15); peerByPlayerName12.m_rpc.Invoke("RPC_BotToClient", new object[1] { val16 }); } else { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find " + text23); } } } } }, delegate(ZPackage pkg) { //IL_0034: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0054: 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_005b: Unknown result type (might be due to invalid IL or missing references) string text20 = pkg.ReadString(); string text21 = text20; string text22 = text21; if (!(text22 == "bed")) { if (text22 == "vector") { Vector3 val13 = pkg.ReadVector3(); ((Character)Player.m_localPlayer).TeleportTo(val13, Quaternion.identity, true); } } else { Vector3 customSpawnPoint = Game.instance.GetPlayerProfile().GetCustomSpawnPoint(); ((Character)Player.m_localPlayer).TeleportTo(customSpawnPoint, Quaternion.identity, true); } }, adminOnly: true, isSecret: false, "run"); DiscordCommand discordCommand12 = new DiscordCommand("!spawn", "spawns prefab at location, `prefab name` `level` `player name` or `x` `y` `z`", delegate(string[] args) { //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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_01a0: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) if (args.Length >= 4) { string text18 = args[1].Trim(); int result6; int num5 = ((!int.TryParse(args[2].Trim(), out result6)) ? 1 : result6); if (args.Length == 6) { if (!float.TryParse(args[3].Trim(), out var result7) || !float.TryParse(args[4].Trim(), out var result8) || !float.TryParse(args[5].Trim(), out var result9)) { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Incorrect spawn command format"); } else if (!ZoneSystem.instance.IsZoneLoaded(new Vector3(result7, result8, result9))) { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to spawn, location zone is not loaded!"); } else if (!Spawn(text18, num5, new Vector3(result7, result8, result9))) { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to spawn: " + text18); } } else { string text19 = args[3].Trim(); if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName() == text19) { if (!Spawn(text18, num5, ((Component)Player.m_localPlayer).transform.position)) { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to spawn: " + text18); } } else { ZNetPeer peerByPlayerName9 = ZNet.instance.GetPeerByPlayerName(text19); if (peerByPlayerName9 != null) { ZPackage val12 = new ZPackage(); val12.Write("!spawn"); val12.Write(text18); val12.Write(num5); peerByPlayerName9.m_rpc.Invoke("RPC_BotToClient", new object[1] { val12 }); } else { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find " + text19); } } } } }, delegate(ZPackage pkg) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) string prefabName = pkg.ReadString(); int level = pkg.ReadInt(); Spawn(prefabName, level, ((Component)Player.m_localPlayer).transform.position); }, adminOnly: true, isSecret: false, "exclamation"); DiscordCommand discordCommand13 = new DiscordCommand("!save", "Save player profiles and world", delegate { ZNet.instance.Save(true, true, true); }, null, adminOnly: true, isSecret: false, "save"); DiscordCommand discordCommand14 = new DiscordCommand("!message", "Broadcast message to all players which shows up center of screen", delegate(string[] args) { string text17 = string.Join(" ", args.Skip(1)); MessageHud.instance.MessageAll((MessageType)2, text17); }, null, adminOnly: true, isSecret: false, "smile"); DiscordCommand discordCommand15 = new DiscordCommand("!image", "Broadcast image to all players which takes over entire screen", delegate(string[] args) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown if (args.Length >= 2) { string text16 = args[1].Trim(); ZPackage val11 = new ZPackage(); val11.Write("!image"); val11.Write(text16); foreach (ZNetPeer peer4 in ZNet.instance.GetPeers()) { peer4.m_rpc.Invoke("RPC_BotToClient", new object[1] { val11 }); } if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { Discord.instance.GetImage(text16); } } }, delegate(ZPackage pkg) { string imageUrl = pkg.ReadString(); Discord.instance.GetImage(imageUrl); }, adminOnly: true, isSecret: false, "paint"); DiscordCommand discordCommand16 = new DiscordCommand("!sleep", "Forced everyone to sleep", delegate { if (!EnvMan.instance.IsTimeSkipping() && (EnvMan.IsAfternoon() || EnvMan.IsNight()) && !(ZNet.instance.GetTimeSeconds() - Game.instance.m_lastSleepTime < 10.0)) { EnvMan.instance.SkipToMorning(); Game.instance.m_sleeping = true; ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "SleepStart", Array.Empty<object>()); } }, null, adminOnly: true, isSecret: false, "moon"); DiscordCommand discordCommand17 = new DiscordCommand("!listkeys", "List of global keys", delegate { StringBuilder stringBuilder11 = new StringBuilder(); foreach (object value in Enum.GetValues(typeof(GlobalKeys))) { stringBuilder11.Append($"`{value}`\n"); } Discord.instance.SendEmbedMessage(DiscordBotPlugin.Webhook.Commands, "Global keys:", stringBuilder11.ToString()); }, null, adminOnly: false, isSecret: false, "fox"); DiscordCommand discordCommand18 = new DiscordCommand("!keys", "List of current global keys", delegate { StringBuilder stringBuilder10 = new StringBuilder(); foreach (string globalKey in ZoneSystem.instance.GetGlobalKeys()) { stringBuilder10.Append("`" + globalKey + "`\n"); } Discord.instance.SendEmbedMessage(DiscordBotPlugin.Webhook.Commands, "Active keys:", stringBuilder10.ToString()); }, null, adminOnly: false, isSecret: false, "game"); DiscordCommand discordCommand19 = new DiscordCommand("!setkey", "Set global key", delegate(string[] args) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (args.Length >= 2) { string text15 = args[1].Trim(); if (!Enum.TryParse<GlobalKeys>(text15, ignoreCase: true, out GlobalKeys result5)) { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find global key: " + text15); } else { ZoneSystem.instance.SetGlobalKey(result5); } } }, null, adminOnly: true, isSecret: false, "unicorn"); DiscordCommand discordCommand20 = new DiscordCommand("!removekey", "Remove global key", delegate(string[] args) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (args.Length >= 2) { string text14 = args[1].Trim(); if (!Enum.TryParse<GlobalKeys>(text14, ignoreCase: true, out GlobalKeys result4)) { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find global key: " + text14); } else { ZoneSystem.instance.RemoveGlobalKey(result4); } } }, null, adminOnly: true, isSecret: false, "pencil"); DiscordCommand discordCommand21 = new DiscordCommand("!listprefabs", "List of prefabs available to spawn, `filter`", delegate(string[] args) { string filter = ((args.Length > 1) ? args[1].Trim().ToLower() : ""); StringBuilder stringBuilder9 = new StringBuilder(); foreach (GameObject item4 in ZNetScene.instance.m_prefabs.Where([<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] (GameObject x) => ((Object)x).name.ToLower().Contains(filter))) { stringBuilder9.Append("`" + ((Object)item4).name + "`\n"); } Discord.instance.SendEmbedMessage(DiscordBotPlugin.Webhook.Commands, "Prefab Names:", stringBuilder9.ToString()); }, null, adminOnly: true, isSecret: false, "fire"); DiscordCommand discordCommand22 = new DiscordCommand("!listevents", "List of available event names", delegate { StringBuilder stringBuilder8 = new StringBuilder(); foreach (RandomEvent event2 in RandEventSystem.instance.m_events) { stringBuilder8.Append("`" + event2.m_name + "`\n"); } Discord.instance.SendEmbedMessage(DiscordBotPlugin.Webhook.Commands, "Available events:", stringBuilder8.ToString()); }, null, adminOnly: true, isSecret: false, "moon"); DiscordCommand discordCommand23 = new DiscordCommand("!event", "Starts an event on a player, `event name` `player name`", delegate(string[] args) { //IL_0054: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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 (args.Length >= 3) { string text12 = args[1].Trim(); string text13 = args[2].Trim(); Vector3 val10; if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName() == text13) { val10 = ((Component)Player.m_localPlayer).transform.position; } else { ZNetPeer peerByPlayerName8 = ZNet.instance.GetPeerByPlayerName(text13); if (peerByPlayerName8 == null) { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find " + text13); return; } val10 = peerByPlayerName8.m_refPos; } RandomEvent @event = RandEventSystem.instance.GetEvent(text12); if (@event == null) { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find event: " + text12); } else { RandEventSystem.instance.SetRandomEvent(@event, val10); } } }, null, adminOnly: true, isSecret: false, "star"); DiscordCommand discordCommand24 = new DiscordCommand("!liststatus", "List of available status effects", delegate { StringBuilder stringBuilder7 = new StringBuilder(); foreach (StatusEffect statusEffect3 in ObjectDB.instance.m_StatusEffects) { stringBuilder7.Append("`" + ((Object)statusEffect3).name + "`\n"); } Discord.instance.SendEmbedMessage(DiscordBotPlugin.Webhook.Commands, "Available status effects:", stringBuilder7.ToString()); }, null, adminOnly: false, isSecret: false, "rocket"); DiscordCommand discordCommand25 = new DiscordCommand("!addstatus", "Add status effect on player, `player name` `status effect` `duration`", delegate(string[] args) { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Expected O, but got Unknown if (args.Length == 4) { string text10 = args[1].Trim(); string text11 = args[2].Trim(); float result3; float num4 = (float.TryParse(args[3].Trim(), out result3) ? result3 : 0f); StatusEffect statusEffect2 = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode(text11)); if (statusEffect2 == null) { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find status effect: " + text11); } else if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName() == text10) { StatusEffect val8 = ((Character)Player.m_localPlayer).GetSEMan().AddStatusEffect(statusEffect2, false, 0, 0f); if (num4 > 0f) { val8.m_ttl = num4; } } else { ZNetPeer peerByPlayerName7 = ZNet.instance.GetPeerByPlayerName(text10); if (peerByPlayerName7 != null) { ZPackage val9 = new ZPackage(); val9.Write("!addstatus"); val9.Write(text11); val9.Write((double)num4); peerByPlayerName7.m_rpc.Invoke("RPC_BotToClient", new object[1] { val9 }); } else { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find " + text10); } } } }, delegate(ZPackage pkg) { string text9 = pkg.ReadString(); float num3 = (float)pkg.ReadDouble(); StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode(text9)); if (statusEffect != null) { StatusEffect val7 = ((Character)Player.m_localPlayer).GetSEMan().AddStatusEffect(statusEffect, false, 0, 0f); if (num3 > 0f) { val7.m_ttl = num3; } } }, adminOnly: true, isSecret: false, "pizza"); DiscordCommand discordCommand26 = new DiscordCommand("!heal", "Heals to full health & stamina, `player name`", delegate(string[] args) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown if (args.Length >= 2) { string text8 = args[1].Trim(); if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName() == text8) { ((Character)Player.m_localPlayer).Heal(((Character)Player.m_localPlayer).GetMaxHealth(), true); ((Character)Player.m_localPlayer).AddStamina(((Character)Player.m_localPlayer).GetMaxStamina()); ((Character)Player.m_localPlayer).AddEitr(((Character)Player.m_localPlayer).GetMaxEitr()); } else { ZNetPeer peerByPlayerName6 = ZNet.instance.GetPeerByPlayerName(text8); if (peerByPlayerName6 != null) { ZPackage val6 = new ZPackage(); val6.Write("!heal"); peerByPlayerName6.m_rpc.Invoke("RPC_BotToClient", new object[1] { val6 }); } else { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find player: " + text8); } } } }, delegate { ((Character)Player.m_localPlayer).Heal(((Character)Player.m_localPlayer).GetMaxHealth(), true); ((Character)Player.m_localPlayer).AddStamina(((Character)Player.m_localPlayer).GetMaxStamina()); ((Character)Player.m_localPlayer).AddEitr(((Character)Player.m_localPlayer).GetMaxEitr()); }, adminOnly: true, isSecret: false, "heart"); DiscordCommand discordCommand27 = new DiscordCommand("!die", "Kills player, `player name`", delegate(string[] args) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_0064: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown if (args.Length >= 2) { string text7 = args[1].Trim(); if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName() == text7) { ((Character)Player.m_localPlayer).Damage(new HitData { m_damage = { m_damage = 99999f }, m_hitType = (HitType)14 }); } else { ZNetPeer peerByPlayerName5 = ZNet.instance.GetPeerByPlayerName(text7); if (peerByPlayerName5 != null) { ZPackage val5 = new ZPackage(); val5.Write("!die"); peerByPlayerName5.m_rpc.Invoke("RPC_BotToClient", new object[1] { val5 }); } else { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find player: " + text7); } } } }, delegate { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown ((Character)Player.m_localPlayer).Damage(new HitData { m_damage = { m_damage = 99999f }, m_hitType = (HitType)14 }); }, adminOnly: true, isSecret: false, "tiger"); DiscordCommand discordCommand28 = new DiscordCommand("!listskills", "List of available skills", delegate { StringBuilder stringBuilder6 = new StringBuilder(); foreach (object value2 in Enum.GetValues(typeof(SkillType))) { stringBuilder6.Append(Formatting.Format(value2.ToString(), Formatting.TextFormat.InlineCode) + "\n"); } Discord.instance.SendEmbedMessage(DiscordBotPlugin.Webhook.Commands, "Available skill types:", stringBuilder6.ToString(), ZNet.instance.GetWorldName()); }, null, adminOnly: false, isSecret: false, "pray"); DiscordCommand discordCommand29 = new DiscordCommand("!raiseskill", "Raises skill level, `player name` `stkill type` `amount`", delegate(string[] args) { //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown if (args.Length >= 3) { string text5 = args[1].Trim(); string text6 = args[2].Trim(); float result; float num2 = (float.TryParse(args[3].Trim(), out result) ? result : 1f); if (!Enum.TryParse<SkillType>(text6, out SkillType _)) { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find skill type: " + text6); } else if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName() == text5) { ((Character)Player.m_localPlayer).GetSkills().CheatRaiseSkill(text6, num2, true); } else { ZNetPeer peerByPlayerName4 = ZNet.instance.GetPeerByPlayerName(text5); if (peerByPlayerName4 != null) { ZPackage val4 = new ZPackage(); val4.Write("!raiseskill"); val4.Write(text6); val4.Write((double)num2); peerByPlayerName4.m_rpc.Invoke("RPC_BotToClient", new object[1] { val4 }); } else { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find player: " + text5); } } } }, delegate(ZPackage pkg) { string text4 = pkg.ReadString(); float num = (float)pkg.ReadDouble(); ((Character)Player.m_localPlayer).GetSkills().CheatRaiseSkill(text4, num, true); }, adminOnly: true, isSecret: false, "muscle"); DiscordCommand discordCommand30 = new DiscordCommand("!pos", "Player position, `player name`", delegate(string[] args) { //IL_0047: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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) if (args.Length >= 2) { string text3 = args[1].Trim(); Vector3 val3; if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName() == text3) { val3 = ((Component)Player.m_localPlayer).transform.position; } else { ZNetPeer peerByPlayerName3 = ZNet.instance.GetPeerByPlayerName(text3); if (peerByPlayerName3 == null) { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find player: " + text3); return; } val3 = peerByPlayerName3.m_refPos; } Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", $"{text3} position: {val3.x},{val3.y},{val3.z}"); } }, null, adminOnly: true, isSecret: false, "rose"); DiscordCommand discordCommand31 = new DiscordCommand("!stats", "Player stats, player must be online, `player name`", delegate(string[] args) { //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (args.Length >= 2) { string text2 = args[1].Trim(); if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName() == text2) { PlayerProfile playerProfile2 = Game.instance.GetPlayerProfile(); StringBuilder stringBuilder5 = new StringBuilder(); foreach (KeyValuePair<PlayerStatType, float> stat in playerProfile2.m_playerStats.m_stats) { if (stat.Value > 0f) { PlayerStatType key2 = stat.Key; stringBuilder5.Append(Formatting.Format(((object)(PlayerStatType)(ref key2)).ToString(), Formatting.TextFormat.Bold) + ": " + Formatting.Format(stat.Value.ToString("0.0"), Formatting.TextFormat.InlineCode) + "\n"); } } Discord.instance.SendEmbedMessage(DiscordBotPlugin.Webhook.Commands, text2 + " Stats", stringBuilder5.ToString()); } else { ZNetPeer peerByPlayerName2 = ZNet.instance.GetPeerByPlayerName(text2); if (peerByPlayerName2 != null) { ZPackage val2 = new ZPackage(); val2.Write("!stats"); peerByPlayerName2.m_rpc.Invoke("RPC_BotToClient", new object[1] { val2 }); } else { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find player: " + text2); } } } }, delegate { //IL_0047: 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) PlayerProfile playerProfile = Game.instance.GetPlayerProfile(); StringBuilder stringBuilder4 = new StringBuilder(); foreach (KeyValuePair<PlayerStatType, float> stat2 in playerProfile.m_playerStats.m_stats) { if (stat2.Value > 0f) { PlayerStatType key = stat2.Key; stringBuilder4.Append(Formatting.Format(((object)(PlayerStatType)(ref key)).ToString(), Formatting.TextFormat.Bold) + ": " + Formatting.Format(stat2.Value.ToString("0.0"), Formatting.TextFormat.InlineCode) + "\n"); } } Discord.instance.SendEmbedMessage(DiscordBotPlugin.Webhook.Commands, playerProfile.m_playerName + " Stats", stringBuilder4.ToString()); }, adminOnly: false, isSecret: false, "wine"); DiscordCommand discordCommand32 = new DiscordCommand("!mods", "List of plugin installed, `player name?`", delegate(string[] args) { //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected O, but got Unknown if (args.Length > 1) { string text = args[1].Trim(); if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerName() == text) { StringBuilder stringBuilder2 = new StringBuilder(); foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos) { stringBuilder2.Append($"{pluginInfo.Value.Metadata.Name}-{pluginInfo.Value.Metadata.Version}\n"); } Discord.instance.SendEmbedMessage(DiscordBotPlugin.Webhook.Commands, text + " installed plugins", stringBuilder2.ToString()); } else { ZNetPeer peerByPlayerName = ZNet.instance.GetPeerByPlayerName(text); if (peerByPlayerName != null) { ZPackage val = new ZPackage(); val.Write("!mods"); peerByPlayerName.m_rpc.Invoke("RPC_BotToClient", new object[1] { val }); } else { Discord.instance.SendMessage(DiscordBotPlugin.Webhook.Commands, "", "Failed to find player: " + text); } } } else { StringBuilder stringBuilder3 = new StringBuilder(); foreach (KeyValuePair<string, PluginInfo> pluginInfo2 in Chainloader.PluginInfos) { stringBuilder3.Append($"{pluginInfo2.Value.Metadata.Name}-{pluginInfo2.Value.Metadata.Version}\n"); } Discord.instance.SendEmbedMessage(DiscordBotPlugin.Webhook.Commands, "Server installed plugins", stringBuilder3.ToString()); } }, delegate { StringBuilder stringBuilder = new StringBuilder(); foreach (KeyValuePair<string, PluginInfo> pluginInfo3 in Chainloader.PluginInfos) { stringBuilder.Append($"{pluginInfo3.Value.Metadata.Name}-{pluginInfo3.Value.Metadata.Version}\n"); } Discord.instance.SendEmbedMessage(DiscordBotPlugin.Webhook.Commands, Game.instance.GetPlayerProfile().m_playerName + " installed plugins", stringBuilder.ToString()); }, adminOnly: false, isSecret: false, "guitar"); } public static bool Spawn(string prefabName, int level, Vector3 pos) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNetScene.instance)) { return false; } GameObject prefab = ZNetScene.instance.GetPrefab(prefabName); if (prefab == null) { return false; } Vector3 val = Random.insideUnitSphere * 5f; val.y = 0f; Vector3 val2 = val; Vector3 val3 = pos + val2; GameObject val4 = Object.Instantiate<GameObject>(prefab, val3, Quaternion.identity); Character val5 = default(Character); if (val4.TryGetComponent<Character>(ref val5)) { val5.SetLevel(level); } return true; } public static bool GiveItem(string itemName, int amount, int quality, int variant) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || !Object.op_Implicit((Object)(object)ObjectDB.instance)) { return false; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemName); ItemDrop val = default(ItemDrop); if (itemPrefab == null || !itemPrefab.TryGetComponent<ItemDrop>(ref val)) { return false; } ItemData val2 = val.m_itemData.Clone(); val2.m_dropPrefab = itemPrefab; val2.m_stack = amount; val2.m_quality = quality; val2.m_variant = variant; ((Humanoid)Player.m_localPlayer).GetInventory().AddItem(val2); return true; } public static void RPC_BotToClient(ZRpc rpc, ZPackage pkg) { string key = pkg.ReadString(); if (m_commands.TryGetValue(key, out var value)) { value.Run(pkg); } } } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] public class Discord : MonoBehaviour { [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] [HarmonyPatch(typeof(ZNet), "Awake")] private static class ZNet_Awake_Patch { [UsedImplicitly] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] private static void Postfix(ZNet __instance) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) ((Component)DiscordBotPlugin.m_instance).gameObject.AddComponent<Discord>(); if (__instance.IsServer() && DiscordBotPlugin.m_serverStartNotice.Value != 0) { instance.SendStatus(DiscordBotPlugin.Webhook.Notifications, "$msg_server_start", __instance.GetWorldName(), "$status_launch", new Color(0.4f, 0.98f, 0.24f)); } } } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class ZNet_OnNewConnection_Patch { [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] private static void Postfix(ZNetPeer peer) { peer.m_rpc.Register<string, string>("RPC_ClientBotMessage", (Action<ZRpc, string, string>)RPC_ClientBotMessage); } } [Serializable] [Description("Discord webhook json object")] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(2)] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] public class DiscordWebhookData { public string content; public bool tts; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public Embed[] embeds; public string username; public string avatar_url; [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public DiscordWebhookData(string username, string content) { if (!string.IsNullOrEmpty(username)) { this.username = username; } this.content = Localization.instance.Localize(content); } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public DiscordWebhookData(string username, params Embed[] embeds) { if (!string.IsNullOrEmpty(username)) { this.username = username; } this.embeds = embeds; } } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] public enum DiscordMessageFlags { CrossPosted = 0, Is_CrossPost = 1, Suppress_Embeds = 2, Source_Message_Deleted = 3, Urgent = 4, Has_Thread = 5, Ephemeral = 6, Loading = 7, Failed_To_Mention_Some_Roles_In_Thread = 8, Suppress_Notifications = 12, Is_Voice_Message = 13, Has_Snapshot = 14, Is_Components_V2 = 15 } [Serializable] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(2)] public class DiscordWebhookComponents { public string username; public string avatar_url; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public EmbedComponent[] components; public int flags = 15; [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public DiscordWebhookComponents(string username, params EmbedComponent[] components) { if (!string.IsNullOrEmpty(username)) { this.username = username; } this.components = components; } } [Serializable] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] public class EmbedComponent { public int type; public int id; } [Serializable] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] public class ActionRow : EmbedComponent { [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public EmbedComponent[] components; public ActionRow() { type = 1; } } [Serializable] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(2)] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] public class Button : EmbedComponent { [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] public enum ButtonStyle { Primary = 1, Secondary, Success, Danger, Link, Premium } public int style; public string label; public string custom_id; public string url; public bool disabled; [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public Button(ButtonStyle style, string label) { this.label = label; this.style = (int)style; type = 2; } } [Serializable] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(2)] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] public class StringSelect : EmbedComponent { public string custom_id; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public EmbedOption[] options; public string placeholder; public int min_values; public int max_values; public bool disabled; public StringSelect() { type = 3; } } [Serializable] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(2)] public class TextInput : EmbedComponent { [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] public enum TextInputStyle { Short = 1, Paragraph } public string custom_id; public int style; public string label; public int min_length; public int max_length; public bool required; public string value; public string placeholder; public TextInput(TextInputStyle style) { this.style = (int)style; type = 4; } } [Serializable] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(2)] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] public class UserSelect : EmbedComponent { public string custom_id; public string placeholder; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public object[] default_values; public int min_values; public int max_values; public bool disabled; public UserSelect() { type = 5; } } [Serializable] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] public class Section : EmbedComponent { [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public EmbedComponent[] components; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(2)] public EmbedComponent accessory; [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public Section(params EmbedComponent[] components) { this.components = components; type = 9; } public Section() { type = 9; } } [Serializable] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] public class TextDisplay : EmbedComponent { [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(2)] public string content; [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public TextDisplay(string content) { this.content = content; type = 10; } } [Serializable] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(2)] public class EmbedOption { public string label; public string value; public string description; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1, 1 })] public Dictionary<string, string> emoji; } [Serializable] [Description("Discord embed json object")] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(2)] public class Embed { public string title; public string description; public string url; public string timestamp; public int? color; public Footer footer; public EmbedImage image; public EmbedImage thumbnail; public EmbedVideo video; public EmbedProvider provider; public EmbedAuthor author; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public EmbedField[] fields; public Embed() { timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public Embed(string title, string description) { this.title = Localization.instance.Localize(title); this.description = Localization.instance.Localize(description); timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public Embed(string title, params EmbedField[] fields) { this.title = title; this.fields = fields; timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public Embed(string description) { this.description = Localization.instance.Localize(description); timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public Embed(string title, List<EmbedField> fields) : this(title, fields.ToArray()) { } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public void AddImage(string imageUrl) { if (!string.IsNullOrEmpty(imageUrl)) { image = new EmbedImage(imageUrl); } } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public void AddThumbnail(string thumbnailUrl) { if (!string.IsNullOrEmpty(thumbnailUrl)) { thumbnail = new EmbedImage(thumbnailUrl); } } public void SetColor(Color Color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) color = ColorToInt(Color); } } [Serializable] [Description("Discord image json object")] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] public class EmbedImage { [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(2)] public string url; public int width; public int height; [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public EmbedImage(string url, int width = 256, int height = 256) { this.url = url; this.width = width; this.height = height; } } [Serializable] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(0)] public class EmbedVideo { [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(2)] public string url; public int height; public int width; } [Serializable] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(2)] public class EmbedProvider { public string name; public string url; } [Serializable] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(2)] [Description("Discord author json object")] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] public class EmbedAuthor { public string name; public string icon_url; } [Serializable] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(2)] [Description("Discord embed json object")] public class EmbedField { public string name; public string value; public bool inline; [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public EmbedField(string name, string value, bool inline = true) { this.name = Localization.instance.Localize(name); this.value = Localization.instance.Localize(value); this.inline = inline; } } [Serializable] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] [Description("Discord footer json object")] public class Footer { [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(2)] public string text; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(2)] public string icon_url; public Footer(string text) { this.text = Localization.instance.Localize(text); } public void AddIcon(string url) { if (!string.IsNullOrEmpty(url)) { icon_url = url; } } } [Serializable] [Description("Discord message json object")] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(2)] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] public class Message { public string id; public string channel_id; public User author; public string content; public string timestamp; public string edited_timestamp; public bool tts; public bool mention_everyone; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public User[] mentions; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public User[] mention_roles; public int type; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public Embed[] embeds; } [Serializable] [Description("Discord user json object")] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(2)] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] public class User { public string id; public string username; public string global_name; public string discriminator; public bool bot; public string avatar; [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public string GetDisplayName() { return ((!string.IsNullOrEmpty(global_name)) ? global_name : username) ?? string.Empty; } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public string GetFullUsername() { return (!string.IsNullOrEmpty(discriminator) && discriminator != "0") ? (username + "#" + discriminator) : (username ?? string.Empty); } } public static Discord instance; private string m_lastMessageID = ""; private string m_lastCommandID = ""; private bool m_isPollingChatter; private bool m_isPollingCommands; private bool m_isDownloadingImage; private bool m_isDownloadingSound; private DateTime m_timeLoaded; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] [method: <0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] [field: <0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public event Action<Message> OnMessageReceived; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] [method: <0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] [field: <0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public event Action<Message> OnCommandReceived; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] [method: <0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] [field: <0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public event Action<Sprite> OnImageDownloaded; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] [method: <0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] [field: <0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public event Action<AudioClip> OnAudioDownloaded; [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] [method: <0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] [field: <0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(new byte[] { 2, 1 })] public event Action<string> OnError; public void Awake() { instance = this; m_timeLoaded = DateTime.UtcNow; if (ZNet.m_isServer) { OnMessageReceived += HandleChatMessage; OnCommandReceived += HandleCommands; OnImageDownloaded += HandleImage; OnError += HandleError; } } private void Start() { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.m_isServer) { return; } if (string.IsNullOrEmpty(DiscordBotPlugin.m_botToken.Value)) { DiscordBotPlugin.DiscordBotLogger.LogWarning((object)"Bot token not set"); return; } if (!string.IsNullOrEmpty(DiscordBotPlugin.m_chatChannelID.Value) && DiscordBotPlugin.m_chatEnabled.Value == DiscordBotPlugin.Toggle.On) { StartPollingChatter(); } if (!string.IsNullOrEmpty(DiscordBotPlugin.m_commandChannelID.Value)) { StartPollingCommands(); } SendMessage(DiscordBotPlugin.Webhook.Commands, ZNet.instance.GetWorldName(), EmojiHelper.Emoji("question") + " type `!help` to find list of available commands"); } private void OnDestroy() { StopPolling(); } private static void HandleError(string message) { if (DiscordBotPlugin.m_logErrors.Value != 0) { DiscordBotPlugin.DiscordBotLogger.LogWarning((object)message); } } private void HandleChatMessage(Message message) { BroadcastMessage(message.author?.GetDisplayName() ?? "", message?.content ?? ""); if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { DisplayChatMessage(message?.author?.GetDisplayName() ?? "", message?.content ?? ""); } } private void HandleCommands(Message message) { if (message.content != null) { string[] array = message.content.Split(new char[1] { ' ' }); string text = array[0].Trim(); if (!DiscordCommands.m_commands.TryGetValue(text, out var value)) { SendMessage(DiscordBotPlugin.Webhook.Commands, ZNet.instance.GetWorldName(), "Failed to find command: " + text); } else if (!value.IsAllowed(message.author?.GetFullUsername() ?? "")) { SendMessage(DiscordBotPlugin.Webhook.Commands, ZNet.instance.GetWorldName(), message.author?.GetFullUsername() + " not allowed to use command: " + text); } else { value.Run(array); } } } private static void HandleImage(Sprite sprite) { if (ImageHud.instance != null) { ImageHud.instance.Show(sprite); } } public void GetImage(string imageUrl) { if (!m_isDownloadingImage) { m_isDownloadingImage = true; ((MonoBehaviour)this).StartCoroutine(DownloadImage(imageUrl)); } } private IEnumerator DownloadImage(string imageUrl) { UnityWebRequest request = UnityWebRequestTexture.GetTexture(imageUrl); try { yield return request.SendWebRequest(); if ((int)request.result != 1) { string message = "Failed to download image from " + imageUrl + ": " + request.error; this.OnError?.Invoke(message); } else { Texture2D texture = DownloadHandlerTexture.GetContent(request); Sprite sprite = Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f)); this.OnImageDownloaded?.Invoke(sprite); } m_isDownloadingImage = false; } finally { ((IDisposable)request)?.Dispose(); } } public void GetSound(string url, AudioType type) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (!m_isDownloadingSound) { m_isDownloadingSound = true; ((MonoBehaviour)this).StartCoroutine(DownloadSound(url, type)); } } private IEnumerator DownloadSound(string url, AudioType type) { //IL_0015: 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) UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(url, type); try { ((DownloadHandlerAudioClip)request.downloadHandler).streamAudio = true; yield return request.SendWebRequest(); if ((int)request.result != 1) { this.OnError?.Invoke("Failed to download audio: " + request.error); } else { AudioClip clip = DownloadHandlerAudioClip.GetContent(request); this.OnAudioDownloaded?.Invoke(clip); } m_isDownloadingSound = false; } finally { ((IDisposable)request)?.Dispose(); } } public void BroadcastMessage(string username, string message) { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.m_isServer) { return; } foreach (ZNetPeer peer in ZNet.instance.GetPeers()) { peer.m_rpc.Invoke("RPC_ClientBotMessage", new object[2] { username, message }); } } public static void RPC_ClientBotMessage(ZRpc rpc, string username, string message) { DisplayChatMessage(username, message); } private static void DisplayChatMessage(string userName, string message) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) string text = "<color=#" + ColorUtility.ToHtmlStringRGB(new Color(0f, 0.5f, 0.5f, 1f)) + ">[Discord]</color><color=orange>" + userName + "</color>: " + message; ((Terminal)Chat.instance).AddString(text); } public void SendComponentMessage(DiscordBotPlugin.Webhook webhook, string username = "", params EmbedComponent[] components) { DiscordWebhookComponents data = new DiscordWebhookComponents(username, components); ((MonoBehaviour)this).StartCoroutine(SendLayoutMessage(data, DiscordBotPlugin.GetWebhookURL(webhook))); } public void SendMessage(DiscordBotPlugin.Webhook webhook, string username = "", string message = "") { DiscordWebhookData data = new DiscordWebhookData(username, message); ((MonoBehaviour)this).StartCoroutine(SendWebhookMessage(data, DiscordBotPlugin.GetWebhookURL(webhook))); } public void SendEmbedMessage(DiscordBotPlugin.Webhook webhook, string title, string content, string username = "", string thumbnail = "") { Embed embed = new Embed(title, content); embed.AddThumbnail(thumbnail); DiscordWebhookData data = new DiscordWebhookData(username, embed); ((MonoBehaviour)this).StartCoroutine(SendWebhookMessage(data, DiscordBotPlugin.GetWebhookURL(webhook))); } public void SendTableEmbed(DiscordBotPlugin.Webhook webhook, string title, Dictionary<string, string> tableData, string username = "", string thumbnail = "") { if (tableData.Count <= 0) { this.OnError?.Invoke("Table data is empty"); } List<EmbedField> list = new List<EmbedField>(); foreach (KeyValuePair<string, string> tableDatum in tableData) { list.Add(new EmbedField(tableDatum.Key, tableDatum.Value)); } Embed embed = new Embed(title, list); embed.AddThumbnail(thumbnail); DiscordWebhookData data = new DiscordWebhookData(username, embed); ((MonoBehaviour)this).StartCoroutine(SendWebhookMessage(data, DiscordBotPlugin.GetWebhookURL(webhook))); } public void SendStatus(DiscordBotPlugin.Webhook webhook, string content, string worldName, string status, Color color, string username = "", string thumbnail = "") { //IL_0009: Unknown result type (might be due to invalid IL or missing references) Embed embed = new Embed(content); embed.SetColor(color); List<EmbedField> list = new List<EmbedField>(); list.Add(new EmbedField("$label_worldname", worldName)); list.Add(new EmbedField("$label_status", status)); embed.fields = list.ToArray(); embed.AddThumbnail(thumbnail); DiscordWebhookData data = new DiscordWebhookData(username, embed); ((MonoBehaviour)this).StartCoroutine(SendWebhookMessage(data, DiscordBotPlugin.GetWebhookURL(webhook))); } private IEnumerator SendWebhookMessage(DiscordWebhookData data, string webhookURL) { if (string.IsNullOrEmpty(webhookURL)) { this.OnError?.Invoke("Webhook URL is not set!"); yield break; } string jsonData = JsonConvert.SerializeObject((object)data); byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonData); UnityWebRequest request = new UnityWebRequest(webhookURL, "POST"); try { request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw); request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); yield return request.SendWebRequest(); if ((int)request.result != 1) { string error = "Failed to send message: " + request.error + " - " + request.downloadHandler.text; this.OnError?.Invoke(error); } } finally { ((IDisposable)request)?.Dispose(); } } private IEnumerator SendLayoutMessage(DiscordWebhookComponents data, string webhookURL) { if (string.IsNullOrEmpty(webhookURL)) { this.OnError?.Invoke("Webhook URL is not set!"); yield break; } string jsonData = JsonConvert.SerializeObject((object)data); byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonData); UnityWebRequest request = new UnityWebRequest(webhookURL + "?with_components=true", "POST"); try { request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw); request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); yield return request.SendWebRequest(); if ((int)request.result != 1) { string error = "Failed to send message: " + request.error + " - " + request.downloadHandler.text; this.OnError?.Invoke(error); this.OnError?.Invoke(jsonData); } } finally { ((IDisposable)request)?.Dispose(); } } public void StartPollingChatter() { if (!m_isPollingChatter && !string.IsNullOrEmpty(DiscordBotPlugin.m_botToken.Value) && !string.IsNullOrEmpty(DiscordBotPlugin.m_chatChannelID.Value)) { m_isPollingChatter = true; ((MonoBehaviour)this).StartCoroutine(PollForMessages()); } } public void StartPollingCommands() { if (!m_isPollingCommands && !string.IsNullOrEmpty(DiscordBotPlugin.m_botToken.Value) && !string.IsNullOrEmpty(DiscordBotPlugin.m_commandChannelID.Value)) { m_isPollingCommands = true; ((MonoBehaviour)this).StartCoroutine(PollForCommands()); } } public void StopPolling() { m_isPollingChatter = false; m_isPollingCommands = false; } private IEnumerator PollForMessages() { while (m_isPollingChatter) { yield return ((MonoBehaviour)this).StartCoroutine(GetChannelMessages()); yield return (object)new WaitForSeconds((float)DiscordBotPlugin.m_pollInterval.Value); } } private IEnumerator PollForCommands() { while (m_isPollingCommands) { yield return ((MonoBehaviour)this).StartCoroutine(GetChannelCommands()); yield return (object)new WaitForSeconds((float)DiscordBotPlugin.m_pollInterval.Value); } } private IEnumerator GetChannelCommands() { string url = "https://discord.com/api/v10/channels/" + DiscordBotPlugin.GetChannelID(DiscordBotPlugin.Channel.Commands) + "/messages?limit=1"; UnityWebRequest request = UnityWebRequest.Get(url); try { request.SetRequestHeader("Authorization", "Bot " + DiscordBotPlugin.m_botToken.Value); request.SetRequestHeader("Content-Type", "application/json"); yield return request.SendWebRequest(); if ((int)request.result == 1) { try { Message[] messages = JsonConvert.DeserializeObject<Message[]>(request.downloadHandler.text); if (messages != null && messages.Length > 0) { Message message = messages[0]; if (!(message.author?.bot ?? true)) { DateTime timeStamp = DateTime.Parse(message.timestamp).ToUniversalTime(); if (!(m_timeLoaded > timeStamp) && message.id != null && !(message.id == m_lastCommandID)) { m_lastCommandID = message.id; this.OnCommandReceived?.Invoke(message); } } } yield break; } catch (Exception e) { this.OnError?.Invoke("Failed to parse message: " + e.Message); yield break; } } this.OnError?.Invoke("Failed to get message: " + request.error); } finally { ((IDisposable)request)?.Dispose(); } } private IEnumerator GetChannelMessages() { string url = "https://discord.com/api/v10/channels/" + DiscordBotPlugin.GetChannelID(DiscordBotPlugin.Channel.Chat) + "/messages?limit=10"; if (!string.IsNullOrEmpty(m_lastMessageID)) { url = url + "&after=" + m_lastMessageID; } UnityWebRequest request = UnityWebRequest.Get(url); try { request.SetRequestHeader("Authorization", "Bot " + DiscordBotPlugin.m_botToken.Value); request.SetRequestHeader("Content-Type", "application/json"); yield return request.SendWebRequest(); if ((int)request.result == 1) { try { Message[] messages = JsonConvert.DeserializeObject<Message[]>(request.downloadHandler.text); if (messages != null) { for (int i = messages.Length - 1; i >= 0; i--) { Message message = messages[i]; if (!(message.author?.bot ?? true) && message.id != null) { if (string.IsNullOrEmpty(m_lastMessageID) || ulong.Parse(message.id) > ulong.Parse(m_lastMessageID)) { m_lastMessageID = message.id; } if (!string.IsNullOrEmpty(m_lastMessageID)) { this.OnMessageReceived?.Invoke(message); } } } } yield break; } catch (Exception e) { this.OnError?.Invoke("Failed to parse messages: " + e.Message); yield break; } } this.OnError?.Invoke("Failed to get messages: " + request.error); } finally { ((IDisposable)request)?.Dispose(); } } [Description("Color utility to format into int for discord")] public static int ColorToInt(Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.RoundToInt(color.r * 255f); int num2 = Mathf.RoundToInt(color.g * 255f); int num3 = Mathf.RoundToInt(color.b * 255f); return (num << 16) + (num2 << 8) + num3; } } [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public static class EmojiHelper { private static readonly Dictionary<string, string> Emojis = new Dictionary<string, string> { { "smile", "\ud83d\ude0a" }, { "grin", "\ud83d\ude01" }, { "laugh", "\ud83d\ude02" }, { "wink", "\ud83d\ude09" }, { "wave", "\ud83d\udc4b" }, { "clap", "\ud83d\udc4f" }, { "thumbsup", "\ud83d\udc4d" }, { "thumbsdown", "\ud83d\udc4e" }, { "ok", "\ud83d\udc4c" }, { "pray", "\ud83d\ude4f" }, { "muscle", "\ud83d\udcaa" }, { "facepalm", "\ud83e\udd26" }, { "dog", "\ud83d\udc36" }, { "cat", "\ud83d\udc31" }, { "mouse", "\ud83d\udc2d" }, { "fox", "\ud83e\udd8a" }, { "bear", "\ud83d\udc3b" }, { "panda", "\ud83d\udc3c" }, { "koala", "\ud83d\udc28" }, { "lion", "\ud83e\udd81" }, { "tiger", "\ud83d\udc2f" }, { "monkey", "\ud83d\udc35" }, { "unicorn", "\ud83e\udd84" }, { "dragon", "\ud83d\udc09" }, { "tree", "\ud83c\udf33" }, { "palm", "\ud83c\udf34" }, { "flower", "\ud83c\udf38" }, { "rose", "\ud83c\udf39" }, { "sun", "☀\ufe0f" }, { "moon", "\ud83c\udf19" }, { "star", "⭐" }, { "rain", "\ud83c\udf27\ufe0f" }, { "snow", "❄\ufe0f" }, { "fire", "\ud83d\udd25" }, { "lightning", "⚡" }, { "pizza", "\ud83c\udf55" }, { "burger", "\ud83c\udf54" }, { "fries", "\ud83c\udf5f" }, { "taco", "\ud83c\udf2e" }, { "cake", "\ud83c\udf70" }, { "donut", "\ud83c\udf69" }, { "coffee", "☕" }, { "tea", "\ud83c\udf75" }, { "beer", "\ud83c\udf7a" }, { "wine", "\ud83c\udf77" }, { "rocket", "\ud83d\ude80" }, { "car", "\ud83d\ude97" }, { "bike", "\ud83d\udeb2" }, { "airplane", "✈\ufe0f" }, { "train", "\ud83d\ude86" }, { "bus", "\ud83d\ude8c" }, { "ship", "\ud83d\udea2" }, { "book", "\ud83d\udcd6" }, { "pencil", "✏\ufe0f" }, { "pen", "\ud83d\udd8a\ufe0f" }, { "paint", "\ud83c\udfa8" }, { "camera", "\ud83d\udcf7" }, { "phone", "\ud83d\udcf1" }, { "computer", "\ud83d\udcbb" }, { "gift", "\ud83c\udf81" }, { "balloon", "\ud83c\udf88" }, { "key", "\ud83d\udd11" }, { "lock", "\ud83d\udd12" }, { "soccer", "⚽" }, { "basketball", "\ud83c\udfc0" }, { "football", "\ud83c\udfc8" }, { "tennis", "\ud83c\udfbe" }, { "golf", "⛳" }, { "run", "\ud83c\udfc3" }, { "swim", "\ud83c\udfca" }, { "ski", "⛷\ufe0f" }, { "game", "\ud83c\udfae" }, { "music", "\ud83c\udfb5" }, { "guitar", "\ud83c\udfb8" }, { "drum", "\ud83e\udd41" }, { "check", "✅" }, { "x", "❌" }, { "warning", "⚠\ufe0f" }, { "question", "❓" }, { "exclamation", "❗" }, { "infinity", "♾\ufe0f" }, { "heart", "❤\ufe0f" }, { "brokenheart", "\ud83d\udc94" }, { "sparkle", "✨" }, { "starstruck", "\ud83e\udd29" }, { "plus", "✚" }, { "minus", "━" }, { "tornado", "\ud83c\udf2a\ufe0f" }, { "storm", "⛈\ufe0f" }, { "save", "\ud83d\udcbe" }, { "stop", "\ud83d\udd34" } }; public static string Emoji(string name) { if (string.IsNullOrWhiteSpace(name)) { return string.Empty; } string value; return Emojis.TryGetValue(name, out value) ? value : name; } } public static class Formatting { public enum TextFormat { Bold, Italic, BoldItalic, Strikethrough, InlineCode, None } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] public static string Format(string text, TextFormat format) { if (1 == 0) { } string result = format switch { TextFormat.Bold => "**" + text + "**", TextFormat.Italic => "*" + text + "*", TextFormat.BoldItalic => "***" + text + "***", TextFormat.Strikethrough => "~~" + text + "~~", TextFormat.InlineCode => "`" + text + "`", _ => text, }; if (1 == 0) { } return result; } } [<2cb2fe35-caa6-4066-8b30-a5790440185e>NullableContext(1)] [<0c5813c0-7a3b-4e69-af6d-a50bfcc1c2c8>Nullable(0)] public static class Links { public static readonly Dictionary<string, string> CreatureLinks = new Dictionary<string, string> { ["Boar"] = "https://valheim.fandom.com/wiki/Special:FilePath/Boar_trophy.png", ["Deer"] = "https://valheim.fandom.com/wiki/Special:FilePath/Deer_trophy.png", ["Neck"] = "https://valheim.fandom.com/wiki/Special:FilePath/Neck_trophy.png", ["Greyling"] = "https://valheim.fandom.com/wiki/Special:FilePath/Greyling_0S.png", ["Greydwarf"] = "https://valheim.fandom.com/wiki/Special:FilePath/Greydwarf_trophy.png", ["Greydwarf_Elite"] = "https://valheim.fandom.com/wiki/Special:FilePath/Greydwarf_Brute_trophy.png", ["Greydwarf_Shaman"] = "https://valheim.fandom.com/wiki/Special:FilePath/Greydwarf_Shaman_trophy.png", ["Troll"] = "https://valheim.fandom.com/wiki/Special:FilePath/Troll_trophy.png", ["Skeleton"] = "https://valheim.fandom.com/wiki/Special:FilePath/Skeleton_trophy.png", ["Skeleton_Poison"] = "https://valheim.fandom.com/wiki/Special:FilePath/Rancid_Remains_trophy.png", ["Ghost"] = "https://valheim.fandom.com/wiki/Special:FilePath/Ghost_0star.png", ["Draugr"] = "https://valheim.fandom.com/wiki/Special:FilePath/Draugr_trophy.png", ["Draugr_Elite"] = "https://valheim.fandom.com/wiki/Special:FilePath/Draugr_Elite_trophy.png", ["Draugr_Ranged"] = "https://valheim.fandom.com/wiki/Special:FilePath/Draugr_Ranged_trophy.png", ["Blob"] = "https://valheim.fandom.com/wiki/Special:FilePath/Blob_trophy.png", ["Leech"] = "https://valheim.fandom.com/wiki/Special:FilePath/Leech_trophy.png", ["Abomination