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);
}
}
}