using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SpaceCraft;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("PlayerInventoryStacks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("PlayerInventoryStacks")]
[assembly: AssemblyTitle("PlayerInventoryStacks")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[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 PlayerInventoryStacks
{
internal static class Backpacks
{
private static readonly HashSet<int> Ids = new HashSet<int>();
private static readonly FieldInfo LockTime = typeof(WorldObject).GetField("_lockInInventoryTime", BindingFlags.Instance | BindingFlags.NonPublic);
internal static void Clear()
{
Ids.Clear();
}
internal static void Register(int id)
{
if (id > 0)
{
Ids.Add(id);
}
}
internal static bool IsPlayer(Inventory inventory)
{
if (inventory != null)
{
return Ids.Contains(inventory.GetId());
}
return false;
}
internal static string Key(WorldObject item)
{
//IL_00a3: 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)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_015c: Unknown result type (might be due to invalid IL or missing references)
//IL_0161: 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)
if (item == null)
{
throw new ArgumentNullException("item");
}
StringBuilder b;
if (item.GetLinkedInventoryId() == 0)
{
List<int> secondaryInventoriesId = item.GetSecondaryInventoriesId();
if ((secondaryInventoriesId == null || secondaryInventoriesId.Count <= 0) && item.GetLinkedWorldObject() == 0 && (float)LockTime.GetValue(item) == 0f)
{
b = new StringBuilder();
Add(item.GetGroup().GetId());
Add(item.GetText());
Add(item.GetSetting());
Add(item.GetGeneticTraitType());
Add(item.GetGeneticTraitValue());
Color color = item.GetColor();
Add(color.r);
Add(color.g);
Add(color.b);
Add(color.a);
Add(item.GetEnergy());
Add(item.GetGrowth());
Add(item.GetHunger());
Add(item.GetPetTime());
Vector2Int count = item.GetCount();
Add(((Vector2Int)(ref count)).x);
count = item.GetCount();
Add(((Vector2Int)(ref count)).y);
Add(item.GetPlanetLinkedHash());
List<Group> linkedGroups = item.GetLinkedGroups();
Add(linkedGroups?.Count ?? 0);
if (linkedGroups != null)
{
foreach (Group item2 in linkedGroups)
{
Add(item2.GetId());
}
}
List<int> panelsId = item.GetPanelsId();
Add(panelsId?.Count ?? 0);
if (panelsId != null)
{
foreach (int item3 in panelsId)
{
Add(item3);
}
}
return b.ToString();
}
}
return "unique:" + item.GetId();
void Add(object value)
{
string text = Convert.ToString(value, CultureInfo.InvariantCulture) ?? "";
b.Append(text.Length).Append(':').Append(text)
.Append('|');
}
}
internal static List<StackLayout.Stack<WorldObject>> Layout(Inventory inventory)
{
return StackLayout.Create(inventory.GetInsideWorldObjects(), Key);
}
internal static bool FullFor(Inventory inventory, WorldObject item)
{
if (!IsPlayer(inventory))
{
return inventory.IsFull();
}
if (item == null)
{
return Layout(inventory).Count >= inventory.GetSize();
}
if (inventory.ContainWorldObject(item))
{
return false;
}
return !StackLayout.CanAdd(inventory.GetInsideWorldObjects(), item, inventory.GetSize(), Key);
}
internal static bool FullForGroup(Inventory inventory, Group group)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
return FullFor(inventory, new WorldObject(0, group));
}
internal static bool FitsCraft(Inventory inventory, List<Group> ingredients, Group output, bool freeCraft)
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Expected O, but got Unknown
List<WorldObject> list = inventory.GetInsideWorldObjects().ToList();
if (!freeCraft)
{
foreach (Group group in ingredients)
{
int num = list.FindLastIndex((WorldObject item) => item.GetGroup() == group);
if (num >= 0)
{
list.RemoveAt(num);
}
}
}
return StackLayout.CanAdd(list, new WorldObject(0, output), inventory.GetSize(), Key);
}
}
[BepInPlugin("local.planetcrafter.playerinventorystacks", "Player Inventory Stacks", "1.0.0")]
[BepInProcess("Planet Crafter.exe")]
public sealed class Plugin : BaseUnityPlugin
{
public const string Id = "local.planetcrafter.playerinventorystacks";
private Harmony harmony;
private void Awake()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
harmony = new Harmony("local.planetcrafter.playerinventorystacks");
try
{
harmony.PatchAll(typeof(Plugin).Assembly);
((BaseUnityPlugin)this).Logger.LogInfo((object)"Player Inventory Stacks 1.0.0 loaded: 64 items per backpack stack; containers unchanged.");
}
catch (Exception ex)
{
harmony.UnpatchSelf();
((BaseUnityPlugin)this).Logger.LogError((object)("Player Inventory Stacks could not patch this game version; all its patches were removed. " + ex));
}
}
private void OnDestroy()
{
Harmony obj = harmony;
if (obj != null)
{
obj.UnpatchSelf();
}
}
}
[HarmonyPatch(typeof(InventoriesHandler), "OnNetworkSpawn")]
internal static class ResetWorld
{
private static void Prefix()
{
Backpacks.Clear();
}
}
[HarmonyPatch(typeof(PlayerBackpack), "SetInventory")]
internal static class RegisterBackpack
{
private static void Prefix(Inventory _playerInventory)
{
if (_playerInventory != null)
{
Backpacks.Register(_playerInventory.GetId());
}
}
}
[HarmonyPatch(typeof(PlayerMainController), "InitPlayerClientRpc")]
internal static class RegisterClientBackpack
{
private static void Prefix(int inventoryId)
{
Backpacks.Register(inventoryId);
}
}
[HarmonyPatch(typeof(SavedDataHandler), "LoadSavedData")]
internal static class RegisterSavedBackpacks
{
private static void Postfix(SavedDataHandler __instance)
{
List<JsonablePlayerState> lastLoadedPlayerData = __instance.GetLastLoadedPlayerData();
if (lastLoadedPlayerData == null)
{
return;
}
foreach (JsonablePlayerState item in lastLoadedPlayerData)
{
Backpacks.Register(item.inventoryId);
}
}
}
[HarmonyPatch(typeof(Inventory), "IsFull")]
internal static class InventoryFull
{
private static bool Prefix(Inventory __instance, ref bool __result)
{
if (!Backpacks.IsPlayer(__instance))
{
return true;
}
__result = Backpacks.Layout(__instance).Count >= __instance.GetSize();
return false;
}
}
[HarmonyPatch(typeof(Inventory), "AddItemInInventory")]
internal static class AddItemCapacity
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Expected O, but got Unknown
return PatchTools.ReplaceFull(instructions, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[1]
{
new CodeInstruction(OpCodes.Ldarg_1, (object)null)
}, "FullFor");
}
}
[HarmonyPatch(typeof(Inventory), "DropObjectsIfNotEnoughSpace")]
internal static class BackpackShrink
{
private static bool Prefix(Inventory __instance, Vector3 dropPosition, bool removeOnly, ref List<WorldObject> __result)
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
if (!Backpacks.IsPlayer(__instance))
{
return true;
}
List<WorldObject> list = Backpacks.Layout(__instance).Skip(Math.Max(0, __instance.GetSize())).SelectMany((StackLayout.Stack<WorldObject> s) => s.Items)
.ToList();
foreach (WorldObject item in list)
{
if (!removeOnly)
{
WorldObjectsHandler.Instance.DropOnFloor(item, dropPosition, 0f, true, false, 0);
}
__instance.RemoveItem(item);
}
__result = list;
return false;
}
}
[HarmonyPatch(typeof(InventoryDisplayer), "SetInventoryBlocks")]
internal static class DisplayStacks
{
private static void Prefix(Inventory ____inventory, ref ReadOnlyCollection<WorldObject> inventoryWorldObjects, out List<StackLayout.Stack<WorldObject>> __state)
{
__state = null;
if (Backpacks.IsPlayer(____inventory))
{
__state = Backpacks.Layout(____inventory);
inventoryWorldObjects = __state.Select((StackLayout.Stack<WorldObject> s) => s.Items[0]).ToList().AsReadOnly();
}
}
private static void Postfix(Inventory ____inventory, GridLayoutGroup ____grid, List<StackLayout.Stack<WorldObject>> __state)
{
//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_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
if (__state == null)
{
return;
}
InventoryBlock[] componentsInChildren = ((Component)____grid).GetComponentsInChildren<InventoryBlock>();
componentsInChildren = componentsInChildren.Skip(Math.Max(0, componentsInChildren.Length - ____inventory.GetSize())).ToArray();
for (int i = 0; i < Math.Min(componentsInChildren.Length, __state.Count); i++)
{
int count = __state[i].Items.Count;
if (count > 1)
{
GameObject val = new GameObject("PlayerStackCount", new Type[2]
{
typeof(RectTransform),
typeof(TextMeshProUGUI)
});
val.transform.SetParent(((Component)componentsInChildren[i]).transform, false);
RectTransform val2 = (RectTransform)val.transform;
val2.anchorMin = Vector2.zero;
val2.anchorMax = Vector2.one;
val2.offsetMin = new Vector2(3f, 3f);
val2.offsetMax = new Vector2(-5f, -3f);
TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
((TMP_Text)component).font = TMP_Settings.defaultFontAsset;
((TMP_Text)component).text = count.ToString();
((TMP_Text)component).fontSize = 22f;
((TMP_Text)component).fontStyle = (FontStyles)1;
((Graphic)component).color = Color.white;
((TMP_Text)component).alignment = (TextAlignmentOptions)1028;
((Graphic)component).raycastTarget = false;
((TMP_Text)component).textWrappingMode = (TextWrappingModes)0;
((TMP_Text)component).outlineWidth = 0.22f;
((TMP_Text)component).outlineColor = new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue);
}
}
}
}
internal static class PatchTools
{
internal static readonly MethodInfo IsFull = AccessTools.Method(typeof(Inventory), "IsFull", (Type[])null, (Type[])null);
internal static IEnumerable<CodeInstruction> ReplaceFull(IEnumerable<CodeInstruction> source, IEnumerable<CodeInstruction> loadCandidate, string helper, int expected = 1)
{
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Expected O, but got Unknown
List<CodeInstruction> list = new List<CodeInstruction>();
int num = 0;
foreach (CodeInstruction item in source)
{
if (CodeInstructionExtensions.Calls(item, IsFull))
{
List<CodeInstruction> list2 = loadCandidate.Select((Func<CodeInstruction, CodeInstruction>)((CodeInstruction c) => new CodeInstruction(c))).ToList();
list2[0].labels.AddRange(item.labels);
list2[0].blocks.AddRange(item.blocks);
list.AddRange(list2);
list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Backpacks), helper, (Type[])null, (Type[])null)));
num++;
}
else
{
list.Add(item);
}
}
if (num != expected)
{
throw new InvalidOperationException($"Expected {expected} capacity checks, found {num}.");
}
return list;
}
internal static WorldObject ActionItem(Component component)
{
WorldObjectAssociated componentInParent = component.GetComponentInParent<WorldObjectAssociated>();
if (componentInParent == null)
{
return null;
}
return componentInParent.GetWorldObject();
}
internal static IEnumerable<CodeInstruction> ActionCapacity(IEnumerable<CodeInstruction> source, FieldInfo owner = null)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected O, but got Unknown
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Expected O, but got Unknown
List<CodeInstruction> list = new List<CodeInstruction>
{
new CodeInstruction(OpCodes.Ldarg_0, (object)null)
};
if (owner != null)
{
list.Add(new CodeInstruction(OpCodes.Ldfld, (object)owner));
}
list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(PatchTools), "ActionItem", (Type[])null, (Type[])null)));
return ReplaceFull(source, list, "FullFor");
}
}
[HarmonyPatch(typeof(ActionMinable), "OnAction")]
internal static class StartMiningCapacity
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
return PatchTools.ActionCapacity(instructions);
}
}
[HarmonyPatch]
internal static class FinishMiningCapacity
{
private static MethodBase TargetMethod()
{
return AccessTools.EnumeratorMoveNext((MethodBase)AccessTools.Method(typeof(ActionMinable), "FinishMining", (Type[])null, (Type[])null));
}
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
{
return PatchTools.ActionCapacity(instructions, AccessTools.Field(original.DeclaringType, "<>4__this"));
}
}
[HarmonyPatch(typeof(ActionGrabable), "OnAction")]
internal static class GrabCapacity
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
return PatchTools.ActionCapacity(instructions);
}
}
[HarmonyPatch(typeof(CraftManager), "TryToCraftInInventory")]
internal static class CraftCapacity
{
private static bool Prefix(PlayerMainController playerController, GroupItem groupItem, ref bool __result)
{
Inventory inventory = playerController.GetPlayerBackpack().GetInventory();
if (!Backpacks.IsPlayer(inventory))
{
return true;
}
bool freeCraft = Managers.GetManager<GameSettingsHandler>().GetCurrentGameSettings().GetFreeCraft();
if (Backpacks.FitsCraft(inventory, ((Group)groupItem).GetRecipe().GetIngredientsGroupInRecipe(), (Group)(object)groupItem, freeCraft))
{
return true;
}
Managers.GetManager<BaseHudHandler>().DisplayCursorText("UI_InventoryFull", 2f, "", "", false);
__result = false;
return false;
}
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Expected O, but got Unknown
return PatchTools.ReplaceFull(instructions, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[1]
{
new CodeInstruction(OpCodes.Ldarg_2, (object)null)
}, "FullForGroup", 2);
}
}
[HarmonyPatch(typeof(WorldObjectsHandler), "RetrieveResourcesFromDeconstructionServerRpc")]
internal static class DeconstructionCapacity
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Expected O, but got Unknown
List<CodeInstruction> list = instructions.ToList();
int num = list.FindIndex((CodeInstruction c) => CodeInstructionExtensions.Calls(c, PatchTools.IsFull));
int num2 = ((num < 0) ? (-1) : list.FindLastIndex(num, (CodeInstruction c) => CodeInstructionExtensions.Calls(c, AccessTools.Method(typeof(WorldObject), "GetGroup", (Type[])null, (Type[])null))));
if (num2 <= 0 || !CodeInstructionExtensions.IsLdloc(list[num2 - 1], (LocalBuilder)null))
{
throw new InvalidOperationException("Could not identify deconstruction resource local.");
}
return PatchTools.ReplaceFull(list, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[1]
{
new CodeInstruction(list[num2 - 1].opcode, list[num2 - 1].operand)
}, "FullFor");
}
}
[HarmonyPatch(typeof(ActionPanelDeconstruct), "Deconstruct")]
internal static class PanelCapacity
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
{
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Expected O, but got Unknown
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Expected O, but got Unknown
var list = (from local in original.GetMethodBody().LocalVariables
select new
{
local = local,
field = local.LocalType.GetField("group", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
} into pair
where pair.field?.FieldType == typeof(Group)
select pair).ToList();
if (list.Count != 1)
{
throw new InvalidOperationException("Could not identify panel ingredient local.");
}
var anon = list[0];
return PatchTools.ReplaceFull(instructions, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[2]
{
new CodeInstruction(OpCodes.Ldloc, (object)anon.local.LocalIndex),
new CodeInstruction(OpCodes.Ldfld, (object)anon.field)
}, "FullForGroup");
}
}
[HarmonyPatch(typeof(InventoriesHandler), "AnInventoryHasBeenClicked")]
internal static class QuickTransferKey
{
internal static bool IsPressed(PlayerInputDispatcher input, Inventory source)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
if (input.IsPressingAccessibilityKey())
{
return true;
}
if (Keyboard.current == null || !Keyboard.current.shiftKey.isPressed)
{
return false;
}
WindowsHandler manager = Managers.GetManager<WindowsHandler>();
UiWindow windowViaUiId = manager.GetWindowViaUiId(manager.GetOpenedUi());
UiWindowContainer val = (UiWindowContainer)(object)((windowViaUiId is UiWindowContainer) ? windowViaUiId : null);
if ((Object)(object)val != (Object)null)
{
if (!Backpacks.IsPlayer(source))
{
return Backpacks.IsPlayer(val.GetOtherInventory(source));
}
return true;
}
return false;
}
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Expected O, but got Unknown
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Expected O, but got Unknown
List<CodeInstruction> list = new List<CodeInstruction>();
int num = 0;
MethodInfo methodInfo = AccessTools.Method(typeof(PlayerInputDispatcher), "IsPressingAccessibilityKey", (Type[])null, (Type[])null);
foreach (CodeInstruction instruction in instructions)
{
if (CodeInstructionExtensions.Calls(instruction, methodInfo))
{
CodeInstruction val = new CodeInstruction(OpCodes.Ldarg_1, (object)null);
val.labels.AddRange(instruction.labels);
val.blocks.AddRange(instruction.blocks);
list.Add(val);
list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(QuickTransferKey), "IsPressed", (Type[])null, (Type[])null)));
num++;
}
else
{
list.Add(instruction);
}
}
if (num != 1)
{
throw new InvalidOperationException("Could not identify inventory quick-transfer key check.");
}
return list;
}
}
internal static class StackLayout
{
internal sealed class Stack<T>
{
internal readonly List<T> Items = new List<T>();
}
internal const int Limit = 64;
internal static List<Stack<T>> Create<T>(IEnumerable<T> items, Func<T, string> key)
{
List<Stack<T>> list = new List<Stack<T>>();
Dictionary<string, Stack<T>> dictionary = new Dictionary<string, Stack<T>>(StringComparer.Ordinal);
foreach (T item in items)
{
string key2 = key(item);
if (!dictionary.TryGetValue(key2, out var value) || value.Items.Count == 64)
{
value = (dictionary[key2] = new Stack<T>());
list.Add(value);
}
value.Items.Add(item);
}
return list;
}
internal static bool CanAdd<T>(IEnumerable<T> items, T candidate, int slots, Func<T, string> key)
{
List<Stack<T>> list = Create(items, key);
if (list.Count < slots)
{
return true;
}
if (list.Count > slots)
{
return false;
}
string text = key(candidate);
foreach (Stack<T> item in list)
{
if (item.Items.Count < 64 && key(item.Items[0]) == text)
{
return true;
}
}
return false;
}
}
}