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 ValheimRarity v4.4.0
plugins/ValheimRarity/ValheimRarity.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [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("ValheimRarity")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("4.4.0.0")] [assembly: AssemblyInformationalVersion("4.4.0")] [assembly: AssemblyProduct("ValheimRarity")] [assembly: AssemblyTitle("ValheimRarity")] [assembly: AssemblyVersion("4.4.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 ValheimRarity { internal static class Borders { private const string RootName = "RarityBorder"; private static Sprite raritySprite; private static Sprite Sprite() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)raritySprite)) { return raritySprite; } using Stream stream = typeof(Borders).Assembly.GetManifestResourceStream("ValheimRarity.RarityFrame.png"); using MemoryStream memoryStream = new MemoryStream(); if (stream == null) { throw new InvalidOperationException("Missing rarity frame resource."); } stream.CopyTo(memoryStream); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); MethodInfo method = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule", throwOnError: true).GetMethod("LoadImage", new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) }); if (method == null || !(bool)method.Invoke(null, new object[3] { val, memoryStream.ToArray(), false })) { throw new InvalidOperationException("Could not load the Epic Loot rarity frame."); } ((Object)val).name = "ValheimRarity-RarityFrame"; ((Texture)val).wrapMode = (TextureWrapMode)1; raritySprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); ((Object)raritySprite).name = "ValheimRarity-RarityFrame"; return raritySprite; } internal static void Set(Transform parent, int tier) { //IL_00cb: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_007b: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) Transform val = parent.Find("RarityBorder"); if (tier < 0) { if (Object.op_Implicit((Object)(object)val)) { ((Component)val).gameObject.SetActive(false); } return; } if (!Object.op_Implicit((Object)(object)val)) { GameObject val2 = new GameObject("RarityBorder", new Type[2] { typeof(RectTransform), typeof(Image) }); val = val2.transform; val.SetParent(parent, false); RectTransform val3 = (RectTransform)val; val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; val3.offsetMin = Vector2.zero; val3.offsetMax = Vector2.zero; Image component = val2.GetComponent<Image>(); component.sprite = Sprite(); component.preserveAspect = true; ((Graphic)component).raycastTarget = false; } Color color = default(Color); ColorUtility.TryParseHtmlString(Settings.RarityColor(tier), ref color); ((Graphic)((Component)val).GetComponent<Image>()).color = color; ((Component)val).gameObject.SetActive(true); Transform val4 = parent.Find("equiped"); if (Object.op_Implicit((Object)(object)val4)) { int num = val4.GetSiblingIndex(); if (val.GetSiblingIndex() < num) { num--; } val.SetSiblingIndex(num); } else { val.SetAsFirstSibling(); } } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] internal static class InventoryBorders { private static void Postfix(InventoryGrid __instance, List<InventoryElement> ___m_elements) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = __instance.GetInventory(); List<ItemData> list = ((inventory != null) ? inventory.GetAllItems() : null); foreach (InventoryElement ___m_element in ___m_elements) { ItemData item = null; if (list != null) { foreach (ItemData item2 in list) { if (item2.m_gridPos.x == ___m_element.Position.x && item2.m_gridPos.y == ___m_element.Position.y) { item = item2; break; } } } Borders.Set(((Component)___m_element.m_button).transform, Plugin.Tier(item)); } } } internal static class ItemNames { internal static string Decorate(ItemData item, string original) { int num = Plugin.Tier(item); if (num >= 0) { ConfigEntry<bool> prefixNames = Settings.PrefixNames; if ((prefixNames == null || prefixNames.Value) && !string.IsNullOrEmpty(original)) { string text = "<color=" + Settings.RarityColor(num) + ">" + Settings.RarityName(num) + " "; if (original.StartsWith(text, StringComparison.Ordinal)) { return original; } return text + original + "</color>"; } } return original; } internal static string Localized(ItemData item) { return Decorate(item, Localization.instance.Localize(item.m_shared.m_name)); } } [HarmonyPatch(typeof(InventoryGrid), "CreateItemTooltip")] internal static class NamedTooltips { [HarmonyPriority(0)] private static void Postfix(ItemData __0, UITooltip __1) { __1.m_topic = ItemNames.Decorate(__0, __1.m_topic); } } [HarmonyPatch(typeof(ItemDrop), "GetHoverText")] internal static class NamedDropText { [HarmonyPriority(0)] private static void Postfix(ItemDrop __instance, ref string __result) { ItemData itemData = __instance.m_itemData; if (Plugin.Tier(itemData) < 0) { return; } ConfigEntry<bool> prefixNames = Settings.PrefixNames; if (prefixNames == null || prefixNames.Value) { string text = Localization.instance.Localize(itemData.m_shared.m_name); string text2 = ItemNames.Decorate(itemData, text); __result = Localization.instance.Localize(__result); if (!__result.Contains(text2)) { __result = __result.Replace(text, text2); } } } } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")] internal static class NamedVanillaUpgrade { [HarmonyPriority(0)] private static void Postfix(InventoryGui __instance) { if (!Station.Active) { object value = AccessTools.Field(typeof(InventoryGui), "m_selectedRecipe").GetValue(__instance); object? value2 = AccessTools.Property(value.GetType(), "ItemData").GetValue(value); ItemData item = (ItemData)((value2 is ItemData) ? value2 : null); if (Plugin.Tier(item) >= 0) { __instance.m_recipeName.text = ItemNames.Decorate(item, __instance.m_recipeName.text); __instance.m_upgradeItemName.text = ItemNames.Decorate(item, __instance.m_upgradeItemName.text); } } } } [BepInPlugin("laugh.valheim.rarity", "Valheim Rarity", "4.4.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string Id = "laugh.valheim.rarity"; internal const string RarityKey = "laugh.valheim.rarity.tier"; internal const string ElementKey = "laugh.valheim.rarity.element"; internal const string UpgradedKey = "laugh.valheim.rarity.stationUpgrade"; internal static readonly string[] Names = new string[6] { "Uncommon", "Common", "Rare", "Epic", "Legendary", "Mythic" }; internal static readonly string[] Colors = new string[6] { "#43C86B", "#E0E0E0", "#409EFF", "#B266FF", "#FFAA33", "#FF4568" }; internal static readonly ConfigEntry<float>[] Multipliers = new ConfigEntry<float>[6]; internal static ConfigEntry<float> ElementFraction; private Harmony harmony; internal static void InitializeConfig(ConfigFile config) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown for (int i = 0; i < 6; i++) { Multipliers[i] = ServerConfiguration.Bind(config, "Stats", Names[i], (float)i + 2f, new ConfigDescription("Legacy tier multiplier; initial default for new per-stat settings and version 1 migration.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>())); } ElementFraction = ServerConfiguration.Bind(config, "Effects", "ElementalDamageFraction", 0.25f, new ConfigDescription("Extra elemental damage as a fraction of boosted combat damage.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); Settings.Initialize(config); } private void Awake() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown InitializeConfig(((BaseUnityPlugin)this).Config); ServerConfiguration.Start(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); PrefabManager.OnVanillaPrefabsAvailable += Station.Register; harmony = new Harmony("laugh.valheim.rarity"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Valheim Rarity loaded."); } private void Update() { ServerConfiguration.Tick(); } private void OnDestroy() { ServerConfiguration.Stop(); PrefabManager.OnVanillaPrefabsAvailable -= Station.Register; Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } internal static bool Eligible(ItemData item) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected I4, but got Unknown if (item?.m_shared == null) { return false; } string prefab = Settings.Prefab(item); if (Settings.Listed(Settings.ExcludedItems, prefab)) { return false; } if (Settings.Listed(Settings.ExtraEquipment, prefab) || Settings.Listed(Settings.ExtraTools, prefab)) { return true; } ItemType itemType = item.m_shared.m_itemType; switch (itemType - 3) { case 0: case 1: case 2: case 3: case 4: case 8: case 9: case 11: case 12: case 14: case 16: case 19: return true; default: return false; } } internal static int Tier(ItemData item) { if (!Eligible(item) || item.m_customData == null || !item.m_customData.TryGetValue("laugh.valheim.rarity.stationUpgrade", out var value) || value != "1") { return -1; } if (!item.m_customData.TryGetValue("laugh.valheim.rarity.tier", out var value2) || !int.TryParse(value2, out var result) || result < 0 || result >= 6) { return -1; } return result; } internal static bool IsTool(ItemData item) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 if (item?.m_shared != null) { if ((int)item.m_shared.m_itemType != 19 && (int)item.m_shared.m_itemType != 15 && !(item.m_shared.m_damages.m_chop > 0f) && !(item.m_shared.m_damages.m_pickaxe > 0f)) { return Settings.Listed(Settings.ExtraTools, Settings.Prefab(item)); } return true; } return false; } internal static void ApplyUpgrade(ItemData item, int tier, string element) { if (!Eligible(item) || tier != Tier(item) + 1 || tier < 0 || tier > 5) { throw new InvalidOperationException("Invalid rarity upgrade."); } float maxDurability = item.GetMaxDurability(); if (item.m_customData == null) { item.m_customData = new Dictionary<string, string>(); } item.m_customData["laugh.valheim.rarity.stationUpgrade"] = "1"; item.m_customData["laugh.valheim.rarity.tier"] = tier.ToString(); item.m_customData.Remove("laugh.valheim.rarity.element"); if (tier >= 4 && Settings.CanEnchant(item)) { switch (element) { case "Fire": case "Lightning": case "Poison": item.m_customData["laugh.valheim.rarity.element"] = element; break; } } if (maxDurability > 0f) { item.m_durability *= item.GetMaxDurability() / maxDurability; } } internal static float Multiplier(ItemData item) { int num = Tier(item); if (num >= 0) { return Multipliers[num].Value; } return 1f; } internal static string Element(ItemData item) { if (Tier(item) < 4 || !Settings.CanEnchant(item) || !item.m_customData.TryGetValue("laugh.valheim.rarity.element", out var value)) { return ""; } return value; } internal static string Label(ItemData item) { int num = Tier(item); if (num >= 0) { return "<color=" + Settings.RarityColor(num) + ">" + Settings.RarityName(num) + "</color>"; } return ""; } } [HarmonyPatch(typeof(ItemDrop), "GetHoverName")] internal static class HoverName { private static void Postfix(ItemDrop __instance, ref string __result) { __result = ItemNames.Decorate(__instance.m_itemData, Localization.instance.Localize(__result)); } } [HarmonyPatch] internal static class Stats { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(ItemData), "GetArmor", new Type[2] { typeof(int), typeof(float) }, (Type[])null); yield return AccessTools.Method(typeof(ItemData), "GetMaxDurability", new Type[1] { typeof(int) }, (Type[])null); yield return AccessTools.Method(typeof(ItemData), "GetBaseBlockPower", new Type[1] { typeof(int) }, (Type[])null); } [HarmonyPriority(0)] private static void Postfix(ItemData __instance, MethodBase __originalMethod, ref float __result) { string stat = ((__originalMethod.Name == "GetArmor") ? "Armor" : ((__originalMethod.Name == "GetMaxDurability") ? "Durability" : "Block")); __result *= Settings.Stat(__instance, stat); } } [HarmonyPatch(typeof(ItemData), "GetDamage", new Type[] { typeof(int), typeof(float) })] internal static class Damage { [HarmonyPriority(0)] private static void Postfix(ItemData __instance, ref DamageTypes __result) { ((DamageTypes)(ref __result)).Modify(Settings.Stat(__instance, "Damage")); float num = (((DamageTypes)(ref __result)).GetTotalPhysicalDamage() + ((DamageTypes)(ref __result)).GetTotalElementalDamage() + __result.m_damage) * Plugin.ElementFraction.Value; switch (Plugin.Element(__instance)) { case "Fire": __result.m_fire += num; break; case "Lightning": __result.m_lightning += num; break; case "Poison": __result.m_poison += num; break; } } } [HarmonyPatch(typeof(Character), "GetDamageModifiers")] internal static class ArmorEffects { private static void Postfix(Character __instance, ref DamageModifiers __result) { //IL_0070: 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_0081: 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_008b: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val == null) { return; } foreach (ItemData equippedItem in ((Humanoid)val).GetInventory().GetEquippedItems()) { if (Settings.IsArmor(equippedItem)) { switch (Plugin.Element(equippedItem)) { case "Fire": ((DamageModifiers)(ref __result)).Apply(new List<DamageModPair> { new DamageModPair { m_type = (DamageType)32, m_modifier = Settings.ResistanceValue } }); break; case "Lightning": ((DamageModifiers)(ref __result)).Apply(new List<DamageModPair> { new DamageModPair { m_type = (DamageType)128, m_modifier = Settings.ResistanceValue } }); break; case "Poison": ((DamageModifiers)(ref __result)).Apply(new List<DamageModPair> { new DamageModPair { m_type = (DamageType)256, m_modifier = Settings.ResistanceValue } }); break; } } } } } [HarmonyPatch] internal static class Tooltip { private static MethodBase TargetMethod() { return typeof(ItemData).GetMethods().Single((MethodInfo m) => m.Name == "GetTooltip" && m.IsStatic && m.GetParameters().Length == 6); } private static void Postfix(object[] __args, ref string __result) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown ItemData item = (ItemData)__args[0]; if (Plugin.Tier(item) >= 0) { string text = Plugin.Element(item); __result = Plugin.Label(item) + string.Format(" · damage ×{0:0.##}, armor ×{1:0.##}, durability ×{2:0.##}, block ×{3:0.##}\n", Settings.Stat(item, "Damage"), Settings.Stat(item, "Armor"), Settings.Stat(item, "Durability"), Settings.Stat(item, "Block")) + ((text == "") ? "" : (text + " enchantment (damage on weapons; resistance on armor/shields)\n")) + __result; } } } internal static class ResourceCosts { internal sealed class Material { internal readonly string Name; internal readonly int Amount; internal readonly string Prefab; internal Material(string name, int amount) : this(name, amount, "") { } internal Material(string name, int amount, string prefab) { Name = name; Amount = amount; Prefab = prefab; } } internal sealed class Plan { internal List<Material> Materials = new List<Material>(); internal int AlternativeCount; internal string Error = ""; internal bool Valid { get { if (Error == "") { return Materials.Count > 0; } return false; } } } internal sealed class Payment { internal ItemData Item; internal int Amount; } internal static Plan Get(ItemData item, int option, bool allowOverrides = true) { if (item?.m_shared == null || !Object.op_Implicit((Object)(object)ObjectDB.instance)) { return new Plan { Error = "No crafting recipe exists for this item." }; } float factor = (Settings.ResourceMultiplier?.Value ?? 3f) * (Settings.Cost[Math.Min(5, Plugin.Tier(item) + 1)]?.Value ?? 1f); string prefab = Settings.Prefab(item); string text = (Settings.RecipeOverrides?.Value ?? "").Split(new char[1] { ';' }).FirstOrDefault((string entry) => entry.Split(new char[1] { '=' })[0].Trim() == prefab && prefab != ""); if (allowOverrides && text != null) { try { List<Material> list = new List<Material>(); foreach (KeyValuePair<string, int> item2 in Settings.ParseAmounts(text.Substring(text.IndexOf('=') + 1))) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item2.Key); ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); if (!Object.op_Implicit((Object)(object)val)) { return new Plan { Error = "Unknown override resource: " + item2.Key }; } list.Add(new Material(val.m_itemData.m_shared.m_name, item2.Value, item2.Key)); } return BuildScaled(list, alternatives: false, 0, factor); } catch (Exception ex) when (ex is FormatException || ex is OverflowException || ex is ArgumentException) { return new Plan { Error = "Invalid configured base recipe override." }; } } List<Recipe> source = ObjectDB.instance.m_recipes.Where((Recipe r) => Object.op_Implicit((Object)(object)r) && r.m_enabled && !r.m_noCraftOnlyUpgrade && Object.op_Implicit((Object)(object)r.m_item)).ToList(); Recipe val2 = ((IEnumerable<Recipe>)source).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => ((Component)r.m_item).gameObject == item.m_dropPrefab)) ?? ((IEnumerable<Recipe>)source).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => r.m_item.m_itemData.m_shared == item.m_shared)); if (!Object.op_Implicit((Object)(object)val2)) { List<Recipe> source2 = source.Where((Recipe r) => r.m_item.m_itemData.m_shared.m_name == item.m_shared.m_name).ToList(); if (source2.Select((Recipe r) => r.m_item).Distinct().Count() > 1) { return new Plan { Error = "Ambiguous modded recipe; configure a base recipe override." }; } val2 = source2.FirstOrDefault(); } if (!Object.op_Implicit((Object)(object)val2) || val2.m_resources == null) { return new Plan { Error = "No crafting recipe exists for this item." }; } List<Material> list2 = new List<Material>(); Requirement[] resources = val2.m_resources; foreach (Requirement val3 in resources) { if (val3 == null) { continue; } int amount = val3.GetAmount(1); if (amount > 0) { if (!Object.op_Implicit((Object)(object)val3.m_resItem) || val3.m_resItem.m_itemData?.m_shared == null) { return new Plan { Error = "A crafting resource is missing; upgrade unavailable." }; } list2.Add(new Material(val3.m_resItem.m_itemData.m_shared.m_name, amount, ((Object)val3.m_resItem).name)); } } return BuildScaled(list2, val2.m_requireOnlyOneIngredient, option, factor); } internal static Plan Build(List<Material> baseMaterials, bool alternatives, int option) { return BuildScaled(baseMaterials, alternatives, option, Settings.ResourceMultiplier?.Value ?? 3f); } internal static Plan BuildScaled(List<Material> baseMaterials, bool alternatives, int option, float factor) { Plan plan = new Plan(); if (float.IsNaN(factor) || float.IsInfinity(factor) || factor <= 0f) { plan.Error = "Invalid resource cost multiplier."; return plan; } List<Material> list = baseMaterials.Where((Material m) => m.Amount > 0).ToList(); if (list.Count == 0) { plan.Error = "This item has no base crafting resource cost."; return plan; } if (list.Any((Material m) => string.IsNullOrEmpty(m.Name))) { plan.Error = "Invalid crafting resource."; return plan; } plan.AlternativeCount = (alternatives ? list.Count : 0); if (alternatives) { int index = (option % list.Count + list.Count) % list.Count; list = new List<Material> { list[index] }; } checked { try { foreach (IGrouping<string, Material> item in list.GroupBy<Material, string>((Material m) => m.Name + "\0" + m.Prefab, StringComparer.Ordinal)) { int num = 0; foreach (Material item2 in item) { num += item2.Amount; } int amount = (int)Math.Ceiling((double)num * (double)factor); plan.Materials.Add(new Material(item.First().Name, amount, item.First().Prefab)); } } catch (OverflowException) { plan.Materials.Clear(); plan.Error = "Crafting resource cost is too large."; } return plan; } } internal static long Owned(IEnumerable<ItemData> items, ItemData selected, string name) { return items.Where((ItemData i) => i != selected && i.m_shared?.m_name == name).Sum((Func<ItemData, long>)((ItemData i) => i.m_stack)); } internal static long OwnedMaterial(IEnumerable<ItemData> items, ItemData selected, Material material) { return items.Where((ItemData i) => i != selected && Matches(i, material)).Sum((Func<ItemData, long>)((ItemData i) => i.m_stack)); } private static bool Matches(ItemData item, Material material) { if (item.m_shared?.m_name == material.Name) { if (!(material.Prefab == "")) { return Settings.Prefab(item) == material.Prefab; } return true; } return false; } internal static bool Allocate(List<ItemData> items, ItemData selected, Plan plan, out List<Payment> payments) { payments = new List<Payment>(); if (!plan.Valid) { return false; } foreach (Material material in plan.Materials) { int num = material.Amount; foreach (ItemData item in items) { if (item != selected && Matches(item, material) && item.m_stack > 0) { int num2 = Math.Min(num, item.m_stack); payments.Add(new Payment { Item = item, Amount = num2 }); num -= num2; if (num == 0) { break; } } } if (num > 0) { payments.Clear(); return false; } } return true; } } internal static class ServerConfiguration { private sealed class ConfigCommand : ConsoleCommand { public override string Name => "rarity_config"; public override string Help => "Admin config: rarity_config Section Key Value (use underscores for section spaces); rarity_config list; rarity_config reload (server file)."; public override void Run(string[] args, Terminal context) { if (args.Length == 1 && args[0] == "list") { foreach (ConfigDefinition key in config.Keys) { context.AddString(key.Section.Replace(' ', '_') + " " + key.Key + " = " + TomlTypeConverter.ConvertToString(config[key].BoxedValue, config[key].SettingType)); } return; } bool flag = !Object.op_Implicit((Object)(object)ZNet.instance) || ZNet.instance.IsServer(); if (!CanEdit(flag, SynchronizationManager.Instance.PlayerIsAdmin)) { context.AddString("Only server admins can change rarity configuration."); return; } if (args.Length == 1 && args[0] == "reload") { if (!flag) { context.AddString("Edit values with rarity_config Section Key Value; reload reads the host's local file only."); return; } Reload(); context.AddString("Rarity configuration reloaded."); return; } if (args.Length < 3) { context.AddString(((ConsoleCommand)this).Help); return; } ConfigDefinition val = ((IEnumerable<ConfigDefinition>)config.Keys).FirstOrDefault((Func<ConfigDefinition, bool>)((ConfigDefinition k) => k.Section.Replace(' ', '_').Equals(args[0], StringComparison.OrdinalIgnoreCase) && k.Key.Equals(args[1], StringComparison.OrdinalIgnoreCase))); if (val == (ConfigDefinition)null) { context.AddString("Unknown setting. Use rarity_config list."); return; } ConfigEntryBase val2 = config[val]; if (!TryValue(val2, string.Join(" ", args.Skip(2)), out var value, out var error)) { context.AddString("Invalid value: " + error); return; } val2.BoxedValue = value; config.Save(); Reload(); context.AddString("Updated " + val.Section + "/" + val.Key + (flag ? " for the server." : "; sent to the server for admin authorization.")); } } private static ConfigFile config; private static ManualLogSource log; private static bool refreshPending; private static float nextPoll; private static DateTime loadedWrite; private static DateTime observedWrite; private static long loadedLength; private static long observedLength; internal static ConfigEntry<T> Bind<T>(ConfigFile file, string section, string key, T value, string description) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown return Bind(file, section, key, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>())); } internal static ConfigEntry<T> Bind<T>(ConfigFile file, string section, string key, T value, ConfigDescription description) { //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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown object[] array = description.Tags.Concat(new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } }).ToArray(); return file.Bind<T>(section, key, value, new ConfigDescription(description.Description + " [Synced with Server; admin only]", description.AcceptableValues, array)); } internal static void Start(ConfigFile file, ManualLogSource logger) { config = file; log = logger; config.SettingChanged += SettingChanged; SynchronizationManager.OnConfigurationSynchronized += Synchronized; ReadStamp(out loadedWrite, out loadedLength); observedWrite = loadedWrite; observedLength = loadedLength; refreshPending = true; CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ConfigCommand()); } internal static void Stop() { if (config != null) { config.SettingChanged -= SettingChanged; } SynchronizationManager.OnConfigurationSynchronized -= Synchronized; config = null; } private static void SettingChanged(object sender, SettingChangedEventArgs e) { refreshPending = true; } private static void Synchronized(object sender, ConfigurationSynchronizationEventArgs e) { if (e.UpdatedPluginGUIDs.Contains("laugh.valheim.rarity")) { refreshPending = true; } } internal static bool CanEdit(bool server, bool admin) { return server || admin; } internal static bool TryValue(ConfigEntryBase entry, string text, out object value, out string error) { value = null; error = ""; try { value = TomlTypeConverter.ConvertToValue(text, entry.SettingType); if (value is float f && (float.IsNaN(f) || float.IsInfinity(f))) { throw new FormatException("A finite number is required."); } if (entry.Description.AcceptableValues != null && !entry.Description.AcceptableValues.IsValid(value)) { throw new FormatException("Value is outside the allowed range or choices."); } if (entry.Definition.Section == "Station" && entry.Definition.Key == "BuildResources") { Dictionary<string, int> dictionary = Settings.ParseAmounts((string)value); if (Object.op_Implicit((Object)(object)ObjectDB.instance)) { foreach (KeyValuePair<string, int> item in dictionary) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item.Key); if (!Object.op_Implicit((Object)(object)((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null))) { throw new FormatException("Unknown construction resource: " + item.Key); } } } } return true; } catch (Exception ex) when (ex is FormatException || ex is OverflowException || ex is ArgumentException) { error = ex.Message; value = null; return false; } } internal static void Tick() { if (config == null) { return; } if (Time.unscaledTime >= nextPoll) { nextPoll = Time.unscaledTime + 0.5f; if (!Object.op_Implicit((Object)(object)ZNet.instance) || ZNet.instance.IsServer()) { ReadStamp(out var write, out var length); if (write != observedWrite || length != observedLength) { observedWrite = write; observedLength = length; } else if (write != loadedWrite || length != loadedLength) { Reload(); } } } if (!refreshPending || !Object.op_Implicit((Object)(object)ObjectDB.instance)) { return; } try { Station.ApplySettings(); Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer)) { bool flag = false; foreach (ItemData item in from i in ((Humanoid)localPlayer).GetInventory().GetAllItems() where Plugin.Tier(i) >= 0 select i) { float num = Mathf.Min(item.m_durability, item.GetMaxDurability()); if (num != item.m_durability) { item.m_durability = num; flag = true; } } if (flag) { AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null).Invoke(((Humanoid)localPlayer).GetInventory(), new object[2] { true, false }); } AccessTools.Method(typeof(Humanoid), "SetupEquipment", (Type[])null, (Type[])null).Invoke(localPlayer, null); AccessTools.Method(typeof(Player), "UpdateKnownRecipesList", (Type[])null, (Type[])null).Invoke(localPlayer, null); AccessTools.Method(typeof(Player), "UpdateAvailablePiecesList", (Type[])null, (Type[])null).Invoke(localPlayer, null); if (Object.op_Implicit((Object)(object)InventoryGui.instance)) { ((Component)InventoryGui.instance).GetComponent<StationWindow>()?.ConfigurationChanged(); } } } catch (Exception ex) { log.LogError((object)("Could not apply live station configuration: " + ex.Message)); } refreshPending = false; } private static void ReadStamp(out DateTime write, out long length) { FileInfo fileInfo = new FileInfo(config.ConfigFilePath); write = (fileInfo.Exists ? fileInfo.LastWriteTimeUtc : DateTime.MinValue); length = (fileInfo.Exists ? fileInfo.Length : 0); } private static void Reload() { bool saveOnConfigSet = config.SaveOnConfigSet; try { config.SaveOnConfigSet = false; config.Reload(); refreshPending = true; log.LogInfo((object)"Reloaded Valheim Rarity configuration; Jotunn synchronizes it with connected players."); } catch (IOException ex) { log.LogWarning((object)("Could not reload configuration: " + ex.Message)); } finally { config.SaveOnConfigSet = saveOnConfigSet; ReadStamp(out loadedWrite, out loadedLength); observedWrite = loadedWrite; observedLength = loadedLength; } } } internal static class Settings { internal static readonly ConfigEntry<float>[] Armor = new ConfigEntry<float>[6]; internal static readonly ConfigEntry<float>[] Damage = new ConfigEntry<float>[6]; internal static readonly ConfigEntry<float>[] Durability = new ConfigEntry<float>[6]; internal static readonly ConfigEntry<float>[] Block = new ConfigEntry<float>[6]; internal static readonly ConfigEntry<float>[] Cost = new ConfigEntry<float>[6]; internal static readonly ConfigEntry<string>[] Names = new ConfigEntry<string>[6]; internal static readonly ConfigEntry<string>[] Colors = new ConfigEntry<string>[6]; internal static ConfigEntry<float> ResourceMultiplier; internal static ConfigEntry<float> WindowWidth; internal static ConfigEntry<float> WindowHeight; internal static ConfigEntry<float> UseDistance; internal static ConfigEntry<bool> PrefixNames; internal static ConfigEntry<bool> RequireUnlock; internal static ConfigEntry<bool> RequireRoof; internal static ConfigEntry<bool> WeaponElements; internal static ConfigEntry<bool> ArmorElements; internal static ConfigEntry<bool> MatchCraftingPanel; internal static ConfigEntry<string> DefaultView; internal static ConfigEntry<string> UnlockItem; internal static ConfigEntry<string> BuildResources; internal static ConfigEntry<string> ExcludedItems; internal static ConfigEntry<string> ExtraEquipment; internal static ConfigEntry<string> ExtraTools; internal static ConfigEntry<string> RecipeOverrides; internal static ConfigEntry<string> Background; internal static ConfigEntry<string> Border; internal static ConfigEntry<string> Resistance; internal static DamageModifier ResistanceValue { get { //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!Enum.TryParse<DamageModifier>(Resistance?.Value ?? "Resistant", out DamageModifier result)) { return (DamageModifier)1; } return result; } } internal static void Initialize(ConfigFile config) { //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Expected O, but got Unknown //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Expected O, but got Unknown for (int i = 0; i < 6; i++) { string section = "Rarity " + Plugin.Names[i]; float value = Plugin.Multipliers[i]?.Value ?? ((float)(i + 2)); Armor[i] = Float(config, section, "ArmorMultiplier", value, 0f, 100f); Damage[i] = Float(config, section, "DamageMultiplier", value, 0f, 100f); Durability[i] = Float(config, section, "DurabilityMultiplier", value, 0.01f, 100f); Block[i] = Float(config, section, "BlockMultiplier", value, 0f, 100f); Cost[i] = Float(config, section, "ResourceCostScale", 1f, 0.01f, 100f); Names[i] = ServerConfiguration.Bind(config, section, "DisplayName", Plugin.Names[i], "Rarity prefix shown in item names."); Colors[i] = ServerConfiguration.Bind(config, section, "Color", Plugin.Colors[i], "HTML color #RRGGBB or #RRGGBBAA."); } ResourceMultiplier = Float(config, "Resources", "CraftingCostMultiplier", 3f, 0.01f, 100f); RecipeOverrides = ServerConfiguration.Bind(config, "Compatibility", "BaseRecipeOverrides", "", "Base cost overrides for items with usable crafting recipes; recipe-less items remain excluded. Format: ItemPrefab=Wood:10,Iron:4;OtherPrefab=Stone:5. Resource costs are multiplied as usual. Changes apply live and synchronize with the server."); ExcludedItems = ServerConfiguration.Bind(config, "Compatibility", "ExcludedPrefabs", "", "Comma-separated equipment prefab names to exclude from this mod."); ExtraEquipment = ServerConfiguration.Bind(config, "Compatibility", "ExtraEquipmentPrefabs", "", "Comma-separated custom equipment prefab names to include even if they use a nonstandard ItemType."); ExtraTools = ServerConfiguration.Bind(config, "Compatibility", "ExtraToolPrefabs", "", "Comma-separated modded tool prefab names. These never gain mod elemental effects."); PrefixNames = ServerConfiguration.Bind(config, "Display", "PrefixItemNames", value: true, "Prefix upgraded equipment names with rarity and color the full name."); RequireUnlock = ServerConfiguration.Bind(config, "Station", "RequireMaterialDiscovery", value: true, "Require the unlock material to have been discovered before building or using the station."); UnlockItem = ServerConfiguration.Bind(config, "Station", "UnlockMaterialPrefab", "Iron", "Material prefab that unlocks this station permanently per character."); BuildResources = ServerConfiguration.Bind(config, "Station", "BuildResources", "Wood:10,Stone:4,Coal:4,Iron:6", "Construction resources as Prefab:amount separated by commas. Changes apply live and synchronize with the server."); if (BuildResources.Value == "Wood:10,Stone:4,Coal:4,Copper:6") { BuildResources.Value = "Wood:10,Stone:4,Coal:4,Iron:6"; } RequireRoof = ServerConfiguration.Bind(config, "Station", "RequireRoof", value: true, "Require shelter to use the station. Changes apply live and synchronize with the server."); UseDistance = Float(config, "Station", "UseDistance", 5f, 1f, 20f); MatchCraftingPanel = ServerConfiguration.Bind(config, "UI", "MatchCraftingPanel", value: true, "Use the character crafting panel's current position and size for the station's own window. When false, use the centered custom-size layout."); DefaultView = ServerConfiguration.Bind(config, "UI", "DefaultView", "Selector", new ConfigDescription("Initial window view on each station opening. Switch views using the button in the window.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "Selector", "Traditional" }), Array.Empty<object>())); WindowWidth = Float(config, "UI", "WindowWidth", 700f, 400f, 1400f); WindowHeight = Float(config, "UI", "WindowHeight", 850f, 500f, 1500f); Background = ServerConfiguration.Bind(config, "UI", "BackgroundColor", "#17130FFA", "Station window background color."); Border = ServerConfiguration.Bind(config, "UI", "BorderColor", "#C69855", "Station window frame color."); WeaponElements = ServerConfiguration.Bind(config, "Effects", "EnableWeaponElements", value: true, "Enable legendary/mythic weapon elemental damage. Tools remain excluded."); ArmorElements = ServerConfiguration.Bind(config, "Effects", "EnableArmorElements", value: true, "Enable legendary/mythic armor and shield elemental resistance."); Resistance = ServerConfiguration.Bind(config, "Effects", "ArmorResistance", "Resistant", new ConfigDescription("Resistance granted by elemental armor/shields.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "Resistant", "VeryResistant", "Immune" }), Array.Empty<object>())); } private static ConfigEntry<float> Float(ConfigFile config, string section, string key, float value, float min, float max) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown return ServerConfiguration.Bind(config, section, key, value, new ConfigDescription(key + ". Applied to upgraded equipment only where relevant.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>())); } internal static string RarityName(int tier) { return (Names[tier]?.Value ?? Plugin.Names[tier]).Replace("<", "").Replace(">", "").Replace("\n", " ") .Replace("\r", " "); } internal static string RarityColor(int tier) { string text = Colors[tier]?.Value ?? Plugin.Colors[tier]; if (text == null || (text.Length != 7 && text.Length != 9) || text[0] != '#' || !text.Skip(1).All(Uri.IsHexDigit)) { return Plugin.Colors[tier]; } return text; } internal static bool Listed(ConfigEntry<string> setting, string prefab) { if (prefab != "") { return (setting?.Value ?? "").Split(new char[1] { ',' }).Any((string s) => s.Trim().Equals(prefab, StringComparison.Ordinal)); } return false; } internal static string Prefab(ItemData item) { if (!Object.op_Implicit((Object)(object)item?.m_dropPrefab)) { return ""; } return ((Object)item.m_dropPrefab).name; } internal static float Stat(ItemData item, string stat) { int num = Plugin.Tier(item); if (num < 0) { return 1f; } return ((ConfigEntry<float>)((object[])(stat switch { "Durability" => Durability, "Damage" => Damage, "Armor" => Armor, _ => Block, }))[num])?.Value ?? Plugin.Multipliers[num].Value; } internal static bool IsArmor(ItemData item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 ItemType itemType = item.m_shared.m_itemType; if ((int)itemType != 5 && (int)itemType != 6 && (int)itemType != 7 && (int)itemType != 11 && (int)itemType != 12 && (int)itemType != 17) { return item.m_shared.m_armor > 0f; } return true; } internal static bool CanEnchant(ItemData item) { if (!Plugin.IsTool(item)) { if (!IsArmor(item)) { return WeaponElements?.Value ?? true; } return ArmorElements?.Value ?? true; } return false; } internal static Dictionary<string, int> ParseAmounts(string text) { Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal); string[] array = text.Split(new char[1] { ',' }); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Trim().Split(new char[1] { ':' }); if (array2.Length != 2 || string.IsNullOrWhiteSpace(array2[0]) || !int.TryParse(array2[1].Trim(), out var result) || result <= 0) { throw new FormatException("Expected ResourcePrefab:positiveAmount, separated by commas."); } string key = array2[0].Trim(); dictionary[key] = checked((dictionary.TryGetValue(key, out var value) ? value : 0) + result); } return dictionary; } } internal static class Station { internal const string PrefabName = "laugh_rarity_upgrade_forge"; internal const string DisplayName = "Rarity Forge"; internal static bool Active { get { if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return IsRarityStation(Player.m_localPlayer.GetCurrentCraftingStation()); } return false; } } internal static void Register() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown PieceConfig val = new PieceConfig { Name = "Rarity Forge", Description = "Upgrade tools, weapons and armor through six rarities. Costs 3x the original crafting resources; quality is unchanged.", PieceTable = "Hammer", Category = "Crafting", CraftingStation = "piece_workbench", Requirements = ((IEnumerable<KeyValuePair<string, int>>)Settings.ParseAmounts(Settings.BuildResources.Value)).Select((Func<KeyValuePair<string, int>, RequirementConfig>)((KeyValuePair<string, int> r) => new RequirementConfig(r.Key, r.Value, 0, true))).ToArray() }; CustomPiece val2 = new CustomPiece("laugh_rarity_upgrade_forge", "forge", val); StationModel.Apply(val2.PiecePrefab); CraftingStation component = val2.PiecePrefab.GetComponent<CraftingStation>(); component.m_name = "Rarity Forge"; component.m_showBasicRecipies = false; component.m_canRepair = false; component.m_hasCraftTab = true; component.m_upgrader = false; component.m_useDistance = Settings.UseDistance.Value; component.m_craftRequireRoof = Settings.RequireRoof.Value; if (!PieceManager.Instance.AddPiece(val2)) { throw new InvalidOperationException("Could not register the Rarity Forge."); } PrefabManager.OnVanillaPrefabsAvailable -= Register; } internal static bool IsRarityStation(CraftingStation station) { if (Object.op_Implicit((Object)(object)station) && station.m_name == "Rarity Forge") { return ((Object)((Component)station).gameObject).name.StartsWith("laugh_rarity_upgrade_forge", StringComparison.Ordinal); } return false; } internal static void ApplySettings() { Requirement[] resources = ((IEnumerable<KeyValuePair<string, int>>)Settings.ParseAmounts(Settings.BuildResources.Value)).Select((Func<KeyValuePair<string, int>, Requirement>)delegate(KeyValuePair<string, int> resource) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(resource.Key); ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("Unknown construction resource: " + resource.Key); } return new Requirement { m_resItem = val, m_amount = resource.Value, m_recover = true }; }).ToArray(); foreach (CraftingStation item in Resources.FindObjectsOfTypeAll<CraftingStation>().Where(IsRarityStation)) { item.m_useDistance = Settings.UseDistance.Value; item.m_craftRequireRoof = Settings.RequireRoof.Value; ((Component)item).GetComponent<Piece>().m_resources = resources; } } internal static bool Unlocked(Player player) { ConfigEntry<bool> requireUnlock = Settings.RequireUnlock; if (requireUnlock != null && !requireUnlock.Value) { return true; } if (!Object.op_Implicit((Object)(object)ObjectDB.instance)) { return false; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(Settings.UnlockItem?.Value ?? "Iron"); ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); if (Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)val)) { return player.IsMaterialKnown(val.m_itemData.m_shared.m_name); } return false; } internal static bool Eligible(ItemData item) { if (Plugin.Eligible(item) && item.m_quality == 1) { return ResourceCosts.Get(item, 0, allowOverrides: false).Valid; } return false; } internal static bool Upgrade(Player player, ItemData item, string element, int materialOption, out string error) { //IL_0046: 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_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0275: 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_0289: Unknown result type (might be due to invalid IL or missing references) error = ""; if (!Object.op_Implicit((Object)(object)player) || !IsRarityStation(player.GetCurrentCraftingStation())) { error = "Use the Rarity Forge to upgrade equipment."; return false; } if (!Unlocked(player)) { error = "Discover the station's unlock material first."; return false; } CraftingStation currentCraftingStation = player.GetCurrentCraftingStation(); if (Vector3.Distance(((Component)player).transform.position, ((Component)currentCraftingStation).transform.position) > currentCraftingStation.m_useDistance || !currentCraftingStation.CheckUsable(player, false)) { error = "The station must be usable and within reach."; return false; } Inventory inventory = ((Humanoid)player).GetInventory(); if (!Plugin.Eligible(item) || !inventory.GetAllItems().Contains(item)) { error = "Select equipment in your inventory."; return false; } if (item.m_quality != 1) { error = "Equipment upgraded at a vanilla crafting station cannot receive rarity upgrades."; return false; } ResourceCosts.Plan plan = ResourceCosts.Get(item, 0, allowOverrides: false); if (!plan.Valid) { error = plan.Error; return false; } int num = Plugin.Tier(item) + 1; if (num > 5) { error = "This item is already Mythic."; return false; } if (num >= 4 && Settings.CanEnchant(item) && element != "Fire" && element != "Lightning" && element != "Poison") { error = "Choose Fire, Lightning or Poison."; return false; } ResourceCosts.Plan plan2 = ResourceCosts.Get(item, materialOption); if (!plan2.Valid) { error = plan2.Error; return false; } if (!ResourceCosts.Allocate(inventory.GetAllItems(), item, plan2, out var payments)) { error = "Not enough crafting resources."; return false; } ItemData val = Preview(item, element); foreach (ResourceCosts.Payment item3 in payments) { ItemData item2 = item3.Item; item2.m_stack -= item3.Amount; if (item3.Item.m_stack == 0) { if (item3.Item.m_equipped) { ((Humanoid)player).UnequipItem(item3.Item, false); } inventory.GetAllItems().Remove(item3.Item); } } item.m_customData = val.m_customData; item.m_durability = val.m_durability; AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null).Invoke(inventory, new object[2] { true, false }); if (item.m_equipped) { AccessTools.Method(typeof(Humanoid), "SetupEquipment", (Type[])null, (Type[])null).Invoke(player, null); } currentCraftingStation.m_craftItemDoneEffects.Create(((Component)currentCraftingStation).transform.position, ((Component)currentCraftingStation).transform.rotation, (Transform)null, 1f, -1, default(ZDOID)); return true; } internal static ItemData Preview(ItemData item, string element) { ItemData obj = item.Clone(); Plugin.ApplyUpgrade(obj, Plugin.Tier(item) + 1, element); return obj; } } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] internal static class StationDiscovery { private static bool Prefix(Player __instance, Piece __0, RequirementMode __1, ref bool __result) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 if (!Object.op_Implicit((Object)(object)__0) || !((Object)__0).name.StartsWith("laugh_rarity_upgrade_forge", StringComparison.Ordinal)) { return true; } bool flag = Station.Unlocked(__instance); if ((int)__1 == 1 || !flag) { __result = flag; return false; } return true; } } [HarmonyPatch(typeof(CraftingStation), "Interact")] internal static class StationAccess { private static bool Prefix(CraftingStation __instance, Humanoid __0, ref bool __result) { if (Station.IsRarityStation(__instance)) { Player val = (Player)(object)((__0 is Player) ? __0 : null); if (val != null && !Station.Unlocked(val)) { ((Character)val).Message((MessageType)2, "Discover " + (Settings.UnlockItem?.Value ?? "Iron") + " to unlock the Rarity Forge.", 0, (Sprite)null, false); __result = false; return false; } } return true; } } [HarmonyPatch] internal static class LegacyMigration { private static IEnumerable<MethodBase> TargetMethods() { return from m in typeof(Inventory).GetMethods() where m.Name == "AddItem" && m.GetParameters().Any((ParameterInfo p) => p.ParameterType == typeof(ItemData)) select m; } private static void Prefix(object[] __args) { foreach (ItemData item in __args.OfType<ItemData>()) { if (item.m_customData != null && !item.m_customData.ContainsKey("laugh.valheim.rarity.stationUpgrade") && item.m_customData.TryGetValue("laugh.valheim.rarity.tier", out var value)) { if (int.TryParse(value, out var result) && result >= 0 && result < 6) { item.m_durability = Mathf.Min(item.GetMaxDurability(), item.m_durability / Plugin.Multipliers[result].Value); } item.m_customData.Remove("laugh.valheim.rarity.tier"); item.m_customData.Remove("laugh.valheim.rarity.element"); } } } } internal static class StationModel { private sealed class Part { internal string Name; internal int Material; internal Mesh Mesh; } private const string ResourcePrefix = "ValheimRarity.UpgradeStation."; private static Part[] parts; private static Material[] materials; internal static Vector2 StoneUV(Vector2 source) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) return new Vector2((2.5f + 55f * source.x) / 128f, (2.5f + 41f * source.y) / 128f); } internal static void Apply(GameObject prefab) { //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true); if (parts == null) { parts = ReadParts(); } if (materials == null) { materials = ReadMaterials(componentsInChildren); } LODGroup[] componentsInChildren2 = prefab.GetComponentsInChildren<LODGroup>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[i]); } MeshRenderer[] array = componentsInChildren; for (int i = 0; i < array.Length; i++) { ((Renderer)array[i]).enabled = false; } Transform[] array2 = (from t in ((IEnumerable<string>)new string[3] { "New", "Worn", "Broken" }).Select((Func<string, Transform>)prefab.transform.Find) where Object.op_Implicit((Object)(object)t) select t).ToArray(); if (array2.Length == 0) { array2 = (Transform[])(object)new Transform[1] { prefab.transform }; } Transform[] array3 = array2; Part[] array4; for (int i = 0; i < array3.Length; i++) { GameObject val = Child(array3[i], "UpgradeStationModel"); array4 = parts; foreach (Part part in array4) { GameObject obj = Child(val.transform, part.Name); obj.AddComponent<MeshFilter>().sharedMesh = part.Mesh; ((Renderer)obj.AddComponent<MeshRenderer>()).sharedMaterial = materials[part.Material]; } } CraftingStation component = prefab.GetComponent<CraftingStation>(); Collider[] componentsInChildren3 = prefab.GetComponentsInChildren<Collider>(true); foreach (Collider val2 in componentsInChildren3) { if (!val2.isTrigger && !((Object)(object)val2 == (Object)(object)component.m_effectAreaCollider)) { Object.DestroyImmediate((Object)(object)val2); } } GameObject val3 = Child(prefab.transform, "UpgradeStationCollision"); array4 = parts; foreach (Part part2 in array4) { Child(val3.transform, part2.Name).AddComponent<MeshCollider>().sharedMesh = part2.Mesh; } Bounds bounds = parts.First((Part p) => p.Name == "coal").Mesh.bounds; Vector3 center = ((Bounds)(ref bounds)).center; Transform val4 = prefab.transform.Find("_enabled"); if (Object.op_Implicit((Object)(object)val4)) { val4.localPosition += center - new Vector3(0.421f, 0.909336f, 0.016f); } AddEmberFlames(prefab, val4); UpdateBuildIcon(prefab, ((Component)array2[0].Find("UpgradeStationModel")).gameObject); } internal static void PreparePlacementGhost(GameObject ghost) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) Transform val = ghost.transform.Find("UpgradeStationCollision"); if (!Object.op_Implicit((Object)(object)val)) { return; } MeshCollider[] componentsInChildren = ((Component)val).GetComponentsInChildren<MeshCollider>(true); foreach (MeshCollider val2 in componentsInChildren) { if (Object.op_Implicit((Object)(object)val2.sharedMesh) && !Object.op_Implicit((Object)(object)((Component)val2).GetComponent<BoxCollider>())) { BoxCollider obj = ((Component)val2).gameObject.AddComponent<BoxCollider>(); Bounds bounds = val2.sharedMesh.bounds; obj.center = ((Bounds)(ref bounds)).center; bounds = val2.sharedMesh.bounds; obj.size = ((Bounds)(ref bounds)).size; } } } private static void AddEmberFlames(GameObject prefab, Transform enabled) { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0267: 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_0282: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Unknown result type (might be due to invalid IL or missing references) Transform val = (Object.op_Implicit((Object)(object)enabled) ? enabled.Find("flames") : null); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("The forge flame template is missing."); } GameObject val2 = Child(prefab.transform, "UpgradeStationFire"); ParticleSystem[] componentsInChildren; foreach (Part item in parts.Where((Part p) => p.Material == 2)) { GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, val2.transform, false); ((Object)val3).name = "Flames_" + item.Name; Bounds bounds = item.Mesh.bounds; val3.transform.localPosition = new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).center.y + 0.025f, ((Bounds)(ref bounds)).center.z); val3.transform.localScale = Vector3.one * ((item.Name == "coal") ? 0.4f : 0.6f); componentsInChildren = val3.GetComponentsInChildren<ParticleSystem>(true); for (int num = 0; num < componentsInChildren.Length; num++) { MainModule main = componentsInChildren[num].main; ((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0; ((MainModule)(ref main)).loop = true; ((MainModule)(ref main)).playOnAwake = true; } val3.SetActive(true); } Bounds bounds2 = parts.First((Part p) => p.Name == "forgecoal").Mesh.bounds; Transform obj = enabled.Find("smoke"); Transform val4 = enabled.Find("Point light"); if (!Object.op_Implicit((Object)(object)obj) || !Object.op_Implicit((Object)(object)val4)) { throw new InvalidOperationException("The forge smoke/light templates are missing."); } GameObject val5 = Object.Instantiate<GameObject>(((Component)obj).gameObject, val2.transform, false); ((Object)val5).name = "Smoke_forgecoal"; Bounds bounds3 = parts.First((Part p) => p.Name == "forge").Mesh.bounds; val5.transform.localPosition = new Vector3(((Bounds)(ref bounds3)).center.x, ((Bounds)(ref bounds3)).max.y + 0.025f, ((Bounds)(ref bounds3)).center.z); val5.transform.localScale = Vector3.one * 0.6f; componentsInChildren = val5.GetComponentsInChildren<ParticleSystem>(true); for (int num = 0; num < componentsInChildren.Length; num++) { MainModule main2 = componentsInChildren[num].main; ((MainModule)(ref main2)).scalingMode = (ParticleSystemScalingMode)0; ((MainModule)(ref main2)).loop = true; ((MainModule)(ref main2)).playOnAwake = true; } val5.SetActive(true); GameObject inUseObject = prefab.GetComponent<CraftingStation>().m_inUseObject; Transform val6 = (Object.op_Implicit((Object)(object)inUseObject) ? inUseObject.transform : enabled); GameObject obj2 = Object.Instantiate<GameObject>(((Component)val4).gameObject, val6, false); ((Object)obj2).name = "EmberLight_forgecoal"; Vector3 val7 = default(Vector3); ((Vector3)(ref val7))..ctor(((Bounds)(ref bounds2)).center.x, ((Bounds)(ref bounds2)).max.y + 0.15f, ((Bounds)(ref bounds2)).center.z); obj2.transform.localPosition = val6.InverseTransformPoint(prefab.transform.TransformPoint(val7)); obj2.SetActive(true); ((Component)val).gameObject.SetActive(false); } private static void UpdateBuildIcon(GameObject prefab, GameObject visual) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0041: Expected O, but got Unknown if ((int)SystemInfo.graphicsDeviceType != 4) { Sprite val = RenderManager.Instance.Render(new RenderRequest(visual) { Width = 128, Height = 128, Rotation = RenderManager.IsometricRotation, UseCache = false }); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("Could not render the upgrade station build icon."); } prefab.GetComponent<Piece>().m_icon = val; prefab.GetComponent<CraftingStation>().m_icon = val; } } private static GameObject Child(Transform parent, string name) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown GameObject val = new GameObject(name) { layer = ((Component)parent).gameObject.layer }; val.transform.SetParent(parent, false); return val; } private static Stream Resource(string file) { return typeof(StationModel).Assembly.GetManifestResourceStream("ValheimRarity.UpgradeStation." + file) ?? throw new InvalidOperationException("Missing upgrade station asset: " + file); } private static Part[] ReadParts() { //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_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) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: 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_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: 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_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Expected O, but got Unknown using Stream stream = Resource("model.bin"); using BinaryReader binaryReader = new BinaryReader(stream); if (binaryReader.ReadInt32() != 1448235853 || binaryReader.ReadInt32() != 1) { throw new InvalidDataException("Unsupported upgrade station mesh format."); } int num = binaryReader.ReadInt32(); if (num != 11) { throw new InvalidDataException("The upgrade station must contain 11 mesh parts."); } Part[] array = new Part[num]; for (int i = 0; i < num; i++) { int num2 = binaryReader.ReadInt32(); if (num2 < 1 || num2 > 128) { throw new InvalidDataException("Invalid mesh name."); } string text = Encoding.UTF8.GetString(binaryReader.ReadBytes(num2)); int num3 = binaryReader.ReadInt32(); int num4 = binaryReader.ReadInt32(); int num5 = binaryReader.ReadInt32(); if (num3 < 0 || num3 > 3 || num4 < 3 || num4 > 65535 || num5 < 3 || num5 > 100000 || num5 % 3 != 0) { throw new InvalidDataException("Invalid upgrade station mesh."); } Vector3[] array2 = (Vector3[])(object)new Vector3[num4]; Vector3[] array3 = (Vector3[])(object)new Vector3[num4]; Vector2[] array4 = (Vector2[])(object)new Vector2[num4]; for (int j = 0; j < num4; j++) { array2[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); array3[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()); array4[j] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle()); if (num3 == 3) { array4[j] = StoneUV(array4[j]); } } int[] array5 = new int[num5]; for (int k = 0; k < num5; k++) { array5[k] = binaryReader.ReadInt32(); if (array5[k] < 0 || array5[k] >= num4) { throw new InvalidDataException("Invalid mesh triangle."); } } Mesh val = new Mesh { name = "RarityStation_" + text, vertices = array2, normals = array3, uv = array4, triangles = array5 }; val.RecalculateBounds(); val.RecalculateTangents(); array[i] = new Part { Name = text, Material = num3, Mesh = val }; } if (stream.Position != stream.Length) { throw new InvalidDataException("Unexpected trailing mesh data."); } return array; } private static Texture2D Texture(string file, bool linear = false, bool normal = false) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false, linear) { name = "RarityStation_" + file, filterMode = (FilterMode)0, wrapMode = (TextureWrapMode)0 }; using (Stream stream = Resource(file)) { using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); MethodInfo method = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule", throwOnError: true).GetMethod("LoadImage", new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) }); if (method == null || !(bool)method.Invoke(null, new object[3] { val, memoryStream.ToArray(), false })) { throw new InvalidDataException("Cannot decode " + file); } } if (normal) { Color32[] pixels = val.GetPixels32(); for (int i = 0; i < pixels.Length; i++) { pixels[i] = new Color32(byte.MaxValue, pixels[i].g, pixels[i].b, pixels[i].r); } val.SetPixels32(pixels); val.Apply(false, false); } return val; } private static Material[] ReadMaterials(MeshRenderer[] renderers) { //IL_0109: 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_0124: Expected O, but got Unknown //IL_0155: 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_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Unknown result type (might be due to invalid IL or missing references) Material[] source = (from m in renderers.SelectMany((MeshRenderer r) => ((Renderer)r).sharedMaterials) where Object.op_Implicit((Object)(object)m) select m).ToArray(); Material val = ((IEnumerable<Material>)source).FirstOrDefault((Func<Material, bool>)((Material m) => ((Object)m).name.StartsWith("Forge_mat", StringComparison.Ordinal))) ?? source.First((Material m) => m.HasProperty("_MainTex")); Material val2 = ((IEnumerable<Material>)source).FirstOrDefault((Func<Material, bool>)((Material m) => ((Object)m).name.StartsWith("ForgeCoals_mat", StringComparison.Ordinal))) ?? val; string[] array = new string[4] { "forge_wood", "forge_metal", "forge_coals", "station_stone" }; Material[] array2 = (Material[])(object)new Material[4]; for (int num = 0; num < array2.Length; num++) { Material val3 = new Material((num == 2) ? val2 : val) { name = "RarityStation_" + array[num] }; val3.mainTexture = (Texture)(object)Texture(array[num] + "_color.png"); if (val3.HasProperty("_Color")) { val3.SetColor("_Color", Color.white); } if (val3.HasProperty("_BumpMap")) { val3.SetTexture("_BumpMap", (Texture)(object)Texture(array[num] + "_normal.png", linear: true, normal: true)); val3.EnableKeyword("_NORMALMAP"); } if (val3.HasProperty("_BumpScale")) { val3.SetFloat("_BumpScale", 0.45f); } if (val3.HasProperty("_Metallic")) { val3.SetFloat("_Metallic", (num == 1) ? 1f : 0f); } if (val3.HasProperty("_Glossiness")) { val3.SetFloat("_Glossiness", (num == 1) ? 0.55f : 0.1f); } if (num == 1) { Texture2D val4 = Texture("forge_metal_metallic.png", linear: true); Texture2D obj = Texture("forge_metal_roughness.png", linear: true); Color32[] pixels = val4.GetPixels32(); Color32[] pixels2 = obj.GetPixels32(); for (int num2 = 0; num2 < pixels.Length; num2++) { pixels[num2] = new Color32(pixels[num2].r, (byte)0, (byte)0, (byte)(255 - pixels2[num2].r)); } val4.SetPixels32(pixels); val4.Apply(false, false); if (val3.HasProperty("_MetallicTex")) { val3.SetTexture("_MetallicTex", (Texture)(object)val4); } if (val3.HasProperty("_MetallicGlossMap")) { val3.SetTexture("_MetallicGlossMap", (Texture)(object)val4); val3.EnableKeyword("_METALLICGLOSSMAP"); } } else { if (val3.HasProperty("_MetallicTex")) { val3.SetTexture("_MetallicTex", (Texture)null); } if (val3.HasProperty("_MetallicGlossMap")) { val3.SetTexture("_MetallicGlossMap", (Texture)null); } val3.DisableKeyword("_METALLICGLOSSMAP"); } if (val3.HasProperty("_EmissionMap")) { val3.SetTexture("_EmissionMap", (Texture)(object)((num == 2) ? Texture("forge_coals_emission.png") : null)); } if (val3.HasProperty("_EmissionColor")) { val3.SetColor("_EmissionColor", (num == 2) ? (Color.white * 2.5f) : Color.black); } if (num == 2) { val3.EnableKeyword("_EMISSION"); } else { val3.DisableKeyword("_EMISSION"); } array2[num] = val3; } return array2; } } [HarmonyPatch(typeof(Player), "SetupPlacementGhost")] internal static class StationPlacementGhost { private static void Postfix(GameObject ___m_placementGhost) { if (Object.op_Implicit((Object)(object)___m_placementGhost) && Station.IsRarityStation(___m_placementGhost.GetComponent<CraftingStation>())) { StationModel.PreparePlacementGhost(___m_placementGhost); } } } internal sealed class StationWindow : MonoBehaviour { private sealed class ItemRow { internal ItemData Item; internal Button Button; internal TMP_Text Label; internal Image Icon; } private InventoryGui gui; private RectTransform panel; private RectTransform backdrop; private Image background; private Image backdropImage; private RectTransform details; private RectTransform itemList; private RectTransform listContent; private RectTransform listViewport; private ScrollRect itemScroll; private ScrollRect statsScroll; private Button viewToggle; private Button previous; private Button nextItem; private TMP_Text listCount; private bool traditional; private string configuredView; private readonly Vector3[] craftingCorners = (Vector3[])(object)new Vector3[4]; private readonly List<ItemRow> rows = new List<ItemRow>(); private readonly List<Image> frame = new List<Image>(); private bool craftingWasVisible; private TMP_Text selection; private TMP_Text title; private TMP_Text stats; private TMP_Text status; private Button materialChoice; private Image icon; private RectTransform iconFrame; private Button upgrade; private readonly List<Button> elementButtons = new List<Button>(); private ItemData selected; private string element = "Fire"; private string message = ""; private float refreshAt; private bool wasActive; private int materialOption; internal static void Tick(InventoryGui gui) { StationWindow stationWindow = ((Component)gui).GetComponent<StationWindow>(); if (!Object.op_Implicit((Object)(object)stationWindow) && Station.Active) { stationWindow = ((Component)gui).gameObject.AddComponent<StationWindow>(); stationWindow.Build(gui); } if (Object.op_Implicit((Object)(object)stationWindow)) { stationWindow.RefreshVisibility(); } } internal void ConfigurationChanged() { if (wasActive && configuredView != Settings.DefaultView.Value) { traditional = Settings.DefaultView.Value == "Traditional"; ApplyViewLayout(); } configuredView = Settings.DefaultView.Value; if (wasActive && Station.Active) { Refresh(); } } private void Build(InventoryGui owner) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0120: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Expected O, but got Unknown //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Expected O, but got Unknown //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Expected O, but got Unknown //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Expected O, but got Unknown //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_049a: Unknown result type (might be due to invalid IL or missing references) //IL_04a9: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Unknown result type (might be due to invalid IL or missing references) //IL_04c0: Unknown result type (might be due to invalid IL or missing references) //IL_04e8: Unknown result type (might be due to invalid IL or missing references) //IL_04ed: Unknown result type (might be due to invalid IL or missing references) //IL_0505: Unknown result type (might be due to invalid IL or missing references) //IL_051b: Unknown result type (might be due to invalid IL or missing references) //IL_05c5: Unknown result type (might be due to invalid IL or missing references) //IL_0664: Unknown result type (might be due to invalid IL or missing references) //IL_066e: Expected O, but got Unknown //IL_06b1: Unknown result type (might be due to invalid IL or missing references) //IL_06bb: Expected O, but got Unknown //IL_06ed: Unknown result type (might be due to invalid IL or missing references) //IL_06f7: Expected O, but got Unknown gui = owner; Canvas componentInParent = ((Component)gui.m_crafting).GetComponentInParent<Canvas>(); backdrop = Rect("RarityStationModal", ((Component)componentInParent).transform, Vector2.zero, Vector2.one); backdropImage = ((Component)backdrop).gameObject.AddComponent<Image>(); panel = Rect("RarityUpgradeWindow", (Transform)(object)backdrop, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f)); panel.pivot = new Vector2(0.5f, 0.5f); background = ((Component)panel).gameObject.AddComponent<Image>(); Frame("TopFrame", new Vector2(0f, 1f), Vector2.one, new Vector2(0f, -4f), Vector2.zero); Frame("BottomFrame", Vector2.zero, new Vector2(1f, 0f), Vector2.zero, new Vector2(0f, 4f)); Frame("LeftFrame", Vector2.zero, new Vector2(0f, 1f), Vector2.zero, new Vector2(4f, 0f)); Frame("RightFrame", new Vector2(1f, 0f), Vector2.one, new Vector2(-4f, 0f), Vector2.zero); Button((Transform)(object)panel, "Close station", "×", 0.92f, 0.947f, 0.98f, 0.99f, (UnityAction)delegate { gui.Hide(); Player.m_localPlayer.SetCraftingStation((CraftingStation)null); }); TMP_Text obj = Text((Transform)(object)panel, "Header", "RARITY FORGE", 0.04f, 0.94f, 0.9f, 0.995f, 26, (TextAlignmentOptions)514); obj.enableAutoSizing = true; obj.fontSizeMin = 14f; obj.fontSizeMax = 26f; viewToggle = Button((Transform)(object)panel, "Change window view", "Use Traditional List", 0.05f, 0.885f, 0.95f, 0.935f, (UnityAction)delegate { traditional = !traditional; ApplyViewLayout(); Refresh(); }); details = Rect("UpgradeDetails", (Transform)(object)panel, Vector2.zero, new Vector2(1f, 0.875f)); selection = Text((Transform)(object)details, "Selection", "", 0.19f, 0.855f, 0.81f, 0.925f, 18, (TextAlignmentOptions)514); previous = Button((Transform)(object)details, "Previous item", "‹", 0.04f, 0.855f, 0.16f, 0.925f, (UnityAction)delegate { Select(-1); }); nextItem = Button((Transform)(object)details, "Next item", "›", 0.84f, 0.855f, 0.96f, 0.925f, (UnityAction)delegate { Select(1); }); iconFrame = Rect("PreviewIcon", (Transform)(object)details, new Vector2(0.07f, 0.69f), new Vector2(0.29f, 0.825f)); RectTransform val = Rect("Icon", (Transform)(object)iconFrame, new Vector2(0.07f, 0.07f), new Vector2(0.93f, 0.93f)); icon = ((Component)val).gameObject.AddComponent<Image>(); icon.preserveAspect = true; ((Graphic)icon).raycastTarget = false; title = Text((Transform)(object)details, "UpgradeTitle", "", 0.34f, 0.69f, 0.95f, 0.825f, 21, (TextAlignmentOptions)513); title.enableAutoSizing = true; title.fontSizeMin = 12f; title.fontSizeMax = 21f; selection.enableAutoSizing = true; selection.fontSizeMin = 12f; selection.fontSizeMax = 18f; TMP_Text obj2 = Text((Transform)(object)details, "StatsCaption", "CURRENT → AFTER UPGRADE\nBase values; combat skills and target resistance still apply.", 0.05f, 0.605f, 0.95f, 0.675f, 15, (TextAlignmentOptions)514); obj2.enableAutoSizing = true; obj2.fontSizeMin = 9f; obj2.fontSizeMax = 15f; RectTransform val2 = Rect("StatsScroll", (Transform)(object)details, new Vector2(0.05f, 0.245f), new Vector2(0.95f, 0.6f)); RectTransform val3 = Rect("Viewport", (Transform)(object)val2, Vector2.zero, Vector2.one); ((Component)val3).gameObject.AddComponent<RectMask2D>(); RectTransform val4 = Rect("Content", (Transform)(object)val3, new Vector2(0f, 1f), Vector2.one); val4.pivot = new Vector2(0.5f, 1f); val4.sizeDelta = new Vector2(0f, 340f); stats = Text((Transform)(object)val4, "StatValues", "", 0f, 0f, 1f, 1f, 18, (TextAlignmentOptions)257); stats.textWrappingMode = (TextWrappingModes)1; ScrollRect val5 = (statsScroll = ((Component)val2).gameObject.AddComponent<ScrollRect>()); val5.viewport = val3; val5.content = val4; val5.horizontal = false; val5.movementType = (MovementType)2; val5.scrollSensitivity = 25f; ((Graphic)((Component)val3).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.05f); string[] array = new string[3] { "Fire", "Lightning", "Poison" }; foreach (string text in array) { string captured = text; int count = elementButtons.Count; elementButtons.Add(Button((Transform)(object)details, text, text, 0.05f + (float)count * 0.305f, 0.172f, 0.335f + (float)count * 0.305f, 0.23f, (UnityAction)delegate { element = captured; message = ""; Refresh(); })); } materialChoice = Button((Transform)(object)details, "Alternative resource", "Change crafting resource", 0.05f, 0.116f, 0.95f, 0.165f, (UnityAction)delegate { materialOption++; message = ""; Refresh(); }); upgrade = Button((Transform)(object)details, "Upgrade equipment", "Upgrade", 0.12f, 0.04f, 0.88f, 0.11f, new UnityAction(Commit)); status = Text((Transform)(object)details, "Status", "", 0.04f, 0.002f, 0.96f, 0.038f, 14, (TextAlignmentOptions)514); status.enableAutoSizing = true; status.fontSizeMin = 8f; status.fontSizeMax = 14f; BuildItemList(); ApplyViewLayout(); ((Component)backdrop).gameObject.SetActive(false); } private List<ItemData> Items() { IEnumerable<ItemData> source = ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems().Where(Station.Eligible); if (!traditional) { return source.ToList(); } return source.OrderBy<ItemData, string>((ItemData i) => Localization.instance.Localize(i.m_shared.m_name), StringComparer.CurrentCultureIgnoreCase).ThenBy((ItemData i) => i.m_quality).ToList(); } private void BuildItemList() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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_00c3: 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_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: 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_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_0205: 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_0242: Unknown result type (might be due to invalid IL or missing references) itemList = Rect("TraditionalEquipmentList", (Transform)(object)panel, new Vector2(0.025f, 0.08f), new Vector2(0.445f, 0.86f)); ((Graphic)((Component)itemList).gameObject.AddComponent<Image>()).color = new Color(0.14f, 0.12f, 0.09f, 0.8f); Text((Transform)(object)itemList, "List heading", "EQUIPMENT", 0.03f, 0.94f, 0.93f, 0.995f, 16, (TextAlignmentOptions)514); RectTransform val = Rect("ItemScroll", (Transform)(object)itemList, Vector2.zero, new Vector2(1f, 0.935f)); listViewport = Rect("Viewport", (Transform)(object)val, Vector2.zero, new Vector2(0.93f, 1f)); ((Component)listViewport).gameObject.AddComponent<RectMask2D>(); ((Graphic)((Component)listViewport).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.02f); listContent = Rect("Content", (Transform)(object)listViewport, new Vector2(0f, 1f), Vector2.one); listContent.pivot = new Vector2(0.5f, 1f); itemScroll = ((Component)val).gameObject.AddComponent<ScrollRect>(); itemScroll.viewport = listViewport; itemScroll.content = listContent; itemScroll.horizontal = false; itemScroll.movementType = (MovementType)2; itemScroll.scrollSensitivity = 30f; RectTransform val2 = Rect("Scrollbar", (Transform)(object)val, new Vector2(0.945f, 0.015f), new Vector2(0.99f, 0.985f)); ((Graphic)((Component)val2).gameObject.AddComponent<Image>()).color = new Color(0.22f, 0.18f, 0.12f); RectTransform val3 = Rect("Handle", (Transform)(object)val2, Vector2.zero, Vector2.one); Image val4 = ((Component)val3).gameObject.AddComponent<Image>(); ((Graphic)val4).color = new Color(0.75f, 0.59f, 0.35f); Scrollbar val5 = ((Component)val2).gameObject.AddComponent<Scrollbar>(); val5.handleRect = val3; ((Selectable)val5).targetGraphic = (Graphic)(object)val4; val5.direction = (Direction)2; itemScroll.verticalScrollbar = val5; itemScroll.verticalScrollbarVisibility = (ScrollbarVisibility)1; listCount = Text((Transform)(object)panel, "List count", "", 0.025f, 0.025f, 0.445f, 0.07f, 13, (TextAlignmentOptions)514); } private void ApplyViewLayout() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_0054: 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_005b: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011e: 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_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) details.anchorMin = (Vector2)(traditional ? new Vector2(0.46f, 0f) : Vector2.zero); details.anchorMax = new Vector2(1f, 0.875f); RectTransform obj = details; Vector2 offsetMin = (details.offsetMax = Vector2.zero); obj.offsetMin = offsetMin; ((Component)itemList).gameObject.SetActive(traditional); ((Component)listCount).gameObject.SetActive(traditional); ((Component)previous).gameObject.SetActive(!traditional); ((Component)nextItem).gameObject.SetActive(!traditional); RectTransform val = (RectTransform)selection.transform; val.anchorMin = new Vector2(traditional ? 0.03f : 0.19f, 0.855f); val.anchorMax = new Vector2(traditional ? 0.97f : 0.81f, 0.925f); offsetMin = (val.offsetMax = Vector2.zero); val.offsetMin = offsetMin; ((Component)viewToggle).GetComponentInChildren<TMP_Text>().text = (traditional ? "Use Selector View" : "Use Traditional List"); stats.fontSize = 14f; stats.enableAutoSizing = true; stats.fontSizeMin = 8f; stats.fontSizeMax = 14f; statsScroll.StopMovement(); ((Behaviour)statsScroll).enabled = false; RectTransform content = statsScroll.content; content.anchorMin = Vector2.zero; content.anchorMax = Vector2.one; offsetMin = (content.offsetMax = Vector2.zero); content.offsetMin = offsetMin; } private void RefreshItemList(List<ItemData> items) { //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_0388: 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_012e: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Expected O, but got Unknown //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0160: 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) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_0200: 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_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result t