--- a/net/minecraft/world/inventory/ContainerEnchantTable.java +++ b/net/minecraft/world/inventory/ContainerEnchantTable.java @@ -31,6 +31,22 @@ import net.minecraft.world.level.block.BlockEnchantmentTable; import net.minecraft.world.level.block.Blocks; +// CraftBukkit start +import java.util.Map; +import net.minecraft.world.item.enchantment.Enchantment; +import org.bukkit.Location; +import org.bukkit.NamespacedKey; +import org.bukkit.craftbukkit.enchantments.CraftEnchantment; +import org.bukkit.craftbukkit.inventory.CraftInventoryEnchanting; +import org.bukkit.craftbukkit.inventory.CraftInventoryView; +import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.craftbukkit.util.CraftNamespacedKey; +import org.bukkit.enchantments.EnchantmentOffer; +import org.bukkit.event.enchantment.EnchantItemEvent; +import org.bukkit.event.enchantment.PrepareItemEnchantEvent; +import org.bukkit.entity.Player; +// CraftBukkit end + public class ContainerEnchantTable extends Container { static final MinecraftKey EMPTY_SLOT_LAPIS_LAZULI = MinecraftKey.withDefaultNamespace("item/empty_slot_lapis_lazuli"); @@ -41,6 +57,10 @@ public final int[] costs; public final int[] enchantClue; public final int[] levelClue; + // CraftBukkit start + private CraftInventoryView bukkitEntity = null; + private Player player; + // CraftBukkit end public ContainerEnchantTable(int i, PlayerInventory playerinventory) { this(i, playerinventory, ContainerAccess.NULL); @@ -54,6 +74,13 @@ super.setChanged(); ContainerEnchantTable.this.slotsChanged(this); } + + // CraftBukkit start + @Override + public Location getLocation() { + return containeraccess.getLocation(); + } + // CraftBukkit end }; this.random = RandomSource.create(); this.enchantmentSeed = ContainerProperty.standalone(); @@ -61,13 +88,13 @@ this.enchantClue = new int[]{-1, -1, -1}; this.levelClue = new int[]{-1, -1, -1}; this.access = containeraccess; - this.addSlot(new Slot(this, this.enchantSlots, 0, 15, 47) { + this.addSlot(new Slot(this.enchantSlots, 0, 15, 47) { // CraftBukkit - decompile error @Override public int getMaxStackSize() { return 1; } }); - this.addSlot(new Slot(this, this.enchantSlots, 1, 35, 47) { + this.addSlot(new Slot(this.enchantSlots, 1, 35, 47) { // CraftBukkit - decompile error @Override public boolean mayPlace(ItemStack itemstack) { return itemstack.is(Items.LAPIS_LAZULI); @@ -101,6 +128,9 @@ this.addDataSlot(ContainerProperty.shared(this.levelClue, 0)); this.addDataSlot(ContainerProperty.shared(this.levelClue, 1)); this.addDataSlot(ContainerProperty.shared(this.levelClue, 2)); + // CraftBukkit start + player = (Player) playerinventory.player.getBukkitEntity(); + // CraftBukkit end } @Override @@ -108,7 +138,7 @@ if (iinventory == this.enchantSlots) { ItemStack itemstack = iinventory.getItem(0); - if (!itemstack.isEmpty() && itemstack.isEnchantable()) { + if (!itemstack.isEmpty()) { // CraftBukkit - relax condition this.access.execute((world, blockposition) -> { Registry> registry = world.registryAccess().registryOrThrow(Registries.ENCHANTMENT).asHolderIdMap(); int i = 0; @@ -148,6 +178,41 @@ } } + // CraftBukkit start + CraftItemStack item = CraftItemStack.asCraftMirror(itemstack); + org.bukkit.enchantments.EnchantmentOffer[] offers = new EnchantmentOffer[3]; + for (j = 0; j < 3; ++j) { + org.bukkit.enchantments.Enchantment enchantment = (this.enchantClue[j] >= 0) ? CraftEnchantment.minecraftHolderToBukkit(registry.byId(this.enchantClue[j])) : null; + offers[j] = (enchantment != null) ? new EnchantmentOffer(enchantment, this.levelClue[j], this.costs[j]) : null; + } + + PrepareItemEnchantEvent event = new PrepareItemEnchantEvent(player, this.getBukkitView(), access.getLocation().getBlock(), item, offers, i); + event.setCancelled(!itemstack.isEnchantable()); + world.getCraftServer().getPluginManager().callEvent(event); + + if (event.isCancelled()) { + for (j = 0; j < 3; ++j) { + this.costs[j] = 0; + this.enchantClue[j] = -1; + this.levelClue[j] = -1; + } + return; + } + + for (j = 0; j < 3; j++) { + EnchantmentOffer offer = event.getOffers()[j]; + if (offer != null) { + this.costs[j] = offer.getCost(); + this.enchantClue[j] = registry.getId(CraftEnchantment.bukkitToMinecraftHolder(offer.getEnchantment())); + this.levelClue[j] = offer.getEnchantmentLevel(); + } else { + this.costs[j] = 0; + this.enchantClue[j] = -1; + this.levelClue[j] = -1; + } + } + // CraftBukkit end + this.broadcastChanges(); }); } else { @@ -175,21 +240,46 @@ ItemStack itemstack2 = itemstack; List list = this.getEnchantmentList(world.registryAccess(), itemstack, i, this.costs[i]); - if (!list.isEmpty()) { - entityhuman.onEnchantmentPerformed(itemstack, j); + // CraftBukkit start + Registry> registry = world.registryAccess().registryOrThrow(Registries.ENCHANTMENT).asHolderIdMap(); + if (true || !list.isEmpty()) { + // entityhuman.onEnchantmentPerformed(itemstack, j); // Moved down + Map enchants = new java.util.HashMap(); + for (WeightedRandomEnchant instance : list) { + enchants.put(CraftEnchantment.minecraftHolderToBukkit(instance.enchantment), instance.level); + } + CraftItemStack item = CraftItemStack.asCraftMirror(itemstack2); + + org.bukkit.enchantments.Enchantment hintedEnchantment = CraftEnchantment.minecraftHolderToBukkit(registry.byId(enchantClue[i])); + int hintedEnchantmentLevel = levelClue[i]; + EnchantItemEvent event = new EnchantItemEvent((Player) entityhuman.getBukkitEntity(), this.getBukkitView(), access.getLocation().getBlock(), item, this.costs[i], enchants, hintedEnchantment, hintedEnchantmentLevel, i); + world.getCraftServer().getPluginManager().callEvent(event); + + int level = event.getExpLevelCost(); + if (event.isCancelled() || (level > entityhuman.experienceLevel && !entityhuman.getAbilities().instabuild) || event.getEnchantsToAdd().isEmpty()) { + return; + } + // CraftBukkit end if (itemstack.is(Items.BOOK)) { itemstack2 = itemstack.transmuteCopy(Items.ENCHANTED_BOOK); this.enchantSlots.setItem(0, itemstack2); } - Iterator iterator = list.iterator(); - - while (iterator.hasNext()) { - WeightedRandomEnchant weightedrandomenchant = (WeightedRandomEnchant) iterator.next(); + // CraftBukkit start + for (Map.Entry entry : event.getEnchantsToAdd().entrySet()) { + Holder nms = CraftEnchantment.bukkitToMinecraftHolder(entry.getKey()); + if (nms == null) { + continue; + } + WeightedRandomEnchant weightedrandomenchant = new WeightedRandomEnchant(nms, entry.getValue()); itemstack2.enchant(weightedrandomenchant.enchantment, weightedrandomenchant.level); } + entityhuman.onEnchantmentPerformed(itemstack, j); + // CraftBukkit end + + // CraftBukkit - TODO: let plugins change this itemstack1.consume(j, entityhuman); if (itemstack1.isEmpty()) { this.enchantSlots.setItem(1, ItemStack.EMPTY); @@ -256,6 +346,7 @@ @Override public boolean stillValid(EntityHuman entityhuman) { + if (!this.checkReachable) return true; // CraftBukkit return stillValid(this.access, entityhuman, Blocks.ENCHANTING_TABLE); } @@ -306,4 +397,17 @@ return itemstack; } + + // CraftBukkit start + @Override + public CraftInventoryView getBukkitView() { + if (bukkitEntity != null) { + return bukkitEntity; + } + + CraftInventoryEnchanting inventory = new CraftInventoryEnchanting(this.enchantSlots); + bukkitEntity = new CraftInventoryView(this.player, inventory, this); + return bukkitEntity; + } + // CraftBukkit end }