Decompiled source of CustomPosters v4.0.2

BepInEx/plugins/CustomPosters/CustomPosters.dll

Decompiled 2 days ago
using System;
using System.Collections;
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.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CustomPosters.Data;
using CustomPosters.Data.PosterLayouts;
using CustomPosters.Data.PosterLayouts.Legacy;
using CustomPosters.Networking;
using CustomPosters.Patches;
using CustomPosters.Utils;
using HarmonyLib;
using LethalNetworkAPI;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Video;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CustomPosters")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Replaces the default posters in the ship with custom posters")]
[assembly: AssemblyFileVersion("4.0.2.0")]
[assembly: AssemblyInformationalVersion("4.0.2+c3ee4d65edc757e8332a2e464098fe3375173973")]
[assembly: AssemblyProduct("CustomPosters")]
[assembly: AssemblyTitle("CustomPosters")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("4.0.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.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;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CustomPosters
{
	internal static class AssetManager
	{
		public static AssetBundle? Bundle { get; private set; }

		public static GameObject? PosterPrefab { get; private set; }

		public static GameObject? Poster5Prefab { get; private set; }

		public static GameObject? TipsPrefab { get; private set; }

		public static void LoadAssets()
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string directoryName = Path.GetDirectoryName(executingAssembly.Location);
			string text = Path.Combine(directoryName, "customposters");
			Bundle = AssetBundle.LoadFromFile(text);
			if ((Object)(object)Bundle == (Object)null)
			{
				Plugin.Log.LogError((object)"Failed to load AssetBundle.");
				return;
			}
			PosterPrefab = Bundle.LoadAsset<GameObject>("CustomPosterPrefab");
			Poster5Prefab = Bundle.LoadAsset<GameObject>("Poster5");
			TipsPrefab = Bundle.LoadAsset<GameObject>("Tips");
			if ((Object)(object)PosterPrefab == (Object)null)
			{
				Plugin.Log.LogError((object)"Failed to load prefab from the AssetBundle.");
			}
			else
			{
				Plugin.Log.LogInfo((object)"Loaded assetbundle.");
			}
			if ((Object)(object)Poster5Prefab == (Object)null)
			{
				Plugin.Log.LogError((object)"Failed to load Poster5 prefab from the AssetBundle.");
			}
			if ((Object)(object)TipsPrefab == (Object)null)
			{
				Plugin.Log.LogError((object)"Failed to load Tips prefab from the AssetBundle.");
			}
		}
	}
	internal static class Constants
	{
		public static readonly string[] ValidImageExtensions = new string[4] { ".png", ".jpg", ".jpeg", ".bmp" };

		public static readonly string[] ValidVideoExtensions = new string[1] { ".mp4" };

		public static readonly string[] AllValidExtensions = new string[5] { ".png", ".jpg", ".jpeg", ".bmp", ".mp4" };

		public const string PluginsFolderName = "plugins";

		public const int DefaultVideoVolume = 10;

		public const float DefaultVideoMaxDistance = 3.5f;

		public static readonly string[] ExcludedModFolderNames = new string[3] { "CustomPosters", "seechela-CustomPosters", "plugins" };

		public const string BiggerShipGUID = "BiggerShip";

		public const string ShipWindowsGUID = "TestAccount666.ShipWindows";

		public const string WiderShipModGUID = "mborsh.WiderShipMod";

		public const string TwoStoryShipGUID = "MelanieMelicious.2StoryShip";

		public const string PosterNamePoster1 = "Poster1";

		public const string PosterNamePoster2 = "Poster2";

		public const string PosterNamePoster3 = "Poster3";

		public const string PosterNamePoster4 = "Poster4";

		public const string PosterNamePoster5 = "Poster5";

		public const string PosterNameCustomTips = "CustomTips";

		public const string WiderShipSideLeft = "Left";

		public const string WiderShipSideRight = "Right";

		public const string WiderShipSideBoth = "Both";

		public const string SinglePackFolderName = "CustomPosters";

		public const string PackSyncIdentifier = "CustomPosters_SyncPack";

		public const string VideoRequestIdentifier = "CustomPosters_RequestVideoTime";

		public const string VideoSyncIdentifier = "CustomPosters_SyncVideoTime";

		public const string Es3SelectedPackKey = "CustomPosters_SelectedPack";

		public const int PosterRenderTextureWidth = 512;

		public const int PosterRenderTextureHeight = 512;

		public const int PosterRenderTextureDepth = 16;
	}
	[BepInPlugin("CustomPosters", "CustomPosters", "4.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private readonly Harmony _harmony = new Harmony("CustomPosters");

		public static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		public static PosterService Service { get; private set; }

		public static PosterConfig ModConfig { get; private set; }

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"Initializing CustomPosters");
			AssetManager.LoadAssets();
			ModConfig = new PosterConfig(((BaseUnityPlugin)this).Config);
			Service = new PosterService();
			ModConfig.Initialize();
			Log.LogInfo((object)"Applying patches");
			_harmony.PatchAll(typeof(StartOfRoundPatch));
			_harmony.PatchAll(typeof(GameNetworkManagerPatch));
			Log.LogInfo((object)"CustomPosters is loaded!");
		}
	}
	internal class FileConfig
	{
		public ConfigEntry<bool> Enabled { get; }

		public ConfigEntry<int> Chance { get; }

		public ConfigEntry<int>? Volume { get; set; }

		public ConfigEntry<float>? MaxDistance { get; set; }

		public ConfigEntry<PosterConfig.VideoAspectRatio>? AspectRatio { get; set; }

		public FileConfig(ConfigEntry<bool> enabled, ConfigEntry<int> chance)
		{
			Enabled = enabled;
			Chance = chance;
		}
	}
	public class PosterConfig
	{
		[Serializable]
		public enum RandomizerMode
		{
			PerPack,
			PerPoster
		}

		[Serializable]
		public enum VideoAspectRatio
		{
			Stretch,
			FitInside,
			FitOutside,
			NoScaling
		}

		[Serializable]
		public enum KeepFor
		{
			Lobby,
			Session,
			SaveSlot
		}

		[Flags]
		public enum VanillaModelOption
		{
			None = 0,
			Poster5 = 1,
			Tips = 2,
			Both = 3
		}

		private readonly Dictionary<string, ConfigEntry<bool>> _packEnabledEntries = new Dictionary<string, ConfigEntry<bool>>();

		private readonly Dictionary<string, ConfigEntry<int>> _packChanceEntries = new Dictionary<string, ConfigEntry<int>>();

		private readonly Dictionary<string, FileConfig> _fileConfigs = new Dictionary<string, FileConfig>();

		private readonly ConfigFile _configFile;

		public ConfigEntry<bool> EnableNetworking { get; private set; }

		public ConfigEntry<RandomizerMode> RandomizerModeSetting { get; private set; }

		public ConfigEntry<KeepFor> KeepPackFor { get; private set; }

		public ConfigEntry<bool> EnableTextureCaching { get; private set; }

		public ConfigEntry<bool> EnableVideoAudio { get; private set; }

		public ConfigEntry<VanillaModelOption> VanillaModelSelection { get; private set; }

		public bool UsePoster5VanillaModel => VanillaModelSelection.Value.HasFlag(VanillaModelOption.Poster5);

		public bool UseTipsVanillaModel => VanillaModelSelection.Value.HasFlag(VanillaModelOption.Tips);

		public PosterConfig(ConfigFile config)
		{
			_configFile = config;
		}

		public void Initialize()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Expected O, but got Unknown
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Expected O, but got Unknown
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Expected O, but got Unknown
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Expected O, but got Unknown
			_configFile.SaveOnConfigSet = false;
			EnableNetworking = _configFile.Bind<bool>("1. Settings", "Enable Networking", true, "Sync posters with all players (requires all to have the mod); false = client-side, makes compatible with vanilla lobbies.");
			RandomizerModeSetting = _configFile.Bind<RandomizerMode>("1. Settings", "RandomizerMode", RandomizerMode.PerPack, "Controls randomization: PerPack selects one pack for all posters; PerPoster randomizes each poster from enabled packs.");
			KeepPackFor = _configFile.Bind<KeepFor>("1. Settings", "Keep pack for", KeepFor.Lobby, "Keeping selection: Lobby = reroll each lobby; Session = until game restart; Save slot = per save file.");
			VanillaModelSelection = _configFile.Bind<VanillaModelOption>("1. Settings", "Vanilla Model", VanillaModelOption.Both, new ConfigDescription("Choose vanilla LC mesh: None (use quads), Poster5, Tips, or Both.", (AcceptableValueBase)null, Array.Empty<object>()));
			EnableVideoAudio = _configFile.Bind<bool>("1. Settings", "EnableVideoAudio", false, "Enable audio for .mp4 poster videos; disable to mute.");
			EnableTextureCaching = _configFile.Bind<bool>("1. Settings", "EnableTextureCaching", false, "Cache textures/videos in memory to improve performance; disable to reduce memory usage.");
			int num = 2;
			foreach (string posterFolder in Plugin.Service.PosterFolders)
			{
				try
				{
					string text = PackName(posterFolder);
					if (string.IsNullOrEmpty(text))
					{
						continue;
					}
					string text2 = $"{num}. {text}";
					string text3 = $"{num}. {text} - Chances";
					ConfigEntry<bool> value = _configFile.Bind<bool>(text2, "Enabled", true, "Enable or disable the " + text + " pack");
					_packEnabledEntries[text] = value;
					ConfigEntry<int> value2 = _configFile.Bind<int>(text3, "Global chance", 0, new ConfigDescription("Chance of selecting the " + text + " pack in PerPack mode; 0 = equal probability with other packs.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
					_packChanceEntries[text] = value2;
					IEnumerable<string> filesFromPack = GetFilesFromPack(posterFolder);
					foreach (string item in filesFromPack)
					{
						string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item);
						string text4 = Path.GetExtension(item).TrimStart('.').ToUpper();
						string fileName = Path.GetFileName(item);
						string text5 = fileNameWithoutExtension + "-" + text4;
						ConfigEntry<bool> enabled = _configFile.Bind<bool>(text2, text5, true, "Enable or disable poster file '" + fileName + "' in pack '" + text + "'");
						ConfigEntry<int> chance = _configFile.Bind<int>(text3, text5 + " Chance", 0, new ConfigDescription("Chance of selecting poster '" + fileName + "' in PerPoster mode; 0 = equal probability with other posters.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
						FileConfig fileConfig = new FileConfig(enabled, chance);
						if (text4 == "MP4")
						{
							fileConfig.Volume = _configFile.Bind<int>(text2, text5 + " Volume", 10, new ConfigDescription("Volume for video '" + fileName + "'.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
							fileConfig.MaxDistance = _configFile.Bind<float>(text2, text5 + " MaxDistance", 3.5f, new ConfigDescription("Maximum distance for audio playback of video '" + fileName + "'", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
							fileConfig.AspectRatio = _configFile.Bind<VideoAspectRatio>(text2, text5 + " AspectRatio", VideoAspectRatio.Stretch, "Aspect ratio for video '" + fileName + "': Stretch (fill), FitInside (no crop), FitOutside (may crop), NoScaling (original size).");
						}
						_fileConfigs[item] = fileConfig;
					}
					num++;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)("Failed to generate config for pack at " + PathUtils.GetPrettyPath(posterFolder) + ": " + ex.Message));
				}
			}
			ClearOrphanedEntries();
			_configFile.Save();
			_configFile.SaveOnConfigSet = true;
			Plugin.Log.LogInfo((object)$"Found {_packEnabledEntries.Count} packs and {_fileConfigs.Count} poster files");
		}

		public bool IsPackEnabled(string packPath)
		{
			string key = PackName(packPath);
			if (_packEnabledEntries.TryGetValue(key, out ConfigEntry<bool> value))
			{
				return value.Value;
			}
			return true;
		}

		public int GetPackChance(string packPath)
		{
			string key = PackName(packPath);
			if (_packChanceEntries.TryGetValue(key, out ConfigEntry<int> value))
			{
				return value.Value;
			}
			return 0;
		}

		public bool IsFileEnabled(string filePath)
		{
			if (_fileConfigs.TryGetValue(Path.GetFullPath(filePath), out FileConfig value))
			{
				return value.Enabled.Value;
			}
			return true;
		}

		public int GetFileChance(string filePath)
		{
			if (_fileConfigs.TryGetValue(Path.GetFullPath(filePath), out FileConfig value))
			{
				return value.Chance.Value;
			}
			return 0;
		}

		public (int volume, float maxDistance, VideoAspectRatio aspectRatio) GetFileAudioSettings(string filePath)
		{
			if (_fileConfigs.TryGetValue(Path.GetFullPath(filePath), out FileConfig value))
			{
				int item = value.Volume?.Value ?? 10;
				float item2 = value.MaxDistance?.Value ?? 3.5f;
				VideoAspectRatio item3 = value.AspectRatio?.Value ?? VideoAspectRatio.Stretch;
				return (item, item2, item3);
			}
			return (10, 3.5f, VideoAspectRatio.Stretch);
		}

		private static string PackName(string packPath)
		{
			return PathUtils.GetDisplayPackName(packPath);
		}

		private static IEnumerable<string> GetFilesFromPack(string packPath)
		{
			List<string> list = new List<string>();
			string path = Path.Combine(packPath, "posters");
			if (Directory.Exists(path))
			{
				list.AddRange(from f in Directory.GetFiles(path)
					where Constants.AllValidExtensions.Contains(Path.GetExtension(f).ToLowerInvariant())
					select f);
			}
			string path2 = Path.Combine(packPath, "tips");
			if (Directory.Exists(path2))
			{
				list.AddRange(from f in Directory.GetFiles(path2)
					where Constants.AllValidExtensions.Contains(Path.GetExtension(f).ToLowerInvariant())
					select f);
			}
			string text = Path.Combine(packPath, "CustomTips.png");
			if (File.Exists(text))
			{
				list.Add(text);
			}
			list.AddRange(from f in Directory.GetFiles(packPath)
				where Constants.AllValidExtensions.Contains(Path.GetExtension(f).ToLowerInvariant())
				select f);
			return from f in list.Distinct<string>(StringComparer.OrdinalIgnoreCase)
				select Path.GetFullPath(f);
		}

		private void ClearOrphanedEntries()
		{
			try
			{
				PropertyInfo propertyInfo = AccessTools.Property(typeof(ConfigFile), "OrphanedEntries");
				if (propertyInfo != null && propertyInfo.GetValue(_configFile) is Dictionary<ConfigDefinition, string> dictionary)
				{
					dictionary.Clear();
					Plugin.Log.LogDebug((object)"Cleared orphaned config entries");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not clear orphaned config entries: " + ex.Message));
			}
		}
	}
	internal static class PosterManager
	{
		[CompilerGenerated]
		private sealed class <>c__DisplayClass26_0
		{
			public string[] validExtensions;

			public Func<string, bool> <>9__4;

			internal bool <CreateCustomPostersAsync>b__4(string f)
			{
				if (validExtensions.Contains(Path.GetExtension(f).ToLower()))
				{
					return Plugin.ModConfig.IsFileEnabled(f);
				}
				return false;
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass26_1
		{
			public (Texture2D? texture, string? filePath) textureResult;

			public Task loadTask;

			internal void <CreateCustomPostersAsync>b__6((Texture2D? texture, string? filePath) result)
			{
				textureResult = result;
			}

			internal bool <CreateCustomPostersAsync>b__7()
			{
				return loadTask.IsCompleted;
			}
		}

		[CompilerGenerated]
		private sealed class <CreateCustomPostersAsync>d__26 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			private <>c__DisplayClass26_1 <>8__1;

			private GameObject <hangarShip>5__2;

			private GameObject <postersParent>5__3;

			private GameObject <posterPlane>5__4;

			private PosterData[] <posterData>5__5;

			private Dictionary<string, List<(Texture2D texture, string filePath)>> <allTextures>5__6;

			private Dictionary<string, List<string>> <allVideos>5__7;

			private Dictionary<string, (Texture2D? texture, string filePath, bool isVideo)> <prioritizedContent>5__8;

			private bool <anyPosterLoaded>5__9;

			private List<string>.Enumerator <>7__wrap9;

			private List<string> <filesToLoad>5__11;

			private int <i>5__12;

			private List<string>.Enumerator <>7__wrap12;

			private string <file>5__14;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <CreateCustomPostersAsync>d__26(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if ((uint)(num - -4) <= 1u || (uint)(num - 1) <= 1u)
				{
					try
					{
						if (num == -4 || num == 1)
						{
							try
							{
							}
							finally
							{
								<>m__Finally2();
							}
						}
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>8__1 = null;
				<hangarShip>5__2 = null;
				<postersParent>5__3 = null;
				<posterPlane>5__4 = null;
				<posterData>5__5 = null;
				<allTextures>5__6 = null;
				<allVideos>5__7 = null;
				<prioritizedContent>5__8 = null;
				<>7__wrap9 = default(List<string>.Enumerator);
				<filesToLoad>5__11 = null;
				<>7__wrap12 = default(List<string>.Enumerator);
				<file>5__14 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Expected O, but got Unknown
				//IL_008b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a4b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a6d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a72: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a94: Unknown result type (might be due to invalid IL or missing references)
				//IL_06b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_06c2: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
					{
						<>1__state = -1;
						CleanUpPosters();
						<hangarShip>5__2 = GameObject.Find("Environment/HangarShip");
						if ((Object)(object)<hangarShip>5__2 == (Object)null)
						{
							return false;
						}
						<postersParent>5__3 = new GameObject("CustomPosters");
						<postersParent>5__3.transform.SetParent(<hangarShip>5__2.transform);
						<postersParent>5__3.transform.localPosition = Vector3.zero;
						<posterPlane>5__4 = GameObject.Find("Environment/HangarShip/Plane.001");
						<posterData>5__5 = PosterLayoutProvider.GetLayout();
						List<string> list3 = Plugin.Service.PosterFolders.Where((string folder) => Plugin.ModConfig.IsPackEnabled(folder)).ToList();
						bool flag = Plugin.ModConfig.EnableNetworking.Value && !ShouldActAsHost && !string.IsNullOrEmpty(_selectedPack);
						if (list3.Count == 0 && !flag)
						{
							Plugin.Log.LogWarning((object)"No enabled packs found");
							if ((Object)(object)<posterPlane>5__4 != (Object)null)
							{
								<posterPlane>5__4.SetActive(true);
							}
							return false;
						}
						List<string> list4 = list3.Select((string pack) => Path.GetFileName(pack)).ToList();
						List<string> list6;
						if (Plugin.ModConfig.RandomizerModeSetting.Value == PosterConfig.RandomizerMode.PerPack)
						{
							if (ShouldActAsHost)
							{
								PosterConfig.KeepFor value2 = Plugin.ModConfig.KeepPackFor.Value;
								if (value2 == PosterConfig.KeepFor.SaveSlot)
								{
									string value3 = SavePersistenceManager.TryGetCurrentSaveId();
									if (string.IsNullOrEmpty(value3))
									{
										_selectedPack = null;
									}
								}
								if (value2 switch
								{
									PosterConfig.KeepFor.Lobby => true, 
									PosterConfig.KeepFor.Session => _selectedPack == null || !list3.Contains(_selectedPack), 
									PosterConfig.KeepFor.SaveSlot => _selectedPack == null || !list3.Contains(_selectedPack), 
									_ => true, 
								})
								{
									List<string> list5 = new List<string>(list3);
									string selectedPack = null;
									while (list5.Count > 0)
									{
										string text5 = PackSelector.SelectPackByChance(list5);
										if (PackHasValidFiles(text5))
										{
											selectedPack = text5;
											break;
										}
										list5.Remove(text5);
									}
									_selectedPack = selectedPack;
									if (!string.IsNullOrEmpty(_selectedPack) && value2 == PosterConfig.KeepFor.SaveSlot)
									{
										try
										{
											string text6 = SavePersistenceManager.TryGetCurrentSaveId();
											if (!string.IsNullOrEmpty(text6))
											{
												SavePersistenceManager.SaveSelectedPack(text6, _selectedPack);
												Plugin.Log.LogInfo((object)("Saved selected pack for save '" + text6 + "'"));
											}
											else
											{
												Plugin.Log.LogDebug((object)"PerSave: No valid saveId yet; not persisting selection.");
											}
										}
										catch (Exception ex)
										{
											Plugin.Log.LogDebug((object)("SaveSlot save skipped: " + ex.Message));
										}
									}
								}
								if (!string.IsNullOrEmpty(_selectedPack) && Plugin.ModConfig.EnableNetworking.Value)
								{
									PosterSyncManager.SendPacket(_selectedPack);
								}
							}
							if (string.IsNullOrEmpty(_selectedPack))
							{
								Plugin.Log.LogInfo((object)(Plugin.ModConfig.EnableNetworking.Value ? "Client is waiting for host to select a pack..." : "No valid pack found, falling back to vanilla posters"));
								if ((Object)(object)<posterPlane>5__4 != (Object)null)
								{
									<posterPlane>5__4.SetActive(true);
								}
								return false;
							}
							string displayPackName = PathUtils.GetDisplayPackName(_selectedPack);
							Plugin.Log.LogInfo((object)("Using pack: " + displayPackName));
							list6 = new List<string> { _selectedPack };
						}
						else
						{
							list6 = list3;
							Plugin.Log.LogInfo((object)"PerPoster mode enabled.");
						}
						<allTextures>5__6 = new Dictionary<string, List<(Texture2D, string)>>();
						<allVideos>5__7 = new Dictionary<string, List<string>>();
						<>7__wrap9 = list6.GetEnumerator();
						<>1__state = -3;
						goto IL_080d;
					}
					case 1:
						<>1__state = -4;
						if ((Object)(object)<>8__1.textureResult.texture != (Object)null && <>8__1.textureResult.filePath != null)
						{
							string key = Path.GetFileNameWithoutExtension(<>8__1.textureResult.filePath).ToLower();
							if (!<allTextures>5__6.ContainsKey(key))
							{
								<allTextures>5__6[key] = new List<(Texture2D, string)>();
							}
							<allTextures>5__6[key].Add((<>8__1.textureResult.texture, <>8__1.textureResult.filePath));
						}
						else
						{
							Plugin.Log.LogWarning((object)("Failed to load texture from " + <file>5__14));
						}
						<>8__1 = null;
						goto IL_079c;
					case 2:
						<>1__state = -3;
						<i>5__12 += 5;
						goto IL_07f0;
					case 3:
						{
							<>1__state = -1;
							goto IL_0b91;
						}
						IL_0ba3:
						if (<i>5__12 < <posterData>5__5.Length)
						{
							GameObject val = CreatePoster(<posterData>5__5[<i>5__12].Name);
							if (!((Object)(object)val == (Object)null))
							{
								((Object)val).name = <posterData>5__5[<i>5__12].Name;
								val.transform.SetParent(<postersParent>5__3.transform);
								val.transform.position = <posterData>5__5[<i>5__12].Position;
								val.transform.rotation = Quaternion.Euler(<posterData>5__5[<i>5__12].Rotation);
								val.transform.localScale = <posterData>5__5[<i>5__12].Scale;
								string key2 = <posterData>5__5[<i>5__12].Name.ToLower();
								if (<prioritizedContent>5__8.TryGetValue(key2, out (Texture2D, string, bool) value) && Plugin.ModConfig.IsFileEnabled(value.Item2))
								{
									PosterRenderer posterRenderer = val.AddComponent<PosterRenderer>();
									(Texture2D, string, bool) tuple = value;
									Texture2D item = tuple.Item1;
									string item2 = tuple.Item2;
									bool item3 = tuple.Item3;
									MeshRenderer component = val.GetComponent<MeshRenderer>();
									posterRenderer.Initialize(item, item3 ? item2 : null, (component != null) ? ((Renderer)component).material : null);
									CreatedPosters.Add(val);
									<anyPosterLoaded>5__9 = true;
								}
								else
								{
									Plugin.Log.LogWarning((object)("No enabled texture found for " + <posterData>5__5[<i>5__12].Name + ". Destroying the poster"));
									Object.Destroy((Object)(object)val);
								}
								<>2__current = null;
								<>1__state = 3;
								return true;
							}
							goto IL_0b91;
						}
						if (<anyPosterLoaded>5__9)
						{
							if ((Object)(object)<posterPlane>5__4 != (Object)null)
							{
								Object.Destroy((Object)(object)<posterPlane>5__4);
							}
							Transform obj = <hangarShip>5__2.transform.Find("Plane");
							GameObject val2 = ((obj != null) ? ((Component)obj).gameObject : null);
							if ((Object)(object)val2 != (Object)null)
							{
								Object.Destroy((Object)(object)val2);
							}
							Plugin.Log.LogInfo((object)"Posters created successfully!");
						}
						else if ((Object)(object)<posterPlane>5__4 != (Object)null)
						{
							<posterPlane>5__4.SetActive(true);
							Plugin.Log.LogWarning((object)"Re-enabled vanilla Plane.001 poster due to no textures loaded");
						}
						return false;
						IL_07f0:
						if (<i>5__12 < <filesToLoad>5__11.Count)
						{
							List<string> list = <filesToLoad>5__11.Skip(<i>5__12).Take(5).ToList();
							<>7__wrap12 = list.GetEnumerator();
							<>1__state = -4;
							goto IL_07a3;
						}
						<filesToLoad>5__11 = null;
						goto IL_080d;
						IL_07a3:
						if (<>7__wrap12.MoveNext())
						{
							<file>5__14 = <>7__wrap12.Current;
							if (Path.GetExtension(<file>5__14).ToLower() == ".mp4")
							{
								string key3 = Path.GetFileNameWithoutExtension(<file>5__14).ToLower();
								if (!<allVideos>5__7.ContainsKey(key3))
								{
									<allVideos>5__7[key3] = new List<string>();
								}
								<allVideos>5__7[key3].Add(<file>5__14);
								Plugin.Service.CacheVideo(<file>5__14);
								goto IL_079c;
							}
							<>8__1 = new <>c__DisplayClass26_1();
							<>8__1.textureResult = (null, null);
							<>8__1.loadTask = LoadTextureAsync(<file>5__14, delegate((Texture2D? texture, string? filePath) result)
							{
								<>8__1.textureResult = result;
							});
							<>2__current = (object)new WaitUntil((Func<bool>)(() => <>8__1.loadTask.IsCompleted));
							<>1__state = 1;
							return true;
						}
						<>m__Finally2();
						<>7__wrap12 = default(List<string>.Enumerator);
						<>2__current = null;
						<>1__state = 2;
						return true;
						IL_080d:
						if (<>7__wrap9.MoveNext())
						{
							string current = <>7__wrap9.Current;
							<>c__DisplayClass26_0 CS$<>8__locals0 = new <>c__DisplayClass26_0();
							string fileName = Path.GetFileName(current);
							string text = Path.Combine(current, "posters");
							string text2 = Path.Combine(current, "tips");
							string text3 = Path.Combine(current, "CustomPosters", "posters");
							string text4 = Path.Combine(current, "CustomPosters", "tips");
							<filesToLoad>5__11 = new List<string>();
							CS$<>8__locals0.validExtensions = new string[5] { ".png", ".jpg", ".jpeg", ".bmp", ".mp4" };
							List<string> list2 = (from p in new string[4] { text, text2, text3, text4 }
								where Directory.Exists(p)
								select Path.GetFullPath(p).Replace('\\', '/')).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList();
							foreach (string item5 in list2)
							{
								List<string> collection = (from f in Directory.GetFiles(item5)
									where CS$<>8__locals0.validExtensions.Contains(Path.GetExtension(f).ToLower()) && Plugin.ModConfig.IsFileEnabled(f)
									select Path.GetFullPath(f).Replace('\\', '/')).ToList();
								<filesToLoad>5__11.AddRange(collection);
							}
							<filesToLoad>5__11 = <filesToLoad>5__11.Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList();
							<i>5__12 = 0;
							goto IL_07f0;
						}
						<>m__Finally1();
						<>7__wrap9 = default(List<string>.Enumerator);
						<prioritizedContent>5__8 = new Dictionary<string, (Texture2D, string, bool)>();
						foreach (KeyValuePair<string, List<(Texture2D, string)>> item6 in <allTextures>5__6)
						{
							(Texture2D, string) tuple2 = PackSelector.SelectContentByChance<(Texture2D, string)>(item6.Value, ((Texture2D texture, string filePath) t) => Plugin.ModConfig.GetFileChance(t.filePath), ((Texture2D texture, string filePath) t) => Plugin.Service.GetFilePriority(t.filePath));
							<prioritizedContent>5__8[item6.Key] = (tuple2.Item1, tuple2.Item2, false);
						}
						foreach (KeyValuePair<string, List<string>> item7 in <allVideos>5__7)
						{
							string item4 = PackSelector.SelectContentByChance(item7.Value, (string v) => Plugin.ModConfig.GetFileChance(v), (string v) => Plugin.Service.GetFilePriority(v));
							<prioritizedContent>5__8[item7.Key] = (null, item4, true);
						}
						if (<allTextures>5__6.Count == 0 && <allVideos>5__7.Count == 0)
						{
							Plugin.Log.LogWarning((object)"No textures found in enabled packs");
							if ((Object)(object)<posterPlane>5__4 != (Object)null)
							{
								<posterPlane>5__4.SetActive(true);
							}
							return false;
						}
						<anyPosterLoaded>5__9 = false;
						<i>5__12 = 0;
						goto IL_0ba3;
						IL_079c:
						<file>5__14 = null;
						goto IL_07a3;
						IL_0b91:
						<i>5__12++;
						goto IL_0ba3;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>7__wrap9).Dispose();
			}

			private void <>m__Finally2()
			{
				<>1__state = -3;
				((IDisposable)<>7__wrap12).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <DelayedUpdateMaterialsAsync>d__28 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public StartOfRound instance;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DelayedUpdateMaterialsAsync>d__28(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (_materialsUpdated)
					{
						return false;
					}
					<>2__current = (object)new WaitForEndOfFrame();
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					HideVanillaPosterPlane();
					<>2__current = ((MonoBehaviour)instance).StartCoroutine(CreateCustomPostersAsync());
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					_materialsUpdated = true;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static bool _materialsUpdated = false;

		internal static string? _selectedPack = null;

		private static readonly List<GameObject> CreatedPosters = new List<GameObject>();

		private static int _sessionMapSeed = 0;

		private static bool _sessionSeedInitialized = false;

		public static string? SelectedPack => _selectedPack;

		public static bool IsNewLobby { get; set; } = true;


		private static bool ShouldActAsHost
		{
			get
			{
				if (Plugin.ModConfig.EnableNetworking.Value)
				{
					if ((Object)(object)NetworkManager.Singleton != (Object)null)
					{
						return NetworkManager.Singleton.IsHost;
					}
					return false;
				}
				return true;
			}
		}

		public static void ResetSession()
		{
			_sessionSeedInitialized = false;
			_sessionMapSeed = 0;
			_selectedPack = null;
			Plugin.Log.LogDebug((object)"Session randomization reset.");
		}

		public static void SetPackForClients(string packName)
		{
			if (!Plugin.ModConfig.EnableNetworking.Value || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.IsHost)
			{
				return;
			}
			Plugin.Log.LogDebug((object)("Client received selected pack from host: " + PathUtils.GetPrettyPath(packName)));
			_selectedPack = LocalPackPath(packName);
			if (string.IsNullOrEmpty(_selectedPack))
			{
				Plugin.Log.LogWarning((object)"Could not resolve host selected pack on client. Keeping vanilla posters.");
				return;
			}
			_materialsUpdated = false;
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance != (Object)null && instance.inShipPhase)
			{
				((MonoBehaviour)instance).StartCoroutine(DelayedUpdateMaterialsAsync(instance));
			}
		}

		private static string? LocalPackPath(string hostPackIdentifier)
		{
			try
			{
				string displayPackName = PathUtils.GetDisplayPackName(hostPackIdentifier);
				string fileName = Path.GetFileName(hostPackIdentifier.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
				foreach (string posterFolder in Plugin.Service.PosterFolders)
				{
					if (string.Equals(PathUtils.GetDisplayPackName(posterFolder), displayPackName, StringComparison.OrdinalIgnoreCase))
					{
						return posterFolder;
					}
				}
				foreach (string posterFolder2 in Plugin.Service.PosterFolders)
				{
					if (string.Equals(Path.GetFileName(posterFolder2), fileName, StringComparison.OrdinalIgnoreCase))
					{
						return posterFolder2;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("LocalPackPath error: " + ex.Message));
			}
			return null;
		}

		public static void OnRoundStart(StartOfRound instance)
		{
			_materialsUpdated = false;
			if (IsNewLobby && ShouldActAsHost)
			{
				InitializeSessionSeedIfNeeded();
				int randomSeed = ComputeSeedAndMaybeLoadSavePack(Plugin.ModConfig.KeepPackFor.Value);
				Plugin.Service.SetRandomSeed(randomSeed);
			}
			if (instance.inShipPhase)
			{
				((MonoBehaviour)instance).StartCoroutine(DelayedUpdateMaterialsAsync(instance));
			}
			IsNewLobby = false;
		}

		private static void InitializeSessionSeedIfNeeded()
		{
			PosterConfig.KeepFor value = Plugin.ModConfig.KeepPackFor.Value;
			if (!_sessionSeedInitialized)
			{
				_sessionMapSeed = ((value == PosterConfig.KeepFor.Session) ? StartOfRound.Instance.randomMapSeed : Environment.TickCount);
				_sessionSeedInitialized = true;
				Plugin.Log.LogDebug((object)$"Seed: {_sessionMapSeed}");
			}
		}

		private static int ComputeSeedAndMaybeLoadSavePack(PosterConfig.KeepFor mode)
		{
			switch (mode)
			{
			case PosterConfig.KeepFor.Session:
				return _sessionMapSeed;
			case PosterConfig.KeepFor.SaveSlot:
			{
				string text = null;
				try
				{
					text = SavePersistenceManager.TryGetCurrentSaveId();
				}
				catch
				{
				}
				int result = ((!string.IsNullOrEmpty(text)) ? HashUtils.DeterministicHash(text) : Environment.TickCount);
				TryLoadSavedPack();
				return result;
			}
			default:
				_selectedPack = null;
				return Environment.TickCount;
			}
		}

		private static void TryLoadSavedPack()
		{
			try
			{
				string text = SavePersistenceManager.TryGetCurrentSaveId();
				string text2 = null;
				if (!string.IsNullOrEmpty(text))
				{
					text2 = SavePersistenceManager.TryLoadSelectedPack(text);
				}
				if (!string.IsNullOrEmpty(text2))
				{
					_selectedPack = text2;
					Plugin.Log.LogInfo((object)("Loaded saved pack for save '" + text + "': " + PathUtils.GetPrettyPath(_selectedPack)));
				}
				else
				{
					_selectedPack = null;
				}
			}
			catch (Exception ex)
			{
				_selectedPack = null;
				Plugin.Log.LogDebug((object)("SaveSlot load skipped: " + ex.Message));
			}
		}

		private static async Task LoadTextureAsync(string filePath, Action<(Texture2D? texture, string? filePath)> onComplete)
		{
			try
			{
				if (!File.Exists(filePath))
				{
					Plugin.Log.LogError((object)("File not found: " + PathUtils.GetPrettyPath(filePath)));
					onComplete?.Invoke((null, null));
					return;
				}
				Texture2D cachedTexture = Plugin.Service.GetCachedTexture(filePath);
				if ((Object)(object)cachedTexture != (Object)null)
				{
					onComplete?.Invoke((cachedTexture, filePath));
					return;
				}
				byte[] array = await File.ReadAllBytesAsync(filePath);
				Texture2D val = new Texture2D(2, 2);
				if (!ImageConversion.LoadImage(val, array))
				{
					Plugin.Log.LogError((object)("Failed to load texture from " + PathUtils.GetPrettyPath(filePath)));
					onComplete?.Invoke((null, null));
				}
				else
				{
					((Texture)val).filterMode = (FilterMode)0;
					Plugin.Service.CacheTexture(filePath, val);
					onComplete?.Invoke((val, filePath));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Error loading file " + PathUtils.GetPrettyPath(filePath) + ": " + ex.Message));
				onComplete?.Invoke((null, null));
			}
		}

		private static void HideVanillaPosterPlane()
		{
			GameObject val = GameObject.Find("Environment/HangarShip/Plane.001 (Old)") ?? GameObject.Find("Environment/HangarShip/Plane.001");
			if (val != null)
			{
				val.SetActive(false);
			}
		}

		private static void CleanUpPosters()
		{
			foreach (GameObject createdPoster in CreatedPosters)
			{
				if (!((Object)(object)createdPoster == (Object)null))
				{
					PosterRenderer component = createdPoster.GetComponent<PosterRenderer>();
					if ((Object)(object)component != (Object)null)
					{
						Object.Destroy((Object)(object)component);
					}
					Object.Destroy((Object)(object)createdPoster);
				}
			}
			CreatedPosters.Clear();
		}

		private static GameObject? CreatePoster(string posterName)
		{
			GameObject val = null;
			val = ((posterName == "CustomTips") ? (Plugin.ModConfig.UseTipsVanillaModel ? AssetManager.TipsPrefab : AssetManager.PosterPrefab) : ((!(posterName == "Poster5")) ? AssetManager.PosterPrefab : (Plugin.ModConfig.UsePoster5VanillaModel ? AssetManager.Poster5Prefab : AssetManager.PosterPrefab)));
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)("Failed to find prefab for " + posterName + ". Falling back to default poster prefab."));
				val = AssetManager.PosterPrefab;
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogError((object)"Default poster prefab is also null!");
					return null;
				}
			}
			return Object.Instantiate<GameObject>(val);
		}

		public static double? GetVideoTimeForPoster(string posterName)
		{
			string posterName2 = posterName;
			GameObject val = ((IEnumerable<GameObject>)CreatedPosters).FirstOrDefault((Func<GameObject, bool>)((GameObject p) => ((Object)p).name == posterName2));
			if (val == null)
			{
				return null;
			}
			return val.GetComponent<PosterRenderer>()?.GetCurrentVideoTime();
		}

		public static void SetVideoTimeForPoster(string posterName, double time)
		{
			string posterName2 = posterName;
			GameObject val = ((IEnumerable<GameObject>)CreatedPosters).FirstOrDefault((Func<GameObject, bool>)((GameObject p) => ((Object)p).name == posterName2));
			if (val != null)
			{
				val.GetComponent<PosterRenderer>()?.SetVideoTime(time);
			}
		}

		[IteratorStateMachine(typeof(<CreateCustomPostersAsync>d__26))]
		private static IEnumerator CreateCustomPostersAsync()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CreateCustomPostersAsync>d__26(0);
		}

		private static bool PackHasValidFiles(string pack)
		{
			try
			{
				string[] validExtensions = new string[5] { ".png", ".jpg", ".jpeg", ".bmp", ".mp4" };
				string text = Path.Combine(pack, "posters");
				string text2 = Path.Combine(pack, "tips");
				string text3 = Path.Combine(pack, "CustomPosters", "posters");
				string text4 = Path.Combine(pack, "CustomPosters", "tips");
				List<string> list = new string[4] { text, text2, text3, text4 }.Where((string p) => Directory.Exists(p)).ToList();
				foreach (string item in list)
				{
					if (Directory.EnumerateFiles(item).Any((string f) => validExtensions.Contains(Path.GetExtension(f).ToLower())))
					{
						return true;
					}
				}
				if (File.Exists(Path.Combine(pack, "CustomTips.png")))
				{
					return true;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("PackHasValidFiles error for " + pack + ": " + ex.Message));
			}
			return false;
		}

		[IteratorStateMachine(typeof(<DelayedUpdateMaterialsAsync>d__28))]
		private static IEnumerator DelayedUpdateMaterialsAsync(StartOfRound instance)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DelayedUpdateMaterialsAsync>d__28(0)
			{
				instance = instance
			};
		}

		public static void ChangePosterPack(string packName)
		{
			if (string.IsNullOrEmpty(packName))
			{
				List<string> enabledPackNames = Plugin.Service.GetEnabledPackNames();
				if (enabledPackNames.Count == 0)
				{
					return;
				}
				int num = enabledPackNames.FindIndex((string p) => p.Equals(_selectedPack, StringComparison.OrdinalIgnoreCase));
				_selectedPack = enabledPackNames[(num + 1) % enabledPackNames.Count];
			}
			else
			{
				if (!Plugin.Service.GetEnabledPackNames().Contains<string>(packName, StringComparer.OrdinalIgnoreCase))
				{
					Plugin.Log.LogWarning((object)("Attempted to select invalid pack: " + packName));
					return;
				}
				_selectedPack = packName;
			}
			Plugin.Service.SetRandomSeed(Environment.TickCount);
			Plugin.Log.LogInfo((object)("Changed poster pack to - " + _selectedPack));
			_materialsUpdated = false;
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance != (Object)null && instance.inShipPhase)
			{
				((MonoBehaviour)instance).StartCoroutine(DelayedUpdateMaterialsAsync(instance));
			}
		}
	}
	public class PosterRenderer : MonoBehaviour
	{
		private VideoPlayer? _videoPlayer;

		private AudioSource? _audioSource;

		private RenderTexture? _renderTexture;

		private float _originalVolume;

		private static VideoAspectRatio ConvertAspectRatio(PosterConfig.VideoAspectRatio aspectRatio)
		{
			//IL_0019: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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)
			return (VideoAspectRatio)(aspectRatio switch
			{
				PosterConfig.VideoAspectRatio.Stretch => 5, 
				PosterConfig.VideoAspectRatio.FitInside => 3, 
				PosterConfig.VideoAspectRatio.FitOutside => 4, 
				PosterConfig.VideoAspectRatio.NoScaling => 0, 
				_ => 5, 
			});
		}

		public void Initialize(Texture2D? texture, string? videoPath, Material? materialTemplate)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Expected O, but got Unknown
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Expected O, but got Unknown
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Expected O, but got Unknown
			string videoPath2 = videoPath;
			if ((Object)(object)materialTemplate == (Object)null)
			{
				Plugin.Log.LogError((object)"Cannot initialize poster, material template is null.");
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			MeshRenderer component = ((Component)this).GetComponent<MeshRenderer>();
			Material val2 = (((Renderer)component).material = new Material(materialTemplate));
			if (videoPath2 != null && Path.GetExtension(videoPath2).ToLower() == ".mp4")
			{
				_renderTexture = new RenderTexture(512, 512, 16);
				val2.SetTexture("_BaseColorMap", (Texture)(object)_renderTexture);
				_videoPlayer = ((Component)this).gameObject.AddComponent<VideoPlayer>();
				_videoPlayer.url = "file://" + videoPath2;
				_videoPlayer.renderMode = (VideoRenderMode)2;
				_videoPlayer.targetTexture = _renderTexture;
				var (num, maxDistance, aspectRatio) = Plugin.ModConfig.GetFileAudioSettings(videoPath2);
				_videoPlayer.aspectRatio = ConvertAspectRatio(aspectRatio);
				_videoPlayer.isLooping = true;
				_videoPlayer.playOnAwake = false;
				_audioSource = ((Component)this).gameObject.AddComponent<AudioSource>();
				_audioSource.spatialBlend = 1f;
				_audioSource.spatialize = false;
				_audioSource.rolloffMode = (AudioRolloffMode)2;
				AnimationCurve val3 = new AnimationCurve((Keyframe[])(object)new Keyframe[6]
				{
					new Keyframe(0f, 1f),
					new Keyframe(0.157f, 0.547f),
					new Keyframe(0.517f, 0.278f),
					new Keyframe(1.259f, 0.102f),
					new Keyframe(2.69f, 0.033f),
					new Keyframe(4f, 0f)
				});
				_audioSource.SetCustomCurve((AudioSourceCurveType)0, val3);
				_audioSource.maxDistance = maxDistance;
				_videoPlayer.Stop();
				_videoPlayer.errorReceived += (ErrorEventHandler)delegate(VideoPlayer player, string message)
				{
					Plugin.Log.LogError((object)("VideoPlayer error for " + PathUtils.GetPrettyPath(videoPath2) + ": " + message));
				};
				_videoPlayer.prepareCompleted += (EventHandler)delegate(VideoPlayer player)
				{
					player.Play();
					if (Plugin.ModConfig.EnableNetworking.Value && (Object)(object)NetworkManager.Singleton != (Object)null && !NetworkManager.Singleton.IsHost)
					{
						PosterSyncManager.RequestVideoTimeFromServer(((Object)((Component)this).gameObject).name);
					}
				};
				_originalVolume = (float)num / 100f;
				if (Plugin.ModConfig.EnableVideoAudio.Value)
				{
					_videoPlayer.audioOutputMode = (VideoAudioOutputMode)1;
					_videoPlayer.SetTargetAudioSource((ushort)0, _audioSource);
					_audioSource.volume = _originalVolume;
				}
				else
				{
					_videoPlayer.audioOutputMode = (VideoAudioOutputMode)0;
					_audioSource.volume = 0f;
				}
				_videoPlayer.Prepare();
			}
			else if ((Object)(object)texture != (Object)null)
			{
				val2.SetTexture("_BaseColorMap", (Texture)(object)texture);
			}
			else
			{
				Plugin.Log.LogError((object)("No valid texture for poster: " + ((Object)((Component)this).gameObject).name));
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		public void SetVideoTime(double time)
		{
			if ((Object)(object)_videoPlayer != (Object)null && _videoPlayer.isPrepared)
			{
				_videoPlayer.time = time;
			}
		}

		public double? GetCurrentVideoTime()
		{
			if ((Object)(object)_videoPlayer != (Object)null && _videoPlayer.isPlaying)
			{
				return _videoPlayer.time;
			}
			return null;
		}

		private void Update()
		{
			if ((Object)(object)_audioSource != (Object)null && !Plugin.ModConfig.EnableVideoAudio.Value)
			{
				if (_audioSource.isPlaying)
				{
					_audioSource.Stop();
				}
				_audioSource.volume = 0f;
				_audioSource.mute = true;
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_renderTexture != (Object)null)
			{
				_renderTexture.Release();
				Object.Destroy((Object)(object)_renderTexture);
			}
			if ((Object)(object)_videoPlayer != (Object)null && _videoPlayer.isPlaying)
			{
				_videoPlayer.Stop();
			}
		}
	}
	public class PosterService
	{
		private readonly List<string> _posterFolders = new List<string>();

		private readonly Dictionary<string, Texture2D> _textureCache = new Dictionary<string, Texture2D>();

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

		private Random _rand;

		public IReadOnlyList<string> PosterFolders => _posterFolders.AsReadOnly();

		public bool IsBiggerShipInstalled { get; private set; }

		public bool IsShipWindowsInstalled { get; private set; }

		public bool IsRightWindowEnabled { get; private set; }

		public bool IsWiderShipModInstalled { get; private set; }

		public string WiderShipExtendedSide { get; private set; } = "Both";


		public bool Is2StoryShipModInstalled { get; private set; }

		public bool EnableRightWindows { get; private set; }

		public bool EnableLeftWindows { get; private set; }

		public string TwoStoryShipLayout { get; private set; } = "Default";


		public Random Rand => _rand;

		public PosterService()
		{
			try
			{
				string pluginPath = Paths.PluginPath;
				HashSet<string> hashSet = new HashSet<string>(Constants.ExcludedModFolderNames, StringComparer.OrdinalIgnoreCase);
				string[] directories = Directory.GetDirectories(pluginPath);
				foreach (string text in directories)
				{
					string fileName = Path.GetFileName(text);
					if (hashSet.Contains(fileName))
					{
						continue;
					}
					string text2 = Path.Combine(text, "CustomPosters");
					if (Directory.Exists(text2) && IsValidPosterPack(text2))
					{
						_posterFolders.Add(text2);
						Plugin.Log.LogDebug((object)("Added single pack: " + PathUtils.GetPrettyPath(text2)));
						continue;
					}
					string[] directories2 = Directory.GetDirectories(text);
					bool flag = false;
					string[] array = directories2;
					foreach (string text3 in array)
					{
						try
						{
							if (IsValidPosterPack(text3))
							{
								_posterFolders.Add(text3);
								Plugin.Log.LogDebug((object)("Added child pack: " + PathUtils.GetPrettyPath(text3)));
								flag = true;
							}
						}
						catch (Exception ex)
						{
							Plugin.Log.LogWarning((object)("Error while checking child folder " + text3 + ": " + ex.Message));
						}
					}
					if (!flag && IsValidPosterPack(text))
					{
						_posterFolders.Add(text);
						Plugin.Log.LogDebug((object)("Added pack from root folder: " + PathUtils.GetPrettyPath(text)));
					}
				}
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogError((object)("Error scanning for poster packs: " + ex2.Message));
			}
			try
			{
				if (_posterFolders.Count > 0)
				{
					List<string> list = new List<string>();
					foreach (string posterFolder in _posterFolders)
					{
						int num = 0;
						try
						{
							string path = Path.Combine(posterFolder, "posters");
							if (Directory.Exists(path))
							{
								num += Directory.GetFiles(path).Count((string f) => Constants.AllValidExtensions.Contains(Path.GetExtension(f).ToLowerInvariant()));
							}
							string path2 = Path.Combine(posterFolder, "tips");
							if (Directory.Exists(path2))
							{
								num += Directory.GetFiles(path2).Count((string f) => Constants.AllValidExtensions.Contains(Path.GetExtension(f).ToLowerInvariant()));
							}
							num += Directory.GetFiles(posterFolder).Count((string f) => Constants.AllValidExtensions.Contains(Path.GetExtension(f).ToLowerInvariant()));
						}
						catch
						{
						}
						list.Add($"{PathUtils.GetDisplayPackName(posterFolder)}={num}");
					}
					Plugin.Log.LogDebug((object)string.Format("Poster packs discovered: {0}; files per pack: {1}", _posterFolders.Count, string.Join(", ", list)));
				}
			}
			catch
			{
			}
			InitializeBiggerShip();
			InitializeShipWindows();
			InitializeWiderShipMod();
			Initialize2StoryShipMod();
			SetRandomSeed(Environment.TickCount);
		}

		private bool IsValidPosterPack(string folderPath)
		{
			try
			{
				string path = Path.Combine(folderPath, "posters");
				if (Directory.Exists(path) && Directory.EnumerateFiles(path, "*.*", SearchOption.TopDirectoryOnly).Any((string file) => Constants.ValidImageExtensions.Contains(Path.GetExtension(file).ToLowerInvariant()) || Constants.ValidVideoExtensions.Contains(Path.GetExtension(file).ToLowerInvariant())))
				{
					return true;
				}
				string text = Path.Combine(folderPath, "tips");
				if (Directory.Exists(text) && File.Exists(Path.Combine(text, "CustomTips.png")))
				{
					return true;
				}
				if (File.Exists(Path.Combine(folderPath, "CustomTips.png")))
				{
					return true;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("IsValidPosterPack error for " + PathUtils.GetPrettyPath(folderPath) + ": " + ex.Message));
			}
			return false;
		}

		private void InitializeBiggerShip()
		{
			IsBiggerShipInstalled = Chainloader.PluginInfos.ContainsKey("BiggerShip");
			if (IsBiggerShipInstalled)
			{
				Plugin.Log.LogInfo((object)"Detected BiggerShip");
			}
		}

		private void InitializeShipWindows()
		{
			IsShipWindowsInstalled = Chainloader.PluginInfos.ContainsKey("TestAccount666.ShipWindows");
			if (IsShipWindowsInstalled)
			{
				string configPath = Path.Combine(Paths.ConfigPath, "TestAccount666.ShipWindows.cfg");
				IsRightWindowEnabled = ConfigFileReader.ReadBoolFromSection(configPath, "Right Window (SideRight)", "1. Enabled = ", defaultValue: false);
				Plugin.Log.LogInfo((object)$"Detected ShipWindows, RW - {IsRightWindowEnabled}");
			}
		}

		private void InitializeWiderShipMod()
		{
			IsWiderShipModInstalled = Chainloader.PluginInfos.ContainsKey("mborsh.WiderShipMod");
			if (!IsWiderShipModInstalled)
			{
				return;
			}
			try
			{
				FieldInfo fieldInfo = Type.GetType("WiderShipMod")?.GetField("ExtendedSide", BindingFlags.Static | BindingFlags.Public);
				if (fieldInfo != null)
				{
					WiderShipExtendedSide = (string)fieldInfo.GetValue(null);
				}
				else
				{
					ReadWiderShipConfigFile();
				}
			}
			catch
			{
				ReadWiderShipConfigFile();
			}
			Plugin.Log.LogInfo((object)("Detected WiderShip, ES - " + WiderShipExtendedSide));
		}

		private void ReadWiderShipConfigFile()
		{
			string configPath = Path.Combine(Paths.ConfigPath, "mborsh.WiderShipMod.cfg");
			WiderShipExtendedSide = ConfigFileReader.ReadStringValue(configPath, "Extended Side = ", "Both");
		}

		private void Initialize2StoryShipMod()
		{
			Is2StoryShipModInstalled = Chainloader.PluginInfos.ContainsKey("MelanieMelicious.2StoryShip");
			if (!Is2StoryShipModInstalled)
			{
				return;
			}
			try
			{
				Type type = Type.GetType("2StoryShip");
				if (type != null)
				{
					FieldInfo field = type.GetField("EnableRightWindows", BindingFlags.Static | BindingFlags.Public);
					FieldInfo field2 = type.GetField("EnableLeftWindows", BindingFlags.Static | BindingFlags.Public);
					if (field != null && field2 != null)
					{
						EnableRightWindows = (bool)field.GetValue(null);
						EnableLeftWindows = (bool)field2.GetValue(null);
					}
					else
					{
						Read2StoryShipConfigFile();
					}
				}
				else
				{
					Read2StoryShipConfigFile();
				}
			}
			catch
			{
				Read2StoryShipConfigFile();
			}
			Plugin.Log.LogInfo((object)$"Detected 2StoryShipMod, RW - {EnableRightWindows}, LW - {EnableLeftWindows}");
		}

		private void Read2StoryShipConfigFile()
		{
			string configPath = Path.Combine(Paths.ConfigPath, "MelanieMelicious.2StoryShip.cfg");
			Dictionary<string, string> dictionary = ConfigFileReader.ReadMultipleValues(configPath, "Enable Right Windows = ", "Enable Left Windows = ");
			EnableRightWindows = !dictionary.TryGetValue("Enable Right Windows = ", out var value) || bool.Parse(value);
			EnableLeftWindows = !dictionary.TryGetValue("Enable Left Windows = ", out var value2) || bool.Parse(value2);
			string text = ConfigFileReader.ReadStringFromSection(configPath, "Wider + 2-Story Exclusive", "Ship Layout = ", "Default");
			if (!string.IsNullOrEmpty(text))
			{
				TwoStoryShipLayout = text.Trim();
			}
		}

		public void SetRandomSeed(int seed)
		{
			_rand = new Random(seed);
		}

		public Texture2D? GetCachedTexture(string filePath)
		{
			if (!Plugin.ModConfig.EnableTextureCaching.Value)
			{
				return null;
			}
			if (_textureCache.TryGetValue(filePath, out Texture2D value))
			{
				Plugin.Log.LogDebug((object)("Retrieved cached texture: " + PathUtils.GetPrettyPath(filePath)));
				return value;
			}
			return null;
		}

		public void CacheTexture(string filePath, Texture2D texture)
		{
			if (Plugin.ModConfig.EnableTextureCaching.Value && !_textureCache.ContainsKey(filePath))
			{
				_textureCache[filePath] = texture;
			}
		}

		public string? GetCachedVideo(string filePath)
		{
			if (!Plugin.ModConfig.EnableTextureCaching.Value)
			{
				return null;
			}
			if (_videoCache.TryGetValue(filePath, out string value))
			{
				Plugin.Log.LogDebug((object)("Retrieved cached video: " + PathUtils.GetPrettyPath(filePath)));
				return value;
			}
			return null;
		}

		public void CacheVideo(string filePath)
		{
			if (Plugin.ModConfig.EnableTextureCaching.Value && !_videoCache.ContainsKey(filePath))
			{
				if (!File.Exists(filePath))
				{
					Plugin.Log.LogError((object)("Cannot cache video, file does not exist: " + PathUtils.GetPrettyPath(filePath)));
					return;
				}
				_videoCache[filePath] = filePath;
				Plugin.Log.LogDebug((object)("Cached video: " + PathUtils.GetPrettyPath(filePath)));
			}
		}

		public void ClearCache()
		{
			foreach (Texture2D value in _textureCache.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			_textureCache.Clear();
			_videoCache.Clear();
			Plugin.Log.LogInfo((object)"Cleared texture and video cache");
		}

		public List<string> GetEnabledPackNames()
		{
			List<string> list = (from f in PosterFolders
				where Plugin.ModConfig.IsPackEnabled(f)
				select Path.GetFullPath(f).NormalizePath()).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList();
			List<string> values = list.Select(Path.GetFileName).ToList();
			Plugin.Log.LogDebug((object)("Enabled pack names: " + string.Join(", ", values)));
			return list;
		}

		public int GetFilePriority(string filePath)
		{
			return Path.GetExtension(filePath).ToLower() switch
			{
				".png" => 1, 
				".jpg" => 2, 
				".jpeg" => 3, 
				".bmp" => 4, 
				".mp4" => 5, 
				_ => int.MaxValue, 
			} * 1000 + Rand.Next(0, 1000);
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "CustomPosters";

		public const string PLUGIN_NAME = "CustomPosters";

		public const string PLUGIN_VERSION = "4.0.2";
	}
}
namespace CustomPosters.Utils
{
	internal static class ConfigFileReader
	{
		public static bool ReadBoolValue(string configPath, string key, bool defaultValue = true)
		{
			if (!File.Exists(configPath))
			{
				return defaultValue;
			}
			try
			{
				string[] array = File.ReadAllLines(configPath);
				string[] array2 = array;
				foreach (string text in array2)
				{
					string text2 = text.Trim();
					if (text2.StartsWith(key, StringComparison.OrdinalIgnoreCase))
					{
						string value = text2.Substring(key.Length).Trim();
						if (bool.TryParse(value, out var result))
						{
							return result;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Error reading config file " + configPath + ": " + ex.Message));
			}
			return defaultValue;
		}

		public static string ReadStringValue(string configPath, string key, string defaultValue = "")
		{
			if (!File.Exists(configPath))
			{
				return defaultValue;
			}
			try
			{
				string[] array = File.ReadAllLines(configPath);
				string[] array2 = array;
				foreach (string text in array2)
				{
					string text2 = text.Trim();
					if (text2.StartsWith(key, StringComparison.OrdinalIgnoreCase))
					{
						return text2.Substring(key.Length).Trim();
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Error reading config file " + configPath + ": " + ex.Message));
			}
			return defaultValue;
		}

		public static bool ReadBoolFromSection(string configPath, string sectionHeader, string key, bool defaultValue = true)
		{
			if (!File.Exists(configPath))
			{
				return defaultValue;
			}
			try
			{
				string[] array = File.ReadAllLines(configPath);
				bool flag = false;
				string[] array2 = array;
				foreach (string text in array2)
				{
					string text2 = text.Trim();
					if (text2.StartsWith("[") && text2.EndsWith("]"))
					{
						flag = text2.Equals("[" + sectionHeader + "]", StringComparison.OrdinalIgnoreCase);
					}
					else if (flag && text2.StartsWith(key, StringComparison.OrdinalIgnoreCase))
					{
						string value = text2.Substring(key.Length).Trim();
						if (bool.TryParse(value, out var result))
						{
							return result;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Error reading config file " + configPath + ": " + ex.Message));
			}
			return defaultValue;
		}

		public static string ReadStringFromSection(string configPath, string sectionHeader, string key, string defaultValue = "")
		{
			if (!File.Exists(configPath))
			{
				return defaultValue;
			}
			try
			{
				bool flag = false;
				string[] array = File.ReadAllLines(configPath);
				foreach (string text in array)
				{
					string text2 = text.Trim();
					if (string.IsNullOrWhiteSpace(text2))
					{
						continue;
					}
					if (text2.StartsWith("[") && text2.EndsWith("]"))
					{
						string a = text2.Substring(1, text2.Length - 2).Trim();
						flag = string.Equals(a, sectionHeader, StringComparison.OrdinalIgnoreCase);
					}
					else if (flag && text2.StartsWith(key, StringComparison.OrdinalIgnoreCase))
					{
						int num = text2.IndexOf('=');
						if (num >= 0 && num + 1 < text2.Length)
						{
							return text2.Substring(num + 1).Trim();
						}
					}
				}
			}
			catch (Exception ex)
			{
				try
				{
					Plugin.Log.LogDebug((object)("ReadStringFromSection error for '" + sectionHeader + ":" + key + "': " + ex.Message));
				}
				catch
				{
				}
			}
			return defaultValue;
		}

		public static Dictionary<string, string> ReadMultipleValues(string configPath, params string[] keys)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			if (!File.Exists(configPath))
			{
				return dictionary;
			}
			try
			{
				string[] array = File.ReadAllLines(configPath);
				HashSet<string> hashSet = new HashSet<string>(keys, StringComparer.OrdinalIgnoreCase);
				string[] array2 = array;
				foreach (string text in array2)
				{
					string text2 = text.Trim();
					foreach (string item in hashSet)
					{
						if (text2.StartsWith(item, StringComparison.OrdinalIgnoreCase))
						{
							string value = text2.Substring(item.Length).Trim();
							dictionary[item] = value;
							if (dictionary.Count == keys.Length)
							{
								return dictionary;
							}
							break;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Error reading config file " + configPath + ": " + ex.Message));
			}
			return dictionary;
		}
	}
	internal static class Extensions
	{
		public static bool IsImage(this string filePath)
		{
			if (string.IsNullOrEmpty(filePath))
			{
				return false;
			}
			string value = Path.GetExtension(filePath).ToLowerInvariant();
			return Constants.ValidImageExtensions.Contains(value);
		}

		public static bool IsVideo(this string filePath)
		{
			if (string.IsNullOrEmpty(filePath))
			{
				return false;
			}
			string value = Path.GetExtension(filePath).ToLowerInvariant();
			return Constants.ValidVideoExtensions.Contains(value);
		}

		public static bool IsValidPosterFile(this string filePath)
		{
			if (string.IsNullOrEmpty(filePath))
			{
				return false;
			}
			string value = Path.GetExtension(filePath).ToLowerInvariant();
			return Constants.AllValidExtensions.Contains(value);
		}

		public static string NormalizePath(this string path)
		{
			return path?.Replace('\\', '/') ?? string.Empty;
		}

		public static string GetPosterName(this string filePath)
		{
			return Path.GetFileNameWithoutExtension(filePath)?.ToLower() ?? string.Empty;
		}

		public static T GetComponentSafe<T>(this GameObject gameObject) where T : Component
		{
			if (!((Object)(object)gameObject != (Object)null))
			{
				return default(T);
			}
			return gameObject.GetComponent<T>();
		}

		public static void AddRangeDistinct<T>(this List<T> list, IEnumerable<T> items, IEqualityComparer<T> comparer = null)
		{
			if (comparer == null)
			{
				comparer = EqualityComparer<T>.Default;
			}
			HashSet<T> hashSet = new HashSet<T>(list, comparer);
			foreach (T item in items)
			{
				if (hashSet.Add(item))
				{
					list.Add(item);
				}
			}
		}
	}
	internal static class HashUtils
	{
		private const int HashSeed = 23;

		private const int HashMul = 31;

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static int DeterministicHash(string input)
		{
			int num = 23;
			for (int i = 0; i < input.Length; i++)
			{
				num = num * 31 + input[i];
			}
			return num;
		}
	}
	internal static class PackSelector
	{
		public static string SelectPackByChance(List<string> enabledPacks)
		{
			if (enabledPacks == null || enabledPacks.Count == 0)
			{
				return null;
			}
			if (enabledPacks.Count == 1)
			{
				return enabledPacks[0];
			}
			List<int> list = enabledPacks.Select((string p) => Plugin.ModConfig.GetPackChance(p)).ToList();
			if (list.All((int c) => c == 0))
			{
				return enabledPacks[Plugin.Service.Rand.Next(enabledPacks.Count)];
			}
			return SelectByWeightedChance(enabledPacks, list);
		}

		public static T SelectContentByChance<T>(List<T> items, Func<T, int> getChance, Func<T, int> getPriority)
		{
			if (items == null || items.Count == 0)
			{
				return default(T);
			}
			if (items.Count == 1)
			{
				return items[0];
			}
			List<int> list = items.Select(getChance).ToList();
			if (list.All((int c) => c == 0))
			{
				return items.OrderBy(getPriority).First();
			}
			return SelectByWeightedChance(items, list);
		}

		private static T SelectByWeightedChance<T>(List<T> items, List<int> chances)
		{
			int num = chances.Sum();
			if (num <= 0)
			{
				return items[0];
			}
			double num2 = Plugin.Service.Rand.NextDouble() * (double)num;
			double num3 = 0.0;
			for (int i = 0; i < items.Count; i++)
			{
				num3 += (double)chances[i];
				if (num2 <= num3)
				{
					return items[i];
				}
			}
			return items[0];
		}
	}
	internal static class PathUtils
	{
		public static string GetPrettyPath(string fullPath)
		{
			if (string.IsNullOrEmpty(fullPath))
			{
				return string.Empty;
			}
			int num = fullPath.IndexOf("plugins", StringComparison.OrdinalIgnoreCase);
			if (num != -1)
			{
				return fullPath.Substring(num + "plugins".Length + 1);
			}
			return fullPath;
		}

		public static string GetPackName(string fullPackName)
		{
			if (string.IsNullOrEmpty(fullPackName))
			{
				return string.Empty;
			}
			int num = fullPackName.IndexOf('-');
			if (num > 0 && num < fullPackName.Length - 1)
			{
				return fullPackName.Substring(num + 1);
			}
			return fullPackName;
		}

		public static string GetDisplayPackName(string packPath)
		{
			if (string.IsNullOrEmpty(packPath))
			{
				return string.Empty;
			}
			string fileName = Path.GetFileName(packPath);
			string directoryName = Path.GetDirectoryName(packPath);
			if (!string.IsNullOrEmpty(directoryName))
			{
				string fileName2 = Path.GetFileName(directoryName);
				if (string.Equals(fileName, "CustomPosters", StringComparison.OrdinalIgnoreCase))
				{
					return GetPackName(fileName2);
				}
				string.IsNullOrEmpty(fileName2);
				return fileName;
			}
			return fileName;
		}
	}
	internal static class SavePersistenceManager
	{
		private const string Es3Key = "CustomPosters_SelectedPack";

		public static string? TryGetCurrentSaveId()
		{
			try
			{
				GameNetworkManager instance = GameNetworkManager.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					Type type = ((object)instance).GetType();
					FieldInfo field = type.GetField("currentSaveFileName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					PropertyInfo property = type.GetProperty("currentSaveFileName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					string text = (field?.GetValue(instance) as string) ?? (property?.GetValue(instance) as string);
					if (!string.IsNullOrEmpty(text))
					{
						return text;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		public static string? TryLoadSelectedPack(string saveId)
		{
			try
			{
				if (string.IsNullOrEmpty(saveId))
				{
					return null;
				}
				if (ES3.KeyExists("CustomPosters_SelectedPack", saveId))
				{
					string text = ES3.Load<string>("CustomPosters_SelectedPack", saveId, "");
					return string.IsNullOrEmpty(text) ? null : text;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Failed to load per save selection from ES3: " + ex.Message));
			}
			return null;
		}

		public static void SaveSelectedPack(string saveId, string packPath)
		{
			try
			{
				if (!string.IsNullOrEmpty(saveId))
				{
					ES3.Save<string>("CustomPosters_SelectedPack", packPath, saveId);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Failed to save per save selection to ES3: " + ex.Message));
			}
		}
	}
}
namespace CustomPosters.Patches
{
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal class GameNetworkManagerPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void OnStartPatch()
		{
			PosterManager.ResetSession();
			if (Plugin.ModConfig.EnableNetworking.Value)
			{
				if ((Object)(object)NetworkManager.Singleton != (Object)null)
				{
					Plugin.Log.LogInfo((object)"Networking is enabled.");
					NetworkManager.Singleton.OnClientConnectedCallback += PosterSyncManager.OnClientConnected;
				}
				else
				{
					Plugin.Log.LogWarning((object)"NetworkManager.Singleton is null, cannot register callbacks.");
				}
			}
			else
			{
				Plugin.Log.LogInfo((object)"Networking is disabled.");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("StartHost")]
		private static void OnStartHostPatch()
		{
			PosterManager.IsNewLobby = true;
		}

		[HarmonyPostfix]
		[HarmonyPatch("JoinLobby")]
		private static void OnJoinLobbyPatch()
		{
			PosterManager.IsNewLobby = true;
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal class StartOfRoundPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void OnRoundStartPatch(StartOfRound __instance)
		{
			PosterManager.OnRoundStart(__instance);
		}
	}
}
namespace CustomPosters.Networking
{
	internal static class PosterSyncManager
	{
		private const string PackSyncIdentifier = "CustomPosters_SyncPack";

		private static readonly LNetworkMessage<string> SyncPackMessage = LNetworkMessage<string>.Connect("CustomPosters_SyncPack", (Action<string, ulong>)null, (Action<string>)PosterManager.SetPackForClients, (Action<string, ulong>)null);

		private const string VideoRequestIdentifier = "CustomPosters_RequestVideoTime";

		private const string VideoSyncIdentifier = "CustomPosters_SyncVideoTime";

		private static readonly LNetworkMessage<string> RequestVideoTimeMessage = LNetworkMessage<string>.Connect("CustomPosters_RequestVideoTime", (Action<string, ulong>)OnVideoTimeRequested, (Action<string>)null, (Action<string, ulong>)null);

		private static readonly LNetworkMessage<VideoSyncData> SyncVideoTimeMessage = LNetworkMessage<VideoSyncData>.Connect("CustomPosters_SyncVideoTime", (Action<VideoSyncData, ulong>)null, (Action<VideoSyncData>)OnVideoTimeReceived, (Action<VideoSyncData, ulong>)null);

		public static void SendPacket(string packName)
		{
			if (!Plugin.ModConfig.EnableNetworking.Value)
			{
				Plugin.Log.LogDebug((object)"Networking disabled.");
			}
			else if ((Object)(object)NetworkManager.Singleton == (Object)null)
			{
				Plugin.Log.LogWarning((object)"NetworkManager.Singleton is null, cannot send pack sync");
			}
			else if (NetworkManager.Singleton.IsHost)
			{
				Plugin.Log.LogDebug((object)("Sending selected pack to all clients: " + PathUtils.GetPrettyPath(packName)));
				SyncPackMessage.SendClients(packName);
			}
		}

		public static void OnClientConnected(ulong clientId)
		{
			if (Plugin.ModConfig.EnableNetworking.Value)
			{
				if ((Object)(object)NetworkManager.Singleton == (Object)null)
				{
					Plugin.Log.LogWarning((object)"NetworkManager.Singleton is null in OnClientConnected");
				}
				else if (NetworkManager.Singleton.IsHost && clientId != NetworkManager.Singleton.LocalClientId && !string.IsNullOrEmpty(PosterManager.SelectedPack))
				{
					Plugin.Log.LogDebug((object)("New client joined, sending pack: " + PathUtils.GetPrettyPath(PosterManager.SelectedPack)));
					SyncPackMessage.SendClient(PosterManager.SelectedPack, clientId);
				}
			}
		}

		public static void RequestVideoTimeFromServer(string posterName)
		{
			if (!Plugin.ModConfig.EnableNetworking.Value)
			{
				Plugin.Log.LogDebug((object)"Networking disabled, skipping video time sync request");
			}
			else if (!((Object)(object)NetworkManager.Singleton == (Object)null) && !NetworkManager.Singleton.IsHost)
			{
				Plugin.Log.LogDebug((object)("Requesting video time for poster: " + posterName));
				RequestVideoTimeMessage.SendServer(posterName);
			}
		}

		private static void OnVideoTimeRequested(string posterName, ulong clientId)
		{
			double? videoTimeForPoster = PosterManager.GetVideoTimeForPoster(posterName);
			if (videoTimeForPoster.HasValue)
			{
				Plugin.Log.LogDebug((object)$"Host received request for '{posterName}'. Sending time: {videoTimeForPoster.Value} to client {clientId}");
				VideoSyncData videoSyncData = default(VideoSyncData);
				videoSyncData.PosterName = posterName;
				videoSyncData.VideoTime = videoTimeForPoster.Value;
				VideoSyncData videoSyncData2 = videoSyncData;
				SyncVideoTimeMessage.SendClient(videoSyncData2, clientId);
			}
		}

		private static void OnVideoTimeReceived(VideoSyncData syncData)
		{
			Plugin.Log.LogDebug((object)$"Client received sync time for '{syncData.PosterName}': {syncData.VideoTime}");
			PosterManager.SetVideoTimeForPoster(syncData.PosterName, syncData.VideoTime);
		}
	}
	public struct VideoSyncData
	{
		public string PosterName;

		public double VideoTime;
	}
}
namespace CustomPosters.Data
{
	public struct PosterData
	{
		public Vector3 Position;

		public Vector3 Rotation;

		public Vector3 Scale;

		public string Name;
	}
	internal static class PosterHelper
	{
		public static PosterData Poster5Vanilla(Vector3 pos, Vector3 rot, Vector3 scale)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			PosterData result = default(PosterData);
			result.Position = pos;
			result.Rotation = rot;
			result.Scale = scale;
			result.Name = "Poster5";
			return result;
		}

		public static PosterData Poster5Quad(Vector3 pos, Vector3 rot, Vector3 scale)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			PosterData result = default(PosterData);
			result.Position = pos;
			result.Rotation = rot;
			result.Scale = scale;
			result.Name = "Poster5";
			return result;
		}

		public static PosterData TipsVanilla(Vector3 pos, Vector3 rot, Vector3 scale)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			PosterData result = default(PosterData);
			result.Position = pos;
			result.Rotation = rot;
			result.Scale = scale;
			result.Name = "CustomTips";
			return result;
		}

		public static PosterData TipsQuad(Vector3 pos, Vector3 rot, Vector3 scale)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			PosterData result = default(PosterData);
			result.Position = pos;
			result.Rotation = rot;
			result.Scale = scale;
			result.Name = "CustomTips";
			return result;
		}
	}
	internal static class PosterLayoutProvider
	{
		public static PosterData[] GetLayout()
		{
			bool isShipWindowsInstalled = Plugin.Service.IsShipWindowsInstalled;
			bool isRightWindowEnabled = Plugin.Service.IsRightWindowEnabled;
			bool isWiderShipModInstalled = Plugin.Service.IsWiderShipModInstalled;
			string widerShipExtendedSide = Plugin.Service.WiderShipExtendedSide;
			bool is2StoryShipModInstalled = Plugin.Service.Is2StoryShipModInstalled;
			bool enableRightWindows = Plugin.Service.EnableRightWindows;
			bool enableLeftWindows = Plugin.Service.EnableLeftWindows;
			bool flag = is2StoryShipModInstalled && string.Equals(Plugin.Service.TwoStoryShipLayout, "Legacy", StringComparison.OrdinalIgnoreCase);
			if (Plugin.Service.IsBiggerShipInstalled)
			{
				Plugin.Log.LogInfo((object)"Choosing layout: BiggerShip");
				return BiggerShip.Get();
			}
			if (is2StoryShipModInstalled)
			{
				if (flag && isWiderShipModInstalled)
				{
					Plugin.Log.LogInfo((object)"Choosing layout: 2 Story Ship (Legacy) + WiderShip");
					return CustomPosters.Data.PosterLayouts.Legacy.TwoStoryShip_WiderShip.Get();
				}
				if (isShipWindowsInstalled && isWiderShipModInstalled && !isRightWindowEnabled)
				{
					Plugin.Log.LogInfo((object)"Choosing layout: 2 Story Ship + ShipWindows + WiderShip  (No right window)");
					return CustomPosters.Data.PosterLayouts.TwoStoryShip_WiderShip.Get();
				}
				if (isShipWindowsInstalled && isWiderShipModInstalled)
				{
					Plugin.Log.LogInfo((object)"Choosing layout: 2 Story Ship + ShipWindows + WiderShip");
					return CustomPosters.Data.PosterLayouts.TwoStoryShip_WiderShip.Get();
				}
				if (isWiderShipModInstalled && !enableLeftWindows)
				{
					Plugin.Log.LogInfo((object)"Choosing layout: 2 Story Ship + WiderShip (No left window)");
					return CustomPosters.Data.PosterLayouts.TwoStoryShip_WiderShip.Get();
				}
				if (isShipWindowsInstalled)
				{
					Plugin.Log.LogInfo((object)"Choosing layout: 2 Story Ship + ShipWindows");
					return TwoStoryShip.Get();
				}
				if (isWiderShipModInstalled)
				{
					Plugin.Log.LogInfo((object)"Choosing layout: 2 Story Ship + WiderShip");
					return CustomPosters.Data.PosterLayouts.TwoStoryShip_WiderShip.Get();
				}
				if (!enableRightWindows && !enableLeftWindows)
				{
					Plugin.Log.LogInfo((object)"Choosing layout: 2 Story Ship (No both windows)");
					return TwoStoryShip.Get();
				}
				if (enableRightWindows && enableLeftWindows)
				{
					Plugin.Log.LogInfo((object)"Choosing layout: 2 Story Ship (All windows)");
					return TwoStoryShip.Get();
				}
				if (!enableRightWindows)
				{
					Plugin.Log.LogInfo((object)"Choosing layout: 2 Story Ship (No right window)");
					return TwoStoryShip.Get();
				}
				if (!enableLeftWindows)
				{
					Plugin.Log.LogInfo((object)"Choosing layout: 2 Story Ship (No left window)");
					return TwoStoryShip.Get();
				}
			}
			if (isShipWindowsInstalled && isRightWindowEnabled && isWiderShipModInstalled && widerShipExtendedSide == "Left")
			{
				Plugin.Log.LogInfo((object)"Choosing layout: ShipWindows + WiderShip (Left)");
				return ShipWindows_WiderShip_Left.Get();
			}
			if (isWiderShipModInstalled)
			{
				Plugin.Log.LogInfo((object)("Choosing layout: WiderShip - " + widerShipExtendedSide));
				switch (widerShipExtendedSide)
				{
				case "Both":
					return WiderShip_Both.Get();
				case "Right":
					return WiderShip_Right.Get();
				case "Left":
					return WiderShip_Left.Get();
				}
			}
			if (isShipWindowsInstalled && isRightWindowEnabled)
			{
				Plugin.Log.LogInfo((object)"Choosing layout: ShipWindows");
				return ShipWindows.Get();
			}
			Plugin.Log.LogInfo((object)"Choosing layout: Vanilla");
			return Vanilla.Get();
		}
	}
}
namespace CustomPosters.Data.PosterLayouts
{
	internal static class BiggerShip
	{
		public static PosterData[] Get()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			bool usePoster5VanillaModel = Plugin.ModConfig.UsePoster5VanillaModel;
			bool useTipsVanillaModel = Plugin.ModConfig.UseTipsVanillaModel;
			return new PosterData[6]
			{
				new PosterData
				{
					Position = new Vector3(4.1886f, 2.8918f, -17.8606f),
					Rotation = new Vector3(0f, 169.6929f, 0f),
					Scale = new Vector3(0.6391f, 0.4882f, 2f),
					Name = "Poster1"
				},
				new PosterData
				{
					Position = new Vector3(6.4202f, 2.4776f, -10.9064f),
					Rotation = new Vector3(0f, 0f, 0f),
					Scale = new Vector3(0.7296f, 0.4896f, 1f),
					Name = "Poster2"
				},
				new PosterData
				{
					Position = new Vector3(9.9186f, 2.8591f, -17.5587f),
					Rotation = new Vector3(0f, 180f, 356.3345f),
					Scale = new Vector3(0.7487f, 1.0539f, 1f),
					Name = "Poster3"
				},
				new PosterData
				{
					Position = new Vector3(5.2187f, 2.5963f, -10.782f),
					Rotation = new Vector3(0f, 10.7715f, 2.68f),
					Scale = new Vector3(0.7289f, 0.9989f, 1f),
					Name = "Poster4"
				},
				usePoster5VanillaModel ? PosterHelper.Poster5Vanilla(new Vector3(5.5286f, 2.5882f, -17.6077f), new Vector3(1.3609f, 329.1297f, 182.4321f), new Vector3(0.465f, 0.71f, 1f)) : PosterHelper.Poster5Quad(new Vector3(5.5286f, 2.5882f, -17.6184f), new Vector3(0f, 169.7645f, 359.8f), new Vector3(0.5516f, 0.769f, 1f)),
				useTipsVanillaModel ? PosterHelper.TipsVanilla(new Vector3(8.147f, 2.399426f, -20.6869f), new Vector3(-270.38f, -321.026f, 219.239f), new Vector3(46.75954f, 100f, 70.89838f)) : PosterHelper.TipsQuad(new Vector3(3.0647f, 2.8174f, -10.4842f), new Vector3(0f, 0f, 0f), new Vector3(0.8596f, 1.2194f, 1f))
			};
		}
	}
	internal static class ShipWindows
	{
		public static PosterData[] Get()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			bool usePoster5VanillaModel = Plugin.ModConfig.UsePoster5VanillaModel;
			bool useTipsVanillaModel = Plugin.ModConfig.UseTipsVanillaModel;
			return new PosterData[6]
			{
				new PosterData
				{
					Position = new Vector3(4.1886f, 2.9318f, -16.8409f),
					Rotation = new Vector3(0f, 200.9872f, 0f),
					Scale = new Vector3(0.6391f, 0.4882f, 2f),
					Name = "Poster1"
				},
				new PosterData
				{
					Position = new Vector3(6.4202f, 2.2577f, -10.822f),
					Rotation = new Vector3(0f, 0f, 0f),
					Scale = new Vector3(0.7296f, 0.4896f, 1f),
					Name = "Poster2"
				},
				new PosterData
				{
					Position = new Vector3(9.9186f, 2.8591f, -17.4716f),
					Rotation = new Vector3(0f, 180f, 356.3345f),
					Scale = new Vector3(0.7487f, 1.0539f, 1f),
					Name = "Poster3"
				},
				new PosterData
				{
					Position = new Vector3(6.4449f, 3.0961f, -10.8219f),
					Rotation = new Vector3(0f, 0f, 2.68f),
					Scale = new Vector3(0.7289f, 0.9989f, 1f),
					Name = "Poster4"
				},
				usePoster5VanillaModel ? PosterHelper.Poster5Vanilla(new Vector3(5.5286f, 2.5882f, -17.3421f), new Vector3(1.3609f, 0.2388f, 182.4321f), new Vector3(0.465f, 0.71f, 1f)) : PosterHelper.Poster5Quad(new Vector3(5.5286f, 2.5882f, -17.3541f), new Vector3(0f, 201.1556f, 359.8f), new Vector3(0.5516f, 0.769f, 1f)),
				useTipsVanillaModel ? PosterHelper.TipsVanilla(new Vector3(8.147f, 2.399426f, -21.929f), new Vector3(-270.38f, -321.026f, 219.239f), new Vector3(46.75954f, 100f, 70.89838f)) : PosterHelper.TipsQuad(new Vector3(3.0647f, 2.8174f, -11.7255f), new Vector3(0f, 0f, 358.6752f), new Vector3(0.8596f, 1.2194f, 1f))
			};
		}
	}
	internal static class ShipWindows_WiderShip_Left
	{
		public static PosterData[] Get()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			bool usePoster5VanillaModel = Plugin.ModConfig.UsePoster5VanillaModel;
			bool useTipsVanillaModel = Plugin.ModConfig.UseTipsVanillaModel;
			return new PosterData[6]
			{
				new PosterData
				{
					Position = new Vector3(4.6777f, 2.9007f, -19.63f),
					Rotation = new Vector3(0f, 118.2274f, 0f),
					Scale = new Vector3(0.6391f, 0.4882f, 2f),
					Name = "Poster1"
				},
				new PosterData
				{
					Position = new Vector3(6.4202f, 2.2577f, -10.8226f),
					Rotation = new Vector3(0f, 0f, 0f),
					Scale = new Vector3(0.7296f, 0.4896f, 1f),
					Name = "Poster2"
				},
				new PosterData
				{
					Position = new Vector3(9.9186f, 2.8591f, -17.4716f),
					Rotation = new Vector3(0f, 180f, 356.3345f),
					Scale = new Vector3(0.7487f, 1.0539f, 1f),
					Name = "Poster3"
				},
				new PosterData
				{
					Position = new Vector3(6.4449f, 3.0961f, -10.8221f),
					Rotation = new Vector3(0f, 0f, 2.68f),
					Scale = new Vector3(0.7289f, 0.9989f, 1f),
					Name = "Poster4"
				},
				usePoster5VanillaModel ? PosterHelper.Poster5Vanilla(new Vector3(5.3602f, 2.5882f, -18.3492f), new Vector3(357.7245f, 277.6282f, 180f), new Vector3(0.465f, 0.71f, 1f)) : PosterHelper.Poster5Quad(new Vector3(5.3602f, 2.5482f, -18.3793f), new Vector3(0f, 118.0114f, 359.8f), new Vector3(0.5516f, 0.769f, 1f)),
				useTipsVanillaModel ? PosterHelper.TipsVanilla(new Vector3(8.147f, 2.399426f, -21.929f), new Vector3(-270.38f, -321.026f, 219.239f), new Vector3(46.75954f, 100f, 70.89838f)) : PosterHelper.TipsQuad(new Vector3(2.8647f, 2.7774f, -11.7341f), new Vector3(0f, 0f, 358.6752f), new Vector3(0.8596f, 1.2194f, 1f))
			};
		}
	}
	internal static class TwoStoryShip
	{
		public static PosterData[] Get()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to inva