Decompiled source of StabilityBeams v0.3.0

StabilityBeams.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace StabilityBeams;

[BepInPlugin("Aquatechnic.NewMetalBeams", "New Metal Beams", "0.3.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class StabilityBeamsPlugin : BaseUnityPlugin
{
	public const string ModGuid = "Aquatechnic.NewMetalBeams";

	public const string ModName = "New Metal Beams";

	public const string ModVersion = "0.3.0";

	internal static ManualLogSource Log;

	internal static string PluginDir;

	internal static ConfigEntry<string> BasePrefabs;

	internal static ConfigEntry<bool> RecolorEnabled;

	internal static ConfigEntry<float> MetalSaturationMax;

	internal static ConfigEntry<string> MetalMaterialKeywords;

	internal static ConfigEntry<string> ColorSource;

	private void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		PluginDir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		BindConfig();
		ApplyPatches();
		PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
	}

	private void BindConfig()
	{
		//IL_0023: 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_0030: Expected O, but got Unknown
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected O, but got Unknown
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Expected O, but got Unknown
		BasePrefabs = ((BaseUnityPlugin)this).Config.Bind<string>("General", "BasePrefabs", "woodiron_beam,woodiron_beam_26,woodiron_beam_45,woodiron_beam_67,woodiron_pole", new ConfigDescription("Comma-separated vanilla piece prefabs that get a variant for every metal tier (restart required). Names containing 'pole' / 'support' are labelled Pole / Support, everything else Beam.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		RecolorEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "ReplaceMetalTexture", true, "Replace the iron parts of each variant with the look of the tier's metal (taken from that metal's item texture).");
		MetalSaturationMax = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "MetalSaturationMax", 0.22f, new ConfigDescription("For materials that mix wood and metal: pixels with saturation below this count as metal. Raise if straps are missed, lower if wood gets recolored.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 0.6f), Array.Empty<object>()));
		MetalMaterialKeywords = ((BaseUnityPlugin)this).Config.Bind<string>("Visuals", "MetalMaterialKeywords", "iron,metal,strap", "Materials (or textures) whose name contains one of these words are treated as entirely metal and fully replaced.");
		ColorSource = ((BaseUnityPlugin)this).Config.Bind<string>("Visuals", "ColorSource", "Config", "Where the metal colors come from: 'Config' = the ShadowColor/HighlightColor entries of each tier (reliable), 'Reference' = sampled from the metal item's own texture.");
		Tiers.BindAll(((BaseUnityPlugin)this).Config);
	}

	private void ApplyPatches()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Expected O, but got Unknown
		Harmony val = new Harmony("Aquatechnic.NewMetalBeams");
		MethodInfo methodInfo = AccessTools.Method(typeof(WearNTear), "GetMaterialProperties", (Type[])null, (Type[])null);
		if (methodInfo == null)
		{
			Log.LogError((object)"WearNTear.GetMaterialProperties not found - stability scaling is DISABLED. The game was probably updated; check the method name/signature in the decompiled assembly.");
			return;
		}
		try
		{
			val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "MaterialPropertiesPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Failed to patch GetMaterialProperties (parameter names/types changed?): " + ex));
		}
	}

	private void OnVanillaPrefabsAvailable()
	{
		PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
		Log.LogInfo((object)("BasePrefabs read from config: " + BasePrefabs.Value));
		List<string> list = (from n in BasePrefabs.Value.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)
			select n.Trim() into n
			where n.Length > 0
			select n).ToList();
		for (int num = 1; num <= 4; num++)
		{
			TierDef tierDef = Tiers.Get(num);
			if (!tierDef.Enabled.Value)
			{
				continue;
			}
			foreach (string item in list)
			{
				try
				{
					CreateTierPiece(item, tierDef);
				}
				catch (Exception arg)
				{
					Log.LogError((object)$"Failed to create {tierDef.Name} variant of '{item}': {arg}");
				}
			}
		}
	}

	private void CreateTierPiece(string baseName, TierDef def)
	{
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: 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_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Expected O, but got Unknown
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Expected O, but got Unknown
		//IL_0232: Unknown result type (might be due to invalid IL or missing references)
		//IL_0239: Expected O, but got Unknown
		//IL_0118: 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_0125: 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_013e: Expected O, but got Unknown
		GameObject prefab = PrefabManager.Instance.GetPrefab(baseName);
		Piece val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Piece>() : null);
		if ((Object)(object)val == (Object)null || (Object)(object)prefab.GetComponent<WearNTear>() == (Object)null)
		{
			Log.LogWarning((object)("Base prefab '" + baseName + "' not found or is not a WearNTear piece - skipped."));
			return;
		}
		string text = baseName.ToLowerInvariant();
		string text2 = (text.Contains("pole") ? "Pole" : (text.Contains("support") ? "Support" : "Beam"));
		Match match = Regex.Match(text, "_(\\d+)$");
		if (match.Success)
		{
			text2 = text2 + " " + match.Groups[1].Value + "°";
		}
		List<RequirementConfig> list = new List<RequirementConfig>();
		int num = 0;
		Requirement[] resources = val.m_resources;
		foreach (Requirement val2 in resources)
		{
			if (!((Object)(object)val2.m_resItem == (Object)null))
			{
				string name = ((Object)val2.m_resItem).name;
				if (name == "Iron")
				{
					num += val2.m_amount;
					continue;
				}
				list.Add(new RequirementConfig
				{
					Item = name,
					Amount = val2.m_amount,
					Recover = true
				});
			}
		}
		int num2 = Math.Max(1, (int)Math.Round((float)Math.Max(1, num) * def.CostMult.Value));
		list.Add(new RequirementConfig
		{
			Item = def.ItemPrefab.Value,
			Amount = num2,
			Recover = true
		});
		string text3 = "sb_" + def.Key + "_" + baseName;
		PieceConfig val3 = new PieceConfig();
		val3.Name = def.Name + "-strapped " + text2;
		val3.Description = "A wooden " + text2.ToLowerInvariant() + " strapped with " + def.Name + ". More stable and sturdier than iron.";
		val3.PieceTable = "Hammer";
		val3.Requirements = list.ToArray();
		PieceConfig val4 = val3;
		CustomPiece val5 = new CustomPiece(text3, baseName, val4);
		GameObject piecePrefab = val5.PiecePrefab;
		WearNTear component = piecePrefab.GetComponent<WearNTear>();
		component.m_health *= def.HealthMult.Value;
		piecePrefab.AddComponent<TieredBeam>().Tier = def.Index;
		if (RecolorEnabled.Value)
		{
			TierVisuals.ApplyToPrefab(piecePrefab, def.Index);
			try
			{
				val5.Piece.m_icon = TierVisuals.RecolorSprite(val5.Piece.m_icon, def.Index);
			}
			catch (Exception ex)
			{
				Log.LogDebug((object)("Icon recolor failed: " + ex.Message));
			}
		}
		PieceManager.Instance.AddPiece(val5);
		Log.LogInfo((object)$"Added piece {text3} ({num2} x {def.ItemPrefab.Value})");
	}
}
public static class Patches
{
	public static void MaterialPropertiesPostfix(WearNTear __instance, ref float maxSupport, ref float minSupport, ref float horizontalLoss, ref float verticalLoss)
	{
		if (TieredBeam.Registry.TryGetValue(__instance, out var value))
		{
			TierDef tierDef = Tiers.Get(value.Tier);
			if (tierDef != null)
			{
				maxSupport *= tierDef.SupportMult.Value;
				horizontalLoss *= tierDef.LossMult.Value;
				verticalLoss *= tierDef.LossMult.Value;
			}
		}
	}
}
public class TieredBeam : MonoBehaviour
{
	internal static readonly Dictionary<WearNTear, TieredBeam> Registry = new Dictionary<WearNTear, TieredBeam>();

