diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/OverrideGiveCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/OverrideGiveCommand.java deleted file mode 100644 index 4fbf77a78..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/OverrideGiveCommand.java +++ /dev/null @@ -1,91 +0,0 @@ -//package net.momirealms.craftengine.bukkit.plugin.command.feature; -// -//import net.kyori.adventure.text.Component; -//import net.momirealms.craftengine.bukkit.api.BukkitAdaptors; -//import net.momirealms.craftengine.bukkit.item.BukkitItemManager; -//import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature; -//import net.momirealms.craftengine.bukkit.util.PlayerUtils; -//import net.momirealms.craftengine.core.item.Item; -//import net.momirealms.craftengine.core.plugin.CraftEngine; -//import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager; -//import net.momirealms.craftengine.core.plugin.locale.MessageConstants; -//import net.momirealms.craftengine.core.util.Key; -//import org.bukkit.NamespacedKey; -//import org.bukkit.command.CommandSender; -//import org.bukkit.entity.Player; -//import org.bukkit.inventory.ItemStack; -//import org.checkerframework.checker.nullness.qual.NonNull; -//import org.incendo.cloud.Command; -//import org.incendo.cloud.bukkit.data.MultiplePlayerSelector; -//import org.incendo.cloud.bukkit.parser.NamespacedKeyParser; -//import org.incendo.cloud.bukkit.parser.selector.MultiplePlayerSelectorParser; -//import org.incendo.cloud.context.CommandContext; -//import org.incendo.cloud.context.CommandInput; -//import org.incendo.cloud.parser.standard.IntegerParser; -//import org.incendo.cloud.suggestion.Suggestion; -//import org.incendo.cloud.suggestion.SuggestionProvider; -// -//import java.util.Collection; -//import java.util.concurrent.CompletableFuture; -// -//public class OverrideGiveCommand extends BukkitCommandFeature { -// -// public OverrideGiveCommand(CraftEngineCommandManager commandManager, CraftEngine plugin) { -// super(commandManager, plugin); -// } -// -// @Override -// public Command.Builder assembleCommand(org.incendo.cloud.CommandManager manager, Command.Builder builder) { -// return builder -// .required("player", MultiplePlayerSelectorParser.multiplePlayerSelectorParser(true)) -// .required("id", NamespacedKeyParser.namespacedKeyComponent().suggestionProvider(new SuggestionProvider<>() { -// @Override -// public @NonNull CompletableFuture> suggestionsFuture(@NonNull CommandContext context, @NonNull CommandInput input) { -// return CompletableFuture.completedFuture(plugin().itemManager().cachedAllItemSuggestions()); -// } -// })) -// .optional("amount", IntegerParser.integerParser(1, 6400)) -// .handler(context -> { -// MultiplePlayerSelector selector = context.get("player"); -// int amount = context.getOrDefault("amount", 1); -// NamespacedKey namespacedKey = context.get("id"); -// Key itemId = Key.of(namespacedKey.namespace(), namespacedKey.value()); -// Collection players = selector.values(); -// -// Component anyItemDisplayName = null; -// -// for (Player player : players) { -// Item builtItem = BukkitItemManager.instance().createWrappedItem(itemId, BukkitAdaptors.adapt(player)); -// if (builtItem == null) { -// return; -// } -// int maxStack = builtItem.maxStackSize(); -// anyItemDisplayName = builtItem.hoverNameComponent() -// .orElseGet(() -> { -// if (builtItem.isCustomItem()) { -// return Component.text(itemId.asString()); -// } else { -// return Component.translatable("item.minecraft." + itemId.value()); -// } -// }); -// -// if (amount > maxStack * 100) { -// plugin().senderFactory().wrap(context.sender()).sendMessage(Component.translatable("commands.give.failed.toomanyitems", Component.text(maxStack * 100), anyItemDisplayName); -// return; -// } -// -// PlayerUtils.giveItem(player, amount, builtItem); -// } -// if (players.size() == 1) { -// plugin().senderFactory().wrap(context.sender()).sendMessage(Component.translatable("commands.give.success.single", Component.text(amount), anyItemDisplayName, )); -// } else if (players.size() > 1) { -// handleFeedback(context, MessageConstants.COMMAND_ITEM_GIVE_SUCCESS_MULTIPLE, Component.text(amount), Component.text(itemId.toString()), Component.text(players.size())); -// } -// }); -// } -// -// @Override -// public String getFeatureID() { -// return "override_minecraft_give"; -// } -//} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index ba59dcb7b..6cae15d41 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -58,6 +58,7 @@ import net.momirealms.craftengine.bukkit.world.BukkitWorldManager; import net.momirealms.craftengine.core.advancement.network.AdvancementHolder; import net.momirealms.craftengine.core.advancement.network.AdvancementProgress; import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.block.entity.render.DynamicBlockEntityRenderer; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.font.FontManager; import net.momirealms.craftengine.core.font.IllegalCharacterProcessResult; @@ -68,6 +69,7 @@ import net.momirealms.craftengine.core.item.context.UseOnContext; import net.momirealms.craftengine.core.item.recipe.network.legacy.LegacyRecipeHolder; import net.momirealms.craftengine.core.item.recipe.network.modern.RecipeBookEntry; import net.momirealms.craftengine.core.item.recipe.network.modern.display.RecipeDisplay; +import net.momirealms.craftengine.core.item.trade.MerchantOffer; import net.momirealms.craftengine.core.pack.host.ResourcePackDownloadData; import net.momirealms.craftengine.core.pack.host.ResourcePackHost; import net.momirealms.craftengine.core.plugin.CraftEngine; @@ -354,6 +356,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes registerC2SGamePacketListener(new ContainerClick1_20(), VersionHelper.isOrAbove1_21_5() ? -1 : this.packetIds.serverboundContainerClickPacket(), "ServerboundContainerClickPacket"); registerC2SGamePacketListener(new InteractEntityListener(), this.packetIds.serverboundInteractPacket(), "ServerboundInteractPacket"); registerC2SGamePacketListener(new CustomPayloadListener1_20(), VersionHelper.isOrAbove1_20_2() ? -1 : this.packetIds.serverboundCustomPayloadPacket(), "ServerboundCustomPayloadPacket"); + registerS2CGamePacketListener(VersionHelper.isOrAbove1_20_5() ? new MerchantOffersListener1_20_5() : new MerchantOffersListener1_20(), this.packetIds.clientBoundMerchantOffersPacket(), "ClientboundMerchantOffersPacket"); registerS2CGamePacketListener(new AddEntityListener(RegistryUtils.currentEntityTypeRegistrySize()), this.packetIds.clientboundAddEntityPacket(), "ClientboundAddEntityPacket"); registerS2CGamePacketListener( VersionHelper.isOrAbove1_20_3() ? @@ -2167,7 +2170,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes float zDist = buf.readFloat(); float maxSpeed = buf.readFloat(); int count = buf.readInt(); - Object option = FastNMS.INSTANCE.method$StreamCodec$decode(NetworkReflections.instance$ParticleTypes$STREAM_CODEC, buf); + Object option = FastNMS.INSTANCE.method$StreamDecoder$decode(NetworkReflections.instance$ParticleTypes$STREAM_CODEC, FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf)); if (option == null) return; if (!CoreReflections.clazz$BlockParticleOption.isInstance(option)) return; Object blockState = FastNMS.INSTANCE.field$BlockParticleOption$blockState(option); @@ -2189,7 +2192,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes buf.writeFloat(zDist); buf.writeFloat(maxSpeed); buf.writeInt(count); - FastNMS.INSTANCE.method$StreamCodec$encode(NetworkReflections.instance$ParticleTypes$STREAM_CODEC, buf, remappedOption); + FastNMS.INSTANCE.method$StreamEncoder$encode(NetworkReflections.instance$ParticleTypes$STREAM_CODEC, FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf), remappedOption); } } @@ -2214,7 +2217,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes float zDist = buf.readFloat(); float maxSpeed = buf.readFloat(); int count = buf.readInt(); - Object option = FastNMS.INSTANCE.method$StreamCodec$decode(NetworkReflections.instance$ParticleTypes$STREAM_CODEC, buf); + Object option = FastNMS.INSTANCE.method$StreamDecoder$decode(NetworkReflections.instance$ParticleTypes$STREAM_CODEC, FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf)); if (option == null) return; if (!CoreReflections.clazz$BlockParticleOption.isInstance(option)) return; Object blockState = FastNMS.INSTANCE.field$BlockParticleOption$blockState(option); @@ -2235,7 +2238,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes buf.writeFloat(zDist); buf.writeFloat(maxSpeed); buf.writeInt(count); - FastNMS.INSTANCE.method$StreamCodec$encode(NetworkReflections.instance$ParticleTypes$STREAM_CODEC, buf, remappedOption); + FastNMS.INSTANCE.method$StreamEncoder$encode(NetworkReflections.instance$ParticleTypes$STREAM_CODEC, FastNMS.INSTANCE.constructor$FriendlyByteBuf(buf), remappedOption); } } @@ -3803,4 +3806,124 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes } } } + + public static class MerchantOffersListener1_20 implements ByteBufferPacketListener { + + @Override + public void onPacketSend(NetWorkUser user, ByteBufPacketEvent event) { + if (!(user instanceof BukkitServerPlayer serverPlayer)) return; + FriendlyByteBuf buf = event.getBuffer(); + int containerId = buf.readContainerId(); + BukkitItemManager manager = BukkitItemManager.instance(); + List> merchantOffers = buf.readCollection(ArrayList::new, byteBuf -> { + Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(byteBuf); + ItemStack cost1 = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf); + ItemStack result = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf); + ItemStack cost2 = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf); + boolean outOfStock = byteBuf.readBoolean(); + int uses = byteBuf.readInt(); + int maxUses = byteBuf.readInt(); + int xp = byteBuf.readInt(); + int specialPrice = byteBuf.readInt(); + float priceMultiplier = byteBuf.readFloat(); + int demand = byteBuf.readInt(); + return new MerchantOffer<>(manager.wrap(cost1), Optional.of(manager.wrap(cost2)), manager.wrap(result), outOfStock, uses, maxUses, xp, specialPrice, priceMultiplier, demand); + }); + for (MerchantOffer offer : merchantOffers) { + offer.applyClientboundData(item -> manager.s2c(item, serverPlayer)); + } + int villagerLevel = buf.readVarInt(); + int villagerXp = buf.readVarInt(); + boolean showProgress = buf.readBoolean(); + boolean canRestock = buf.readBoolean(); + + event.setChanged(true); + buf.clear(); + buf.writeVarInt(event.packetID()); + buf.writeContainerId(containerId); + buf.writeCollection(merchantOffers, (byteBuf, offer) -> { + Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(byteBuf); + FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(friendlyBuf, offer.cost1().getItem()); + FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(friendlyBuf, offer.result().getItem()); + FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(friendlyBuf, offer.cost2().get().getItem()); + byteBuf.writeBoolean(offer.outOfStock()); + byteBuf.writeInt(offer.uses()); + byteBuf.writeInt(offer.maxUses()); + byteBuf.writeInt(offer.xp()); + byteBuf.writeInt(offer.specialPrice()); + byteBuf.writeFloat(offer.priceMultiplier()); + byteBuf.writeInt(offer.demand()); + }); + + buf.writeVarInt(villagerLevel); + buf.writeVarInt(villagerXp); + buf.writeBoolean(showProgress); + buf.writeBoolean(canRestock); + } + } + + public static class MerchantOffersListener1_20_5 implements ByteBufferPacketListener { + + @SuppressWarnings("unchecked") + @Override + public void onPacketSend(NetWorkUser user, ByteBufPacketEvent event) { + if (!(user instanceof BukkitServerPlayer serverPlayer)) return; + FriendlyByteBuf buf = event.getBuffer(); + int containerId = buf.readContainerId(); + BukkitItemManager manager = BukkitItemManager.instance(); + List> merchantOffers = buf.readCollection(ArrayList::new, byteBuf -> { + Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(byteBuf); + ItemStack cost1 = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.field$ItemCost$itemStack(FastNMS.INSTANCE.method$StreamDecoder$decode(NetworkReflections.instance$ItemCost$STREAM_CODEC, friendlyBuf))); + ItemStack result = FastNMS.INSTANCE.method$FriendlyByteBuf$readItem(friendlyBuf); + Optional cost2 = ((Optional) FastNMS.INSTANCE.method$StreamDecoder$decode(NetworkReflections.instance$ItemCost$OPTIONAL_STREAM_CODEC, friendlyBuf)) + .map(cost -> FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.field$ItemCost$itemStack(cost))); + boolean outOfStock = byteBuf.readBoolean(); + int uses = byteBuf.readInt(); + int maxUses = byteBuf.readInt(); + int xp = byteBuf.readInt(); + int specialPrice = byteBuf.readInt(); + float priceMultiplier = byteBuf.readFloat(); + int demand = byteBuf.readInt(); + return new MerchantOffer<>(manager.wrap(cost1), cost2.map(manager::wrap), manager.wrap(result), outOfStock, uses, maxUses, xp, specialPrice, priceMultiplier, demand); + }); + for (MerchantOffer offer : merchantOffers) { + offer.applyClientboundData(item -> manager.s2c(item, serverPlayer)); + } + int villagerLevel = buf.readVarInt(); + int villagerXp = buf.readVarInt(); + boolean showProgress = buf.readBoolean(); + boolean canRestock = buf.readBoolean(); + + event.setChanged(true); + buf.clear(); + buf.writeVarInt(event.packetID()); + buf.writeContainerId(containerId); + buf.writeCollection(merchantOffers, (byteBuf, offer) -> { + Object friendlyBuf = FastNMS.INSTANCE.constructor$FriendlyByteBuf(byteBuf); + FastNMS.INSTANCE.method$StreamEncoder$encode(NetworkReflections.instance$ItemCost$STREAM_CODEC, friendlyBuf, itemStackToItemCost(offer.cost1().getLiteralObject(), offer.cost1().count())); + FastNMS.INSTANCE.method$FriendlyByteBuf$writeItem(friendlyBuf, offer.result().getItem()); + FastNMS.INSTANCE.method$StreamEncoder$encode(NetworkReflections.instance$ItemCost$OPTIONAL_STREAM_CODEC, friendlyBuf, offer.cost2().map(it -> itemStackToItemCost(it.getLiteralObject(), it.count()))); + byteBuf.writeBoolean(offer.outOfStock()); + byteBuf.writeInt(offer.uses()); + byteBuf.writeInt(offer.maxUses()); + byteBuf.writeInt(offer.xp()); + byteBuf.writeInt(offer.specialPrice()); + byteBuf.writeFloat(offer.priceMultiplier()); + byteBuf.writeInt(offer.demand()); + }); + + buf.writeVarInt(villagerLevel); + buf.writeVarInt(villagerXp); + buf.writeBoolean(showProgress); + buf.writeBoolean(canRestock); + } + + private Object itemStackToItemCost(Object itemStack, int count) { + return FastNMS.INSTANCE.constructor$ItemCost( + FastNMS.INSTANCE.method$Item$builtInRegistryHolder(FastNMS.INSTANCE.method$ItemStack$getItem(itemStack)), + count, + FastNMS.INSTANCE.method$DataComponentExactPredicate$allOf(FastNMS.INSTANCE.method$ItemStack$getComponents(itemStack)) + ); + } + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java index b8b0e9cc8..ad0d6b86e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketIds.java @@ -60,6 +60,8 @@ public interface PacketIds { int clientboundUpdateAdvancementsPacket(); + int clientBoundMerchantOffersPacket(); + int serverboundContainerClickPacket(); int serverboundSetCreativeModeSlotPacket(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java index 8b33c8fef..ed5beaa0c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20.java @@ -161,6 +161,11 @@ public class PacketIds1_20 implements PacketIds { return PlayPacketIdHelper.byClazz(NetworkReflections.clazz$ClientboundBlockEventPacket, PacketFlow.CLIENTBOUND); } + @Override + public int clientBoundMerchantOffersPacket() { + return PlayPacketIdHelper.byClazz(NetworkReflections.clazz$ClientboundMerchantOffersPacket, PacketFlow.CLIENTBOUND); + } + @Override public int serverboundContainerClickPacket() { return PlayPacketIdHelper.byClazz(NetworkReflections.clazz$ServerboundContainerClickPacket, PacketFlow.SERVERBOUND); @@ -171,7 +176,6 @@ public class PacketIds1_20 implements PacketIds { return PlayPacketIdHelper.byClazz(NetworkReflections.clazz$ServerboundSetCreativeModeSlotPacket, PacketFlow.SERVERBOUND); } - @Override public int serverboundInteractPacket() { return PlayPacketIdHelper.byClazz(NetworkReflections.clazz$ServerboundInteractPacket, PacketFlow.SERVERBOUND); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java index 9aea4a3df..e6240cb1d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PacketIds1_20_5.java @@ -160,6 +160,11 @@ public class PacketIds1_20_5 implements PacketIds { return PlayPacketIdHelper.byName("minecraft:forget_level_chunk", PacketFlow.CLIENTBOUND); } + @Override + public int clientBoundMerchantOffersPacket() { + return PlayPacketIdHelper.byName("minecraft:merchant_offers", PacketFlow.CLIENTBOUND); + } + @Override public int serverboundContainerClickPacket() { return PlayPacketIdHelper.byName("minecraft:container_click", PacketFlow.SERVERBOUND); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java index 6cc1e3c7d..736271cfa 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java @@ -4463,4 +4463,11 @@ public final class CoreReflections { public static final Field field$EnumProperty$values = requireNonNull( ReflectionUtils.getDeclaredField(clazz$EnumProperty, VersionHelper.isOrAbove1_21_2() ? List.class : ImmutableSet.class, 0) ); + + public static final Class clazz$ItemCost = MiscUtils.requireNonNullIf( + BukkitReflectionUtils.findReobfOrMojmapClass( + "world.item.trading.ItemCost", + "world.item.trading.ItemCost" + ), VersionHelper.isOrAbove1_20_5() + ); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java index e36fac81c..e6513a3ed 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/NetworkReflections.java @@ -1692,4 +1692,25 @@ public final class NetworkReflections { CoreReflections.clazz$SoundSource ) ); + + public static final Class clazz$ClientboundMerchantOffersPacket = requireNonNull( + BukkitReflectionUtils.findReobfOrMojmapClass( + "network.protocol.game.PacketPlayOutOpenWindowMerchant", + "network.protocol.game.ClientboundMerchantOffersPacket" + ) + ); + + public static final Object instance$ItemCost$STREAM_CODEC; + public static final Object instance$ItemCost$OPTIONAL_STREAM_CODEC; + + static { + try { + instance$ItemCost$STREAM_CODEC = !VersionHelper.isOrAbove1_20_5() ? null : + ReflectionUtils.getDeclaredField(CoreReflections.clazz$ItemCost, clazz$StreamCodec, 0).get(null); + instance$ItemCost$OPTIONAL_STREAM_CODEC = !VersionHelper.isOrAbove1_20_5() ? null : + ReflectionUtils.getDeclaredField(CoreReflections.clazz$ItemCost, clazz$StreamCodec, 1).get(null); + } catch (ReflectiveOperationException e) { + throw new ReflectionInitException("Failed to initialize ItemCost$STREAM_CODEC", e); + } + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/trade/MerchantOffer.java b/core/src/main/java/net/momirealms/craftengine/core/item/trade/MerchantOffer.java new file mode 100644 index 000000000..4fa2f74b7 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/item/trade/MerchantOffer.java @@ -0,0 +1,87 @@ +package net.momirealms.craftengine.core.item.trade; + +import net.momirealms.craftengine.core.item.Item; + +import java.util.Optional; +import java.util.function.Function; + +public class MerchantOffer { + private Item cost1; + private Optional> cost2; + private Item result; + private final int uses; + private final int maxUses; + private final int specialPrice; + private final int xp; + private final float priceMultiplier; + private final int demand; + private final boolean outOfStock; + + public MerchantOffer(Item cost1, + Optional> cost2, + Item result, + boolean outOfStock, + int uses, + int maxUses, + int xp, + int specialPrice, + float priceMultiplier, + int demand) { + this.cost1 = cost1; + this.cost2 = cost2; + this.result = result; + this.outOfStock = outOfStock; + this.uses = uses; + this.maxUses = maxUses; + this.specialPrice = specialPrice; + this.xp = xp; + this.priceMultiplier = priceMultiplier; + this.demand = demand; + } + + public void applyClientboundData(Function, Item> function) { + this.cost1 = function.apply(this.cost1); + this.cost2 = this.cost2.map(function); + this.result = function.apply(this.result); + } + + public Item cost1() { + return cost1; + } + + public Optional> cost2() { + return cost2; + } + + public Item result() { + return result; + } + + public int uses() { + return uses; + } + + public int maxUses() { + return maxUses; + } + + public int specialPrice() { + return specialPrice; + } + + public int xp() { + return xp; + } + + public float priceMultiplier() { + return priceMultiplier; + } + + public int demand() { + return demand; + } + + public boolean outOfStock() { + return outOfStock; + } +} diff --git a/gradle.properties b/gradle.properties index a606d91b8..352edc9f8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -50,7 +50,7 @@ byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.5 anti_grief_version=1.0.2 -nms_helper_version=1.0.102 +nms_helper_version=1.0.103 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.34.5