Decompiled source of UltimateMonitor v1.3.0

UltimateMonitor.dll

Decompiled 9 months 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.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using Colossal.Collections;
using Colossal.Serialization.Entities;
using Colossal.UI.Binding;
using Game;
using Game.Citizens;
using Game.Common;
using Game.Companies;
using Game.Simulation;
using Game.Tools;
using Game.UI;
using Gooee.Plugins;
using Gooee.Plugins.Attributes;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UltimateMonitor.ComponentTypes;
using UltimateMonitor.Configuration;
using UltimateMonitor.Data;
using UltimateMonitor.Systems;
using UltimateMonitor.UI;
using Unity.Burst;
using Unity.Burst.Intrinsics;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using UnityEngine;
using UnityEngine.Scripting;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Cities2Modding")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Cities2Modding")]
[assembly: AssemblyDescription("UltimateMonitor")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: AssemblyInformationalVersion("1.3.0.0+2ed5607b56ca9992fb9df3757185d74a80ed732e")]
[assembly: AssemblyProduct("UltimateMonitor")]
[assembly: AssemblyTitle("UltimateMonitor")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 UltimateMonitor
{
	[BepInPlugin("UltimateMonitor", "UltimateMonitor", "1.3.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private void Awake()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			((BaseUnityPlugin)this).Logger.LogInfo((object)(Environment.NewLine + "          ___              ___  ___        __         ___  __   __  \r\n|  | |     |  |  |\\/|  /\\   |  |__   |\\/| /  \\ |\\ | |  |  /  \\ |__) \r\n\\__/ |___  |  |  |  | /~~\\  |  |___  |  | \\__/ | \\| |  |  \\__/ |  \\ \r\n                                                                    "));
			new Harmony("UltimateMonitor").PatchAll();
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "UltimateMonitor";

		public const string PLUGIN_NAME = "UltimateMonitor";

		public const string PLUGIN_VERSION = "1.3.0.0";
	}
}
namespace UltimateMonitor.UI
{
	[ControllerDepends(/*Could not decode attribute arguments.*/)]
	[ControllerDepends(/*Could not decode attribute arguments.*/)]
	public class UltimateMonitorController : Controller<UltimateMonitorViewModel>
	{
		public static readonly UltimateMonitorConfig _config = UltimateMonitorConfig.Load();

		private CountEmploymentSystem _countEmploymentSystem;

		private UltimateMonitorDataSystem _dataSystem;

		public override UltimateMonitorViewModel Configure()
		{
			_countEmploymentSystem = ((ComponentSystemBase)this).World.GetOrCreateSystemManaged<CountEmploymentSystem>();
			_dataSystem = ((ComponentSystemBase)this).World.GetOrCreateSystemManaged<UltimateMonitorDataSystem>();
			JobHandle val5 = default(JobHandle);
			((UISystemBase)this).AddUpdateBinding((IUpdateBinding)(object)new GetterValueBinding<int>("unemploymentInfo", "unemploymentEducation0", (Func<int>)(() => _countEmploymentSystem.GetUnemploymentByEducation(ref val5)[0]), (IWriter<int>)null, (EqualityComparer<int>)null));
			JobHandle val4 = default(JobHandle);
			((UISystemBase)this).AddUpdateBinding((IUpdateBinding)(object)new GetterValueBinding<int>("unemploymentInfo", "unemploymentEducation1", (Func<int>)(() => _countEmploymentSystem.GetUnemploymentByEducation(ref val4)[1]), (IWriter<int>)null, (EqualityComparer<int>)null));
			JobHandle val3 = default(JobHandle);
			((UISystemBase)this).AddUpdateBinding((IUpdateBinding)(object)new GetterValueBinding<int>("unemploymentInfo", "unemploymentEducation2", (Func<int>)(() => _countEmploymentSystem.GetUnemploymentByEducation(ref val3)[2]), (IWriter<int>)null, (EqualityComparer<int>)null));
			JobHandle val2 = default(JobHandle);
			((UISystemBase)this).AddUpdateBinding((IUpdateBinding)(object)new GetterValueBinding<int>("unemploymentInfo", "unemploymentEducation3", (Func<int>)(() => _countEmploymentSystem.GetUnemploymentByEducation(ref val2)[3]), (IWriter<int>)null, (EqualityComparer<int>)null));
			JobHandle val = default(JobHandle);
			((UISystemBase)this).AddUpdateBinding((IUpdateBinding)(object)new GetterValueBinding<int>("unemploymentInfo", "unemploymentEducation4", (Func<int>)(() => _countEmploymentSystem.GetUnemploymentByEducation(ref val)[4]), (IWriter<int>)null, (EqualityComparer<int>)null));
			AddUnemploymentBindings();
			UltimateMonitorViewModel ultimateMonitorViewModel = new UltimateMonitorViewModel();
			ultimateMonitorViewModel.Items = new List<MonitorItem>(25)
			{
				new MonitorItem
				{
					Name = "Electricity",
					Icon = "Media/Game/Icons/Electricity.svg",
					Colour = "#FFB80E",
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "electricityInfo.electricityAvailability" }
				},
				new MonitorItem
				{
					Name = "Water",
					Icon = "Media/Game/Icons/Water.svg",
					Colour = "#39C2FF",
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "waterInfo.waterAvailability" }
				},
				new MonitorItem
				{
					Name = "Sewage",
					Icon = "Media/Game/Icons/Sewage.svg",
					Colour = "#997E62",
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "waterInfo.sewageAvailability" }
				},
				new MonitorItem
				{
					Name = "Garbage",
					Icon = "Media/Game/Icons/Garbage.svg",
					Colour = "#31CF00",
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "garbageInfo.processingAvailability" }
				},
				new MonitorItem
				{
					Name = "FireHazard",
					Icon = "Media/Game/Icons/FireSafety.svg",
					Colour = "GreenToRed",
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "fireAndRescueInfo.averageFireHazard" }
				},
				new MonitorItem
				{
					Name = "CrimeRate",
					Icon = "Media/Game/Notifications/CrimeScene.svg",
					Colour = "#255D95",
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "policeInfo.averageCrimeProbability" }
				},
				new MonitorItem
				{
					Name = "TrafficFlow",
					Icon = "Media/Game/Icons/TrafficLights.svg",
					Colour = "#808080",
					ValueOperation = ValueOperation.Custom,
					ValueSubscriptions = new string[1] { "trafficInfo.trafficFlow" }
				},
				new MonitorItem
				{
					Name = "ParkingAvailability",
					Icon = "Media/Game/Icons/Parking.svg",
					Colour = "#808080",
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "roadsInfo.parkingAvailability" }
				},
				new MonitorItem
				{
					Name = "Unemployment",
					Icon = "Media/Game/Icons/Workers.svg",
					Colour = "#a06d6a",
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "populationInfo.unemployment" }
				},
				new MonitorItem
				{
					Name = "UnemploymentUneducated",
					Icon = "Media/Game/Icons/Uneducated.svg",
					Colour = "#966aa0",
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "unemploymentInfo.unemploymentEducation0" }
				},
				new MonitorItem
				{
					Name = "UnemploymentPoorlyEducated",
					Icon = "Media/Game/Icons/PoorlyEducated.svg",
					Colour = "#796aa0",
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "unemploymentInfo.unemploymentEducation1" }
				},
				new MonitorItem
				{
					Name = "UnemploymentEducated",
					Icon = "Media/Game/Icons/Educated.svg",
					Colour = "#6a79a0",
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "unemploymentInfo.unemploymentEducation2" }
				},
				new MonitorItem
				{
					Name = "UnemploymentWellEducated",
					Icon = "Media/Game/Icons/WellEducated.svg",
					Colour = "#6a9da0",
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "unemploymentInfo.unemploymentEducation3" }
				},
				new MonitorItem
				{
					Name = "UnemploymentHighlyEducated",
					Icon = "Media/Game/Icons/HighlyEducated.svg",
					Colour = "#6aa078",
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "unemploymentInfo.unemploymentEducation4" }
				},
				new MonitorItem
				{
					Name = "HealthcareEfficiency",
					Icon = "Media/Game/Icons/Healthcare.svg",
					Colour = "#E56333",
					ValueOperation = ValueOperation.Average,
					ValueSubscriptions = new string[2] { "healthcareInfo.healthcareAvailability", "healthcareInfo.averageHealth" }
				},
				new MonitorItem
				{
					Name = "DeathcareEfficiency",
					Icon = "Media/Game/Icons/Deathcare.svg",
					Colour = "#797979",
					ValueOperation = ValueOperation.Average,
					ValueSubscriptions = new string[2] { "healthcareInfo.cemeteryAvailability", "healthcareInfo.deathcareAvailability" }
				},
				new MonitorItem
				{
					Name = "ImprisonmentCapacity",
					Icon = "Media/Game/Icons/Police.svg",
					Colour = "#FFB80E",
					ValueOperation = ValueOperation.Average,
					ValueSubscriptions = new string[2] { "policeInfo.jailAvailability", "policeInfo.prisonAvailability" }
				},
				new MonitorItem
				{
					Name = "EducationAvailability",
					Icon = "Media/Game/Icons/Education.svg",
					Colour = "#61819C",
					ValueOperation = ValueOperation.Average,
					ValueSubscriptions = new string[4] { "educationInfo.elementaryAvailability", "educationInfo.highSchoolAvailability", "educationInfo.collegeAvailability", "educationInfo.universityAvailability" }
				},
				new MonitorItem
				{
					Name = "IncomeEfficiency",
					Icon = "Media/Game/Icons/Money.svg",
					Colour = "#9ADF4B",
					ValueOperation = ValueOperation.Custom,
					ValueSubscriptions = new string[2] { "budget.totalIncome", "budget.totalExpenses" }
				},
				new MonitorItem
				{
					Name = "MonthlyPopulationGrowth",
					Icon = "Media/Game/Icons/Population.svg",
					Colour = "#97B4BE",
					ValueOperation = ValueOperation.Custom,
					ValueSubscriptions = new string[5] { "populationInfo.population", "populationInfo.birthRate", "populationInfo.movedIn", "populationInfo.deathRate", "populationInfo.movedAway" }
				},
				new MonitorItem
				{
					Name = "AveragePollution",
					Icon = "Media/Game/Icons/GroundPollution.svg",
					Colour = "#9D662E",
					ValueOperation = ValueOperation.Average,
					ValueSubscriptions = new string[4] { "pollutionInfo.averageGroundPollution", "pollutionInfo.averageWaterPollution", "pollutionInfo.averageAirPollution", "pollutionInfo.averageNoisePollution" }
				},
				new MonitorItem
				{
					Name = "HomelessHouseholds",
					Icon = "Media/Game/Icons/NoMoney.svg",
					Colour = "#d8903e",
					Type = MonitorItemType.Raw,
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "unemploymentInfo.homelessHouseholds" }
				},
				new MonitorItem
				{
					Name = "UnderEmployed",
					Icon = "Media/Game/Icons/Household.svg",
					Colour = "#b5b05e",
					Type = MonitorItemType.Raw,
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "unemploymentInfo.underEmployed" }
				},
				new MonitorItem
				{
					Name = "Employable",
					Icon = "Media/Game/Icons/Neutral.svg",
					Colour = "#5eb57b",
					Type = MonitorItemType.Raw,
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "unemploymentInfo.employable" }
				},
				new MonitorItem
				{
					Name = "Unemployed",
					Icon = "Media/Game/Icons/Sad.svg",
					Colour = "#b55e5e",
					Type = MonitorItemType.Raw,
					ValueOperation = ValueOperation.None,
					ValueSubscriptions = new string[1] { "unemploymentInfo.unemployed" }
				}
			};
			List<MonitorWindow> windows = _config.Windows;
			ultimateMonitorViewModel.Windows = ((windows == null) ? new List<MonitorWindow>(1)
			{
				new MonitorWindow
				{
					Name = "Default",
					Monitors = new List<MonitorWindowDisplay>()
				}
			} : _config.Windows);
			return ultimateMonitorViewModel;
		}

		private void AddUnemploymentBindings()
		{
			((UISystemBase)this).AddUpdateBinding((IUpdateBinding)(object)new GetterValueBinding<int>("unemploymentInfo", "homelessHouseholds", (Func<int>)(() => _dataSystem.Data.HomelessHouseholds), (IWriter<int>)null, (EqualityComparer<int>)null));
			((UISystemBase)this).AddUpdateBinding((IUpdateBinding)(object)new GetterValueBinding<int>("unemploymentInfo", "underEmployed", (Func<int>)(() => _dataSystem.Data.UnderEmployed), (IWriter<int>)null, (EqualityComparer<int>)null));
			((UISystemBase)this).AddUpdateBinding((IUpdateBinding)(object)new GetterValueBinding<int>("unemploymentInfo", "employable", (Func<int>)(() => _dataSystem.Data.Employable), (IWriter<int>)null, (EqualityComparer<int>)null));
			((UISystemBase)this).AddUpdateBinding((IUpdateBinding)(object)new GetterValueBinding<int>("unemploymentInfo", "unemployed", (Func<int>)(() => _dataSystem.Data.Unemployed), (IWriter<int>)null, (EqualityComparer<int>)null));
		}

		[OnTrigger]
		private void OnAddMonitor(string json)
		{
			if (string.IsNullOrEmpty(json))
			{
				return;
			}
			Dictionary<string, object> dictionary = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
			if (dictionary == null)
			{
				return;
			}
			string windowName = (string)dictionary["WindowName"];
			string monitorName = (string)dictionary["MonitorName"];
			MonitorWindow monitorWindow = base.Model.Windows.FirstOrDefault((MonitorWindow w) => w.Name == windowName);
			if (monitorWindow == null)
			{
				return;
			}
			MonitorItem monitorItem = base.Model.Items.FirstOrDefault((MonitorItem i) => i.Name == monitorName);
			if (monitorItem != null)
			{
				List<MonitorWindowDisplay> list = monitorWindow.Monitors ?? new List<MonitorWindowDisplay>();
				if (list.Count((MonitorWindowDisplay m) => m.MonitorItemName == monitorName) <= 0)
				{
					list.Add(new MonitorWindowDisplay
					{
						MonitorItemName = monitorItem.Name,
						Order = list.Count
					});
					monitorWindow.Monitors = list;
					base.TriggerUpdate();
				}
			}
		}

		[OnTrigger]
		private void OnRemoveMonitor(string json)
		{
			if (string.IsNullOrEmpty(json))
			{
				return;
			}
			Dictionary<string, object> dictionary = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
			if (dictionary == null)
			{
				return;
			}
			string windowName = (string)dictionary["WindowName"];
			string monitorName = (string)dictionary["MonitorName"];
			MonitorWindow monitorWindow = base.Model.Windows.FirstOrDefault((MonitorWindow w) => w.Name == windowName);
			if (monitorWindow == null || monitorWindow.Monitors == null || base.Model.Items.FirstOrDefault((MonitorItem i) => i.Name == monitorName) == null)
			{
				return;
			}
			List<MonitorWindowDisplay> monitors = monitorWindow.Monitors;
			if (monitors == null || monitors.Count((MonitorWindowDisplay m) => m.MonitorItemName == monitorName) == 0)
			{
				return;
			}
			monitors.RemoveAll((MonitorWindowDisplay m) => m.MonitorItemName == monitorName);
			int num = 0;
			foreach (MonitorWindowDisplay item in monitors.OrderBy((MonitorWindowDisplay m) => m.Order))
			{
				item.Order = num;
				num++;
			}
			base.TriggerUpdate();
		}

		[OnTrigger]
		private void OnUpdateMonitorOrder(string json)
		{
			if (string.IsNullOrEmpty(json))
			{
				return;
			}
			Dictionary<string, object> dictionary = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
			if (dictionary == null)
			{
				return;
			}
			string windowName = (string)dictionary["WindowName"];
			string monitorName = (string)dictionary["MonitorName"];
			long num = (long)dictionary["Direction"];
			if (num == 0L)
			{
				return;
			}
			MonitorWindow monitorWindow = base.Model.Windows.FirstOrDefault((MonitorWindow w) => w.Name == windowName);
			MonitorWindowDisplay monitorWindowDisplay = monitorWindow?.Monitors?.FirstOrDefault((MonitorWindowDisplay m) => m.MonitorItemName == monitorName);
			if (monitorWindow == null || monitorWindowDisplay == null)
			{
				return;
			}
			List<MonitorWindowDisplay> monitors = monitorWindow.Monitors;
			int lastOrder = monitorWindowDisplay.Order;
			int order = monitorWindowDisplay.Order + (int)num;
			monitors.OrderBy((MonitorWindowDisplay m) => m.Order);
			if (num > 0 && monitorWindowDisplay.Order + 1 < monitors.Count)
			{
				monitors.FirstOrDefault((MonitorWindowDisplay m) => m.Order == lastOrder + 1).Order = lastOrder;
				monitorWindowDisplay.Order = order;
				base.TriggerUpdate();
			}
			else if (monitorWindowDisplay.Order - 1 >= 0)
			{
				monitors.FirstOrDefault((MonitorWindowDisplay m) => m.Order == lastOrder - 1).Order = lastOrder;
				monitorWindowDisplay.Order = order;
				base.TriggerUpdate();
			}
		}

		[OnTrigger]
		private void OnUpdateMonitorWindow(string json)
		{
			if (string.IsNullOrEmpty(json))
			{
				return;
			}
			Dictionary<string, object> dictionary = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
			if (dictionary == null)
			{
				return;
			}
			string windowName = (string)dictionary["WindowName"];
			MonitorWindow monitorWindow = base.Model.Windows.FirstOrDefault((MonitorWindow w) => w.Name == windowName);
			if (monitorWindow != null)
			{
				WindowSize result2;
				if (dictionary.ContainsKey("Orientation") && Enum.TryParse<MeterOrientation>((string)dictionary["Orientation"], out var result))
				{
					monitorWindow.Orientation = result;
					base.TriggerUpdate();
				}
				else if (dictionary.ContainsKey("Size") && Enum.TryParse<WindowSize>((string)dictionary["Size"], out result2))
				{
					monitorWindow.Size = result2;
					base.TriggerUpdate();
				}
			}
		}

		private List<PluginToolbarChildItem> GetGooeeMenuItems()
		{
			return ((IEnumerable<MonitorWindow>)base.Model.Windows).Select((Func<MonitorWindow, PluginToolbarChildItem>)((MonitorWindow w) => new PluginToolbarChildItem
			{
				Label = ((w.Name == "Default") ? "UltimateMonitor.Menu.Default" : w.Name),
				OnClick = "OnToggleWindow",
				OnClickKey = w.Name,
				Icon = "window-maximize",
				IsFAIcon = true
			})).ToList();
		}

		[OnTrigger]
		private void OnToggleAddWindow()
		{
			base.Model.ShowAddWindow = !base.Model.ShowAddWindow;
			base.TriggerUpdate();
		}

		[OnTrigger]
		private void OnToggleWindow(string windowName)
		{
			if (!string.IsNullOrEmpty(windowName))
			{
				MonitorWindow monitorWindow = base.Model.Windows.FirstOrDefault((MonitorWindow w) => w.Name == windowName);
				if (monitorWindow != null)
				{
					monitorWindow.IsVisible = !monitorWindow.IsVisible;
					base.TriggerUpdate();
				}
			}
		}

		[OnTrigger]
		private void OnAddWindow(string windowName)
		{
			base.Model.ShowAddWindow = false;
			if (base.Model.Windows.Count((MonitorWindow w) => w.Name.ToLowerInvariant() == windowName.ToLowerInvariant()) == 0)
			{
				base.Model.Windows.Add(new MonitorWindow
				{
					Name = windowName,
					Monitors = new List<MonitorWindowDisplay>()
				});
				_config.Windows = base.Model.Windows;
				_config.Save();
				base.TriggerToolbarUpdate();
			}
			OnToggleWindow(windowName);
			base.TriggerUpdate();
		}

		[OnTrigger]
		private void OnRemoveWindow(string windowName)
		{
			base.Model.Windows.RemoveAll((MonitorWindow w) => w.Name.ToLowerInvariant() == windowName.ToLowerInvariant());
			_config.Windows = base.Model.Windows;
			_config.Save();
			base.TriggerToolbarUpdate();
			base.TriggerUpdate();
		}

		[OnTrigger]
		private void OnUpdateWindowPosition(string json)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(json))
			{
				return;
			}
			Dictionary<string, object> dictionary = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
			if (dictionary != null)
			{
				string windowName = (string)dictionary["windowName"];
				int num = (int)(long)dictionary["x"];
				int num2 = (int)(long)dictionary["y"];
				MonitorWindow monitorWindow = base.Model.Windows.FirstOrDefault((MonitorWindow w) => w.Name.ToLowerInvariant() == windowName.ToLowerInvariant());
				if (monitorWindow != null)
				{
					monitorWindow.Position = new Vector2Int(num, num2);
					_config.Windows = base.Model.Windows;
					_config.Save();
					base.TriggerUpdate();
				}
			}
		}
	}
	[ControllerTypes(new Type[] { typeof(UltimateMonitorController) })]
	[PluginToolbar(typeof(UltimateMonitorController), "UltimateMonitor.Resources.gooee-menu.json")]
	public class UltimateMonitorPlugin : IGooeePluginWithControllers, IGooeePlugin, IGooeeChangeLog, IGooeeLanguages, IGooeeStyleSheet
	{
		public string Name => "UltimateMonitor";

		public string Version => "1.3.0.0";

		public string ScriptResource => "UltimateMonitor.Resources.ui.js";

		public string ChangeLogResource => "UltimateMonitor.Resources.changelog.md";

		public string StyleResource => null;

		public IController[] Controllers { get; set; }

		public string LanguageResourceFolder => "UltimateMonitor.Resources.lang";
	}
	public class UltimateMonitorViewModel : Model
	{
		public List<MonitorItem> Items { get; set; }

		public List<MonitorWindow> Windows { get; set; }

		public bool ShowAddWindow { get; set; }
	}
	public class MonitorWindow
	{
		public string Name { get; set; }

		public bool IsVisible { get; set; }

		public List<MonitorWindowDisplay> Monitors { get; set; }

		public WindowSize Size { get; set; }

		public MeterOrientation Orientation { get; set; }

		public Vector2Int Position { get; set; }
	}
	public class MonitorWindowDisplay
	{
		public string MonitorItemName { get; set; }

		public int Order { get; set; }
	}
	public class MonitorItem
	{
		public string Name { get; set; }

		public string Icon { get; set; }

		public string Colour { get; set; }

		public MonitorItemType Type { get; set; }

		public ValueOperation ValueOperation { get; set; }

		public string[] ValueSubscriptions { get; set; }
	}
	public enum MonitorItemType
	{
		ProgressBar,
		Raw
	}
	public enum ValueOperation
	{
		None,
		Sum,
		Average,
		Mean,
		Min,
		Max,
		Variance,
		StandardDeviation,
		Custom
	}
	public enum MeterOrientation
	{
		Horizontal,
		Vertical
	}
	public enum WindowSize
	{
		Medium,
		ExtraSmall,
		Small,
		Large
	}
}
namespace UltimateMonitor.Systems
{
	public class UltimateMonitorDataSystem : GameSystemBase
	{
		private MonitoringData _data;

