Decompiled source of CitiesV2 v0.1.4

CitiesV2.dll

Decompiled a day 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 System.Text.Json;
using System.Text.Json.Serialization;
using AssetBundleLoader;
using BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem.Collections;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using ObjectLoader;
using SOD.Common.BepInEx;
using SOD.Common.Extensions;
using UnityEngine;
using UniverseLib;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("CitiesV2")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+7c267528a4ff8da9463e2b7def45b3e6b9de9486")]
[assembly: AssemblyProduct("CitiesV2")]
[assembly: AssemblyTitle("CitiesV2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
public class LoaderMethods : CitiesV2
{
	public static void ReplaceFloorData(List<string> replacementFloors, string targetBuilding, int targetFloorSetting, int floorsAmount)
	{
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Expected O, but got Unknown
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Expected O, but got Unknown
		InteriorFloorSetting val = null;
		string path = Path.Combine(CitiesV2.dir, "Floorplans\\");
		Enumerator<BuildingPreset> enumerator = AssetLoader.Instance.allBuildingData.GetEnumerator();
		bool flag = default(bool);
		while (enumerator.MoveNext())
		{
			BuildingPreset current = enumerator.Current;
			if (((Object)current).name.ToLower() == targetBuilding.ToLower())
			{
				val = current.floorLayouts[targetFloorSetting];
				ManualLogSource log = PluginController<CitiesV2, IEmptyBindings>.Log;
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(37, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Found target building: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(targetBuilding);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" at setting: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(targetFloorSetting);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
				}
				log.LogInfo(val2);
				break;
			}
		}
		if (val == null)
		{
			return;
		}
		val.blueprints.Clear();
		val.floorsWithThisSetting = floorsAmount;
		foreach (string replacementFloor in replacementFloors)
		{
			val.blueprints.Add(new TextAsset(File.ReadAllText(Path.Combine(path, replacementFloor + ".json"))));
			((Object)val.blueprints[replacementFloors.IndexOf(replacementFloor)]).name = replacementFloor;
			CityData.Instance.floorData.Add(replacementFloor, JsonUtility.FromJson<FloorSaveData>(File.ReadAllText(Path.Combine(path, replacementFloor + ".json"))));
		}
	}
}
public class FloorLoaderConfig
{
	public List<string>? floorNames { get; set; }

	public string? targetBuilding { get; set; }

	public int targetFloorConfig { get; set; }

	public int floorsAmount { get; set; }
}
public class FloorLoader : CitiesV2
{
	public static Dictionary<string, FloorSaveData> floorSaveDatas = new Dictionary<string, FloorSaveData>();

	public static void Postfix()
	{
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Expected O, but got Unknown
		bool flag2 = default(bool);
		foreach (FloorLoaderConfig floorLoaderConfig in CitiesV2.floorLoaderConfigs)
		{
			string path = Path.Combine(CitiesV2.dir, "Floorplans\\");
			bool flag = true;
			foreach (string floorName in floorLoaderConfig.floorNames)
			{
				if (!File.Exists(Path.Combine(path, floorName + ".json")))
				{
					flag = false;
					break;
				}
			}
			if (flag)
			{
				LoaderMethods.ReplaceFloorData(floorLoaderConfig.floorNames, floorLoaderConfig.targetBuilding, floorLoaderConfig.targetFloorConfig, floorLoaderConfig.floorsAmount);
				ManualLogSource log = PluginController<CitiesV2, IEmptyBindings>.Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(50, 3, ref flag2);
				if (flag2)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Replaced floor data for ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(floorLoaderConfig.targetBuilding);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" at setting ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(floorLoaderConfig.targetFloorConfig);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" with ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(floorLoaderConfig.floorNames.Count);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" floors.");
				}
				log.LogInfo(val);
			}
		}
	}
}
[HarmonyPatch(typeof(Toolbox), "Start")]
public class BuildingLoader : CitiesV2
{
	public static List<BuildingManifest> buildings = new List<BuildingManifest>();

	public static List<AssetBundle> bundles = new List<AssetBundle>();

	public static List<string> loaded = new List<string>();

