Decompiled source of RichDiscordPresence v1.0.5

RichDiscordPresence\RichDiscordPresence.dll

Decompiled 9 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("RichDiscordPresence")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RichDiscordPresence")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("1c31fc1f-1533-4b90-8a55-feeabea1cf7a")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
public class DiscordRpc
{
	[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
	public delegate void ReadyCallback();

	[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
	public delegate void DisconnectedCallback(int errorCode, string message);

	[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
	public delegate void ErrorCallback(int errorCode, string message);

	[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
	public delegate void JoinCallback(string secret);

	[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
	public delegate void SpectateCallback(string secret);

	[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
	public delegate void RequestCallback(ref JoinRequest request);

	public struct EventHandlers
	{
		public ReadyCallback readyCallback;

		public DisconnectedCallback disconnectedCallback;

		public ErrorCallback errorCallback;

		public JoinCallback joinCallback;

		public SpectateCallback spectateCallback;

		public RequestCallback requestCallback;
	}

	[Serializable]
	public struct RichPresenceStruct
	{
		public IntPtr state;

		public IntPtr details;

		public long startTimestamp;

		public long endTimestamp;

		public IntPtr largeImageKey;

		public IntPtr largeImageText;

		public IntPtr smallImageKey;

		public IntPtr smallImageText;

		public IntPtr partyId;

		public int partySize;

		public int partyMax;

		public IntPtr matchSecret;

		public IntPtr joinSecret;

		public IntPtr spectateSecret;

		public bool instance;
	}

	[Serializable]
	public struct JoinRequest
	{
		public string userId;

		public string username;

		public string discriminator;

		public string avatar;
	}

	public enum Reply
	{
		No,
		Yes,
		Ignore
	}

	public class RichPresence
	{
		private RichPresenceStruct _presence;

		private readonly List<IntPtr> _buffers = new List<IntPtr>(10);

		public string state;

		public string details;

		public long startTimestamp;

		public long endTimestamp;

		public string largeImageKey;

		public string largeImageText;

		public string smallImageKey;

		public string smallImageText;

		public string partyId;

		public int partySize;

		public int partyMax;

		public string matchSecret;

		public string joinSecret;

		public string spectateSecret;

		public bool instance;

		internal RichPresenceStruct GetStruct()
		{
			if (_buffers.Count > 0)
			{
				FreeMem();
			}
			_presence.state = StrToPtr(state, 128);
			_presence.details = StrToPtr(details, 128);
			_presence.startTimestamp = startTimestamp;
			_presence.endTimestamp = endTimestamp;
			_presence.largeImageKey = StrToPtr(largeImageKey, 32);
			_presence.largeImageText = StrToPtr(largeImageText, 128);
			_presence.smallImageKey = StrToPtr(smallImageKey, 32);
			_presence.smallImageText = StrToPtr(smallImageText, 128);
			_presence.partyId = StrToPtr(partyId, 128);
			_presence.partySize = partySize;
			_presence.partyMax = partyMax;
			_presence.matchSecret = StrToPtr(matchSecret, 128);
			_presence.joinSecret = StrToPtr(joinSecret, 128);
			_presence.spectateSecret = StrToPtr(spectateSecret, 128);
			_presence.instance = instance;
			return _presence;
		}

		private IntPtr StrToPtr(string input, int maxbytes)
		{
			if (string.IsNullOrEmpty(input))
			{
				return IntPtr.Zero;
			}
			string s = StrClampBytes(input, maxbytes);
			int byteCount = Encoding.UTF8.GetByteCount(s);
			IntPtr intPtr = Marshal.AllocHGlobal(byteCount);
			_buffers.Add(intPtr);
			Marshal.Copy(Encoding.UTF8.GetBytes(s), 0, intPtr, byteCount);
			return intPtr;
		}

		private static string StrToUtf8NullTerm(string toconv)
		{
			string text = toconv.Trim();
			byte[] bytes = Encoding.Default.GetBytes(text);
			if (bytes.Length != 0 && bytes[^1] != 0)
			{
				text += "\0\0";
			}
			return Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(text));
		}

		private static string StrClampBytes(string toclamp, int maxbytes)
		{
			string text = StrToUtf8NullTerm(toclamp);
			byte[] bytes = Encoding.UTF8.GetBytes(text);
			if (bytes.Length <= maxbytes)
			{
				return text;
			}
			byte[] array = new byte[0];
			Array.Copy(bytes, 0, array, 0, maxbytes - 1);
			array[^1] = 0;
			array[^2] = 0;
			return Encoding.UTF8.GetString(array);
		}

		internal void FreeMem()
		{
			for (int num = _buffers.Count - 1; num >= 0; num--)
			{
				Marshal.FreeHGlobal(_buffers[num]);
				_buffers.RemoveAt(num);
			}
		}
	}

	[DllImport("discord-rpc", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Discord_Initialize")]
	public static extern void Initialize(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId);

	[DllImport("discord-rpc", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Discord_Shutdown")]
	public static extern void Shutdown();

	[DllImport("discord-rpc", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Discord_RunCallbacks")]
	public static extern void RunCallbacks();

	[DllImport("discord-rpc", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Discord_UpdatePresence")]
	private static extern void UpdatePresenceNative(ref RichPresenceStruct presence);

	[DllImport("discord-rpc", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Discord_ClearPresence")]
	public static extern void ClearPresence();

	[DllImport("discord-rpc", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Discord_Respond")]
	public static extern void Respond(string userId, Reply reply);

	public static void UpdatePresence(RichPresence presence)
	{
		RichPresenceStruct presence2 = presence.GetStruct();
		UpdatePresenceNative(ref presence2);
		presence.FreeMem();
	}
}
namespace RichDiscordPresence;

[BepInPlugin("shudnal.RichDiscordPresence", "Rich Discord Presence", "1.0.5")]
[BepInProcess("valheim.exe")]
public class RichDiscordPresence : BaseUnityPlugin
{
	[HarmonyPatch(typeof(FejdStartup), "Awake")]
	private class FejdStartup_Awake_MainMenu
	{
		private static void Postfix()
		{
			if (modEnabled.Value)
			{
				LogInfo("FejdStartup.Awake");
				SetPresence(updateState: true);
			}
		}
	}

	[HarmonyPatch(typeof(FejdStartup), "OnDestroy")]
	private class FejdStartup_OnDestroy_MainMenu
	{
		private static void Postfix()
		{
			if (modEnabled.Value)
			{
				LogInfo("FejdStartup.OnDestroy");
				SetPresence(updateState: true);
			}
		}
	}

	[HarmonyPatch(typeof(ZNet), "Awake")]
	private class ZNet_Awake_PlayersCount
	{
		private static void Postfix()
		{
			if (modEnabled.Value)
			{
				playerCount = ZNet.instance.GetNrOfPlayers();
				LogInfo("ZNet.Awake");
				SetPresence();
			}
		}
	}

	[HarmonyPatch(typeof(ZNet), "UpdatePlayerList")]
	private class ZNet_UpdatePlayerList_PlayersCount
	{
		private static void Postfix()
		{
			if (modEnabled.Value && showServerSize.Value && ZNet.instance.GetNrOfPlayers() != playerCount)
			{
				playerCount = ZNet.instance.GetNrOfPlayers();
				LogInfo("ZNet.UpdatePlayerList");
				SetPresence();
			}
		}
	}

	[HarmonyPatch(typeof(ZNet), "RPC_PlayerList")]
	private class ZNet_RPC_PlayerList_PlayersCount
	{
		private static void Postfix()
		{
			if (modEnabled.Value && showServerSize.Value && ZNet.instance.GetNrOfPlayers() != playerCount)
			{
				playerCount = ZNet.instance.GetNrOfPlayers();
				LogInfo("ZNet.RPC_PlayerList");
				SetPresence();
			}
		}
	}

	[HarmonyPatch(typeof(Player), "UpdateBiome")]
	private class Player_UpdateBiome_Roaming
	{
		private static void Postfix(Player __instance)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if (modEnabled.Value && !((Object)(object)Player.m_localPlayer != (Object)(object)__instance) && currentBiome != __instance.GetCurrentBiome())
			{
				currentBiome = __instance.GetCurrentBiome();
				LogInfo("Player.UpdateBiome");
				SetPresence(updateState: true);
			}
		}
	}

	[HarmonyPatch(typeof(Ship), "OnTriggerEnter")]
	private class Ship_OnTriggerEnter_Sailing
	{
		private static void Postfix(Collider collider)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (modEnabled.Value && !((Object)(object)((Component)collider).GetComponent<Player>() != (Object)(object)Player.m_localPlayer) && onShip != ((Object)(object)Ship.GetLocalShip() != (Object)null))
			{
				onShip = (Object)(object)Ship.GetLocalShip() != (Object)null;
				LogInfo("Ship.OnTriggerEnter");
				SetPresence(updateState: true);
			}
		}
	}

	[HarmonyPatch(typeof(Ship), "OnTriggerExit")]
	private class Ship_OnTriggerExit_Sailing
	{
		private static void Postfix(Collider collider)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (modEnabled.Value && !((Object)(object)((Component)collider).GetComponent<Player>() != (Object)(object)Player.m_localPlayer) && onShip != ((Object)(object)Ship.GetLocalShip() != (Object)null))
			{
				onShip = (Object)(object)Ship.GetLocalShip() != (Object)null;
				LogInfo("Ship.OnTriggerExit");
				SetPresence(updateState: true);
			}
		}
	}

	[HarmonyPatch(typeof(EnvMan), "SetForceEnvironment")]
	private class EnvMan_SetForceEnvironment_SpecialEnv
	{
		private static void Postfix(string ___m_forceEnv)
		{
			if (modEnabled.Value && !(forceEnv == ___m_forceEnv))
			{
				forceEnv = ___m_forceEnv;
				LogInfo("EnvMan.SetForceEnvironment");
				SetPresence(updateState: true);
			}
		}
	}

	[HarmonyPatch(typeof(Player), "UpdateEnvStatusEffects")]
	private class Player_UpdateEnvStatusEffects_Roaming
	{
		private static void Postfix(Player __instance)
		{
			if (modEnabled.Value && !((Object)(object)Player.m_localPlayer != (Object)(object)__instance))
			{
				bool flag = __instance.IsSafeInHome() && __instance.GetBaseValue() >= safeInHomeBaseValue.Value;
				if (safeInHome != flag)
				{
					safeInHome = flag;
					LogInfo("Player.UpdateEnvStatusEffects");
					SetPresence(updateState: true);
				}
			}
		}
	}

	[HarmonyPatch(typeof(Trader), "Update")]
	private class Trader_Update_Trader
	{
		private static void Postfix(Trader __instance, float ___m_byeRange)
		{
			//IL_004b: 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)
			if (modEnabled.Value && showTrader.Value && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				float num = Utils.DistanceXZ(((Component)Player.m_localPlayer).transform.position, ((Component)__instance).transform.position);
				if (num > ___m_byeRange && (Object)(object)activeTrader != (Object)null)
				{
					activeTrader = null;
					LogInfo("Trader.Update");
					SetPresence(updateState: true);
				}
				else if (num <= ___m_byeRange && (Object)(object)activeTrader == (Object)null)
				{
					activeTrader = __instance;
					LogInfo("Trader.Update");
					SetPresence(updateState: true);
				}
			}
		}
	}

	[HarmonyPatch(typeof(EnemyHud), "UpdateHuds")]
	private class EnemyHud_UpdateHuds_Boss
	{
		private static void Postfix(EnemyHud __instance, Player player)
		{
			if (modEnabled.Value && !((Object)(object)Player.m_localPlayer != (Object)(object)player) && showingBossHud != __instance.ShowingBossHud())
			{
				showingBossHud = __instance.ShowingBossHud();
				LogInfo("EnemyHud.UpdateHuds");
				SetPresence(updateState: true);
			}
		}
	}

	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static EventHandler <>9__59_0;

		public static EventHandler <>9__59_1;

		public static ConsoleEvent <>9__59_2;

		public static Func<Teleport, bool> <>9__75_0;

		internal void <ConfigInit>b__59_0(object sender, EventArgs args)
		{
			UpdateImageDescription();
		}

		internal void <ConfigInit>b__59_1(object sender, EventArgs args)
		{
			UpdateImageDescription();
		}

		internal void <ConfigInit>b__59_2(ConsoleEventArgs args)
		{
			if (!modEnabled.Value)
			{
				((BaseUnityPlugin)instance).Logger.LogInfo((object)"Mod disabled");
			}
			else
			{
				SetPresence(updateState: true);
			}
		}

		internal bool <SetPresence>b__75_0(Teleport tp)
		{
			return !Utility.IsNullOrWhiteSpace(tp.m_enterText);
		}
	}

	private const string pluginID = "shudnal.RichDiscordPresence";

	private const string pluginName = "Rich Discord Presence";

	private const string pluginVersion = "1.0.5";

	private Harmony _harmony;

	private static ConfigEntry<bool> modEnabled;

	private static ConfigEntry<bool> loggingEnabled;

	private static ConfigEntry<string> ApplicationID;

	private static ConfigEntry<string> localizationLanguage;

	private static ConfigEntry<string> msgMainMenu;

	private static ConfigEntry<string> msgSingleplayer;

	private static ConfigEntry<string> msgMultiplayer;

	private static ConfigEntry<string> msgMultiplayerAlone;

	private static ConfigEntry<string> msgRoaming;

	private static ConfigEntry<string> msgBoss;

	private static ConfigEntry<string> msgAtHome;

	private static ConfigEntry<string> msgSailing;

	private static ConfigEntry<string> msgInDungeon;

	private static ConfigEntry<string> msgTrader;

	private static ConfigEntry<string> msgBiomeMeadows;

	private static ConfigEntry<string> msgBiomeSwamp;

	private static ConfigEntry<string> msgBiomeMountain;

	private static ConfigEntry<string> msgBiomeBlackForest;

	private static ConfigEntry<string> msgBiomePlains;

	private static ConfigEntry<string> msgBiomeAshLands;

	private static ConfigEntry<string> msgBiomeDeepNorth;

	private static ConfigEntry<string> msgBiomeOcean;

	private static ConfigEntry<string> msgBiomeMistlands;

	private static ConfigEntry<bool> showIngameTime;

	private static ConfigEntry<bool> showServerSize;

	private static ConfigEntry<bool> showServerName;

	private static ConfigEntry<bool> showGameState;

	private static ConfigEntry<int> serverMaxCapacity;

	private static ConfigEntry<string> serverName;

	private static ConfigEntry<bool> showTrader;

	private static ConfigEntry<int> safeInHomeBaseValue;

	private static ConfigEntry<string> liKeyDefault;

	private static ConfigEntry<string> liTextDefault;

	private static ConfigEntry<string> siKeyDefault;

	private static ConfigEntry<string> siTextDefault;

	private static ConfigEntry<string> liDescriptions;

	private static ConfigEntry<string> siDescriptions;

	private static readonly long started = (long)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;

	private static readonly Random random = new Random();

	private static RichDiscordPresence instance;

	private static DiscordRpc.EventHandlers handlers;

	private static Biome currentBiome = (Biome)0;

	private static string forceEnv = "";

	private static bool safeInHome;

	private static int playerCount = 0;

	private static Trader activeTrader;

	private static bool showingBossHud;

	private static bool onShip;

	private static readonly Dictionary<string, string> imageDescription = new Dictionary<string, string>();

	private static string details = "";

	private static string state = "";

	private void Awake()
	{
		_harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "shudnal.RichDiscordPresence");
		instance = this;
		ConfigInit();
		if (Utility.IsNullOrWhiteSpace(ApplicationID.Value))
		{
			((BaseUnityPlugin)instance).Logger.LogWarning((object)"Application ID is not set. Set and relaunch the game to load discord.");
			return;
		}
		DiscordRpc.Initialize(ApplicationID.Value, ref handlers, autoRegister: true, "");
		Game.isModded = true;
		UpdateImageDescription();
	}

	private void OnDestroy()
	{
		((BaseUnityPlugin)this).Config.Save();
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}

	private void OnDisable()
	{
		if (modEnabled.Value)
		{
			LogInfo("Shutdown");
			DiscordRpc.Shutdown();
		}
	}

	public static void LogInfo(object data)
	{
		if (loggingEnabled.Value)
		{
			((BaseUnityPlugin)instance).Logger.LogInfo(data);
		}
	}

	private void ConfigInit()
	{
		//IL_05b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ae: Expected O, but got Unknown
		((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 2555, "Nexus mod ID for updates");
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable the mod.");
		loggingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Logging enabled", false, "Enable logging.");
		ApplicationID = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Application ID", "", "The APPLICATION ID you get from discord developer portal -> Applications -> Your app -> General Information");
		localizationLanguage = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Loсalization language", "", "Specify language to make bosses, locations and biomes localized to it. If empty - current game language is used");
		msgMainMenu = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "State - Main menu", "Main Menu", "Message while in menu");
		msgSingleplayer = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "State - Singleplayer", "On their own", "Semicolon separated in singleplayer messages");
		msgMultiplayer = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "State - Multiplayer", "In a Group", "Semicolon separated in multiplayer messages");
		msgMultiplayerAlone = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "State - Alone in multiplayer", "Feeling lonely", "Semicolon separated in multiplayer but alone messages");
		msgRoaming = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "Details - Roaming", "Roaming around;Taking a stroll;Moving around;Wandering around;Prowling around;Walking around;Sauntering;", "Semicolon separated Biome: messages");
		msgBoss = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "Details - Fighting boss", "Fighting;Brawling;In combat;Is being fought;In a fight;Struggling against;Battling;In a battle;Hell of a fight", "Semicolon separated Boss: messages");
		msgAtHome = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "Details - Safe at home", "Hanging out at home;Keeping warm safely;Working at base;Chilling at home;Warm and safe;Safe at home;Warm and cozy", "Semicolon separated while safe at home messages");
		msgSailing = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "Details - Sailing", "Sailing;Seafaring;Boating;Yachting;Boat trip", "Semicolon separated sailing messages");
		msgInDungeon = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "Details - Dungeon", "Conquering;Killing things;Wiping out;Tomb Raiding;Grave-robbing;Plundering;Looting;Pillaging", "Semicolon separated in dungeon messages");
		msgTrader = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "Details - Trader", "Trading;Making a deal;Exchanging;Doing business;Negotiating;Bargaining;Haggling", "Semicolon separated when Trader nearby messages");
		msgBiomeMeadows = ((BaseUnityPlugin)this).Config.Bind<string>("Messages - Roaming Biome Specific", "Meadows", "", "Semicolon separated Biome: messages");
		msgBiomeSwamp = ((BaseUnityPlugin)this).Config.Bind<string>("Messages - Roaming Biome Specific", "Swamp", "", "Semicolon separated Biome: messages");
		msgBiomeMountain = ((BaseUnityPlugin)this).Config.Bind<string>("Messages - Roaming Biome Specific", "Mountain", "", "Semicolon separated Biome: messages");
		msgBiomeBlackForest = ((BaseUnityPlugin)this).Config.Bind<string>("Messages - Roaming Biome Specific", "BlackForest", "", "Semicolon separated Biome: messages");
		msgBiomePlains = ((BaseUnityPlugin)this).Config.Bind<string>("Messages - Roaming Biome Specific", "Plains", "", "Semicolon separated Biome: messages");
		msgBiomeAshLands = ((BaseUnityPlugin)this).Config.Bind<string>("Messages - Roaming Biome Specific", "AshLands", "", "Semicolon separated Biome: messages");
		msgBiomeDeepNorth = ((BaseUnityPlugin)this).Config.Bind<string>("Messages - Roaming Biome Specific", "DeepNorth", "", "Semicolon separated Biome: messages");
		msgBiomeOcean = ((BaseUnityPlugin)this).Config.Bind<string>("Messages - Roaming Biome Specific", "Ocean", "", "Semicolon separated Biome: messages");
		msgBiomeMistlands = ((BaseUnityPlugin)this).Config.Bind<string>("Messages - Roaming Biome Specific", "Mistlands", "", "Semicolon separated Biome: messages");
		safeInHomeBaseValue = ((BaseUnityPlugin)this).Config.Bind<int>("Misc", "Base value limit to be safe at home", 3, "How much PlayerBase objects should be near to consider player be safe at home");
		showIngameTime = ((BaseUnityPlugin)this).Config.Bind<bool>("State", "Show ingame time", true, "Show time since game start");
		showServerSize = ((BaseUnityPlugin)this).Config.Bind<bool>("State", "Show server size", true, "Show server size");
		showServerName = ((BaseUnityPlugin)this).Config.Bind<bool>("State", "Show server name", true, "Show server name");
		showGameState = ((BaseUnityPlugin)this).Config.Bind<bool>("State", "Show game state", true, "Show game state (singleplayer, multiplayer, multiplayer alone)");
		serverName = ((BaseUnityPlugin)this).Config.Bind<string>("State", "Server name", "", "If left emtpy the ingame server name will be used");
		serverMaxCapacity = ((BaseUnityPlugin)this).Config.Bind<int>("State", "Server max capacity", 0, "If left empty default Valheim capacity will be used");
		showTrader = ((BaseUnityPlugin)this).Config.Bind<bool>("State", "Show active Trader", true, "Show Trader name and trader message if any Trader is nearby");
		liKeyDefault = ((BaseUnityPlugin)this).Config.Bind<string>("Images - Default", "Large image key", "logo", "Default Large image key");
		liTextDefault = ((BaseUnityPlugin)this).Config.Bind<string>("Images - Default", "Large image text", "Valheim", "Default Large image text");
		siKeyDefault = ((BaseUnityPlugin)this).Config.Bind<string>("Images - Default", "Small image key", "", "Default Small image key");
		siTextDefault = ((BaseUnityPlugin)this).Config.Bind<string>("Images - Default", "Small image text", "", "Default Small image text");
		liDescriptions = ((BaseUnityPlugin)this).Config.Bind<string>("Images - Descriptions", "Large images descriptions", "", "Semicolon separated list of key-text Large Image descriptions where key is what's before : in details string. More at mod's page.");
		liDescriptions.SettingChanged += delegate
		{
			UpdateImageDescription();
		};
		siDescriptions = ((BaseUnityPlugin)this).Config.Bind<string>("Images - Descriptions", "Small images descriptions", "", "Semicolon separated list of key-text Small Image descriptions where key is what's after : in details string. More at mod's page.");
		siDescriptions.SettingChanged += delegate
		{
			UpdateImageDescription();
		};
		object obj = <>c.<>9__59_2;
		if (obj == null)
		{
			ConsoleEvent val = delegate
			{
				if (!modEnabled.Value)
				{
					((BaseUnityPlugin)instance).Logger.LogInfo((object)"Mod disabled");
				}
				else
				{
					SetPresence(updateState: true);
				}
			};
			<>c.<>9__59_2 = val;
			obj = (object)val;
		}
		new ConsoleCommand("richdiscordpresence", "Force Rich Presence update", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
	}

	private static void UpdateImageDescription()
	{
		imageDescription.Clear();
		string[] array = liDescriptions.Value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text in array)
		{
			int num = text.IndexOf("-");
			if (num != -1 && num != text.Length)
			{
				LogInfo("Loaded image description: " + text.Substring(0, num).Trim() + ", " + text.Substring(num + 1).Trim());
				imageDescription.Add(text.Substring(0, num).Trim(), text.Substring(num + 1).Trim());
			}
		}
		string[] array2 = siDescriptions.Value.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text2 in array2)
		{
			int num2 = text2.IndexOf("-");
			if (num2 != -1 && num2 != text2.Length)
			{
				LogInfo("Loaded image description: " + text2.Substring(0, num2).Trim() + ", " + text2.Substring(num2 + 1).Trim());
				imageDescription.Add(text2.Substring(0, num2).Trim(), text2.Substring(num2 + 1).Trim());
			}
		}
	}

	private static string GetRandomState(string state)
	{
		string[] array = state.Split(new char[1] { ';' }, StringSplitOptions.None);
		return array[random.Next(array.Length)];
	}

	private static string BiomeSpecific(Biome biome)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Invalid comparison between Unknown and I4
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Invalid comparison between Unknown and I4
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected I4, but got Unknown
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Invalid comparison between Unknown and I4
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Invalid comparison between Unknown and I4
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Invalid comparison between Unknown and I4
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Invalid comparison between Unknown and I4
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Invalid comparison between Unknown and I4
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Invalid comparison between Unknown and I4
		if ((int)biome <= 16)
		{
			switch (biome - 1)
			{
			default:
				if ((int)biome != 8)
				{
					if ((int)biome != 16)
					{
						break;
					}
					return GetRandomState(msgBiomePlains.Value);
				}
				return GetRandomState(msgBiomeBlackForest.Value);
			case 0:
				return GetRandomState(msgBiomeMeadows.Value);
			case 1:
				return GetRandomState(msgBiomeSwamp.Value);
			case 3:
				return GetRandomState(msgBiomeMountain.Value);
			case 2:
				break;
			}
		}
		else if ((int)biome <= 64)
		{
			if ((int)biome == 32)
			{
				return GetRandomState(msgBiomeAshLands.Value);
			}
			if ((int)biome == 64)
			{
				return GetRandomState(msgBiomeDeepNorth.Value);
			}
		}
		else
		{
			if ((int)biome == 256)
			{
				return GetRandomState(msgBiomeOcean.Value);
			}
			if ((int)biome == 512)
			{
				return GetRandomState(msgBiomeMistlands.Value);
			}
		}
		return "";
	}

	public static void SetPresence(bool updateState = false)
	{
		//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fb: Invalid comparison between Unknown and I4
		//IL_0233: Unknown result type (might be due to invalid IL or missing references)
		//IL_0307: Unknown result type (might be due to invalid IL or missing references)
		if (!modEnabled.Value)
		{
			return;
		}
		string text = "";
		string text2 = "";
		string text3 = "";
		string text4 = "";
		if (updateState)
		{
			if ((Object)(object)FejdStartup.instance != (Object)null)
			{
				details = msgMainMenu.Value;
				state = "";
			}
			else if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				details = "";
				state = "";
			}
			else
			{
				StringBuilder stringBuilder = new StringBuilder(256);
				string text5 = GetRandomState(msgRoaming.Value);
				if (showingBossHud)
				{
					string name = EnemyHud.instance.GetActiveBoss().m_name;
					text5 = GetRandomState(msgBoss.Value);
					stringBuilder.Append(Utility.IsNullOrWhiteSpace(localizationLanguage.Value) ? name : Localization.instance.TranslateSingleId(name, localizationLanguage.Value));
					stringBuilder.Append(": ");
					stringBuilder.Append(Utility.IsNullOrWhiteSpace(text5) ? "$menu_combat" : text5);
				}
				else if (showTrader.Value && (Object)(object)activeTrader != (Object)null)
				{
					text5 = GetRandomState(msgTrader.Value);
					stringBuilder.Append(Utility.IsNullOrWhiteSpace(localizationLanguage.Value) ? activeTrader.m_name : Localization.instance.TranslateSingleId(activeTrader.m_name, localizationLanguage.Value));
					stringBuilder.Append(": ");
					stringBuilder.Append(Utility.IsNullOrWhiteSpace(text5) ? "$npc_haldor_random_talk2" : text5);
				}
				else if ((Object)(object)Player.m_localPlayer != (Object)null && ((Character)Player.m_localPlayer).InInterior())
				{
					text5 = GetRandomState(msgInDungeon.Value);
					string text6 = "$tutorial_hildirdungeon_label";
					Location zoneLocation = Location.GetZoneLocation(((Component)Player.m_localPlayer).transform.position);
					if ((Object)(object)zoneLocation != (Object)null)
					{
						Teleport val = ((Component)zoneLocation).GetComponentsInChildren<Teleport>().First((Teleport tp) => !Utility.IsNullOrWhiteSpace(tp.m_enterText));
						if ((Object)(object)val != (Object)null)
						{
							text6 = val.m_enterText;
						}
					}
					stringBuilder.Append(Utility.IsNullOrWhiteSpace(localizationLanguage.Value) ? text6 : Localization.instance.TranslateSingleId(text6, localizationLanguage.Value));
					if (!Utility.IsNullOrWhiteSpace(text5))
					{
						stringBuilder.Append(": ");
						stringBuilder.Append(text5);
					}
				}
				else if ((int)currentBiome > 0)
				{
					string text7 = BiomeSpecific(currentBiome);
					if (safeInHome)
					{
						text5 = GetRandomState(msgAtHome.Value);
					}
					else if (onShip)
					{
						text5 = GetRandomState(msgSailing.Value);
					}
					else if (!Utility.IsNullOrWhiteSpace(text7))
					{
						text5 = text7;
					}
					string text8 = "$biome_" + ((object)(Biome)(ref currentBiome)).ToString().ToLower();
					stringBuilder.Append(Utility.IsNullOrWhiteSpace(localizationLanguage.Value) ? text8 : Localization.instance.TranslateSingleId(text8, localizationLanguage.Value));
					if (!Utility.IsNullOrWhiteSpace(text5))
					{
						stringBuilder.Append(": ");
						stringBuilder.Append(text5);
					}
				}
				details = Localization.instance.Localize(stringBuilder.ToString());
				StringBuilder stringBuilder2 = new StringBuilder(256);
				if (ZNet.IsSinglePlayer)
				{
					if (showGameState.Value)
					{
						stringBuilder2.Append(GetRandomState(msgSingleplayer.Value));
					}
				}
				else
				{
					if (showServerName.Value)
					{
						stringBuilder2.Append(Utility.IsNullOrWhiteSpace(serverName.Value) ? ZNet.m_ServerName : serverName.Value);
					}
					if (showServerName.Value && showGameState.Value)
					{
						stringBuilder2.Append(": ");
					}
					if (showGameState.Value)
					{
						if (((Object)(object)ZNet.instance == (Object)null || playerCount == 1) && !Utility.IsNullOrWhiteSpace(msgMultiplayerAlone.Value))
						{
							stringBuilder2.Append(GetRandomState(msgMultiplayerAlone.Value));
						}
						else
						{
							stringBuilder2.Append(GetRandomState(msgMultiplayer.Value));
						}
					}
				}
				state = Localization.instance.Localize(stringBuilder2.ToString());
			}
		}
		if (imageDescription.Count > 0)
		{
			string[] array = details.Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries);
			if (imageDescription.ContainsKey(array[0].Trim().Replace(" ", "_").ToLower()))
			{
				text = array[0].Trim().Replace(" ", "_").ToLower();
				text2 = imageDescription[text];
			}
			if (array.Length > 1 && imageDescription.ContainsKey(array[1].Trim().Replace(" ", "_").ToLower()))
			{
				text3 = array[1].Trim().Replace(" ", "_").ToLower();
				text4 = imageDescription[text3];
			}
		}
		LogInfo("Details: \"" + details + "\"" + ((!Utility.IsNullOrWhiteSpace(text)) ? (", Large Image: " + text) : string.Empty) + ((!Utility.IsNullOrWhiteSpace(text2)) ? (", Large Text: \"" + text2 + "\"") : string.Empty) + ((!Utility.IsNullOrWhiteSpace(text3)) ? (", Small Image: " + text3) : string.Empty) + ((!Utility.IsNullOrWhiteSpace(text4)) ? (", Small Text: \"" + text4 + "\"") : string.Empty));
		try
		{
			if (Utility.IsNullOrWhiteSpace(state) && Utility.IsNullOrWhiteSpace(details))
			{
				DiscordRpc.ClearPresence();
				return;
			}
			DiscordRpc.RichPresence presence = new DiscordRpc.RichPresence
			{
				details = details,
				state = state,
				largeImageKey = (Utility.IsNullOrWhiteSpace(text) ? liKeyDefault.Value : text),
				largeImageText = (Utility.IsNullOrWhiteSpace(text2) ? liTextDefault.Value : text2),
				smallImageKey = (Utility.IsNullOrWhiteSpace(text3) ? siKeyDefault.Value : text3),
				smallImageText = (Utility.IsNullOrWhiteSpace(text4) ? siTextDefault.Value : text4),
				startTimestamp = (showIngameTime.Value ? started : 0),
				partySize = ((showServerSize.Value && !ZNet.IsSinglePlayer && (Object)(object)ZNet.instance != (Object)null) ? playerCount : 0),
				partyMax = ((showServerSize.Value && !ZNet.IsSinglePlayer) ? ((serverMaxCapacity.Value == 0) ? 10 : serverMaxCapacity.Value) : 0)
			};
			DiscordRpc.UpdatePresence(presence);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)instance).Logger.LogWarning((object)ex);
		}
	}
}