using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using Agents;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Gear;
using HarmonyLib;
using HawChow.DropItemEverywhere;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using LevelGeneration;
using Localization;
using Player;
using UnityEngine;
using UnityEngine.Rendering;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("HawChow")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DropItemEverywhere")]
[assembly: AssemblyTitle("DropItemEverywhere")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[BepInPlugin("HawChow.DropItemEverywhere", "DropItemEverywhere", "1.0.0")]
public sealed class Plugin : BasePlugin
{
internal static ManualLogSource Logger;
internal static ConfigEntry<string> ContainerKey;
internal static ConfigEntry<string> PlaceKey;
internal static ConfigEntry<float> ContainerHoldSeconds;
internal static ConfigEntry<float> PlaceHoldSeconds;
internal static ConfigEntry<float> ContainerReachMeters;
internal static ConfigEntry<float> SurfaceReachMeters;
internal static ConfigEntry<float> SurfaceOffsetMeters;
internal static ConfigEntry<float> ClearanceSearchMeters;
internal static ConfigEntry<bool> VerboseLogging;
internal static ConfigEntry<bool> ShowGhostPreview;
internal static ConfigEntry<bool> ShowProgressBar;
internal static void Diag(string message)
{
if (VerboseLogging == null || VerboseLogging.Value)
{
ManualLogSource logger = Logger;
if (logger != null)
{
logger.LogInfo((object)("[DIAG] " + message));
}
}
}
public override void Load()
{
//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
//IL_01b2: Expected O, but got Unknown
//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
//IL_01fd: Expected O, but got Unknown
//IL_0238: Unknown result type (might be due to invalid IL or missing references)
//IL_024e: Unknown result type (might be due to invalid IL or missing references)
Logger = ((BasePlugin)this).Log;
ContainerKey = ((BasePlugin)this).Config.Bind<string>("Keys", "ContainerKey", "E", "Key that stores the carried resource pack/consumable into an empty slot of the container in reach. Hold it for ContainerHoldSeconds. Uses raw keyboard state, so it works even if the game's Use action is rebound.");
PlaceKey = ((BasePlugin)this).Config.Bind<string>("Keys", "PlaceKey", "G", "Key that puts the carried resource pack/consumable down on the surface you are looking at. Hold it for PlaceHoldSeconds. Kept off the Interact/Use key so it can never collide with using the pack.");
ContainerHoldSeconds = ((BasePlugin)this).Config.Bind<float>("Interaction", "ContainerHoldSeconds", 0.4f, "Seconds the ContainerKey must be held to store the carried item into a container slot. 0 stores immediately on press. A one-frame key dropout never resets the hold; the action is only cancelled after the key stays up for a quarter second.");
PlaceHoldSeconds = ((BasePlugin)this).Config.Bind<float>("Interaction", "PlaceHoldSeconds", 0.25f, "Seconds the PlaceKey must be held to place the carried item on a surface.");
ContainerReachMeters = ((BasePlugin)this).Config.Bind<float>("Interaction", "ContainerReachMeters", 2f, "Maximum distance at which a container slot can be targeted.");
SurfaceReachMeters = ((BasePlugin)this).Config.Bind<float>("Placement", "SurfaceReachMeters", 3f, "Maximum ray distance for placing the carried item on a world surface.");
SurfaceOffsetMeters = ((BasePlugin)this).Config.Bind<float>("Placement", "SurfaceOffsetMeters", 0.1f, "Minimum lift along the hit normal before the item is spawned. The placement probe then steps further out along the normal until the item's own bounds no longer overlap world geometry, which is what keeps items from clipping into small containers.");
ClearanceSearchMeters = ((BasePlugin)this).Config.Bind<float>("Placement", "ClearanceSearchMeters", 1f, "Maximum distance searched along the hit normal for a position where the carried item does not overlap world geometry. Covers putting an item down on top of a small locker/box.");
ShowGhostPreview = ((BasePlugin)this).Config.Bind<bool>("Feedback", "ShowGhostPreview", true, "Draw a semi-transparent silhouette of the carried item where it is about to be stored or placed.");
ShowProgressBar = ((BasePlugin)this).Config.Bind<bool>("Feedback", "ShowProgressBar", true, "Show the vanilla interaction prompt and its hold timer bar while storing or placing.");
VerboseLogging = ((BasePlugin)this).Config.Bind<bool>("Diagnostics", "VerboseLogging", true, "Write placement/container diagnostics to the BepInEx log. Set to false once the mod behaves as expected.");
ApplyKeyBindings();
ClassInjector.RegisterTypeInIl2Cpp<ResourceContainerSlot>();
ClassInjector.RegisterTypeInIl2Cpp<PlacementController>();
ClassInjector.RegisterTypeInIl2Cpp<UiProbeRunner>();
((BasePlugin)this).AddComponent<UiProbeRunner>();
Harmony val = new Harmony("HawChow.DropItemEverywhere");
try
{
val.PatchAll();
}
catch (Exception ex)
{
Logger.LogError((object)("Harmony PatchAll failed: " + ex));
}
ReportUiProbe("load");
ReportPatchState();
ManualLogSource logger = Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(57, 4, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("DropItemEverywhere");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("1.0.0");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" loaded;");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" container storage key=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<KeyCode>(DropItemKeys.Container);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", surface placement key=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<KeyCode>(DropItemKeys.Place);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
}
logger.LogInfo(val2);
}
private void ApplyKeyBindings()
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
//IL_0014: 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_005f: Expected I4, but got Unknown
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Expected O, but got Unknown
//IL_009a: 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: Expected I4, but got Unknown
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val;
if (DropPolicy.TryParseKeyCode(ContainerKey.Value, out var keyCode))
{
DropItemKeys.Container = (KeyCode)keyCode;
}
else
{
ManualLogSource logger = Logger;
val = new BepInExWarningLogInterpolatedStringHandler(58, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ContainerKey '");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ContainerKey.Value);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' is not a recognised key name; keeping ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>((int)DropItemKeys.Container);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<KeyCode>(DropItemKeys.Container);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
}
logger.LogWarning(val);
}
if (DropPolicy.TryParseKeyCode(PlaceKey.Value, out var keyCode2))
{
DropItemKeys.Place = (KeyCode)keyCode2;
return;
}
ManualLogSource logger2 = Logger;
val = new BepInExWarningLogInterpolatedStringHandler(54, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("PlaceKey '");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(PlaceKey.Value);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' is not a recognised key name; keeping ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>((int)DropItemKeys.Place);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<KeyCode>(DropItemKeys.Place);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(").");
}
logger2.LogWarning(val);
}
private static void ReportPatchState()
{
//IL_0193: Unknown result type (might be due to invalid IL or missing references)
//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
try
{
Diag("patch state: " + PatchState("container.Setup", AccessTools.Method(typeof(LG_WeakResourceContainer), "Setup", (Type[])null, (Type[])null)) + " | " + PatchState("pickup.Setup", AccessTools.Method(typeof(LG_PickupItem_Sync), "Setup", (Type[])null, (Type[])null)) + " | " + PatchState("pickup.OnStateChange", AccessTools.Method(typeof(LG_PickupItem_Sync), "OnStateChange", (Type[])null, (Type[])null)) + " | " + PatchState("storage.SpawnContent", AccessTools.Method(typeof(LG_ResourceContainer_Storage), "SpawnContent", (Type[])null, (Type[])null)) + " | " + PatchState("player.Setup", AccessTools.Method(typeof(LocalPlayerAgent), "Setup", (Type[])null, (Type[])null)) + " | " + PatchState("playerInteraction.UpdateWorldInteractions", AccessTools.Method(typeof(PlayerInteraction), "UpdateWorldInteractions", (Type[])null, (Type[])null)) + " | " + PatchState("pack.UpdateInteraction", AccessTools.Method(typeof(ResourcePackFirstPerson), "UpdateInteraction", (Type[])null, (Type[])null)));
}
catch (Exception ex)
{
Logger.LogError((object)("Failed to report patch state: " + ex));
}
Diag("engine input probe: GetKey reachable=" + DropItemKeys.Probe() + $" container({DropItemKeys.Container})={DropItemKeys.IsHeld(DropItemKeys.Container)}" + $" place({DropItemKeys.Place})={DropItemKeys.IsHeld(DropItemKeys.Place)}");
}
private static string PatchState(string name, MethodBase method)
{
if (method == null)
{
return name + "=missing";
}
Patches patchInfo = Harmony.GetPatchInfo(method);
if (patchInfo == null)
{
return name + "=unpatched";
}
return name + $"=pre:{patchInfo.Prefixes.Count},post:{patchInfo.Postfixes.Count}";
}
internal static void ReportUiProbe(string stage)
{
try
{
string text = "unavailable";
try
{
text = ((GuiManager.InteractionLayer == null) ? "null" : "present");
}
catch (Exception ex)
{
text = "<" + ex.GetType().Name + ">";
}
Diag($"ui probe ({stage}): interactionLayer={text} dropText='{ProbeText(864u)}' buttonText='{ProbeText(827u)}' previewPrefabs={ProbePreviewPrefabs()} useBinding='{ProbeBinding()}'");
}
catch (Exception ex2)
{
Logger.LogError((object)("UI probe (" + stage + ") failed: " + ex2));
}
}
private static string ProbeText(uint textId)
{
try
{
string text = Text.Get(textId);
return string.IsNullOrEmpty(text) ? "<empty>" : text;
}
catch (Exception ex)
{
return "<" + ex.GetType().Name + ">";
}
}
private static string ProbeBinding()
{
try
{
string bindingName = InputMapper.GetBindingName((InputAction)6);
return string.IsNullOrEmpty(bindingName) ? "<empty>" : bindingName;
}
catch (Exception ex)
{
return "<" + ex.GetType().Name + ">";
}
}
private static int ProbePreviewPrefabs()
{
try
{
Il2CppReferenceArray<Dictionary<uint, List<GameObject>>> loadedPrefabsPerItemMode = ItemSpawnManager.m_loadedPrefabsPerItemMode;
if (loadedPrefabsPerItemMode == null || ((Il2CppArrayBase<Dictionary<uint, List<GameObject>>>)(object)loadedPrefabsPerItemMode).Length <= 2 || ((Il2CppArrayBase<Dictionary<uint, List<GameObject>>>)(object)loadedPrefabsPerItemMode)[2] == null)
{
return -1;
}
return ((Il2CppArrayBase<Dictionary<uint, List<GameObject>>>)(object)loadedPrefabsPerItemMode)[2].Count;
}
catch (Exception ex)
{
Logger.LogError((object)("Preview prefab probe failed: " + ex));
return -2;
}
}
}
[HarmonyPatch(typeof(LG_WeakResourceContainer), "Setup")]
internal static class WeakResourceContainerSetupPatch
{
[HarmonyPostfix]
private static void Postfix(LG_WeakResourceContainer __instance)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
try
{
SlotRegistry.CreateSlots(__instance);
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(44, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to create container placement slots: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
logger.LogError(val);
}
}
}
[HarmonyPatch(typeof(LG_PickupItem_Sync), "Setup")]
internal static class PickupItemSetupPatch
{
[HarmonyPostfix]
private static void Postfix(LG_PickupItem_Sync __instance)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
try
{
SlotRegistry.OnItemSetup(__instance);
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(58, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to associate a spawned item with a container slot: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
logger.LogError(val);
}
}
}
[HarmonyPatch(typeof(LG_PickupItem_Sync), "OnStateChange")]
internal static class PickupItemStatePatch
{
[HarmonyPrefix]
private static void Prefix(LG_PickupItem_Sync __instance, pPickupItemState newState)
{
//IL_0001: 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_001a: Expected O, but got Unknown
try
{
SlotRegistry.BeforeItemStateChange(__instance, newState);
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(56, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to update container-slot state before item sync: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
logger.LogError(val);
}
}
[HarmonyPostfix]
private static void Postfix(LG_PickupItem_Sync __instance, pPickupItemState newState)
{
//IL_0001: 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_001a: Expected O, but got Unknown
try
{
SlotRegistry.AfterItemStateChange(__instance, newState);
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(55, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to update container-slot state after item sync: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
logger.LogError(val);
}
}
}
[HarmonyPatch(typeof(LG_ResourceContainer_Storage), "SpawnContent")]
internal static class ResourceContainerContentSpawnPatch
{
[HarmonyPostfix]
private static void Postfix(LG_ResourceContainer_Storage __instance)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
try
{
SlotRegistry.OnStorageContentSpawned(__instance);
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(47, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to initialize existing container items: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
logger.LogError(val);
}
}
}
[HarmonyPatch(typeof(LocalPlayerAgent), "Setup")]
internal static class LocalPlayerSetupPatch
{
[HarmonyPostfix]
private static void Postfix(LocalPlayerAgent __instance)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Expected O, but got Unknown
try
{
GameObject gameObject = ((Component)__instance).gameObject;
if ((Object)(object)gameObject.GetComponent<PlacementController>() == (Object)null)
{
gameObject.AddComponent<PlacementController>().Agent = __instance;
Plugin.Diag("PlacementController attached to the local player.");
}
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(43, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to attach the placement controller: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
logger.LogError(val);
}
}
}
[HarmonyPatch(typeof(PlayerInteraction), "UpdateWorldInteractions")]
internal static class PlayerInteractionBlockPatch
{
[HarmonyPrefix]
private static bool Prefix()
{
return !VanillaInteractionGuard.ShouldBlock();
}
}
[HarmonyPatch(typeof(ResourcePackFirstPerson), "UpdateInteraction")]
internal static class ResourcePackInteractionBlockPatch
{
[HarmonyPrefix]
private static bool Prefix()
{
return !VanillaInteractionGuard.ShouldBlock();
}
}
namespace HawChow.DropItemEverywhere;
internal static class DropItemKeys
{
internal static KeyCode Container = (KeyCode)101;
internal static KeyCode Place = (KeyCode)103;
private static bool _inputUnavailable;
internal static bool IsHeld(KeyCode key)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected O, but got Unknown
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
if (_inputUnavailable)
{
return false;
}
try
{
return Input.GetKey(key);
}
catch (Exception ex)
{
_inputUnavailable = true;
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(84, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("UnityEngine.Input.GetKey(");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<KeyCode>(key);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(") is unavailable; drop keys are disabled for this session: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
logger.LogError(val);
}
return false;
}
}
internal static bool Probe()
{
try
{
Input.GetKey((KeyCode)0);
return true;
}
catch (Exception ex)
{
_inputUnavailable = true;
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
logger.LogError((object)("UnityEngine.Input is not reachable in this build; drop keys are disabled: " + ex));
}
return false;
}
}
}
internal static class DropPolicy
{
internal const int ResourcePackSlot = 4;
internal const int ConsumableSlot = 5;
internal const int KeycardSlot = 7;
internal const float MinHalfExtent = 0.03f;
internal const float MaxHalfExtent = 0.35f;
private const int KeyCodeA = 97;
private const int KeyCodeAlpha0 = 48;
private const int KeyCodeF1 = 282;
private const float SurfaceFacingThreshold = -0.05f;
internal static bool IsSupportedSlot(int slot)
{
if (slot != 4 && slot != 5)
{
return slot == 7;
}
return true;
}
internal static bool IsValidSurfaceNormal(float x, float y, float z)
{
return x * x + y * y + z * z > 0.0001f;
}
internal static bool IsSurfaceVisible(float normalX, float normalY, float normalZ, float forwardX, float forwardY, float forwardZ)
{
return normalX * forwardX + normalY * forwardY + normalZ * forwardZ < -0.05f;
}
internal static float ClampHalfExtent(float value)
{
if (value < 0.03f)
{
return 0.03f;
}
if (!(value > 0.35f))
{
return value;
}
return 0.35f;
}
internal static float ProgressFraction(float heldSeconds, float durationSeconds)
{
if (durationSeconds <= 0.0001f)
{
return 1f;
}
float num = heldSeconds / durationSeconds;
if (num < 0f)
{
return 0f;
}
if (!(num > 1f))
{
return num;
}
return 1f;
}
internal static bool IsHoldCancelled(float releasedSeconds, float graceSeconds)
{
return releasedSeconds >= graceSeconds;
}
internal static bool CanDeposit(int itemSlot, bool slotHasMatchingAnchor, bool containerOpen, bool slotEmpty, bool itemAllowsInteraction, bool packUseActive)
{
if (IsSupportedSlot(itemSlot) && slotHasMatchingAnchor && containerOpen && slotEmpty && itemAllowsInteraction)
{
return !packUseActive;
}
return false;
}
internal static bool CanPlaceOnSurface(int itemSlot, bool hasSurfaceHit, bool surfaceFacesCamera, bool placementRayBlocked, bool itemAllowsInteraction, bool packUseActive)
{
if (IsSupportedSlot(itemSlot) && hasSurfaceHit && surfaceFacesCamera && !placementRayBlocked && itemAllowsInteraction)
{
return !packUseActive;
}
return false;
}
internal static bool ShouldBlockVanillaInteractions(bool supportedItemWielded, bool itemUsable, bool validDepositTarget)
{
return supportedItemWielded && itemUsable && validDepositTarget;
}
internal static bool TryParseKeyCode(string text, out int keyCode)
{
keyCode = 0;
if (string.IsNullOrWhiteSpace(text))
{
return false;
}
string text2 = text.Trim().ToUpperInvariant();
if (text2.Length == 1)
{
char c = text2[0];
if (c >= 'A' && c <= 'Z')
{
keyCode = 97 + (c - 65);
return true;
}
if (c >= '0' && c <= '9')
{
keyCode = 48 + (c - 48);
return true;
}
return false;
}
int length = text2.Length;
if ((length == 2 || length == 3) && text2[0] == 'F' && int.TryParse(text2.Substring(1), out var result) && result >= 1 && result <= 12)
{
keyCode = 282 + result - 1;
return true;
}
switch (text2)
{
case "SPACE":
keyCode = 32;
return true;
case "TAB":
keyCode = 9;
return true;
case "RETURN":
case "ENTER":
keyCode = 13;
return true;
case "ESCAPE":
case "ESC":
keyCode = 27;
return true;
case "BACKSPACE":
keyCode = 8;
return true;
case "LEFTSHIFT":
keyCode = 304;
return true;
case "LEFTCONTROL":
case "LEFTCTRL":
keyCode = 306;
return true;
case "LEFTALT":
keyCode = 308;
return true;
case "UP":
keyCode = 273;
return true;
case "DOWN":
keyCode = 274;
return true;
case "RIGHT":
keyCode = 275;
return true;
case "LEFT":
keyCode = 276;
return true;
case "MOUSE0":
case "MOUSELEFT":
keyCode = 323;
return true;
case "MOUSE1":
case "MOUSERIGHT":
keyCode = 324;
return true;
case "MOUSE2":
case "MOUSEMIDDLE":
keyCode = 325;
return true;
default:
return false;
}
}
}
internal static class DropPreview
{
private const int PreviewItemMode = 2;
private const float GhostAlpha = 0.25f;
private const float RetrySeconds = 30f;
private static GameObject _ghost;
private static int _ghostItemCrc;
private static float _retryAt;
private static bool _reported;
internal static void Show(ItemEquippable item, Vector3 position, Quaternion rotation)
{
//IL_0065: 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_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
if (Plugin.ShowGhostPreview != null && !Plugin.ShowGhostPreview.Value)
{
Hide();
}
else
{
if (Time.realtimeSinceStartup < _retryAt)
{
return;
}
try
{
if (!TryGetItemCrc(item, out var crc))
{
Hide();
return;
}
if ((Object)(object)_ghost == (Object)null || _ghostItemCrc != crc)
{
Hide();
GameObject val = ResolvePrefab(crc);
if ((Object)(object)val == (Object)null)
{
return;
}
_ghost = Object.Instantiate<GameObject>(val, position, rotation);
_ghostItemCrc = crc;
ApplyGhostLook(_ghost);
}
Transform transform = _ghost.transform;
transform.position = position;
transform.rotation = rotation;
}
catch (Exception exception)
{
Report("Failed to draw the placement preview: ", exception);
Hide();
}
}
}
internal static void Hide()
{
if ((Object)(object)_ghost == (Object)null)
{
_ghostItemCrc = 0;
return;
}
try
{
Object.Destroy((Object)(object)_ghost);
}
catch (Exception exception)
{
Report("Failed to destroy the placement preview: ", exception);
}
_ghost = null;
_ghostItemCrc = 0;
}
private static bool TryGetItemCrc(ItemEquippable item, out int crc)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
crc = 0;
if ((Object)(object)item == (Object)null)
{
return false;
}
if (((Item)item).ItemDataBlock == null)
{
return false;
}
crc = (int)((Item)item).Get_pItemData().itemID_gearCRC;
return crc != 0;
}
private static GameObject ResolvePrefab(int crc)
{
Il2CppReferenceArray<Dictionary<uint, List<GameObject>>> loadedPrefabsPerItemMode = ItemSpawnManager.m_loadedPrefabsPerItemMode;
if (loadedPrefabsPerItemMode == null || ((Il2CppArrayBase<Dictionary<uint, List<GameObject>>>)(object)loadedPrefabsPerItemMode).Length <= 2 || ((Il2CppArrayBase<Dictionary<uint, List<GameObject>>>)(object)loadedPrefabsPerItemMode)[2] == null)
{
return null;
}
List<GameObject> val = ((Il2CppArrayBase<Dictionary<uint, List<GameObject>>>)(object)loadedPrefabsPerItemMode)[2][(uint)crc];
if (val == null || val.Count < 1)
{
return null;
}
return val[0];
}
private static void ApplyGhostLook(GameObject ghost)
{
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
Shader val = Shader.Find("Transparent/Diffuse");
Il2CppArrayBase<Renderer> componentsInChildren = ghost.GetComponentsInChildren<Renderer>(true);
for (int i = 0; i < componentsInChildren.Length; i++)
{
Renderer val2 = componentsInChildren[i];
if ((Object)(object)val2 == (Object)null)
{
continue;
}
val2.shadowCastingMode = (ShadowCastingMode)0;
val2.receiveShadows = false;
Il2CppReferenceArray<Material> materials = val2.materials;
for (int j = 0; j < ((Il2CppArrayBase<Material>)(object)materials).Length; j++)
{
Material val3 = ((Il2CppArrayBase<Material>)(object)materials)[j];
if (!((Object)(object)val3 == (Object)null))
{
if ((Object)(object)val != (Object)null)
{
val3.shader = val;
}
Color black = Color.black;
val3.color = ((Color)(ref black)).AlphaMultiplied(0.25f);
}
}
}
}
private static void Report(string prefix, Exception exception)
{
_retryAt = Time.realtimeSinceStartup + 30f;
if (!_reported)
{
_reported = true;
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
logger.LogError((object)(prefix + exception));
}
}
}
}
internal static class InteractionPrompt
{
private const uint DropItemTextId = 864u;
private const uint ButtonPromptTextId = 827u;
private const float RetrySeconds = 30f;
private static bool _active;
private static float _retryAt;
private static bool _reported;
internal static void Show(string itemName, string buttonName, float fraction)
{
if ((Plugin.ShowProgressBar != null && !Plugin.ShowProgressBar.Value) || Time.realtimeSinceStartup < _retryAt)
{
return;
}
try
{
GuiManager.InteractionLayer.InteractPromptVisible = true;
GuiManager.InteractionLayer.SetInteractPrompt(BuildMessage(itemName), BuildButton(buttonName), (ePUIMessageStyle)0);
GuiManager.InteractionLayer.SetTimer(Mathf.Clamp01(fraction));
_active = true;
}
catch (Exception exception)
{
Report(exception);
}
}
internal static void Hide()
{
if (!_active)
{
return;
}
_active = false;
try
{
GuiManager.InteractionLayer.InteractPromptVisible = false;
GuiManager.InteractionLayer.SetInteractPrompt(string.Empty, string.Empty, (ePUIMessageStyle)0);
}
catch (Exception exception)
{
Report(exception);
}
}
private static string BuildMessage(string itemName)
{
string text = TextOrFallback(864u);
try
{
return string.Format(text, itemName);
}
catch (FormatException)
{
return (text + " " + itemName).Trim();
}
}
private static string BuildButton(string buttonName)
{
string text = TextOrFallback(827u);
try
{
return string.Format(text, buttonName);
}
catch (FormatException)
{
return (buttonName + " " + text).Trim();
}
}
private static string TextOrFallback(uint textId)
{
try
{
string text = Text.Get(textId);
if (!string.IsNullOrEmpty(text))
{
return text;
}
}
catch (Exception exception)
{
Report(exception);
}
if (textId != 864)
{
return "[{0}]";
}
return "{0}";
}
private static void Report(Exception exception)
{
_active = false;
_retryAt = Time.realtimeSinceStartup + 30f;
if (!_reported)
{
_reported = true;
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
logger.LogError((object)("The vanilla interaction prompt is unavailable; the drop actions keep working without a progress bar: " + exception));
}
}
}
}
internal static class ItemDropper
{
internal static bool TryGetInventorySlot(ItemEquippable item, out InventorySlot inventorySlot)
{
if ((Object)(object)item == (Object)null)
{
inventorySlot = (InventorySlot)0;
return false;
}
return TryGetInventorySlot((Item)(object)item, out inventorySlot);
}
internal static bool TryGetInventorySlot(Item item, out InventorySlot inventorySlot)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
inventorySlot = (InventorySlot)0;
if ((Object)(object)item == (Object)null || item.ItemDataBlock == null)
{
return false;
}
int num = (((Object)(object)((Il2CppObjectBase)item).TryCast<ArtifactPickup_Core>() != (Object)null) ? 7 : ((int)item.ItemDataBlock.inventorySlot));
if (!DropPolicy.IsSupportedSlot(num))
{
return false;
}
inventorySlot = (InventorySlot)(byte)num;
return true;
}
internal static bool IsPackUseActive(ItemEquippable item)
{
if ((Object)(object)item == (Object)null)
{
return false;
}
ResourcePackFirstPerson val = ((Il2CppObjectBase)item).TryCast<ResourcePackFirstPerson>();
if ((Object)(object)val != (Object)null && (Object)(object)val.m_interactApplyResource != (Object)null)
{
return ((Interact_Timed)val.m_interactApplyResource).TimerIsActive;
}
return false;
}
internal static bool IsItemUsable(ItemEquippable item)
{
if ((Object)(object)item != (Object)null && item.AllowPlayerInteraction)
{
return !IsPackUseActive(item);
}
return false;
}
internal static bool TryDropToContainer(PlayerAgent player, ContainerSlotState slot, out string failure)
{
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_012b: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0131: Unknown result type (might be due to invalid IL or missing references)
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: 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_0149: Unknown result type (might be due to invalid IL or missing references)
failure = null;
if ((Object)(object)player == (Object)null || (Object)(object)player.Inventory == (Object)null || slot == null)
{
failure = "missing player/inventory/slot";
return false;
}
ItemEquippable wieldedItem = player.Inventory.WieldedItem;
if (!TryGetInventorySlot(wieldedItem, out var inventorySlot))
{
failure = "unsupported wielded item (" + (((Object)(object)wieldedItem == (Object)null) ? "null" : ((Item)wieldedItem).PublicName) + ")";
return false;
}
if (!slot.IsOpen)
{
failure = "container is not open";
return false;
}
if (!slot.TryGetAnchor(inventorySlot, out var anchor))
{
failure = $"slot {slot.SlotIndex} has no anchor for {inventorySlot}";
return false;
}
if (!slot.IsEmptyFor())
{
failure = $"slot {slot.SlotIndex} is occupied";
return false;
}
if (!IsItemUsable(wieldedItem))
{
failure = "wielded item cannot be interacted with right now";
return false;
}
if (!TryGetPickupSync(wieldedItem, out var sync))
{
failure = "no synchronized pickup component for the carried item";
return false;
}
pItemData_Custom val = CopyRemainingAmmo(sync.GetCustomData(), inventorySlot);
sync.AttemptPickupInteraction((ePickupItemInteractionType)1, player.Owner, val, anchor.position, anchor.rotation, slot.Container.SpawnNode, false, false);
return true;
}
internal static bool TryDropToSurface(PlayerAgent player, Vector3 position, Quaternion rotation, out string failure)
{
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
failure = null;
if ((Object)(object)player == (Object)null || (Object)(object)player.Inventory == (Object)null)
{
failure = "missing player/inventory";
return false;
}
if (((Agent)player).CourseNode == null)
{
failure = "player has no course node";
return false;
}
ItemEquippable wieldedItem = player.Inventory.WieldedItem;
if (!TryGetInventorySlot(wieldedItem, out var inventorySlot))
{
failure = "unsupported wielded item (" + (((Object)(object)wieldedItem == (Object)null) ? "null" : ((Item)wieldedItem).PublicName) + ")";
return false;
}
if (!IsItemUsable(wieldedItem))
{
failure = "wielded item cannot be interacted with right now";
return false;
}
if (!TryGetPickupSync(wieldedItem, out var sync))
{
failure = "no synchronized pickup component for the carried item";
return false;
}
pItemData_Custom val = CopyRemainingAmmo(sync.GetCustomData(), inventorySlot);
sync.AttemptPickupInteraction((ePickupItemInteractionType)1, player.Owner, val, position, rotation, ((Agent)player).CourseNode, true, false);
return true;
}
private static bool TryGetPickupSync(ItemEquippable wieldedItem, out iPickupItemSync sync)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
sync = null;
if ((Object)(object)wieldedItem == (Object)null)
{
return false;
}
Item val = default(Item);
if (!PlayerBackpackManager.TryGetItemInLevelFromItemData(((Item)wieldedItem).Get_pItemData(), ref val))
{
return false;
}
ItemInLevel val2 = ((Il2CppObjectBase)val).TryCast<ItemInLevel>();
if ((Object)(object)val2 == (Object)null)
{
return false;
}
sync = val2.GetSyncComponent();
return sync != null;
}
private static pItemData_Custom CopyRemainingAmmo(pItemData_Custom customData, InventorySlot inventorySlot)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Expected I4, but got Unknown
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
int num = (int)inventorySlot;
if (num != 4 && num != 5)
{
return customData;
}
PlayerBackpack localBackpack = PlayerBackpackManager.LocalBackpack;
if (((localBackpack != null) ? localBackpack.AmmoStorage : null) != null)
{
customData.ammo = localBackpack.AmmoStorage.GetInventorySlotAmmo(inventorySlot).AmmoInPack;
}
return customData;
}
}
public sealed class PlacementController : MonoBehaviour
{
private const float MinHoldSeconds = 0.05f;
private const float MaxHoldSeconds = 3f;
private const float ReleaseGraceSeconds = 0.25f;
private const float AttemptCooldownSeconds = 0.75f;
private const float ClearanceStepMeters = 0.05f;
private const float FallbackHalfExtent = 0.12f;
private static PlacementController _instance;
private static bool _inputProbed;
private bool _containerArmed;
private bool _containerConsumed;
private float _containerCooldown;
private float _containerHeldSeconds;
private float _containerReleaseSeconds;
private bool _placeArmed;
private bool _placeConsumed;
private float _placeHeldSeconds;
private float _placeReleaseSeconds;
public LocalPlayerAgent Agent;
public PlacementController(IntPtr pointer)
: base(pointer)
{
}
internal static bool TryGetAgent(out LocalPlayerAgent agent)
{
agent = (((Object)(object)_instance == (Object)null) ? null : _instance.Agent);
return (Object)(object)agent != (Object)null;
}
private void Awake()
{
_instance = this;
}
private void OnDestroy()
{
if ((Object)(object)_instance == (Object)(object)this)
{
_instance = null;
}
HideAllFeedback();
ResetContainer();
ResetPlace();
}
private void Update()
{
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Expected I4, but got Unknown
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Expected I4, but got Unknown
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_instance == (Object)null)
{
_instance = this;
}
LocalPlayerAgent agent = Agent;
if ((Object)(object)agent == (Object)null || !((Agent)agent).IsLocallyOwned || Time.deltaTime <= 0f)
{
if (_containerArmed || _placeArmed)
{
Plugin.Diag($"hold reset: agent={(Object)(object)agent != (Object)null} owned={(Object)(object)agent != (Object)null && ((Agent)agent).IsLocallyOwned} deltaTime={Time.deltaTime:F4}");
}
HideAllFeedback();
ResetContainer();
ResetPlace();
return;
}
if (!_inputProbed)
{
_inputProbed = true;
Plugin.Diag($"input probe: UnityEngine.Input reachable={DropItemKeys.Probe()} containerKey={(int)DropItemKeys.Container}/{DropItemKeys.Container} placeKey={(int)DropItemKeys.Place}/{DropItemKeys.Place}.");
Plugin.ReportUiProbe("in-game");
}
UpdateContainer(agent);
UpdatePlace(agent);
}
private void UpdateContainer(LocalPlayerAgent agent)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_029b: Unknown result type (might be due to invalid IL or missing references)
//IL_02a2: 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)
if (_containerCooldown > 0f)
{
_containerCooldown -= Time.deltaTime;
}
bool flag = DropItemKeys.IsHeld(DropItemKeys.Container);
if (flag)
{
_containerReleaseSeconds = 0f;
}
else if (_containerArmed)
{
_containerReleaseSeconds += Time.deltaTime;
if (DropPolicy.IsHoldCancelled(_containerReleaseSeconds, 0.25f))
{
Plugin.Diag($"E hold cancelled: the key stayed up {_containerReleaseSeconds:F2}s (progress {_containerHeldSeconds:F2}s).");
CancelContainer();
return;
}
flag = true;
}
ItemEquippable item = (((Object)(object)((PlayerAgent)agent).Inventory == (Object)null) ? null : ((PlayerAgent)agent).Inventory.WieldedItem);
ContainerSlotState slot;
Transform anchor;
string reason;
bool flag2 = TryGetDepositTarget(agent, item, out slot, out anchor, out reason);
if (flag)
{
if (!_containerArmed && _containerCooldown <= 0f)
{
_containerArmed = true;
_containerConsumed = false;
_containerHeldSeconds = 0f;
DescribePress(agent, "E");
}
if (!_containerArmed || _containerConsumed || _containerCooldown > 0f)
{
return;
}
if (!flag2)
{
_containerConsumed = true;
HideAllFeedback();
Plugin.Diag("E hold cancelled: " + reason);
return;
}
float num = Mathf.Clamp(Plugin.ContainerHoldSeconds.Value, 0f, 3f);
_containerHeldSeconds += Time.deltaTime;
float fraction = DropPolicy.ProgressFraction(_containerHeldSeconds, num);
DropPreview.Show(item, anchor.position, anchor.rotation);
InteractionPrompt.Show(ItemName(item), UseBindingName(), fraction);
if (!(_containerHeldSeconds < num))
{
_containerConsumed = true;
_containerCooldown = 0.75f;
HideAllFeedback();
if (ItemDropper.TryDropToContainer((PlayerAgent)(object)agent, slot, out var failure))
{
Plugin.Diag($"stored the carried item in container slot {slot.SlotIndex} after {_containerHeldSeconds:F2}s (E).");
}
else
{
Plugin.Diag("container deposit failed: " + failure);
}
}
}
else if (_containerCooldown <= 0f && flag2)
{
DropPreview.Show(item, anchor.position, anchor.rotation);
InteractionPrompt.Show(ItemName(item), UseBindingName(), 0f);
}
else
{
HideAllFeedback();
}
}
private void UpdatePlace(LocalPlayerAgent agent)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_0182: Unknown result type (might be due to invalid IL or missing references)
//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
bool flag = DropItemKeys.IsHeld(DropItemKeys.Place);
if (flag)
{
_placeReleaseSeconds = 0f;
}
else if (_placeArmed)
{
_placeReleaseSeconds += Time.deltaTime;
if (DropPolicy.IsHoldCancelled(_placeReleaseSeconds, 0.25f))
{
Plugin.Diag($"G hold cancelled: the key stayed up {_placeReleaseSeconds:F2}s (progress {_placeHeldSeconds:F2}s).");
CancelPlace();
return;
}
flag = true;
}
if (!flag)
{
return;
}
if (!_placeArmed)
{
_placeArmed = true;
_placeConsumed = false;
_placeHeldSeconds = 0f;
DescribePress(agent, "G");
}
if (_placeConsumed)
{
return;
}
ItemEquippable item = (((Object)(object)((PlayerAgent)agent).Inventory == (Object)null) ? null : ((PlayerAgent)agent).Inventory.WieldedItem);
if (!TryGetSurfaceTarget(agent, item, out var position, out var rotation, out var reason))
{
_placeConsumed = true;
HidePlacementFeedback();
Plugin.Diag("G hold cancelled: " + reason);
return;
}
float num = Mathf.Clamp(Plugin.PlaceHoldSeconds.Value, 0.05f, 3f);
_placeHeldSeconds += Time.deltaTime;
float fraction = DropPolicy.ProgressFraction(_placeHeldSeconds, num);
DropPreview.Show(item, position, rotation);
InteractionPrompt.Show(ItemName(item), PlaceBindingName(), fraction);
if (!(_placeHeldSeconds < num))
{
_placeConsumed = true;
HideAllFeedback();
if (ItemDropper.TryDropToSurface((PlayerAgent)(object)agent, position, rotation, out var failure))
{
Plugin.Diag($"placed the carried item on a surface after {_placeHeldSeconds:F2}s (G) at {position} lift={SurfaceProbe.LastOffset:F2}m mask={SurfaceProbe.LastSource}.");
}
else
{
Plugin.Diag("surface placement failed: " + failure);
}
}
}
private static string ItemName(ItemEquippable item)
{
if (!((Object)(object)item == (Object)null))
{
return ((Item)item).PublicName;
}
return string.Empty;
}
private static string UseBindingName()
{
string value = Plugin.ContainerKey.Value;
if (!string.IsNullOrEmpty(value))
{
return value.Trim().ToUpperInvariant();
}
return "E";
}
private static string PlaceBindingName()
{
string value = Plugin.PlaceKey.Value;
if (!string.IsNullOrEmpty(value))
{
return value.Trim().ToUpperInvariant();
}
return "G";
}
private static void HideAllFeedback()
{
DropPreview.Hide();
InteractionPrompt.Hide();
}
private static void HidePlacementFeedback()
{
DropPreview.Hide();
InteractionPrompt.Hide();
}
private unsafe void DescribePress(LocalPlayerAgent agent, string key)
{
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Expected I4, but got Unknown
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
ItemEquippable val = (((Object)(object)((PlayerAgent)agent).Inventory == (Object)null) ? null : ((PlayerAgent)agent).Inventory.WieldedItem);
InventorySlot inventorySlot;
bool flag = ItemDropper.TryGetInventorySlot(val, out inventorySlot);
string value = (((Object)(object)val == (Object)null) ? "null" : ((Item)val).PublicName);
string value2 = (((Object)(object)val == (Object)null || ((Item)val).ItemDataBlock == null) ? "n/a" : ((int)((Item)val).ItemDataBlock.inventorySlot).ToString());
string value3 = (flag ? ((object)(*(InventorySlot*)(&inventorySlot))/*cast due to .constrained prefix*/).ToString() : "n/a");
bool value4 = (Object)(object)((PlayerAgent)agent).Interaction != (Object)null && ((PlayerAgent)agent).Interaction.HasWorldInteraction;
Plugin.Diag($"{key} pressed: focus={((PlayerAgent)agent).InputFilter} item={value} itemDataSlot={value2} recognized={flag} worldInteraction={value4} packUseActive={ItemDropper.IsPackUseActive(val)} carried={value3}");
}
private static bool TryGetDepositTarget(LocalPlayerAgent agent, ItemEquippable item, out ContainerSlotState slot, out Transform anchor, out string reason)
{
//IL_0051: 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_0085: Expected I4, but got Unknown
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
slot = null;
anchor = null;
if (!SlotRegistry.TryGetSlotTarget((PlayerAgent)(object)agent, out var state, out var hit))
{
reason = "no container slot in reach";
return false;
}
if (!ItemDropper.TryGetInventorySlot(item, out var inventorySlot))
{
reason = "the wielded item cannot be stored (item=" + (((Object)(object)item == (Object)null) ? "null" : ((Item)item).PublicName) + ")";
return false;
}
bool slotHasMatchingAnchor = state.TryGetAnchor(inventorySlot, out anchor);
if (!DropPolicy.CanDeposit((int)inventorySlot, slotHasMatchingAnchor, state.IsOpen, state.IsEmptyFor(), (Object)(object)item != (Object)null && item.AllowPlayerInteraction, ItemDropper.IsPackUseActive(item)))
{
reason = state.Describe(inventorySlot) + $" distance={((RaycastHit)(ref hit)).distance:F2}";
return false;
}
slot = state;
reason = null;
return true;
}
private static bool TryGetSurfaceTarget(LocalPlayerAgent agent, ItemEquippable item, out Vector3 position, out Quaternion rotation, out string reason)
{
//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_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_00e5: 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_0173: Unknown result type (might be due to invalid IL or missing references)
//IL_0177: Unknown result type (might be due to invalid IL or missing references)
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Unknown result type (might be due to invalid IL or missing references)
//IL_0185: Unknown result type (might be due to invalid IL or missing references)
//IL_018c: Unknown result type (might be due to invalid IL or missing references)
//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
//IL_01df: Unknown result type (might be due to invalid IL or missing references)
//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
//IL_021e: Unknown result type (might be due to invalid IL or missing references)
//IL_0225: Unknown result type (might be due to invalid IL or missing references)
//IL_022f: Unknown result type (might be due to invalid IL or missing references)
//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_023b: 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_023e: Unknown result type (might be due to invalid IL or missing references)
//IL_0243: Unknown result type (might be due to invalid IL or missing references)
//IL_0253: Unknown result type (might be due to invalid IL or missing references)
//IL_0254: Unknown result type (might be due to invalid IL or missing references)
//IL_0265: Unknown result type (might be due to invalid IL or missing references)
//IL_0287: Expected I4, but got Unknown
//IL_02be: Unknown result type (might be due to invalid IL or missing references)
//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
//IL_02db: Unknown result type (might be due to invalid IL or missing references)
//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
//IL_033b: 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_0342: Unknown result type (might be due to invalid IL or missing references)
//IL_0347: Unknown result type (might be due to invalid IL or missing references)
//IL_034e: Unknown result type (might be due to invalid IL or missing references)
//IL_0353: Unknown result type (might be due to invalid IL or missing references)
//IL_0356: Unknown result type (might be due to invalid IL or missing references)
//IL_035c: Unknown result type (might be due to invalid IL or missing references)
position = Vector3.zero;
rotation = Quaternion.identity;
if ((Object)(object)agent == (Object)null || (Object)(object)((PlayerAgent)agent).FPSCamera == (Object)null)
{
reason = "no camera";
return false;
}
if (!ItemDropper.TryGetInventorySlot(item, out var inventorySlot))
{
reason = "the wielded item cannot be placed (item=" + (((Object)(object)item == (Object)null) ? "null" : ((Item)item).PublicName) + ")";
return false;
}
Vector3 position2 = ((PlayerAgent)agent).FPSCamera.Position;
Vector3 forward = ((PlayerAgent)agent).FPSCamera.Forward;
float num = Mathf.Clamp(Plugin.SurfaceReachMeters.Value, 0.25f, 8f);
int interactionLayerMask = SlotRegistry.InteractionLayerMask;
int num2 = LayerManager.MASK_TRIPMINE_CAMERARAY & ~interactionLayerMask;
RaycastHit val = default(RaycastHit);
bool flag = Physics.Raycast(position2, forward, ref val, num, num2, (QueryTriggerInteraction)1);
string text = (flag ? "tripmine-mask" : "none");
if (!flag)
{
flag = Physics.Raycast(position2 + forward * 0.6f, forward, ref val, Mathf.Max(0.25f, num - 0.6f), ~interactionLayerMask, (QueryTriggerInteraction)1);
text = (flag ? "all-layers-fallback" : "none");
}
if (!flag || (Object)(object)((RaycastHit)(ref val)).collider == (Object)null || ((RaycastHit)(ref val)).collider.isTrigger)
{
SurfaceProbe.LastSource = text + (flag ? "(rejected)" : string.Empty);
reason = "no surface in reach (probe=" + SurfaceProbe.LastSource + ")";
return false;
}
Vector3 val2 = ((RaycastHit)(ref val)).normal;
Vector3 normalized = ((Vector3)(ref val2)).normalized;
if (!DropPolicy.IsValidSurfaceNormal(normalized.x, normalized.y, normalized.z))
{
SurfaceProbe.LastSource = text + "(bad-normal)";
reason = "surface normal is degenerate (probe=" + SurfaceProbe.LastSource + ")";
return false;
}
if (!DropPolicy.IsSurfaceVisible(normalized.x, normalized.y, normalized.z, forward.x, forward.y, forward.z))
{
SurfaceProbe.LastSource = text + "(back-face)";
reason = "the surface faces away from you, so it is the inside of something (probe=" + SurfaceProbe.LastSource + ")";
return false;
}
Vector3 val3 = ((RaycastHit)(ref val)).point - ((Vector3)(ref forward)).normalized * 0.05f;
val2 = val3 - position2;
bool flag2 = ((Vector3)(ref val2)).sqrMagnitude > 0.01f && Physics.Linecast(position2, val3, LayerManager.MASK_TRIPMINE_PLACEMENT_BLOCKERS);
if (!DropPolicy.CanPlaceOnSurface((int)inventorySlot, hasSurfaceHit: true, surfaceFacesCamera: true, flag2, (Object)(object)item != (Object)null && item.AllowPlayerInteraction, ItemDropper.IsPackUseActive(item)))
{
SurfaceProbe.LastSource = text + (flag2 ? "(blocked)" : "(item-gate)");
reason = "surface placement rejected (probe=" + SurfaceProbe.LastSource + ")";
return false;
}
Vector3 val4 = Vector3.ProjectOnPlane(forward, normalized);
if (((Vector3)(ref val4)).sqrMagnitude < 0.0001f)
{
val4 = Vector3.ProjectOnPlane(Vector3.forward, normalized);
}
if (((Vector3)(ref val4)).sqrMagnitude < 0.0001f)
{
val4 = Vector3.ProjectOnPlane(Vector3.right, normalized);
}
if (((Vector3)(ref val4)).sqrMagnitude < 0.0001f)
{
SurfaceProbe.LastSource = text + "(no-forward)";
reason = "no stable rotation for this surface (probe=" + SurfaceProbe.LastSource + ")";
return false;
}
rotation = Quaternion.LookRotation(((Vector3)(ref val4)).normalized, normalized);
if (!TryFindClearSpot(((RaycastHit)(ref val)).point, normalized, rotation, EstimateItemHalfExtents(item), out position, out var lift, out reason))
{
return false;
}
SurfaceProbe.LastOffset = lift;
SurfaceProbe.LastSource = text;
reason = null;
return true;
}
private static bool TryFindClearSpot(Vector3 hitPoint, Vector3 normal, Quaternion rotation, Vector3 halfExtents, out Vector3 position, out float lift, out string reason)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//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_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: 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_004f: 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_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
float num = Mathf.Clamp(Plugin.SurfaceOffsetMeters.Value, 0.02f, 0.5f);
float num2 = Mathf.Clamp(Plugin.ClearanceSearchMeters.Value, num, 2.5f);
Vector3 val = halfExtents * 0.9f;
for (float num3 = num; num3 <= num2 + 0.0001f; num3 += 0.05f)
{
Vector3 val2 = hitPoint + normal * num3;
bool flag;
try
{
flag = Physics.CheckBox(val2, val, rotation, LayerManager.MASK_TRIPMINE_PLACEMENT_BLOCKERS, (QueryTriggerInteraction)1);
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
logger.LogError((object)("Clearance probe failed; falling back to the plain surface offset: " + ex));
}
flag = false;
}
if (!flag)
{
position = val2;
lift = num3;
reason = null;
return true;
}
}
position = hitPoint + normal * num;
lift = num;
reason = $"no clear space within {num2:F2} m of the surface, the item would clip (probe={SurfaceProbe.LastSource})";
return false;
}
private static Vector3 EstimateItemHalfExtents(ItemEquippable item)
{
//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_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: 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_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: 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_0055: 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_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: 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_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: 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_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: 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_0167: 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_0175: Unknown result type (might be due to invalid IL or missing references)
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
//IL_018a: Unknown result type (might be due to invalid IL or missing references)
//IL_018f: 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_01e9: Unknown result type (might be due to invalid IL or missing references)
//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
//IL_020b: Unknown result type (might be due to invalid IL or missing references)
//IL_01d2: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: 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_00f9: 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)
//IL_0113: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = Vector3.zero;
bool flag = false;
try
{
Il2CppArrayBase<Renderer> componentsInChildren = ((Component)item).GetComponentsInChildren<Renderer>(true);
Vector3 val2 = Vector3.zero;
Vector3 val3 = Vector3.zero;
Vector3 val5 = default(Vector3);
Vector3 val6 = default(Vector3);
for (int i = 0; i < componentsInChildren.Length; i++)
{
Renderer val4 = componentsInChildren[i];
if (!((Object)(object)val4 == (Object)null))
{
Bounds bounds = val4.bounds;
Vector3 center = ((Bounds)(ref bounds)).center;
Vector3 extents = ((Bounds)(ref bounds)).extents;
((Vector3)(ref val5))..ctor(center.x - extents.x, center.y - extents.y, center.z - extents.z);
((Vector3)(ref val6))..ctor(center.x + extents.x, center.y + extents.y, center.z + extents.z);
if (!flag)
{
val2 = val5;
val3 = val6;
flag = true;
}
else
{
((Vector3)(ref val2))..ctor(Mathf.Min(val2.x, val5.x), Mathf.Min(val2.y, val5.y), Mathf.Min(val2.z, val5.z));
((Vector3)(ref val3))..ctor(Mathf.Max(val3.x, val6.x), Mathf.Max(val3.y, val6.y), Mathf.Max(val3.z, val6.z));
}
}
}
if (flag)
{
val = new Vector3(val3.x - val2.x, val3.y - val2.y, val3.z - val2.z);
}
}
catch (Exception ex)
{
flag = false;
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
logger.LogError((object)("Failed to measure the carried item; using the default clearance box: " + ex));
}
}
if (!flag)
{
return new Vector3(0.12f, 0.12f, 0.12f);
}
return new Vector3(DropPolicy.ClampHalfExtent(val.x * 0.5f), DropPolicy.ClampHalfExtent(val.y * 0.5f), DropPolicy.ClampHalfExtent(val.z * 0.5f));
}
private void CancelContainer()
{
HideAllFeedback();
ResetContainer();
}
private void CancelPlace()
{
HideAllFeedback();
ResetPlace();
}
private void ResetContainer()
{
_containerArmed = false;
_containerConsumed = false;
_containerHeldSeconds = 0f;
_containerReleaseSeconds = 0f;
}
private void ResetPlace()
{
_placeArmed = false;
_placeConsumed = false;
_placeHeldSeconds = 0f;
_placeReleaseSeconds = 0f;
}
}
internal static class SurfaceProbe
{
internal static string LastSource = "none";
internal static float LastOffset;
}
internal static class VanillaInteractionGuard
{
internal static bool ShouldBlock()
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Expected I4, but got Unknown
try
{
if (!PlacementController.TryGetAgent(out var agent) || (Object)(object)((PlayerAgent)agent).Inventory == (Object)null)
{
return false;
}
ItemEquippable wieldedItem = ((PlayerAgent)agent).Inventory.WieldedItem;
if (!ItemDropper.TryGetInventorySlot(wieldedItem, out var inventorySlot))
{
return false;
}
if (!SlotRegistry.TryGetSlotTarget((PlayerAgent)(object)agent, out var state, out var _))
{
return false;
}
Transform anchor;
bool validDepositTarget = DropPolicy.CanDeposit((int)inventorySlot, state.TryGetAnchor(inventorySlot, out anchor), state.IsOpen, state.IsEmptyFor(), (Object)(object)wieldedItem != (Object)null && wieldedItem.AllowPlayerInteraction, ItemDropper.IsPackUseActive(wieldedItem));
return DropPolicy.ShouldBlockVanillaInteractions(supportedItemWielded: true, (Object)(object)wieldedItem != (Object)null && wieldedItem.AllowPlayerInteraction, validDepositTarget);
}
catch (Exception ex)
{
ManualLogSource logger = Plugin.Logger;
if (logger != null)
{
logger.LogError((object)("Vanilla interaction guard failed: " + ex));
}
return false;
}
}
}
internal static class PluginInfo
{
internal const string Guid = "HawChow.DropItemEverywhere";
internal const string Name = "DropItemEverywhere";
internal const string Version = "1.0.0";
}
public sealed class ResourceContainerSlot : MonoBehaviour
{
public ResourceContainerSlot(IntPtr pointer)
: base(pointer)
{
}
private void OnDestroy()
{
SlotRegistry.Unregister(this);
}
}
internal sealed class ContainerSlotState
{
private readonly Dictionary<IntPtr, LG_PickupItem_Sync> _items = new Dictionary<IntPtr, LG_PickupItem_Sync>();
internal ResourceContainerSlot Marker { get; }
internal LG_WeakResourceContainer Container { get; }
internal LG_ResourceContainer_Storage Storage { get; }
internal StorageSlot StorageSlot { get; }
internal int SlotIndex { get; }
internal IEnumerable<LG_PickupItem_Sync> Items => _items.Values;
internal bool IsOpen
{
get
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Invalid comparison between Unknown and I4
if ((Object)(object)Container == (Object)null)
{
return false;
}
if (Container.ISOpen)
{
return true;
}
iResourceContainerGraphics graphics = Container.m_graphics;
LG_WeakResourceContainer_Graphics val = ((graphics == null) ? null : ((Il2CppObjectBase)graphics).TryCast<LG_WeakResourceContainer_Graphics>());
if ((Object)(object)val != (Object)null)
{
return (int)val.m_status == 3;
}
return false;
}
}
internal bool HasAnyAnchor
{
get
{
if (StorageSlot != null)
{
if (!((Object)(object)StorageSlot.ResourcePack != (Object)null) && !((Object)(object)StorageSlot.Consumable != (Object)null))
{
return (Object)(object)StorageSlot.Keycard != (Object)null;
}
return true;
}
return false;
}
}
internal ContainerSlotState(ResourceContainerSlot marker, LG_WeakResourceContainer container, LG_ResourceContainer_Storage storage, StorageSlot slot, int slotIndex)
{
Marker = marker;
Container = container;
Storage = storage;
StorageSlot = slot;
SlotIndex = slotIndex;
}
internal bool TryGetAnchor(InventorySlot inventorySlot, out Transform anchor)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Expected I4, but got Unknown
switch ((int)inventorySlot)
{
case 4:
{
StorageSlot storageSlot3 = StorageSlot;
anchor = ((storageSlot3 != null) ? storageSlot3.ResourcePack : null);
return (Object)(object)anchor != (Object)null;
}
case 5:
{
StorageSlot storageSlot2 = StorageSlot;
anchor = ((storageSlot2 != null) ? storageSlot2.Consumable : null);
return (Object)(object)anchor != (Object)null;
}
case 7:
{
StorageSlot storageSlot = StorageSlot;
anchor = ((storageSlot != null) ? storageSlot.Keycard : null);
return (Object)(object)anchor != (Object)null;
}
default:
anchor = null;
return false;
}
}
internal Transform GetAnchor(InventorySlot inventorySlot)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
if (!TryGetAnchor(inventorySlot, out var anchor))
{
return null;
}
return anchor;
}
internal bool IsEmptyFor(LG_PickupItem_Sync itemBeingPlaced = null)
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
foreach (KeyValuePair<IntPtr, LG_PickupItem_Sync> item in _items)
{
LG_PickupItem_Sync value = item.Value;
if ((Object)(object)value != (Object)null && (Object)(object)value != (Object)(object)itemBeingPlaced && (int)value.GetCurrentState().status == 0)
{
return false;
}
}
StorageSlot storageSlot = StorageSlot;
if (!AnchorContainsItem((storageSlot != null) ? storageSlot.ResourcePack : null, itemBeingPlaced))
{
StorageSlot storageSlot2 = StorageSlot;
if (!AnchorContainsItem((storageSlot2 != null) ? storageSlot2.Consumable : null, itemBeingPlaced))
{
StorageSlot storageSlot3 = StorageSlot;
return !AnchorContainsItem((storageSlot3 != null) ? storageSlot3.Keycard : null, itemBeingPlaced);
}
}
return false;
}
internal void ClearItems()
{
_items.Clear();
}
internal void Track(LG_PickupItem_Sync item)
{
if (!((Object)(object)item == (Object)null))
{
_items[((Il2CppObjectBase)item).Pointer] = item;
}
}
internal void Remove(LG_PickupItem_Sync item)
{
if ((Object)(object)item != (Object)null)
{
_items.Remove(((Il2CppObjectBase)item).Pointer);
}
}
internal string Describe(InventorySlot inventorySlot)
{
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
Transform anchor;
return $"slot={SlotIndex} locker={(Object)(object)Container != (Object)null && Container.m_isLocker} open={IsOpen} anchor={TryGetAnchor(inventorySlot, out anchor)} empty={IsEmptyFor()}";
}
private bool AnchorContainsItem(Transform anchor, LG_PickupItem_Sync itemBeingPlaced)
{
//IL_0051: 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)
if ((Object)(object)anchor == (Object)null)
{
return false;
}
foreach (ItemInLevel componentsInChild in ((Component)anchor).GetComponentsInChildren<ItemInLevel>(true))
{
if (!((Object)(object)componentsInChild == (Object)null))
{
iPickupItemSync syncComponent = componentsInChild.GetSyncComponent();
LG_PickupItem_Sync val = ((syncComponent == null) ? null : ((Il2CppObjectBase)syncComponent).TryCast<LG_PickupItem_Sync>());
if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)itemBeingPlaced && (int)val.GetCurrentState().status == 0)
{
return true;
}
}
}
return false;
}
}
internal static class SlotRegistry
{
private readonly struct SlotGeometry
{
internal readonly Vector3 LocalPosition;
internal readonly Vector3 LocalScale;
internal SlotGeometry(Vector3 localPosition, Vector3 localScale)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: 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_0009: Unknown result type (might be due to invalid IL or missing references)
LocalPosition = localPosition;
LocalScale = localScale;
}
}
private static readonly SlotGeometry[] LockerSlots = new SlotGeometry[6]
{
new SlotGeometry(new Vector3(-0.724f, -0.252f, 1.754f), new Vector3(0.42f, 0.433f, 0.3f)),
new SlotGeometry(new Vector3(-0.672f, -0.252f, 1.454f), new Vector3(0.5f, 0.433f, 0.25f)),
new SlotGeometry(new Vector3(-0.672f, -0.252f, 1.154f), new Vector3(0.5f, 0.433f, 0.25f)),
new SlotGeometry(new Vector3(-0.672f, -0.252f, 0.854f), new Vector3(0.5f, 0.433f, 0.25f)),
new SlotGeometry(new Vector3(-0.672f, -0.252f, 0.354f), new Vector3(0.5f, 0.433f, 0.67f)),
new SlotGeometry(new Vector3(-0.276f, -0.252f, 1.754f), new Vector3(0.42f, 0.433f, 0.3f))
};
private static readonly SlotGeometry[] BoxSlots = new SlotGeometry[3]
{
new SlotGeometry(new Vector3(0.009f, 0f, 0.163f), new Vector3(0.33f, 0.54f, 0.323f)),
new SlotGeometry(new Vector3(-0.343f, 0f, 0.163f), new Vector3(0.34f, 0.54f, 0.323f)),
new SlotGeometry(new Vector3(0.358f, 0f, 0.163f), new Vector3(0.33f, 0.54f, 0.323f))
};
private static readonly Dictionary<IntPtr, ContainerSlotState> StatesByMarker = new Dictionary<IntPtr, ContainerSlotState>();
private static readonly Dictionary<IntPtr, List<ContainerSlotState>> StatesByContainer = new Dictionary<IntPtr, List<ContainerSlotState>>();
private static readonly Dictionary<IntPtr, ContainerSlotState> StatesByItem = new Dictionary<IntPtr, ContainerSlotState>();
private static int _containersLogged;
internal static int InteractionLayerMask
{
get
{
if (LayerManager.LAYER_INTERACTION < 0)
{
return 0;
}
return 1 << LayerManager.LAYER_INTERACTION;
}
}
internal static void CreateSlots(LG_WeakResourceContainer container)
{
//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
//IL_01be: Unknown result type (might be due to invalid IL or missing references)
//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
//IL_01f6: 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_0219: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)container == (Object)null || container.m_storage == null || container.m_sync == null)
{
Plugin.Diag($"container Setup skipped: null container/storage/sync (container={(Object)(object)container != (Object)null}).");
return;
}
IntPtr pointer = ((Il2CppObjectBase)container).Pointer;
if (StatesByContainer.ContainsKey(pointer))
{
return;
}
LG_ResourceContainer_Storage val = ((Il2CppObjectBase)container.m_storage).TryCast<LG_ResourceContainer_Storage>();
LG_ResourceContainer_Sync val2 = ((Il2CppObjectBase)container.m_sync).TryCast<LG_ResourceContainer_Sync>();
if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || val.m_storageSlots == null)
{
Plugin.Diag($"container Setup skipped: storage={(Object)(object)val != (Object)null} sync={(Object)(object)val2 != (Object)null} slots={((val != null) ? val.m_storageSlots : null) != null}.");
return;
}
int lAYER_INTERACTION = LayerManager.LAYER_INTERACTION;
if (lAYER_INTERACTION < 0)
{
Plugin.Logger.LogError((object)"GTFO LAYER_INTERACTION is unavailable; container slots were not created.");
return;
}
SlotGeometry[] array = (container.m_isLocker ? LockerSlots : BoxSlots);
int num = Math.Min(((Il2CppArrayBase<StorageSlot>)(object)val.m_storageSlots).Length, array.Length);
List<ContainerSlotState> list = new List<ContainerSlotState>(num);
StatesByContainer[pointer] = list;
int num2 = 0;
for (int i = 0; i < num; i++)
{
StorageSlot val3 = ((Il2CppArrayBase<StorageSlot>)(object)val.m_storageSlots)[i];
if (val3 != null)
{
GameObject val4 = new GameObject($"DropItemEverywhere_Slot_{i}")
{
layer = lAYER_INTERACTION
};
val4.transform.SetParent(((Component)container).transform, false);
val4.transform.localPosition = array[i].LocalPosition;
val4.transform.localRotation = Quaternion.identity;
val4.transform.localScale = array[i].LocalScale;
((Collider)val4.AddComponent<BoxCollider>()).isTrigger = true;
ResourceContainerSlot resourceContainerSlot = val4.AddComponent<ResourceContainerSlot>();
ContainerSlotState containerSlotState = new ContainerSlotState(resourceContainerSlot, container, val, val3, i);
StatesByMarker[((Il2CppObjectBase)resourceContainerSlot).Pointer] = containerSlotState;
list.Add(containerSlotState);
num2++;
}
}
if (_containersLogged < 8)
{
_containersLogged++;
Plugin.Diag($"container slots created: locker={container.m_isLocker} slots={num} created={num2} layer={lAYER_INTERACTION}. anchors[s0]={((num > 0) ? ContainerSlotStateSummary(list) : "n/a")}");
}
foreach (LG_PickupItem_Sync componentsInChild in ((Component)container).GetComponentsInChildren<LG_PickupItem_Sync>(true))
{
OnItemSetup(componentsInChild);
}
}
private static string ContainerSlotStateSummary(List<ContainerSlotState> states)
{
if (states.Count == 0)
{
return "none";
}
ContainerSlotState containerSlotState = states[0];
return $"pack={(Object)(object)containerSlotState.StorageSlot.ResourcePack != (Object)null} consumable={(Object)(object)containerSlotState.StorageSlot.Consumable != (Object)null} keycard={(Object)(object)containerSlotState.StorageSlot.Keycard != (Object)null}";
}
internal static bool TryGetState(ResourceContainerSlot marker, out ContainerSlotState state)
{
state = null;
if ((Object)(object)marker == (Object)null)
{
return false;
}
return StatesByMarker.TryGetValue(((Il2CppObjectBase)marker).Pointer, out state);
}
internal static bool TryGetSlotTarget(PlayerAgent player, out ContainerSlotState state, out RaycastHit hit)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
state = null;
hit = default(RaycastHit);
int interactionLayerMask = InteractionLayerMask;
if ((Object)(object)player == (Object)null || (Object)(object)player.FPSCamera == (Object)null || interactionLayerMask == 0)
{
return false;
}
float num = Mathf.Clamp(Plugin.ContainerReachMeters.Value, 0.25f, 5f);
if (!Physics.Raycast(player.FPSCamera.Position, player.FPSCamera.Forward, ref hit, num, interactionLayerMask, (QueryTriggerInteraction)2) || (Object)(object)((RaycastHit)(ref hit)).collider == (Object)null)
{
return false;
}
return TryGetState(((Component)((RaycastHit)(ref hit)).collider).GetComponent<ResourceContainerSlot>(), out state);
}
internal static bool IsAnySlotTargeted(PlayerAgent player)
{
ContainerSlotState state;
RaycastHit hit;
return TryGetSlotTarget(player, out state, out hit);
}
internal static bool TryFindAt(Vector3 position, out ContainerSlotState state)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
state = null;
int interactionLayerMask = InteractionLayerMask;
if (interactionLayerMask == 0)
{
return false;
}
foreach (Collider item in (Il2CppArrayBase<Collider>)(object)Physics.OverlapSphere(position, 0.025f, interactionLayerMask, (QueryTriggerInteraction)2))
{
if (!((Object)(object)item == (Object)null) && TryGetState(((Component)item).GetComponent<ResourceContainerSlot>(), out state))
{
return true;
}
}
state = null;
return false;
}
internal static bool TryFindForItem(LG_PickupItem_Sync item, out ContainerSlotState state)
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
state = null;
if ((Object)(object)item == (Object)null)
{
return false;
}
IntPtr pointer = ((Il2CppObjectBase)item).Pointer;
if (StatesByItem.TryGetValue(pointer, out state))
{
return true;
}
return TryFindAt(((Component)item).transform.position, out state);
}
internal static void Unregister(ResourceContainerSlot marker)
{
if ((Object)(object)marker == (Object)null)
{
return;
}
IntPtr pointer = ((Il2CppObjectBase)marker).Pointer;
if (!StatesByMarker.TryGetValue(pointer, out var value))
{
return;
}
StatesByMarker.Remove(pointer);
IntPtr pointer2 = ((Il2CppObjectBase)value.Container).Pointer;
if (StatesByContainer.TryGetValue(pointer2, out var value2))
{
value2.Remove(value);
if (value2.Count == 0)
{
StatesByContainer.Remove(pointer2);
}
}
foreach (LG_PickupItem_Sync item in value.Items)
{
if (!((Object)(object)item == (Object)null))
{
StatesByItem.Remove(((Il2CppObjectBase)item).Pointer);
ItemInLevel itemInLevel = GetItemInLevel(item);
if ((Object)(object)itemInLevel != (Object)null)
{
itemInLevel.container = null;
}
Transform transform = ((Component)item).transform;
if ((Object)(object)transform.parent == (Object)(object)((Component)marker).transform)
{
transform.SetParent((Transform)null, true);
}
}
}
value.ClearItems();
}
internal static void OnStorageContentSpawned(LG_ResourceContainer_Storage storage)
{
if ((Object)(object)storage == (Object)null)
{
return;
}
foreach (LG_PickupItem_Sync componentsInChild in ((Component)storage).GetComponentsInChildren<LG_PickupItem_Sync>(true))
{
OnItemSetup(componentsInChild);
}
}
internal static void OnItemSetup(LG_PickupItem_Sync item)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)item == (Object)null) && (int)item.GetCurrentState().status == 0 && TryFindAt(((Component)item).transform.position, out var state) && ItemDropper.TryGetInventorySlot(item.item, out var inventorySlot) && state.TryGetAnchor(inventorySlot, out var _))
{
TrackItem(state, item);
ItemInLevel itemInLevel = GetItemInLevel(item);
if ((Object)(object)itemInLevel != (Object)null)
{
itemInLevel.container = state.Storage;
}
ParentToSlot(state, item);
}
}
internal static void BeforeItemStateChange(LG_PickupItem_Sync item, pPickupItemState newState)
{
//IL_0009: 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_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected I4, but got Unknown
//IL_0041: 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_0047: 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)
if ((Object)(object)item == (Object)null || newState.updateCustomDataOnly)
{
return;
}
switch ((int)newState.status)
{
case 1:
{
RemoveItem(item);
ItemInLevel itemInLevel2 = GetItemInLevel(item);
if ((Object)(object)itemInLevel2 != (Object)null)
{
itemInLevel2.container = null;
}
break;
}
case 0:
{
if (TryFindAt(newState.placement.position, out var state) && ItemDropper.TryGetInventorySlot(item.item, out var inventorySlot) && state.TryGetAnchor(inventorySlot, out var _) && state.IsEmptyFor(item))
{
TrackItem(state, item);
ItemInLevel itemInLevel = GetItemInLevel(item);
if ((Object)(object)itemInLevel != (Object)null)
{
itemInLevel.container = state.Storage;
}
}
break;
}
}
}
internal static void AfterItemStateChange(LG_PickupItem_Sync item, pPickupItemState newState)
{
//IL_0009: 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_0013: 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_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Invalid comparison between Unknown and I4
if ((Object)(object)item == (Object)null || newState.updateCustomDataOnly)
{
return;
}
if ((int)newState.status == 0 && TryFindForItem(item, out var state))
{
TrackItem(state, item);
ItemInLevel itemInLevel = GetItemInLevel(item);
if ((Object)(object)itemInLevel != (Object)null)
{
itemInLevel.container = state.Storage;
}
ParentToSlot(state, item);
}
else if ((int)newState.status == 1)
{
Transform transform = ((Component)item).transform;
if ((Object)(object)((Component)transform).GetComponentInParent<ResourceContainerSlot>() != (Object)null)
{
transform.SetParent((Transform)null, true);
}
}
}
internal static void OnItemDestroyed(LG_PickupItem_Sync item)
{
RemoveItem(item);
}
private static void TrackItem(ContainerSlotState state, LG_PickupItem_Sync item)
{
if (state != null && !((Object)(object)item == (Object)null))
{
IntPtr pointer = ((Il2CppObjectBase)item).Pointer;
if (StatesByItem.TryGetValue(pointer, out var value) && value != state)
{
value.Remove(item);
}
state.Track(item);
StatesByItem[pointer] = state;
}
}
private static void RemoveItem(LG_PickupItem_Sync item)
{
if (!((Object)(object)item == (Object)null))
{
IntPtr pointer = ((Il2CppObjectBase)item).Pointer;
if (StatesByItem.TryGetValue(pointer, out var value))
{
StatesByItem.Remove(pointer);
value.Remove(item);
}
}
}
private static void ParentToSlot(ContainerSlotState state, LG_PickupItem_Sync item)
{
if (state != null && !((Object)(object)item == (Object)null))
{
Transform transform = ((Component)item).transform;
if ((Object)(object)transform.parent != (Object)(object)((Component)state.Marker).transform)
{
transform.SetParent(((Component)state.Marker).transform, true);
}
}
}
private static ItemInLevel GetItemInLevel(LG_PickupItem_Sync item)
{
if ((Object)(object)item == (Object)null || (Object)(object)item.item == (Object)null)
{
return null;
}
return ((Il2CppObjectBase)item.item).TryCast<ItemInLevel>();
}
}
public sealed class UiProbeRunner : MonoBehaviour
{
private static readonly float[] Delays = new float[3] { 15f, 35f, 55f };
private float _startedAt = -1f;
private int _next;
public UiProbeRunner(IntPtr pointer)
: base(pointer)
{
}
private void Update()
{
if (_next < Delays.Length)
{
if (_startedAt < 0f)
{
_startedAt = Time.realtimeSinceStartup;
}
else if (!(Time.realtimeSinceStartup - _startedAt < Delays[_next]))
{
int next = _next;
_next++;
Plugin.ReportUiProbe($"t+{Delays[next]:F0}s");
}
}
}
}