浏览代码

update for 1.21.3 compatibility

nossr50 8 月之前
父节点
当前提交
99bb5857f8

+ 3 - 1
Changelog.txt

@@ -1,9 +1,11 @@
+Version 2.2.023
+    Compatibility with Minecraft 1.21.3
+
 Version 2.2.022
 Version 2.2.022
     Fixed a bug where Roll was always reducing damage (thanks Ineusia)
     Fixed a bug where Roll was always reducing damage (thanks Ineusia)
     Fix COTW errors on older versions (thanks Warriorrrr)
     Fix COTW errors on older versions (thanks Warriorrrr)
     Fixed slimes spawning from slime division not inheriting tags. (thanks Ineusia)
     Fixed slimes spawning from slime division not inheriting tags. (thanks Ineusia)
 
 
-
 Version 2.2.021
 Version 2.2.021
     Fixed issue where Roll wasn't reducing as much damage as it should have been (thanks Ineusia)
     Fixed issue where Roll wasn't reducing as much damage as it should have been (thanks Ineusia)
     Updated locale_es (thanks Devilcasters)
     Updated locale_es (thanks Devilcasters)

+ 34 - 30
pom.xml

@@ -13,6 +13,8 @@
     </scm>
     </scm>
 
 
     <properties>
     <properties>
+        <spigot.version>1.21.3-R0.1-SNAPSHOT</spigot.version>
+        <adventure.version>4.3.5-SNAPSHOT</adventure.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <maven.compiler.source>17</maven.compiler.source>
         <maven.compiler.source>17</maven.compiler.source>
         <maven.compiler.target>17</maven.compiler.target>
         <maven.compiler.target>17</maven.compiler.target>
@@ -300,7 +302,7 @@
         <dependency>
         <dependency>
             <groupId>net.kyori</groupId>
             <groupId>net.kyori</groupId>
             <artifactId>adventure-text-serializer-bungeecord</artifactId>
             <artifactId>adventure-text-serializer-bungeecord</artifactId>
-            <version>4.3.2</version>
+            <version>${adventure.version}</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>net.kyori</groupId>
             <groupId>net.kyori</groupId>
@@ -340,22 +342,22 @@
         <dependency>
         <dependency>
             <groupId>net.kyori</groupId>
             <groupId>net.kyori</groupId>
             <artifactId>adventure-platform-api</artifactId>
             <artifactId>adventure-platform-api</artifactId>
-            <version>4.3.3</version>
+            <version>${adventure.version}</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>net.kyori</groupId>
             <groupId>net.kyori</groupId>
             <artifactId>adventure-platform-bukkit</artifactId>
             <artifactId>adventure-platform-bukkit</artifactId>
-            <version>LATEST</version>
+            <version>${adventure.version}</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>net.kyori</groupId>
             <groupId>net.kyori</groupId>
             <artifactId>adventure-platform-facet</artifactId>
             <artifactId>adventure-platform-facet</artifactId>
-            <version>4.3.3</version>
+            <version>${adventure.version}</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>net.kyori</groupId>
             <groupId>net.kyori</groupId>
             <artifactId>adventure-platform-viaversion</artifactId>
             <artifactId>adventure-platform-viaversion</artifactId>
-            <version>4.3.3</version>
+            <version>${adventure.version}</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>net.kyori</groupId>
             <groupId>net.kyori</groupId>
@@ -376,7 +378,7 @@
         <dependency>
         <dependency>
             <groupId>org.spigotmc</groupId>
             <groupId>org.spigotmc</groupId>
             <artifactId>spigot-api</artifactId>
             <artifactId>spigot-api</artifactId>
-            <version>1.21-R0.1-SNAPSHOT</version>
+            <version>${spigot.version}</version>
             <scope>provided</scope>
             <scope>provided</scope>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
@@ -427,6 +429,12 @@
             <version>5.2.0</version>
             <version>5.2.0</version>
             <scope>test</scope>
             <scope>test</scope>
         </dependency>
         </dependency>
+<!--        <dependency>-->
+<!--            <groupId>com.github.seeseemelk</groupId>-->
+<!--            <artifactId>MockBukkit-v1.21</artifactId>-->
+<!--            <version>[version]</version>-->
+<!--            <scope>test</scope>-->
+<!--        </dependency>-->
         <dependency>
         <dependency>
             <groupId>org.apache.tomcat</groupId>
             <groupId>org.apache.tomcat</groupId>
             <artifactId>tomcat-jdbc</artifactId>
             <artifactId>tomcat-jdbc</artifactId>
@@ -450,29 +458,25 @@
             <version>0.3.1</version>
             <version>0.3.1</version>
             <scope>compile</scope>
             <scope>compile</scope>
         </dependency>
         </dependency>
