* Fix #2574: Use the fabric item API for auto input and auto output * Only auto-insert at most 4 items at once
This commit is contained in:
parent
9958324539
commit
b300456e77
4 changed files with 65 additions and 205 deletions
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* This file is part of RebornCore, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2021 TeamReborn
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package reborncore.api.items;
|
||||
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.block.entity.ChestBlockEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.inventory.SidedInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import reborncore.common.util.ItemUtils;
|
||||
|
||||
public class InventoryUtils {
|
||||
|
||||
public static ItemStack insertItemStacked(Inventory inventory, ItemStack input, boolean simulate) {
|
||||
ItemStack stack = input.copy();
|
||||
for (int i = 0; i < inventory.size(); i++) {
|
||||
ItemStack targetStack = inventory.getStack(i);
|
||||
|
||||
//Nice and simple, insert the item into a blank slot
|
||||
if (targetStack.isEmpty()) {
|
||||
if (!simulate) {
|
||||
inventory.setStack(i, stack);
|
||||
}
|
||||
return ItemStack.EMPTY;
|
||||
} else if (ItemUtils.isItemEqual(stack, targetStack, true, false)) {
|
||||
int freeStackSpace = targetStack.getMaxCount() - targetStack.getCount();
|
||||
if (freeStackSpace > 0) {
|
||||
int transferAmount = Math.min(freeStackSpace, input.getCount());
|
||||
if (!simulate) {
|
||||
targetStack.increment(transferAmount);
|
||||
}
|
||||
stack.decrement(transferAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
public static ItemStack insertItem(ItemStack input, Inventory inventory, Direction direction) {
|
||||
ItemStack stack = input.copy();
|
||||
|
||||
if (inventory instanceof SidedInventory sidedInventory) {
|
||||
for (int slot : sidedInventory.getAvailableSlots(direction)) {
|
||||
if (sidedInventory.canInsert(slot, stack, direction)) {
|
||||
stack = insertIntoInv(sidedInventory, slot, stack);
|
||||
if (stack.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
} else {
|
||||
for (int i = 0; i < inventory.size() & !stack.isEmpty(); i++) {
|
||||
if (inventory.isValid(i, stack)) {
|
||||
stack = insertIntoInv(inventory, i, stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Inventory getInventoryAt(World world, BlockPos blockPos) {
|
||||
Inventory inventory = null;
|
||||
BlockState blockState = world.getBlockState(blockPos);
|
||||
Block block = blockState.getBlock();
|
||||
if (block instanceof InventoryProvider) {
|
||||
inventory = ((InventoryProvider) block).getInventory(blockState, world, blockPos);
|
||||
} else if (block instanceof BlockEntityProvider) {
|
||||
BlockEntity blockEntity = world.getBlockEntity(blockPos);
|
||||
if (blockEntity instanceof Inventory) {
|
||||
inventory = (Inventory) blockEntity;
|
||||
if (inventory instanceof ChestBlockEntity && block instanceof ChestBlock) {
|
||||
inventory = ChestBlock.getInventory((ChestBlock) block, blockState, world, blockPos, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return inventory;
|
||||
}
|
||||
|
||||
private static ItemStack insertIntoInv(Inventory inventory, int slot, ItemStack input) {
|
||||
ItemStack targetStack = inventory.getStack(slot);
|
||||
ItemStack stack = input.copy();
|
||||
|
||||
//Nice and simple, insert the item into a blank slot
|
||||
if (targetStack.isEmpty()) {
|
||||
inventory.setStack(slot, stack);
|
||||
return ItemStack.EMPTY;
|
||||
} else if (ItemUtils.isItemEqual(stack, targetStack, true, false)) {
|
||||
int freeStackSpace = targetStack.getMaxCount() - targetStack.getCount();
|
||||
if (freeStackSpace > 0) {
|
||||
int transferAmount = Math.min(freeStackSpace, stack.getCount());
|
||||
targetStack.increment(transferAmount);
|
||||
stack.decrement(transferAmount);
|
||||
}
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
}
|
|
@ -25,10 +25,10 @@
|
|||
package reborncore.common.blockentity;
|
||||
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.InventoryStorage;
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage;
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.StorageUtil;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.inventory.SidedInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.StringNbtReader;
|
||||
|
@ -37,8 +37,6 @@ import org.apache.commons.lang3.Validate;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import reborncore.RebornCore;
|
||||
import reborncore.api.items.InventoryUtils;
|
||||
import reborncore.common.util.ItemUtils;
|
||||
import reborncore.common.util.NBTSerializable;
|
||||
import reborncore.common.util.RebornInventory;
|
||||
|
||||
|
@ -291,53 +289,14 @@ public class SlotConfiguration implements NBTSerializable {
|
|||
if (targetStack.getMaxCount() == targetStack.getCount()) {
|
||||
return;
|
||||
}
|
||||
Inventory sourceInv = InventoryUtils.getInventoryAt(machineBase.getWorld(), machineBase.getPos().offset(side));
|
||||
if (sourceInv == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
IntList availableSlots = null;
|
||||
|
||||
if (sourceInv instanceof SidedInventory) {
|
||||
availableSlots = IntArrayList.wrap(((SidedInventory) sourceInv).getAvailableSlots(side.getOpposite()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < sourceInv.size(); i++) {
|
||||
if (availableSlots != null && !availableSlots.contains(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ItemStack sourceStack = sourceInv.getStack(i);
|
||||
if (sourceStack.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if(!canInsertItem(slotID, sourceStack, side, machineBase)){
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sourceInv instanceof SidedInventory && !((SidedInventory) sourceInv).canExtract(i, sourceStack, side.getOpposite())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//Checks if we are going to merge stacks that the items are the same
|
||||
if (!targetStack.isEmpty()) {
|
||||
if (!ItemUtils.isItemEqual(sourceStack, targetStack, true, false)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
int extract = 4;
|
||||
if (!targetStack.isEmpty()) {
|
||||
extract = Math.min(targetStack.getMaxCount() - targetStack.getCount(), extract);
|
||||
}
|
||||
ItemStack extractedStack = sourceInv.removeStack(i, extract);
|
||||
if (targetStack.isEmpty()) {
|
||||
inventory.setStack(slotID, extractedStack);
|
||||
} else {
|
||||
inventory.getStack(slotID).increment(extractedStack.getCount());
|
||||
}
|
||||
inventory.setHashChanged();
|
||||
break;
|
||||
}
|
||||
StorageUtil.move(
|
||||
ItemStorage.SIDED.find(machineBase.getWorld(), machineBase.getPos().offset(side), side.getOpposite()),
|
||||
InventoryStorage.of(machineBase, null).getSlot(slotID),
|
||||
iv -> true,
|
||||
4, // Move up to 4 per tick.
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
private void handleItemOutput(MachineBaseBlockEntity machineBase) {
|
||||
|
@ -346,13 +305,14 @@ public class SlotConfiguration implements NBTSerializable {
|
|||
if (sourceStack.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Inventory destInventory = InventoryUtils.getInventoryAt(machineBase.getWorld(), machineBase.getPos().offset(side));
|
||||
if (destInventory == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack stack = InventoryUtils.insertItem(sourceStack, destInventory, side.getOpposite());
|
||||
inventory.setStack(slotID, stack);
|
||||
StorageUtil.move(
|
||||
InventoryStorage.of(machineBase, null).getSlot(slotID),
|
||||
ItemStorage.SIDED.find(machineBase.getWorld(), machineBase.getPos().offset(side), side.getOpposite()),
|
||||
iv -> true,
|
||||
Long.MAX_VALUE,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
|
||||
package reborncore.common.blocks;
|
||||
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.InventoryStorage;
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleSlotStorage;
|
||||
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.InventoryProvider;
|
||||
|
@ -50,7 +54,6 @@ import reborncore.api.ToolManager;
|
|||
import reborncore.api.blockentity.IMachineGuiHandler;
|
||||
import reborncore.api.blockentity.IUpgrade;
|
||||
import reborncore.api.blockentity.IUpgradeable;
|
||||
import reborncore.api.items.InventoryUtils;
|
||||
import reborncore.common.BaseBlockEntityProvider;
|
||||
import reborncore.common.blockentity.MachineBaseBlockEntity;
|
||||
import reborncore.common.fluid.FluidUtil;
|
||||
|
@ -196,11 +199,14 @@ public abstract class BlockMachineBase extends BaseBlockEntityProvider implement
|
|||
}
|
||||
} else if (stack.getItem() instanceof IUpgrade && blockEntity instanceof IUpgradeable upgradeableEntity) {
|
||||
if (upgradeableEntity.canBeUpgraded()) {
|
||||
if (InventoryUtils.insertItemStacked(upgradeableEntity.getUpgradeInvetory(), stack,
|
||||
true).getCount() > 0) {
|
||||
stack = InventoryUtils.insertItemStacked(upgradeableEntity.getUpgradeInvetory(), stack, false);
|
||||
playerIn.setStackInHand(Hand.MAIN_HAND, stack);
|
||||
return ActionResult.SUCCESS;
|
||||
int inserted = (int) insertItemStacked(
|
||||
InventoryStorage.of(upgradeableEntity.getUpgradeInvetory(), null),
|
||||
ItemVariant.of(stack),
|
||||
stack.getCount()
|
||||
);
|
||||
if (inserted > 0) {
|
||||
stack.decrement(inserted);
|
||||
return ActionResult.success(worldIn.isClient());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -214,6 +220,28 @@ public abstract class BlockMachineBase extends BaseBlockEntityProvider implement
|
|||
return super.onUse(state, worldIn, pos, playerIn, hand, hitResult);
|
||||
}
|
||||
|
||||
// TODO: use the fabric one when it will be PR'ed.
|
||||
@SuppressWarnings({"deprecation", "UnstableApiUsage"})
|
||||
public static long insertItemStacked(InventoryStorage inventory, ItemVariant variant, long maxAmount) {
|
||||
long inserted = 0;
|
||||
try (Transaction tx = Transaction.openOuter()) {
|
||||
outer: for (int loop = 0; loop < 2; ++loop) {
|
||||
for (SingleSlotStorage<ItemVariant> slot : inventory.getSlots()) {
|
||||
if (slot.getResource().equals(variant) || loop == 1) {
|
||||
inserted += slot.insert(variant, maxAmount - inserted, tx);
|
||||
|
||||
if (inserted == maxAmount) {
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tx.commit();
|
||||
}
|
||||
return inserted;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public BlockState rotate(BlockState state, BlockRotation rotation) {
|
||||
|
|
|
@ -24,11 +24,13 @@
|
|||
|
||||
package techreborn.blockentity.machine.tier1;
|
||||
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage;
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.Storage;
|
||||
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.entity.HopperBlockEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
|
@ -44,8 +46,6 @@ import techreborn.init.ModSounds;
|
|||
import techreborn.init.TRBlockEntities;
|
||||
import techreborn.init.TRContent;
|
||||
|
||||
import static reborncore.api.items.InventoryUtils.getInventoryAt;
|
||||
|
||||
public class ResinBasinBlockEntity extends MachineBaseBlockEntity {
|
||||
private Direction direction = Direction.NORTH;
|
||||
|
||||
|
@ -92,16 +92,15 @@ public class ResinBasinBlockEntity extends MachineBaseBlockEntity {
|
|||
// Try and deposit
|
||||
if (isFull) {
|
||||
// Get inventory
|
||||
Inventory invBelow = getInventoryBelow();
|
||||
Storage<ItemVariant> invBelow = getInventoryBelow();
|
||||
if (invBelow != null) {
|
||||
|
||||
ItemStack out = new ItemStack(TRContent.Parts.SAP, (Math.random() <= 0.5) ? 1 : 2);
|
||||
out = HopperBlockEntity.transfer(null, invBelow, out, Direction.UP);
|
||||
|
||||
if (out.isEmpty()) {
|
||||
// Successfully deposited
|
||||
isFull = false;
|
||||
shouldUpdateState = true;
|
||||
try (Transaction tx = Transaction.openOuter()) {
|
||||
int sentAmount = (Math.random() <= 0.5) ? 1 : 2;
|
||||
if (invBelow.insert(ItemVariant.of(TRContent.Parts.SAP), sentAmount, tx) > 0) {
|
||||
tx.commit();
|
||||
isFull = false;
|
||||
shouldUpdateState = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,8 +169,8 @@ public class ResinBasinBlockEntity extends MachineBaseBlockEntity {
|
|||
direction = world.getBlockState(pos).get(ResinBasinBlock.FACING).getOpposite();
|
||||
}
|
||||
|
||||
private Inventory getInventoryBelow() {
|
||||
return getInventoryAt(this.getWorld(), this.pos.offset(Direction.DOWN));
|
||||
private Storage<ItemVariant> getInventoryBelow() {
|
||||
return ItemStorage.SIDED.find(this.getWorld(), this.pos.offset(Direction.DOWN), Direction.UP);
|
||||
}
|
||||
|
||||
private boolean validPlacement() {
|
||||
|
|
Loading…
Reference in a new issue