using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BigActions.Features.Discovery;
using BigActions.Features.SelfStow;
using BigActions.Game;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BigActions")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BigActions")]
[assembly: AssemblyTitle("BigActions")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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]
[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]
[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 BigActions
{
[BepInPlugin("com.ruan.bigactions", "Big Actions", "1.0.0")]
public sealed class Plugin : BasePlugin
{
public const string Guid = "com.ruan.bigactions";
public const string Name = "Big Actions";
public const string Version = "1.0.0";
internal static ManualLogSource Logger;
public override void Load()
{
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Expected O, but got Unknown
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
Logger = ((BasePlugin)this).Log;
PluginConfig.Init(((BasePlugin)this).Config);
if (PluginConfig.EnableInteropDumper.Value)
{
InteropDumper.Dump();
}
if (PluginConfig.EnableGuardPatches.Value)
{
new Harmony("com.ruan.bigactions").PatchAll(typeof(SelfGuardPatches));
Logger.LogInfo((object)"SelfGuardPatches aplicados.");
}
ClassInjector.RegisterTypeInIl2Cpp<SelfStowInput>();
((BasePlugin)this).AddComponent<SelfStowInput>();
ManualLogSource logger = Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(12, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Big Actions");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.0");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" carregado.");
}
logger.LogInfo(val);
}
}
internal static class PluginConfig
{
public static ConfigEntry<bool> Enabled;
public static ConfigEntry<KeyCode> BackpackKey;
public static ConfigEntry<KeyCode> BeltKey;
public static ConfigEntry<BothFullBehavior> BothFull;
public static ConfigEntry<bool> EnableGuardPatches;
public static ConfigEntry<bool> EnableInteropDumper;
public static ConfigEntry<bool> Verbose;
public static void Init(ConfigFile config)
{
Enabled = config.Bind<bool>("General", "Enabled", true, "Liga/desliga o mod.");
BackpackKey = config.Bind<KeyCode>("Keys", "Backpack", (KeyCode)49, "Tecla pra mochila (toggle contextual: guarda/retira/troca conforme o estado).");
BeltKey = config.Bind<KeyCode>("Keys", "Belt", (KeyCode)50, "Tecla pro cinto (toggle contextual).");
BothFull = config.Bind<BothFullBehavior>("General", "BothOccupied", BothFullBehavior.DoNothing, "O que fazer quando mao E container estao cheios. O jogo nao tem swap nativo e voce so tem uma mao, entao troca atomica nao existe. DoNothing = seguro, nao faz nada. TryPlaceOverFull = experimental, so funciona se colocar num container cheio devolver o item antigo pra mao (a confirmar in-game).");
EnableGuardPatches = config.Bind<bool>("Advanced", "EnableGuardPatches", false, "Aplica Harmony prefixes pra neutralizar o bloqueio de auto-interacao nos proprios pockets. So ligue se a predicao do cliente brigar com o mod; o caminho principal chama os Commands direto, pulando a mira.");
EnableInteropDumper = config.Bind<bool>("Dev", "EnableInteropDumper", false, "Ferramenta de dev: despeja tipos/membros da interop que batem em keywords, num txt, no boot. Desligado por padrao.");
Verbose = config.Bind<bool>("General", "Verbose", false, "Logs verbosos de cada acao.");
}
}
}
namespace BigActions.Game
{
internal static class GameBindings
{
public static PlayerCharacter? LocalPlayer
{
get
{
if (!((Object)(object)WorldManager.localPlayerCharacter == (Object)null))
{
return WorldManager.localPlayerCharacter;
}
return null;
}
}
public static PropHome? BackpackSlot(PlayerCharacter player)
{
PlayerRegistry registry = player.registry;
if (registry != null)
{
return registry.backpackPocket;
}
return null;
}
public static PropHome? BeltSlot(PlayerCharacter player)
{
PlayerRegistry registry = player.registry;
if (registry != null)
{
return registry.holsterPocket;
}
return null;
}
public static bool HandOccupied(PlayerCharacter player)
{
PlayerHands hands = player.hands;
if (hands != null)
{
return hands.isHoldingSomething;
}
return false;
}
public static Prop? HeldProp(PlayerCharacter player)
{
PlayerHands hands = player.hands;
if (hands != null)
{
return hands.heldProp;
}
return null;
}
public static bool IsHomeEmpty(PropHome home)
{
return (Object)(object)home.pinnedProp == (Object)null;
}
public static Prop? PinnedProp(PropHome home)
{
return home.pinnedProp;
}
public static bool HomeAccepts(PropHome home, Prop prop)
{
return home.IsSafeToPlace(prop);
}
public static List<PropHome>? ContentPockets(Prop wearable)
{
return wearable.childPropHomes;
}
public static void PlaceInHome(PlayerCharacter player, Prop prop, PropHome home)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
player.playerNetworking.CmdPlaceInHome(prop, home.shellReference);
}
public static void TakeFromHome(PlayerCharacter player, Prop prop)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
player.playerNetworking.CmdPickUp(new PlayerHeldInformation(prop));
}
public static string HomeName(PropHome home)
{
//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)
return ((object)home.saveableHomeName/*cast due to .constrained prefix*/).ToString();
}
}
internal sealed class ItemContainer
{
private readonly PlayerCharacter _player;
private readonly PropHome _equipSlot;
private Prop? _held;
private Prop? _wearable;
private PropHome? _emptyFitPocket;
private PropHome? _occupiedPocket;
public ContainerKind Kind { get; }
public ItemContainer(PlayerCharacter player, ContainerKind kind, PropHome equipSlot)
{
_player = player;
Kind = kind;
_equipSlot = equipSlot;
}
public void Toggle()
{
_held = GameBindings.HeldProp(_player);
_wearable = GameBindings.PinnedProp(_equipSlot);
_emptyFitPocket = null;
_occupiedPocket = null;
bool heldFitsEquipSlot = (Object)(object)_held != (Object)null && GameBindings.IsHomeEmpty(_equipSlot) && GameBindings.HomeAccepts(_equipSlot, _held);
int value = 0;
if ((Object)(object)_wearable != (Object)null)
{
List<PropHome> val = GameBindings.ContentPockets(_wearable);
if (val != null)
{
value = val.Count;
if ((Object)(object)_held != (Object)null)
{
_emptyFitPocket = FirstEmptyAccepting(val, _held);
}
_occupiedPocket = FirstOccupied(val);
}
}
StowAction stowAction = StowDecider.Decide(new StowState((Object)(object)_held != (Object)null, heldFitsEquipSlot, (Object)(object)_wearable != (Object)null, (Object)(object)_emptyFitPocket != (Object)null, (Object)(object)_occupiedPocket != (Object)null));
Log($"held={(Object)(object)_held != (Object)null} equipado={(Object)(object)_wearable != (Object)null} bolsos={value} vaga={(Object)(object)_emptyFitPocket != (Object)null} item={(Object)(object)_occupiedPocket != (Object)null} -> {stowAction}");
StowExecutor.Execute(stowAction, this);
}
public void Equip()
{
if (!((Object)(object)_held == (Object)null))
{
GameBindings.PlaceInHome(_player, _held, _equipSlot);
}
}
public void Unequip()
{
if (!((Object)(object)_wearable == (Object)null))
{
GameBindings.TakeFromHome(_player, _wearable);
}
}
public void Stow()
{
if (!((Object)(object)_held == (Object)null) && !((Object)(object)_emptyFitPocket == (Object)null))
{
GameBindings.PlaceInHome(_player, _held, _emptyFitPocket);
}
}
public void Take()
{
if (!((Object)(object)_occupiedPocket == (Object)null))
{
Prop val = GameBindings.PinnedProp(_occupiedPocket);
if (!((Object)(object)val == (Object)null))
{
GameBindings.TakeFromHome(_player, val);
}
}
}
public void Swap()
{
if (!((Object)(object)_held == (Object)null) && !((Object)(object)_occupiedPocket == (Object)null))
{
GameBindings.PlaceInHome(_player, _held, _occupiedPocket);
}
}
private static PropHome? FirstEmptyAccepting(List<PropHome> pockets, Prop held)
{
for (int i = 0; i < pockets.Count; i++)
{
PropHome val = pockets[i];
if ((Object)(object)val != (Object)null && GameBindings.IsHomeEmpty(val) && GameBindings.HomeAccepts(val, held))
{
return val;
}
}
return null;
}
private static PropHome? FirstOccupied(List<PropHome> pockets)
{
for (int i = 0; i < pockets.Count; i++)
{
PropHome val = pockets[i];
if ((Object)(object)val != (Object)null && !GameBindings.IsHomeEmpty(val))
{
return val;
}
}
return null;
}
private void Log(string msg)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
if (PluginConfig.Verbose.Value)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(3, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<ContainerKind>(Kind);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(msg);
}
logger.LogInfo(val);
}
}
}
internal static class LocalPlayer
{
public static bool TryGetContainer(ContainerKind kind, out ItemContainer container)
{
container = null;
PlayerCharacter localPlayer = GameBindings.LocalPlayer;
if ((Object)(object)localPlayer == (Object)null)
{
return false;
}
PropHome val = ((kind == ContainerKind.Backpack) ? GameBindings.BackpackSlot(localPlayer) : GameBindings.BeltSlot(localPlayer));
if ((Object)(object)val == (Object)null)
{
return false;
}
container = new ItemContainer(localPlayer, kind, val);
return true;
}
public static bool InGameplay()
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Invalid comparison between Unknown and I4
if ((Object)(object)GameBindings.LocalPlayer == (Object)null)
{
return false;
}
if ((int)Cursor.lockState != 1)
{
return false;
}
return true;
}
}
}
namespace BigActions.Features.SelfStow
{
public enum BothFullBehavior
{
DoNothing,
TryPlaceOverFull
}
public enum ContainerKind
{
Backpack,
Belt
}
internal static class SelfGuardPatches
{
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPrefix]
private static bool ForceAllowGrab(PropHome __instance, ref bool __result)
{
if (!IsLocalOwnPocket(__instance))
{
return true;
}
__result = false;
return false;
}
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
[HarmonyPrefix]
private static bool ForceAllowPlace(PropHome __instance, ref bool __result)
{
if (!IsLocalOwnPocket(__instance))
{
return true;
}
__result = false;
return false;
}
private static bool IsLocalOwnPocket(PropHome home)
{
PlayerCharacter localPlayer = GameBindings.LocalPlayer;
if ((Object)(object)localPlayer != (Object)null && (Object)(object)home != (Object)null)
{
return (Object)(object)home.parentCharacter == (Object)(object)localPlayer;
}
return false;
}
}
internal sealed class SelfStowInput : MonoBehaviour
{
public SelfStowInput(IntPtr ptr)
: base(ptr)
{
}
private void Update()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
if (PluginConfig.Enabled.Value && LocalPlayer.InGameplay())
{
if (Input.GetKeyDown(PluginConfig.BackpackKey.Value))
{
Trigger(ContainerKind.Backpack);
}
else if (Input.GetKeyDown(PluginConfig.BeltKey.Value))
{
Trigger(ContainerKind.Belt);
}
}
}
private static void Trigger(ContainerKind kind)
{
if (LocalPlayer.TryGetContainer(kind, out ItemContainer container))
{
container.Toggle();
}
}
}
public enum StowAction
{
None,
Equip,
Unequip,
Stow,
Take,
Swap
}
public static class StowDecider
{
public static StowAction Decide(StowState s)
{
if (s.HeldFitsEquipSlot)
{
return StowAction.Equip;
}
if (!s.WearableEquipped)
{
return StowAction.None;
}
if (s.HandOccupied)
{
if (s.PocketHasRoomForHeld)
{
return StowAction.Stow;
}
if (s.PocketHasItem)
{
return StowAction.Swap;
}
return StowAction.None;
}
if (s.PocketHasItem)
{
return StowAction.Take;
}
return StowAction.Unequip;
}
}
internal static class StowExecutor
{
public static void Execute(StowAction action, ItemContainer container)
{
switch (action)
{
case StowAction.Equip:
container.Equip();
break;
case StowAction.Unequip:
container.Unequip();
break;
case StowAction.Stow:
container.Stow();
break;
case StowAction.Take:
container.Take();
break;
case StowAction.Swap:
if (PluginConfig.BothFull.Value == BothFullBehavior.TryPlaceOverFull)
{
container.Swap();
}
break;
case StowAction.None:
break;
}
}
}
public readonly struct StowState
{
public readonly bool HandOccupied;
public readonly bool HeldFitsEquipSlot;
public readonly bool WearableEquipped;
public readonly bool PocketHasRoomForHeld;
public readonly bool PocketHasItem;
public StowState(bool handOccupied, bool heldFitsEquipSlot, bool wearableEquipped, bool pocketHasRoomForHeld, bool pocketHasItem)
{
HandOccupied = handOccupied;
HeldFitsEquipSlot = heldFitsEquipSlot;
WearableEquipped = wearableEquipped;
PocketHasRoomForHeld = pocketHasRoomForHeld;
PocketHasItem = pocketHasItem;
}
}
}
namespace BigActions.Features.Discovery
{
internal static class InteropDumper
{
private static readonly string[] Keywords = new string[18]
{
"Pocket", "Holster", "Backpack", "Belt", "Home", "Pin", "Prop", "Stow", "Hand", "Held",
"Cmd", "Rpc", "Server", "Snatch", "Grab", "Place", "Inventory", "Container"
};
private static readonly string[] TargetAssemblies = new string[2] { "Assembly-CSharp", "Mirror" };
public static void Dump()
{
//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
//IL_01bd: Expected O, but got Unknown
//IL_0182: Unknown result type (might be due to invalid IL or missing references)
//IL_0189: Expected O, but got Unknown
bool flag = default(bool);
try
{
StringBuilder stringBuilder = new StringBuilder();
foreach (Assembly item in AppDomain.CurrentDomain.GetAssemblies().Where(delegate(Assembly a)
{
string name = a.GetName().Name;
return name != null && ((ReadOnlySpan<string>)TargetAssemblies).Contains(name);
}))
{
StringBuilder stringBuilder2 = stringBuilder;
StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(8, 1, stringBuilder2);
handler.AppendLiteral("=== ");
handler.AppendFormatted(item.GetName().Name);
handler.AppendLiteral(" ===");
stringBuilder2.AppendLine(ref handler);
foreach (Type item2 in from t in SafeTypes(item)
orderby t.FullName
select t)
{
if (Matches(item2.Name))
{
stringBuilder.AppendLine(item2.FullName);
MemberInfo[] members = item2.GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
foreach (MemberInfo memberInfo in members)
{
stringBuilder.Append(" ").AppendLine(memberInfo.ToString());
}
}
}
}
string text = Path.Combine(Paths.PluginPath, "BigActions");
Directory.CreateDirectory(text);
string text2 = Path.Combine(text, "interop-dump.txt");
File.WriteAllText(text2, stringBuilder.ToString());
ManualLogSource logger = Plugin.Logger;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(26, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("InteropDumper: escrito em ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text2);
}
logger.LogInfo(val);
}
catch (Exception ex)
{
ManualLogSource logger2 = Plugin.Logger;
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(22, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("InteropDumper falhou: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
}
logger2.LogError(val2);
}
}
private static bool Matches(string name)
{
return Keywords.Any((string k) => name.IndexOf(k, StringComparison.OrdinalIgnoreCase) >= 0);
}
private static Type[] SafeTypes(Assembly asm)
{
try
{
return asm.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
return ex.Types.Where((Type t) => t != null).ToArray();
}
}
}
}