	public int Tier;

	private WearNTear _wnt;

	private void Awake()
	{
		_wnt = ((Component)this).GetComponent<WearNTear>();
		if ((Object)(object)_wnt != (Object)null)
		{
			Registry[_wnt] = this;
		}
	}

	private void OnDestroy()
	{
		if ((Object)(object)_wnt != (Object)null)
		{
			Registry.Remove(_wnt);
		}
	}
}
internal class TierDef
{
	public int Index;

	public string Key;

	public string Name;

	public Color FallbackShadow;

	public Color FallbackHighlight;

	public ConfigEntry<string> ShadowColor;

	public ConfigEntry<string> HighlightColor;

	public ConfigEntry<bool> Enabled;

	public ConfigEntry<float> SupportMult;

	public ConfigEntry<float> LossMult;

	public ConfigEntry<float> HealthMult;

	public ConfigEntry<string> ItemPrefab;

	public ConfigEntry<float> CostMult;

	public Color Shadow => Parse(ShadowColor.Value, FallbackShadow);

	public Color Highlight => Parse(HighlightColor.Value, FallbackHighlight);

	private static Color Parse(string hex, Color fallback)
	{
		//IL_0011: 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)
		Color result = default(Color);
		if (!ColorUtility.TryParseHtmlString(hex.Trim(), ref result))
		{
			return fallback;
		}
		return result;
	}
}
internal static class Tiers
{
	public const int Count = 4;