		private static FieldInfo m_Unemployed = typeof(CountEmploymentSystem).GetField("m_Unemployed", BindingFlags.Instance | BindingFlags.NonPublic);

		private static FieldInfo m_Adults = typeof(CountEmploymentSystem).GetField("m_Adults", BindingFlags.Instance | BindingFlags.NonPublic);

		private float _lastResultTick;

		private EntityQuery _homelessHouseholdsQuery;

		private EntityQuery _employeesQuery;

		private CountEmploymentSystem _countEmploymentSystem;

		private UnemploymentMonitorSystem _unemploymentSystem;

		public MonitoringData Data => _data;

		protected override void OnCreate()
		{
			((GameSystemBase)this).OnCreate();
			_countEmploymentSystem = ((ComponentSystemBase)this).World.GetOrCreateSystemManaged<CountEmploymentSystem>();
			_unemploymentSystem = ((ComponentSystemBase)this).World.GetOrCreateSystemManaged<UnemploymentMonitorSystem>();
			BuildEntityQueries();
		}

		protected override void OnUpdate()
		{
			if (Time.time >= _lastResultTick + 1f)
			{
				_lastResultTick = Time.time;
				UpdateData();
			}
		}

		private void BuildEntityQueries()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			EntityQueryDesc val = new EntityQueryDesc();
			val.All = (ComponentType[])(object)new ComponentType[2]
			{
				ComponentType.ReadOnly<Household>(),
				ComponentType.ReadOnly<HomelessHousehold>()
			};
			val.None = (ComponentType[])(object)new ComponentType[5]
			{
				ComponentType.ReadOnly<Deleted>(),
				ComponentType.ReadOnly<Destroyed>(),
				ComponentType.ReadOnly<Temp>(),
				ComponentType.ReadOnly<TouristHousehold>(),
				ComponentType.ReadOnly<CommuterHousehold>()
			};
			EntityQueryDesc val2 = val;
			val = new EntityQueryDesc();
			val.All = (ComponentType[])(object)new ComponentType[2]
			{
				ComponentType.ReadOnly<Employee>(),
				ComponentType.ReadOnly<Worker>()
			};
			val.None = (ComponentType[])(object)new ComponentType[3]
			{
				ComponentType.ReadOnly<Deleted>(),
				ComponentType.ReadOnly<Destroyed>(),
				ComponentType.ReadOnly<Temp>()
			};
			EntityQueryDesc val3 = val;
			_homelessHouseholdsQuery = ((ComponentSystemBase)this).GetEntityQuery((EntityQueryDesc[])(object)new EntityQueryDesc[1] { val2 });
			_employeesQuery = ((ComponentSystemBase)this).GetEntityQuery((EntityQueryDesc[])(object)new EntityQueryDesc[1] { val3 });
		}

