Decompiled source of BNYS mod v1.1.1

Bunject.NewYardSystem.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Logging;
using Bunburrows;
using Bunject.Internal;
using Bunject.Levels;
using Bunject.Monitoring;
using Bunject.NewYardSystem.Internal;
using Bunject.NewYardSystem.Levels;
using Bunject.NewYardSystem.Levels.Archive;
using Bunject.NewYardSystem.Levels.Local;
using Bunject.NewYardSystem.Levels.Web;
using Bunject.NewYardSystem.Model;
using Bunject.NewYardSystem.Resources;
using Bunject.NewYardSystem.Utility;
using Bunject.Tiling;
using HarmonyLib;
using Levels;
using Misc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("BunjectNewYardSystem")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BunjectNewYardSystem")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("72607052-293c-42fa-b044-aed2841c5102")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Bunject.NewYardSystem
{
	[BepInPlugin("sergedev.bunject.newyardsystem", "BNYS", "1.1.1")]
	public class BNYSPlugin : BaseUnityPlugin, IBunjectorPlugin, IMonitor
	{
		public const string pluginGuid = "sergedev.bunject.newyardsystem";

		public const string pluginName = "BNYS";

		public const string pluginVersion = "1.1.1";

		public static string pluginsDirectory = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "..\\"));

		public static string rootDirectory = Path.GetFullPath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));

		public static string inlineDirectory = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "BNYS");

		private List<CustomWorld> CustomWorlds;

		private List<IModBunburrow> AllModBurrows;

		private List<BNYSModBunburrowBase> BNYSModBurrows;

		private EmergencyLevelsList emergencyList;

		private bool surfaceLevelsGenerated;

		public ManualLogSource Logger => ((BaseUnityPlugin)this).Logger;

		public void Awake()
		{
			Logger.LogInfo((object)"Bunject New Yard System [BNYS] Plugin Awakened. v1.1.1");
			BunjectAPI.SaveFolder = "BNYS";
			CustomBunburrowCache customBunburrowCache = new CustomBunburrowCache();
			try
			{
				CustomWorlds = LoadCustomWorlds().ToList();
			}
			catch (Exception ex)
			{
				Logger.LogError((object)"Error caught on loading custom burrows... ");
				Logger.LogError((object)ex.Message);
				Logger.LogError((object)ex);
				return;
			}
			List<IModBunburrow> list = new List<IModBunburrow>();
			if (CustomWorlds.Count > 0)
			{
				Logger.LogInfo((object)"Initial Load - Building Cached Burrows!");
				foreach (CustomBunburrowModel cachedBurrow in customBunburrowCache.CustomBurrows)
				{
					Burrow burrowModel = CustomWorlds.Where((CustomWorld cw) => cachedBurrow.World == cw.Title || string.IsNullOrEmpty(cachedBurrow.World)).SelectMany((CustomWorld cw) => cw.Burrows).FirstOrDefault((Burrow b) => b.Name == cachedBurrow.Name);
					CustomWorld customWorld2 = CustomWorlds.FirstOrDefault((CustomWorld cw) => cw.Burrows.Contains(burrowModel));
					if (burrowModel != null)
					{
						Logger.LogInfo((object)("Cached Burrow : " + burrowModel.Name + " found!"));
						cachedBurrow.World = customWorld2.Title;
						cachedBurrow.Prefix = customWorld2.Prefix;
						cachedBurrow.Indicator = burrowModel.Indicator;
						list.Add((IModBunburrow)(object)customWorld2.GenerateBunburrow(this, burrowModel.Name));
					}
					else
					{
						Logger.LogInfo((object)("Cached Burrow : " + cachedBurrow.Name + " NOT found!"));
						list.Add((IModBunburrow)(object)new BNYSLostBunburrow(cachedBurrow));
					}
				}
				Logger.LogInfo((object)"Initial Load - Building Uncached Burrows!");
				foreach (Burrow burrow in CustomWorlds.SelectMany((CustomWorld cw) => cw.Burrows))
				{
					CustomWorld customWorld = CustomWorlds.FirstOrDefault((CustomWorld cw) => cw.Burrows.Contains(burrow));
					if (customBunburrowCache.CustomBurrows.FirstOrDefault((CustomBunburrowModel cb) => cb.Name == burrow.Name && (cb.World == customWorld.Title || string.IsNullOrEmpty(cb.World))) == null)
					{
						Logger.LogInfo((object)("Uncached Burrow : " + burrow.Name + " built!"));
						BNYSModBunburrowBase bNYSModBunburrowBase = customWorld.GenerateBunburrow(this, burrow.Name);
						list.Add((IModBunburrow)(object)bNYSModBunburrowBase);
						customBunburrowCache.CacheBunburrow(bNYSModBunburrowBase);
					}
				}
				customBunburrowCache.SaveCache();
				AllModBurrows = list.ToList();
				BNYSModBurrows = list.OfType<BNYSModBunburrowBase>().ToList();
				LinkLevelLists(BNYSModBurrows);
				foreach (IModBunburrow item in list)
				{
					BunjectAPI.RegisterBunburrow(item);
					if (!(item is BNYSModBunburrowBase bNYSModBunburrowBase2))
					{
						continue;
					}
					foreach (int elevatorDepth in bNYSModBunburrowBase2.BurrowModel.ElevatorDepths)
					{
						BunjectAPI.RegisterElevator(item.ID, elevatorDepth);
					}
				}
				BunjectAPI.RegisterPlugin((IBunjectorPlugin)(object)this);
				Logger.LogInfo((object)"Initial Load Finished!");
			}
			else
			{
				Logger.LogInfo((object)"All worlds empty! Please configure a burrow with a surface entrance, and depth of at least 1!");
			}
		}

		public void OnAssetsLoaded()
		{
			Logger.LogInfo((object)"!!! STARTING PATCH OF SURFACE RIGHT!!!");
			SurfaceBurrowsPatch.PatchSurfaceBurrows(AssetsManager.SurfaceRightLevel, null);
			Logger.LogInfo((object)"!!! END PATCH OF SURFACE RIGHT!!!");
			GenerateSurfaceLevels(AssetsManager.SurfaceRightLevel);
		}

		public void OnProgressionLoaded(GeneralProgression progression)
		{
			progression.HandleBunburrowSignsDiscovery();
			progression.HandleBackToSurfaceUnlock();
			progression.HandleOphelinePortableComputerUnlock();
		}

		public LevelObject StartLevelTransition(LevelObject level, LevelIdentity identity)
		{
			return level;
		}

		public LevelsList LoadEmergencyLevelsList(LevelsList original)
		{
			if ((Object)(object)emergencyList == (Object)null)
			{
				emergencyList = ScriptableObject.CreateInstance<EmergencyLevelsList>();
				emergencyList.Bnys = this;
			}
			return (LevelsList)(object)emergencyList;
		}

		public void LoadBurrowSurfaceLevel(string listName, LevelObject otherwise)
		{
			Burrow burrow = CustomWorlds.SelectMany((CustomWorld cw) => cw.Burrows).FirstOrDefault((Burrow b) => b.Name == listName);
			if (burrow != null)
			{
				CustomWorlds.FirstOrDefault((CustomWorld cw) => cw.Burrows.Contains(burrow)).Burrows.Where((Burrow b) => b.Depth > 0 && b.HasSurfaceEntry).ToList().IndexOf(burrow);
				Logger.LogWarning((object)"Burrow was not surfaceable / not in the list of generated surface levels!");
			}
		}

		public IEnumerable<CustomWorld> LoadCustomWorlds()
		{
			foreach (string item in Directory.EnumerateDirectories(rootDirectory))
			{
				string text = Path.Combine(item, "config.json");
				if (!File.Exists(text))
				{
					continue;
				}
				CustomWorld customWorld = LoadWorldConfig(text);
				if (customWorld == null || !customWorld.Burrows.Any((Burrow b) => b.HasSurfaceEntry && b.Depth > 0) || !customWorld.Enabled)
				{
					continue;
				}
				foreach (Burrow burrow in customWorld.Burrows)
				{
					PatchBurrowDetails(item, burrow);
				}
				yield return customWorld;
			}
			foreach (string item2 in Directory.EnumerateDirectories(pluginsDirectory))
			{
				foreach (string item3 in Directory.EnumerateFiles(item2, "*.bnys"))
				{
					CustomWorld customWorld2 = LoadWorldConfigFromArchive(item3);
					if (customWorld2 != null && customWorld2.Burrows.Any((Burrow b) => b.HasSurfaceEntry && b.Depth > 0) && customWorld2.Enabled)
					{
						yield return customWorld2;
					}
				}
			}
		}

		private CustomWorld LoadWorldConfig(string filename)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			CustomWorld customWorld = null;
			try
			{
				using StreamReader streamReader = new StreamReader(filename);
				customWorld = (CustomWorld)new JsonSerializer().Deserialize((TextReader)streamReader, typeof(LocalCustomWorld));
			}
			catch (Exception ex)
			{
				Logger.LogError((object)"Following file could not be parsed");
				Logger.LogError((object)filename);
				Logger.LogError((object)ex.Message);
				Logger.LogError((object)ex);
			}
			if (string.IsNullOrEmpty(customWorld.Title))
			{
				customWorld.Title = "Untitled";
			}
			if (!string.IsNullOrEmpty(customWorld.ProxyURL))
			{
				try
				{
					return LoadProxyWorld(customWorld);
				}
				catch (Exception ex2)
				{
					Logger.LogError((object)"Error loading Proxy World config.json");
					Logger.LogError((object)filename);
					Logger.LogError((object)ex2.Message);
					Logger.LogError((object)ex2);
				}
			}
			return customWorld;
		}

		private CustomWorld LoadWorldConfigFromArchive(string archivePath)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			ZipArchive zipArchive = ZipFile.OpenRead(archivePath);
			Logger.LogInfo((object)("Opening World Archive: " + archivePath));
			ZipArchiveEntry entry = zipArchive.GetEntry("config.json");
			if (entry == null)
			{
				Logger.LogError((object)("Archive " + Path.GetFileName(archivePath) + " is missing config.json."));
				Logger.LogError((object)"Please double check that config.json is at the root level of the .bnys (zip) file.");
				return null;
			}
			ArchiveCustomWorld archiveCustomWorld = null;
			try
			{
				using Stream stream = entry.Open();
				using StreamReader streamReader = new StreamReader(stream);
				archiveCustomWorld = (ArchiveCustomWorld)new JsonSerializer().Deserialize((TextReader)streamReader, typeof(ArchiveCustomWorld));
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Archive " + Path.GetFileName(archivePath) + " config.json file could not be parsed: "));
				Logger.LogError((object)ex.Message);
				Logger.LogError((object)ex);
			}
			archiveCustomWorld.Archive = zipArchive;
			if (string.IsNullOrEmpty(archiveCustomWorld.Title))
			{
				archiveCustomWorld.Title = "Untitled";
			}
			if (!string.IsNullOrEmpty(archiveCustomWorld.ProxyURL))
			{
				try
				{
					return LoadProxyWorld(archiveCustomWorld);
				}
				catch (Exception ex2)
				{
					Logger.LogError((object)("Error loading Archive Proxy World config.json - " + Path.GetFileName(archivePath)));
					Logger.LogError((object)ex2.Message);
					Logger.LogError((object)ex2);
				}
			}
			return archiveCustomWorld;
		}

		private WebCustomWorld LoadProxyWorld(CustomWorld basis)
		{
			Uri uri = new Uri(basis.ProxyURL);
			WebCustomWorld webCustomWorld = new Uri(uri, "config.json").Load<WebCustomWorld>();
			if (webCustomWorld != null)
			{
				webCustomWorld.ProxyUri = uri;
				webCustomWorld.ProxyURL = basis.ProxyURL;
				webCustomWorld.Enabled = webCustomWorld.Enabled || basis.Enabled;
				webCustomWorld.LiveReloading = false;
				if (string.IsNullOrEmpty(webCustomWorld.Title))
				{
					webCustomWorld.Title = basis.Title;
				}
				if (webCustomWorld.Burrows != null)
				{
					foreach (Burrow burrow in webCustomWorld.Burrows)
					{
						burrow.ProxyUri = new Uri(webCustomWorld.ProxyUri, burrow.Directory + "/");
					}
					if (webCustomWorld.SurfaceEntries == null || webCustomWorld.SurfaceEntries.Count == 0)
					{
						webCustomWorld.SurfaceEntries = basis.SurfaceEntries;
					}
				}
				if (string.IsNullOrEmpty(webCustomWorld.Title))
				{
					webCustomWorld.Title = "Untitled";
				}
			}
			return webCustomWorld;
		}

		private void PatchBurrowDetails(string directory, Burrow burrow)
		{
			if (!Path.IsPathRooted(burrow.Directory))
			{
				burrow.Directory = Path.Combine(directory, burrow.Directory);
			}
		}

		private void GenerateSurfaceLevels(LevelObject coreSurfaceRight)
		{
			if (surfaceLevelsGenerated)
			{
				return;
			}
			LevelObject val = coreSurfaceRight;
			foreach (CustomWorld world in CustomWorlds)
			{
				try
				{
					ExtendedSurfaceLevelGenerator.CreateSurfaceLevels(world, BNYSModBurrows.Where((BNYSModBunburrowBase b) => b.World == world).ToList(), val);
					val = world.GeneratedSurfaceLevels.LastOrDefault() ?? val;
				}
				catch (Exception ex)
				{
					Logger.LogError((object)("Error occurred while generating surface levels for world: " + world.Title));
					Logger.LogError((object)ex.Message);
					Logger.LogError((object)ex);
				}
			}
			PatchLevelAsEndcap(val);
			surfaceLevelsGenerated = true;
		}

		private void PatchLevelAsEndcap(LevelObject endcapLevel)
		{
			Traverse.Create((object)endcapLevel).Field("specificBackground").SetValue((object)SurfaceBurrowsPatch.EndingBackground);
		}

		private void LinkLevelLists(List<BNYSModBunburrowBase> burrows)
		{
			foreach (BNYSModBunburrowBase burrow in burrows)
			{
				if (!string.IsNullOrEmpty(burrow.BurrowModel.Links.Left))
				{
					BNYSModBunburrowBase bNYSModBunburrowBase = burrows.FirstOrDefault((BNYSModBunburrowBase bb) => bb.LocalName == burrow.BurrowModel.Links.Left);
					if (bNYSModBunburrowBase != null)
					{
						burrow.GetLevels().AdjacentBunburrows.SetPart((Direction)0, bNYSModBunburrowBase.GetLevels());
					}
				}
				if (!string.IsNullOrEmpty(burrow.BurrowModel.Links.Up))
				{
					BNYSModBunburrowBase bNYSModBunburrowBase2 = burrows.FirstOrDefault((BNYSModBunburrowBase bb) => bb.LocalName == burrow.BurrowModel.Links.Up);
					if (bNYSModBunburrowBase2 != null)
					{
						burrow.GetLevels().AdjacentBunburrows.SetPart((Direction)2, bNYSModBunburrowBase2.GetLevels());
					}
				}
				if (!string.IsNullOrEmpty(burrow.BurrowModel.Links.Right))
				{
					BNYSModBunburrowBase bNYSModBunburrowBase3 = burrows.FirstOrDefault((BNYSModBunburrowBase bb) => bb.LocalName == burrow.BurrowModel.Links.Right);
					if (bNYSModBunburrowBase3 != null)
					{
						burrow.GetLevels().AdjacentBunburrows.SetPart((Direction)1, bNYSModBunburrowBase3.GetLevels());
					}
				}
				if (!string.IsNullOrEmpty(burrow.BurrowModel.Links.Down))
				{
					BNYSModBunburrowBase bNYSModBunburrowBase4 = burrows.FirstOrDefault((BNYSModBunburrowBase bb) => bb.LocalName == burrow.BurrowModel.Links.Down);
					if (bNYSModBunburrowBase4 != null)
					{
						burrow.GetLevels().AdjacentBunburrows.SetPart((Direction)3, bNYSModBunburrowBase4.GetLevels());
					}
				}
			}
		}

		public static BunburrowStyle ResolveStyle(string style)
		{
			switch (style)
			{
			case "Aquatic":
			case "Sunken":
				return AssetsManager.BunburrowsListOfStyles[(Bunburrow)1];
			case "Hay":
				return AssetsManager.BunburrowsListOfStyles[(Bunburrow)2];
			case "Purple":
			case "Forgotten":
				return AssetsManager.BunburrowsListOfStyles[(Bunburrow)4];
			case "Ghostly":
			case "Spooky":
				return AssetsManager.BunburrowsListOfStyles[(Bunburrow)3];
			case "Void":
				return AssetsManager.BunburrowsListOfStyles.VoidB;
			case "Temple":
				return AssetsManager.BunburrowsListOfStyles.Temple;
			case "Hell":
				return AssetsManager.BunburrowsListOfStyles.Hell;
			case "HellTemple":
				return AssetsManager.BunburrowsListOfStyles.HellTemple;
			default:
				return AssetsManager.BunburrowsListOfStyles[(Bunburrow)0];
			}
		}
	}
}
namespace Bunject.NewYardSystem.Utility
{
	public static class UriExtensions
	{
		public static string Load(this Uri uri)
		{
			Console.WriteLine("Loading: " + uri);
			using WebClient webClient = new WebClient();
			return webClient.DownloadString(uri);
		}