	private static readonly TierDef[] Defs = new TierDef[5];

	public static TierDef Get(int tier)
	{
		if (tier >= 1 && tier <= 4)
		{
			return Defs[tier];
		}
		return null;
	}

	private static ConfigEntry<T> Bind<T>(ConfigFile cfg, string section, string key, T def, string desc)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Expected O, but got Unknown
		return cfg.Bind<T>(section, key, def, new ConfigDescription(desc, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
	}

	private static void Define(ConfigFile cfg, int idx, string key, string name, string item, float support, float loss, float health, float cost, Color shadow, Color highlight)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
		string text = $"Tier {idx} - {name}";
		Defs[idx] = new TierDef
		{
			Index = idx,
			Key = key,
			Name = name,
			FallbackShadow = shadow,
			FallbackHighlight = highlight,
			Enabled = Bind(cfg, text, "Enabled", def: true, "If false, this tier's pieces are not added (restart required)."),
			SupportMult = Bind(cfg, text, "SupportMultiplier", support, "Multiplier on max support (higher = taller / longer spans)."),
			LossMult = Bind(cfg, text, "LossMultiplier", loss, "Multiplier on horizontal and vertical support loss (lower = better)."),
			HealthMult = Bind(cfg, text, "HealthMultiplier", health, "Multiplier on piece health (restart required)."),
			ItemPrefab = Bind(cfg, text, "MetalItem", item, "Item prefab that replaces Iron in the recipe and supplies the texture (restart required)."),
			ShadowColor = cfg.Bind<string>(text, "ShadowColor", "#" + ColorUtility.ToHtmlStringRGB(shadow), "Hex color of the darkest parts of the metal (e.g. #5A0610)."),
			HighlightColor = cfg.Bind<string>(text, "HighlightColor", "#" + ColorUtility.ToHtmlStringRGB(highlight), "Hex color of the brightest parts of the metal (e.g. #FFC83A)."),
			CostMult = Bind(cfg, text, "CostMultiplier", cost, "Metal amount = base recipe's Iron amount x this (min 1) (restart required).")
		};
	}

	public static void BindAll(ConfigFile cfg)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: 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_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		Define(cfg, 1, "silver", "Silver", "Silver", 1.25f, 0.85f, 1.25f, 1f, new Color(0.35f, 0.38f, 0.44f), new Color(0.95f, 0.97f, 1f));
		Define(cfg, 2, "blackmetal", "Black Metal", "BlackMetal", 1.5f, 0.7f, 1.6f, 1f, new Color(0.03f, 0.03f, 0.06f), new Color(0.27f, 0.27f, 0.37f));
		Define(cfg, 3, "flametal", "Flametal", "FlametalNew", 1.8f, 0.55f, 2f, 1.5f, new Color(0.23f, 0.04f, 0.01f), new Color(1f, 0.48f, 0.13f));
		Define(cfg, 4, "bloodgold", "Bloodgold", "Gold", 2.2f, 0.4f, 2.6f, 2f, new Color(0.35f, 0.02f, 0.05f), new Color(1f, 0.78f, 0.23f));
	}
}
internal static class TierVisuals
{
	private class RefData
	{
		public Color[] Ramp = (Color[])(object)new Color[256];

		public Color Emission = Color.black;

		public float Metallic = -1f;

		public float Glossiness = -1f;
	}

	private static readonly Dictionary<int, RefData> Refs = new Dictionary<int, RefData>();

	private static readonly Dictionary<string, Material> Materials = new Dictionary<string, Material>();

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

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

