using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SmartStorage.Core;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SmartStorage")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Smart Storage for Valheim - automatic item sorting into chests")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("SmartStorage")]
[assembly: AssemblyTitle("SmartStorage")]
[assembly: AssemblyVersion("0.1.0.0")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[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 SmartStorage
{
[BepInPlugin("com.macheon.smartstorage", "SmartStorage", "0.2.0")]
public class SmartStoragePlugin : BaseUnityPlugin
{
public const string PluginGuid = "com.macheon.smartstorage";
public const string PluginName = "SmartStorage";
public const string PluginVersion = "0.2.0";
private Harmony? _harmony;
internal static ManualLogSource? LogSource;
internal static ConfigEntry<bool>? ModEnabled;
internal static ConfigEntry<float>? ScanRadius;
internal static ConfigEntry<bool>? ShowNotifications;
internal static ConfigEntry<bool>? RequireOwnedContainers;
internal static ConfigEntry<bool>? VerboseLogging;
private void Awake()
{
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Expected O, but got Unknown
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: Expected O, but got Unknown
LogSource = ((BaseUnityPlugin)this).Logger;
ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "Enabled", true, "Enable or disable the Smart Storage mod entirely.");
ScanRadius = ((BaseUnityPlugin)this).Config.Bind<float>("2. Detection", "ScanRadius", 10f, new ConfigDescription("Search radius (in meters) around the player to find matching containers.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
ShowNotifications = ((BaseUnityPlugin)this).Config.Bind<bool>("3. UI", "ShowNotifications", true, "Show a HUD message when an item is auto-sorted.");
RequireOwnedContainers = ((BaseUnityPlugin)this).Config.Bind<bool>("4. Multiplayer", "RequireOwnedContainers", true, "Only target containers you own (recommended in multiplayer to avoid issues).");
VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("5. Debug", "VerboseLogging", false, "Log every Smart Storage transfer to the BepInEx console.");
((BaseUnityPlugin)this).Logger.LogInfo((object)"======================================");
((BaseUnityPlugin)this).Logger.LogInfo((object)" SmartStorage v0.2.0 loaded!");
((BaseUnityPlugin)this).Logger.LogInfo((object)$" Scan radius: {ScanRadius.Value}m | Notifications: {ShowNotifications.Value}");
((BaseUnityPlugin)this).Logger.LogInfo((object)"======================================");
_harmony = new Harmony("com.macheon.smartstorage");
_harmony.PatchAll();
}
private void OnDestroy()
{
Harmony? harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
}
}
namespace SmartStorage.Patches
{
[HarmonyPatch]
public static class InventoryPatches
{
private static string GetItemName(ItemData item)
{
return (Localization.instance != null) ? Localization.instance.Localize(item.m_shared.m_name) : item.m_shared.m_name;
}
[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
[HarmonyPrefix]
public static bool OnSelectedItem_Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Vector2i pos, Modifier mod)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Invalid comparison between Unknown and I4
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
ConfigEntry<bool>? modEnabled = SmartStoragePlugin.ModEnabled;
if (modEnabled != null && !modEnabled.Value)
{
return true;
}
if (item == null)
{
return true;
}
if ((int)mod != 2)
{
return true;
}
if (!__instance.IsContainerOpen())
{
return true;
}
if (item.m_shared.m_questItem)
{
return true;
}
Player localPlayer = Player.m_localPlayer;
if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsTeleporting())
{
return true;
}
Inventory inventory = ((Humanoid)localPlayer).GetInventory();
if (grid.GetInventory() != inventory)
{
return true;
}
Container currentContainer = GetCurrentContainer(__instance);
float radius = SmartStoragePlugin.ScanRadius?.Value ?? 10f;
bool requireOwned = SmartStoragePlugin.RequireOwnedContainers?.Value ?? true;
Container val = ContainerScanner.FindBestContainerForItem(item, ((Component)localPlayer).transform.position, currentContainer, radius, requireOwned);
if ((Object)(object)val == (Object)null)
{
return true;
}
string itemName = GetItemName(item);
int stack = item.m_stack;
val.GetInventory().MoveItemToThis(inventory, item);
ConfigEntry<bool>? showNotifications = SmartStoragePlugin.ShowNotifications;
if (showNotifications != null && showNotifications.Value)
{
string text = $"\ud83d\udce6 {itemName} x{stack} → coffre intelligent";
MessageHud instance = MessageHud.instance;
if (instance != null)
{
instance.ShowMessage((MessageType)1, text, 0, (Sprite)null, false);
}
}
ConfigEntry<bool>? verboseLogging = SmartStoragePlugin.VerboseLogging;
if (verboseLogging != null && verboseLogging.Value)
{
ManualLogSource? logSource = SmartStoragePlugin.LogSource;
if (logSource != null)
{
logSource.LogInfo((object)$"[SMART STORE] {itemName} x{stack} → {((Object)val).name} at {((Component)val).transform.position}");
}
}
return false;
}
private static Container? GetCurrentContainer(InventoryGui gui)
{
object? obj = typeof(InventoryGui).GetField("m_currentContainer", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(gui);
return (Container?)((obj is Container) ? obj : null);
}
}
}
namespace SmartStorage.Core
{
public static class ContainerScanner
{
public const float DefaultScanRadius = 10f;
private const float CacheLifetimeSeconds = 2f;
private static Container[]? _cachedContainers = null;
private static float _cacheTimestamp = 0f;
private static Vector3 _cachePosition = Vector3.zero;
private const float CachePositionThreshold = 5f;
public static Container? FindBestContainerForItem(ItemData item, Vector3 playerPosition, Container? excludeContainer = null, float radius = 10f, bool requireOwned = true)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_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)
if (item == null)
{
return null;
}
string name = item.m_shared.m_name;
float num = radius * radius;
Container[] cachedOrFreshContainers = GetCachedOrFreshContainers(playerPosition);
Container[] array = cachedOrFreshContainers;
foreach (Container val in array)
{
if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)excludeContainer)
{
continue;
}
Vector3 val2 = ((Component)val).transform.position - playerPosition;
float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
if (!(sqrMagnitude > num) && (!requireOwned || val.IsOwner()))
{
Inventory inventory = val.GetInventory();
if (inventory != null && inventory.HaveItem(name, false) && inventory.CanAddItem(item, item.m_stack))
{
return val;
}
}
}
return null;
}
private static Container[] GetCachedOrFreshContainers(Vector3 playerPosition)
{
//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)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: 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)
float time = Time.time;
Vector3 val = playerPosition - _cachePosition;
float magnitude = ((Vector3)(ref val)).magnitude;
if (_cachedContainers == null || !(time - _cacheTimestamp < 2f) || !(magnitude < 5f))
{
_cachedContainers = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
_cacheTimestamp = time;
_cachePosition = playerPosition;
}
return _cachedContainers;
}
}
}