		public static T Load<T>(this Uri uri) where T : class
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			Console.WriteLine("Loading: " + uri);
			using WebClient webClient = new WebClient();
			using StreamReader streamReader = new StreamReader(webClient.OpenRead(uri));
			return new JsonSerializer().Deserialize((TextReader)streamReader, typeof(T)) as T;
		}
	}
	public class CoordinateJsonConverter : JsonConverter<SurfaceCoordinate>
	{
		public override bool CanWrite => false;

		public override SurfaceCoordinate ReadJson(JsonReader reader, Type objectType, SurfaceCoordinate existingValue, bool hasExistingValue, JsonSerializer serializer)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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_0009: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			JsonToken tokenType = reader.TokenType;
			if ((int)tokenType != 1)
			{
				if ((int)tokenType == 2)
				{
					return new SurfaceCoordinate(((JContainer)JArray.Load(reader)).Values<int>().ToArray());
				}
				Console.WriteLine("Uh oh!");
				Console.WriteLine(Enum.GetName(typeof(JsonToken), reader.TokenType));
				return new SurfaceCoordinate();
			}
			JToken val = JToken.Load(reader);
			SurfaceCoordinate surfaceCoordinate = new SurfaceCoordinate();
			JToken obj = val[(object)"Hole"];
			surfaceCoordinate.Hole = ((obj == null) ? null : obj.Values<int>()?.ToArray());
			JToken obj2 = val[(object)"Sign"];
			surfaceCoordinate.Sign = ((obj2 == null) ? null : obj2.Values<int>()?.ToArray());
			surfaceCoordinate.NoSign = val.Value<bool?>((object)"NoSign").GetValueOrDefault();
			return surfaceCoordinate;
		}

		public override void WriteJson(JsonWriter writer, SurfaceCoordinate value, JsonSerializer serializer)
		{
			throw new NotImplementedException();
		}
	}
}
namespace Bunject.NewYardSystem.Resources
{
	internal static class DefaultLevel
	{
		public static string Content = "T,T,T,T,T,T,T,T,T,T,T,T,T,T,T" + Environment.NewLine + "T,T,T,T,T,T,T,T,T,T,T,T,T,T,T" + Environment.NewLine + "T,T,T,T,T,T,T,T,T,T,T,T,T,T,T" + Environment.NewLine + "T,T,T,T,T,T,T,T,T,T,T,T,T,T,T" + Environment.NewLine + "T,T,T,T,T,T,T,S,T,T,T,T,T,T,T" + Environment.NewLine + "T,T,T,T,T,T,T,T,T,T,T,T,T,T,T" + Environment.NewLine + "T,T,T,T,T,T,T,T,T,T,T,T,T,T,T" + Environment.NewLine + "T,T,T,T,T,T,T,T,T,T,T,T,T,T,T" + Environment.NewLine + "T,T,T,T,T,T,T,T,T,T,T,T,T,T,T" + Environment.NewLine;
	}
	internal class ImportImage
	{
		public static Sprite ImportSprite(string name, string path, Vector2 pivot, float pixelsPerUnit)
		{
			//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)
			Texture2D val = ImportTexture(name, path);
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), pivot, pixelsPerUnit);
		}

		public static Texture2D ImportTexture(string name, string path)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			byte[] array = File.ReadAllBytes(path);
			Texture2D val = new Texture2D(2, 2);
			ImageConversion.LoadImage(val, array);
			((Object)val).name = name;
			val.Apply();
			return val;
		}
	}
}
namespace Bunject.NewYardSystem.Model
{
	public class Burrow
	{
		public string Directory { get; set; }