-<!--        <dependency>-->
-<!--            <groupId>org.apache.logging.log4j</groupId>-->
-<!--            <artifactId>log4j-core</artifactId>-->
-<!--            <version>2.22.1</version> &lt;!&ndash; Make sure this version matches the other log4j dependencies &ndash;&gt;-->
-<!--            <scope>test</scope>-->
-<!--        </dependency>-->
-<!--        <dependency>-->
-<!--            <groupId>org.apache.logging.log4j</groupId>-->
-<!--            <artifactId>log4j-api</artifactId>-->
-<!--            <version>2.22.1</version>-->
-<!--            <scope>test</scope>-->
-<!--        </dependency>-->
-<!--        <dependency>-->
-<!--            <groupId>org.apache.logging.log4j</groupId>-->
-<!--            <artifactId>log4j-slf4j-impl</artifactId>-->
-<!--            <version>2.22.1</version>-->
-<!--            <scope>test</scope>-->
-<!--        </dependency>-->
-<!--        <dependency>-->
-<!--            <groupId>com.github.seeseemelk</groupId>-->
-<!--            <artifactId>MockBukkit-v1.19</artifactId>-->
-<!--            <version>LATEST</version>-->
-<!--            <scope>test</scope>-->
-<!--        </dependency>-->
     </dependencies>
     </dependencies>
+<!--    <profiles>-->
+<!--        <profile>-->
+<!--            <id>spigot-1.18.2</id>-->
+<!--            <properties>-->
+<!--                <spigot.version>1.18.2-R0.1-SNAPSHOT</spigot.version>-->
+<!--            </properties>-->
+<!--        </profile>-->
+<!--        <profile>-->
+<!--            <id>spigot-1.21.1</id>-->
+<!--            <properties>-->
+<!--                <spigot.version>1.21.1-R0.1-SNAPSHOT</spigot.version>-->
+<!--            </properties>-->
+<!--        </profile>-->
+<!--        <profile>-->
+<!--            <id>spigot-1.21.3</id>-->
+<!--            <properties>-->
+<!--                <spigot.version>1.21.3-R0.1-SNAPSHOT</spigot.version>-->
+<!--            </properties>-->
+<!--        </profile>-->
+<!--    </profiles>-->
 </project>
 </project>

+ 1 - 0
src/main/java/com/gmail/nossr50/chat/ChatManager.java

@@ -14,6 +14,7 @@ import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.text.StringUtils;
 import com.gmail.nossr50.util.text.StringUtils;
 import net.kyori.adventure.audience.Audience;
 import net.kyori.adventure.audience.Audience;
+import net.kyori.adventure.chat.SignedMessage;
 import net.kyori.adventure.text.TextComponent;
 import net.kyori.adventure.text.TextComponent;
 import org.bukkit.command.ConsoleCommandSender;
 import org.bukkit.command.ConsoleCommandSender;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.NotNull;

+ 3 - 2
src/main/java/com/gmail/nossr50/listeners/EntityListener.java

@@ -49,6 +49,7 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.List;
 import java.util.Set;
 import java.util.Set;
 
 
