Decompiled source of SeneaL Recycle v1.0.0

plugins/SeneaL-Recycle/SeneaL-Recycle.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using SeneaLUI.Core;
using SeneaLUI.Inv;
using SeneaLUI.Mods;
using SeneaLUI.Net;
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: AssemblyVersion("0.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 SeneaLUI.Recycle
{
	public sealed class NativeRecycler : Recycler
	{
		private readonly List<KeyValuePair<ItemDrop, int>> _scratch = new List<KeyValuePair<ItemDrop, int>>(8);

		public override bool On
		{
			get
			{
				if (RecyclePlugin.On != null && RecyclePlugin.On.Value)
				{
					return Policy.CanRecycle;
				}
				return false;
			}
		}

		public override void List(Player player, List<Recipe> recipes, List<ItemData> items, List<bool> can, Dictionary<ItemData, string> why)
		{
			ObjectDB instance = ObjectDB.instance;
			if (!Object.op_Implicit((Object)(object)instance))
			{
				return;
			}
			List<ItemData> allItems = ((Humanoid)player).GetInventory().GetAllItems();
			CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
			for (int i = 0; i < allItems.Count; i++)
			{
				ItemData val = allItems[i];
				if (val.m_equipped || Raw(val))
				{
					continue;
				}
				Recipe recipe = instance.GetRecipe(val);
				if (Object.op_Implicit((Object)(object)recipe) && recipe.m_enabled && Object.op_Implicit((Object)(object)recipe.m_item) && recipe.m_resources != null && recipe.m_resources.Length != 0 && (player.IsRecipeKnown(recipe.m_item.m_itemData.m_shared.m_name) || (RecyclePlugin.Unknown.Value && Policy.CanRecycleUnknown)))
				{
					string text = null;
					if ((RecyclePlugin.Station.Value || Policy.RecycleOwnStation) && Object.op_Implicit((Object)(object)recipe.m_craftingStation) && (!Object.op_Implicit((Object)(object)currentCraftingStation) || currentCraftingStation.m_name != recipe.m_craftingStation.m_name))
					{
						text = string.Format(Loc.T("Recycle.NeedStation"), Localization.instance.Localize(recipe.m_craftingStation.m_name));
					}
					_scratch.Clear();
					((Recycler)this).Gains(val, recipe, _scratch);
					if (text == null && _scratch.Count == 0)
					{
						text = ((Batches(val, recipe) == 0) ? string.Format(Loc.T("Recycle.NeedStack"), recipe.m_amount) : Loc.T("Recycle.Nothing"));
					}
					recipes.Add(recipe);
					items.Add(val);
					can.Add(text == null);
					if (text != null)
					{
						why[val] = text;
					}
				}
			}
		}

		public override void Gains(ItemData item, Recipe recipe, List<KeyValuePair<ItemDrop, int>> into)
		{
			int num = Batches(item, recipe);
			if (num <= 0)
			{
				return;
			}
			float num2 = Mathf.Min(Mathf.Clamp01(RecyclePlugin.Rate.Value), Policy.MaxRecycleRate);
			Requirement[] resources = recipe.m_resources;
			foreach (Requirement val in resources)
			{
				if (Object.op_Implicit((Object)(object)val.m_resItem) && val.m_recover && !val.m_upgraderResource)
				{
					int num3 = 0;
					for (int j = 1; j <= Mathf.Max(1, item.m_quality); j++)
					{
						num3 += val.GetAmount(j);
					}
					int num4 = Mathf.FloorToInt((float)(num3 * num) * num2);
					if (num4 > 0)
					{
						into.Add(new KeyValuePair<ItemDrop, int>(val.m_resItem, num4));
					}
				}
			}
		}

		public override bool Take(Player player, ItemData item, Recipe recipe)
		{
			_scratch.Clear();
			((Recycler)this).Gains(item, recipe, _scratch);
			if (_scratch.Count == 0)
			{
				return false;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (item.m_shared.m_maxStackSize > 1)
			{
				inventory.RemoveItem(item, Batches(item, recipe) * Mathf.Max(1, recipe.m_amount));
			}
			else
			{
				inventory.RemoveItem(item);
			}
			for (int i = 0; i < _scratch.Count; i++)
			{
				Recycling.Give(player, inventory, _scratch[i].Key, _scratch[i].Value);
			}
			return true;
		}

		private static bool Raw(ItemData item)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			SharedData shared = item.m_shared;
			if ((int)shared.m_itemType != 1 && (int)shared.m_itemType != 13)
			{
				if ((int)shared.m_itemType == 16)
				{
					return shared.m_maxStackSize > 1;
				}
				return false;
			}
			return true;
		}

		private static int Batches(ItemData item, Recipe recipe)
		{
			if (item.m_shared.m_maxStackSize <= 1)
			{
				return 1;
			}
			return item.m_stack / Mathf.Max(1, recipe.m_amount);
		}
	}
	[BepInPlugin("seneaL.valheim.ui.recycle", "SeneaL Recycle", "1.0.0")]
	[BepInDependency("seneaL.valheim.ui", "1.2.0")]
	public sealed class RecyclePlugin : BaseUnityPlugin
	{
		public const string Guid = "seneaL.valheim.ui.recycle";

		public const string Name = "SeneaL Recycle";

		public const string Version = "1.0.0";

		private const string Texts = "SeneaLUI.Recycle.Languages.";

		private readonly NativeRecycler _recycler = new NativeRecycler();

		public static ConfigEntry<bool> On { get; private set; }

		public static ConfigEntry<float> Rate { get; private set; }

		public static ConfigEntry<bool> Station { get; private set; }

		public static ConfigEntry<bool> Unknown { get; private set; }

		private void Awake()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			On = ((BaseUnityPlugin)this).Config.Bind<bool>("Recycle", "Enabled", true, "A Recycle tab at crafting stations that takes a crafted item apart into part of its materials. Ignored while Valheim Recycle or Recycle N Reclaim is installed: their recycling fills the same tab instead.");
			Rate = ((BaseUnityPlugin)this).Config.Bind<float>("Recycle", "Rate", 0.5f, new ConfigDescription("Share of the materials that comes back, counting every quality level of the item (rounded down).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			Station = ((BaseUnityPlugin)this).Config.Bind<bool>("Recycle", "OwnStation", true, "An item is recycled only at the station it is crafted at.");
			Unknown = ((BaseUnityPlugin)this).Config.Bind<bool>("Recycle", "UnknownRecipes", false, "Also list items whose recipe you do not know yet.");
			LoadTexts();
			Recycling.Register((Recycler)(object)_recycler);
			Func<bool> free = () => !Recycle.On && !Rnr.On;
			Func<bool> active = () => On.Value && free() && Policy.CanRecycle;
			Func<string> why = () => (!free() || Policy.CanRecycle) ? ((!free()) ? string.Format(Loc.T("Recycle.WhyMod"), Rnr.On ? "Recycle N Reclaim" : "Valheim Recycle") : string.Format(Loc.T("Recycle.WhyOn"), Loc.T("Recycle.Enabled"))) : Loc.T("Recycle.WhyServer");
			Addon obj = Addons.Register("seneaL.valheim.ui.recycle", "SeneaL Recycle", (Func<string>)null, (string)null, (string)null);
			obj.Switch((Func<string>)(() => Loc.T("Recycle.Enabled")), On, free, why);
			obj.Slider((Func<string>)(() => Loc.T("Recycle.Rate")), Rate, 0f, 1f, (Func<float, string>)((float v) => Mathf.RoundToInt(v * 100f) + "%"), active, (Func<float>)(() => Policy.MaxRecycleRate), why);
			obj.Switch((Func<string>)(() => Loc.T("Recycle.Station")), Station, (Func<bool>)(() => active() && !Policy.RecycleOwnStation), (Func<string>)(() => (!Policy.RecycleOwnStation) ? why() : Loc.T("Recycle.WhyServer")));
			obj.Switch((Func<string>)(() => Loc.T("Recycle.Unknown")), Unknown, (Func<bool>)(() => active() && Policy.CanRecycleUnknown), (Func<string>)(() => Policy.CanRecycleUnknown ? why() : Loc.T("Recycle.WhyServer")));
		}

		private void OnDestroy()
		{
			Recycling.Unregister((Recycler)(object)_recycler);
		}

		private static void LoadTexts()
		{
			Assembly assembly = typeof(RecyclePlugin).Assembly;
			string[] manifestResourceNames = assembly.GetManifestResourceNames();
			foreach (string text in manifestResourceNames)
			{
				if (!text.StartsWith("SeneaLUI.Recycle.Languages.") || !text.EndsWith(".txt"))
				{
					continue;
				}
				using Stream stream = assembly.GetManifestResourceStream(text);
				using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8);
				Loc.Extend(text.Substring("SeneaLUI.Recycle.Languages.".Length, text.Length - "SeneaLUI.Recycle.Languages.".Length - 4), streamReader.ReadToEnd());
			}
		}
	}
}