		public string Name { get; set; }

		public string Indicator { get; set; }

		public string Style { get; set; } = "Pink";


		public bool HasSurfaceEntry { get; set; }

		public bool IsVoid { get; set; }

		public int UpperBunnyCount { get; set; }

		public int TempleBunnyCount { get; set; }

		public int HellBunnyCount { get; set; }

		public int Depth { get; set; }

		public BurrowLinks Links { get; set; } = new BurrowLinks();


		public List<int> ElevatorDepths { get; set; } = new List<int>();


		[JsonIgnore]
		public Uri ProxyUri { get; set; }

		[JsonIgnore]
		public ModLevelsList Levels { get; set; }
	}
	public class BurrowLinks
	{
		public string Left { get; set; }

		public string Up { get; set; }

		public string Right { get; set; }

		public string Down { get; set; }
	}
	public class CustomBunburrowModel
	{
		public string World { get; set; }

		public string Name { get; set; }

		public string Prefix { get; set; }

		public string Indicator { get; set; }

		[JsonIgnore]
		public int ID { get; set; }
	}
	public abstract class CustomWorld
	{
		public string ProxyURL { get; set; }

		public bool Enabled { get; set; } = true;


		public bool LiveReloading { get; set; }

		public string Title { get; set; }

		public string Prefix { get; set; }

		public List<Burrow> Burrows { get; set; }

		public List<SurfaceEntry> SurfaceEntries { get; set; }

		[JsonIgnore]
		public Uri ProxyUri { get; set; }

		[JsonIgnore]
		public List<LevelObject> GeneratedSurfaceLevels { get; set; }

		public abstract BNYSModBunburrowBase GenerateBunburrow(BNYSPlugin pluginRef, string bunburrowName);
	}
	public class GlobalConfig
	{
		public List<string> WebBurrows { get; set; }
	}
	public class LevelMetadata
	{
		public string Name { get; set; }

		public bool LiveReloading { get; set; }

		public LevelTools Tools { get; set; } = new LevelTools();


		public string Style { get; set; }

		public bool IsTemple { get; set; }

		public bool IsHell { get; set; }

		public string Content { get; set; }

		public bool IsWebLevel { get; set; }
	}
	public class LevelTools
	{
		public int Traps { get; set; }

		public int Pickaxes { get; set; }

		public int Carrots { get; set; }

		public int Shovels { get; set; }
	}
	public class SurfaceEntry
	{
		public Dictionary<string, SurfaceCoordinate> Coordinates { get; set; }

		public SurfaceEntryGrid Grid { get; set; }
	}
	[JsonConverter(typeof(CoordinateJsonConverter))]
	public class SurfaceCoordinate
	{
		public int[] Hole { get; set; }

		public int[] Sign { get; set; }

