From d4fba3b549c9c2deacfa8db31bea6dec2d0a71d5 Mon Sep 17 00:00:00 2001 From: fullwall Date: Mon, 9 Sep 2024 19:35:05 +0800 Subject: [PATCH] Trial clearing component predicates for merchant offers in 1.20.6+ --- .../net/citizensnpcs/trait/ShopTrait.java | 24 ++++++++++++------ .../main/java/net/citizensnpcs/util/NMS.java | 6 +++++ .../java/net/citizensnpcs/util/NMSBridge.java | 6 +++++ .../nms/v1_20_R4/util/NMSImpl.java | 25 +++++++++++++++++++ .../nms/v1_21_R1/util/NMSImpl.java | 25 +++++++++++++++++++ 5 files changed, 78 insertions(+), 8 deletions(-) diff --git a/main/src/main/java/net/citizensnpcs/trait/ShopTrait.java b/main/src/main/java/net/citizensnpcs/trait/ShopTrait.java index 48718d8b7..6222c9f4c 100644 --- a/main/src/main/java/net/citizensnpcs/trait/ShopTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/ShopTrait.java @@ -2,6 +2,7 @@ package net.citizensnpcs.trait; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.function.Consumer; import java.util.function.Function; @@ -33,6 +34,7 @@ import com.google.common.base.Splitter; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.CitizensAPI; @@ -74,6 +76,7 @@ import net.citizensnpcs.trait.shop.PermissionAction; import net.citizensnpcs.trait.shop.PermissionAction.PermissionActionGUI; import net.citizensnpcs.trait.shop.StoredShops; import net.citizensnpcs.util.InventoryMultiplexer; +import net.citizensnpcs.util.NMS; import net.citizensnpcs.util.Util; /** @@ -958,6 +961,7 @@ public class ShopTrait extends Trait { this.shop = shop; this.player = player; Map tradesMap = Maps.newHashMap(); + Set clearComponentPredicates = Sets.newHashSet(); Merchant merchant = Bukkit.createMerchant(shop.getTitle()); List recipes = Lists.newArrayList(); for (NPCShopPage page : shop.pages) { @@ -967,14 +971,17 @@ public class ShopTrait extends Trait { continue; MerchantRecipe recipe = new MerchantRecipe(result.clone(), 100000000); for (NPCShopAction action : item.cost) { - if (action instanceof ItemAction) { - ItemAction ia = (ItemAction) action; - for (ItemStack stack : ia.items) { - stack = stack.clone(); - recipe.addIngredient(stack); - if (recipe.getIngredients().size() == 2) - break; - } + if (!(action instanceof ItemAction)) + continue; + ItemAction ia = (ItemAction) action; + if (!ia.compareSimilarity && ia.items.size() > 0) { + clearComponentPredicates.add(recipes.size()); + } + for (ItemStack stack : ia.items) { + stack = stack.clone(); + recipe.addIngredient(stack); + if (recipe.getIngredients().size() == 2) + break; } } if (recipe.getIngredients().size() == 0) @@ -984,6 +991,7 @@ public class ShopTrait extends Trait { } } merchant.setRecipes(recipes); + NMS.clearMerchantComponentPredicates(merchant, clearComponentPredicates); trades = tradesMap; view = player.openMerchant(merchant, true); } diff --git a/main/src/main/java/net/citizensnpcs/util/NMS.java b/main/src/main/java/net/citizensnpcs/util/NMS.java index 50f65813d..87e630700 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMS.java +++ b/main/src/main/java/net/citizensnpcs/util/NMS.java @@ -9,6 +9,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.function.Consumer; import java.util.function.Function; @@ -36,6 +37,7 @@ import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.Merchant; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.scoreboard.Team; import org.bukkit.util.Vector; @@ -153,6 +155,10 @@ public class NMS { BRIDGE.cancelMoveDestination(entity); } + public static void clearMerchantComponentPredicates(Merchant merchant, Set clearComponentPredicates) { + BRIDGE.clearMerchantComponentPredicates(merchant, clearComponentPredicates); + } + public static Iterable createBundlePacket(List packets) { return BRIDGE.createBundlePacket(packets); } diff --git a/main/src/main/java/net/citizensnpcs/util/NMSBridge.java b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java index 3f852d97b..ba1806d01 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMSBridge.java +++ b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java @@ -3,6 +3,7 @@ package net.citizensnpcs.util; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.function.Function; @@ -23,6 +24,7 @@ import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.Merchant; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.scoreboard.Team; import org.bukkit.util.Vector; @@ -63,6 +65,10 @@ public interface NMSBridge { public void cancelMoveDestination(Entity entity); + public default void clearMerchantComponentPredicates(Merchant merchant, Set clearComponentPredicates) { + // TODO: implement for <=1.19.4 + } + public default Iterable createBundlePacket(List packets) { return packets; } diff --git a/v1_20_R4/src/main/java/net/citizensnpcs/nms/v1_20_R4/util/NMSImpl.java b/v1_20_R4/src/main/java/net/citizensnpcs/nms/v1_20_R4/util/NMSImpl.java index f70c053ce..f904ef114 100644 --- a/v1_20_R4/src/main/java/net/citizensnpcs/nms/v1_20_R4/util/NMSImpl.java +++ b/v1_20_R4/src/main/java/net/citizensnpcs/nms/v1_20_R4/util/NMSImpl.java @@ -8,7 +8,9 @@ import java.util.Collections; import java.util.EnumSet; import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import java.util.Map; +import java.util.Optional; import java.util.Random; import java.util.Set; import java.util.TreeMap; @@ -39,6 +41,7 @@ import org.bukkit.craftbukkit.v1_20_R4.event.CraftEventFactory; import org.bukkit.craftbukkit.v1_20_R4.event.CraftPortalEvent; import org.bukkit.craftbukkit.v1_20_R4.inventory.CraftInventoryAnvil; import org.bukkit.craftbukkit.v1_20_R4.inventory.CraftInventoryView; +import org.bukkit.craftbukkit.v1_20_R4.inventory.CraftMerchant; import org.bukkit.entity.EntityType; import org.bukkit.entity.FishHook; import org.bukkit.entity.Player; @@ -46,6 +49,7 @@ import org.bukkit.entity.Tameable; import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; +import org.bukkit.inventory.Merchant; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.scoreboard.Team; import org.bukkit.util.Vector; @@ -260,6 +264,7 @@ import net.citizensnpcs.util.PlayerAnimation; import net.citizensnpcs.util.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; +import net.minecraft.core.component.DataComponentPredicate; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.ByteArrayTag; import net.minecraft.nbt.CompoundTag; @@ -356,6 +361,8 @@ import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.trading.ItemCost; +import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.dimension.end.EndDragonFight; @@ -496,6 +503,24 @@ public class NMSImpl implements NMSBridge { } } + @Override + public void clearMerchantComponentPredicates(Merchant merchant, Set clearComponentPredicates) { + net.minecraft.world.item.trading.Merchant handle = ((CraftMerchant) merchant).getMerchant(); + ListIterator itr = handle.getOffers().listIterator(); + for (int i = 0; itr.hasNext(); i++) { + if (!clearComponentPredicates.contains(i)) + continue; + MerchantOffer offer = itr.next(); + offer.baseCostA = new ItemCost(offer.baseCostA.item(), offer.baseCostA.count(), + DataComponentPredicate.EMPTY, offer.baseCostA.itemStack()); + ItemCost costB = offer.getItemCostB().orElseGet(() -> null); + if (costB != null) { + offer.costB = Optional + .of(new ItemCost(costB.item(), costB.count(), DataComponentPredicate.EMPTY, costB.itemStack())); + } + } + } + @Override @SuppressWarnings("rawtypes") public Iterable createBundlePacket(List source) { diff --git a/v1_21_R1/src/main/java/net/citizensnpcs/nms/v1_21_R1/util/NMSImpl.java b/v1_21_R1/src/main/java/net/citizensnpcs/nms/v1_21_R1/util/NMSImpl.java index 5fcbaff3c..ec93a57f0 100644 --- a/v1_21_R1/src/main/java/net/citizensnpcs/nms/v1_21_R1/util/NMSImpl.java +++ b/v1_21_R1/src/main/java/net/citizensnpcs/nms/v1_21_R1/util/NMSImpl.java @@ -8,7 +8,9 @@ import java.util.Collections; import java.util.EnumSet; import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import java.util.Map; +import java.util.Optional; import java.util.Random; import java.util.Set; import java.util.TreeMap; @@ -37,6 +39,7 @@ import org.bukkit.craftbukkit.v1_21_R1.entity.CraftEntity; import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_21_R1.event.CraftEventFactory; import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventoryAnvil; +import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftMerchant; import org.bukkit.craftbukkit.v1_21_R1.inventory.view.CraftAnvilView; import org.bukkit.entity.EntityType; import org.bukkit.entity.FishHook; @@ -46,6 +49,7 @@ import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; import org.bukkit.event.entity.EntityKnockbackEvent.KnockbackCause; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; +import org.bukkit.inventory.Merchant; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.scoreboard.Team; import org.bukkit.util.Vector; @@ -260,6 +264,7 @@ import net.citizensnpcs.util.PlayerAnimation; import net.citizensnpcs.util.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; +import net.minecraft.core.component.DataComponentPredicate; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.ByteArrayTag; import net.minecraft.nbt.CompoundTag; @@ -356,6 +361,8 @@ import net.minecraft.world.inventory.ContainerLevelAccess; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.trading.ItemCost; +import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.dimension.end.EndDragonFight; @@ -476,6 +483,24 @@ public class NMSImpl implements NMSBridge { } } + @Override + public void clearMerchantComponentPredicates(Merchant merchant, Set clearComponentPredicates) { + net.minecraft.world.item.trading.Merchant handle = ((CraftMerchant) merchant).getMerchant(); + ListIterator itr = handle.getOffers().listIterator(); + for (int i = 0; itr.hasNext(); i++) { + if (!clearComponentPredicates.contains(i)) + continue; + MerchantOffer offer = itr.next(); + offer.baseCostA = new ItemCost(offer.baseCostA.item(), offer.baseCostA.count(), + DataComponentPredicate.EMPTY, offer.baseCostA.itemStack()); + ItemCost costB = offer.getItemCostB().orElseGet(() -> null); + if (costB != null) { + offer.costB = Optional + .of(new ItemCost(costB.item(), costB.count(), DataComponentPredicate.EMPTY, costB.itemStack())); + } + } + } + @Override @SuppressWarnings("rawtypes") public Iterable createBundlePacket(List source) {