--- a/net/minecraft/world/inventory/MerchantResultSlot.java
+++ b/net/minecraft/world/inventory/MerchantResultSlot.java
@@ -47,13 +_,34 @@
 
     @Override
     public void onTake(Player player, ItemStack stack) {
-        this.checkTakeAchievements(stack);
+        // this.checkTakeAchievements(stack); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent; move to after event is called and not cancelled
         MerchantOffer activeOffer = this.slots.getActiveOffer();
+        // Paper start - Add PlayerTradeEvent and PlayerPurchaseEvent
+        io.papermc.paper.event.player.PlayerPurchaseEvent event = null;
+        if (activeOffer != null && player instanceof net.minecraft.server.level.ServerPlayer serverPlayer) {
+            if (this.merchant instanceof net.minecraft.world.entity.npc.AbstractVillager abstractVillager) {
+                event = new io.papermc.paper.event.player.PlayerTradeEvent(serverPlayer.getBukkitEntity(), (org.bukkit.entity.AbstractVillager) abstractVillager.getBukkitEntity(), activeOffer.asBukkit(), true, true);
+            } else if (this.merchant instanceof org.bukkit.craftbukkit.inventory.CraftMerchantCustom.MinecraftMerchant) {
+                event = new io.papermc.paper.event.player.PlayerPurchaseEvent(serverPlayer.getBukkitEntity(), activeOffer.asBukkit(), false, true);
+            }
+            if (event != null) {
+                if (!event.callEvent()) {
+                    stack.setCount(0);
+                    event.getPlayer().updateInventory();
+                    int level = merchant instanceof net.minecraft.world.entity.npc.Villager villager ? villager.getVillagerData().getLevel() : 1;
+                    serverPlayer.sendMerchantOffers(player.containerMenu.containerId, merchant.getOffers(), level, merchant.getVillagerXp(), merchant.showProgressBar(), merchant.canRestock());
+                    return;
+                }
+                activeOffer = org.bukkit.craftbukkit.inventory.CraftMerchantRecipe.fromBukkit(event.getTrade()).toMinecraft();
+            }
+        }
+        this.checkTakeAchievements(stack);
+        // Paper end - Add PlayerTradeEvent and PlayerPurchaseEvent
         if (activeOffer != null) {
             ItemStack item = this.slots.getItem(0);
             ItemStack item1 = this.slots.getItem(1);
             if (activeOffer.take(item, item1) || activeOffer.take(item1, item)) {
-                this.merchant.notifyTrade(activeOffer);
+                this.merchant.processTrade(activeOffer, event); // Paper - Add PlayerTradeEvent and PlayerPurchaseEvent
                 player.awardStat(Stats.TRADED_WITH_VILLAGER);
                 this.slots.setItem(0, item);
                 this.slots.setItem(1, item1);