		public bool NoSign { get; set; }

		public SurfaceCoordinate()
		{
		}

		public SurfaceCoordinate(params int[] holeCoordinates)
		{
			Hole = holeCoordinates;
		}
	}
	public class SurfaceEntryGrid
	{
		public string NW { get; set; }

		public string N { get; set; }

		public string NE { get; set; }

		public string W { get; set; }

		public string C { get; set; }

		public string E { get; set; }

		public string SW { get; set; }

		public string S { get; set; }

		public string SE { get; set; }
	}
}
namespace Bunject.NewYardSystem.Internal
{
	internal class CustomBunburrowCache
	{
		private string cachePath;

		public List<CustomBunburrowModel> CustomBurrows;

		public CustomBunburrowCache()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			string rootSaveDataPath = SaveFileModUtility.GetRootSaveDataPath();
			cachePath = Path.Combine(rootSaveDataPath, "mod-burrow-cache.json");
			if (!Directory.Exists(rootSaveDataPath))
			{
				Directory.CreateDirectory(rootSaveDataPath);
			}
			if (File.Exists(cachePath))
			{
				using (StreamReader streamReader = new StreamReader(cachePath))
				{
					CustomBurrows = new JsonSerializer().Deserialize((TextReader)streamReader, typeof(List<CustomBunburrowModel>)) as List<CustomBunburrowModel>;
					return;
				}
			}
			CustomBurrows = new List<CustomBunburrowModel>();
		}

		public CustomBunburrowModel CacheBunburrow(IBNYSModBunburrow bunburrow)
		{
			CustomBunburrowModel customBunburrowModel = new CustomBunburrowModel
			{
				World = bunburrow.WorldName,
				Name = bunburrow.LocalName,
				Prefix = bunburrow.WorldPrefix,
				Indicator = bunburrow.LocalIndicator
			};
			CustomBurrows.Add(customBunburrowModel);
			return customBunburrowModel;
		}

		public void SaveCache()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			using StreamWriter streamWriter = new StreamWriter(cachePath);
			new JsonSerializer().Serialize((TextWriter)streamWriter, (object)CustomBurrows);
		}
	}
}
namespace Bunject.NewYardSystem.Levels
{
	public class BNYSLevelsList : ModLevelsList
	{
		public BNYSPlugin Bnys { get; set; }

		public BNYSModBunburrowBase ModBunburrow { get; set; }

		public bool PermitReloading { get; set; } = true;


		public bool DelayReloading { get; set; }

		public BNYSLevelObject this[int depth]
		{
			get
			{
				return ((ModLevelsList)this)[depth] as BNYSLevelObject;
			}
			set
			{
				((ModLevelsList)this)[depth] = (ModLevelObject)(object)value;
			}
		}

		public override LevelObject LoadLevel(int depth, LoadingContext loadingContext)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Invalid comparison between Unknown and I4
			if (depth > 0 && depth <= ((ModLevelsList)this).MaximumDepth)
			{
				BNYSLevelObject bNYSLevelObject = this[depth];
				if ((Object)(object)bNYSLevelObject == (Object)null)
				{
					bNYSLevelObject = ScriptableObject.CreateInstance<BNYSLevelObject>();
					((ModLevelObject)bNYSLevelObject).BunburrowName = ModBunburrow.BurrowModel.Name;
					((ModLevelObject)bNYSLevelObject).Depth = depth;
					ReloadLevel(depth, bNYSLevelObject);
					this[depth] = bNYSLevelObject;
				}
				else if (PermitReloading && bNYSLevelObject.ShouldReload && (int)loadingContext == 1)
				{
					ReloadLevel(depth, bNYSLevelObject);
				}
				return (LevelObject)(object)bNYSLevelObject;
			}
			Bnys.Logger.LogWarning((object)$"{ModBunburrow.Name}: Depth requested, {depth}, exceeds burrow depth of {((ModLevelsList)this).MaximumDepth}");
			return null;
		}

		private void ReloadLevel(int depth, BNYSLevelObject levelObject)
		{
			LevelMetadata levelMetadata = ModBunburrow.LoadLevel(depth);
			levelObject.ShouldReload = PermitReloading && (ModBunburrow.World.LiveReloading || levelMetadata.LiveReloading);
			levelObject.LastReloadTime = DateTime.Now;
			levelObject.DelayReload = DelayReloading;
			PopulateLevel(levelObject, levelMetadata, depth);
		}

		private LevelMetadata CreateDefaultLevelMetadata()
		{
			return new LevelMetadata
			{
				Name = "Failed Level Load",
				LiveReloading = true,
				IsHell = false,
				IsTemple = false,
				Tools = new LevelTools()
			};
		}

