Reimplement enchantmnet glint, fix NCP compatibility
This commit is contained in:
1 parent
3bedc7448c
commit
dd9bd5f291
6 files changed
+179
-24
No files matched your search
@@ -2,18 +2,13 @@
|
||||
// Authors: Barny1094875, NotAlexNoyle.
|
||||
package net.trueog.flyingbowog.Commands;
|
||||
|
||||
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.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
public class GiveCommand implements CommandExecutor {
|
||||
|
||||
@@ -33,17 +28,7 @@ public class GiveCommand implements CommandExecutor {
|
||||
// give bows
|
||||
if (player.hasPermission("flyingbow.cangive")) {
|
||||
|
||||
// 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(FlyingBowOG.LORE_MARKER)));
|
||||
// Tag as a Flying Bow via PersistentDataContainer (Panilla-legal NBT).
|
||||
FlyingBowOG.tagFlyingBow(bowMeta);
|
||||
flyingBowItem.setItemMeta(bowMeta);
|
||||
|
||||
player.getInventory().addItem(flyingBowItem);
|
||||
player.getInventory().addItem(FlyingBowOG.createFlyingBowItem());
|
||||
|
||||
}
|
||||
// tell the player that they don't have permission to use this command
|
||||
|
||||
@@ -10,13 +10,16 @@ import net.trueog.flyingbowog.Commands.CommandsTabCompleter;
|
||||
import net.trueog.flyingbowog.Commands.GiveCommand;
|
||||
import net.trueog.flyingbowog.Listeners.OnAnvilUpdateResultEvent;
|
||||
import net.trueog.flyingbowog.Listeners.OnEntityDamageEvent;
|
||||
import net.trueog.flyingbowog.Listeners.OnEntityDismountEvent;
|
||||
import net.trueog.flyingbowog.Listeners.OnEntityShootBowEvent;
|
||||
import net.trueog.flyingbowog.Listeners.OnGenericGameEvent;
|
||||
import net.trueog.flyingbowog.Listeners.OnPrepareAnvilEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
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;
|
||||
@@ -43,14 +46,7 @@ public final class FlyingBowOG extends JavaPlugin implements Listener {
|
||||
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(LORE_MARKER)));
|
||||
// Tag as a Flying Bow via PersistentDataContainer (Panilla-legal NBT).
|
||||
tagFlyingBow(bowMeta);
|
||||
flyingBowItem.setItemMeta(bowMeta);
|
||||
ItemStack flyingBowItem = createFlyingBowItem();
|
||||
|
||||
// add the recipe into the game
|
||||
ShapedRecipe flyingBowRecipe = new ShapedRecipe(flyingBowKey, flyingBowItem);
|
||||
@@ -64,6 +60,7 @@ public final class FlyingBowOG extends JavaPlugin implements Listener {
|
||||
getServer().getPluginManager().registerEvents(new OnEntityShootBowEvent(), this);
|
||||
getServer().getPluginManager().registerEvents(new OnGenericGameEvent(), this);
|
||||
getServer().getPluginManager().registerEvents(new OnEntityDamageEvent(), this);
|
||||
getServer().getPluginManager().registerEvents(new OnEntityDismountEvent(), this);
|
||||
getServer().getPluginManager().registerEvents(new OnPrepareAnvilEvent(), this);
|
||||
getServer().getPluginManager().registerEvents(new OnAnvilUpdateResultEvent(), this);
|
||||
|
||||
@@ -78,6 +75,33 @@ public final class FlyingBowOG extends JavaPlugin implements Listener {
|
||||
|
||||
}
|
||||
|
||||
// Builds a fresh Flying Bow: cyan name, lore marker, PDC identity tag, and a
|
||||
// hidden Unbreaking I enchant that exists only for the enchantment glint. This
|
||||
// is the same glint trick DiamondBank-OG uses on its Diamond Shards, and it
|
||||
// clears every item validator on the stack: Unbreaking is bow-legal at level 1
|
||||
// (IllegalStack only strips wrong-type or over-max enchants), HIDE_ENCHANTS
|
||||
// keeps
|
||||
// the tooltip clean, and the bow's identity still lives in the PDC -- so even a
|
||||
// strict Panilla config that strips HideFlags only costs the glint, never the
|
||||
// bow. Single source of truth for both the recipe result and /flyingbow give.
|
||||
public static ItemStack createFlyingBowItem() {
|
||||
|
||||
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(LORE_MARKER)));
|
||||
// Tag as a Flying Bow via PersistentDataContainer (Panilla-legal NBT).
|
||||
tagFlyingBow(bowMeta);
|
||||
// Enchantment glint only: hidden, bow-legal Unbreaking I.
|
||||
bowMeta.addEnchant(Enchantment.DURABILITY, 1, false);
|
||||
bowMeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||
flyingBowItem.setItemMeta(bowMeta);
|
||||
|
||||
return flyingBowItem;
|
||||
|
||||
}
|
||||
|
||||
// Stamps a Flying Bow marker into an item's PersistentDataContainer.
|
||||
public static void tagFlyingBow(ItemMeta meta) {
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
// This is free and unencumbered software released into the public domain.
|
||||
// Authors: NotAlexNoyle.
|
||||
package net.trueog.flyingbowog.Listeners;
|
||||
|
||||
import net.trueog.flyingbowog.NCPHook;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.potion.PotionType;
|
||||
import org.spigotmc.event.entity.EntityDismountEvent;
|
||||
|
||||
// Single cleanup point for the NoCheatPlus MOVING_CREATIVEFLY exemption taken in
|
||||
// OnEntityShootBowEvent. EntityDismountEvent fires for every way a ride ends -- the
|
||||
// arrow landing and being removed, the self-hit removal, manual dismount, or death --
|
||||
// so restoring the check here guarantees the exemption never leaks past the ride.
|
||||
public class OnEntityDismountEvent implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onEntityDismount(EntityDismountEvent event) {
|
||||
|
||||
if (!(event.getEntity() instanceof Player player))
|
||||
return;
|
||||
if (!(event.getDismounted() instanceof Arrow arrow))
|
||||
return;
|
||||
|
||||
// Only react to our cyan, UNCRAFTABLE Flying Bow arrows.
|
||||
Color color = arrow.getColor();
|
||||
if (color == null || color.asRGB() != 0x00FFFF)
|
||||
return;
|
||||
if (arrow.getBasePotionData().getType() != PotionType.UNCRAFTABLE)
|
||||
return;
|
||||
|
||||
NCPHook.unexemptCreativeFly(player);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ package net.trueog.flyingbowog.Listeners;
|
||||
import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; // Purpur 1.19
|
||||
import java.util.Map;
|
||||
import net.trueog.flyingbowog.FlyingBowOG;
|
||||
import net.trueog.flyingbowog.NCPHook;
|
||||
import net.trueog.utilitiesog.UtilitiesOG;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Color;
|
||||
@@ -75,6 +76,10 @@ public class OnEntityShootBowEvent implements Listener {
|
||||
|
||||
rideArrow.addPassenger(shooter);
|
||||
|
||||
// Stop NoCheatPlus from flagging the arrow ride as illegal flight
|
||||
// (MOVING_CREATIVEFLY). Cleared on dismount in OnEntityDismountEvent.
|
||||
NCPHook.exemptCreativeFly(shooter);
|
||||
|
||||
}, 1L);
|
||||
|
||||
// Strip Infinity from the bow (too OP for this item).
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
// This is free and unencumbered software released into the public domain.
|
||||
// Authors: NotAlexNoyle.
|
||||
package net.trueog.flyingbowog;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
// Soft integration with NoCheatPlus. While a player rides a Flying Bow arrow they
|
||||
// move through the air faster than survival movement allows, and NCP's CreativeFly
|
||||
// check (MOVING_CREATIVEFLY) flags that as illegal flight, setting the player back or
|
||||
// kicking them. We exempt that single check for the duration of the ride.
|
||||
//
|
||||
// NCP is an optional dependency (softdepend). The exemption API is reached by
|
||||
// reflection rather than a compile-time dependency: NoCheatPlus publishes a broken
|
||||
// Maven artifact (its POM points at an unpublished parent), and reflection also binds
|
||||
// to whatever NCP version is actually installed at runtime. If NoCheatPlus is absent
|
||||
// or its API ever changes shape, every call here is a silent no-op and the Flying Bow
|
||||
// keeps working.
|
||||
public final class NCPHook {
|
||||
|
||||
// Cached reflection handles, resolved once on first use. ready == true means
|
||||
// all
|
||||
// handles bound and exemption calls will be attempted.
|
||||
private static boolean resolved = false;
|
||||
private static boolean ready = false;
|
||||
private static Method exemptMethod;
|
||||
private static Method unexemptMethod;
|
||||
private static Object creativeFlyCheckType;
|
||||
|
||||
private NCPHook() {
|
||||
|
||||
}
|
||||
|
||||
// Exempt the player from MOVING_CREATIVEFLY while riding a Flying Bow arrow.
|
||||
public static void exemptCreativeFly(Player player) {
|
||||
|
||||
if (!resolve())
|
||||
return;
|
||||
|
||||
try {
|
||||
|
||||
exemptMethod.invoke(null, player, creativeFlyCheckType);
|
||||
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
// NCP unavailable or API mismatch: leave checking as-is.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Restore MOVING_CREATIVEFLY checking once the ride ends.
|
||||
public static void unexemptCreativeFly(Player player) {
|
||||
|
||||
if (!resolve())
|
||||
return;
|
||||
|
||||
try {
|
||||
|
||||
unexemptMethod.invoke(null, player, creativeFlyCheckType);
|
||||
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
// NCP unavailable or API mismatch: leave checking as-is.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Bind the NCP exemption API on first use. Returns whether the hook is usable.
|
||||
private static synchronized boolean resolve() {
|
||||
|
||||
if (resolved)
|
||||
return ready;
|
||||
resolved = true;
|
||||
|
||||
if (Bukkit.getPluginManager().getPlugin("NoCheatPlus") == null)
|
||||
return false;
|
||||
|
||||
try {
|
||||
|
||||
Class<?> checkType = Class.forName("fr.neatmonster.nocheatplus.checks.CheckType");
|
||||
Class<?> exemptionManager = Class.forName("fr.neatmonster.nocheatplus.hooks.NCPExemptionManager");
|
||||
|
||||
creativeFlyCheckType = Enum.valueOf(checkType.asSubclass(Enum.class), "MOVING_CREATIVEFLY");
|
||||
exemptMethod = exemptionManager.getMethod("exemptPermanently", Player.class, checkType);
|
||||
unexemptMethod = exemptionManager.getMethod("unexempt", Player.class, checkType);
|
||||
|
||||
ready = true;
|
||||
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
// Missing classes / renamed API: disable the hook quietly.
|
||||
ready = false;
|
||||
|
||||
}
|
||||
|
||||
return ready;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ main: net.trueog.flyingbowog.FlyingBowOG
|
||||
authors: [barny1094875, NotAlexNoyle]
|
||||
api-version: 1.19
|
||||
depend: [Item-NBT-API]
|
||||
softdepend: [NoCheatPlus]
|
||||
commands:
|
||||
flyingbow:
|
||||
usage: /flyingbow
|
||||
|
||||
Reference in new issue
Block a user