Skip to content

Commit

Permalink
internal: add BaseInventory implementation that saves/loads nbt correct
Browse files Browse the repository at this point in the history
  • Loading branch information
MrTJP committed Jan 27, 2023
1 parent 235147e commit 29c4364
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 0 deletions.
54 changes: 54 additions & 0 deletions src/core/scala/mrtjp/projectred/core/inventory/BaseInventory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package mrtjp.projectred.core.inventory;

import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;

/**
* Simple extension of default vanilla Inventory class that allows for proper saving and loading
* to a CompoundNBT. Default implementation does not load items back into their original slots.
* <p>
* Use BaseInventory#save and BaseInventory#load instead of Inventory#createTag and Inventory#fromTag
*/
public class BaseInventory extends Inventory {

private static final String TAG_ITEMS = "items";
private static final String TAG_SLOT = "slot";
private static final String TAG_ITEM_COUNT = "item_count";

public BaseInventory(int size) {
super(size);
}

public void save(CompoundNBT tag) {
ListNBT list = new ListNBT();
for (int i = 0; i < getContainerSize(); i++) {
ItemStack stack = getItem(i);
if (!stack.isEmpty()) {
CompoundNBT itemTag = new CompoundNBT();
itemTag.putInt(TAG_SLOT, i);
stack.save(itemTag);
list.add(itemTag);
}
}
tag.put(TAG_ITEMS, list);
tag.putInt(TAG_ITEM_COUNT, list.size());
}

public void load(CompoundNBT tag) {
clearContent();
ListNBT list = tag.getList(TAG_ITEMS, 10);
for (int i = 0; i < list.size(); i++) {
CompoundNBT itemTag = list.getCompound(i);
int slot = itemTag.contains("index") ? itemTag.getInt("index") : itemTag.getInt(TAG_SLOT); //TODO remove legacy support
if (slot >= 0 && slot < getContainerSize()) {
setItem(slot, ItemStack.of(itemTag));
}
}
}

public static int getItemCount(CompoundNBT tag) {
return tag.contains(TAG_ITEM_COUNT) ? tag.getInt(TAG_ITEM_COUNT) : tag.getList(TAG_ITEMS, 10).size(); //TODO remove legacy support
}
}
43 changes: 43 additions & 0 deletions src/core/scala/mrtjp/projectred/lib/InventoryLib.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package mrtjp.projectred.lib;

import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.container.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;

import java.util.function.Consumer;

public class InventoryLib {

public static void injectItemStack(IInventory inventory, ItemStack stack, boolean reverse) {
Expand Down Expand Up @@ -66,4 +70,43 @@ private static void injectItemStack(IInventory inventory, ItemStack stack, int s
public static boolean areStackable(ItemStack a, ItemStack b) {
return ItemStack.isSame(a, b) && ItemStack.tagMatches(a, b) && a.getMaxStackSize() > 1 && b.getMaxStackSize() > 1;
}

public static void addPlayerInventory(PlayerInventory playerInventory, int x, int y, Consumer<Slot> slotConsumer) {
addInventory(playerInventory, 9, x, y, 9, 3, slotConsumer); // Inventory (0 - 26)
addInventory(playerInventory, 0, x, y + 58, 9, 1, slotConsumer); // Hotbar slots (27 - 35)
}

public static void addPlayerInventory(PlayerInventory playerInventory, int x, int y, SlotFactory slotFactory, Consumer<Slot> slotConsumer) {
addInventory(playerInventory, 9, x, y, 9, 3, slotFactory, slotConsumer); // Inventory (0 - 26)
addInventory(playerInventory, 0, x, y + 58, 9, 1, slotFactory, slotConsumer); // Hotbar slots (27 - 35)
}

public static void addInventory(IInventory inventory, int i, int x, int y, int columns, int rows, Consumer<Slot> slotConsumer) {
addInventory(inventory, i, x, y, columns, rows, Slot::new, slotConsumer);
}

/**
* Creates a grid of slots for a container with standard spacing.
*
* @param inventory The inventory backing the slots
* @param i Inventory index of the first slot
* @param x X position of the top left slot
* @param y Y position of the top left slot
* @param columns Number of columns in the grid
* @param rows Number of rows in the grid
* @param slotFactory Factory for creating the slots
* @param slotConsumer Consumer for the slots (typically Container.addSlot(...))
*/
public static void addInventory(IInventory inventory, int i, int x, int y, int columns, int rows, SlotFactory slotFactory, Consumer<Slot> slotConsumer) {
for (int c = 0; c < columns; c++) {
for (int r = 0; r < rows; r++) {
slotConsumer.accept(slotFactory.createSlot(inventory, i + (r * columns + c), x + c * 18, y + r * 18));
}
}
}

@FunctionalInterface
public interface SlotFactory {
Slot createSlot(IInventory inventory, int index, int x, int y);
}
}

0 comments on commit 29c4364

Please sign in to comment.