		private void PopulateLevel(BNYSLevelObject levelObject, LevelMetadata levelConfig, int depth)
		{
			((Object)levelObject).name = "Level " + ModBunburrow.Name + " - " + levelConfig.Name;
			((ModLevelObject)levelObject).CustomNameKey = levelConfig.Name;
			((ModLevelObject)levelObject).BunburrowStyle = BNYSPlugin.ResolveStyle(levelConfig.Style);
			LevelTools tools = levelConfig.Tools;
			if (tools != null)
			{
				((ModLevelObject)levelObject).NumberOfTraps = tools.Traps;
				((ModLevelObject)levelObject).NumberOfPickaxes = tools.Pickaxes;
				((ModLevelObject)levelObject).NumberOfCarrots = tools.Carrots;
				((ModLevelObject)levelObject).NumberOfShovels = tools.Shovels;
			}
			((ModLevelObject)levelObject).IsTemple = levelConfig.IsTemple;
			((ModLevelObject)levelObject).IsHell = levelConfig.IsHell;
			((ModLevelObject)levelObject).Content = levelConfig.Content;
		}
	}
	public class BNYSLevelObject : ModLevelObject
	{
		private bool shouldReload = true;

		public bool ShouldReload
		{
			get
			{
				if (!DelayReload)
				{
					return shouldReload;
				}
				if (shouldReload)
				{
					return LastReloadTime.Minute != DateTime.Now.Minute;
				}
				return false;
			}
			set
			{
				shouldReload = value;
			}
		}

		public DateTime LastReloadTime { get; set; }

		public bool DelayReload { get; set; }
	}
	public abstract class BNYSModBunburrowBase : IBNYSModBunburrow, IModBunburrow
	{
		private BunburrowStyle style;

		private Vector2Int? customSignCoordinate;

		private LevelsList levelsList;

		protected BNYSPlugin Bnys { get; private set; }

		public CustomWorld World { get; private set; }

		public Burrow BurrowModel { get; private set; }

		public string WorldName => World.Title;

		public string LocalName => BurrowModel.Name;

		public string WorldPrefix => World.Prefix;

		public string LocalIndicator => BurrowModel.Indicator;

		public bool IsVoid => BurrowModel.IsVoid;

		public int ID { get; set; }

		public string Name => WorldName + "::" + LocalName;

		public string Indicator => (string.IsNullOrEmpty(WorldPrefix) ? string.Empty : (WorldPrefix + "-")) + LocalIndicator;

		public BunburrowStyle Style
		{
			get
			{
				if ((Object)(object)style == (Object)null)
				{
					style = BNYSPlugin.ResolveStyle(BurrowModel.Style);
				}
				return style;
			}
		}

		public bool HasEntrance => BurrowModel.HasSurfaceEntry;

		public bool HasSign { get; private set; } = true;


		public LevelObject SurfaceLevel { get; set; }

		public BNYSModBunburrowBase(BNYSPlugin bnys, CustomWorld worldModel, Burrow burrowModel)
		{
			Bnys = bnys;
			World = worldModel;
			BurrowModel = burrowModel;
			InitializeCustomSignCoordinate();
		}

		public Vector2Int? OverrideSignCoordinate()
		{
			return customSignCoordinate;
		}

		private void InitializeCustomSignCoordinate()
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			SurfaceCoordinate surfaceCoordinate = World.SurfaceEntries?.Where((SurfaceEntry se) => se.Coordinates != null)?.SelectMany((SurfaceEntry se) => se.Coordinates)?.Where((KeyValuePair<string, SurfaceCoordinate> kvp) => kvp.Key == LocalName)?.Select((KeyValuePair<string, SurfaceCoordinate> kvp) => kvp.Value)?.FirstOrDefault();
			if (surfaceCoordinate == null)
			{
				return;
			}
			if (!surfaceCoordinate.NoSign)
			{
				if (surfaceCoordinate.Sign != null && surfaceCoordinate.Sign.Length > 1)
				{
					customSignCoordinate = new Vector2Int(surfaceCoordinate.Sign[0], surfaceCoordinate.Sign[1]);
				}
			}
			else
			{
				HasSign = false;
			}
		}

		public abstract LevelMetadata LoadLevel(int depth);

		public LevelsList GetLevels()
		{
			if ((Object)(object)levelsList == (Object)null)
			{
				levelsList = (LevelsList)(object)GenerateLevelsList();
			}
			return levelsList;
		}

		public LevelObject GetSurfaceLevel()
		{
			return SurfaceLevel;
		}

		protected virtual BNYSLevelsList GenerateLevelsList()
		{
			BNYSLevelsList bNYSLevelsList = ScriptableObject.CreateInstance<BNYSLevelsList>();
			bNYSLevelsList.ModBunburrow = this;
			bNYSLevelsList.Bnys = Bnys;
			((Object)bNYSLevelsList).name = Name;
			((ModLevelsList)bNYSLevelsList).MaximumDepth = BurrowModel.Depth;
			((ModLevelsList)bNYSLevelsList).NumberOfRegularBunnies = BurrowModel.UpperBunnyCount;
			((ModLevelsList)bNYSLevelsList).NumberOfTempleBunnies = BurrowModel.TempleBunnyCount;
			((ModLevelsList)bNYSLevelsList).NumberOfHellBunnies = BurrowModel.HellBunnyCount;
			return bNYSLevelsList;
		}

		protected LevelMetadata CreateDefaultLevelMetadata()
		{
			return new LevelMetadata
			{
				Name = "Failed Level Load",
				LiveReloading = true,
				IsHell = false,
				IsTemple = false,
				Tools = new LevelTools()
			};
		}
	}
	public interface IBNYSModBunburrow
	{
		string WorldName { get; }

		string LocalName { get; }

		string WorldPrefix { get; }

		string LocalIndicator { get; }
	}
	internal class ContentValidator
	{
		private const string RESTRICTED_TILES = "^(F|D[0-9]+|P[0-9]+|N[0-9]+|Oph|X|C|PU|A|Y(?:{.*})?)|T\\{\\.*[PS].*\\}$";

		private static readonly Regex restrictedTileRegex = new Regex("^(F|D[0-9]+|P[0-9]+|N[0-9]+|Oph|X|C|PU|A|Y(?:{.*})?)|T\\{\\.*[PS].*\\}$");

		public static List<LevelValidationError> ValidateLevelContent(string content)
		{
			List<string> tilesFromContent = TileValidator.GetTilesFromContent(content);
			List<LevelValidationError> list = new List<LevelValidationError>();
			if (tilesFromContent.Count > 135)
			{
				list.Add(new LevelValidationError("Level has too many tiles", isWarning: true));
			}
			if (tilesFromContent.Count < 135)
			{
				list.Add(new LevelValidationError("Level has too few tiles"));
			}
			foreach (var (text, num) in tilesFromContent.Select((string t, int i) => (t, i)))
			{
				if (restrictedTileRegex.IsMatch(text) || !TileValidator.ValidateTile(text))
				{
					list.Add(new TileValidationError("Tile '" + text + "' is not valid", num / 15, num % 15));
				}
			}
			return list;
		}
	}
	public class EmergencyLevelsList : ModLevelsList
	{
		private LevelObject defaultLevel;

		public BNYSPlugin Bnys { get; set; }

		public override LevelObject LoadLevel(int depth, LoadingContext loadingContext)
		{
			if ((Object)(object)defaultLevel == (Object)null)
			{
				defaultLevel = GenerateDefaultLevel();
			}
			Bnys.Logger.LogError((object)"Something went wrong - loading default level!");
			return defaultLevel;
		}

		private LevelObject GenerateDefaultLevel()
		{
			ModLevelObject obj = ScriptableObject.CreateInstance<ModLevelObject>();
			obj.CustomNameKey = "Default Level";
			obj.BunburrowName = "Emergency List";
			obj.Depth = 1;
			obj.Content = DefaultLevel.Content;
			obj.BunburrowStyle = AssetsManager.BunburrowsListOfStyles[(Bunburrow)0];
			return (LevelObject)(object)obj;
		}
	}
	internal class ExtendedSurfaceLevelGenerator
	{
		[Flags]
		private enum SurfaceType
		{
			None = 0,
			Coordinates = 1,
			Grid = 2
		}

		public const string WallRow = "W,W,W,W,W,W,W,W,W,W,W,W,W,W,W";

		public const string TopRow = "W,T,T,T,T,T,T,T,T,T,T,T,W{0},W,W";

		public const string SpaceRow = "W,W{0},T,T,T,T,T,T,T,T,T,T,T,W,W";

		public const string EntryRow = "W,T,T,T,{0},T,T,{1},T,T,{2},T,T,W,W";

		public const string OpenRow = "T,T,T,T,T,T,T,T,T,T,T,T,T,T,T";

		public static void CreateSurfaceLevels(CustomWorld world, List<BNYSModBunburrowBase> modBunburrows, LevelObject precedingLevel)
		{
			if (world.GeneratedSurfaceLevels == null)
			{
				Dictionary<string, BNYSModBunburrowBase> burrows = modBunburrows.Where((BNYSModBunburrowBase b) => b.BurrowModel.Depth > 0).ToDictionary((BNYSModBunburrowBase b) => b.LocalName);
				world.GeneratedSurfaceLevels = GenerateLevels(precedingLevel, world, burrows).ToList();
			}
		}

		private static IEnumerable<LevelObject> GenerateLevels(LevelObject precedingLevel, CustomWorld world, Dictionary<string, BNYSModBunburrowBase> burrows)
		{
			IEnumerable<SurfaceEntry> surfaceEntries = world.SurfaceEntries;
			foreach (SurfaceEntry item3 in surfaceEntries ?? Enumerable.Empty<SurfaceEntry>())
			{
				string text = null;
				List<BNYSModBunburrowBase> list = null;
				switch (GetSurfaceType(item3))
				{
				case SurfaceType.Coordinates:
					Console.WriteLine(world.Title + ": Creating Coordinate Surface World!");
					(text, list) = GenerateCoordinatesSurfaceContent(item3.Coordinates, burrows);
					break;
				case SurfaceType.Grid:
					Console.WriteLine(world.Title + ": Creating Grid Surface World!");
					(text, list) = GenerateGridSurfaceContent(item3.Grid, burrows);
					break;
				}
				if (list == null || string.IsNullOrEmpty(text) || list.Count <= 0)
				{
					continue;
				}
				Console.WriteLine($"{list.Count} burrows placed in surface world");
				precedingLevel = GenerateLevel(world, text, precedingLevel);
				foreach (BNYSModBunburrowBase item4 in list)
				{
					item4.SurfaceLevel = precedingLevel;
				}
				yield return precedingLevel;
			}
			List<BNYSModBunburrowBase> enterableBurrows = burrows.Values.Where((BNYSModBunburrowBase b) => b.BurrowModel.HasSurfaceEntry).ToList();
			while (enterableBurrows.Any())
			{
				Console.WriteLine(world.Title + ": Creating DEFAULT Surface World");
				(string, List<BNYSModBunburrowBase>) tuple3 = GenerateDefaultSurfaceLevel(enterableBurrows);
				string item = tuple3.Item1;
				List<BNYSModBunburrowBase> item2 = tuple3.Item2;
				precedingLevel = GenerateLevel(world, item, precedingLevel);
				foreach (BNYSModBunburrowBase item5 in item2)
				{
					item5.SurfaceLevel = precedingLevel;
				}
				yield return precedingLevel;
			}
		}

		private static LevelObject GenerateLevel(CustomWorld world, string levelContent, LevelObject previousLevel)
		{
			ModLevelObject val = ScriptableObject.CreateInstance<ModLevelObject>();
			((Object)val).name = "SurfaceRight BNYS";
			val.Content = levelContent;
			val.IsSurface = true;
			val.CustomNameKey = world.Title;
			val.SpecificBackground = SurfaceBurrowsPatch.ExtendedBackground;
			val.BunburrowStyle = previousLevel.BunburrowStyle;
			val.SideLevels.SetPart((Direction)0, previousLevel);
			if ((Object)(object)previousLevel != (Object)null)
			{
				previousLevel.SideLevels.SetPart((Direction)1, (LevelObject)(object)val);
			}
			return (LevelObject)(object)val;
		}

		private static (string, List<BNYSModBunburrowBase>) GenerateCoordinatesSurfaceContent(Dictionary<string, SurfaceCoordinate> coordinates, Dictionary<string, BNYSModBunburrowBase> bunburrows)
		{
			string[][] emptyLevelContent = GetEmptyLevelContent();
			List<BNYSModBunburrowBase> list = new List<BNYSModBunburrowBase>();
			foreach (KeyValuePair<string, SurfaceCoordinate> coordinate in coordinates)
			{
				if (bunburrows.TryGetValue(coordinate.Key, out var value) && coordinate.Value?.Hole != null && coordinate.Value.Hole.Length != 0)
				{
					int num = coordinate.Value.Hole[0];
					int num2 = 3;
					if (coordinate.Value.Hole.Length > 1)
					{
						num2 = coordinate.Value.Hole[1];
					}
					emptyLevelContent[num2][num] = "N" + value.ID;
					list.Add(value);
					bunburrows.Remove(coordinate.Key);
				}
			}
			return (string.Join(",", emptyLevelContent.Select((string[] row) => string.Join(",", row)).ToArray()), list);
		}

		private static (string, List<BNYSModBunburrowBase>) GenerateGridSurfaceContent(SurfaceEntryGrid grid, Dictionary<string, BNYSModBunburrowBase> bunburrows)
		{
			Dictionary<string, SurfaceCoordinate> coordinates = new Dictionary<string, SurfaceCoordinate>();
			Action<string, SurfaceCoordinate> action = delegate(string burrowName, SurfaceCoordinate coordinate)
			{
				if (!string.IsNullOrEmpty(burrowName))
				{
					coordinates.Add(burrowName, coordinate);
				}
			};
			action(grid.NW, new SurfaceCoordinate(4, 1));
			action(grid.N, new SurfaceCoordinate(7, 1));
			action(grid.NE, new SurfaceCoordinate(10, 1));
			action(grid.W, new SurfaceCoordinate(4, 3));
			action(grid.C, new SurfaceCoordinate(7, 3));
			action(grid.E, new SurfaceCoordinate(10, 3));
			action(grid.SW, new SurfaceCoordinate(4, 5));
			action(grid.S, new SurfaceCoordinate(7, 5));
			action(grid.SE, new SurfaceCoordinate(10, 5));
			return GenerateCoordinatesSurfaceContent(coordinates, bunburrows);
		}

		private static (string, List<BNYSModBunburrowBase>) GenerateDefaultSurfaceLevel(List<BNYSModBunburrowBase> bunburrows)
		{
			List<BNYSModBunburrowBase> list = new List<BNYSModBunburrowBase>();
			BNYSModBunburrowBase bNYSModBunburrowBase = bunburrows.FirstOrDefault();
			if (bNYSModBunburrowBase != null)
			{
				bunburrows.Remove(bNYSModBunburrowBase);
				list.Add(bNYSModBunburrowBase);
			}
			BNYSModBunburrowBase bNYSModBunburrowBase2 = bunburrows.FirstOrDefault();
			if (bNYSModBunburrowBase2 != null)
			{
				bunburrows.Remove(bNYSModBunburrowBase2);
				list.Add(bNYSModBunburrowBase2);
			}
			BNYSModBunburrowBase bNYSModBunburrowBase3 = bunburrows.FirstOrDefault();
			if (bNYSModBunburrowBase3 != null)
			{
				bunburrows.Remove(bNYSModBunburrowBase3);
				list.Add(bNYSModBunburrowBase3);
			}
			return (GetBasicLevelContent(bNYSModBunburrowBase, bNYSModBunburrowBase2, bNYSModBunburrowBase3), list);
		}

		private static string[][] GetEmptyLevelContent()
		{
			return new string[9]
			{
				"W,W,W,W,W,W,W,W,W,W,W,W,W,W,W",
				"W,T,T,T,T,T,T,T,T,T,T,T,W{0},W,W",
				"W,W{0},T,T,T,T,T,T,T,T,T,T,T,W,W",
				string.Format("W,T,T,T,{0},T,T,{1},T,T,{2},T,T,W,W", "T", "T", "T"),
				"T,T,T,T,T,T,T,T,T,T,T,T,T,T,T",
				"T,T,T,T,T,T,T,T,T,T,T,T,T,T,T",
				"T,T,T,T,T,T,T,T,T,T,T,T,T,T,T",
				"W,W,W,W,W,W,W,W,W,W,W,W,W,W,W",
				"W,W,W,W,W,W,W,W,W,W,W,W,W,W,W"
			}.Select((string r) => r.Split(new char[1] { ',' })).ToArray();
		}

		private static string GetBasicLevelContent(BNYSModBunburrowBase first, BNYSModBunburrowBase second, BNYSModBunburrowBase third)
		{
			string[] value = new string[9]
			{
				"W,W,W,W,W,W,W,W,W,W,W,W,W,W,W",
				"W,T,T,T,T,T,T,T,T,T,T,T,W{0},W,W",
				"W,W{0},T,T,T,T,T,T,T,T,T,T,T,W,W",
				$"W,T,T,T,{GetLevelEntryCode(first)},T,T,{GetLevelEntryCode(second)},T,T,{GetLevelEntryCode(third)},T,T,W,W",
				"T,T,T,T,T,T,T,T,T,T,T,T,T,T,T",
				"T,T,T,T,T,T,T,T,T,T,T,T,T,T,T",
				"T,T,T,T,T,T,T,T,T,T,T,T,T,T,T",
				"W,W,W,W,W,W,W,W,W,W,W,W,W,W,W",
				"W,W,W,W,W,W,W,W,W,W,W,W,W,W,W"
			};
			return string.Join(Environment.NewLine, value);
		}

		private static string GetLevelEntryCode(BNYSModBunburrowBase burrow)
		{
			if (burrow != null)
			{
				return "N" + burrow.ID;
			}
			return "T";
		}

		private static SurfaceType GetSurfaceType(SurfaceEntry surfaceEntry)
		{
			SurfaceType surfaceType = SurfaceType.None;
			int num = 0;
			if (surfaceEntry.Coordinates != null)
			{
				surfaceType |= SurfaceType.Coordinates;
				num++;
			}
			if (surfaceEntry.Grid != null)
			{
				surfaceType |= SurfaceType.Grid;
				num++;
			}
			if (num > 1)
			{
				List<string> list = new List<string>();
				foreach (SurfaceType item in Enum.GetValues(typeof(SurfaceType)).Cast<SurfaceType>())
				{
					if (surfaceType.HasFlag(item) && item != 0)
					{
						list.Add(Enum.GetName(typeof(SurfaceType), item));
					}
				}
				throw new Exception("SurfaceEntry cannot have both a Coordinates and Grid - please select only one.");
			}
			return surfaceType;
		}

		private static int CountFlags<T>(T instance) where T : Enum
		{
			int num = 0;
			foreach (T item in Enum.GetValues(typeof(T)).Cast<T>())
			{
				if (instance.HasFlag(item))
				{
					num++;
				}
			}
			return num;
		}
	}
	public class LevelValidationError
	{
		public string Message { get; private set; }

		public bool IsWarning { get; private set; }

		public LevelValidationError(string message, bool isWarning)
		{
			Message = message;
			IsWarning = isWarning;
		}

		public LevelValidationError(string message)
			: this(message, isWarning: false)
		{
		}

		public override string ToString()
		{
			return Message;
		}
	}
	public class TileValidationError : LevelValidationError
	{
		public TileValidationError(string message, int row, int column)
			: base($"Tile on Row {row}, Column {column}: {message}")
		{
		}
	}
	internal class SurfaceBurrowsPatch
	{
		private const string PatchedTexture = "PatchedTexture";

		private const string PatchedTexturePath = "ExtendedRegion.png";

		public static Sprite EndingBackground;

		public static Sprite ExtendedBackground;

		private static string lastContentPatch;

		public static void PatchSurfaceBurrows(LevelObject original, LevelObject newRightExit)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (lastContentPatch == null)
			{
				lastContentPatch = GeneratePatchedContent(original.Content);
				EndingBackground = original.SpecificBackground;
				ExtendedBackground = ImportImage.ImportSprite("PatchedTexture", Path.Combine(BNYSPlugin.rootDirectory, "ExtendedRegion.png"), new Vector2(0f, 1f), 16f);
				PatchLevel(original, lastContentPatch, ExtendedBackground);
			}
			else if (original.Content != lastContentPatch)
			{
				PatchLevel(original, lastContentPatch, ExtendedBackground);
			}
		}

		private static string GeneratePatchedContent(string content)
		{
			string[] array = content.Split(new string[3] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
			for (int i = 4; i < 7; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ',' });
				array2[12] = "T";
				array2[13] = "T";
				array2[14] = "T";
				array[i] = string.Join(",", array2);
			}
			return string.Join(Environment.NewLine, array);
		}

		private static void PatchLevel(LevelObject level, string content, Sprite replacementSprite)
		{
			Traverse obj = Traverse.Create((object)level);
			obj.Field("content").SetValue((object)content);
			obj.Field("specificBackground").SetValue((object)replacementSprite);
		}
	}
	public class BNYSLostBunburrow : IModBunburrow
	{
		public int ID { get; set; }

		public string Name { get; set; }

		public string Indicator { get; set; }

		public bool IsVoid { get; set; }

		public BunburrowStyle Style { get; set; }

		public bool HasEntrance => false;

		public bool HasSign => false;

		public BNYSLostBunburrow(CustomBunburrowModel cachedBurrow)
		{
			Name = (string.IsNullOrEmpty(cachedBurrow.World) ? string.Empty : (cachedBurrow.World + "::")) + cachedBurrow.Name;
			Indicator = (string.IsNullOrEmpty(cachedBurrow.Prefix) ? string.Empty : (cachedBurrow.Prefix + "-")) + cachedBurrow.Indicator;
		}

		public Vector2Int? OverrideSignCoordinate()
		{
			return null;
		}

		public LevelObject GetLevel(int depth)
		{
			return null;
		}

		public LevelsList GetLevels()
		{
			return null;
		}

		public LevelObject GetSurfaceLevel()
		{
			return null;
		}
	}
}
namespace Bunject.NewYardSystem.Levels.Web
{
	public class BNYSWebModBunburrow : BNYSModBunburrowBase
	{
		public new WebCustomWorld World { get; private set; }

