add shulker extraction and fix storing techreborn storage (#3111)
* add shulker extraction and fix storing techreborn storage Only accept when nbt is null. Adds shulker-extracting support * fix when storeItemStack was empty * fix inputting stack at first * Use MC pair --------- Co-authored-by: modmuss50 <modmuss50@gmail.com>
This commit is contained in:
parent
9841d3332d
commit
8b527dbead
2 changed files with 116 additions and 5 deletions
|
@ -30,11 +30,15 @@ import net.fabricmc.fabric.api.transfer.v1.item.PlayerInventoryStorage;
|
||||||
import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleSlotStorage;
|
import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleSlotStorage;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.inventory.Inventories;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Formatting;
|
import net.minecraft.util.Formatting;
|
||||||
|
import net.minecraft.util.Pair;
|
||||||
|
import net.minecraft.util.collection.DefaultedList;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import reborncore.common.powerSystem.RcEnergyItem;
|
import reborncore.common.powerSystem.RcEnergyItem;
|
||||||
import reborncore.common.recipes.IRecipeInput;
|
import reborncore.common.recipes.IRecipeInput;
|
||||||
import team.reborn.energy.api.EnergyStorage;
|
import team.reborn.energy.api.EnergyStorage;
|
||||||
|
@ -78,6 +82,95 @@ public class ItemUtils {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean canExtractAnyFromShulker(ItemStack shulkerStack, ItemStack targetStack) {
|
||||||
|
//bundle method
|
||||||
|
List<ItemStack> stacks = getBlockEntityStacks(shulkerStack);
|
||||||
|
if (stacks == null) return false;
|
||||||
|
for (ItemStack stack : stacks) {
|
||||||
|
if (isItemEqual(targetStack, stack, true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public static int canExtractFromCachedShulker(List<ItemStack> stacks, ItemStack targetStack) {
|
||||||
|
//bundle method
|
||||||
|
if (stacks == null) return 0;
|
||||||
|
int defaultValue = 0;
|
||||||
|
for (ItemStack stack : stacks) {
|
||||||
|
if (isItemEqual(targetStack, stack, true)) {
|
||||||
|
defaultValue += stack.getCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isStackListEmpty(List<ItemStack> stacks) {
|
||||||
|
for (ItemStack stack : stacks) {
|
||||||
|
if (!stack.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int extractableFromCachedShulker(List<ItemStack> stacks, ItemStack targetStack, int maxAmount) {
|
||||||
|
int extracted = 0;
|
||||||
|
for (ItemStack stack : stacks) {
|
||||||
|
if (stack.isEmpty()) continue;
|
||||||
|
if (isItemEqual(targetStack, stack, true)) {
|
||||||
|
int count = stack.getCount();
|
||||||
|
int toExtract = Math.min(maxAmount, count);
|
||||||
|
stack.decrement(toExtract);
|
||||||
|
maxAmount -= toExtract;
|
||||||
|
extracted += toExtract;
|
||||||
|
}
|
||||||
|
if (maxAmount == 0) break;
|
||||||
|
if (maxAmount < 0) throw new AssertionError("Extracted more than required amount!");
|
||||||
|
}
|
||||||
|
return extracted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Pair<Integer, ItemStack> extractFromShulker(ItemStack shulkerStack, DefaultedList<ItemStack> entityStack, ItemStack targetStack, int capacity) {
|
||||||
|
ItemStack newStack = shulkerStack.copy();
|
||||||
|
if (entityStack == null) {
|
||||||
|
entityStack = getBlockEntityStacks(newStack);
|
||||||
|
}
|
||||||
|
if (entityStack == null) {
|
||||||
|
return new Pair<>(0, shulkerStack);
|
||||||
|
}
|
||||||
|
int extracted = extractableFromCachedShulker(entityStack, targetStack, capacity);
|
||||||
|
if (extracted == 0) {
|
||||||
|
return new Pair<>(0, shulkerStack);
|
||||||
|
}
|
||||||
|
NbtCompound blockEntityTag = newStack.getSubNbt("BlockEntityTag");
|
||||||
|
if (blockEntityTag == null) throw new IllegalStateException("BlockEntityTag is removed during operation!");
|
||||||
|
if (isStackListEmpty(entityStack)) {
|
||||||
|
if (blockEntityTag.contains("Items")) blockEntityTag.remove("Items");
|
||||||
|
if (blockEntityTag.getKeys().size() == 0) {
|
||||||
|
//remove empty nbt
|
||||||
|
blockEntityTag = null;
|
||||||
|
newStack.removeSubNbt("BlockEntityTag");
|
||||||
|
}
|
||||||
|
return new Pair<>(extracted, newStack);
|
||||||
|
}
|
||||||
|
Inventories.writeNbt(blockEntityTag, entityStack);
|
||||||
|
return new Pair<>(extracted, newStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @Nullable DefaultedList<ItemStack> getBlockEntityStacks(ItemStack targetStack) {
|
||||||
|
int maxSize = 128; // theorical max is 255
|
||||||
|
NbtCompound compound = targetStack.getSubNbt("BlockEntityTag");
|
||||||
|
if (compound == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
DefaultedList<ItemStack> returnStacks = DefaultedList.ofSize(maxSize, ItemStack.EMPTY);
|
||||||
|
if (compound.contains("Items")) {
|
||||||
|
Inventories.readNbt(compound, returnStacks);
|
||||||
|
}
|
||||||
|
return returnStacks;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isEqualIgnoreEnergy(ItemStack stack1, ItemStack stack2) {
|
public static boolean isEqualIgnoreEnergy(ItemStack stack1, ItemStack stack2) {
|
||||||
if (stack1 == stack2) {
|
if (stack1 == stack2) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -36,10 +36,12 @@ import net.minecraft.item.SkullItem;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Formatting;
|
import net.minecraft.util.Formatting;
|
||||||
|
import net.minecraft.util.collection.DefaultedList;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Direction;
|
import net.minecraft.util.math.Direction;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import oshi.util.tuples.Pair;
|
||||||
import reborncore.api.IListInfoProvider;
|
import reborncore.api.IListInfoProvider;
|
||||||
import reborncore.api.IToolDrop;
|
import reborncore.api.IToolDrop;
|
||||||
import reborncore.api.blockentity.InventoryProvider;
|
import reborncore.api.blockentity.InventoryProvider;
|
||||||
|
@ -90,7 +92,6 @@ public class StorageUnitBaseBlockEntity extends MachineBaseBlockEntity implement
|
||||||
inventory = new RebornInventory<>(2, "ItemInventory", 64, this);
|
inventory = new RebornInventory<>(2, "ItemInventory", 64, this);
|
||||||
configureEntity(type);
|
configureEntity(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureEntity(TRContent.StorageUnit type) {
|
private void configureEntity(TRContent.StorageUnit type) {
|
||||||
// Set capacity to local config unless overridden by server
|
// Set capacity to local config unless overridden by server
|
||||||
if(serverCapacity == -1){
|
if(serverCapacity == -1){
|
||||||
|
@ -184,7 +185,6 @@ public class StorageUnitBaseBlockEntity extends MachineBaseBlockEntity implement
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemStack processInput(ItemStack inputStack) {
|
public ItemStack processInput(ItemStack inputStack) {
|
||||||
|
|
||||||
if (!isValid(INPUT_SLOT, inputStack)){
|
if (!isValid(INPUT_SLOT, inputStack)){
|
||||||
return inputStack;
|
return inputStack;
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,21 @@ public class StorageUnitBaseBlockEntity extends MachineBaseBlockEntity implement
|
||||||
|
|
||||||
// Amount of items that can be added before reaching capacity
|
// Amount of items that can be added before reaching capacity
|
||||||
int reminder = maxCapacity - getCurrentCapacity();
|
int reminder = maxCapacity - getCurrentCapacity();
|
||||||
|
DefaultedList<ItemStack> optionalShulkerStack = ItemUtils.getBlockEntityStacks(inputStack);
|
||||||
|
if (isLocked() && ItemUtils.canExtractFromCachedShulker(optionalShulkerStack, lockedItemStack) > 0 ) {
|
||||||
|
Pair<Integer, ItemStack> pair = ItemUtils.extractFromShulker(inputStack, optionalShulkerStack, lockedItemStack, reminder);
|
||||||
|
if (pair.getA() != 0) {
|
||||||
|
int amount = pair.getA();
|
||||||
|
if (storeItemStack.isEmpty()) {
|
||||||
|
storeItemStack = lockedItemStack.copy();
|
||||||
|
amount = amount -1;
|
||||||
|
}
|
||||||
|
addStoredItemCount(amount);
|
||||||
|
inputStack.setNbt(pair.getB().getNbt());
|
||||||
|
inventory.setHashChanged();
|
||||||
|
}
|
||||||
|
return inputStack;
|
||||||
|
}
|
||||||
if (inputStack.getCount() <= reminder) {
|
if (inputStack.getCount() <= reminder) {
|
||||||
// Add full stack
|
// Add full stack
|
||||||
if (storeItemStack == ItemStack.EMPTY){
|
if (storeItemStack == ItemStack.EMPTY){
|
||||||
|
@ -251,7 +265,6 @@ public class StorageUnitBaseBlockEntity extends MachineBaseBlockEntity implement
|
||||||
if (world == null || world.isClient) {
|
if (world == null || world.isClient) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is an item in the input AND stored is less than max capacity
|
// If there is an item in the input AND stored is less than max capacity
|
||||||
if (!inventory.getStack(INPUT_SLOT).isEmpty() && !isFull()) {
|
if (!inventory.getStack(INPUT_SLOT).isEmpty() && !isFull()) {
|
||||||
inventory.setStack(INPUT_SLOT, processInput(inventory.getStack(INPUT_SLOT)));
|
inventory.setStack(INPUT_SLOT, processInput(inventory.getStack(INPUT_SLOT)));
|
||||||
|
@ -391,10 +404,15 @@ public class StorageUnitBaseBlockEntity extends MachineBaseBlockEntity implement
|
||||||
}
|
}
|
||||||
// do not allow other storage units to avoid NBT overflow. Fix #2580
|
// do not allow other storage units to avoid NBT overflow. Fix #2580
|
||||||
if (inputStack.isIn(TRContent.ItemTags.STORAGE_UNITS)) {
|
if (inputStack.isIn(TRContent.ItemTags.STORAGE_UNITS)) {
|
||||||
return false;
|
NbtCompound tagCompound = inputStack.getNbt();
|
||||||
|
return (tagCompound == null || tagCompound.getSize() == 0) && (getStoredStack().isEmpty() || ItemUtils.isItemEqual(getStoredStack(), inputStack, true, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLocked()) {
|
if (isLocked()) {
|
||||||
|
//allow shulker bundle extraction when locked
|
||||||
|
if (ItemUtils.canExtractAnyFromShulker(inputStack, lockedItemStack)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return ItemUtils.isItemEqual(lockedItemStack, inputStack, true, true);
|
return ItemUtils.isItemEqual(lockedItemStack, inputStack, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue