From 2efe1efc50c44a2417ae5cbda8dfb4c247114f2a Mon Sep 17 00:00:00 2001 From: nossr50 Date: Sat, 15 Mar 2025 12:28:35 -0700 Subject: [PATCH] Crossbow trickshot no longer rewards archery xp Fixes #5153 Fixes #5144 --- Changelog.txt | 1 + .../gmail/nossr50/listeners/EntityListener.java | 3 ++- .../skills/crossbows/CrossbowsManager.java | 11 ++++++++++- .../gmail/nossr50/util/MetadataConstants.java | 1 + .../gmail/nossr50/util/skills/CombatUtils.java | 4 ++-- .../nossr50/util/skills/ProjectileUtils.java | 16 +++++++++++++++- 6 files changed, 31 insertions(+), 5 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 78f6defd3..759d05a6b 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,4 +1,5 @@ Version 2.2.034 + Fixed bug where arrow would award archery xp after a crossbow trickshot bounce Version 2.2.033 Added Breeze_Rod entries to potions.yml for Awkward potion (see notes) diff --git a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java index ceef31e10..90976b638 100644 --- a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java @@ -21,6 +21,7 @@ import com.gmail.nossr50.util.player.NotificationManager; import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.random.ProbabilityUtil; import com.gmail.nossr50.util.skills.CombatUtils; +import com.gmail.nossr50.util.skills.ProjectileUtils; import com.gmail.nossr50.worldguard.WorldGuardManager; import com.gmail.nossr50.worldguard.WorldGuardUtils; import org.bukkit.ChatColor; @@ -1090,7 +1091,7 @@ public class EntityListener implements Listener { return; if (event.getEntity() instanceof Arrow arrow) { - if (arrow.isShotFromCrossbow()) { + if (ProjectileUtils.isCrossbowProjectile(arrow)) { Crossbows.processCrossbows(event, pluginRef, arrow); } } diff --git a/src/main/java/com/gmail/nossr50/skills/crossbows/CrossbowsManager.java b/src/main/java/com/gmail/nossr50/skills/crossbows/CrossbowsManager.java index 9a1e0a7c0..59087c37d 100644 --- a/src/main/java/com/gmail/nossr50/skills/crossbows/CrossbowsManager.java +++ b/src/main/java/com/gmail/nossr50/skills/crossbows/CrossbowsManager.java @@ -20,7 +20,10 @@ import org.bukkit.projectiles.ProjectileSource; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; +import static com.gmail.nossr50.util.MetadataConstants.MCMMO_METADATA_VALUE; +import static com.gmail.nossr50.util.MetadataConstants.METADATA_KEY_CROSSBOW_PROJECTILE; import static com.gmail.nossr50.util.skills.CombatUtils.delayArrowMetaCleanup; +import static com.gmail.nossr50.util.skills.ProjectileUtils.isCrossbowProjectile; public class CrossbowsManager extends SkillManager { public CrossbowsManager(McMMOPlayer mmoPlayer) { @@ -28,7 +31,7 @@ public class CrossbowsManager extends SkillManager { } public void handleRicochet(@NotNull Plugin pluginRef, @NotNull Arrow arrow, @NotNull Vector hitBlockNormal) { - if (!arrow.isShotFromCrossbow()) + if (!isCrossbowProjectile(arrow)) return; // Check player permission @@ -79,6 +82,12 @@ public class CrossbowsManager extends SkillManager { new FixedMetadataValue(pluginRef, bounceCount + 1)); spawnedArrow.setMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW, new FixedMetadataValue(pluginRef, originalArrowShooter)); + // Easy fix to recognize the arrow as a crossbow projectile + // TODO: Replace the hack with the new API for setting weapon on projectiles + if (!spawnedArrow.hasMetadata(METADATA_KEY_CROSSBOW_PROJECTILE)) { + spawnedArrow.setMetadata(MetadataConstants.METADATA_KEY_CROSSBOW_PROJECTILE, MCMMO_METADATA_VALUE); + } + // There are reasons to keep this despite using the metadata values above spawnedArrow.setShotFromCrossbow(true); // Don't allow multi-shot or infinite arrows to be picked up diff --git a/src/main/java/com/gmail/nossr50/util/MetadataConstants.java b/src/main/java/com/gmail/nossr50/util/MetadataConstants.java index d3145e42c..a99f47ee9 100644 --- a/src/main/java/com/gmail/nossr50/util/MetadataConstants.java +++ b/src/main/java/com/gmail/nossr50/util/MetadataConstants.java @@ -14,6 +14,7 @@ public class MetadataConstants { * Take great care if you ever modify the value of these keys */ public static final @NotNull String METADATA_KEY_REPLANT = "mcMMO: Recently Replanted"; + public static final @NotNull String METADATA_KEY_CROSSBOW_PROJECTILE = "mcMMO: Crossbow Projectile"; public static final @NotNull String METADATA_KEY_SPAWNED_ARROW = "mcMMO: Spawned Arrow"; public static final @NotNull String METADATA_KEY_MULTI_SHOT_ARROW = "mcMMO: Multi-shot Arrow"; public static final @NotNull String METADATA_KEY_BOUNCE_COUNT = "mcMMO: Arrow Bounce Count"; diff --git a/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java b/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java index 5afa956a6..a50f2271e 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java +++ b/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java @@ -39,6 +39,7 @@ import java.util.List; import static com.gmail.nossr50.datatypes.experience.XPGainReason.PVP; import static com.gmail.nossr50.util.AttributeMapper.MAPPED_MOVEMENT_SPEED; import static com.gmail.nossr50.util.MobMetadataUtils.hasMobFlag; +import static com.gmail.nossr50.util.skills.ProjectileUtils.isCrossbowProjectile; public final class CombatUtils { @@ -567,9 +568,8 @@ public final class CombatUtils { } } else if (painSource instanceof Arrow arrow) { ProjectileSource projectileSource = arrow.getShooter(); - boolean isCrossbow = arrow.isShotFromCrossbow(); + boolean isCrossbow = isCrossbowProjectile(arrow); if (projectileSource instanceof Player player) { - if (!Misc.isNPCEntityExcludingVillagers(player)) { if (!isCrossbow && mcMMO.p.getSkillTools().canCombatSkillsTrigger(PrimarySkillType.ARCHERY, target)) { processArcheryCombat(target, player, event, arrow); diff --git a/src/main/java/com/gmail/nossr50/util/skills/ProjectileUtils.java b/src/main/java/com/gmail/nossr50/util/skills/ProjectileUtils.java index 4835afc47..ae2fe7161 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/ProjectileUtils.java +++ b/src/main/java/com/gmail/nossr50/util/skills/ProjectileUtils.java @@ -9,6 +9,8 @@ import org.bukkit.plugin.Plugin; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; +import static com.gmail.nossr50.util.MetadataConstants.MCMMO_METADATA_VALUE; + public class ProjectileUtils { public static Vector getNormal(BlockFace blockFace) { return switch (blockFace) { @@ -27,7 +29,6 @@ public class ProjectileUtils { * * @param arrow projectile */ - // TODO: Add test public static void cleanupProjectileMetadata(@NotNull Arrow arrow) { if (arrow.hasMetadata(MetadataConstants.METADATA_KEY_INF_ARROW)) { arrow.removeMetadata(MetadataConstants.METADATA_KEY_INF_ARROW, mcMMO.p); @@ -52,6 +53,10 @@ public class ProjectileUtils { if (arrow.hasMetadata(MetadataConstants.METADATA_KEY_BOUNCE_COUNT)) { arrow.removeMetadata(MetadataConstants.METADATA_KEY_BOUNCE_COUNT, mcMMO.p); } + + if (arrow.hasMetadata(MetadataConstants.METADATA_KEY_CROSSBOW_PROJECTILE)) { + arrow.removeMetadata(MetadataConstants.METADATA_KEY_CROSSBOW_PROJECTILE, mcMMO.p); + } } public static void copyArrowMetadata(@NotNull Plugin pluginRef, @NotNull Arrow arrowToCopy, @NotNull Arrow newArrow) { @@ -80,5 +85,14 @@ public class ProjectileUtils { newArrow.setMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW, arrowToCopy.getMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW).get(0)); } + + if (arrowToCopy.hasMetadata(MetadataConstants.METADATA_KEY_CROSSBOW_PROJECTILE)) { + newArrow.setMetadata(MetadataConstants.METADATA_KEY_CROSSBOW_PROJECTILE, MCMMO_METADATA_VALUE); + } + } + + public static boolean isCrossbowProjectile(@NotNull Arrow arrow) { + return arrow.isShotFromCrossbow() + || arrow.hasMetadata(MetadataConstants.METADATA_KEY_CROSSBOW_PROJECTILE); } }