		public BNYSWebModBunburrow(BNYSPlugin bnys, WebCustomWorld worldModel, Burrow burrowModel)
			: base(bnys, worldModel, burrowModel)
		{
			World = worldModel;
		}

		protected override BNYSLevelsList GenerateLevelsList()
		{
			BNYSLevelsList bNYSLevelsList = base.GenerateLevelsList();
			bNYSLevelsList.PermitReloading = true;
			bNYSLevelsList.DelayReloading = true;
			return bNYSLevelsList;
		}

		public override LevelMetadata LoadLevel(int depth)
		{
			string text = null;
			LevelMetadata levelMetadata = null;
			Uri uri = new Uri(base.BurrowModel.ProxyUri, $"{depth}.json");
			try
			{
				levelMetadata = uri.Load<LevelMetadata>();
				levelMetadata.IsWebLevel = true;
			}
			catch (Exception ex)
			{
				base.Bnys.Logger.LogError((object)$"{base.Name} - {depth}: File doesn't exist, Level json failed to load from web.  Ensure {depth}.json exists and conforms to JSON standards.");
				base.Bnys.Logger.LogError((object)"Error loading files related to level:");
				base.Bnys.Logger.LogError((object)Path.Combine(base.BurrowModel.Directory, depth.ToString()));
				base.Bnys.Logger.LogError((object)"Expected web endpoint:");
				base.Bnys.Logger.LogError((object)uri.ToString());
				base.Bnys.Logger.LogError((object)ex.Message);
				base.Bnys.Logger.LogError((object)ex);
				levelMetadata = CreateDefaultLevelMetadata();
			}
			if (string.IsNullOrEmpty(levelMetadata.Content))
			{
				Uri uri2 = new Uri(base.BurrowModel.ProxyUri, $"{depth}.level");
				try
				{
					text = uri2.Load();
					levelMetadata.IsWebLevel = true;
				}
				catch (Exception ex2)
				{
					base.Bnys.Logger.LogError((object)"Error loading files related to level:");
					base.Bnys.Logger.LogError((object)Path.Combine(base.BurrowModel.Directory, depth.ToString()));
					base.Bnys.Logger.LogError((object)"Expected web path:");
					base.Bnys.Logger.LogError((object)uri2);
					base.Bnys.Logger.LogError((object)ex2.Message);
					base.Bnys.Logger.LogError((object)ex2);
				}
			}
			if (string.IsNullOrEmpty(text))
			{
				base.Bnys.Logger.LogError((object)$"{base.Name} - {depth}: Level content failed to load.  Ensure {depth}.level exists and is appropriately formatted.");
				text = DefaultLevel.Content;
			}
			else
			{
				List<LevelValidationError> list = ContentValidator.ValidateLevelContent(text);
				if (list.Count > 0)
				{
					base.Bnys.Logger.LogWarning((object)$"{base.Name} - {depth}: Invalid level content found: ");
					foreach (LevelValidationError item in list)
					{
						if (item.IsWarning)
						{
							base.Bnys.Logger.LogWarning((object)item);
						}
						else
						{
							base.Bnys.Logger.LogError((object)item);
						}
					}
				}
				if (list.Any((LevelValidationError ve) => !ve.IsWarning))
				{
					text = DefaultLevel.Content;
				}
			}
			levelMetadata.Style = levelMetadata.Style ?? base.BurrowModel.Style;
			levelMetadata.Content = text;
			return levelMetadata;
		}
	}
	public class WebCustomWorld : CustomWorld
	{
		public override BNYSModBunburrowBase GenerateBunburrow(BNYSPlugin pluginRef, string bunburrowName)
		{
			return new BNYSWebModBunburrow(pluginRef, this, base.Burrows.First((Burrow b) => b.Name == bunburrowName));
		}
	}
}
namespace Bunject.NewYardSystem.Levels.Local
{
	public class BNYSLocalModBunburrow : BNYSModBunburrowBase
	{
		public new LocalCustomWorld World { get; private set; }

