* 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;
|
package reborncore.common.blockentity;
|
||||||
|
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
import net.fabricmc.fabric.api.transfer.v1.item.InventoryStorage;
|
||||||
import it.unimi.dsi.fastutil.ints.IntList;
|
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.Inventory;
|
||||||
import net.minecraft.inventory.SidedInventory;
|
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.nbt.StringNbtReader;
|
import net.minecraft.nbt.StringNbtReader;
|
||||||
|
@ -37,8 +37,6 @@ import org.apache.commons.lang3.Validate;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import reborncore.RebornCore;
|
import reborncore.RebornCore;
|
||||||
import reborncore.api.items.InventoryUtils;
|
|
||||||
import reborncore.common.util.ItemUtils;
|
|
||||||
import reborncore.common.util.NBTSerializable;
|
import reborncore.common.util.NBTSerializable;
|
||||||
import reborncore.common.util.RebornInventory;
|
import reborncore.common.util.RebornInventory;
|
||||||
|
|
||||||
|
@ -291,53 +289,14 @@ public class SlotConfiguration implements NBTSerializable {
|
||||||
if (targetStack.getMaxCount() == targetStack.getCount()) {
|
if (targetStack.getMaxCount() == targetStack.getCount()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Inventory sourceInv = InventoryUtils.getInventoryAt(machineBase.getWorld(), machineBase.getPos().offset(side));
|
|
||||||
if (sourceInv == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IntList availableSlots = null;
|
StorageUtil.move(
|
||||||
|
ItemStorage.SIDED.find(machineBase.getWorld(), machineBase.getPos().offset(side), side.getOpposite()),
|
||||||
if (sourceInv instanceof SidedInventory) {
|
InventoryStorage.of(machineBase, null).getSlot(slotID),
|
||||||
availableSlots = IntArrayList.wrap(((SidedInventory) sourceInv).getAvailableSlots(side.getOpposite()));
|
iv -> true,
|
||||||
}
|
4, // Move up to 4 per tick.
|
||||||
|
null
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleItemOutput(MachineBaseBlockEntity machineBase) {
|
private void handleItemOutput(MachineBaseBlockEntity machineBase) {
|
||||||
|
@ -346,13 +305,14 @@ public class SlotConfiguration implements NBTSerializable {
|
||||||
if (sourceStack.isEmpty()) {
|
if (sourceStack.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Inventory destInventory = InventoryUtils.getInventoryAt(machineBase.getWorld(), machineBase.getPos().offset(side));
|
|
||||||
if (destInventory == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemStack stack = InventoryUtils.insertItem(sourceStack, destInventory, side.getOpposite());
|
StorageUtil.move(
|
||||||
inventory.setStack(slotID, stack);
|
InventoryStorage.of(machineBase, null).getSlot(slotID),
|
||||||
|
ItemStorage.SIDED.find(machineBase.getWorld(), machineBase.getPos().offset(side), side.getOpposite()),
|
||||||
|
iv -> true,
|
||||||
|
Long.MAX_VALUE,
|
||||||
|
null
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|
|
@ -24,6 +24,10 @@
|
||||||
|
|
||||||
package reborncore.common.blocks;
|
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.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.InventoryProvider;
|
import net.minecraft.block.InventoryProvider;
|
||||||
|
@ -50,7 +54,6 @@ import reborncore.api.ToolManager;
|
||||||
import reborncore.api.blockentity.IMachineGuiHandler;
|
import reborncore.api.blockentity.IMachineGuiHandler;
|
||||||
import reborncore.api.blockentity.IUpgrade;
|
import reborncore.api.blockentity.IUpgrade;
|
||||||
import reborncore.api.blockentity.IUpgradeable;
|
import reborncore.api.blockentity.IUpgradeable;
|
||||||
import reborncore.api.items.InventoryUtils;
|
|
||||||
import reborncore.common.BaseBlockEntityProvider;
|
import reborncore.common.BaseBlockEntityProvider;
|
||||||
import reborncore.common.blockentity.MachineBaseBlockEntity;
|
import reborncore.common.blockentity.MachineBaseBlockEntity;
|
||||||
import reborncore.common.fluid.FluidUtil;
|
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) {
|
} else if (stack.getItem() instanceof IUpgrade && blockEntity instanceof IUpgradeable upgradeableEntity) {
|
||||||
if (upgradeableEntity.canBeUpgraded()) {
|
if (upgradeableEntity.canBeUpgraded()) {
|
||||||
if (InventoryUtils.insertItemStacked(upgradeableEntity.getUpgradeInvetory(), stack,
|
int inserted = (int) insertItemStacked(
|
||||||
true).getCount() > 0) {
|
InventoryStorage.of(upgradeableEntity.getUpgradeInvetory(), null),
|
||||||
stack = InventoryUtils.insertItemStacked(upgradeableEntity.getUpgradeInvetory(), stack, false);
|
ItemVariant.of(stack),
|
||||||
playerIn.setStackInHand(Hand.MAIN_HAND, stack);
|
stack.getCount()
|
||||||
return ActionResult.SUCCESS;
|
);
|
||||||
|
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);
|
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")
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public BlockState rotate(BlockState state, BlockRotation rotation) {
|
public BlockState rotate(BlockState state, BlockRotation rotation) {
|
||||||
|
|
|
@ -24,11 +24,13 @@
|
||||||
|
|
||||||
package techreborn.blockentity.machine.tier1;
|
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.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
import net.minecraft.block.entity.HopperBlockEntity;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.inventory.Inventory;
|
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.sound.SoundCategory;
|
import net.minecraft.sound.SoundCategory;
|
||||||
|
@ -44,8 +46,6 @@ import techreborn.init.ModSounds;
|
||||||
import techreborn.init.TRBlockEntities;
|
import techreborn.init.TRBlockEntities;
|
||||||
import techreborn.init.TRContent;
|
import techreborn.init.TRContent;
|
||||||
|
|
||||||
import static reborncore.api.items.InventoryUtils.getInventoryAt;
|
|
||||||
|
|
||||||
public class ResinBasinBlockEntity extends MachineBaseBlockEntity {
|
public class ResinBasinBlockEntity extends MachineBaseBlockEntity {
|
||||||
private Direction direction = Direction.NORTH;
|
private Direction direction = Direction.NORTH;
|
||||||
|
|
||||||
|
@ -92,16 +92,15 @@ public class ResinBasinBlockEntity extends MachineBaseBlockEntity {
|
||||||
// Try and deposit
|
// Try and deposit
|
||||||
if (isFull) {
|
if (isFull) {
|
||||||
// Get inventory
|
// Get inventory
|
||||||
Inventory invBelow = getInventoryBelow();
|
Storage<ItemVariant> invBelow = getInventoryBelow();
|
||||||
if (invBelow != null) {
|
if (invBelow != null) {
|
||||||
|
try (Transaction tx = Transaction.openOuter()) {
|
||||||
ItemStack out = new ItemStack(TRContent.Parts.SAP, (Math.random() <= 0.5) ? 1 : 2);
|
int sentAmount = (Math.random() <= 0.5) ? 1 : 2;
|
||||||
out = HopperBlockEntity.transfer(null, invBelow, out, Direction.UP);
|
if (invBelow.insert(ItemVariant.of(TRContent.Parts.SAP), sentAmount, tx) > 0) {
|
||||||
|
tx.commit();
|
||||||
if (out.isEmpty()) {
|
isFull = false;
|
||||||
// Successfully deposited
|
shouldUpdateState = true;
|
||||||
isFull = false;
|
}
|
||||||
shouldUpdateState = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,8 +169,8 @@ public class ResinBasinBlockEntity extends MachineBaseBlockEntity {
|
||||||
direction = world.getBlockState(pos).get(ResinBasinBlock.FACING).getOpposite();
|
direction = world.getBlockState(pos).get(ResinBasinBlock.FACING).getOpposite();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Inventory getInventoryBelow() {
|
private Storage<ItemVariant> getInventoryBelow() {
|
||||||
return getInventoryAt(this.getWorld(), this.pos.offset(Direction.DOWN));
|
return ItemStorage.SIDED.find(this.getWorld(), this.pos.offset(Direction.DOWN), Direction.UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean validPlacement() {
|
private boolean validPlacement() {
|
||||||
|
|
Loading…
Reference in a new issue