--- a/net/minecraft/world/entity/monster/piglin/Piglin.java
+++ b/net/minecraft/world/entity/monster/piglin/Piglin.java
@@ -78,8 +_,8 @@
     private static final double PROBABILITY_OF_SPAWNING_WITH_CROSSBOW_INSTEAD_OF_SWORD = 0.5;
     private static final boolean DEFAULT_IS_BABY = false;
     private static final boolean DEFAULT_CANNOT_HUNT = false;
-    private final SimpleContainer inventory = new SimpleContainer(8);
-    private boolean cannotHunt = false;
+    public final SimpleContainer inventory = new SimpleContainer(8);
+    public boolean cannotHunt = false;
     protected static final ImmutableList<SensorType<? extends Sensor<? super Piglin>>> SENSOR_TYPES = ImmutableList.of(
         SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.NEAREST_ITEMS, SensorType.HURT_BY, SensorType.PIGLIN_SPECIFIC_SENSOR
     );
@@ -124,6 +_,12 @@
         MemoryModuleType.ATE_RECENTLY,
         MemoryModuleType.NEAREST_REPELLENT
     );
+    // CraftBukkit start - Custom bartering and interest list
+    public java.util.Set<Item> allowedBarterItems = new java.util.HashSet<>();
+    public java.util.Set<Item> interestItems = new java.util.HashSet<>();
+    private static final com.mojang.serialization.Codec<java.util.Set<net.minecraft.world.item.Item>> ITEM_SET_CODEC = net.minecraft.core.registries.BuiltInRegistries.ITEM
+        .byNameCodec().listOf().xmap(java.util.HashSet::new, List::copyOf);
+    // CraftBukkit end
 
     public Piglin(EntityType<? extends AbstractPiglin> entityType, Level level) {
         super(entityType, level);
@@ -136,6 +_,10 @@
         output.putBoolean("IsBaby", this.isBaby());
         output.putBoolean("CannotHunt", this.cannotHunt);
         this.writeInventoryToTag(output);
+        // CraftBukkit start
+        output.store("Bukkit.BarterList", ITEM_SET_CODEC, this.allowedBarterItems);
+        output.store("Bukkit.InterestList", ITEM_SET_CODEC, this.interestItems);
+        // CraftBukkit end
     }
 
     @Override
@@ -144,6 +_,10 @@
         this.setBaby(input.getBooleanOr("IsBaby", false));
         this.setCannotHunt(input.getBooleanOr("CannotHunt", false));
         this.readInventoryFromTag(input);
+        // CraftBukkit start
+        this.allowedBarterItems = input.read("Bukkit.BarterList", ITEM_SET_CODEC).orElseGet(java.util.HashSet::new);
+        this.interestItems = input.read("Bukkit.InterestList", ITEM_SET_CODEC).orElseGet(java.util.HashSet::new);
+        // CraftBukkit end
     }
 
     @VisibleForDebug
@@ -310,7 +_,9 @@
     @Override
     protected void finishConversion(ServerLevel serverLevel) {
         PiglinAi.cancelAdmiring(serverLevel, this);
+        this.forceDrops = true; // Paper - Add missing forceDrop toggles
         this.inventory.removeAllItems().forEach(itemStack -> this.spawnAtLocation(serverLevel, itemStack));
+        this.forceDrops = false; // Paper - Add missing forceDrop toggles
         super.finishConversion(serverLevel);
     }
 
@@ -324,7 +_,7 @@
         return this.isBaby() ? null : ItemTags.PIGLIN_PREFERRED_WEAPONS;
     }
 
-    private boolean isChargingCrossbow() {
+    public boolean isChargingCrossbow() {
         return this.entityData.get(DATA_IS_CHARGING_CROSSBOW);
     }
 
@@ -386,7 +_,7 @@
     }
 
     protected void holdInOffHand(ItemStack stack) {
-        if (stack.is(PiglinAi.BARTERING_ITEM)) {
+        if (stack.is(PiglinAi.BARTERING_ITEM) || this.allowedBarterItems.contains(stack.getItem())) { // CraftBukkit - Changes to accept custom payment items
             this.setItemSlot(EquipmentSlot.OFFHAND, stack);
             this.setGuaranteedDrop(EquipmentSlot.OFFHAND);
         } else {
@@ -411,15 +_,15 @@
             return false;
         } else {
             TagKey<Item> preferredWeaponType = this.getPreferredWeaponType();
-            boolean flag = PiglinAi.isLovedItem(newItem) || preferredWeaponType != null && newItem.is(preferredWeaponType);
-            boolean flag1 = PiglinAi.isLovedItem(currentItem) || preferredWeaponType != null && currentItem.is(preferredWeaponType);
+            boolean flag = PiglinAi.isLovedItem(newItem, this) || preferredWeaponType != null && newItem.is(preferredWeaponType); // CraftBukkit
+            boolean flag1 = PiglinAi.isLovedItem(currentItem, this) || preferredWeaponType != null && currentItem.is(preferredWeaponType); // CraftBukkit
             return flag && !flag1 || (flag || !flag1) && super.canReplaceCurrentItem(newItem, currentItem, slot);
         }
     }
 
     @Override
     protected void pickUpItem(ServerLevel level, ItemEntity entity) {
-        this.onItemPickup(entity);
+        // this.onItemPickup(entity); // Paper - EntityPickupItemEvent fixes; call in PiglinAi#pickUpItem after EntityPickupItemEvent is fired
         PiglinAi.pickUpItem(level, this, entity);
     }
 
@@ -439,17 +_,17 @@
 
     @Nullable
     @Override
-    protected SoundEvent getAmbientSound() {
+    public SoundEvent getAmbientSound() {
         return this.level().isClientSide() ? null : PiglinAi.getSoundForCurrentActivity(this).orElse(null);
     }
 
     @Override
-    protected SoundEvent getHurtSound(DamageSource damageSource) {
+    public SoundEvent getHurtSound(DamageSource damageSource) {
         return SoundEvents.PIGLIN_HURT;
     }
 
     @Override
-    protected SoundEvent getDeathSound() {
+    public SoundEvent getDeathSound() {
         return SoundEvents.PIGLIN_DEATH;
     }
 