		private void UpdateData()
		{
			//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_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)
			_data.HomelessHouseholds = ((EntityQuery)(ref _homelessHouseholdsQuery)).CalculateEntityCount();
			_data.UnderEmployed = _unemploymentSystem.GetUnderemployedCount();
			_data.Employable = ((NativeValue<int>)m_Adults.GetValue(_countEmploymentSystem)).value;
			_data.Unemployed = ((NativeValue<int>)m_Unemployed.GetValue(_countEmploymentSystem)).value;
		}
	}
	public class UnemploymentMonitorSystem : GameSystemBase
	{
		[BurstCompile]
		private struct CalculateUnderemploymentJob : IJobChunk
		{
			public EntityTypeHandle m_EntityType;

			public ComponentTypeHandle<Worker> m_WorkerType;

			public ComponentTypeHandle<Citizen> m_CitizenType;

			[ReadOnly]
			public ComponentLookup<Worker> m_Workers;

			[ReadOnly]
			public ComponentLookup<Citizen> m_Citizens;

			public ComponentLookup<UnderemployedWorker> m_UnderemployedWorkers;

			[ReadOnly]
			public SharedComponentTypeHandle<UpdateFrame> m_UpdateFrameType;

			public uint m_UpdateFrameIndex;

			public ParallelWriter m_CommandBuffer;

			public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
			{
				//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)
				//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_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
				if (((ArchetypeChunk)(ref chunk)).GetSharedComponent<UpdateFrame>(m_UpdateFrameType).m_Index != m_UpdateFrameIndex)
				{
					return;
				}
				NativeArray<Entity> nativeArray = ((ArchetypeChunk)(ref chunk)).GetNativeArray(m_EntityType);
				NativeArray<Worker> nativeArray2 = ((ArchetypeChunk)(ref chunk)).GetNativeArray<Worker>(ref m_WorkerType);
				NativeArray<Citizen> nativeArray3 = ((ArchetypeChunk)(ref chunk)).GetNativeArray<Citizen>(ref m_CitizenType);
				for (int i = 0; i < nativeArray.Length; i++)
				{
					Entity val = nativeArray[i];
					Worker val2 = nativeArray2[i];
					Citizen val3 = nativeArray3[i];
					if (((Citizen)(ref val3)).GetEducationLevel() > val2.m_Level)
					{
						((ParallelWriter)(ref m_CommandBuffer)).AddComponent<UnderemployedWorker>(unfilteredChunkIndex, val, new UnderemployedWorker
						{
							m_EducationLevel = ((Citizen)(ref val3)).GetEducationLevel(),
							m_JobLevel = val2.m_Level
						});
					}
					else if (m_UnderemployedWorkers.HasComponent(val))
					{
						((ParallelWriter)(ref m_CommandBuffer)).RemoveComponent<UnderemployedWorker>(unfilteredChunkIndex, val);
					}
				}
			}

			void IJobChunk.Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
			{
				Execute(in chunk, unfilteredChunkIndex, useEnabledMask, in chunkEnabledMask);
			}
		}

		private struct TypeHandle
		{
			public EntityTypeHandle __Unity_Entities_Entity_TypeHandle;

			[ReadOnly]
			public ComponentTypeHandle<Citizen> __Game_Citizens_Citizen_RO_ComponentTypeHandle;

			[ReadOnly]
			public ComponentTypeHandle<Worker> __Game_Citizens_Worker_RO_ComponentTypeHandle;

			[ReadOnly]
			public ComponentLookup<Worker> __Game_Citizens_Worker_RO_ComponentLookup;

			[ReadOnly]
			public ComponentLookup<Citizen> __Game_Citizens_Citizen_RO_ComponentLookup;

			public ComponentLookup<UnderemployedWorker> __UnemploymentMonitor_UnderemployedWorker_RW_ComponentLookup;

			public SharedComponentTypeHandle<UpdateFrame> __Game_Simulation_UpdateFrame_SharedComponentTypeHandle;

			[MethodImpl(MethodImplOptions.AggressiveInlining)]
			public void __AssignHandles(ref SystemState state)
			{
				//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)
				//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_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_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: 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)
				__Unity_Entities_Entity_TypeHandle = ((SystemState)(ref state)).GetEntityTypeHandle();
				__Game_Citizens_Citizen_RO_ComponentTypeHandle = ((SystemState)(ref state)).GetComponentTypeHandle<Citizen>(true);
				__Game_Citizens_Worker_RO_ComponentTypeHandle = ((SystemState)(ref state)).GetComponentTypeHandle<Worker>(true);
				__Game_Citizens_Worker_RO_ComponentLookup = ((SystemState)(ref state)).GetComponentLookup<Worker>(true);
				__Game_Citizens_Citizen_RO_ComponentLookup = ((SystemState)(ref state)).GetComponentLookup<Citizen>(true);
				__UnemploymentMonitor_UnderemployedWorker_RW_ComponentLookup = ((SystemState)(ref state)).GetComponentLookup<UnderemployedWorker>(false);
				__Game_Simulation_UpdateFrame_SharedComponentTypeHandle = ((SystemState)(ref state)).GetSharedComponentTypeHandle<UpdateFrame>();
			}
		}

		private EntityQuery m_CreatedGroup;

		private ManualLogSource logger = new ManualLogSource("UnderemploymentSystem");

		public static readonly int kUpdatesPerDay = 16;

		private EndFrameBarrier m_EndFrameBarrier;

		private SimulationSystem m_SimulationSystem;

		private TypeHandle __TypeHandle;

		public int GetUnderemployedCount()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//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_0027: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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)
			EntityQueryDesc val = new EntityQueryDesc();
			val.All = (ComponentType[])(object)new ComponentType[1] { ComponentType.ReadOnly<UnderemployedWorker>() };
			val.None = (ComponentType[])(object)new ComponentType[3]
			{
				ComponentType.ReadOnly<Deleted>(),
				ComponentType.ReadOnly<Destroyed>(),
				ComponentType.ReadOnly<Temp>()
			};
			EntityQueryDesc val2 = val;
			EntityQuery entityQuery = ((ComponentSystemBase)this).GetEntityQuery((EntityQueryDesc[])(object)new EntityQueryDesc[1] { val2 });
			return ((EntityQuery)(ref entityQuery)).CalculateEntityCount();
		}

		public override int GetUpdateInterval(SystemUpdatePhase phase)
		{
			return 262144 / (kUpdatesPerDay * 16);
		}

		[Preserve]
		protected override void OnCreate()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//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_0053: 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_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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			((GameSystemBase)this).OnCreate();
			Logger.Sources.Add((ILogSource)(object)logger);
			m_EndFrameBarrier = ((ComponentSystemBase)this).World.GetOrCreateSystemManaged<EndFrameBarrier>();
			m_SimulationSystem = ((ComponentSystemBase)this).World.GetOrCreateSystemManaged<SimulationSystem>();
			EntityQueryDesc val = new EntityQueryDesc();
			val.All = (ComponentType[])(object)new ComponentType[2]
			{
				ComponentType.ReadOnly<Worker>(),
				ComponentType.ReadOnly<Citizen>()
			};
			val.None = (ComponentType[])(object)new ComponentType[3]
			{
				ComponentType.ReadOnly<Deleted>(),
				ComponentType.ReadOnly<Destroyed>(),
				ComponentType.ReadOnly<Temp>()
			};
			EntityQueryDesc val2 = val;
			m_CreatedGroup = ((ComponentSystemBase)this).GetEntityQuery((EntityQueryDesc[])(object)new EntityQueryDesc[1] { val2 });
			((ComponentSystemBase)this).RequireForUpdate(m_CreatedGroup);
		}

		protected override void OnCreateForCompiler()
		{
			((ComponentSystemBase)this).OnCreateForCompiler();
			__AssignQueries(ref ((SystemBase)this).CheckedStateRef);
			__TypeHandle.__AssignHandles(ref ((SystemBase)this).CheckedStateRef);
		}

		[Preserve]
		protected override void OnUpdate()
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_00a4: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			uint updateFrame = SimulationUtils.GetUpdateFrame(m_SimulationSystem.frameIndex, kUpdatesPerDay, 16);
			__TypeHandle.__Game_Citizens_Citizen_RO_ComponentLookup.Update(ref ((SystemBase)this).CheckedStateRef);
			__TypeHandle.__Game_Citizens_Worker_RO_ComponentLookup.Update(ref ((SystemBase)this).CheckedStateRef);
			__TypeHandle.__UnemploymentMonitor_UnderemployedWorker_RW_ComponentLookup.Update(ref ((SystemBase)this).CheckedStateRef);
			((EntityTypeHandle)(ref __TypeHandle.__Unity_Entities_Entity_TypeHandle)).Update(ref ((SystemBase)this).CheckedStateRef);
			CalculateUnderemploymentJob calculateUnderemploymentJob = default(CalculateUnderemploymentJob);
			calculateUnderemploymentJob.m_Citizens = __TypeHandle.__Game_Citizens_Citizen_RO_ComponentLookup;
			calculateUnderemploymentJob.m_Workers = __TypeHandle.__Game_Citizens_Worker_RO_ComponentLookup;
			calculateUnderemploymentJob.m_EntityType = __TypeHandle.__Unity_Entities_Entity_TypeHandle;
			calculateUnderemploymentJob.m_CitizenType = __TypeHandle.__Game_Citizens_Citizen_RO_ComponentTypeHandle;
			calculateUnderemploymentJob.m_WorkerType = __TypeHandle.__Game_Citizens_Worker_RO_ComponentTypeHandle;
			calculateUnderemploymentJob.m_UnderemployedWorkers = __TypeHandle.__UnemploymentMonitor_UnderemployedWorker_RW_ComponentLookup;
			EntityCommandBuffer val = ((SafeCommandBufferSystem)m_EndFrameBarrier).CreateCommandBuffer();
			calculateUnderemploymentJob.m_CommandBuffer = ((EntityCommandBuffer)(ref val)).AsParallelWriter();
			calculateUnderemploymentJob.m_UpdateFrameIndex = updateFrame;
			calculateUnderemploymentJob.m_UpdateFrameType = __TypeHandle.__Game_Simulation_UpdateFrame_SharedComponentTypeHandle;
			((SystemBase)this).Dependency = JobChunkExtensions.ScheduleParallel<CalculateUnderemploymentJob>(calculateUnderemploymentJob, m_CreatedGroup, ((SystemBase)this).Dependency);
		}

		[Preserve]
		protected override void OnDestroy()
		{
			((GameSystemBase)this).OnDestroy();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private void __AssignQueries(ref SystemState state)
		{
		}

		[Preserve]
		public UnemploymentMonitorSystem()
		{
		}//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Expected O, but got Unknown

	}
}
namespace UltimateMonitor.Data
{
	public struct MonitoringData
	{
		public int HomelessHouseholds { get; set; }

