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(); ((BasePlugin)this).AddComponent(); ManualLogSource logger = Logger; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(12, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("Big Actions"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("1.0.0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" carregado."); } logger.LogInfo(val); } } internal static class PluginConfig { public static ConfigEntry Enabled; public static ConfigEntry BackpackKey; public static ConfigEntry BeltKey; public static ConfigEntry BothFull; public static ConfigEntry EnableGuardPatches; public static ConfigEntry EnableInteropDumper; public static ConfigEntry Verbose; public static void Init(ConfigFile config) { Enabled = config.Bind("General", "Enabled", true, "Liga/desliga o mod."); BackpackKey = config.Bind("Keys", "Backpack", (KeyCode)49, "Tecla pra mochila (toggle contextual: guarda/retira/troca conforme o estado)."); BeltKey = config.Bind("Keys", "Belt", (KeyCode)50, "Tecla pro cinto (toggle contextual)."); BothFull = config.Bind("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("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("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("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? 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 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 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 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(Kind); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(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)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(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(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(); } } } }