		public BNYSLocalModBunburrow(BNYSPlugin bnys, LocalCustomWorld worldModel, Burrow burrowModel)
			: base(bnys, worldModel, burrowModel)
		{
			World = worldModel;
		}

		public override LevelMetadata LoadLevel(int depth)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			string path = Path.Combine(base.BurrowModel.Directory, $"{depth}.level");
			string path2 = Path.Combine(base.BurrowModel.Directory, $"{depth}.json");
			string text = null;
			LevelMetadata levelMetadata = null;
			if (File.Exists(path2))
			{
				try
				{
					using StreamReader streamReader = new StreamReader(path2);
					levelMetadata = (LevelMetadata)new JsonSerializer().Deserialize((TextReader)streamReader, typeof(LevelMetadata));
				}
				catch (Exception ex)
				{
					base.Bnys.Logger.LogError((object)$"{base.Name} - {depth}: Level json failed to load.  Ensure {depth}.json exists and conforms to JSON standards.");
					base.Bnys.Logger.LogError((object)"Error loading files related to level:");
					base.Bnys.Logger.LogError((object)Path.Combine(base.BurrowModel.Directory, depth.ToString()));
					base.Bnys.Logger.LogError((object)ex.Message);
					base.Bnys.Logger.LogError((object)ex);
					levelMetadata = CreateDefaultLevelMetadata();
				}
			}
			else
			{
				base.Bnys.Logger.LogError((object)$"{base.Name} - {depth}: Level json failed to load.  Ensure {depth}.json exists and conforms to JSON standards.");
				base.Bnys.Logger.LogError((object)"Error loading files related to level:");
				base.Bnys.Logger.LogError((object)Path.Combine(base.BurrowModel.Directory, depth.ToString()));
				levelMetadata = CreateDefaultLevelMetadata();
			}
			if (string.IsNullOrEmpty(levelMetadata.Content) && File.Exists(path))
			{
				try
				{
					text = File.ReadAllText(path);
				}
				catch (Exception ex2)
				{
					base.Bnys.Logger.LogError((object)"Error loading files related to level:");
					base.Bnys.Logger.LogError((object)Path.Combine(base.BurrowModel.Directory, depth.ToString()));
					base.Bnys.Logger.LogError((object)ex2.Message);
					base.Bnys.Logger.LogError((object)ex2);
				}
			}
			if (string.IsNullOrEmpty(text))
			{
				base.Bnys.Logger.LogError((object)$"{base.Name} - {depth}: Level content failed to load.  Ensure {depth}.level exists and is appropriately formatted.");
				text = DefaultLevel.Content;
			}
			else
			{
				List<LevelValidationError> list = ContentValidator.ValidateLevelContent(text);
				if (list.Count > 0)
				{
					base.Bnys.Logger.LogWarning((object)$"{base.Name} - {depth}: Invalid level content found: ");
					foreach (LevelValidationError item in list)
					{
						if (item.IsWarning)
						{
							base.Bnys.Logger.LogWarning((object)item);
						}
						else
						{
							base.Bnys.Logger.LogError((object)item);
						}
					}
				}
				if (list.Any((LevelValidationError ve) => !ve.IsWarning))
				{
					text = DefaultLevel.Content;
				}
			}
			levelMetadata.Style = levelMetadata.Style ?? base.BurrowModel.Style;
			levelMetadata.Content = text;
			return levelMetadata;
		}
	}
	public class LocalCustomWorld : CustomWorld
	{
		public override BNYSModBunburrowBase GenerateBunburrow(BNYSPlugin pluginRef, string bunburrowName)
		{
			return new BNYSLocalModBunburrow(pluginRef, this, base.Burrows.First((Burrow b) => b.Name == bunburrowName));
		}
	}
}
namespace Bunject.NewYardSystem.Levels.Archive
{
	public class BNYSArchiveModBunburrow : BNYSModBunburrowBase
	{
		public new ArchiveCustomWorld World { get; private set; }