	public static void Postfix()
	{
		RoomLoader.LoadAll();
		foreach (KeyValuePair<string, BuildingManifestBase> buildingManifest2 in CitiesV2.buildingManifests)
		{
			if (loaded.Contains(buildingManifest2.Key))
			{
				return;
			}
			BuildingManifest buildingManifest = LoadBuilding(buildingManifest2.Value, CitiesV2.dir, buildingManifest2.Key);
			if (buildingManifest == null)
			{
				continue;
			}
			buildings.Add(buildingManifest);
			PluginController<CitiesV2, IEmptyBindings>.Log.LogInfo((object)"Buildings have been cached");
			foreach (Stairfix stairfix in buildingManifest2.Value.Stairfixes)
			{
				StairwellFix.toRun.Add(stairfix);
			}
			PluginController<CitiesV2, IEmptyBindings>.Log.LogInfo((object)"Stairfixes have been added.");
		}
		Enumerator<string, ScriptableObject> enumerator3 = Toolbox.Instance.resourcesCache[Il2CppType.Of<RoomConfiguration>()].Values.GetEnumerator();
		while (enumerator3.MoveNext())
		{
			Enumerator<WallFrontage> enumerator4 = ((Il2CppObjectBase)enumerator3.Current).Cast<RoomConfiguration>().wallFrontage.GetEnumerator();
			while (enumerator4.MoveNext())
			{
				WallFrontage current3 = enumerator4.Current;
				current3.onlyIfBorderingOutside = true;
				Enumerator<WallFrontageClass> enumerator5 = current3.insideFrontage.GetEnumerator();
				while (enumerator5.MoveNext())
				{
					WallFrontageClass current4 = enumerator5.Current;
					current3.outsideFrontage.Add(current4);
				}
				enumerator5 = current3.outsideFrontage.GetEnumerator();
				while (enumerator5.MoveNext())
				{
					WallFrontageClass current5 = enumerator5.Current;
					if (!current3.insideFrontage.Contains(current5))
					{
						current3.insideFrontage.Add(current5);
					}
				}
			}
		}
		Enumerator<FurnitureCluster> enumerator6 = Toolbox.Instance.allFurnitureClusters.GetEnumerator();
		while (enumerator6.MoveNext())
		{
			FurnitureCluster current6 = enumerator6.Current;
			current6.limitToFloor = false;
			current6.limitToFloorRange = false;
			current6.allowedInOpenPlan = (AllowedOpenPlan)0;
		}
		enumerator3 = Toolbox.Instance.resourcesCache[Il2CppType.Of<FurnitureClass>()].Values.GetEnumerator();
		while (enumerator3.MoveNext())
		{
			ScriptableObject current7 = enumerator3.Current;
			((Il2CppObjectBase)current7).Cast<FurnitureClass>().limitToFloor = false;
			((Il2CppObjectBase)current7).Cast<FurnitureClass>().limitToFloorRange = false;
			((Il2CppObjectBase)current7).Cast<FurnitureClass>().requiresCeiling = false;
		}
		Enumerator<AddressPreset> enumerator7 = Toolbox.Instance.allAddressPresets.GetEnumerator();
		while (enumerator7.MoveNext())
		{
			AddressPreset current8 = enumerator7.Current;
			if (((Object)current8).name == "SyncClinic")
			{
				current8.baseScore = 1;
			}
		}
		FloorLoader.Postfix();
		FloorRegistration.Postfix();
		PluginController<CitiesV2, IEmptyBindings>.Log.LogInfo((object)"Everything went according to plan");
	}