+import static com.gmail.nossr50.util.AttributeMapper.MAPPED_MAX_HEALTH;
 import static com.gmail.nossr50.util.MobMetadataUtils.*;
 import static com.gmail.nossr50.util.MobMetadataUtils.*;
 
 
 public class EntityListener implements Listener {
 public class EntityListener implements Listener {
@@ -411,7 +412,7 @@ public class EntityListener implements Listener {
                     player.sendMessage(ChatColor.GOLD + "(mmodebug start of combat report) EntityDamageByEntityEvent DEBUG Info:");
                     player.sendMessage(ChatColor.GOLD + "(mmodebug start of combat report) EntityDamageByEntityEvent DEBUG Info:");
                     player.sendMessage("You are being damaged by another player in this event");
                     player.sendMessage("You are being damaged by another player in this event");
                     player.sendMessage("Raw Damage: " + entityDamageEvent.getDamage());
                     player.sendMessage("Raw Damage: " + entityDamageEvent.getDamage());
-                    player.sendMessage("Your max health: "+player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
+                    player.sendMessage("Your max health: "+player.getAttribute(MAPPED_MAX_HEALTH).getValue());
                     player.sendMessage("Your current health: "+player.getHealth());
                     player.sendMessage("Your current health: "+player.getHealth());
 
 
                     player.sendMessage(ChatColor.GREEN + "Damage Modifiers (final damage)");
                     player.sendMessage(ChatColor.GREEN + "Damage Modifiers (final damage)");
@@ -444,7 +445,7 @@ public class EntityListener implements Listener {
                     }
                     }
 
 
                     player.sendMessage("Final damage: " + entityDamageEvent.getFinalDamage());
                     player.sendMessage("Final damage: " + entityDamageEvent.getFinalDamage());
-                    player.sendMessage("Target players max health: "+otherPlayer.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue());
+                    player.sendMessage("Target players max health: "+otherPlayer.getAttribute(MAPPED_MAX_HEALTH).getValue());
                     player.sendMessage("Target players current health: "+otherPlayer.getHealth());
                     player.sendMessage("Target players current health: "+otherPlayer.getHealth());
 
 
                     if (entityDamageEvent.isCancelled()) {
                     if (entityDamageEvent.isCancelled()) {

+ 0 - 7
src/main/java/com/gmail/nossr50/mcMMO.java

@@ -138,7 +138,6 @@ public class mcMMO extends JavaPlugin {
     private PotionConfig potionConfig;
     private PotionConfig potionConfig;
     private CustomItemSupportConfig customItemSupportConfig;
     private CustomItemSupportConfig customItemSupportConfig;
     private EnchantmentMapper enchantmentMapper;
     private EnchantmentMapper enchantmentMapper;
-    private AttributeMapper attributeMapper;
 
 
     private FoliaLib foliaLib;
     private FoliaLib foliaLib;
     private PartyManager partyManager;
     private PartyManager partyManager;
@@ -195,8 +194,6 @@ public class mcMMO extends JavaPlugin {
             materialMapStore = new MaterialMapStore();
             materialMapStore = new MaterialMapStore();
             // Init compatibility mappers
             // Init compatibility mappers
             enchantmentMapper = new EnchantmentMapper(this);
             enchantmentMapper = new EnchantmentMapper(this);
-            attributeMapper = new AttributeMapper(this);
-
             loadConfigFiles();
             loadConfigFiles();
 
 
             if (!noErrorsInConfigFiles) {
             if (!noErrorsInConfigFiles) {
@@ -818,10 +815,6 @@ public class mcMMO extends JavaPlugin {
         return enchantmentMapper;
         return enchantmentMapper;
     }
     }
 
 
-    public AttributeMapper getAttributeMapper() {
-        return attributeMapper;
-    }
-
     public @NotNull FoliaLib getFoliaLib() {
     public @NotNull FoliaLib getFoliaLib() {
         return foliaLib;
         return foliaLib;
     }
     }

+ 37 - 25
src/main/java/com/gmail/nossr50/runnables/skills/RuptureTask.java

@@ -13,7 +13,7 @@ import org.bukkit.entity.LivingEntity;
 import org.bukkit.entity.Player;
 import org.bukkit.entity.Player;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.NotNull;
 
 
-import static org.bukkit.attribute.Attribute.GENERIC_MAX_HEALTH;
+import static com.gmail.nossr50.util.AttributeMapper.MAPPED_MAX_HEALTH;
 
 
 public class RuptureTask extends CancellableRunnable {
 public class RuptureTask extends CancellableRunnable {
 
 
@@ -28,9 +28,16 @@ public class RuptureTask extends CancellableRunnable {
     private int damageTickTracker;
     private int damageTickTracker;
     private int animationTick;
     private int animationTick;
     private final double pureTickDamage;
     private final double pureTickDamage;
-    private final double explosionDamage;
 
 
-    public RuptureTask(@NotNull McMMOPlayer ruptureSource, @NotNull LivingEntity targetEntity, double pureTickDamage, double explosionDamage) {
+    /**
+     * Constructor for the RuptureTask class.
+     *
+     * @param ruptureSource The McMMOPlayer who is the source of the rupture.
+     * @param targetEntity The LivingEntity that is the target of the rupture.
+     * @param pureTickDamage The amount of damage to be applied per tick.
+     */
+    public RuptureTask(@NotNull McMMOPlayer ruptureSource, @NotNull LivingEntity targetEntity,
+                       double pureTickDamage) {
         this.ruptureSource = ruptureSource;
         this.ruptureSource = ruptureSource;
         this.targetEntity = targetEntity;
         this.targetEntity = targetEntity;
         this.expireTick = mcMMO.p.getAdvancedConfig().getRuptureDurationSeconds(targetEntity instanceof Player) * 20;
         this.expireTick = mcMMO.p.getAdvancedConfig().getRuptureDurationSeconds(targetEntity instanceof Player) * 20;
@@ -39,7 +46,24 @@ public class RuptureTask extends CancellableRunnable {
         this.damageTickTracker = 0;
         this.damageTickTracker = 0;
         this.animationTick = ANIMATION_TICK_INTERVAL; //Play an animation right away
         this.animationTick = ANIMATION_TICK_INTERVAL; //Play an animation right away
         this.pureTickDamage = pureTickDamage;
         this.pureTickDamage = pureTickDamage;
-        this.explosionDamage = explosionDamage;
+    }
+
+    /**
+     * Deprecated constructor for the RuptureTask class.
+     *
+     * @deprecated This constructor is deprecated and will be removed in future versions.
+     * Use {@link #RuptureTask(McMMOPlayer, LivingEntity, double)} instead.
+     *
+     * @param ruptureSource The McMMOPlayer who is the source of the rupture.
+     * @param targetEntity The LivingEntity that is the target of the rupture.
+     * @param pureTickDamage The amount of damage to be applied per tick.
+     * @param ignored This parameter is ignored and should not be used.
+     * @since 2.2.023
+     */
+    @Deprecated(forRemoval = true, since = "2.2.023")
+    public RuptureTask(@NotNull McMMOPlayer ruptureSource, @NotNull LivingEntity targetEntity,
+                       double pureTickDamage, double ignored) {
+        this(ruptureSource, targetEntity, pureTickDamage);
     }
     }
 
 
     @Override
     @Override
@@ -100,11 +124,11 @@ public class RuptureTask extends CancellableRunnable {
 
 
             final double damagedHealth = healthBeforeRuptureIsApplied - damage;
             final double damagedHealth = healthBeforeRuptureIsApplied - damage;
 
 
-            final AttributeInstance maxHealthAttribute = targetEntity.getAttribute(GENERIC_MAX_HEALTH);
+            final AttributeInstance maxHealthAttribute = targetEntity.getAttribute(MAPPED_MAX_HEALTH);
             if (maxHealthAttribute == null) {
             if (maxHealthAttribute == null) {
                 // Can't remove health if max health is null
                 // Can't remove health if max health is null
                 mcMMO.p.getLogger().info("RuptureTask: Target entity has an illegal state for its health." +
                 mcMMO.p.getLogger().info("RuptureTask: Target entity has an illegal state for its health." +
-                        " Cancelling Rupture. Target has null " + GENERIC_MAX_HEALTH + " attribute.");
+                        " Cancelling Rupture. Target has null " + MAPPED_MAX_HEALTH + " attribute.");
                 return true;
                 return true;
             }
             }
 
 
@@ -129,18 +153,6 @@ public class RuptureTask extends CancellableRunnable {
     }
     }
 
 
     public void endRupture() {
     public void endRupture() {
-//        targetEntity.setMetadata(mcMMO.EXPLOSION_FROM_RUPTURE, new FixedMetadataValue(mcMMO.p, "null"));
-//
-//        ParticleEffectUtils.playGreaterImpactEffect(targetEntity); //Animate
-//
-//        if (ruptureSource.getPlayer() != null && ruptureSource.getPlayer().isValid()) {
-//            targetEntity.damage(getExplosionDamage(), ruptureSource.getPlayer());
-//        } else {
-//            targetEntity.damage(getExplosionDamage(), null);
-//        }
-//
-//        targetEntity.removeMetadata(mcMMO.RUPTURE_META_KEY, mcMMO.p);
-
         targetEntity.removeMetadata(MetadataConstants.METADATA_KEY_RUPTURE, mcMMO.p);
         targetEntity.removeMetadata(MetadataConstants.METADATA_KEY_RUPTURE, mcMMO.p);
         this.cancel(); //Task no longer needed
         this.cancel(); //Task no longer needed
     }
     }
@@ -159,10 +171,6 @@ public class RuptureTask extends CancellableRunnable {
         return tickDamage;
         return tickDamage;
     }
     }
 
 
-    private double getExplosionDamage() {
-        return explosionDamage;
-    }
-
     @Override
     @Override
     public String toString() {
     public String toString() {
         return "RuptureTask{" +
         return "RuptureTask{" +
@@ -172,7 +180,6 @@ public class RuptureTask extends CancellableRunnable {
                 ", ruptureTick=" + ruptureTick +
                 ", ruptureTick=" + ruptureTick +
                 ", damageTickTracker=" + damageTickTracker +
                 ", damageTickTracker=" + damageTickTracker +
                 ", pureTickDamage=" + pureTickDamage +
                 ", pureTickDamage=" + pureTickDamage +
-                ", explosionDamage=" + explosionDamage +
                 '}';
                 '}';
     }
     }
 
 
@@ -181,11 +188,16 @@ public class RuptureTask extends CancellableRunnable {
         if (this == o) return true;
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
         if (o == null || getClass() != o.getClass()) return false;
         RuptureTask that = (RuptureTask) o;
         RuptureTask that = (RuptureTask) o;
-        return expireTick == that.expireTick && ruptureTick == that.ruptureTick && damageTickTracker == that.damageTickTracker && Double.compare(that.pureTickDamage, pureTickDamage) == 0 && Double.compare(that.explosionDamage, explosionDamage) == 0 && Objects.equal(ruptureSource, that.ruptureSource) && Objects.equal(targetEntity, that.targetEntity);
+        return expireTick == that.expireTick
+                && ruptureTick == that.ruptureTick
+                && damageTickTracker == that.damageTickTracker
+                && Double.compare(that.pureTickDamage, pureTickDamage) == 0
+                && Objects.equal(ruptureSource, that.ruptureSource) && Objects.equal(targetEntity, that.targetEntity);
     }
     }
 
 
     @Override
     @Override
     public int hashCode() {
     public int hashCode() {
-        return Objects.hashCode(ruptureSource, targetEntity, expireTick, ruptureTick, damageTickTracker, pureTickDamage, explosionDamage);
+        return Objects.hashCode(ruptureSource, targetEntity, expireTick,
+                ruptureTick, damageTickTracker, pureTickDamage);
     }
     }
 }
 }

+ 1 - 2
src/main/java/com/gmail/nossr50/skills/swords/SwordsManager.java

@@ -91,8 +91,7 @@ public class SwordsManager extends SkillManager {
             }
             }
 
 
             RuptureTask ruptureTask = new RuptureTask(mmoPlayer, target,
             RuptureTask ruptureTask = new RuptureTask(mmoPlayer, target,
-                    mcMMO.p.getAdvancedConfig().getRuptureTickDamage(target instanceof Player, getRuptureRank()),
-                    mcMMO.p.getAdvancedConfig().getRuptureExplosionDamage(target instanceof Player, getRuptureRank()));
+                    mcMMO.p.getAdvancedConfig().getRuptureTickDamage(target instanceof Player, getRuptureRank()));
 
 
             RuptureTaskMeta ruptureTaskMeta = new RuptureTaskMeta(mcMMO.p, ruptureTask);
             RuptureTaskMeta ruptureTaskMeta = new RuptureTaskMeta(mcMMO.p, ruptureTask);
 
 

+ 4 - 2
src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java

@@ -31,6 +31,8 @@ import org.jetbrains.annotations.NotNull;
 
 
 import java.util.HashMap;
 import java.util.HashMap;
 
 
+import static com.gmail.nossr50.util.AttributeMapper.MAPPED_JUMP_STRENGTH;
+import static com.gmail.nossr50.util.AttributeMapper.MAPPED_MOVEMENT_SPEED;
 import static com.gmail.nossr50.util.MobMetadataUtils.flagMetadata;
 import static com.gmail.nossr50.util.MobMetadataUtils.flagMetadata;
 
 
 public class TamingManager extends SkillManager {
 public class TamingManager extends SkillManager {
@@ -235,13 +237,13 @@ public class TamingManager extends SkillManager {
 
 
         // Bred mules & donkeys can actually have horse-like stats, but llamas cannot.
         // Bred mules & donkeys can actually have horse-like stats, but llamas cannot.
         if (beast instanceof AbstractHorse horseLikeCreature && !(beast instanceof Llama)) {
         if (beast instanceof AbstractHorse horseLikeCreature && !(beast instanceof Llama)) {
-            AttributeInstance jumpAttribute = horseLikeCreature.getAttribute(mcMMO.p.getAttributeMapper().getHorseJumpStrength());
+            AttributeInstance jumpAttribute = horseLikeCreature.getAttribute(MAPPED_JUMP_STRENGTH);
 
 
             if (jumpAttribute != null) {
             if (jumpAttribute != null) {
                 double jumpStrength = jumpAttribute.getValue();
                 double jumpStrength = jumpAttribute.getValue();
                 // Taken from https://minecraft.wiki/w/Horse#Jump_strength
                 // Taken from https://minecraft.wiki/w/Horse#Jump_strength
                 jumpStrength = -0.1817584952 * Math.pow(jumpStrength, 3) + 3.689713992 * Math.pow(jumpStrength, 2) + 2.128599134 * jumpStrength - 0.343930367;
                 jumpStrength = -0.1817584952 * Math.pow(jumpStrength, 3) + 3.689713992 * Math.pow(jumpStrength, 2) + 2.128599134 * jumpStrength - 0.343930367;
-                message = message.concat("\n" + LocaleLoader.getString("Combat.BeastLoreHorseSpeed", horseLikeCreature.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).getValue() * 43))
+                message = message.concat("\n" + LocaleLoader.getString("Combat.BeastLoreHorseSpeed", horseLikeCreature.getAttribute(MAPPED_MOVEMENT_SPEED).getValue() * 43))
                         .concat("\n" + LocaleLoader.getString("Combat.BeastLoreHorseJumpStrength", jumpStrength));
                         .concat("\n" + LocaleLoader.getString("Combat.BeastLoreHorseJumpStrength", jumpStrength));
             }
             }
         }
         }

+ 183 - 31
src/main/java/com/gmail/nossr50/util/AttributeMapper.java

@@ -4,42 +4,194 @@ import com.gmail.nossr50.mcMMO;
 import org.bukkit.Registry;
 import org.bukkit.Registry;
 import org.bukkit.attribute.Attribute;
 import org.bukkit.attribute.Attribute;
 
 
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.stream.Stream;
+
 public class AttributeMapper {
 public class AttributeMapper {
-    private final mcMMO pluginRef;
-    private static final String GENERIC_JUMP_STRENGTH = "generic.jump_strength";
-    private static final String HORSE_JUMP_STRENGTH = "horse.jump_strength";
-    private final Attribute horseJumpStrength;
-
-    public AttributeMapper(mcMMO pluginRef) {
-        this.pluginRef = pluginRef;
-        this.horseJumpStrength = initHorseJumpStrength();
+
+    public static final String ATTRIBUTE = "ATTRIBUTE";
+    public static final String ORG_BUKKIT_REGISTRY = "org.bukkit.Registry";
+
+    // Prevent instantiation
+    private AttributeMapper() {
     }
     }
 
 
-    private Attribute initHorseJumpStrength() {
-        // TODO: Use modern matching?
-//        if (Registry.ATTRIBUTE.match(GENERIC_JUMP_STRENGTH) != null) {
-//            return Registry.ATTRIBUTE.match(GENERIC_JUMP_STRENGTH);
-//        }
-//
-//        if (Registry.ATTRIBUTE.match(HORSE_JUMP_STRENGTH) != null) {
-//            return Registry.ATTRIBUTE.match(HORSE_JUMP_STRENGTH);
-//        }
-
-        for (Attribute attr : Registry.ATTRIBUTE) {
-            if (attr.getKey().getKey().equalsIgnoreCase(HORSE_JUMP_STRENGTH)
-                    || attr.getKey().getKey().equalsIgnoreCase(GENERIC_JUMP_STRENGTH)
-                    || attr.name().equalsIgnoreCase(HORSE_JUMP_STRENGTH)
-                    || attr.name().equalsIgnoreCase(GENERIC_JUMP_STRENGTH)) {
-                return attr;
-            }
-        }
+    // Define constants for attribute keys and their legacy counterparts
+    private static final String MAX_HEALTH_1_21_3_STR = "max_health";
+    private static final String MAX_HEALTH_1_18_2_STR = "generic.max_health";
+    public static final Attribute MAPPED_MAX_HEALTH;
+
+    private static final String JUMP_STRENGTH_1_23_1 = "jump_strength";
+    private static final String JUMP_STRENGTH_1_21_1 = "generic.jump_strength";
+    private static final String JUMP_STR_1_18_2 = "horse.jump_strength";
+    public static final Attribute MAPPED_JUMP_STRENGTH;
 
 
-        pluginRef.getLogger().severe("Unable to find the Generic Jump Strength or Horse Jump Strength attribute, " +
-                "mcMMO will not function properly.");
-        throw new IllegalStateException("Unable to find the Generic Jump Strength or Horse Jump Strength attribute");
+    public static final Attribute MAPPED_MOVEMENT_SPEED;
+    private static final String MOVEMENT_SPEED_1_18_2 = "generic.movement_speed";
+    private static final String MOVEMENT_SPEED_1_21_1 = "generic.movement_speed";
+    private static final String MOVEMENT_SPEED_1_21_3 = "movement_speed";
+
+    // Add other attributes similarly...
+    // For brevity, only key attributes are shown
+
+    static {
+        MAPPED_MAX_HEALTH = findAttribute(MAX_HEALTH_1_21_3_STR, MAX_HEALTH_1_18_2_STR);
+        MAPPED_JUMP_STRENGTH = findAttribute(JUMP_STRENGTH_1_23_1, JUMP_STRENGTH_1_21_1, JUMP_STR_1_18_2);
+        MAPPED_MOVEMENT_SPEED = findAttribute(MOVEMENT_SPEED_1_18_2, MOVEMENT_SPEED_1_21_1, MOVEMENT_SPEED_1_21_3);
     }
     }
 
 
-    public Attribute getHorseJumpStrength() {
-        return horseJumpStrength;
+    private static Attribute findAttribute(String... keys) {
+        Stream<?> attributeStream;
+        try {
+            // Try to get Registry.ATTRIBUTE using reflection
+            Class<?> registryClass = Class.forName(ORG_BUKKIT_REGISTRY);
+            Field attributeField = registryClass.getField(ATTRIBUTE);
+            Object attributeRegistry = attributeField.get(null);
+
+            // Get the stream() method of the attribute registry
+            Method streamMethod = attributeRegistry.getClass().getMethod("stream");
+            attributeStream = (Stream<?>) streamMethod.invoke(attributeRegistry);
+        } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException | NoSuchMethodException |
+                 InvocationTargetException e) {
+            // Fallback to older versions where Attribute is an enum
+            Object[] enumConstants = Attribute.class.getEnumConstants();
+            attributeStream = Arrays.stream(enumConstants);
+        }
+
+        Optional<?> optionalAttribute = attributeStream
+                .filter(attr -> {
+                    try {
+                        String attrKey = null;
+                        String attrName = null;
+
+                        // Try to get attr.getKey().getKey()
+                        Method getKeyMethod = attr.getClass().getMethod("getKey");
+                        Object namespacedKey = getKeyMethod.invoke(attr);
+
+                        if (namespacedKey != null) {
+                            Method getKeyStringMethod = namespacedKey.getClass().getMethod("getKey");
+                            attrKey = (String) getKeyStringMethod.invoke(namespacedKey);
+                        }
+
+                        // Try to get attr.name()
+                        Method nameMethod;
+                        try {
+                            nameMethod = attr.getClass().getMethod("name");
+                            attrName = (String) nameMethod.invoke(attr);
+                        } catch (NoSuchMethodException e) {
+                            // name() method doesn't exist in newer versions
+                            attrName = null;
+                        }
+
+                        // Compare with provided keys
+                        for (String key : keys) {
+                            if ((attrKey != null && attrKey.equalsIgnoreCase(key)) ||
+                                    (attrName != null && attrName.equalsIgnoreCase(key))) {
+                                return true;
+                            }
+                        }
+                    } catch (Exception e) {
+                        mcMMO.p.getLogger().severe("Unable to find the attribute with possible keys: "
+                                + Arrays.toString(keys) + ", mcMMO will not function properly.");
+                        throw new RuntimeException(e);
+                    }
+                    return false;
+                })
+                .findFirst();
+
+        if (optionalAttribute.isPresent()) {
+            return (Attribute) optionalAttribute.get();
+        } else {
+            mcMMO.p.getLogger().severe("Unable to find the attribute with possible keys: "
+                    + Arrays.toString(keys) + ", mcMMO will not function properly.");
+            throw new IllegalStateException("Unable to find the attribute with possible keys: "
+                    + Arrays.toString(keys));
+        }
     }
     }
+
+    /*
+    For easy reference...
+    List of 1.18 Attributes by name...
+        GENERIC_MAX_HEALTH("generic.max_health"),
+        GENERIC_FOLLOW_RANGE("generic.follow_range"),
+        GENERIC_KNOCKBACK_RESISTANCE("generic.knockback_resistance"),
+        GENERIC_MOVEMENT_SPEED("generic.movement_speed"),
+        GENERIC_FLYING_SPEED("generic.flying_speed"),
+        GENERIC_ATTACK_DAMAGE("generic.attack_damage"),
+        GENERIC_ATTACK_KNOCKBACK("generic.attack_knockback"),
+        GENERIC_ATTACK_SPEED("generic.attack_speed"),
+        GENERIC_ARMOR("generic.armor"),
+        GENERIC_ARMOR_TOUGHNESS("generic.armor_toughness"),
+        GENERIC_LUCK("generic.luck"),
+        HORSE_JUMP_STRENGTH("horse.jump_strength"),
+        ZOMBIE_SPAWN_REINFORCEMENTS("zombie.spawn_reinforcements");
+    List of 1.21.1 Attributes by name...
+        GENERIC_MAX_HEALTH("generic.max_health"),
+        GENERIC_FOLLOW_RANGE("generic.follow_range"),
+        GENERIC_KNOCKBACK_RESISTANCE("generic.knockback_resistance"),
+        GENERIC_MOVEMENT_SPEED("generic.movement_speed"),
+        GENERIC_FLYING_SPEED("generic.flying_speed"),
+        GENERIC_ATTACK_DAMAGE("generic.attack_damage"),
+        GENERIC_ATTACK_KNOCKBACK("generic.attack_knockback"),
+        GENERIC_ATTACK_SPEED("generic.attack_speed"),
+        GENERIC_ARMOR("generic.armor"),
+        GENERIC_ARMOR_TOUGHNESS("generic.armor_toughness"),
+        GENERIC_FALL_DAMAGE_MULTIPLIER("generic.fall_damage_multiplier"),
+        GENERIC_LUCK("generic.luck"),
+        GENERIC_MAX_ABSORPTION("generic.max_absorption"),
+        GENERIC_SAFE_FALL_DISTANCE("generic.safe_fall_distance"),
+        GENERIC_SCALE("generic.scale"),
+        GENERIC_STEP_HEIGHT("generic.step_height"),
+        GENERIC_GRAVITY("generic.gravity"),
+        GENERIC_JUMP_STRENGTH("generic.jump_strength"),
+        GENERIC_EXPLOSION_KNOCKBACK_RESISTANCE("generic.explosion_knockback_resistance"),
+        GENERIC_MOVEMENT_EFFICIENCY("generic.movement_efficiency"),
+        GENERIC_OXYGEN_BONUS("generic.oxygen_bonus"),
+        GENERIC_WATER_MOVEMENT_EFFICIENCY("generic.water_movement_efficiency"),
+        PLAYER_BLOCK_INTERACTION_RANGE("player.block_interaction_range"),
+        PLAYER_ENTITY_INTERACTION_RANGE("player.entity_interaction_range"),
+        PLAYER_BLOCK_BREAK_SPEED("player.block_break_speed"),
+        PLAYER_MINING_EFFICIENCY("player.mining_efficiency"),
+        PLAYER_SNEAKING_SPEED("player.sneaking_speed"),
+        PLAYER_SUBMERGED_MINING_SPEED("player.submerged_mining_speed"),
+        PLAYER_SWEEPING_DAMAGE_RATIO("player.sweeping_damage_ratio"),
+        ZOMBIE_SPAWN_REINFORCEMENTS("zombie.spawn_reinforcements");
+    List of 1.21.3 Attributes...
+        Attribute MAX_HEALTH = getAttribute("max_health");
+        Attribute FOLLOW_RANGE = getAttribute("follow_range");
+        Attribute KNOCKBACK_RESISTANCE = getAttribute("knockback_resistance");
+        Attribute MOVEMENT_SPEED = getAttribute("movement_speed");
+        Attribute FLYING_SPEED = getAttribute("flying_speed");
+        Attribute ATTACK_DAMAGE = getAttribute("attack_damage");
+        Attribute ATTACK_KNOCKBACK = getAttribute("attack_knockback");
+        Attribute ATTACK_SPEED = getAttribute("attack_speed");
+        Attribute ARMOR = getAttribute("armor");
+        Attribute ARMOR_TOUGHNESS = getAttribute("armor_toughness");
+        Attribute FALL_DAMAGE_MULTIPLIER = getAttribute("fall_damage_multiplier");
+        Attribute LUCK = getAttribute("luck");
+        Attribute MAX_ABSORPTION = getAttribute("max_absorption");
+        Attribute SAFE_FALL_DISTANCE = getAttribute("safe_fall_distance");
+        Attribute SCALE = getAttribute("scale");
+        Attribute STEP_HEIGHT = getAttribute("step_height");
+        Attribute GRAVITY = getAttribute("gravity");
+        Attribute JUMP_STRENGTH = getAttribute("jump_strength");
+        Attribute BURNING_TIME = getAttribute("burning_time");
+        Attribute EXPLOSION_KNOCKBACK_RESISTANCE = getAttribute("explosion_knockback_resistance");
+        Attribute MOVEMENT_EFFICIENCY = getAttribute("movement_efficiency");
+        Attribute OXYGEN_BONUS = getAttribute("oxygen_bonus");
+        Attribute WATER_MOVEMENT_EFFICIENCY = getAttribute("water_movement_efficiency");
+        Attribute TEMPT_RANGE = getAttribute("tempt_range");
+        Attribute BLOCK_INTERACTION_RANGE = getAttribute("block_interaction_range");
+        Attribute ENTITY_INTERACTION_RANGE = getAttribute("entity_interaction_range");
+        Attribute BLOCK_BREAK_SPEED = getAttribute("block_break_speed");
+        Attribute MINING_EFFICIENCY = getAttribute("mining_efficiency");
+        Attribute SNEAKING_SPEED = getAttribute("sneaking_speed");
+        Attribute SUBMERGED_MINING_SPEED = getAttribute("submerged_mining_speed");
+        Attribute SWEEPING_DAMAGE_RATIO = getAttribute("sweeping_damage_ratio");
+        Attribute SPAWN_REINFORCEMENTS = getAttribute("spawn_reinforcements");
+    */
 }
 }

+ 22 - 9
src/main/java/com/gmail/nossr50/util/adapter/BiomeAdapter.java

@@ -7,26 +7,39 @@ import java.util.*;
 public class BiomeAdapter {
 public class BiomeAdapter {
     public static final Set<Biome> WATER_BIOMES;
     public static final Set<Biome> WATER_BIOMES;
     public static final Set<Biome> ICE_BIOMES;
     public static final Set<Biome> ICE_BIOMES;
-    
+
     static {
     static {
-        List<Biome> allBiomes = Arrays.asList(Biome.values());
-        List<Biome> waterBiomes = new ArrayList<>();
-        List<Biome> iceBiomes = new ArrayList<>();
+        final List<Biome> allBiomes = getAllBiomes();
+        final Set<Biome> waterBiomes = new HashSet<>();
+        final Set<Biome> iceBiomes = new HashSet<>();
         for (Biome biome : allBiomes) {
         for (Biome biome : allBiomes) {
-            if (isWater(biome.name()) && !isCold(biome.name())) {
+            String biomeName = getBiomeName(biome);
+            if (isWater(biomeName) && !isCold(biomeName)) {
                 waterBiomes.add(biome);
                 waterBiomes.add(biome);
-            } else if (isCold(biome.name())) {
+            } else if (isCold(biomeName)) {
                 iceBiomes.add(biome);
                 iceBiomes.add(biome);
             }
             }
         }
         }
-        WATER_BIOMES = EnumSet.copyOf(waterBiomes);
-        ICE_BIOMES = EnumSet.copyOf(iceBiomes);
+        WATER_BIOMES = Collections.unmodifiableSet(waterBiomes);
+        ICE_BIOMES = Collections.unmodifiableSet(iceBiomes);
+    }
+
+    @SuppressWarnings("deprecation")
+    private static List<Biome> getAllBiomes() {
+        return Arrays.asList(Biome.values());
+    }
+
+    @SuppressWarnings("deprecation")
+    private static String getBiomeName(Biome biome) {
+        return biome.name();
     }
     }
 
 
     private static boolean isWater(String name) {
     private static boolean isWater(String name) {
         return name.contains("RIVER") || name.contains("OCEAN");
         return name.contains("RIVER") || name.contains("OCEAN");
     }
     }
+
     private static boolean isCold(String name) {
     private static boolean isCold(String name) {
-        return (name.contains("COLD") || name.contains("ICE") || name.contains("FROZEN") || name.contains("TAIGA")) && !(name.contains("WARM"));
+        return (name.contains("COLD") || name.contains("ICE")
+                || name.contains("FROZEN") || name.contains("TAIGA")) && !name.contains("WARM");
     }
     }
 }
 }

+ 2 - 1
src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java

@@ -39,6 +39,7 @@ import org.jetbrains.annotations.Nullable;
 import java.util.List;
 import java.util.List;
 
 
 import static com.gmail.nossr50.datatypes.experience.XPGainReason.PVP;
 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.MobMetadataUtils.hasMobFlag;
 
 
 public final class CombatUtils {
 public final class CombatUtils {
@@ -1071,7 +1072,7 @@ public final class CombatUtils {
     }
     }
 
 
     public static void modifyMoveSpeed(@NotNull LivingEntity livingEntity, double multiplier) {
     public static void modifyMoveSpeed(@NotNull LivingEntity livingEntity, double multiplier) {
-        AttributeInstance attributeInstance = livingEntity.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED);
+        AttributeInstance attributeInstance = livingEntity.getAttribute(MAPPED_MOVEMENT_SPEED);
 
 
         if (attributeInstance != null) {
         if (attributeInstance != null) {
             double normalSpeed = attributeInstance.getBaseValue();
             double normalSpeed = attributeInstance.getBaseValue();