		public int UnderEmployed { get; set; }

		public int Employable { get; set; }

		public int Unemployed { get; set; }
	}
}
namespace UltimateMonitor.Configuration
{
	public abstract class ConfigBase
	{
		public static readonly string MOD_PATH = Path.Combine(Application.persistentDataPath, "Mods", "UltimateMonitor");

		private static readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings
		{
			NullValueHandling = (NullValueHandling)1,
			Formatting = (Formatting)1
		};

		public static Action OnUpdated;

		protected abstract string ConfigFileName { get; }

		public virtual void Save()
		{
			string contents = JsonConvert.SerializeObject((object)this, _serializerSettings);
			Directory.CreateDirectory(MOD_PATH);
			File.WriteAllText(Path.Combine(MOD_PATH, ConfigFileName), contents);
			OnUpdated?.Invoke();
		}

		public static T Load<T>(bool useDefaultAsTemplate = true) where T : ConfigBase, new()
		{
			T val = new T();
			Directory.CreateDirectory(MOD_PATH);
			string path = Path.Combine(MOD_PATH, val.ConfigFileName);
			string text = "";
			if (File.Exists(path))
			{
				text = File.ReadAllText(path);
			}
			else
			{
				if (!useDefaultAsTemplate)
				{
					return new T();
				}
				text = LoadDefaultAndSave<T>();
			}
			return (T)JsonConvert.DeserializeObject(text, typeof(T), _serializerSettings);
		}