	public static BuildingManifest LoadBuilding(BuildingManifestBase manifest, string baseDir, string extraDir)
	{
		BuildingManifestBase manifest2 = manifest;
		if (manifest2.hasBeenAdded)
		{
			return null;
		}
		Loader.TempChangePath(Path.Combine(baseDir, extraDir));
		BuildingManifest buildingManifest = new BuildingManifest();
		buildingManifest.preset = Loader.LoadFromJson<BuildingPreset>(Path.Combine(baseDir, extraDir, manifest2.BuildingPresetSO));
		buildingManifest.assetBundle = BundleLoader.LoadBundle(Path.Combine(baseDir, extraDir, manifest2.BuildingAssetBundle), false, false);
		bundles.Add(buildingManifest.assetBundle);
		List<Object> list = buildingManifest.assetBundle.LoadAllAssets().ToList();
		BuildingPreset preset = buildingManifest.preset;
		buildingManifest.baseTexture = ((Il2CppObjectBase)list.Find((Object x) => x.name == manifest2.BuildingTexture)).Cast<Texture2D>();
		buildingManifest.windowMap = ((Il2CppObjectBase)list.Find((Object x) => x.name == manifest2.BuildingWindowMap)).Cast<Texture2D>();
		buildingManifest.addonMap = ((Il2CppObjectBase)list.Find((Object x) => x.name == manifest2.BuildingAddonMap)).Cast<Texture2D>();
		buildingManifest.litMap = ((Il2CppObjectBase)list.Find((Object x) => x.name == manifest2.BuildingLitMap)).Cast<Texture2D>();
		buildingManifest.unlitMap = ((Il2CppObjectBase)list.Find((Object x) => x.name == manifest2.BuildingUnlitMap)).Cast<Texture2D>();
		buildingManifest.prefab = ((Il2CppObjectBase)list.Find((Object x) => x.name == manifest2.BuildingPrefab)).Cast<GameObject>();
		buildingManifest.posOffset = manifest2.PosOffset;
		preset.addonMap = buildingManifest.addonMap;
		preset.windowMap = buildingManifest.windowMap;
		preset.emissionMapLit = buildingManifest.litMap;
		preset.emissionMapUnlit = buildingManifest.unlitMap;
		preset.prefab = buildingManifest.prefab;
		preset.tex = buildingManifest.baseTexture;
		preset.captureMesh = ((Component)preset.prefab.transform.Find("Base")).GetComponent<MeshFilter>().sharedMesh;
		Material material = ((Renderer)((Component)preset.prefab.transform.Find("Base")).GetComponent<MeshRenderer>()).material;
		Material material2 = ((Renderer)((Component)((Il2CppObjectBase)Helpers.GetScriptableObject("OneFIfthAve", typeof(BuildingPreset))).Cast<BuildingPreset>().prefab.transform.Find("Base")).GetComponent<MeshRenderer>()).material;
		material.shader = material2.shader;
		((Object)preset.prefab).hideFlags = (HideFlags)32;
		((Object)preset).hideFlags = (HideFlags)32;
		preset.prefab.tag = "BuildingModel";
		((Object)preset).name = ((SoCustomComparison)preset).presetName;
		preset.CalculateMeshHeight();
		IEnumerator enumerator = preset.prefab.transform.GetEnumerator();
		try
		{
			while (enumerator.MoveNext())
			{
				Transform val = ((Il2CppObjectBase)enumerator.Current).Cast<Transform>();
				if (((Object)val).name.Contains("Base"))
				{
					((Component)val).tag = "BuildingModelLights";
					((Component)val).gameObject.layer = 27;
				}
			}
		}
		finally
		{
			if (enumerator is IDisposable disposable)
			{
				disposable.Dispose();
			}
		}
		if (File.Exists(Path.Combine(baseDir, extraDir, manifest2.CompiledWindowMap)))
		{
			preset.sortedWindows = WindowFloorPatch.Unpack(JsonSerializer.Deserialize<List<WindowFloorPatch>>(File.ReadAllText(Path.Combine(baseDir, extraDir, manifest2.CompiledWindowMap))));
		}
		if (preset.sortedWindows == null && (Object)(object)preset.windowMap != (Object)null)
		{
			preset.sortedWindows = new List<WindowUVFloor>();
			preset.GenerateWindowData();
			File.WriteAllText(Path.Combine(baseDir, extraDir, manifest2.CompiledWindowMap), JsonSerializer.Serialize(WindowFloorPatch.GeneratePatched(preset.sortedWindows), CitiesV2.serializerOptions));
		}
		if (File.Exists(Path.Combine(baseDir, extraDir, manifest2.CompiledAddonMap)))
		{
			preset.cableLinkPoints = EnumerableExtensions.ToListIl2Cpp<CableLinkPoint>((IEnumerable<CableLinkPoint>)JsonSerializer.Deserialize<List<CableLinkPoint>>(File.ReadAllText(Path.Combine(baseDir, extraDir, manifest2.CompiledAddonMap)), CitiesV2.serializerOptions));
		}
		if ((preset.cableLinkPoints == null || preset.cableLinkPoints.Count == 0) && (Object)(object)preset.addonMap != (Object)null)
		{
			preset.GenerateAddonData();
			File.WriteAllText(Path.Combine(baseDir, extraDir, manifest2.CompiledAddonMap), JsonSerializer.Serialize(EnumerableExtensions.ToList<CableLinkPoint>(preset.cableLinkPoints), CitiesV2.serializerOptions));
		}
		Loader.RevertPath();
		AssetLoader.Instance.allBuildingData.Add(preset);
		return buildingManifest;
	}
}
[Serializable]
public class WindowFloorPatch
{
	[Serializable]
	public class WindowBlockPatch
	{
		public float OriginPixelX { get; set; }

		public float OriginPixelY { get; set; }

		public float RectSizeX { get; set; }

		public float RectSizeY { get; set; }

		public float CentrePixelX { get; set; }

		public float CentrePixelY { get; set; }

		public float LocalMeshPositionLeftX { get; set; }

		public float LocalMeshPositionLeftY { get; set; }

		public float LocalMeshPositionLeftZ { get; set; }

		public float LocalMeshPositionRightX { get; set; }

		public float LocalMeshPositionRightY { get; set; }

		public float LocalMeshPositionRightZ { get; set; }

		public int Floor { get; set; }

		public float SideX { get; set; }

		public float SideY { get; set; }

		public int Horizonal { get; set; }
	}

