Added PlayerPurchaseEvent for standalone Merchant GUIs (#5583)

This commit is contained in:
Alexander 2021-05-24 11:51:06 +01:00 committed by GitHub
parent 615df3d8a6
commit afe0785bfe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 122 additions and 30 deletions

View File

@ -1,78 +1,75 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 2 Jul 2020 16:10:10 -0700
Subject: [PATCH] added PlayerTradeEvent
Subject: [PATCH] Added PlayerTradeEvent
[Amendment: Alexander <protonull@protonmail.com>]
PlayerTradeEvent is used for player purchases from villagers and wandering
traders, but not custom merchants created via Bukkit.createMerchant(). During
discussions in Discord it was decided that it'd be better to add a new event
that PlayerTradeEvent inherits from than change getVillager()'s annotation to
@Nullable, especially since that'd also infringe on the implication of the
event being about villager trades.
diff --git a/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java
new file mode 100755
index 0000000000000000000000000000000000000000..198e5464eae6b961c83148a57c18f91a4bb33cf6
diff --git a/src/main/java/io/papermc/paper/event/player/PlayerPurchaseEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerPurchaseEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5648055c5e815474bf1e564a5c192ff5c0624fb
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java
@@ -0,0 +1,121 @@
+++ b/src/main/java/io/papermc/paper/event/player/PlayerPurchaseEvent.java
@@ -0,0 +1,112 @@
+package io.papermc.paper.event.player;
+
+import org.bukkit.entity.AbstractVillager;
+import java.util.Objects;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.bukkit.inventory.MerchantRecipe;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Called when a player trades with a villager or wandering trader
+ * Called when a player trades with a standalone merchant GUI.
+ */
+public class PlayerTradeEvent extends PlayerEvent implements Cancellable {
+
+public class PlayerPurchaseEvent extends PlayerEvent implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private boolean cancelled;
+
+ private boolean increaseTradeUses;
+ private boolean rewardExp;
+ private final AbstractVillager villager;
+ private MerchantRecipe trade;
+
+ public PlayerTradeEvent(@NotNull Player player, @NotNull AbstractVillager villager, @NotNull MerchantRecipe trade, boolean rewardExp, boolean increaseTradeUses) {
+ super(player);
+ this.villager = villager;
+ this.trade = trade;
+ public PlayerPurchaseEvent(@NotNull Player player,
+ @NotNull MerchantRecipe trade,
+ boolean rewardExp,
+ boolean increaseTradeUses) {
+ super(Objects.requireNonNull(player, "Player cannot be null!"));
+ setTrade(trade);
+ this.rewardExp = rewardExp;
+ this.increaseTradeUses = increaseTradeUses;
+ }
+
+ /**
+ * Gets the Villager or Wandering trader associated with this event
+ * @return the villager or wandering trader
+ */
+ @NotNull
+ public AbstractVillager getVillager() {
+ return villager;
+ }
+
+ /**
+ * Gets the associated trade with this event
+ * @return the trade
+ */
+ @NotNull
+ public MerchantRecipe getTrade() {
+ return trade;
+ return this.trade;
+ }
+
+ /**
+ * Sets the trade. This is then used to determine the next prices
+ * @param trade the trade to use
+ */
+ public void setTrade(@Nullable MerchantRecipe trade) {
+ this.trade = trade;
+ public void setTrade(@NotNull MerchantRecipe trade) {
+ this.trade = Objects.requireNonNull(trade, "Trade cannot be null!");
+ }
+
+ /**
+ * @return will trade try to reward exp
+ */
+ public boolean isRewardingExp() {
+ return rewardExp;
+ return this.rewardExp;
+ }
+
+ /**
@ -87,7 +84,7 @@ index 0000000000000000000000000000000000000000..198e5464eae6b961c83148a57c18f91a
+ * @return whether or not the trade will count as a use of the trade
+ */
+ public boolean willIncreaseTradeUses() {
+ return increaseTradeUses;
+ return this.increaseTradeUses;
+ }
+
+ /**
@ -130,4 +127,40 @@ index 0000000000000000000000000000000000000000..198e5464eae6b961c83148a57c18f91a
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+}
diff --git a/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java b/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java
new file mode 100755
index 0000000000000000000000000000000000000000..a41fc186746b87f76347dfcc1f80d0969398322b
--- /dev/null
+++ b/src/main/java/io/papermc/paper/event/player/PlayerTradeEvent.java
@@ -0,0 +1,29 @@
+package io.papermc.paper.event.player;
+
+import org.bukkit.entity.AbstractVillager;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.MerchantRecipe;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Called when a player trades with a villager or wandering trader
+ */
+public class PlayerTradeEvent extends PlayerPurchaseEvent {
+
+ private final AbstractVillager villager;
+
+ public PlayerTradeEvent(@NotNull Player player, @NotNull AbstractVillager villager, @NotNull MerchantRecipe trade, boolean rewardExp, boolean increaseTradeUses) {
+ super(player, trade, rewardExp, increaseTradeUses);
+ this.villager = villager;
+ }
+
+ /**
+ * Gets the Villager or Wandering trader associated with this event
+ * @return the villager or wandering trader
+ */
+ @NotNull
+ public AbstractVillager getVillager() {
+ return this.villager;
+ }
+
+}

View File

@ -0,0 +1,59 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Alexander <protonull@protonmail.com>
Date: Thu, 6 May 2021 13:01:25 +0100
Subject: [PATCH] Have CraftMerchantCustom emit PlayerPurchaseEvent
diff --git a/src/main/java/net/minecraft/world/item/trading/IMerchant.java b/src/main/java/net/minecraft/world/item/trading/IMerchant.java
index 5644affeadc51ac3209ee9a087b3d2dd887e401c..7c54ca6af424b9d31f73187df9015f5df84762f4 100644
--- a/src/main/java/net/minecraft/world/item/trading/IMerchant.java
+++ b/src/main/java/net/minecraft/world/item/trading/IMerchant.java
@@ -19,7 +19,7 @@ public interface IMerchant {
MerchantRecipeList getOffers();
- void a(MerchantRecipe merchantrecipe);
+ void a(MerchantRecipe merchantrecipe); default void handlePurchase(MerchantRecipe merchantRecipe) { a(merchantRecipe); } // Paper - OBFHELPER
void k(ItemStack itemstack);
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java
index 206c133ebc6c44038585236b0628543b8bed278c..a7230776b8e85d5d1873ab2dc4e10c5bf78889bb 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java
@@ -81,6 +81,35 @@ public class CraftMerchantCustom extends CraftMerchant {
@Override
public void a(MerchantRecipe merchantrecipe) {
+ // Paper start
+ /** Based on {@link net.minecraft.world.entity.npc.EntityVillagerAbstract#b(MerchantRecipe)} */
+ if (getTrader() instanceof net.minecraft.server.level.EntityPlayer) {
+ final net.minecraft.server.level.EntityPlayer trader = (net.minecraft.server.level.EntityPlayer) getTrader();
+ final io.papermc.paper.event.player.PlayerPurchaseEvent event = new io.papermc.paper.event.player.PlayerPurchaseEvent(
+ trader.getBukkitEntity(),
+ merchantrecipe.asBukkit(),
+ false, // reward xp?
+ true); // should increase uses?
+ event.callEvent();
+ if (event.isCancelled()) {
+ return;
+ }
+ final org.bukkit.inventory.MerchantRecipe eventTrade = event.getTrade();
+ if (event.willIncreaseTradeUses()) {
+ eventTrade.setUses(eventTrade.getUses() + 1);
+ }
+ if (event.isRewardingExp() && eventTrade.hasExperienceReward()) {
+ /** Based on {@link net.minecraft.world.entity.npc.EntityVillagerTrader#b(MerchantRecipe)} */
+ final int xp = 3 + net.minecraft.world.entity.Entity.SHARED_RANDOM.nextInt(4);
+ final World world = trader.getWorld();
+ world.addEntity(new net.minecraft.world.entity.EntityExperienceOrb(
+ world, trader.locX(), trader.locY() + 0.5d, trader.locZ(), xp,
+ org.bukkit.entity.ExperienceOrb.SpawnReason.VILLAGER_TRADE, trader, null));
+ }
+ return;
+ }
+ // Paper end
+
// increase recipe's uses
merchantrecipe.increaseUses();
}