Decompiled source of BumperStickers v1.3.2

BumperStickers.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CG;
using CG.Game;
using CG.Space;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
using VoidManager;
using VoidManager.Chat.Router;
using VoidManager.MPModChecks;
using VoidManager.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("BumperStickers")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+0256cffb3034001545d82efd1fc25564eb71288f")]
[assembly: AssemblyProduct("BumperStickers")]
[assembly: AssemblyTitle("Joke bumper stickers on the ship's stern")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 BumperStickers
{
	[BepInPlugin("fredthesled.VoidCrew.BumperStickers", "Bumper Stickers", "1.3.2")]
	[BepInProcess("Void Crew.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class BepinPlugin : BaseUnityPlugin
	{
		internal static BepinPlugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> SnapToHull;

		internal static ConfigEntry<float> PushOut;

		internal static ConfigEntry<float> ScaleMultiplier;

		internal static ConfigEntry<float> OffsetX;

		internal static ConfigEntry<float> OffsetY;

		internal static ConfigEntry<float> OffsetZ;

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Stickers", "Enabled", true, "Show the bumper stickers.");
			SnapToHull = ((BaseUnityPlugin)this).Config.Bind<bool>("Placement", "SnapToHull", true, "Keep the editor-authored X/Y/rotation but find the real hull surface depth in-game. Turn off to use the authored Z exactly.");
			PushOut = ((BaseUnityPlugin)this).Config.Bind<float>("Placement", "PushOut", 0.15f, "Extra distance (m) to lift each sticker off the hull surface, along its own facing.");
			ScaleMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Placement", "ScaleMultiplier", 1f, "Multiplies the sizes authored in the Unity editor (1.0 = exactly as authored).");
			OffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Placement", "OffsetX", 0f, "Nudge all stickers, ship-local X (m).");
			OffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Placement", "OffsetY", 0f, "Nudge all stickers, ship-local Y (m).");
			OffsetZ = ((BaseUnityPlugin)this).Config.Bind<float>("Placement", "OffsetZ", 0f, "Nudge all stickers, ship-local Z (m). Negative = further behind.");
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "fredthesled.VoidCrew.BumperStickers");
			try
			{
				ModdingUtils.RegisterLocalMod();
				Log.LogInfo((object)"Registered as a local (cosmetic, client-side) mod.");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not register as a local mod: " + ex.Message));
			}
			Log.LogInfo((object)"Bumper Stickers 1.3.2 loaded.");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "fredthesled.VoidCrew.BumperStickers";

		public const string PLUGIN_NAME = "BumperStickers";

		public const string USERS_PLUGIN_NAME = "Bumper Stickers";

		public const string PLUGIN_VERSION = "1.3.2";

		public const string PLUGIN_DESCRIPTION = "Slaps joke bumper stickers on the stern of your ship. Client-side; /stickers to adjust.";

		public const string PLUGIN_AUTHORS = "fredthesled";
	}
	internal enum ShipKind
	{
		Unknown,
		Frigate,
		Striker,
		Destroyer
	}
	internal struct Placement
	{
		public readonly string Resource;

		public readonly Vector3 LocalPosition;

		public readonly Quaternion LocalRotation;

		public readonly Vector3 LocalScale;

		public Placement(string resource, Vector3 pos, Quaternion rot, Vector3 scale)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			Resource = resource;
			LocalPosition = pos;
			LocalRotation = rot;
			LocalScale = scale;
		}
	}
	internal static class Placements
	{
		internal static readonly Dictionary<ShipKind, Placement[]> ByShip = new Dictionary<ShipKind, Placement[]>
		{
			[ShipKind.Frigate] = new Placement[4]
			{
				new Placement("honk", new Vector3(-1.6903f, 4.5724f, -20.73f), new Quaternion(0f, 0f, -0.034899496f, 0.99939084f), new Vector3(3.13536f, 0.78384f, 1f)),
				new Placement("honors", new Vector3(2.2289f, 4.5724f, -20.73f), new Quaternion(0f, 0f, 0.026176948f, 0.9996573f), new Vector3(3.13536f, 0.78384f, 1f)),
				new Placement("pride", new Vector3(-1.6903f, 3.475f, -20.73f), new Quaternion(0f, 0f, 0.021814885f, 0.99976206f), new Vector3(3.13536f, 0.78384f, 1f)),
				new Placement("rescued", new Vector3(2.2289f, 3.475f, -20.73f), new Quaternion(0f, 0f, -0.026176948f, 0.9996573f), new Vector3(3.13536f, 0.78384f, 1f))
			},
			[ShipKind.Striker] = new Placement[4]
			{
				new Placement("honk", new Vector3(-1.54f, 4.22f, -22.17f), new Quaternion(0f, 0f, -0.034899496f, 0.99939084f), new Vector3(2.42948f, 0.60737f, 1f)),
				new Placement("honors", new Vector3(1.44f, 4.17f, -22.1f), new Quaternion(0f, 0f, 0.026176948f, 0.9996573f), new Vector3(2.1492748f, 0.5373187f, 1f)),
				new Placement("pride", new Vector3(-4.09f, 4.414f, -20.497f), new Quaternion(0.16727015f, 0.5717232f, -0.1114021f, 0.7954514f), new Vector3(2.7063954f, 0.67659885f, 1f)),
				new Placement("rescued", new Vector3(4.493f, 4.393f, -19.612f), new Quaternion(0.1981368f, -0.56696314f, 0.11385787f, 0.79141074f), new Vector3(4f, 1f, 1f))
			},
			[ShipKind.Destroyer] = new Placement[4]
			{
				new Placement("honk", new Vector3(-2.03f, 3.55f, -39.62f), new Quaternion(0f, 0f, -0.034899496f, 0.99939084f), new Vector3(2.83116f, 0.70779f, 1f)),
				new Placement("honors", new Vector3(1.5089f, 3.55f, -39.62f), new Quaternion(0f, 0f, 0.026176948f, 0.9996573f), new Vector3(2.83116f, 0.70779f, 1f)),
				new Placement("pride", new Vector3(-2.03f, 2.55906f, -39.62f), new Quaternion(0f, 0f, 0.021814885f, 0.99976206f), new Vector3(2.83116f, 0.70779f, 1f)),
				new Placement("rescued", new Vector3(1.5089f, 2.55906f, -39.62f), new Quaternion(0f, 0f, -0.026176948f, 0.9996573f), new Vector3(2.83116f, 0.70779f, 1f))
			}
		};
	}
	[HarmonyPatch(typeof(PlayerControlledShip), "Start")]
	internal static class ShipStartPatch
	{
		private static void Postfix(PlayerControlledShip __instance)
		{
			((MonoBehaviour)BepinPlugin.Instance).StartCoroutine(StickerManager.AttachDelayed(__instance));
		}
	}
	internal static class StickerManager
	{
		private static readonly List<GameObject> Stickers = new List<GameObject>();

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

		private static PlayerControlledShip _lastShip;

		private static readonly List<Vector3> HullVerts = new List<Vector3>();

		private static readonly Regex PhantomCollider = new Regex("repulsion|shield|barrier|forcefield|force_field", RegexOptions.IgnoreCase);

		internal static PlayerControlledShip CurrentShip
		{
			get
			{
				if ((Object)(object)_lastShip != (Object)null)
				{
					return _lastShip;
				}
				ClientGame current = ClientGame.Current;
				if (current == null)
				{
					return null;
				}
				PlayerControlledShip playerShip = current.PlayerShip;
				if (playerShip == null)
				{
					return null;
				}
				GameObject gameObject = ((AbstractCloneStarObject)playerShip).GameObject;
				if (gameObject == null)
				{
					return null;
				}
				return gameObject.GetComponent<PlayerControlledShip>();
			}
		}

		internal static IEnumerator AttachDelayed(PlayerControlledShip ship)
		{
			yield return (object)new WaitForSeconds(2f);
			if ((Object)(object)ship != (Object)null)
			{
				Attach(ship);
			}
		}

		internal static void Attach(PlayerControlledShip ship)
		{
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: 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_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			Clear();
			if ((Object)(object)ship == (Object)null || !BepinPlugin.Enabled.Value)
			{
				return;
			}
			_lastShip = ship;
			Transform transform = ((Component)ship).transform;
			string how;
			ShipKind shipKind = IdentifyShip(transform, out how);
			if (shipKind == ShipKind.Unknown || !Placements.ByShip.TryGetValue(shipKind, out var value))
			{
				BepinPlugin.Log.LogWarning((object)("Unrecognised ship (" + how + "); no stickers placed."));
				return;
			}
			BepinPlugin.Log.LogInfo((object)$"Ship identified as {shipKind} ({how}); placing {value.Length} stickers.");
			int num = ExteriorLayer(transform);
			float value2 = BepinPlugin.ScaleMultiplier.Value;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(BepinPlugin.OffsetX.Value, BepinPlugin.OffsetY.Value, BepinPlugin.OffsetZ.Value);
			LogExteriorGeometry(transform);
			BuildHullVertexCache(transform);
			Placement[] array = value;
			for (int i = 0; i < array.Length; i++)
			{
				Placement placement = array[i];
				Texture2D val2 = LoadTexture("BumperStickers.Assets." + placement.Resource + ".png");
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Vector3 val3 = placement.LocalPosition + val;
				if (BepinPlugin.SnapToHull.Value)
				{
					float num2 = HullSurfaceZ(transform, val3.x, val3.y, Mathf.Max(placement.LocalScale.x, placement.LocalScale.y) * 0.5f);
					if (!float.IsNaN(num2))
					{
						BepinPlugin.Log.LogInfo((object)$"  {placement.Resource}: authored z={val3.z:F2} -> hull surface z={num2:F2}");
						val3.z = num2;
					}
					else
					{
						BepinPlugin.Log.LogInfo((object)$"  {placement.Resource}: no hull vertices near ({val3.x:F1}, {val3.y:F1}); keeping authored z={val3.z:F2}");
					}
				}
				val3 += placement.LocalRotation * new Vector3(0f, 0f, 0f - BepinPlugin.PushOut.Value);
				GameObject val4 = GameObject.CreatePrimitive((PrimitiveType)5);
				((Object)val4).name = "BumperSticker_" + placement.Resource;
				Object.Destroy((Object)(object)val4.GetComponent<Collider>());
				val4.layer = num;
				val4.transform.SetParent(transform, false);
				val4.transform.localPosition = val3;
				val4.transform.localRotation = placement.LocalRotation;
				val4.transform.localScale = new Vector3(placement.LocalScale.x * value2, placement.LocalScale.y * value2, 1f);
				MeshRenderer component = val4.GetComponent<MeshRenderer>();
				((Renderer)component).material = MakeMaterial(val2);
				((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
				Stickers.Add(val4);
			}
			ManualLogSource log = BepinPlugin.Log;
			string text = $"Attached {Stickers.Count} stickers to {shipKind} (layer {num}); ";
			object obj;
			if (Stickers.Count <= 0)
			{
				obj = "n/a";
			}
			else
			{
				Vector3 position = Stickers[0].transform.position;
				obj = ((Vector3)(ref position)).ToString("F1");
			}
			log.LogInfo((object)(text + "first at world " + (string?)obj + "."));
		}

		private static ShipKind IdentifyShip(Transform root, out string how)
		{
			MeshRenderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<MeshRenderer>();
			foreach (MeshRenderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					string text = ((Object)val).name.ToLowerInvariant();
					if (text.Contains("striker"))
					{
						how = "name '" + ((Object)val).name + "'";
						return ShipKind.Striker;
					}
					if (text.Contains("frigate"))
					{
						how = "name '" + ((Object)val).name + "'";
						return ShipKind.Frigate;
					}
					if (text.Contains("destroyer"))
					{
						how = "name '" + ((Object)val).name + "'";
						return ShipKind.Destroyer;
					}
				}
			}
			float num = MeasuredWidth(root);
			how = $"width {num:F1}m";
			if (num <= 0f)
			{
				return ShipKind.Unknown;
			}
			if (num < 50f)
			{
				return ShipKind.Frigate;
			}
			if (num < 80f)
			{
				return ShipKind.Destroyer;
			}
			return ShipKind.Striker;
		}

		private static void BuildHullVertexCache(Transform root)
		{
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			HullVerts.Clear();
			int num = 0;
			MeshFilter[] componentsInChildren = ((Component)root).GetComponentsInChildren<MeshFilter>();
			foreach (MeshFilter val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.sharedMesh == (Object)null || !val.sharedMesh.isReadable)
				{
					continue;
				}
				string text = ((Object)val).name.ToLowerInvariant();
				if ((text.Contains("exterior") || text.Contains("hull")) && !text.Contains("lod1") && !text.Contains("lod2") && !text.Contains("lod3") && !text.Contains("shadow") && !text.Contains("interior"))
				{
					num++;
					Transform transform = ((Component)val).transform;
					Vector3[] vertices = val.sharedMesh.vertices;
					foreach (Vector3 val2 in vertices)
					{
						HullVerts.Add(root.InverseTransformPoint(transform.TransformPoint(val2)));
					}
				}
			}
			BepinPlugin.Log.LogInfo((object)$"Hull vertex cache: {HullVerts.Count} verts from {num} exterior mesh(es).");
		}

		private static float HullSurfaceZ(Transform root, float x, float y, float radius)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < 4; i++)
			{
				if (HullVerts.Count <= 0)
				{
					break;
				}
				float num = radius * (float)(1 << i);
				float num2 = float.MaxValue;
				foreach (Vector3 hullVert in HullVerts)
				{
					if (!(Mathf.Abs(hullVert.x - x) > num) && !(Mathf.Abs(hullVert.y - y) > num) && hullVert.z < num2)
					{
						num2 = hullVert.z;
					}
				}
				if (num2 < float.MaxValue)
				{
					return num2;
				}
			}
			RaycastHit[] array = Physics.RaycastAll(root.TransformPoint(new Vector3(x, y, -400f)), root.forward, 800f, -1, (QueryTriggerInteraction)1);
			bool flag = false;
			RaycastHit val = default(RaycastHit);
			RaycastHit[] array2 = array;
			for (int j = 0; j < array2.Length; j++)
			{
				RaycastHit val2 = array2[j];
				if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && ((Component)((RaycastHit)(ref val2)).collider).transform.IsChildOf(root) && !PhantomCollider.IsMatch(((Object)((RaycastHit)(ref val2)).collider).name) && (!flag || ((RaycastHit)(ref val2)).distance < ((RaycastHit)(ref val)).distance))
				{
					val = val2;
					flag = true;
				}
			}
			if (flag)
			{
				BepinPlugin.Log.LogInfo((object)("    (ray hit collider '" + ((Object)((RaycastHit)(ref val)).collider).name + "')"));
				return root.InverseTransformPoint(((RaycastHit)(ref val)).point).z;
			}
			return float.NaN;
		}

		private static void LogExteriorGeometry(Transform root)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: 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_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			MeshRenderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<MeshRenderer>();
			Vector3 val2 = default(Vector3);
			Vector3 val3 = default(Vector3);
			foreach (MeshRenderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || !((Renderer)val).enabled || ((Object)val).name.StartsWith("BumperSticker"))
				{
					continue;
				}
				string text = ((Object)val).name.ToLowerInvariant();
				if (text.Contains("exterior") || text.Contains("hull"))
				{
					Bounds bounds = ((Renderer)val).bounds;
					Vector3 center = ((Bounds)(ref bounds)).center;
					Vector3 extents = ((Bounds)(ref bounds)).extents;
					((Vector3)(ref val2))..ctor(float.MaxValue, float.MaxValue, float.MaxValue);
					((Vector3)(ref val3))..ctor(float.MinValue, float.MinValue, float.MinValue);
					for (int j = 0; j < 8; j++)
					{
						Vector3 val4 = center + new Vector3((((j & 1) == 0) ? (-1f) : 1f) * extents.x, (((j & 2) == 0) ? (-1f) : 1f) * extents.y, (((j & 4) == 0) ? (-1f) : 1f) * extents.z);
						Vector3 val5 = root.InverseTransformPoint(val4);
						val2 = Vector3.Min(val2, val5);
						val3 = Vector3.Max(val3, val5);
					}
					list.Add($"    '{((Object)val).name}' local min={val2:F1} max={val3:F1}");
				}
			}
			BepinPlugin.Log.LogInfo((object)$"Exterior meshes in ship-local space ({list.Count}):");
			foreach (string item in list)
			{
				BepinPlugin.Log.LogInfo((object)item);
			}
		}

		private static float MeasuredWidth(Transform root)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			float num = float.MaxValue;
			float num2 = float.MinValue;
			MeshRenderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<MeshRenderer>();
			foreach (MeshRenderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || !((Renderer)val).enabled || ((Object)val).name.StartsWith("BumperSticker"))
				{
					continue;
				}
				Bounds bounds = ((Renderer)val).bounds;
				Vector3 center = ((Bounds)(ref bounds)).center;
				Vector3 extents = ((Bounds)(ref bounds)).extents;
				for (int j = 0; j < 8; j++)
				{
					Vector3 val2 = center + new Vector3((((j & 1) == 0) ? (-1f) : 1f) * extents.x, (((j & 2) == 0) ? (-1f) : 1f) * extents.y, (((j & 4) == 0) ? (-1f) : 1f) * extents.z);
					float x = root.InverseTransformPoint(val2).x;
					if (x < num)
					{
						num = x;
					}
					if (x > num2)
					{
						num2 = x;
					}
				}
			}
			if (!(num2 > num))
			{
				return 0f;
			}
			return num2 - num;
		}

		private static int ExteriorLayer(Transform root)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			float num = -1f;
			int layer = ((Component)root).gameObject.layer;
			MeshRenderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<MeshRenderer>();
			foreach (MeshRenderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && ((Renderer)val).enabled && !((Object)val).name.StartsWith("BumperSticker"))
				{
					Bounds bounds = ((Renderer)val).bounds;
					float num2 = ((Bounds)(ref bounds)).size.x * ((Bounds)(ref bounds)).size.y * ((Bounds)(ref bounds)).size.z;
					if (num2 > num)
					{
						num = num2;
						layer = ((Component)val).gameObject.layer;
					}
				}
			}
			return layer;
		}

		internal static void Clear()
		{
			foreach (GameObject sticker in Stickers)
			{
				if ((Object)(object)sticker != (Object)null)
				{
					Object.Destroy((Object)(object)sticker);
				}
			}
			Stickers.Clear();
		}

		internal static bool Reapply(out string status)
		{
			PlayerControlledShip currentShip = CurrentShip;
			if ((Object)(object)currentShip == (Object)null)
			{
				status = "No player ship right now - stickers will appear when one spawns.";
				return false;
			}
			Attach(currentShip);
			status = $"Stickers reapplied ({Stickers.Count}).";
			return true;
		}

		internal static string Describe()
		{
			PlayerControlledShip currentShip = CurrentShip;
			if ((Object)(object)currentShip == (Object)null)
			{
				return "No player ship right now.";
			}
			string how;
			ShipKind shipKind = IdentifyShip(((Component)currentShip).transform, out how);
			return $"ship={shipKind} ({how}) | placed={Stickers.Count} | scale x{BepinPlugin.ScaleMultiplier.Value} " + $"offset=({BepinPlugin.OffsetX.Value}, {BepinPlugin.OffsetY.Value}, {BepinPlugin.OffsetZ.Value}) " + $"enabled={BepinPlugin.Enabled.Value}";
		}

		internal static void DumpHierarchy(Transform t, int depth, int maxDepth)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			BepinPlugin.Log.LogInfo((object)$"{new string(' ', depth * 2)}{((Object)t).name} [{t.childCount} children, layer {((Component)t).gameObject.layer}]");
			if (depth >= maxDepth)
			{
				return;
			}
			foreach (Transform item in t)
			{
				DumpHierarchy(item, depth + 1, maxDepth);
			}
		}

		private static Material MakeMaterial(Texture2D tex)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			Shader val = null;
			string text = null;
			string[] array = new string[4] { "HDRP/Unlit", "HDRP/Lit", "Unlit/Texture", "Standard" };
			foreach (string text2 in array)
			{
				val = Shader.Find(text2);
				if ((Object)(object)val != (Object)null)
				{
					text = text2;
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				BepinPlugin.Log.LogError((object)"No usable shader found for stickers.");
				val = Shader.Find("Hidden/InternalErrorShader");
			}
			Material val2 = new Material(val);
			array = new string[3] { "_UnlitColorMap", "_BaseColorMap", "_MainTex" };
			foreach (string text3 in array)
			{
				if (val2.HasProperty(text3))
				{
					val2.SetTexture(text3, (Texture)(object)tex);
				}
			}
			array = new string[3] { "_UnlitColor", "_BaseColor", "_Color" };
			foreach (string text4 in array)
			{
				if (val2.HasProperty(text4))
				{
					val2.SetColor(text4, Color.white);
				}
			}
			BepinPlugin.Log.LogInfo((object)("Sticker material uses shader '" + text + "'."));
			return val2;
		}

		private static Texture2D LoadTexture(string resourceName)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			if (TexCache.TryGetValue(resourceName, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
			if (stream == null)
			{
				BepinPlugin.Log.LogError((object)("Embedded resource '" + resourceName + "' not found. Available: " + string.Join(", ", Assembly.GetExecutingAssembly().GetManifestResourceNames())));
				return null;
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
			if (!ImageConversion.LoadImage(val, array))
			{
				BepinPlugin.Log.LogError((object)("Failed to decode '" + resourceName + "'."));
				return null;
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			TexCache[resourceName] = val;
			return val;
		}
	}
	public class VoidManagerPlugin : VoidPlugin
	{
		public override MultiplayerType MPType => (MultiplayerType)8;

		public override string Author => "fredthesled";

		public override string Description => "Slaps joke bumper stickers on the stern of your ship. Client-side; /stickers to adjust.";
	}
}
namespace BumperStickers.Commands
{
	public class StickersCommand : ChatCommand
	{
		public override string[] CommandAliases()
		{
			return new string[2] { "stickers", "sticker" };
		}

		public override string Description()
		{
			return "Toggle/tune the bumper stickers. Subcommands: on, off, respawn, pos <x> <y> <z>, scale <s>, info, dump.";
		}

		public override string[] UsageExamples()
		{
			return new string[4] { "/stickers", "/stickers pos 0 -0.5 0", "/stickers scale 1.2", "/stickers info" };
		}

		public override void Execute(string arguments)
		{
			string[] array = (arguments ?? "").Trim().Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			string status;
			switch ((array.Length == 0) ? "toggle" : array[0].ToLowerInvariant())
			{
			case "on":
				BepinPlugin.Enabled.Value = true;
				StickerManager.Reapply(out status);
				Messaging.Echo("Stickers ON. " + status, true);
				break;
			case "off":
				BepinPlugin.Enabled.Value = false;
				StickerManager.Clear();
				Messaging.Echo("Stickers OFF.", true);
				break;
			case "toggle":
				if (!BepinPlugin.Enabled.Value)
				{
					goto case "on";
				}
				goto case "off";
			case "reload":
			case "respawn":
				StickerManager.Reapply(out status);
				Messaging.Echo(status, true);
				break;
			case "pos":
			{
				if (array.Length == 4 && TryF(array[1], out var f) && TryF(array[2], out var f2) && TryF(array[3], out var f3))
				{
					BepinPlugin.OffsetX.Value = f;
					BepinPlugin.OffsetY.Value = f2;
					BepinPlugin.OffsetZ.Value = f3;
					StickerManager.Reapply(out status);
					Messaging.Echo($"Offset set to ({f}, {f2}, {f3}). {status}", true);
				}
				else
				{
					Messaging.Echo("Usage: /stickers pos <x> <y> <z>  (ship-local metres; -z = further back)", true);
				}
				break;
			}
			case "scale":
			{
				if (array.Length == 2 && TryF(array[1], out var f5) && f5 > 0f)
				{
					BepinPlugin.ScaleMultiplier.Value = f5;
					StickerManager.Reapply(out status);
					Messaging.Echo($"Scale multiplier set to {f5}. {status}", true);
				}
				else
				{
					Messaging.Echo("Usage: /stickers scale <multiplier>  (1 = exactly as authored)", true);
				}
				break;
			}
			case "snap":
				BepinPlugin.SnapToHull.Value = !BepinPlugin.SnapToHull.Value;
				StickerManager.Reapply(out status);
				Messaging.Echo("Snap-to-hull " + (BepinPlugin.SnapToHull.Value ? "ON (find real hull depth)" : "OFF (use authored depth)") + ". " + status, true);
				break;
			case "out":
			{
				if (array.Length == 2 && TryF(array[1], out var f4))
				{
					BepinPlugin.PushOut.Value = f4;
					StickerManager.Reapply(out status);
					Messaging.Echo($"Lift off hull set to {f4}m. {status}", true);
				}
				else
				{
					Messaging.Echo("Usage: /stickers out <metres>  (how far to lift stickers off the hull)", true);
				}
				break;
			}
			case "info":
				Messaging.Echo(StickerManager.Describe(), true);
				break;
			case "dump":
			{
				PlayerControlledShip currentShip = StickerManager.CurrentShip;
				if ((Object)(object)currentShip == (Object)null)
				{
					Messaging.Echo("No player ship right now.", true);
					break;
				}
				StickerManager.DumpHierarchy(((Component)currentShip).transform, 0, 3);
				Messaging.Echo("Ship hierarchy dumped to BepInEx\\LogOutput.log (depth 3).", true);
				break;
			}
			default:
				Messaging.Echo("Subcommands: on | off | respawn | snap | out <m> | pos <x> <y> <z> | scale <s> | info | dump", true);
				break;
			}
		}

		private static bool TryF(string s, out float f)
		{
			return float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out f);
		}
	}
}