--- a/net/minecraft/world/entity/npc/WanderingTrader.java
+++ b/net/minecraft/world/entity/npc/WanderingTrader.java
@@ -45,11 +_,15 @@
 import net.minecraft.world.phys.Vec3;
 import org.apache.commons.lang3.tuple.Pair;
 
-public class WanderingTrader extends AbstractVillager implements Consumable.OverrideConsumeSound {
+public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVillager implements Consumable.OverrideConsumeSound { // CraftBukkit
     private static final int DEFAULT_DESPAWN_DELAY = 0;
     @Nullable
     private BlockPos wanderTarget;
     private int despawnDelay = 0;
+    // Paper start - Add more WanderingTrader API
+    public boolean canDrinkPotion = true;
+    public boolean canDrinkMilk = true;
+    // Paper end - Add more WanderingTrader API
 
     public WanderingTrader(EntityType<? extends WanderingTrader> entityType, Level level) {
         super(entityType, level);
@@ -65,7 +_,7 @@
                     this,
                     PotionContents.createItemStack(Items.POTION, Potions.INVISIBILITY),
                     SoundEvents.WANDERING_TRADER_DISAPPEARED,
-                    wanderingTrader -> this.level().isDarkOutside() && !wanderingTrader.isInvisible()
+                    wanderingTrader -> this.canDrinkPotion && this.level().isDarkOutside() && !wanderingTrader.isInvisible() // Paper - Add more WanderingTrader API
                 )
             );
         this.goalSelector
@@ -75,7 +_,7 @@
                     this,
                     new ItemStack(Items.MILK_BUCKET),
                     SoundEvents.WANDERING_TRADER_REAPPEARED,
-                    wanderingTrader -> this.level().isBrightOutside() && wanderingTrader.isInvisible()
+                    wanderingTrader -> this.canDrinkMilk && this.level().isBrightOutside() && wanderingTrader.isInvisible() // Paper - Add more WanderingTrader API
                 )
             );
         this.goalSelector.addGoal(1, new TradeWithPlayerGoal(this));
@@ -163,22 +_,22 @@
     protected void rewardTradeXp(MerchantOffer offer) {
         if (offer.shouldRewardExp()) {
             int i = 3 + this.random.nextInt(4);
-            this.level().addFreshEntity(new ExperienceOrb(this.level(), this.getX(), this.getY() + 0.5, this.getZ(), i));
+            this.level().addFreshEntity(new ExperienceOrb(this.level(), this.getX(), this.getY() + 0.5, this.getZ(), i, org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, this.getTradingPlayer(), this)); // Paper
         }
     }
 
     @Override
-    protected SoundEvent getAmbientSound() {
+    public SoundEvent getAmbientSound() {
         return this.isTrading() ? SoundEvents.WANDERING_TRADER_TRADE : SoundEvents.WANDERING_TRADER_AMBIENT;
     }
 
     @Override
-    protected SoundEvent getHurtSound(DamageSource damageSource) {
+    public SoundEvent getHurtSound(DamageSource damageSource) {
         return SoundEvents.WANDERING_TRADER_HURT;
     }
 
     @Override
-    protected SoundEvent getDeathSound() {
+    public SoundEvent getDeathSound() {
         return SoundEvents.WANDERING_TRADER_DEATH;
     }
 
@@ -215,7 +_,7 @@
 
     private void maybeDespawn() {
         if (this.despawnDelay > 0 && !this.isTrading() && --this.despawnDelay == 0) {
-            this.discard();
+            this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
         }
     }
 
@@ -224,7 +_,7 @@
     }
 
     @Nullable
-    BlockPos getWanderTarget() {
+    public BlockPos getWanderTarget() {
         return this.wanderTarget;
     }
 
