using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using InstantFertilizer.Model;
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.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("InstantFertilizer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1+e30cc8add4f22a2b50c7ca0d66db26e621f72edc")]
[assembly: AssemblyProduct("InstantFertilizer")]
[assembly: AssemblyTitle("InstantFertilizer")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 InstantFertilizer
{
[BepInPlugin("nbusseneau.InstantFertilizer", "InstantFertilizer", "0.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
private const string ModGUID = "nbusseneau.InstantFertilizer";
private const string ModName = "InstantFertilizer";
private const string ModVersion = "0.1.1";
private static readonly List<Fertilizer> s_defaultFertilizers = new List<Fertilizer>(2)
{
new Fertilizer("$item_ancientseed", 3, "defeated_eikthyr"),
new Fertilizer("$item_ymirremains", 1, "defeated_gdking")
};
private static ConfigEntry<string> s_fertilizers;
internal static ManualLogSource Logger { get; private set; }
public static List<Fertilizer> Fertilizers { get; private set; }
private static List<Fertilizer> ParseFertilizers(string serializedFertilizers)
{
return (from f in serializedFertilizers.Split(new char[1] { ',' }).Select(Fertilizer.FromString)
where f != null
select f).ToList();
}
public void Awake()
{
//IL_000b: 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_0018: Expected O, but got Unknown
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Expected O, but got Unknown
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
Logger = ((BaseUnityPlugin)this).Logger;
ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
{
IsAdminOnly = true
};
string text = "Comma-separated list of fertilizers that may be used.\nFertilizer format: " + Fertilizer.SerializedFormat + "\nSee https://valheim.fandom.com/wiki/Global_Keys for quick reference of available global keys, or use `none` if you do not want to gate fertilizing behind a global key.\nNote that the mod is not able to determine in advance if an item or global key actually exists. If a fertilizer appears to be ignored, double check item names and global keys.";
s_fertilizers = ((BaseUnityPlugin)this).Config.Bind<string>("Behaviour", "Fertilizer list", GeneralExtensions.Join<Fertilizer>((IEnumerable<Fertilizer>)s_defaultFertilizers, (Func<Fertilizer, string>)null, ", "), new ConfigDescription(text, (AcceptableValueBase)null, new object[1] { val }));
Fertilizers = ParseFertilizers(s_fertilizers.Value);
s_fertilizers.SettingChanged += delegate
{
Fertilizers = ParseFertilizers(s_fertilizers.Value);
};
SetUpConfigWatcher();
Assembly executingAssembly = Assembly.GetExecutingAssembly();
new Harmony("nbusseneau.InstantFertilizer").PatchAll(executingAssembly);
}
public void OnDestroy()
{
((BaseUnityPlugin)this).Config.Save();
}
private void SetUpConfigWatcher()
{
FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath));
fileSystemWatcher.Changed += ReadConfigValues;
fileSystemWatcher.Created += ReadConfigValues;
fileSystemWatcher.Renamed += ReadConfigValues;
fileSystemWatcher.IncludeSubdirectories = true;
fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
fileSystemWatcher.EnableRaisingEvents = true;
}
private void ReadConfigValues(object sender, FileSystemEventArgs e)
{
if (!File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath))
{
return;
}
try
{
Logger.LogDebug((object)"Attempting to reload configuration...");
((BaseUnityPlugin)this).Config.Reload();
}
catch
{
Logger.LogError((object)("There was an issue loading " + ((BaseUnityPlugin)this).Config.ConfigFilePath));
}
}
}
}
namespace InstantFertilizer.Patches
{
[HarmonyPatch(typeof(Pickable))]
public class PickablePatches
{
[HarmonyPostfix]
[HarmonyPatch("GetHoverText")]
private static void PickableGetFertilizeHoverText(Pickable __instance, ref string __result)
{
if (__instance.m_picked && __instance.m_enabled != 0)
{
__result += FertilizerManager.GetFertilizeHoverText();
}
}
}
[HarmonyPatch(typeof(Plant))]
public class PlantPatches
{
[HarmonyPostfix]
[HarmonyPatch("GetHoverText")]
private static void PlantGetFertilizeHoverText(Plant __instance, ref string __result)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
if ((int)__instance.m_status == 0)
{
__result += FertilizerManager.GetFertilizeHoverText();
}
}
}
[HarmonyPatch(typeof(Player))]
public class PlayerPatches
{
[HarmonyPrefix]
[HarmonyPatch("Interact")]
private static void Fertilize(Player __instance, GameObject go, bool hold, ref bool __runOriginal)
{
if (((Character)__instance).InAttack() || ((Character)__instance).InDodge() || hold)
{
return;
}
bool flag = false;
Plant componentInParent = go.GetComponentInParent<Plant>();
if (componentInParent != null)
{
flag = FertilizerManager.TryFertilize(__instance, componentInParent);
}
else
{
Pickable componentInParent2 = go.GetComponentInParent<Pickable>();
if (componentInParent2 != null)
{
flag = FertilizerManager.TryFertilize(__instance, componentInParent2);
}
}
if (flag)
{
__runOriginal = false;
}
}
}
[HarmonyPatch(typeof(ObjectDB))]
public class ZNetScenePatches
{
[HarmonyPostfix]
[HarmonyPatch("Awake")]
[HarmonyPatch("CopyOtherDB")]
private static void ClearCachedGlobalKeys()
{
FertilizerManager.ClearCachedGlobalKeys();
}
}
}
namespace InstantFertilizer.Model
{
public class Fertilizer
{
public const char Delimiter = ':';
public static readonly string SerializedFormat = $"itemName{':'}requiredAmount{':'}requiredGlobalKey";
public string ItemName { get; }
public int RequiredAmount { get; }
public string RequiredGlobalKey { get; }
public string HoverText { get; }
public Fertilizer(string itemName, int requiredAmount, string requiredGlobalKey)
{
ItemName = itemName;
RequiredAmount = requiredAmount;
RequiredGlobalKey = requiredGlobalKey;
HoverText = $"{requiredAmount} {itemName}";
base..ctor();
}
public override string ToString()
{
return $"{ItemName}{':'}{RequiredAmount}{':'}{RequiredGlobalKey}";
}
public static Fertilizer FromString(string serializedFertilizer)
{
string[] array = serializedFertilizer.Trim().Split(new char[1] { ':' });
if (array.Length != 3)
{
Plugin.Logger.LogError((object)("Could not deserialize the following fertilizer entry: " + serializedFertilizer + "\r\nInvalid format: must be `" + SerializedFormat + "`"));
return null;
}
string text = array[0];
string s = array[1];
string requiredGlobalKey = array[2];
string itemName = text;
if (!int.TryParse(s, out var result))
{
Plugin.Logger.LogError((object)("Could not deserialize the following fertilizer entry: " + serializedFertilizer + "\r\nInvalid amount: must be a valid integer"));
return null;
}
return new Fertilizer(itemName, result, requiredGlobalKey);
}
}
public static class FertilizerManager
{
public const string GlobalKeyIgnore = "none";
private static readonly Dictionary<string, bool> s_cachedGlobalKeys = new Dictionary<string, bool>();
public static void ClearCachedGlobalKeys()
{
s_cachedGlobalKeys.Clear();
}
private static bool HasGlobalKey(string globalKey)
{
if (globalKey == "none")
{
return true;
}
if (s_cachedGlobalKeys.TryGetValue(globalKey, out var value))
{
return value;
}
value = ZoneSystem.instance.GetGlobalKey(globalKey);
if (value)
{
s_cachedGlobalKeys[globalKey] = true;
}
return value;
}
public static string GetFertilizeHoverText()
{
IEnumerable<string> enumerable = from fertilizer in Plugin.Fertilizers
where HasGlobalKey(fertilizer.RequiredGlobalKey)
select fertilizer.HoverText;
if (!enumerable.Any())
{
return string.Empty;
}
string text = "\n[<color=yellow><b>$KEY_Use</b></color>] $InstantFertilizer_Fertilize (" + string.Join(" / ", enumerable) + ")";
return Localization.instance.Localize(text);
}
public static bool TryFertilize(Player player, Pickable pickable)
{
if (!pickable.m_nview.IsValid() || !pickable.m_picked || pickable.m_enabled == 0)
{
return false;
}
return TryFertilizeInternal(player, (Component)(object)pickable, delegate
{
pickable.m_nview.ClaimOwnership();
pickable.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_SetPicked", new object[1] { false });
});
}
public static bool TryFertilize(Player player, Plant plant)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
if (!plant.m_nview.IsValid() || (int)plant.m_status != 0)
{
return false;
}
return TryFertilizeInternal(player, (Component)(object)plant, delegate
{
plant.m_nview.ClaimOwnership();
plant.Grow();
});
}
private static bool TryFertilizeInternal(Player player, Component component, Action onFertilize)
{
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
player.m_lastHoverInteractTime = Time.time;
IEnumerable<Fertilizer> enumerable = Plugin.Fertilizers.Where((Fertilizer fertilizer) => HasGlobalKey(fertilizer.RequiredGlobalKey));
if (!enumerable.Any())
{
return false;
}
bool flag = false;
foreach (Fertilizer item2 in enumerable)
{
ItemData item = ((Humanoid)player).m_inventory.GetItem(item2.ItemName, -1, false);
flag = item != null && ((Humanoid)player).m_inventory.CountItems(item2.ItemName, -1, true) >= item2.RequiredAmount && ((Humanoid)player).m_inventory.RemoveItem(item, item2.RequiredAmount);
if (flag)
{
break;
}
}
if (!flag)
{
((Character)player).Message((MessageType)2, "$InstantFertilizer_FertilizerRequired", 0, (Sprite)null);
return false;
}
onFertilize();
((Humanoid)player).DoInteractAnimation(component.transform.position);
return true;
}
}
}