Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of StabilityBeams v0.3.0
StabilityBeams.dll
Decompiled a day agousing 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; } }