minecraft-src/net/minecraft/world/item/component/BundleContents.java
2025-07-04 01:41:11 +03:00

189 lines
5.5 KiB
Java

package net.minecraft.world.item.component;
import com.google.common.collect.Lists;
import com.mojang.serialization.Codec;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.inventory.tooltip.TooltipComponent;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BeehiveBlockEntity;
import org.apache.commons.lang3.math.Fraction;
import org.jetbrains.annotations.Nullable;
public final class BundleContents implements TooltipComponent {
public static final BundleContents EMPTY = new BundleContents(List.of());
public static final Codec<BundleContents> CODEC = ItemStack.CODEC.listOf().xmap(BundleContents::new, bundleContents -> bundleContents.items);
public static final StreamCodec<RegistryFriendlyByteBuf, BundleContents> STREAM_CODEC = ItemStack.STREAM_CODEC
.apply(ByteBufCodecs.list())
.map(BundleContents::new, bundleContents -> bundleContents.items);
private static final Fraction BUNDLE_IN_BUNDLE_WEIGHT = Fraction.getFraction(1, 16);
private static final int NO_STACK_INDEX = -1;
final List<ItemStack> items;
final Fraction weight;
BundleContents(List<ItemStack> items, Fraction weight) {
this.items = items;
this.weight = weight;
}
public BundleContents(List<ItemStack> items) {
this(items, computeContentWeight(items));
}
private static Fraction computeContentWeight(List<ItemStack> content) {
Fraction fraction = Fraction.ZERO;
for (ItemStack itemStack : content) {
fraction = fraction.add(getWeight(itemStack).multiplyBy(Fraction.getFraction(itemStack.getCount(), 1)));
}
return fraction;
}
static Fraction getWeight(ItemStack stack) {
BundleContents bundleContents = stack.get(DataComponents.BUNDLE_CONTENTS);
if (bundleContents != null) {
return BUNDLE_IN_BUNDLE_WEIGHT.add(bundleContents.weight());
} else {
List<BeehiveBlockEntity.Occupant> list = stack.getOrDefault(DataComponents.BEES, List.of());
return !list.isEmpty() ? Fraction.ONE : Fraction.getFraction(1, stack.getMaxStackSize());
}
}
public ItemStack getItemUnsafe(int index) {
return (ItemStack)this.items.get(index);
}
public Stream<ItemStack> itemCopyStream() {
return this.items.stream().map(ItemStack::copy);
}
public Iterable<ItemStack> items() {
return this.items;
}
public Iterable<ItemStack> itemsCopy() {
return Lists.<ItemStack, ItemStack>transform(this.items, ItemStack::copy);
}
public int size() {
return this.items.size();
}
public Fraction weight() {
return this.weight;
}
public boolean isEmpty() {
return this.items.isEmpty();
}
public boolean equals(Object object) {
if (this == object) {
return true;
} else {
return !(object instanceof BundleContents bundleContents)
? false
: this.weight.equals(bundleContents.weight) && ItemStack.listMatches(this.items, bundleContents.items);
}
}
public int hashCode() {
return ItemStack.hashStackList(this.items);
}
public String toString() {
return "BundleContents" + this.items;
}
public static class Mutable {
private final List<ItemStack> items;
private Fraction weight;
public Mutable(BundleContents contents) {
this.items = new ArrayList(contents.items);
this.weight = contents.weight;
}
public BundleContents.Mutable clearItems() {
this.items.clear();
this.weight = Fraction.ZERO;
return this;
}
private int findStackIndex(ItemStack stack) {
if (!stack.isStackable()) {
return -1;
} else {
for (int i = 0; i < this.items.size(); i++) {
if (ItemStack.isSameItemSameComponents((ItemStack)this.items.get(i), stack)) {
return i;
}
}
return -1;
}
}
private int getMaxAmountToAdd(ItemStack stack) {
Fraction fraction = Fraction.ONE.subtract(this.weight);
return Math.max(fraction.divideBy(BundleContents.getWeight(stack)).intValue(), 0);
}
public int tryInsert(ItemStack stack) {
if (!stack.isEmpty() && stack.getItem().canFitInsideContainerItems()) {
int i = Math.min(stack.getCount(), this.getMaxAmountToAdd(stack));
if (i == 0) {
return 0;
} else {
this.weight = this.weight.add(BundleContents.getWeight(stack).multiplyBy(Fraction.getFraction(i, 1)));
int j = this.findStackIndex(stack);
if (j != -1) {
ItemStack itemStack = (ItemStack)this.items.remove(j);
ItemStack itemStack2 = itemStack.copyWithCount(itemStack.getCount() + i);
stack.shrink(i);
this.items.add(0, itemStack2);
} else {
this.items.add(0, stack.split(i));
}
return i;
}
} else {
return 0;
}
}
public int tryTransfer(Slot slot, Player player) {
ItemStack itemStack = slot.getItem();
int i = this.getMaxAmountToAdd(itemStack);
return this.tryInsert(slot.safeTake(itemStack.getCount(), i, player));
}
@Nullable
public ItemStack removeOne() {
if (this.items.isEmpty()) {
return null;
} else {
ItemStack itemStack = ((ItemStack)this.items.remove(0)).copy();
this.weight = this.weight.subtract(BundleContents.getWeight(itemStack).multiplyBy(Fraction.getFraction(itemStack.getCount(), 1)));
return itemStack;
}
}
public Fraction weight() {
return this.weight;
}
public BundleContents toImmutable() {
return new BundleContents(List.copyOf(this.items), this.weight);
}
}
}