2016-06-22 23:49:47 -04:00
|
|
|
/*
|
2022-04-14 03:42:00 +00:00
|
|
|
* Copyright (c) Forge Development LLC and contributors
|
2022-02-28 13:41:23 -08:00
|
|
|
* SPDX-License-Identifier: LGPL-2.1-only
|
2016-06-22 23:49:47 -04:00
|
|
|
*/
|
|
|
|
|
|
2016-01-17 16:41:34 +00:00
|
|
|
package net.minecraftforge.items;
|
|
|
|
|
|
2021-07-17 00:08:49 -05:00
|
|
|
import net.minecraft.world.entity.item.ItemEntity;
|
|
|
|
|
import net.minecraft.world.entity.player.Player;
|
|
|
|
|
import net.minecraft.sounds.SoundEvents;
|
|
|
|
|
import net.minecraft.world.item.ItemStack;
|
|
|
|
|
import net.minecraft.sounds.SoundSource;
|
|
|
|
|
import net.minecraft.util.Mth;
|
|
|
|
|
import net.minecraft.world.level.Level;
|
2016-01-02 14:38:18 +01:00
|
|
|
import net.minecraftforge.items.wrapper.PlayerMainInvWrapper;
|
2022-06-07 15:31:26 -05:00
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
|
import org.jetbrains.annotations.Nullable;
|
2016-11-13 17:09:54 -05:00
|
|
|
|
2024-04-30 10:56:00 -07:00
|
|
|
public class ItemHandlerHelper {
|
2022-06-07 15:31:26 -05:00
|
|
|
@NotNull
|
2024-04-30 10:56:00 -07:00
|
|
|
public static ItemStack insertItem(IItemHandler dest, @NotNull ItemStack stack, boolean simulate) {
|
2016-12-21 15:52:30 -08:00
|
|
|
if (dest == null || stack.isEmpty())
|
2017-04-25 12:06:23 -07:00
|
|
|
return stack;
|
2016-01-17 16:41:34 +00:00
|
|
|
|
2024-04-30 10:56:00 -07:00
|
|
|
for (int i = 0; i < dest.getSlots(); i++) {
|
2016-01-17 16:41:34 +00:00
|
|
|
stack = dest.insertItem(i, stack, simulate);
|
2024-04-30 10:56:00 -07:00
|
|
|
if (stack.isEmpty()) {
|
2016-12-21 15:52:30 -08:00
|
|
|
return ItemStack.EMPTY;
|
2016-01-17 16:41:34 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return stack;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-30 10:56:00 -07:00
|
|
|
public static boolean canItemStacksStack(@NotNull ItemStack a, @NotNull ItemStack b) {
|
|
|
|
|
return ItemStack.isSameItemSameComponents(a, b);
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
|
2022-06-07 15:31:26 -05:00
|
|
|
@NotNull
|
2024-04-30 10:56:00 -07:00
|
|
|
public static ItemStack copyStackWithSize(@NotNull ItemStack itemStack, int size) {
|
2016-01-17 16:41:34 +00:00
|
|
|
if (size == 0)
|
2016-12-21 15:52:30 -08:00
|
|
|
return ItemStack.EMPTY;
|
2016-11-13 17:09:54 -05:00
|
|
|
ItemStack copy = itemStack.copy();
|
2016-12-21 15:52:30 -08:00
|
|
|
copy.setCount(size);
|
2016-01-17 16:41:34 +00:00
|
|
|
return copy;
|
|
|
|
|
}
|
2016-01-02 14:38:18 +01:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Inserts the ItemStack into the inventory, filling up already present stacks first.
|
|
|
|
|
* This is equivalent to the behaviour of a player picking up an item.
|
|
|
|
|
* Note: This function stacks items without subtypes with different metadata together.
|
|
|
|
|
*/
|
2022-06-07 15:31:26 -05:00
|
|
|
@NotNull
|
2024-04-30 10:56:00 -07:00
|
|
|
public static ItemStack insertItemStacked(IItemHandler inventory, @NotNull ItemStack stack, boolean simulate) {
|
2016-12-21 15:52:30 -08:00
|
|
|
if (inventory == null || stack.isEmpty())
|
2016-01-02 14:38:18 +01:00
|
|
|
return stack;
|
|
|
|
|
|
|
|
|
|
// not stackable -> just insert into a new slot
|
2024-04-30 10:56:00 -07:00
|
|
|
if (!stack.isStackable()) {
|
2016-01-02 14:38:18 +01:00
|
|
|
return insertItem(inventory, stack, simulate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sizeInventory = inventory.getSlots();
|
|
|
|
|
|
|
|
|
|
// go through the inventory and try to fill up already existing items
|
2024-04-30 10:56:00 -07:00
|
|
|
for (int i = 0; i < sizeInventory; i++) {
|
2016-01-02 14:38:18 +01:00
|
|
|
ItemStack slot = inventory.getStackInSlot(i);
|
2024-04-30 10:56:00 -07:00
|
|
|
if (canItemStacksStack(slot, stack)) {
|
2016-01-02 14:38:18 +01:00
|
|
|
stack = inventory.insertItem(i, stack, simulate);
|
|
|
|
|
|
2024-04-30 10:56:00 -07:00
|
|
|
if (stack.isEmpty()) {
|
2016-01-02 14:38:18 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// insert remainder into empty slots
|
2024-04-30 10:56:00 -07:00
|
|
|
if (!stack.isEmpty()) {
|
2016-01-02 14:38:18 +01:00
|
|
|
// find empty slot
|
2024-04-30 10:56:00 -07:00
|
|
|
for (int i = 0; i < sizeInventory; i++) {
|
|
|
|
|
if (inventory.getStackInSlot(i).isEmpty()) {
|
2016-01-02 14:38:18 +01:00
|
|
|
stack = inventory.insertItem(i, stack, simulate);
|
2024-04-30 10:56:00 -07:00
|
|
|
if (stack.isEmpty()) {
|
2016-01-02 14:38:18 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return stack;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** giveItemToPlayer without preferred slot */
|
2022-06-07 15:31:26 -05:00
|
|
|
public static void giveItemToPlayer(Player player, @NotNull ItemStack stack) {
|
2016-01-02 14:38:18 +01:00
|
|
|
giveItemToPlayer(player, stack, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Inserts the given itemstack into the players inventory.
|
|
|
|
|
* If the inventory can't hold it, the item will be dropped in the world at the players position.
|
|
|
|
|
*
|
|
|
|
|
* @param player The player to give the item to
|
|
|
|
|
* @param stack The itemstack to insert
|
|
|
|
|
*/
|
2024-04-30 10:56:00 -07:00
|
|
|
public static void giveItemToPlayer(Player player, @NotNull ItemStack stack, int preferredSlot) {
|
2018-07-03 06:41:18 +01:00
|
|
|
if (stack.isEmpty()) return;
|
|
|
|
|
|
2021-07-17 00:08:49 -05:00
|
|
|
IItemHandler inventory = new PlayerMainInvWrapper(player.getInventory());
|
2023-04-01 20:45:29 -05:00
|
|
|
Level level = player.level();
|
2016-01-02 14:38:18 +01:00
|
|
|
|
|
|
|
|
// try adding it into the inventory
|
2016-04-04 15:44:03 -07:00
|
|
|
ItemStack remainder = stack;
|
2016-01-02 14:38:18 +01:00
|
|
|
// insert into preferred slot first
|
2024-04-30 10:56:00 -07:00
|
|
|
if (preferredSlot >= 0 && preferredSlot < inventory.getSlots()) {
|
2016-01-02 14:38:18 +01:00
|
|
|
remainder = inventory.insertItem(preferredSlot, stack, false);
|
|
|
|
|
}
|
2024-04-30 10:56:00 -07:00
|
|
|
|
2016-01-02 14:38:18 +01:00
|
|
|
// then into the inventory in general
|
2024-04-30 10:56:00 -07:00
|
|
|
if (!remainder.isEmpty()) {
|
2016-04-04 15:44:03 -07:00
|
|
|
remainder = insertItemStacked(inventory, remainder, false);
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// play sound if something got picked up
|
2024-04-30 10:56:00 -07:00
|
|
|
if (remainder.isEmpty() || remainder.getCount() != stack.getCount()) {
|
2022-03-02 02:59:37 +08:00
|
|
|
level.playSound(null, player.getX(), player.getY() + 0.5, player.getZ(),
|
|
|
|
|
SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, 0.2F, ((level.random.nextFloat() - level.random.nextFloat()) * 0.7F + 1.0F) * 2.0F);
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
|
2022-03-02 02:59:37 +08:00
|
|
|
// drop remaining itemstack into the level
|
2024-04-30 10:56:00 -07:00
|
|
|
if (!remainder.isEmpty() && !level.isClientSide) {
|
2022-03-02 02:59:37 +08:00
|
|
|
ItemEntity entityitem = new ItemEntity(level, player.getX(), player.getY() + 0.5, player.getZ(), remainder);
|
2021-03-09 13:37:23 -08:00
|
|
|
entityitem.setPickUpDelay(40);
|
|
|
|
|
entityitem.setDeltaMovement(entityitem.getDeltaMovement().multiply(0, 1, 0));
|
2016-01-02 14:38:18 +01:00
|
|
|
|
2022-03-02 02:59:37 +08:00
|
|
|
level.addFreshEntity(entityitem);
|
2016-01-02 14:38:18 +01:00
|
|
|
}
|
|
|
|
|
}
|
2016-11-28 18:03:47 -06:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This method uses the standard vanilla algorithm to calculate a comparator output for how "full" the inventory is.
|
|
|
|
|
* This method is an adaptation of Container#calcRedstoneFromInventory(IInventory).
|
|
|
|
|
* @param inv The inventory handler to test.
|
|
|
|
|
* @return A redstone value in the range [0,15] representing how "full" this inventory is.
|
|
|
|
|
*/
|
2024-04-30 10:56:00 -07:00
|
|
|
public static int calcRedstoneFromInventory(@Nullable IItemHandler inv) {
|
|
|
|
|
if (inv == null) {
|
2016-11-28 18:03:47 -06:00
|
|
|
return 0;
|
2024-04-30 10:56:00 -07:00
|
|
|
} else {
|
2016-11-28 18:03:47 -06:00
|
|
|
int itemsFound = 0;
|
|
|
|
|
float proportion = 0.0F;
|
|
|
|
|
|
2024-04-30 10:56:00 -07:00
|
|
|
for (int j = 0; j < inv.getSlots(); ++j) {
|
2016-11-28 18:03:47 -06:00
|
|
|
ItemStack itemstack = inv.getStackInSlot(j);
|
|
|
|
|
|
2024-04-30 10:56:00 -07:00
|
|
|
if (!itemstack.isEmpty()) {
|
2016-12-21 15:52:30 -08:00
|
|
|
proportion += (float)itemstack.getCount() / (float)Math.min(inv.getSlotLimit(j), itemstack.getMaxStackSize());
|
2016-11-28 18:03:47 -06:00
|
|
|
++itemsFound;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proportion = proportion / (float)inv.getSlots();
|
2021-07-17 00:08:49 -05:00
|
|
|
return Mth.floor(proportion * 14.0F) + (itemsFound > 0 ? 1 : 0);
|
2016-11-28 18:03:47 -06:00
|
|
|
}
|
|
|
|
|
}
|
2016-01-17 16:41:34 +00:00
|
|
|
}
|