	public List<WindowBlockPatch> Back { get; set; }

	public List<WindowBlockPatch> Front { get; set; }

	public List<WindowBlockPatch> Left { get; set; }

	public List<WindowBlockPatch> Right { get; set; }

	public static List<WindowFloorPatch> GeneratePatched(List<WindowUVFloor> original)
	{
		List<WindowFloorPatch> list = new List<WindowFloorPatch>();
		Enumerator<WindowUVFloor> enumerator = original.GetEnumerator();
		while (enumerator.MoveNext())
		{
			WindowUVFloor current = enumerator.Current;
			WindowFloorPatch windowFloorPatch = new WindowFloorPatch();
			windowFloorPatch.Left = new List<WindowBlockPatch>();
			windowFloorPatch.Right = new List<WindowBlockPatch>();
			windowFloorPatch.Front = new List<WindowBlockPatch>();
			windowFloorPatch.Back = new List<WindowBlockPatch>();
			Enumerator<WindowUVBlock> enumerator2 = current.back.GetEnumerator();
			while (enumerator2.MoveNext())
			{
				WindowUVBlock current2 = enumerator2.Current;
				int floor = current2.floor;
				current2.floor = floor + 1;
				windowFloorPatch.Back.Add(GeneratePatched(current2));
			}
			enumerator2 = current.front.GetEnumerator();
			while (enumerator2.MoveNext())
			{
				WindowUVBlock current3 = enumerator2.Current;
				int floor = current3.floor;
				current3.floor = floor + 1;
				windowFloorPatch.Front.Add(GeneratePatched(current3));
			}
			enumerator2 = current.right.GetEnumerator();
			while (enumerator2.MoveNext())
			{
				WindowUVBlock current4 = enumerator2.Current;
				int floor = current4.floor;
				current4.floor = floor + 1;
				windowFloorPatch.Right.Add(GeneratePatched(current4));
			}
			enumerator2 = current.left.GetEnumerator();
			while (enumerator2.MoveNext())
			{
				WindowUVBlock current5 = enumerator2.Current;
				int floor = current5.floor;
				current5.floor = floor + 1;
				windowFloorPatch.Left.Add(GeneratePatched(current5));
			}
			list.Add(windowFloorPatch);
		}
		return list;
	}

	public static List<WindowUVFloor> Unpack(List<WindowFloorPatch> patched)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		List<WindowUVFloor> val = new List<WindowUVFloor>();
		foreach (WindowFloorPatch item in patched)
		{
			WindowUVFloor val2 = new WindowUVFloor();
			val2.left = new List<WindowUVBlock>();
			val2.right = new List<WindowUVBlock>();
			val2.front = new List<WindowUVBlock>();
			val2.back = new List<WindowUVBlock>();
			foreach (WindowBlockPatch item2 in item.Left)
			{
				val2.left.Add(Unpack(item2));
			}
			foreach (WindowBlockPatch item3 in item.Right)
			{
				val2.right.Add(Unpack(item3));
			}
			foreach (WindowBlockPatch item4 in item.Front)
			{
				val2.front.Add(Unpack(item4));
			}
			foreach (WindowBlockPatch item5 in item.Back)
			{
				val2.back.Add(Unpack(item5));
			}
			val.Add(val2);
		}
		return val;
	}

	public static WindowBlockPatch GeneratePatched(WindowUVBlock src)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: 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_003a: 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_005c: 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_007e: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: 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)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		return new WindowBlockPatch
		{
			OriginPixelX = src.originPixel.x,
			OriginPixelY = src.originPixel.y,
			RectSizeX = src.rectSize.x,
			RectSizeY = src.rectSize.y,
			CentrePixelX = src.centrePixel.x,
			CentrePixelY = src.centrePixel.y,
			LocalMeshPositionLeftX = src.localMeshPositionLeft.x,
			LocalMeshPositionLeftY = src.localMeshPositionLeft.y,
			LocalMeshPositionLeftZ = src.localMeshPositionLeft.z,
			LocalMeshPositionRightX = src.localMeshPositionRight.x,
			LocalMeshPositionRightY = src.localMeshPositionRight.y,
			LocalMeshPositionRightZ = src.localMeshPositionRight.z,
			Floor = src.floor,
			SideX = src.side.x,
			SideY = src.side.y,
			Horizonal = src.horizonal
		};
	}

	public static WindowUVBlock Unpack(WindowBlockPatch src)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: 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_0029: 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_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: 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_00b4: Expected O, but got Unknown
		return new WindowUVBlock
		{
			originPixel = new Vector2(src.OriginPixelX, src.OriginPixelY),
			rectSize = new Vector2(src.RectSizeX, src.RectSizeY),
			centrePixel = new Vector2(src.CentrePixelX, src.CentrePixelY),
			localMeshPositionLeft = new Vector3(src.LocalMeshPositionLeftX, src.LocalMeshPositionLeftY, src.LocalMeshPositionLeftZ),
			localMeshPositionRight = new Vector3(src.LocalMeshPositionRightX, src.LocalMeshPositionRightY, src.LocalMeshPositionRightZ),
			floor = src.Floor,
			side = new Vector2(src.SideX, src.SideY),
			horizonal = src.Horizonal
		};
	}
}
[Serializable]
public class BuildingManifestBase
{
	[JsonIgnore]
	public bool hasBeenAdded;

