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 RestedBrews v1.0.0
RestedBrews.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; 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 UnityEngine; [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("RestedBrews")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Rested Brews")] [assembly: AssemblyTitle("RestedBrews")] [assembly: AssemblyVersion("1.0.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 RestedBrews { internal static class BrewRegistrar { private const string BaseTemplate = "MeadBaseTasty"; private const string PotionTemplate = "MeadTasty"; private const string Cauldron = "piece_cauldron"; private static readonly Dictionary<BrewTier, CustomItem> BaseItems = new Dictionary<BrewTier, CustomItem>(); private static readonly Dictionary<BrewTier, CustomItemConversion> Conversions = new Dictionary<BrewTier, CustomItemConversion>(); public static void RegisterAll() { for (int i = 0; i < BrewTiers.All.Count; i++) { Register(BrewTiers.All[i], i); } PrefabManager.OnVanillaPrefabsAvailable -= RegisterAll; } private static void Register(BrewTier tier, int index) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_00a5: 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_00ee: 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_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0129: 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_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Expected O, but got Unknown //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Expected O, but got Unknown //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Expected O, but got Unknown SE_RestedBrew sE_RestedBrew = ScriptableObject.CreateInstance<SE_RestedBrew>(); ((Object)sE_RestedBrew).name = tier.EffectName; ((StatusEffect)sE_RestedBrew).m_name = "$" + tier.Token; ((StatusEffect)sE_RestedBrew).m_ttl = 1f; sE_RestedBrew.TierIndex = index; ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)sE_RestedBrew, false)); CustomItem val = new CustomItem(tier.PotionPrefab, "MeadTasty", new ItemConfig { Name = "$" + tier.Token, Description = "$" + tier.Token + "_desc" }); SharedData shared = val.ItemDrop.m_itemData.m_shared; shared.m_itemType = (ItemType)2; shared.m_food = 0f; shared.m_foodStamina = 0f; shared.m_foodEitr = 0f; shared.m_consumeStatusEffect = (StatusEffect)(object)sE_RestedBrew; Tint(val.ItemPrefab, tier.Tint); ItemManager.Instance.AddItem(val); ItemConfig val2 = new ItemConfig { Name = "$" + tier.Token + "_base", Description = "$" + tier.Token + "_base_desc", CraftingStation = "piece_cauldron", MinStationLevel = tier.StationLevel.Value, Enabled = tier.Enabled.Value }; foreach (KeyValuePair<string, int> item in tier.ParseIngredients()) { val2.AddRequirement(item.Key, item.Value, 0); } CustomItem val3 = new CustomItem(tier.BasePrefab, "MeadBaseTasty", val2); Tint(val3.ItemPrefab, tier.Tint); ItemManager.Instance.AddItem(val3); BaseItems[tier] = val3; CustomItemConversion val4 = new CustomItemConversion((ConversionConfig)new FermenterConversionConfig { FromItem = tier.BasePrefab, ToItem = tier.PotionPrefab, ProducedItems = tier.PotionsPerBatch.Value }); ItemManager.Instance.AddItemConversion(val4); Conversions[tier] = val4; RenderIcon(val, tier); RenderIcon(val3, tier); AddLocalization(tier); } private static void Tint(GameObject prefab, Color tint) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer obj in componentsInChildren) { obj.sharedMaterials = ((IEnumerable<Material>)obj.sharedMaterials).Select((Func<Material, Material>)delegate(Material m) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)m == (Object)null) { return (Material)null; } Material val = new Material(m); if (val.HasProperty("_Color")) { val.color *= tint; } return val; }).ToArray(); } } private static void RenderIcon(CustomItem item, BrewTier tier) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) try { Sprite val = RenderManager.Instance.Render(item.ItemPrefab, RenderManager.IsometricRotation); if ((Object)(object)val != (Object)null) { item.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val }; } } catch (Exception ex) { RestedBrewsPlugin.Log.LogWarning((object)(tier.DisplayName + ": icon render failed, keeping vanilla icon (" + ex.Message + ")")); } } private static void AddLocalization(BrewTier tier) { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { { tier.Token, tier.DisplayName }, { tier.Token + "_desc", "A fermented brew from the " + tier.Biomes + ". Drink it to become Rested anywhere" + ((tier.Minutes.Value > 0f) ? $" for {tier.Minutes.Value:0.#} minutes." : $", as if you had rested at comfort {tier.MaxComfort.Value}.") }, { tier.Token + "_base", tier.DisplayName + " base" }, { tier.Token + "_base_desc", "Ferment this in a Fermenter to make the " + tier.DisplayName + "." } }); } public static void ValidateAndLog() { ObjectDB instance = ObjectDB.instance; StatusEffect obj = ((instance != null) ? instance.GetStatusEffect(SEMan.s_statusEffectRested) : null); SE_Rested val = (SE_Rested)(object)((obj is SE_Rested) ? obj : null); if ((Object)(object)val != (Object)null) { RestedBrewsPlugin.Log.LogInfo((object)$"Live Rested: base {val.m_baseTTL}s, +{val.m_TTLPerComfortLevel}s per comfort level."); } else { RestedBrewsPlugin.Log.LogWarning((object)"Could not find the vanilla Rested effect; brews will do nothing."); } ApplyConfig(); foreach (BrewTier item in BrewTiers.All) { string arg = ((item.Minutes.Value > 0f) ? "fixed" : $"comfort {item.MaxComfort.Value}"); RestedBrewsPlugin.Log.LogInfo((object)($"{item.DisplayName}: {item.DurationSeconds() / 60f:0.#} min ({arg}), " + $"cauldron level {item.StationLevel.Value}, ingredients {item.Ingredients.Value}, " + $"enabled {IsRecipeEnabled(item)}")); } } public static void ApplyConfig() { //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown if ((Object)(object)ObjectDB.instance == (Object)null) { return; } foreach (BrewTier item in BrewTiers.All) { if (!BaseItems.TryGetValue(item, out var value)) { continue; } CustomRecipe recipe = value.Recipe; if ((Object)(object)((recipe != null) ? recipe.Recipe : null) == (Object)null) { continue; } Recipe recipe2 = value.Recipe.Recipe; List<Requirement> list = new List<Requirement>(); List<string> list2 = new List<string>(); foreach (KeyValuePair<string, int> item2 in item.ParseIngredients()) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item2.Key); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null) { list2.Add(item2.Key); continue; } list.Add(new Requirement { m_resItem = val, m_amount = item2.Value, m_recover = true }); } if (list2.Count > 0) { RestedBrewsPlugin.Log.LogWarning((object)(item.DisplayName + ": unknown ingredient(s) " + string.Join(", ", list2) + "; recipe disabled.")); } recipe2.m_resources = list.ToArray(); recipe2.m_minStationLevel = item.StationLevel.Value; recipe2.m_enabled = item.Enabled.Value && list2.Count == 0 && list.Count > 0; if (Conversions.TryGetValue(item, out var value2)) { ConversionConfig config = value2.Config; FermenterConversionConfig val2 = (FermenterConversionConfig)(object)((config is FermenterConversionConfig) ? config : null); if (val2 != null) { val2.ProducedItems = item.PotionsPerBatch.Value; SetProducedItems(item, item.PotionsPerBatch.Value); } } } } private static bool IsRecipeEnabled(BrewTier tier) { if (BaseItems.TryGetValue(tier, out var value)) { CustomRecipe recipe = value.Recipe; if ((Object)(object)((recipe != null) ? recipe.Recipe : null) != (Object)null) { return value.Recipe.Recipe.m_enabled; } } return false; } private static void SetProducedItems(BrewTier tier, int amount) { GameObject prefab = PrefabManager.Instance.GetPrefab("fermenter"); Fermenter val = ((prefab != null) ? prefab.GetComponent<Fermenter>() : null); if ((Object)(object)val == (Object)null) { return; } foreach (ItemConversion item in val.m_conversion) { if ((Object)(object)item.m_from != (Object)null && ((Object)item.m_from).name == tier.BasePrefab) { item.m_producedItems = amount; } } } } public class BrewTier { public string Key; public string DisplayName; public string Biomes; public Color Tint; public string DefaultIngredients; public int DefaultStationLevel; public int DefaultMaxComfort; public float DefaultMinutes; public ConfigEntry<bool> Enabled; public ConfigEntry<string> Ingredients; public ConfigEntry<int> StationLevel; public ConfigEntry<int> MaxComfort; public ConfigEntry<float> Minutes; public ConfigEntry<int> PotionsPerBatch; public string BasePrefab => "RestedBrew_" + Key + "_Base"; public string PotionPrefab => "RestedBrew_" + Key; public string EffectName => "SE_RestedBrew_" + Key; public string Token => "restedbrew_" + Key; public float DurationSeconds() { if (!(Minutes.Value > 0f)) { return SE_RestedBrew.RestedDuration(MaxComfort.Value); } return Minutes.Value * 60f; } public List<KeyValuePair<string, int>> ParseIngredients() { List<KeyValuePair<string, int>> list = new List<KeyValuePair<string, int>>(); string[] array = Ingredients.Value.Split(new char[1] { ',' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ':' }); if (array2.Length != 2 || !int.TryParse(array2[1].Trim(), out var result) || result < 1) { if (text.Trim().Length > 0) { RestedBrewsPlugin.Log.LogWarning((object)(DisplayName + ": ignoring bad ingredient entry '" + text.Trim() + "'")); } } else { list.Add(new KeyValuePair<string, int>(array2[0].Trim(), result)); } } return list; } } public static class BrewTiers { public static readonly List<BrewTier> All = new List<BrewTier> { new BrewTier { Key = "forest", DisplayName = "Forest Draught", Biomes = "Black Forest", Tint = new Color(0.35f, 0.75f, 0.35f), DefaultIngredients = "BoneFragments:5,Thistle:3", DefaultStationLevel = 1, DefaultMaxComfort = 13 }, new BrewTier { Key = "frostmarsh", DisplayName = "Frostmarsh Draught", Biomes = "Swamp + Mountains", Tint = new Color(0.45f, 0.85f, 0.95f), DefaultIngredients = "Bloodbag:2,Turnip:3,Onion:3,FreezeGland:1", DefaultStationLevel = 3, DefaultMaxComfort = 17, DefaultMinutes = 25f }, new BrewTier { Key = "mistfield", DisplayName = "Mistfield Draught", Biomes = "Plains + Mistlands", Tint = new Color(0.75f, 0.5f, 0.95f), DefaultIngredients = "Cloudberry:5,Barley:3,RoyalJelly:2,MushroomJotunPuffs:2", DefaultStationLevel = 5, DefaultMaxComfort = 20, DefaultMinutes = 30f }, new BrewTier { Key = "emberfrost", DisplayName = "Emberfrost Draught", Biomes = "Ashlands + Deep North", Tint = new Color(1f, 0.45f, 0.2f), DefaultIngredients = "Vineberry:3,Fiddleheadfern:2,MushroomSmokePuff:2,Lingonberry:5", DefaultStationLevel = 7, DefaultMaxComfort = 22, DefaultMinutes = 35f } }; public static ConfigEntry<bool> PauseNearFire; public static void BindConfig(ConfigFile config) { //IL_001a: 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_0027: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Expected O, but got Unknown //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Expected O, but got Unknown PauseNearFire = config.Bind<bool>("0 - General", "PauseNearFire", true, new ConfigDescription("Pause a brew's Rested timer while you are within a fire's warmth.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); for (int i = 0; i < All.Count; i++) { BrewTier brewTier = All[i]; string text = $"{i + 1} - {brewTier.DisplayName}"; ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { IsAdminOnly = true }; brewTier.Enabled = config.Bind<bool>(text, "Enabled", true, new ConfigDescription("Allow brewing the " + brewTier.DisplayName + " (" + brewTier.Biomes + ").", (AcceptableValueBase)null, new object[1] { val })); brewTier.Ingredients = config.Bind<string>(text, "Ingredients", brewTier.DefaultIngredients, new ConfigDescription("Cauldron ingredients for the brew base, as Prefab:amount pairs separated by commas.", (AcceptableValueBase)null, new object[1] { val })); brewTier.StationLevel = config.Bind<int>(text, "CauldronLevel", brewTier.DefaultStationLevel, new ConfigDescription("Cauldron level needed (1 + number of attached Cauldron upgrades).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), new object[1] { val })); brewTier.MaxComfort = config.Bind<int>(text, "ComfortLevel", brewTier.DefaultMaxComfort, new ConfigDescription("If Minutes is 0, the potion grants Rested as if you rested at this comfort level (default: the best comfort buildable in this tier).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 40), new object[1] { val })); brewTier.Minutes = config.Bind<float>(text, "Minutes", brewTier.DefaultMinutes, new ConfigDescription("Fixed Rested duration in minutes. 0 = use ComfortLevel instead.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 180f), new object[1] { val })); brewTier.PotionsPerBatch = config.Bind<int>(text, "PotionsPerBatch", 4, new ConfigDescription("Potions produced by one fermented brew base.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), new object[1] { val })); } } } [HarmonyPatch(typeof(Player), "CanConsumeItem")] internal static class CanConsumeItemPatch { private static void Postfix(Player __instance, ItemData item, ref bool __result) { if (!__result || !(item?.m_shared.m_consumeStatusEffect is SE_RestedBrew sE_RestedBrew)) { return; } StatusEffect statusEffect = ((Character)__instance).GetSEMan().GetStatusEffect(SEMan.s_statusEffectRested); if (!((Object)(object)statusEffect == (Object)null)) { float num = BrewTiers.All[sE_RestedBrew.TierIndex].DurationSeconds(); if (SE_RestedBrew.ActiveBrewDuration(statusEffect) >= num || statusEffect.GetRemaningTime() >= num) { ((Character)__instance).Message((MessageType)2, "You are already well rested", 0, (Sprite)null, false); __result = false; } } } } [HarmonyPatch(typeof(SE_Rested), "UpdateStatusEffect")] internal static class RestedUpdatePatch { private static void Postfix(SE_Rested __instance, float dt) { if (BrewTiers.PauseNearFire.Value && !(SE_RestedBrew.ActiveBrewDuration((StatusEffect)(object)__instance) <= 0f)) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && ((Character)localPlayer).GetSEMan().HaveStatusEffect(SEMan.s_statusEffectCampFire)) { ref float reference = ref SE_RestedBrew.TimeRef.Invoke((StatusEffect)(object)__instance); reference = Mathf.Max(0f, reference - dt); } } } } [BepInPlugin("com.syloreon.restedbrews", "Rested Brews", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class RestedBrewsPlugin : BaseUnityPlugin { public const string PluginGuid = "com.syloreon.restedbrews"; public const string PluginName = "Rested Brews"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; private void Awake() { //IL_007f: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; BrewTiers.BindConfig(((BaseUnityPlugin)this).Config); PrefabManager.OnVanillaPrefabsAvailable += BrewRegistrar.RegisterAll; ItemManager.OnItemsRegistered += BrewRegistrar.ValidateAndLog; SynchronizationManager.OnConfigurationSynchronized += delegate { BrewRegistrar.ApplyConfig(); }; new Harmony("com.syloreon.restedbrews").PatchAll(); Log.LogInfo((object)"Rested Brews v1.0.0 loaded."); } } public class SE_RestedBrew : StatusEffect { internal static readonly FieldRef<StatusEffect, float> TimeRef = AccessTools.FieldRefAccess<StatusEffect, float>("m_time"); public int TierIndex; private static StatusEffect s_brewRested; private static float s_brewDuration; public static float ActiveBrewDuration(StatusEffect currentRested) { if (!((Object)(object)currentRested != (Object)null) || !((Object)(object)currentRested == (Object)(object)s_brewRested)) { return 0f; } return s_brewDuration; } public override void Setup(Character character) { ((StatusEffect)this).Setup(character); Player val = (Player)(object)((character is Player) ? character : null); if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer) { return; } float num = BrewTiers.All[TierIndex].DurationSeconds(); if (num <= 0f) { return; } SEMan sEMan = ((Character)val).GetSEMan(); sEMan.AddStatusEffect(SEMan.s_statusEffectRested, true, 0, 0f, (short)(-1)); StatusEffect statusEffect = sEMan.GetStatusEffect(SEMan.s_statusEffectRested); if (!((Object)(object)statusEffect == (Object)null)) { if (statusEffect.GetRemaningTime() < num) { statusEffect.m_ttl = num; TimeRef.Invoke(statusEffect) = 0f; } if (num > ActiveBrewDuration(statusEffect)) { s_brewRested = statusEffect; s_brewDuration = num; } ((Character)val).Message((MessageType)2, $"Rested for {Mathf.RoundToInt(statusEffect.GetRemaningTime() / 60f)} min", 0, (Sprite)null, false); } } public static float RestedDuration(int comfort) { ObjectDB instance = ObjectDB.instance; StatusEffect obj = ((instance != null) ? instance.GetStatusEffect(SEMan.s_statusEffectRested) : null); SE_Rested val = (SE_Rested)(object)((obj is SE_Rested) ? obj : null); if ((Object)(object)val == (Object)null) { return 0f; } return val.m_baseTTL + (float)(comfort - 1) * val.m_TTLPerComfortLevel; } } }