Преглед изворни кода

Crossbow trickshot no longer rewards archery xp
Fixes #5153 Fixes #5144

nossr50 пре 2 месеци
родитељ
комит
2efe1efc50

+ 1 - 0
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)

+ 2 - 1
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);
             }
         }

+ 10 - 1
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

+ 1 - 0
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";

+ 2 - 2
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);

+ 15 - 1
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);
     }
 }