		public static T LoadDefault<T>() where T : ConfigBase, new()
		{
			return new T();
		}

		private static string LoadDefaultAndSave<T>() where T : ConfigBase, new()
		{
			T val = new T();
			Directory.CreateDirectory(MOD_PATH);
			string path = Path.Combine(MOD_PATH, val.ConfigFileName);
			string text = JsonConvert.SerializeObject((object)val, _serializerSettings);
			File.WriteAllText(path, text);
			return text;
		}

		private static string UppercaseFirst(string s)
		{
			if (string.IsNullOrEmpty(s))
			{
				return string.Empty;
			}
			return char.ToUpper(s[0]) + s.Substring(1);
		}
	}
	public class UltimateMonitorConfig : ConfigBase
	{
		public List<MonitorWindow> Windows { get; set; }

		protected override string ConfigFileName => "config.json";

		public static UltimateMonitorConfig Load()
		{
			return ConfigBase.Load<UltimateMonitorConfig>();
		}
	}
}
namespace UltimateMonitor.ComponentTypes
{
	public struct UnderemployedWorker : IComponentData, IQueryTypeParameter, ISerializable
	{
		public int m_EducationLevel;

		public int m_JobLevel;

		public UnderemployedWorker(int educationLevel, int jobLevel)
		{
			m_EducationLevel = educationLevel;
			m_JobLevel = jobLevel;
		}

		public void Deserialize<TReader>(TReader reader) where TReader : IReader
		{
			((IReader)reader).Read(ref m_EducationLevel);
			((IReader)reader).Read(ref m_JobLevel);
		}

		public void Serialize<TWriter>(TWriter writer) where TWriter : IWriter
		{
			((IWriter)writer).Write(m_EducationLevel);
			((IWriter)writer).Write(m_JobLevel);
		}
	}
}