package net.minecraft.world.inventory; import com.mojang.logging.LogUtils; import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; import javax.annotation.Nullable; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.tags.BlockTags; import net.minecraft.util.Mth; import net.minecraft.util.StringUtil; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.ItemEnchantments; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.AnvilBlock; import net.minecraft.world.level.block.state.BlockState; import org.slf4j.Logger; public class AnvilMenu extends ItemCombinerMenu { public static final int INPUT_SLOT = 0; public static final int ADDITIONAL_SLOT = 1; public static final int RESULT_SLOT = 2; private static final Logger LOGGER = LogUtils.getLogger(); private static final boolean DEBUG_COST = false; public static final int MAX_NAME_LENGTH = 50; private int repairItemCountCost; @Nullable private String itemName; private final DataSlot cost = DataSlot.standalone(); private boolean onlyRenaming = false; private static final int COST_FAIL = 0; private static final int COST_BASE = 1; private static final int COST_ADDED_BASE = 1; private static final int COST_REPAIR_MATERIAL = 1; private static final int COST_REPAIR_SACRIFICE = 2; private static final int COST_INCOMPATIBLE_PENALTY = 1; private static final int COST_RENAME = 1; private static final int INPUT_SLOT_X_PLACEMENT = 27; private static final int ADDITIONAL_SLOT_X_PLACEMENT = 76; private static final int RESULT_SLOT_X_PLACEMENT = 134; private static final int SLOT_Y_PLACEMENT = 47; public AnvilMenu(int p_39005_, Inventory p_39006_) { this(p_39005_, p_39006_, ContainerLevelAccess.NULL); } public AnvilMenu(int p_39008_, Inventory p_39009_, ContainerLevelAccess p_39010_) { super(MenuType.ANVIL, p_39008_, p_39009_, p_39010_, createInputSlotDefinitions()); this.addDataSlot(this.cost); } private static ItemCombinerMenuSlotDefinition createInputSlotDefinitions() { return ItemCombinerMenuSlotDefinition.create() .withSlot(0, 27, 47, p_266635_ -> true) .withSlot(1, 76, 47, p_266634_ -> true) .withResultSlot(2, 134, 47) .build(); } @Override protected boolean isValidBlock(BlockState p_39019_) { return p_39019_.is(BlockTags.ANVIL); } @Override protected boolean mayPickup(Player p_39023_, boolean p_39024_) { return (p_39023_.hasInfiniteMaterials() || p_39023_.experienceLevel >= this.cost.get()) && this.cost.get() > 0; } @Override protected void onTake(Player p_150474_, ItemStack p_150475_) { if (!p_150474_.hasInfiniteMaterials()) { p_150474_.giveExperienceLevels(-this.cost.get()); } if (this.repairItemCountCost > 0) { ItemStack itemstack = this.inputSlots.getItem(1); if (!itemstack.isEmpty() && itemstack.getCount() > this.repairItemCountCost) { itemstack.shrink(this.repairItemCountCost); this.inputSlots.setItem(1, itemstack); } else { this.inputSlots.setItem(1, ItemStack.EMPTY); } } else if (!this.onlyRenaming) { this.inputSlots.setItem(1, ItemStack.EMPTY); } this.cost.set(0); this.inputSlots.setItem(0, ItemStack.EMPTY); this.access.execute((p_150479_, p_150480_) -> { BlockState blockstate = p_150479_.getBlockState(p_150480_); if (!p_150474_.hasInfiniteMaterials() && blockstate.is(BlockTags.ANVIL) && p_150474_.getRandom().nextFloat() < 0.12F) { BlockState blockstate1 = AnvilBlock.damage(blockstate); if (blockstate1 == null) { p_150479_.removeBlock(p_150480_, false); p_150479_.levelEvent(1029, p_150480_, 0); } else { p_150479_.setBlock(p_150480_, blockstate1, 2); p_150479_.levelEvent(1030, p_150480_, 0); } } else { p_150479_.levelEvent(1030, p_150480_, 0); } }); } @Override public void createResult() { ItemStack itemstack = this.inputSlots.getItem(0); this.onlyRenaming = false; this.cost.set(1); int i = 0; long j = 0L; int k = 0; if (!itemstack.isEmpty() && EnchantmentHelper.canStoreEnchantments(itemstack)) { ItemStack itemstack1 = itemstack.copy(); ItemStack itemstack2 = this.inputSlots.getItem(1); ItemEnchantments.Mutable itemenchantments$mutable = new ItemEnchantments.Mutable(EnchantmentHelper.getEnchantmentsForCrafting(itemstack1)); j += (long)itemstack.getOrDefault(DataComponents.REPAIR_COST, 0).intValue() + itemstack2.getOrDefault(DataComponents.REPAIR_COST, 0).intValue(); this.repairItemCountCost = 0; if (!itemstack2.isEmpty()) { boolean flag = itemstack2.has(DataComponents.STORED_ENCHANTMENTS); if (itemstack1.isDamageableItem() && itemstack.isValidRepairItem(itemstack2)) { int l2 = Math.min(itemstack1.getDamageValue(), itemstack1.getMaxDamage() / 4); if (l2 <= 0) { this.resultSlots.setItem(0, ItemStack.EMPTY); this.cost.set(0); return; } int j3; for (j3 = 0; l2 > 0 && j3 < itemstack2.getCount(); j3++) { int k3 = itemstack1.getDamageValue() - l2; itemstack1.setDamageValue(k3); i++; l2 = Math.min(itemstack1.getDamageValue(), itemstack1.getMaxDamage() / 4); } this.repairItemCountCost = j3; } else { if (!flag && (!itemstack1.is(itemstack2.getItem()) || !itemstack1.isDamageableItem())) { this.resultSlots.setItem(0, ItemStack.EMPTY); this.cost.set(0); return; } if (itemstack1.isDamageableItem() && !flag) { int l = itemstack.getMaxDamage() - itemstack.getDamageValue(); int i1 = itemstack2.getMaxDamage() - itemstack2.getDamageValue(); int j1 = i1 + itemstack1.getMaxDamage() * 12 / 100; int k1 = l + j1; int l1 = itemstack1.getMaxDamage() - k1; if (l1 < 0) { l1 = 0; } if (l1 < itemstack1.getDamageValue()) { itemstack1.setDamageValue(l1); i += 2; } } ItemEnchantments itemenchantments = EnchantmentHelper.getEnchantmentsForCrafting(itemstack2); boolean flag2 = false; boolean flag3 = false; for (Entry> entry : itemenchantments.entrySet()) { Holder holder = entry.getKey(); int i2 = itemenchantments$mutable.getLevel(holder); int j2 = entry.getIntValue(); j2 = i2 == j2 ? j2 + 1 : Math.max(j2, i2); Enchantment enchantment = holder.value(); boolean flag1 = enchantment.canEnchant(itemstack); if (this.player.hasInfiniteMaterials() || itemstack.is(Items.ENCHANTED_BOOK)) { flag1 = true; } for (Holder holder1 : itemenchantments$mutable.keySet()) { if (!holder1.equals(holder) && !Enchantment.areCompatible(holder, holder1)) { flag1 = false; i++; } } if (!flag1) { flag3 = true; } else { flag2 = true; if (j2 > enchantment.getMaxLevel()) { j2 = enchantment.getMaxLevel(); } itemenchantments$mutable.set(holder, j2); int l3 = enchantment.getAnvilCost(); if (flag) { l3 = Math.max(1, l3 / 2); } i += l3 * j2; if (itemstack.getCount() > 1) { i = 40; } } } if (flag3 && !flag2) { this.resultSlots.setItem(0, ItemStack.EMPTY); this.cost.set(0); return; } } } if (this.itemName != null && !StringUtil.isBlank(this.itemName)) { if (!this.itemName.equals(itemstack.getHoverName().getString())) { k = 1; i += k; itemstack1.set(DataComponents.CUSTOM_NAME, Component.literal(this.itemName)); } } else if (itemstack.has(DataComponents.CUSTOM_NAME)) { k = 1; i += k; itemstack1.remove(DataComponents.CUSTOM_NAME); } int k2 = i <= 0 ? 0 : (int)Mth.clamp(j + i, 0L, 2147483647L); this.cost.set(k2); if (i <= 0) { itemstack1 = ItemStack.EMPTY; } if (k == i && k > 0) { if (this.cost.get() >= 40) { this.cost.set(39); } this.onlyRenaming = true; } if (this.cost.get() >= 40 && !this.player.hasInfiniteMaterials()) { itemstack1 = ItemStack.EMPTY; } if (!itemstack1.isEmpty()) { int i3 = itemstack1.getOrDefault(DataComponents.REPAIR_COST, 0); if (i3 < itemstack2.getOrDefault(DataComponents.REPAIR_COST, 0)) { i3 = itemstack2.getOrDefault(DataComponents.REPAIR_COST, 0); } if (k != i || k == 0) { i3 = calculateIncreasedRepairCost(i3); } itemstack1.set(DataComponents.REPAIR_COST, i3); EnchantmentHelper.setEnchantments(itemstack1, itemenchantments$mutable.toImmutable()); } this.resultSlots.setItem(0, itemstack1); this.broadcastChanges(); } else { this.resultSlots.setItem(0, ItemStack.EMPTY); this.cost.set(0); } } public static int calculateIncreasedRepairCost(int p_39026_) { return (int)Math.min(p_39026_ * 2L + 1L, 2147483647L); } public boolean setItemName(String p_288970_) { String s = validateName(p_288970_); if (s != null && !s.equals(this.itemName)) { this.itemName = s; if (this.getSlot(2).hasItem()) { ItemStack itemstack = this.getSlot(2).getItem(); if (StringUtil.isBlank(s)) { itemstack.remove(DataComponents.CUSTOM_NAME); } else { itemstack.set(DataComponents.CUSTOM_NAME, Component.literal(s)); } } this.createResult(); return true; } else { return false; } } @Nullable private static String validateName(String p_288995_) { String s = StringUtil.filterText(p_288995_); return s.length() <= 50 ? s : null; } public int getCost() { return this.cost.get(); } }