		public BNYSArchiveModBunburrow(BNYSPlugin bnys, ArchiveCustomWorld worldModel, Burrow burrowModel)
			: base(bnys, worldModel, burrowModel)
		{
			World = worldModel;
		}

		protected override BNYSLevelsList GenerateLevelsList()
		{
			BNYSLevelsList bNYSLevelsList = base.GenerateLevelsList();
			bNYSLevelsList.PermitReloading = false;
			return bNYSLevelsList;
		}

		public override LevelMetadata LoadLevel(int depth)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			string entryName = base.BurrowModel.Directory + "/" + $"{depth}.level";
			string text = base.BurrowModel.Directory + "/" + $"{depth}.json";
			string text2 = null;
			LevelMetadata levelMetadata = null;
			ZipArchiveEntry entry = World.Archive.GetEntry(text);
			if (entry != null)
			{
				try
				{
					using Stream stream = entry.Open();
					using StreamReader streamReader = new StreamReader(stream);
					levelMetadata = (LevelMetadata)new JsonSerializer().Deserialize((TextReader)streamReader, typeof(LevelMetadata));
				}
				catch (Exception ex)
				{
					base.Bnys.Logger.LogError((object)$"{base.Name} - {depth}: Level json failed to load.  Ensure {depth}.json exists and conforms to JSON standards.");
					base.Bnys.Logger.LogError((object)"Error reading zip file entry related to level:");
					base.Bnys.Logger.LogError((object)text);
					base.Bnys.Logger.LogError((object)ex.Message);
					base.Bnys.Logger.LogError((object)ex);
					levelMetadata = CreateDefaultLevelMetadata();
				}
			}
			else
			{
				base.Bnys.Logger.LogError((object)$"{base.Name} - {depth}: Level json failed to load.  Ensure {depth}.json exists and conforms to JSON standards.");
				base.Bnys.Logger.LogError((object)"Could not find zip file entry:");
				base.Bnys.Logger.LogError((object)text);
				levelMetadata = CreateDefaultLevelMetadata();
			}
			if (string.IsNullOrEmpty(levelMetadata.Content))
			{
				ZipArchiveEntry entry2 = World.Archive.GetEntry(entryName);
				if (entry2 != null)
				{
					try
					{
						using Stream stream2 = entry2.Open();
						using StreamReader streamReader2 = new StreamReader(stream2);
						text2 = streamReader2.ReadToEnd();
					}
					catch (Exception ex2)
					{
						base.Bnys.Logger.LogError((object)"Error reading archive entry related to level content:");
						base.Bnys.Logger.LogError((object)Path.Combine(base.BurrowModel.Directory, depth.ToString()));
						base.Bnys.Logger.LogError((object)ex2.Message);
						base.Bnys.Logger.LogError((object)ex2);
					}
				}
			}
			if (string.IsNullOrEmpty(text2))
			{
				base.Bnys.Logger.LogError((object)$"{base.Name} - {depth}: Level content failed to load.  Ensure {depth}.level exists and is appropriately formatted.");
				text2 = DefaultLevel.Content;
			}
			else
			{
				List<LevelValidationError> list = ContentValidator.ValidateLevelContent(text2);
				if (list.Count > 0)
				{
					base.Bnys.Logger.LogWarning((object)$"{base.Name} - {depth}: Invalid level content found: ");
					foreach (LevelValidationError item in list)
					{
						if (item.IsWarning)
						{
							base.Bnys.Logger.LogWarning((object)item);
						}
						else
						{
							base.Bnys.Logger.LogError((object)item);
						}
					}
				}
				if (list.Any((LevelValidationError ve) => !ve.IsWarning))
				{
					text2 = DefaultLevel.Content;
				}
			}
			levelMetadata.Style = levelMetadata.Style ?? base.BurrowModel.Style;
			levelMetadata.Content = text2;
			return levelMetadata;
		}
	}
	public class ArchiveCustomWorld : CustomWorld
	{
		[JsonIgnore]
		public ZipArchive Archive { get; set; }

		public override BNYSModBunburrowBase GenerateBunburrow(BNYSPlugin pluginRef, string bunburrowName)
		{
			return new BNYSArchiveModBunburrow(pluginRef, this, base.Burrows.First((Burrow b) => b.Name == bunburrowName));
		}
	}
}
namespace Bunject.NewYardSystem.Exceptions
{
	public class InvalidBurrowLinkException : Exception
	{
		public InvalidBurrowLinkException(string worldName, string burrowName, string linkDirection, string linkName)
			: base(worldName + " - " + burrowName + " has an invalid " + linkDirection + " burrow link: '" + linkName + "'")
		{
		}
	}
}