diff --git a/src/main/java/net/trueog/flyingbowog/Commands/GiveCommand.java b/src/main/java/net/trueog/flyingbowog/Commands/GiveCommand.java index 697ff0f..e864531 100644 --- a/src/main/java/net/trueog/flyingbowog/Commands/GiveCommand.java +++ b/src/main/java/net/trueog/flyingbowog/Commands/GiveCommand.java @@ -6,12 +6,12 @@ import java.util.Collections; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextDecoration; +import net.trueog.flyingbowog.FlyingBowOG; import org.bukkit.Material; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -38,9 +38,10 @@ public class GiveCommand implements CommandExecutor { ItemMeta bowMeta = flyingBowItem.getItemMeta(); bowMeta.displayName(Component.text("Flying Bow").color(TextColor.color(0, 255, 255)) .decorate(TextDecoration.ITALIC)); - bowMeta.lore(Collections.singletonList(Component.text("Shoot this bow to FLY"))); + bowMeta.lore(Collections.singletonList(Component.text(FlyingBowOG.LORE_MARKER))); + // Tag as a Flying Bow via PersistentDataContainer (Panilla-legal NBT). + FlyingBowOG.tagFlyingBow(bowMeta); flyingBowItem.setItemMeta(bowMeta); - flyingBowItem.addItemFlags(ItemFlag.HIDE_DYE); player.getInventory().addItem(flyingBowItem); diff --git a/src/main/java/net/trueog/flyingbowog/FlyingBowOG.java b/src/main/java/net/trueog/flyingbowog/FlyingBowOG.java index 59d23c9..ca15bff 100644 --- a/src/main/java/net/trueog/flyingbowog/FlyingBowOG.java +++ b/src/main/java/net/trueog/flyingbowog/FlyingBowOG.java @@ -17,37 +17,43 @@ import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.event.Listener; -import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ShapedRecipe; import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; import org.bukkit.plugin.java.JavaPlugin; public final class FlyingBowOG extends JavaPlugin implements Listener { private static FlyingBowOG plugin; + // PersistentDataContainer key identifying a Flying Bow. Stored under the + // vanilla-legal PublicBukkitValues NBT compound so anti-illegal-item plugins + // (e.g. Panilla) do not strip it, unlike the old HideFlags-based marker. + private static NamespacedKey flyingBowKey; + + // Lore line shown on every Flying Bow (display only; identity is the PDC tag). + public static final String LORE_MARKER = "Shoot this bow to FLY"; + @Override public void onEnable() { // Plugin startup logic plugin = this; + flyingBowKey = new NamespacedKey(this, "flying_bow"); // create the flying bow item ItemStack flyingBowItem = new ItemStack(Material.BOW); ItemMeta bowMeta = flyingBowItem.getItemMeta(); bowMeta.displayName( Component.text("Flying Bow").color(TextColor.color(0, 255, 255)).decorate(TextDecoration.ITALIC)); - bowMeta.lore(Collections.singletonList(Component.text("Shoot this bow to FLY"))); + bowMeta.lore(Collections.singletonList(Component.text(LORE_MARKER))); + // Tag as a Flying Bow via PersistentDataContainer (Panilla-legal NBT). + tagFlyingBow(bowMeta); flyingBowItem.setItemMeta(bowMeta); - // adding a useless itemFlag to identify this as a flying bow - // this was easier for me than adding an attribute, and no other bow should have - // this flag - flyingBowItem.addItemFlags(ItemFlag.HIDE_DYE); - // add the recipe into the game - ShapedRecipe flyingBowRecipe = new ShapedRecipe(new NamespacedKey(this, "flying_bow"), flyingBowItem); + ShapedRecipe flyingBowRecipe = new ShapedRecipe(flyingBowKey, flyingBowItem); flyingBowRecipe.shape("sd ", "sed", "sd "); flyingBowRecipe.setIngredient('s', Material.STICK); flyingBowRecipe.setIngredient('e', Material.ELYTRA); @@ -72,6 +78,28 @@ public final class FlyingBowOG extends JavaPlugin implements Listener { } + // Stamps a Flying Bow marker into an item's PersistentDataContainer. + public static void tagFlyingBow(ItemMeta meta) { + + meta.getPersistentDataContainer().set(flyingBowKey, PersistentDataType.BYTE, (byte) 1); + + } + + // Canonical Flying Bow identity check used by every listener. Identity lives in + // the PDC marker only (Panilla-legal NBT). + public static boolean isFlyingBow(ItemStack item) { + + if (item == null || item.getType() != Material.BOW) + return false; + + ItemMeta meta = item.getItemMeta(); + if (meta == null) + return false; + + return meta.getPersistentDataContainer().has(flyingBowKey, PersistentDataType.BYTE); + + } + public static String getPrefix() { return "&7[&5FlyingBow&f-&4OG&7] "; diff --git a/src/main/java/net/trueog/flyingbowog/Listeners/OnEntityShootBowEvent.java b/src/main/java/net/trueog/flyingbowog/Listeners/OnEntityShootBowEvent.java index 134d6a4..10e7287 100644 --- a/src/main/java/net/trueog/flyingbowog/Listeners/OnEntityShootBowEvent.java +++ b/src/main/java/net/trueog/flyingbowog/Listeners/OnEntityShootBowEvent.java @@ -16,7 +16,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityShootBowEvent; -import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionData; import org.bukkit.potion.PotionType; @@ -32,19 +31,10 @@ public class OnEntityShootBowEvent implements Listener { // Only react to players shooting arrows with our Flying Bow. if (!(event.getEntity() instanceof Player player)) return; - FlyingBowOG.getPlugin().getLogger().info("[FB-DEBUG] shoot by player " + player.getName()); - if (!(event.getProjectile() instanceof Arrow arrow)) { - - FlyingBowOG.getPlugin().getLogger() - .info("[FB-DEBUG] projectile NOT Arrow: " + event.getProjectile().getType()); + if (!(event.getProjectile() instanceof Arrow arrow)) return; - - } - ItemStack bow = player.getInventory().getItemInMainHand(); - FlyingBowOG.getPlugin().getLogger().info("[FB-DEBUG] mainhand=" + bow.getType() + " flags=" + bow.getItemFlags() - + " isFlyingBow=" + isFlyingBow(bow)); - if (!isFlyingBow(bow)) + if (!FlyingBowOG.isFlyingBow(bow)) return; // Block flying bow usage while player is already wearing an elytra. @@ -80,15 +70,10 @@ public class OnEntityShootBowEvent implements Listener { boolean sameWorld = shooter.getWorld().getKey().toString().equals(worldKey); - FlyingBowOG.getPlugin().getLogger().info("[FB-DEBUG] mount tick: sameWorld=" + sameWorld + " dead=" - + rideArrow.isDead() + " valid=" + rideArrow.isValid()); - if (!sameWorld || rideArrow.isDead() || !rideArrow.isValid()) return; - boolean mounted = rideArrow.addPassenger(shooter); - FlyingBowOG.getPlugin().getLogger() - .info("[FB-DEBUG] addPassenger returned " + mounted + " passengers=" + rideArrow.getPassengers()); + rideArrow.addPassenger(shooter); }, 1L); @@ -142,7 +127,7 @@ public class OnEntityShootBowEvent implements Listener { Player player = event.getPlayer(); - boolean holdingFlyingBow = isFlyingBow(player.getInventory().getItemInMainHand()); + boolean holdingFlyingBow = FlyingBowOG.isFlyingBow(player.getInventory().getItemInMainHand()); boolean ridingFlyingBowArrow = isRidingTaggedArrow(player); if (!(holdingFlyingBow || ridingFlyingBowArrow)) @@ -165,13 +150,6 @@ public class OnEntityShootBowEvent implements Listener { } - // Identifies your custom “Flying Bow”. - private boolean isFlyingBow(ItemStack item) { - - return item != null && item.getType() == Material.BOW && item.getItemFlags().contains(ItemFlag.HIDE_DYE); - - } - // True if the player is riding one of the cyan, UNCRAFTABLE arrows. private boolean isRidingTaggedArrow(Player player) { diff --git a/src/main/java/net/trueog/flyingbowog/Listeners/OnPrepareAnvilEvent.java b/src/main/java/net/trueog/flyingbowog/Listeners/OnPrepareAnvilEvent.java index 4236a97..631c373 100644 --- a/src/main/java/net/trueog/flyingbowog/Listeners/OnPrepareAnvilEvent.java +++ b/src/main/java/net/trueog/flyingbowog/Listeners/OnPrepareAnvilEvent.java @@ -11,7 +11,6 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.inventory.PrepareAnvilEvent; import org.bukkit.inventory.AnvilInventory; -import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.Damageable; @@ -31,7 +30,7 @@ public class OnPrepareAnvilEvent implements Listener { if (secondItem != null) { - if (firstItem.getItemFlags().contains(ItemFlag.HIDE_DYE) && firstItem.getType().equals(Material.BOW)) { + if (FlyingBowOG.isFlyingBow(firstItem)) { if (secondItem.getType().equals(Material.PHANTOM_MEMBRANE)) { @@ -104,10 +103,8 @@ public class OnPrepareAnvilEvent implements Listener { // if the second item is a bow if (secondItem.getType().equals(Material.BOW)) { - // if only one bow has the HIDE_DYE flag - if (firstItem.getItemFlags().contains(ItemFlag.HIDE_DYE) - ^ secondItem.getItemFlags().contains(ItemFlag.HIDE_DYE)) - { + // if only one of the two bows is a flying bow + if (FlyingBowOG.isFlyingBow(firstItem) ^ FlyingBowOG.isFlyingBow(secondItem)) { // set the result to null event.setResult(null);