	public static void ApplyToPrefab(GameObject prefab, int tier)
	{
		Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val in componentsInChildren)
		{
			if (!(val is MeshRenderer) && !(val is SkinnedMeshRenderer))
			{
				continue;
			}
			Material[] sharedMaterials = val.sharedMaterials;
			bool flag = false;
			for (int j = 0; j < sharedMaterials.Length; j++)
			{
				Material val2 = sharedMaterials[j];
				if (!((Object)(object)val2 == (Object)null))
				{
					bool flag2 = IsMetalMaterial(val2);
					if (tier == 1)
					{
						StabilityBeamsPlugin.Log.LogInfo((object)("[" + ((Object)prefab).name + "] renderer '" + ((Object)val).name + "': material '" + ((Object)val2).name + "', texture '" + (((Object)(object)val2.mainTexture != (Object)null) ? ((Object)val2.mainTexture).name : "none") + "' -> " + (flag2 ? "ALL metal" : "metal by saturation")));
					}
					Material tierMaterial = GetTierMaterial(val2, tier, flag2);
					if ((Object)(object)tierMaterial != (Object)(object)val2)
					{
						sharedMaterials[j] = tierMaterial;
						flag = true;
					}
				}
			}
			if (flag)
			{
				val.sharedMaterials = sharedMaterials;
			}
		}
	}

	public static Sprite RecolorSprite(Sprite src, int tier)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)src == (Object)null || (Object)(object)src.texture == (Object)null)
		{
			return src;
		}
		Texture2D val = Recolor((Texture)(object)src.texture, tier, allMetal: false);
		if ((Object)(object)val == (Object)null)
		{
			return src;
		}
		return Sprite.Create(val, src.rect, new Vector2(0.5f, 0.5f), src.pixelsPerUnit);
	}

	private static bool IsMetalMaterial(Material m)
	{
		IEnumerable<string> source = from w in StabilityBeamsPlugin.MetalMaterialKeywords.Value.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)
			select w.Trim().ToLowerInvariant() into w
			where w.Length > 0
			select w;
		string a = (((Object)m).name ?? "").ToLowerInvariant();
		string b = (((Object)(object)m.mainTexture != (Object)null) ? (((Object)m.mainTexture).name ?? "").ToLowerInvariant() : "");
		return source.Any((string w) => a.Contains(w) || b.Contains(w));
	}

	private static Material GetTierMaterial(Material src, int tier, bool allMetal)
	{
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Expected O, but got Unknown
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)src == (Object)null))
		{
			Texture mainTexture = src.mainTexture;
			Texture2D val = (Texture2D)(object)((mainTexture is Texture2D) ? mainTexture : null);
			if (val != null)
			{
				string key = $"{((Object)src).GetInstanceID()}:{tier}:{allMetal}";
				if (Materials.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
				{
					return value;
				}
				Texture2D val2 = LoadCustom(((Object)val).name, tier) ?? Recolor((Texture)(object)val, tier, allMetal);
				if ((Object)(object)val2 == (Object)null)
				{
					return src;
				}
				Material val3 = new Material(src)
				{
					name = ((Object)src).name + "_sb" + tier
				};
				val3.mainTexture = (Texture)(object)val2;
				if (allMetal)
				{
					RefData refData = GetRef(tier);
					if (refData.Metallic >= 0f && val3.HasProperty("_Metallic"))
					{
						val3.SetFloat("_Metallic", refData.Metallic);
					}
					if (refData.Glossiness >= 0f && val3.HasProperty("_Glossiness"))
					{
						val3.SetFloat("_Glossiness", refData.Glossiness);
					}
					if (((Color)(ref refData.Emission)).maxColorComponent > 0.01f && val3.HasProperty("_EmissionColor"))
					{
						val3.EnableKeyword("_EMISSION");
						val3.SetColor("_EmissionColor", refData.Emission);
					}
				}
				Materials[key] = val3;
				return val3;
			}
		}
		return src;
	}

	private static RefData GetRef(int tier)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: 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_0045: 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_026f: Unknown result type (might be due to invalid IL or missing references)
		//IL_028f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: 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_01dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		if (Refs.TryGetValue(tier, out var value))
		{
			return value;
		}
		TierDef tierDef = Tiers.Get(tier);
		RefData refData = new RefData();
		for (int i = 0; i < 256; i++)
		{
			refData.Ramp[i] = Color.Lerp(tierDef.Shadow, tierDef.Highlight, (float)i / 255f);
		}
		bool flag = string.Equals(StabilityBeamsPlugin.ColorSource.Value.Trim(), "Reference", StringComparison.OrdinalIgnoreCase);
		try
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(tierDef.ItemPrefab.Value);
			Material val = null;
			Texture2D val2 = null;
			if ((Object)(object)prefab != (Object)null)
			{
				Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					Material[] sharedMaterials = componentsInChildren[j].sharedMaterials;
					foreach (Material val3 in sharedMaterials)
					{
						if ((Object)(object)val3 != (Object)null)
						{
							Texture mainTexture = val3.mainTexture;
							Texture2D val4 = (Texture2D)(object)((mainTexture is Texture2D) ? mainTexture : null);
							if (val4 != null)
							{
								val = val3;
								val2 = val4;
								break;
							}
						}
					}
					if ((Object)(object)val2 != (Object)null)
					{
						break;
					}
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				StabilityBeamsPlugin.Log.LogWarning((object)("No reference texture found for item '" + tierDef.ItemPrefab.Value + "' - using fallback colors for " + tierDef.Name + "."));
			}
			else
			{
				if (flag)
				{
					BuildRamp(val2, refData.Ramp);
				}
				if (val.HasProperty("_Metallic"))
				{
					refData.Metallic = val.GetFloat("_Metallic");
				}
				if (val.HasProperty("_Glossiness"))
				{
					refData.Glossiness = val.GetFloat("_Glossiness");
				}
				if (val.HasProperty("_EmissionColor"))
				{
					Color color = val.GetColor("_EmissionColor");
					if (((Color)(ref color)).maxColorComponent > 0.01f)
					{
						refData.Emission = color;
					}
				}
			}
		}
		catch (Exception ex)
		{
			StabilityBeamsPlugin.Log.LogWarning((object)("Reference sampling for " + tierDef.Name + " failed, using fallback colors: " + ex.Message));
		}
		StabilityBeamsPlugin.Log.LogInfo((object)(tierDef.Name + ": color source " + (flag ? "reference texture" : "config") + ", ramp dark=" + ColorUtility.ToHtmlStringRGB(refData.Ramp[0]) + " mid=" + ColorUtility.ToHtmlStringRGB(refData.Ramp[128]) + " light=" + ColorUtility.ToHtmlStringRGB(refData.Ramp[255])));
		Refs[tier] = refData;
		return refData;
	}

	private static void BuildRamp(Texture2D refTex, Color[] ramp)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: 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_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_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = ReadableCopy((Texture)(object)refTex, 256, mipmaps: false);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Color32[] pixels = val.GetPixels32();
		Object.Destroy((Object)(object)val);
		List<float> list = new List<float>(pixels.Length);
		List<Color> list2 = new List<Color>(pixels.Length);
		Color32[] array = pixels;
		foreach (Color32 val2 in array)
		{
			if (val2.a >= 128)
			{
				Color item = Color32.op_Implicit(val2);
				list.Add(((Color)(ref item)).grayscale);
				list2.Add(item);
			}
		}
		int count = list.Count;
		if (count < 16)
		{
			return;
		}
		float[] keys = list.ToArray();
		Color[] array2 = list2.ToArray();
		Array.Sort(keys, array2);
		for (int j = 0; j < 256; j++)
		{
			int num = j * count / 256;
			int num2 = Math.Max(num + 1, (j + 1) * count / 256);
			float num3 = 0f;
			float num4 = 0f;
			float num5 = 0f;
			for (int k = num; k < num2; k++)
			{
				num3 += array2[k].r;
				num4 += array2[k].g;
				num5 += array2[k].b;
			}
			int num6 = num2 - num;
			ramp[j] = new Color(num3 / (float)num6, num4 / (float)num6, num5 / (float)num6, 1f);
		}
	}

	private static Texture2D Recolor(Texture src, int tier, bool allMetal)
	{
		//IL_009f: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: 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_026f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0271: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: 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_027f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0283: Unknown result type (might be due to invalid IL or missing references)
		//IL_0293: Unknown result type (might be due to invalid IL or missing references)
		//IL_0295: 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)
		if (!(src is Texture2D))
		{
			return null;
		}
		string key = $"{((Object)src).GetInstanceID()}:{tier}:{allMetal}";
		if (Recolored.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
		{
			return value;
		}
		RefData refData = GetRef(tier);
		Texture2D val = ReadableCopy(src, 0, mipmaps: true);
		if ((Object)(object)val == (Object)null)
		{
			return null;
		}
		float value2 = StabilityBeamsPlugin.MetalSaturationMax.Value;
		Color32[] pixels = val.GetPixels32();
		int num = pixels.Length;
		float[] array = new float[num];
		int[] array2 = new int[256];
		int num2 = 0;
		float num4 = default(float);
		float num5 = default(float);
		float num6 = default(float);
		for (int i = 0; i < num; i++)
		{
			Color val2 = Color32.op_Implicit(pixels[i]);
			float num3;
			if (pixels[i].a < 10)
			{
				num3 = 0f;
			}
			else if (allMetal)
			{
				num3 = 1f;
			}
			else
			{
				Color.RGBToHSV(val2, ref num4, ref num5, ref num6);
				num3 = Mathf.Clamp01(1f - (num5 - value2) / 0.08f);
			}
			array[i] = num3;
			if (num3 > 0.5f)
			{
				array2[Mathf.Clamp((int)(((Color)(ref val2)).grayscale * 255f), 0, 255)]++;
				num2++;
			}
		}
		StabilityBeamsPlugin.Log.LogInfo((object)$"Recolor '{((Object)src).name}' for tier {tier}: {num2} of {num} pixels detected as metal ({100f * (float)num2 / (float)num:F1}%)");
		if (num2 == 0)
		{
			StabilityBeamsPlugin.Log.LogWarning((object)("No metal pixels found in '" + ((Object)src).name + "'. Raise Visuals.MetalSaturationMax in the config."));
			Object.Destroy((Object)(object)val);
			return null;
		}
		float[] array3 = new float[256];
		int num7 = 0;
		for (int j = 0; j < 256; j++)
		{
			array3[j] = num7;
			num7 += array2[j];
		}
		for (int k = 0; k < num; k++)
		{
			if (!(array[k] <= 0f))
			{
				Color val3 = Color32.op_Implicit(pixels[k]);
				int num8 = Mathf.Clamp((int)(((Color)(ref val3)).grayscale * 255f), 0, 255);
				float num9 = (array3[num8] + 0.5f * (float)array2[num8]) / (float)num2;
				Color val4 = refData.Ramp[Mathf.Clamp((int)(num9 * 255f), 0, 255)];
				Color val5 = Color.Lerp(val3, val4, array[k]);
				val5.a = val3.a;
				pixels[k] = Color32.op_Implicit(val5);
			}
		}
		val.SetPixels32(pixels);
		val.Apply(true);
		((Object)val).name = ((Object)src).name + "_sb" + tier;
		Recolored[key] = val;
		return val;
	}

	private static Texture2D ReadableCopy(Texture src, int maxSize, bool mipmaps)
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Expected O, but got Unknown
		if ((Object)(object)src == (Object)null || src.width <= 0 || src.height <= 0)
		{
			return null;
		}
		int num = src.width;
		int num2 = src.height;
		if (maxSize > 0 && Math.Max(num, num2) > maxSize)
		{
			float num3 = (float)maxSize / (float)Math.Max(num, num2);
			num = Math.Max(1, (int)((float)num * num3));
			num2 = Math.Max(1, (int)((float)num2 * num3));
		}
		RenderTexture temporary = RenderTexture.GetTemporary(num, num2, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
		RenderTexture active = RenderTexture.active;
		try
		{
			Graphics.Blit(src, temporary);
			RenderTexture.active = temporary;
			Texture2D val = new Texture2D(num, num2, (TextureFormat)4, mipmaps);
			val.ReadPixels(new Rect(0f, 0f, (float)num, (float)num2), 0, 0);
			((Texture)val).wrapMode = src.wrapMode;
			((Texture)val).filterMode = src.filterMode;
			((Texture)val).anisoLevel = src.anisoLevel;
			return val;
		}
		finally
		{
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
		}
	}

	private static Texture2D LoadCustom(string sourceTextureName, int tier)
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Expected O, but got Unknown
		string text = Path.Combine(Path.Combine(StabilityBeamsPlugin.PluginDir, "Textures"), $"{sourceTextureName}_tier{tier}.png");
		if (Files.TryGetValue(text, out var value))
		{
			return value;
		}
		Texture2D val = null;
		if (File.Exists(text))
		{
			val = new Texture2D(2, 2, (TextureFormat)4, true);
			if (ImageConversion.LoadImage(val, File.ReadAllBytes(text)))
			{
				((Object)val).name = Path.GetFileName(text);
			}
			else
			{
				StabilityBeamsPlugin.Log.LogWarning((object)("Could not decode texture: " + text));
				val = null;
			}
		}
		Files[text] = val;
		return val;
	}
}