Decompiled source of RuneheimCore v1.0.5

RuneheimCore.dll

Decompiled an hour ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("RuneheimCore")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: AssemblyInformationalVersion("1.0.5")]
[assembly: AssemblyProduct("RuneheimCore")]
[assembly: AssemblyTitle("RuneheimCore")]
[assembly: AssemblyVersion("1.0.5.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RuneheimCore
{
	[BepInPlugin("daytreee.runeheimcore", "Runeheim Core", "1.0.5")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "daytreee.runeheimcore";

		public const string ModName = "Runeheim Core";

		public const string Version = "1.0.5";

		internal static ManualLogSource Log;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			((Component)this).gameObject.AddComponent<RhServer.Syncer>();
			RhLog.Banner(((Component)this).gameObject);
		}
	}
	public static class RhCompendium
	{
		public class Page
		{
			public string Title;

			public Func<bool> Available;

			public Action<RectTransform> Build;

			public Action Refresh;

			public Action Hide;

			public int Order = 100;
		}

		private static readonly List<Page> pages = new List<Page>();

		public static IReadOnlyList<Page> Pages => pages;

		public static Page Register(Page page)
		{
			pages.RemoveAll((Page p) => p.Title == page.Title);
			pages.Add(page);
			pages.Sort((Page a, Page b) => a.Order.CompareTo(b.Order));
			return page;
		}
	}
	public static class RhLog
	{
		private class ErrorCounter : ILogListener, IDisposable
		{
			public readonly Dictionary<string, int> Errors = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

			public void LogEvent(object sender, LogEventArgs e)
			{
				//IL_0001: 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)
				if ((e.Level & 3) != 0 && e.Source != null)
				{
					Errors.TryGetValue(e.Source.SourceName, out var value);
					Errors[e.Source.SourceName] = value + 1;
				}
			}

			public void Dispose()
			{
			}
		}

		private class Line : List<(string text, ConsoleColor colour)>
		{
			public int Length => this.Sum(((string text, ConsoleColor colour) s) => s.text.Length);

			public Line Add(string text, ConsoleColor colour)
			{
				Add((text, colour));
				return this;
			}
		}

		private class Summary : MonoBehaviour
		{
			private void Start()
			{
				if (summarised)
				{
					return;
				}
				summarised = true;
				try
				{
					WriteSummary();
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Runeheim summary: " + ex.Message));
				}
			}
		}

		private const int Width = 72;

		private static readonly Stopwatch Clock = new Stopwatch();

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

		private static bool summarised;

		private static ErrorCounter counter;

		private static readonly Type CM = typeof(Paths).Assembly.GetType("BepInEx.ConsoleManager");

		private static readonly MethodInfo SetColour = CM?.GetMethod("SetConsoleColor", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

		public static void Note(string guid, string note)
		{
			if (!string.IsNullOrEmpty(guid))
			{
				Notes[guid] = note;
			}
		}

		private static Line Rule()
		{
			return new Line().Add("  " + new string('━', 72), ConsoleColor.DarkYellow);
		}

		private static Line Blank()
		{
			return new Line();
		}

		private static Line Centre(Line l)
		{
			int count = Math.Max(0, (72 - l.Length) / 2) + 2;
			Line line = new Line().Add(new string(' ', count), ConsoleColor.Gray);
			line.AddRange(l);
			return line;
		}

		private static object Static(string name)
		{
			PropertyInfo propertyInfo = CM?.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (propertyInfo != null)
			{
				return propertyInfo.GetValue(null, null);
			}
			return CM?.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null);
		}

		private static TextWriter ConsoleOut()
		{
			object obj = Static("ConsoleActive");
			bool flag = default(bool);
			int num;
			if (obj is bool)
			{
				flag = (bool)obj;
				num = 1;
			}
			else
			{
				num = 0;
			}
			if (((uint)num & (flag ? 1u : 0u)) == 0)
			{
				return null;
			}
			return Static("ConsoleStream") as TextWriter;
		}

		private static void Colour(ConsoleColor c)
		{
			try
			{
				SetColour?.Invoke(null, new object[1] { c });
			}
			catch
			{
			}
		}

		private static void Write(List<Line> lines, LogLevel level)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_00b5: Expected O, but got Unknown
			StringBuilder stringBuilder = new StringBuilder();
			foreach (Line line in lines)
			{
				stringBuilder.Append('\n').Append(string.Concat(line.Select(((string text, ConsoleColor colour) s) => s.text)).TrimEnd(Array.Empty<char>()));
			}
			TextWriter textWriter = null;
			try
			{
				textWriter = ConsoleOut();
			}
			catch
			{
			}
			if (textWriter == null || SetColour == null)
			{
				Plugin.Log.Log(level, (object)stringBuilder.ToString());
				return;
			}
			LogEventArgs e = new LogEventArgs((object)stringBuilder.ToString(), level, (ILogSource)(object)Plugin.Log);
			foreach (DiskLogListener item in Logger.Listeners.OfType<DiskLogListener>())
			{
				try
				{
					item.LogEvent((object)null, e);
				}
				catch
				{
				}
			}
			try
			{
				foreach (Line line2 in lines)
				{
					foreach (var item2 in line2)
					{
						var (value, _) = item2;
						Colour(item2.colour);
						textWriter.Write(value);
					}
					textWriter.Write(Environment.NewLine);
				}
				textWriter.Flush();
			}
			catch
			{
			}
			finally
			{
				Colour(ConsoleColor.Gray);
			}
		}

		internal static void Banner(GameObject host)
		{
			Clock.Start();
			counter = new ErrorCounter();
			Logger.Listeners.Add((ILogListener)(object)counter);
			Write(new List<Line>
			{
				Blank(),
				Rule(),
				Blank(),
				Centre(new Line().Add("R  U  N  E  H  E  I  M", ConsoleColor.Yellow)),
				Blank(),
				Centre(new Line().Add("Runeheim Core 1.0.5", ConsoleColor.Gray)),
				Centre(new Line().Add("loading the Runeheim mods ...", ConsoleColor.DarkGray)),
				Rule(),
				Blank()
			}, (LogLevel)16);
			host.AddComponent<Summary>();
		}

		private static void WriteSummary()
		{
			Clock.Stop();
			if (counter != null)
			{
				Logger.Listeners.Remove((ILogListener)(object)counter);
			}
			List<PluginInfo> list = (from p in Chainloader.PluginInfos.Values
				where p.Metadata.GUID.StartsWith("daytreee.", StringComparison.OrdinalIgnoreCase)
				orderby (!(p.Metadata.GUID == "daytreee.runeheimcore")) ? 1 : 0
				select p).ThenBy<PluginInfo, string>((PluginInfo p) => p.Metadata.Name, StringComparer.OrdinalIgnoreCase).ToList();
			int totalWidth = Math.Max(26, list.Select((PluginInfo p) => p.Metadata.Name.Length).DefaultIfEmpty(0).Max() + 2);
			int num = 0;
			List<Line> list2 = new List<Line>
			{
				Blank(),
				Centre(new Line().Add("◊  ", ConsoleColor.DarkYellow).Add("the Runeheim mods", ConsoleColor.White).Add("  ◊", ConsoleColor.DarkYellow)),
				Blank()
			};
			foreach (PluginInfo item in list)
			{
				int num2 = Errors(item);
				bool num3 = (Object)(object)item.Instance == (Object)null;
				bool flag = num3 || num2 > 0;
				if (flag)
				{
					num++;
				}
				Line line = new Line().Add("           ", ConsoleColor.Gray).Add(item.Metadata.Name.PadRight(totalWidth), flag ? ConsoleColor.Red : ConsoleColor.Gray).Add(item.Metadata.Version.ToString().PadRight(10), ConsoleColor.DarkYellow);
				string value;
				if (num3)
				{
					line.Add("faltered: did not load", ConsoleColor.Red);
				}
				else if (num2 > 0)
				{
					line.Add(string.Format("faltered: {0} error{1} while loading", num2, (num2 == 1) ? "" : "s"), ConsoleColor.Red);
				}
				else if (Notes.TryGetValue(item.Metadata.GUID, out value) && !string.IsNullOrEmpty(value))
				{
					line.Add(value, ConsoleColor.DarkCyan);
				}
				list2.Add(line);
			}
			if (list.Count == 0)
			{
				list2.Add(Centre(new Line().Add("(no Runeheim mods found)", ConsoleColor.DarkGray)));
			}
			Line line2 = new Line().Add(string.Format("{0} mod{1}  ·  ", list.Count, (list.Count == 1) ? "" : "s"), ConsoleColor.DarkGray);
			if (num > 0)
			{
				line2.Add($"{num} faltered", ConsoleColor.Red).Add("  ·  ", ConsoleColor.DarkGray);
			}
			line2.Add($"{Chainloader.PluginInfos.Count} plugins  ·  {Clock.Elapsed.TotalSeconds:0.0} s", ConsoleColor.DarkGray);
			list2.AddRange(new Line[8]
			{
				Blank(),
				Rule(),
				Blank(),
				Centre(new Line().Add("R U N E H E I M     L O A D E D", (num == 0) ? ConsoleColor.Yellow : ConsoleColor.Red)),
				Blank(),
				Centre(line2),
				Rule(),
				Blank()
			});
			Write(list2, (LogLevel)((num == 0) ? 16 : 4));
			static int Errors(PluginInfo p)
			{
				if (counter == null || !counter.Errors.TryGetValue(p.Metadata.Name, out var value2))
				{
					return 0;
				}
				return value2;
			}
		}
	}
	public static class RhPlayers
	{
		public const string LevelKey = "RS_Level";

		public static Func<int> LocalLevel;

		public static int Level(Player p)
		{
			if ((Object)(object)p == (Object)null)
			{
				return 1;
			}
			if ((Object)(object)p == (Object)(object)Player.m_localPlayer && LocalLevel != null)
			{
				try
				{
					return Mathf.Max(1, LocalLevel());
				}
				catch
				{
				}
			}
			ZNetView component = ((Component)p).GetComponent<ZNetView>();
			if (!((Object)(object)component != (Object)null) || !component.IsValid())
			{
				return 1;
			}
			return Mathf.Max(1, component.GetZDO().GetInt("RS_Level", 1));
		}

		public static void Publish()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || LocalLevel == null)
			{
				return;
			}
			ZNetView component = ((Component)localPlayer).GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.IsValid() && component.IsOwner())
			{
				int num;
				try
				{
					num = LocalLevel();
				}
				catch
				{
					return;
				}
				if (component.GetZDO().GetInt("RS_Level", 0) != num)
				{
					component.GetZDO().Set("RS_Level", num);
				}
			}
		}
	}
	public static class RhServer
	{
		internal class Syncer : MonoBehaviour
		{
			private void LateUpdate()
			{
				if (pending)
				{
					pending = false;
					Sync();
				}
			}
		}

		private static readonly HashSet<ConfigFile> watched = new HashSet<ConfigFile>();

		private static bool pending;

		private static Type sync;

		private static PropertyInfo isAdmin;

		private static MethodInfo send;

		private static object syncInstance;

		private static bool looked;

		public static bool IsAdmin
		{
			get
			{
				if ((Object)(object)ZNet.instance == (Object)null)
				{
					return true;
				}
				Look();
				try
				{
					if (isAdmin != null && syncInstance != null)
					{
						return (bool)isAdmin.GetValue(syncInstance);
					}
				}
				catch
				{
				}
				return ZNet.instance.IsServer();
			}
		}

		private static void Look()
		{
			if (!looked)
			{
				looked = true;
				sync = Type.GetType("Jotunn.Managers.SynchronizationManager, Jotunn");
				if (!(sync == null))
				{
					syncInstance = sync.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
					isAdmin = sync.GetProperty("PlayerIsAdmin");
					send = sync.GetMethod("SynchronizeChangedConfig", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
		}

		public static bool IsServerEntry(ConfigEntryBase e)
		{
			object obj;
			if (e == null)
			{
				obj = null;
			}
			else
			{
				ConfigDescription description = e.Description;
				obj = ((description != null) ? description.Tags : null);
			}
			object[] array = (object[])obj;
			if (array == null)
			{
				return false;
			}
			object[] array2 = array;
			bool flag = default(bool);
			foreach (object obj2 in array2)
			{
				FieldInfo fieldInfo = obj2?.GetType().GetField("IsAdminOnly");
				int num;
				if (fieldInfo != null)
				{
					object value = fieldInfo.GetValue(obj2);
					if (value is bool)
					{
						flag = (bool)value;
						num = 1;
					}
					else
					{
						num = 0;
					}
				}
				else
				{
					num = 0;
				}
				if (((uint)num & (flag ? 1u : 0u)) != 0)
				{
					return true;
				}
			}
			return false;
		}

		public static void Watch(ConfigFile cfg)
		{
			if (cfg == null || !watched.Add(cfg))
			{
				return;
			}
			cfg.SettingChanged += delegate(object s, SettingChangedEventArgs a)
			{
				if (IsServerEntry(a.ChangedSetting) && (Object)(object)ZNet.instance != (Object)null && IsAdmin)
				{
					pending = true;
				}
			};
		}

		public static void Sync()
		{
			Look();
			try
			{
				send?.Invoke(syncInstance, null);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Server settings sync: " + (ex.InnerException?.Message ?? ex.Message)));
			}
		}
	}
	public static class RhSettings
	{
		public enum Kind
		{
			Section,
			Info,
			Toggle,
			Slider,
			Choice,
			Button
		}

		public class Row
		{
			public Kind Kind;

			public string Title;

			public string Desc;

			public Func<string> DynamicTitle;

			public bool Indent;

			public bool Server;

			public Func<bool> Active;

			public Func<bool> Get;

			public Action<bool> Set;

			public Func<float> GetF;

			public Action<float> SetF;

			public float Min;

			public float Max;

			public bool Whole;

			public bool Invert;

			public Func<float, string> Fmt;

			public string[] Options;

			public string[] OptionTips;

			public Func<int> GetI;

			public Action<int> SetI;

			public string ButtonText;

			public Action Click;

			public Func<bool> IsDefault;

			public Action Reset;
		}

		public class Page
		{
			public string Id;

			public string Title;

			public string Group;

			public int Order;

			public readonly List<Row> Rows = new List<Row>();

			public Row Add(Row r)
			{
				Rows.Add(r);
				Version++;
				return r;
			}

			public Row Section(string title)
			{
				return Add(new Row
				{
					Kind = Kind.Section,
					Title = title
				});
			}

			public Row Info(string text)
			{
				return Add(new Row
				{
					Kind = Kind.Info,
					Title = text
				});
			}

			public Row Info(Func<string> text)
			{
				return Add(new Row
				{
					Kind = Kind.Info,
					Title = text(),
					DynamicTitle = text
				});
			}

			public Row Button(string title, string desc, string label, Action click)
			{
				return Add(new Row
				{
					Kind = Kind.Button,
					Title = title,
					Desc = desc,
					ButtonText = label,
					Click = click
				});
			}

			public Row Toggle(ConfigEntry<bool> e, string title, string desc = null, Func<bool> active = null, bool indent = false)
			{
				bool server = RhServer.IsServerEntry((ConfigEntryBase)(object)e);
				return Add(new Row
				{
					Kind = Kind.Toggle,
					Title = title,
					Desc = (desc ?? Describe((ConfigEntryBase)(object)e)),
					Indent = indent,
					Server = server,
					Active = Gate(server, active),
					Get = () => e.Value,
					Set = delegate(bool v)
					{
						if (Allowed(server))
						{
							e.Value = v;
						}
					},
					IsDefault = () => e.Value == (bool)((ConfigEntryBase)e).DefaultValue,
					Reset = delegate
					{
						if (Allowed(server))
						{
							e.Value = (bool)((ConfigEntryBase)e).DefaultValue;
						}
					}
				});
			}

			public Row Slider(ConfigEntry<float> e, string title, string desc, float min, float max, Func<float, string> fmt, Func<bool> active = null, bool indent = false, bool invert = false)
			{
				bool server = RhServer.IsServerEntry((ConfigEntryBase)(object)e);
				return Add(new Row
				{
					Kind = Kind.Slider,
					Title = title,
					Desc = (desc ?? Describe((ConfigEntryBase)(object)e)),
					Indent = indent,
					Server = server,
					Active = Gate(server, active),
					Min = min,
					Max = max,
					Fmt = fmt,
					Invert = invert,
					GetF = () => e.Value,
					SetF = delegate(float v)
					{
						if (Allowed(server))
						{
							e.Value = (float)Math.Round(v, 2);
						}
					},
					IsDefault = () => Mathf.Abs(e.Value - (float)((ConfigEntryBase)e).DefaultValue) < 0.005f,
					Reset = delegate
					{
						if (Allowed(server))
						{
							e.Value = (float)((ConfigEntryBase)e).DefaultValue;
						}
					}
				});
			}

			public Row Slider(ConfigEntry<int> e, string title, string desc, int min, int max, Func<float, string> fmt, Func<bool> active = null, bool indent = false)
			{
				bool server = RhServer.IsServerEntry((ConfigEntryBase)(object)e);
				return Add(new Row
				{
					Kind = Kind.Slider,
					Title = title,
					Desc = (desc ?? Describe((ConfigEntryBase)(object)e)),
					Indent = indent,
					Server = server,
					Active = Gate(server, active),
					Min = min,
					Max = max,
					Fmt = fmt,
					Whole = true,
					GetF = () => e.Value,
					SetF = delegate(float v)
					{
						if (Allowed(server))
						{
							e.Value = Mathf.RoundToInt(v);
						}
					},
					IsDefault = () => e.Value == (int)((ConfigEntryBase)e).DefaultValue,
					Reset = delegate
					{
						if (Allowed(server))
						{
							e.Value = (int)((ConfigEntryBase)e).DefaultValue;
						}
					}
				});
			}

			public Row Choice<T>(ConfigEntry<T> e, string title, string desc, Func<T, string> name = null, Func<T, string> tip = null, Func<bool> active = null) where T : struct, Enum
			{
				bool server = RhServer.IsServerEntry((ConfigEntryBase)(object)e);
				T[] values = (T[])Enum.GetValues(typeof(T));
				return Add(new Row
				{
					Kind = Kind.Choice,
					Title = title,
					Desc = (desc ?? Describe((ConfigEntryBase)(object)e)),
					Server = server,
					Active = Gate(server, active),
					Options = Array.ConvertAll(values, (T v) => (name == null) ? v.ToString() : name(v)),
					OptionTips = ((tip != null) ? Array.ConvertAll(values, (T v) => tip(v)) : null),
					GetI = () => Array.IndexOf(values, e.Value),
					SetI = delegate(int i)
					{
						if (Allowed(server))
						{
							e.Value = values[i];
						}
					},
					IsDefault = () => e.Value.Equals(((ConfigEntryBase)e).DefaultValue),
					Reset = delegate
					{
						if (Allowed(server))
						{
							e.Value = (T)((ConfigEntryBase)e).DefaultValue;
						}
					}
				});
			}
		}

		private static readonly List<Page> pages = new List<Page>();

		public static IReadOnlyList<Page> Pages => pages;

		public static int Version { get; private set; }

		public static Page AddPage(string id, string title, string group, int order = 100)
		{
			pages.RemoveAll((Page p) => p.Id == id);
			Page page = new Page
			{
				Id = id,
				Title = title,
				Group = group,
				Order = order
			};
			pages.Add(page);
			pages.Sort((Page a, Page b) => a.Order.CompareTo(b.Order));
			Version++;
			return page;
		}

		internal static string Describe(ConfigEntryBase e)
		{
			object obj;
			if (e == null)
			{
				obj = null;
			}
			else
			{
				ConfigDescription description = e.Description;
				obj = ((description != null) ? description.Description : null);
			}
			if (obj == null)
			{
				obj = "";
			}
			return (string)obj;
		}

		private static Func<bool> Gate(bool server, Func<bool> active)
		{
			if (!server)
			{
				return active;
			}
			return () => RhServer.IsAdmin && (active == null || active());
		}

		private static bool Allowed(bool server)
		{
			if (!server || RhServer.IsAdmin)
			{
				return true;
			}
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)2, "Only a server admin can change this", 0, (Sprite)null, false);
			}
			return false;
		}
	}
}