diff --git a/paper/pom.xml b/paper/pom.xml index ce0e1978cf..5f4e8b84e7 100644 --- a/paper/pom.xml +++ b/paper/pom.xml @@ -31,7 +31,7 @@ net.citizensnpcs citizens-main - 2.0.42-SNAPSHOT + 2.0.43-SNAPSHOT jar provided diff --git a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerTradesWithMerchantScriptEvent.java b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerTradesWithMerchantScriptEvent.java index f422eb9bc7..626c390744 100644 --- a/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerTradesWithMerchantScriptEvent.java +++ b/paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerTradesWithMerchantScriptEvent.java @@ -9,6 +9,7 @@ import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.player.PlayerPurchaseEvent; import io.papermc.paper.event.player.PlayerTradeEvent; +import org.bukkit.entity.AbstractVillager; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -37,7 +38,6 @@ public class PlayerTradesWithMerchantScriptEvent extends BukkitScriptEvent imple // @Determine // TradeTag to change the trade that should be processed. // - // // @Player Always. // // --> @@ -51,6 +51,7 @@ public PlayerTradesWithMerchantScriptEvent() { } public PlayerPurchaseEvent event; + public AbstractVillager villager; @Override public boolean matches(ScriptPath path) { @@ -71,7 +72,7 @@ public ScriptEntryData getScriptEntryData() { @Override public ObjectTag getContext(String name) { return switch (name) { - case "merchant" -> event instanceof PlayerTradeEvent tradeEvent ? new EntityTag(tradeEvent.getVillager()) : null; + case "merchant" -> villager != null ? new EntityTag(villager) : null; case "trade" -> new TradeTag(event.getTrade()).duplicate(); default -> super.getContext(name); }; @@ -80,6 +81,10 @@ public ObjectTag getContext(String name) { @EventHandler public void playerTradeEvent(PlayerPurchaseEvent event) { this.event = event; + villager = event instanceof PlayerTradeEvent tradeEvent ? tradeEvent.getVillager() : null; + if (event instanceof PlayerTradeEvent && EntityTag.isCitizensNPC(villager)) { + return; + } fire(event); } } diff --git a/plugin/pom.xml b/plugin/pom.xml index b9ba8f0938..9385f4aa5a 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -44,7 +44,7 @@ net.citizensnpcs citizens-main - 2.0.42-SNAPSHOT + 2.0.43-SNAPSHOT jar provided diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/ScriptEventRegistry.java b/plugin/src/main/java/com/denizenscript/denizen/events/ScriptEventRegistry.java index ea2764e4b1..97788d5c92 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/events/ScriptEventRegistry.java +++ b/plugin/src/main/java/com/denizenscript/denizen/events/ScriptEventRegistry.java @@ -4,10 +4,7 @@ import com.denizenscript.denizen.events.block.*; import com.denizenscript.denizen.events.entity.*; import com.denizenscript.denizen.events.item.*; -import com.denizenscript.denizen.events.npc.NPCNavigationScriptEvent; -import com.denizenscript.denizen.events.npc.NPCOpensScriptEvent; -import com.denizenscript.denizen.events.npc.NPCSpawnScriptEvent; -import com.denizenscript.denizen.events.npc.NPCStuckScriptEvent; +import com.denizenscript.denizen.events.npc.*; import com.denizenscript.denizen.events.player.*; import com.denizenscript.denizen.events.server.*; import com.denizenscript.denizen.events.vehicle.*; @@ -25,6 +22,9 @@ public class ScriptEventRegistry { public static void registerCitizensEvents() { ScriptEvent.registerScriptEvent(NPCNavigationScriptEvent.class); ScriptEvent.registerScriptEvent(NPCOpensScriptEvent.class); + if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { + ScriptEvent.registerScriptEvent(NPCShopTradeScriptEvent.class); + } ScriptEvent.registerScriptEvent(NPCSpawnScriptEvent.class); ScriptEvent.registerScriptEvent(NPCStuckScriptEvent.class); } diff --git a/plugin/src/main/java/com/denizenscript/denizen/events/npc/NPCShopTradeScriptEvent.java b/plugin/src/main/java/com/denizenscript/denizen/events/npc/NPCShopTradeScriptEvent.java new file mode 100644 index 0000000000..2ddb2847d4 --- /dev/null +++ b/plugin/src/main/java/com/denizenscript/denizen/events/npc/NPCShopTradeScriptEvent.java @@ -0,0 +1,117 @@ +package com.denizenscript.denizen.events.npc; + +import com.denizenscript.denizen.events.BukkitScriptEvent; +import com.denizenscript.denizen.objects.ItemTag; +import com.denizenscript.denizen.objects.NPCTag; +import com.denizenscript.denizen.objects.PlayerTag; +import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; +import com.denizenscript.denizencore.objects.ObjectTag; +import com.denizenscript.denizencore.objects.core.ElementTag; +import com.denizenscript.denizencore.objects.core.ListTag; +import com.denizenscript.denizencore.objects.core.MapTag; +import com.denizenscript.denizencore.scripts.ScriptEntryData; +import net.citizensnpcs.trait.ShopTrait; +import net.citizensnpcs.trait.shop.*; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +import java.util.List; + +public class NPCShopTradeScriptEvent extends BukkitScriptEvent implements Listener { + + // <--[event] + // @Events + // player trades with npc + // + // @Switch shop: to only process the event if the transaction was within a specific shop. + // + // @Group NPC + // + // @Location true + // + // @Triggers when a player trades in a Citizens shop. + // + // @Context + // return a MapTag of the types of costs and what their values were in the purchase. + // return a MapTag of the types of results and what their values were in the purchase. + // returns the name of the shop the purchase was made in. + // + // @Player Always. + // + // @NPC when the shop is accessed through an NPC. + // + // --> + + public NPCShopTradeScriptEvent() { + registerCouldMatcher("player trades with npc"); + registerSwitches("shop"); + } + + public PlayerTag player; + public NPCTag npc; + public ShopTrait.NPCShop shop; + public ShopTrait.NPCShopPurchaseEvent event; + + @Override + public boolean matches(ScriptPath path) { + if (!runInCheck(path, player.getLocation())) { + return false; + } + if (!path.tryObjectSwitch("shop", new ElementTag(shop.getName()))) { + return false; + } + return super.matches(path); + } + + @Override + public ScriptEntryData getScriptEntryData() { + return new BukkitScriptEntryData(player, npc); + } + + @Override + public ObjectTag getContext(String name) { + return switch (name) { + case "cost" -> actionListToMap(event.getItem().getCost()); + case "result" -> actionListToMap(event.getItem().getResult()); + case "shop" -> new ElementTag(shop.getName(), true); + default -> super.getContext(name); + }; + } + + private MapTag actionListToMap(List actions) { + MapTag result = new MapTag(); + for (NPCShopAction action : actions) { + if (action instanceof CommandAction commandAction) { + result.putObject("commands", new ListTag(commandAction.commands, true)); + } + else if (action instanceof ConditionAction conditionAction) { + result.putObject("condition", new ElementTag(conditionAction.describe(), true)); + } + else if (action instanceof ExperienceAction experienceAction) { + result.putObject("experience", new ElementTag(experienceAction.exp)); + } + else if (action instanceof ItemAction itemAction) { + result.putObject("items", new ListTag(itemAction.items, ItemTag::new)); + } + else if (action instanceof MoneyAction moneyAction) { + result.putObject("money", new ElementTag(moneyAction.money)); + } + else if (action instanceof OpenShopAction openShopAction) { + result.putObject("open_shop", new ElementTag(openShopAction.shopName, true)); + } + else if (action instanceof PermissionAction permissionAction) { + result.putObject("permissions", new ListTag(permissionAction.permissions, true)); + } + } + return result; + } + + @EventHandler + public void onNPCShopPurchase(ShopTrait.NPCShopPurchaseEvent event) { + this.event = event; + shop = event.getShop(); + player = PlayerTag.mirrorBukkitPlayer(event.getPlayer()); + npc = shop.getNPC().isPresent() ? new NPCTag(shop.getNPC().get()) : null; + fire(event); + } +}