	public string BuildingPresetSO { get; set; }

	public string BuildingAssetBundle { get; set; }

	public string BuildingPrefab { get; set; }

	public string BuildingTexture { get; set; }

	public string BuildingUnlitMap { get; set; }

	public string BuildingLitMap { get; set; }

	public string? BuildingWindowMap { get; set; }

	public string? BuildingAddonMap { get; set; }

	public float PosOffset { get; set; }

	public string? CompiledWindowMap { get; set; }

	public string? CompiledAddonMap { get; set; }

	public List<Stairfix> Stairfixes { get; set; }
}
public class BuildingManifest
{
	public BuildingPreset? preset;

	public AssetBundle? assetBundle;

	public GameObject? prefab;

	public Texture2D? baseTexture;

	public Texture2D? unlitMap;

	public Texture2D? litMap;

	public Texture2D? windowMap;

	public Texture2D? addonMap;

	public float posOffset;

	public List<Stairfix>? Stairfixes;

	public BuildingManifestBase? baseManifest;
}
[BepInPlugin("truedartt.citiesv2", "CitiesV2", "0.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class CitiesV2 : PluginController<CitiesV2>
{
	public const string PluginGUID = "truedartt.citiesv2";

	public const string PluginName = "CitiesV2";

	public const string PluginVersion = "0.1.0";

	protected static JsonSerializerOptions serializerOptions = new JsonSerializerOptions
	{
		AllowTrailingCommas = true,
		WriteIndented = true,
		MaxDepth = 256
	};

	protected static string dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

	protected static List<FloorLoaderConfig> floorLoaderConfigs = new List<FloorLoaderConfig>();

	public static readonly Dictionary<string, BuildingManifestBase> buildingManifests = new Dictionary<string, BuildingManifestBase>();

	public static readonly Dictionary<string, string> rooms = new Dictionary<string, string>();

	public override void Load()
	{
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Expected O, but got Unknown
		PluginController<CitiesV2, IEmptyBindings>.Log.LogInfo((object)Path.Combine(dir, "LoaderConfigs.json"));
		try
		{
			floorLoaderConfigs = JsonSerializer.Deserialize<List<FloorLoaderConfig>>(File.ReadAllText(Path.Combine(dir, "LoaderConfigs.json")), serializerOptions);
		}
		catch (Exception ex)
		{
			PluginController<CitiesV2, IEmptyBindings>.Log.LogError((object)ex);
		}
		try
		{
			buildingManifests.Add("DartTower", JsonSerializer.Deserialize<BuildingManifestBase>(File.ReadAllText(Path.Combine(dir, "DartTower", "DartTower_manifest.json"))));
		}
		catch (Exception ex2)
		{
			PluginController<CitiesV2, IEmptyBindings>.Log.LogError((object)ex2);
		}
		Loader.SetPath(dir);
		rooms.Add("Terrace", Path.Combine(dir, "RoomConfigs"));
		((PluginController<CitiesV2, IEmptyBindings>)(object)this).Harmony.PatchAll(Assembly.GetExecutingAssembly());
		ManualLogSource log = PluginController<CitiesV2, IEmptyBindings>.Log;
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(18, 1, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Plugin ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("CitiesV2");
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" is loaded!");
		}
		log.LogInfo(val);
	}
}
public class FloorRegistration : CitiesV2
{
	public static void Postfix()
	{
		PluginController<CitiesV2, IEmptyBindings>.Log.LogMessage((object)"Floor registration has begun.");
		Dictionary<string, FloorSaveData> floorData = CityData.Instance.floorData;
		foreach (BuildingManifest building in BuildingLoader.buildings)
		{
			Enumerator<InteriorFloorSetting> enumerator2 = building.preset.floorLayouts.GetEnumerator();
			while (enumerator2.MoveNext())
			{
				InteriorFloorSetting current2 = enumerator2.Current;
				Enumerator<TextAsset> enumerator3 = current2.blueprints.GetEnumerator();
				while (enumerator3.MoveNext())
				{
					TextAsset current3 = enumerator3.Current;
					if (!floorData.ContainsKey(((Object)current3).name))
					{
						floorData.Add(((Object)current3).name, Loader.LoadObject<FloorSaveData>(current3.text));
					}
				}
				enumerator3 = current2.controlRoomVariants.GetEnumerator();
				while (enumerator3.MoveNext())
				{
					TextAsset current4 = enumerator3.Current;
					if (!floorData.ContainsKey(((Object)current4).name))
					{
						floorData.Add(((Object)current4).name, Loader.LoadObject<FloorSaveData>(current4.text));
					}
				}
			}
			enumerator2 = building.preset.basementLayouts.GetEnumerator();
			while (enumerator2.MoveNext())
			{
				InteriorFloorSetting current5 = enumerator2.Current;
				Enumerator<TextAsset> enumerator3 = current5.blueprints.GetEnumerator();
				while (enumerator3.MoveNext())
				{
					TextAsset current6 = enumerator3.Current;
					if (!floorData.ContainsKey(((Object)current6).name))
					{
						floorData.Add(((Object)current6).name, Loader.LoadObject<FloorSaveData>(current6.text));
					}
				}
				enumerator3 = current5.controlRoomVariants.GetEnumerator();
				while (enumerator3.MoveNext())
				{
					TextAsset current7 = enumerator3.Current;
					if (!floorData.ContainsKey(((Object)current7).name))
					{
						floorData.Add(((Object)current7).name, Loader.LoadObject<FloorSaveData>(current7.text));
					}
				}
			}
		}
	}
}
[HarmonyPatch(typeof(BuildingCreator), "Awake")]
public class BuildingRegistration : CitiesV2
{
	public static void Postfix(BuildingCreator __instance)
	{
		foreach (BuildingManifest building in BuildingLoader.buildings)
		{
			__instance.buildingPresets.Add(building.preset);
		}
	}
}
public class RoomLoader : CitiesV2
{
	public static List<string> loaded = new List<string>();

	public static List<RoomConfiguration> roomConfigs = new List<RoomConfiguration>();

	public static List<RoomTypePreset> presets = new List<RoomTypePreset>();

	public static List<FiltersToAdd> filtersToAdd = new List<FiltersToAdd>();

	public static void LoadAll()
	{
		foreach (KeyValuePair<string, string> room in CitiesV2.rooms)
		{
			if (loaded.Contains(room.Key))
			{
				break;
			}
			loaded.Add(room.Key);
			LoadRoom(room.Key, room.Value);
		}
	}

	public static void LoadRoom(string name, string dir)
	{
		_ = Toolbox.Instance.resourcesCache;
		RoomConfiguration val = Loader.LoadFromJson<RoomConfiguration>(Path.Combine(dir, name, name + "_config.json"));
		RoomClassPreset val2 = ScriptableObject.CreateInstance<RoomClassPreset>();
		((SoCustomComparison)val2).presetName = name;
		((Object)val2).name = name;
		Toolbox.Instance.resourcesCache[Il2CppType.Of<RoomClassPreset>()].Add(((Object)val2).name, (ScriptableObject)(object)val2);
		RoomTypePreset val4 = (val.roomType = Loader.LoadFromJson<RoomTypePreset>(Path.Combine(dir, name, name + "_preset.json")));
		val.roomClass = val2;
		val.openPlanRoom = val4;
		val.debugRoom = val;
		((Object)val4).name = name;
		((Object)val).name = name;
		val.steps = ((Il2CppObjectBase)Helpers.GetScriptableObject("Hallway", typeof(RoomConfiguration))).Cast<RoomConfiguration>().steps;
		FiltersToAdd filtersToAdd = Loader.LoadFromJson<FiltersToAdd>(Path.Combine(dir, name, name + "_filters.json"));
		foreach (RoomTypeFilter filter in filtersToAdd.Filters)
		{
			filter.roomClasses.Add(val2);
		}
		foreach (AddressPreset address in filtersToAdd.Addresses)
		{
			address.roomConfig.Add(val);
		}
		roomConfigs.Add(val);
		presets.Add(val4);
		if (filtersToAdd.MaterialGroups.Count == 0 && filtersToAdd.Clusters.Count == 0 && filtersToAdd.BasicFurniture.Count == 0)
		{
			return;
		}
		RoomTypeFilter val5 = ((Il2CppObjectBase)ScriptableObject.CreateInstance(Il2CppType.Of<RoomTypeFilter>())).Cast<RoomTypeFilter>();
		((SoCustomComparison)val5).presetName = name;
		((Object)val5).name = name;
		val5.roomClasses.Add(val2);
		Toolbox.Instance.resourcesCache[Il2CppType.Of<RoomTypeFilter>()].Add(((Object)val5).name, (ScriptableObject)(object)val5);
		HashSet<FurniturePreset> val6 = new HashSet<FurniturePreset>();
		foreach (FurniturePreset item in filtersToAdd.BasicFurniture)
		{
			item.allowedRoomFilters.Add(val5);
			val6.Add(item);
		}
		foreach (MaterialGroupPreset materialGroup in filtersToAdd.MaterialGroups)
		{
			materialGroup.allowedRoomFilters.Add(val5);
		}
		foreach (FurnitureCluster cluster in filtersToAdd.Clusters)
		{
			cluster.allowedRoomFilters.Add(val5);
			cluster.enableDebug = true;
		}
		RoomLoader.filtersToAdd.Add(filtersToAdd);
		Toolbox.Instance.furnitureRoomTypeRef.Add(val2, val6);
	}
}
[Serializable]
public class FiltersToAdd
{
	public List<RoomTypeFilter> Filters { get; set; } = new List<RoomTypeFilter>();


	public List<FurniturePreset> BasicFurniture { get; set; } = new List<FurniturePreset>();


	public List<FurnitureCluster> Clusters { get; set; } = new List<FurnitureCluster>();


	public List<MaterialGroupPreset> MaterialGroups { get; set; } = new List<MaterialGroupPreset>();


	public List<AddressPreset> Addresses { get; set; } = new List<AddressPreset>();

}
[HarmonyPatch(typeof(Player), "PrepForStart")]
public class StairwellFix : CitiesV2
{
	[Serializable]
	public class NodePair
	{
		public Vector2Int nodeOne { get; set; }

		public Vector2Int nodeTwo { get; set; }
	}

	public static List<Stairfix> toRun = new List<Stairfix>();

	public static void Postfix()
	{
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Expected O, but got Unknown
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Expected O, but got Unknown
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Expected O, but got Unknown
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		PluginController<CitiesV2, IEmptyBindings>.Log.LogMessage((object)"Fixing Stair connections...");
		bool flag = default(bool);
		foreach (BuildingManifest building in BuildingLoader.buildings)
		{
			Enumerator<NewBuilding> enumerator2 = HighlanderSingleton<CityBuildings>.Instance.buildingDirectory.GetEnumerator();
			while (enumerator2.MoveNext())
			{
				NewBuilding current2 = enumerator2.Current;
				if ((SoCustomComparison)(object)current2.preset != (SoCustomComparison)(object)building.preset)
				{
					continue;
				}
				IEnumerator enumerator3 = ((Component)current2).gameObject.transform.GetEnumerator();
				try
				{
					while (enumerator3.MoveNext())
					{
						Transform val = ((Il2CppObjectBase)enumerator3.Current).Cast<Transform>();
						if (!(((Object)val).name != ((Object)building.preset.prefab).name + "(Clone)"))
						{
							ManualLogSource log = PluginController<CitiesV2, IEmptyBindings>.Log;
							BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(12, 1, ref flag);
							if (flag)
							{
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("OG position ");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Vector3>(val.position);
							}
							log.LogInfo(val2);
							val.position = new Vector3(val.position.x, val.position.y + building.posOffset, val.position.z);
							ManualLogSource log2 = PluginController<CitiesV2, IEmptyBindings>.Log;
							val2 = new BepInExInfoLogInterpolatedStringHandler(13, 1, ref flag);
							if (flag)
							{
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("NEW position ");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Vector3>(val.position);
							}
							log2.LogInfo(val2);
						}
					}
				}
				finally
				{
					if (enumerator3 is IDisposable disposable)
					{
						disposable.Dispose();
					}
				}
			}
		}
		foreach (Stairfix item in toRun)
		{
			ManualLogSource log3 = PluginController<CitiesV2, IEmptyBindings>.Log;
			BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(25, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Fixing: ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(item.floorPresetIndex);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("(floorIndex) at ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(item.preset);
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
			}
			log3.LogInfo(val2);
			FixStairwell(item);
		}
	}

	public static Vector2Int CalculatePos(Vector2Int pos, int rotation, int grid = 21)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		rotation %= 4;
		return (Vector2Int)(rotation switch
		{
			1 => new Vector2Int(grid - 1 - ((Vector2Int)(ref pos)).y, ((Vector2Int)(ref pos)).x), 
			2 => new Vector2Int(grid - 1 - ((Vector2Int)(ref pos)).x, grid - 1 - ((Vector2Int)(ref pos)).y), 
			3 => new Vector2Int(((Vector2Int)(ref pos)).y, grid - 1 - ((Vector2Int)(ref pos)).x), 
			_ => pos, 
		});
	}

	public static void FixStairwell(Stairfix stairfix)
	{
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0302: Unknown result type (might be due to invalid IL or missing references)
		List<NewBuilding> list = new List<NewBuilding>();
		new List<NewFloor>();
		BuildingPreset val = ((Il2CppObjectBase)Toolbox.Instance.resourcesCache[Il2CppType.Of<BuildingPreset>()][stairfix.preset]).Cast<BuildingPreset>();
		List<string> list2 = new List<string>();
		if (stairfix.isBasement)
		{
			Enumerator<TextAsset> enumerator = val.basementLayouts[stairfix.floorPresetIndex].blueprints.GetEnumerator();
			while (enumerator.MoveNext())
			{
				TextAsset current = enumerator.Current;
				list2.Add(((Object)current).name);
			}
			enumerator = val.basementLayouts[stairfix.floorPresetIndex].controlRoomVariants.GetEnumerator();
			while (enumerator.MoveNext())
			{
				TextAsset current2 = enumerator.Current;
				list2.Add(((Object)current2).name);
			}
		}
		else
		{
			Enumerator<TextAsset> enumerator = val.floorLayouts[stairfix.floorPresetIndex].blueprints.GetEnumerator();
			while (enumerator.MoveNext())
			{
				TextAsset current3 = enumerator.Current;
				list2.Add(((Object)current3).name);
			}
			enumerator = val.floorLayouts[stairfix.floorPresetIndex].controlRoomVariants.GetEnumerator();
			while (enumerator.MoveNext())
			{
				TextAsset current4 = enumerator.Current;
				list2.Add(((Object)current4).name);
			}
		}
		Enumerator<NewBuilding> enumerator2 = HighlanderSingleton<CityBuildings>.Instance.buildingDirectory.GetEnumerator();
		while (enumerator2.MoveNext())
		{
			NewBuilding current5 = enumerator2.Current;
			if (((Object)current5.preset).name == stairfix.preset)
			{
				list.Add(current5);
			}
		}
		foreach (NewBuilding item in list)
		{
			int rotations = item.rotations;
			List<NodePair> list3 = new List<NodePair>();
			foreach (NodePair stairConnector in stairfix.stairConnectors)
			{
				list3.Add(new NodePair
				{
					nodeOne = CalculatePos(stairConnector.nodeOne, rotations),
					nodeTwo = CalculatePos(stairConnector.nodeTwo, rotations)
				});
			}
			Enumerator<int, NewFloor> enumerator5 = item.floors.Values.GetEnumerator();
			while (enumerator5.MoveNext())
			{
				NewFloor current8 = enumerator5.Current;
				if (!list2.Contains(current8.floorName))
				{
					continue;
				}
				Dictionary<NodePair, (NewNode, NewNode)> dictionary = new Dictionary<NodePair, (NewNode, NewNode)>();
				foreach (NodePair item2 in list3)
				{
					dictionary.Add(item2, default((NewNode, NewNode)));
				}
				Enumerator<NewAddress> enumerator6 = current8.addresses.GetEnumerator();
				while (enumerator6.MoveNext())
				{
					Enumerator<NewNode> enumerator7 = ((NewGameLocation)enumerator6.Current).nodes.GetEnumerator();
					while (enumerator7.MoveNext())
					{
						NewNode current10 = enumerator7.Current;
						foreach (NodePair item3 in list3)
						{
							if (item3.nodeOne == current10.floorCoord)
							{
								dictionary[item3] = (current10, dictionary[item3].Item2);
							}
							else if (item3.nodeTwo == current10.floorCoord)
							{
								dictionary[item3] = (dictionary[item3].Item1, current10);
							}
						}
					}
				}
				foreach (var value in dictionary.Values)
				{
					value.Item1.AddAccessToOtherNode(value.Item2, true, true, (AccessType)4, true);
				}
			}
		}
	}
}
[Serializable]
public class Stairfix
{
	public List<StairwellFix.NodePair> stairConnectors { get; set; }

	public string preset { get; set; }

	public int floorPresetIndex { get; set; }

	public bool isBasement { get; set; }
}
[HarmonyPatch(typeof(Elevator), "UpdateCables")]
public class ElevatorFix
{
	public static bool Prefix(Elevator __instance)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: 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_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		if (__instance.top != null && (Object)(object)__instance.cable1 != (Object)null)
		{
			float num = __instance.top.position.y + PathFinder.Instance.tileSize.z - __instance.cable1.localPosition.y;
			float num2 = __instance.bottom.position.y + PathFinder.Instance.tileSize.z - __instance.cable1.localPosition.y;
			__instance.cable1.localScale = new Vector3(1f, num - num2 + 0.5f, 1f);
			__instance.cable2.localScale = new Vector3(1f, num - num2 + 0.5f, 1f);
		}
		return false;
	}
}