diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java index a0d0dfcc42dc..c4326de93f8f 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java @@ -22,6 +22,7 @@ import org.bukkit.block.Biome; import org.bukkit.block.BlockType; import org.bukkit.block.banner.PatternType; +import org.bukkit.craftbukkit.attribute.CraftAttribute; import org.bukkit.craftbukkit.block.CraftBlockType; import org.bukkit.craftbukkit.block.banner.CraftPatternType; import org.bukkit.craftbukkit.damage.CraftDamageType; @@ -131,6 +132,9 @@ public static Holder bukkitToMinecraftHolder(B bukkit, R * @return the bukkit registry of the provided class */ public static Registry createRegistry(Class bukkitClass, IRegistryCustom registryHolder) { + if (bukkitClass == Attribute.class) { + return new CraftRegistry<>(Attribute.class, registryHolder.lookupOrThrow(Registries.ATTRIBUTE), CraftAttribute::new, FieldRename.ATTRIBUTE_RENAME); + } if (bukkitClass == Enchantment.class) { return new CraftRegistry<>(Enchantment.class, registryHolder.lookupOrThrow(Registries.ENCHANTMENT), CraftEnchantment::new, FieldRename.ENCHANTMENT_RENAME); } @@ -214,10 +218,6 @@ public static B get(Registry bukkit, NamespacedKey namespac if (bClass == Particle.class) { return bukkit.get(FieldRename.PARTICLE_TYPE_RENAME.apply(namespacedKey, apiVersion)); } - - if (bClass == Attribute.class) { - return bukkit.get(FieldRename.ATTRIBUTE_RENAME.apply(namespacedKey, apiVersion)); - } } return bukkit.get(namespacedKey); diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java index fb4de996fb95..98993663204e 100644 --- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java +++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java @@ -12,19 +12,15 @@ import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.legacy.FieldRename; import org.bukkit.craftbukkit.util.ApiVersion; -import org.bukkit.craftbukkit.util.CraftNamespacedKey; +import org.bukkit.craftbukkit.util.Handleable; +import org.jetbrains.annotations.NotNull; -public class CraftAttribute { +public class CraftAttribute implements Attribute, Handleable { - public static Attribute minecraftToBukkit(AttributeBase minecraft) { - Preconditions.checkArgument(minecraft != null); - - IRegistry registry = CraftRegistry.getMinecraftRegistry(Registries.ATTRIBUTE); - Attribute bukkit = Registry.ATTRIBUTE.get(CraftNamespacedKey.fromMinecraft(registry.getResourceKey(minecraft).orElseThrow().location())); - - Preconditions.checkArgument(bukkit != null); + private static int count = 0; - return bukkit; + public static Attribute minecraftToBukkit(AttributeBase minecraft) { + return CraftRegistry.minecraftToBukkit(minecraft, Registries.ATTRIBUTE, Registry.ATTRIBUTE); } public static Attribute minecraftHolderToBukkit(Holder minecraft) { @@ -45,10 +41,7 @@ public static Attribute stringToBukkit(String string) { } public static AttributeBase bukkitToMinecraft(Attribute bukkit) { - Preconditions.checkArgument(bukkit != null); - - return CraftRegistry.getMinecraftRegistry(Registries.ATTRIBUTE) - .getOptional(CraftNamespacedKey.toMinecraft(bukkit.getKey())).orElseThrow(); + return CraftRegistry.bukkitToMinecraft(bukkit); } public static Holder bukkitToMinecraftHolder(Attribute bukkit) { @@ -69,4 +62,81 @@ public static String bukkitToString(Attribute bukkit) { return bukkit.getKey().toString(); } + + private final NamespacedKey key; + private final AttributeBase attributeBase; + private final String name; + private final int ordinal; + + public CraftAttribute(NamespacedKey key, AttributeBase attributeBase) { + this.key = key; + this.attributeBase = attributeBase; + // For backwards compatibility, minecraft values will stile return the uppercase name without the namespace, + // in case plugins use for example the name as key in a config file to receive attribute specific values. + // Custom attributes will return the key with namespace. For a plugin this should look than like a new attribute + // (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly). + if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) { + this.name = key.getKey().toUpperCase(Locale.ROOT); + } else { + this.name = key.toString(); + } + this.ordinal = count++; + } + + @Override + public AttributeBase getHandle() { + return attributeBase; + } + + @NotNull + @Override + public NamespacedKey getKey() { + return key; + } + + @NotNull + @Override + public String getTranslationKey() { + return attributeBase.getDescriptionId(); + } + + @Override + public int compareTo(@NotNull Attribute attribute) { + return ordinal - attribute.ordinal(); + } + + @NotNull + @Override + public String name() { + return name; + } + + @Override + public int ordinal() { + return ordinal; + } + + @Override + public String toString() { + // For backwards compatibility + return name(); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (!(other instanceof CraftAttribute otherAttribute)) { + return false; + } + + return getKey().equals(otherAttribute.getKey()); + } + + @Override + public int hashCode() { + return getKey().hashCode(); + } } diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java b/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java index d33111f0edf9..3a0dc5a73ac5 100644 --- a/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java +++ b/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java @@ -354,7 +354,39 @@ public static LootTables valueOf_LootTables(String name) { private static final FieldRenameData ATTRIBUTE_DATA = FieldRenameData.Builder.newBuilder() .forAllVersions() .withKeyRename() - .change("HORSE.JUMP_STRENGTH", "GENERIC.JUMP_STRENGTH") + .change("HORSE.JUMP_STRENGTH", "JUMP_STRENGTH") + .change("GENERIC.MAX_HEALTH", "MAX_HEALTH") + .change("GENERIC.FOLLOW_RANGE", "FOLLOW_RANGE") + .change("GENERIC.KNOCKBACK_RESISTANCE", "KNOCKBACK_RESISTANCE") + .change("GENERIC.MOVEMENT_SPEED", "MOVEMENT_SPEED") + .change("GENERIC.FLYING_SPEED", "FLYING_SPEED") + .change("GENERIC.ATTACK_DAMAGE", "ATTACK_DAMAGE") + .change("GENERIC.ATTACK_KNOCKBACK", "ATTACK_KNOCKBACK") + .change("GENERIC.ATTACK_SPEED", "ATTACK_SPEED") + .change("GENERIC.ARMOR", "ARMOR") + .change("GENERIC.ARMOR_TOUGHNESS", "ARMOR_TOUGHNESS") + .change("GENERIC.FALL_DAMAGE_MULTIPLIER", "FALL_DAMAGE_MULTIPLIER") + .change("GENERIC.LUCK", "LUCK") + .change("GENERIC.MAX_ABSORPTION", "MAX_ABSORPTION") + .change("GENERIC.SAFE_FALL_DISTANCE", "SAFE_FALL_DISTANCE") + .change("GENERIC.SCALE", "SCALE") + .change("GENERIC.STEP_HEIGHT", "STEP_HEIGHT") + .change("GENERIC.GRAVITY", "GRAVITY") + .change("GENERIC.JUMP_STRENGTH", "JUMP_STRENGTH") + .change("GENERIC.BURNING_TIME", "BURNING_TIME") + .change("GENERIC.EXPLOSION_KNOCKBACK_RESISTANCE", "EXPLOSION_KNOCKBACK_RESISTANCE") + .change("GENERIC.MOVEMENT_EFFICIENCY", "MOVEMENT_EFFICIENCY") + .change("GENERIC.OXYGEN_BONUS", "OXYGEN_BONUS") + .change("GENERIC.WATER_MOVEMENT_EFFICIENCY", "WATER_MOVEMENT_EFFICIENCY") + .change("GENERIC.TEMPT_RANGE", "TEMPT_RANGE") + .change("PLAYER.BLOCK_INTERACTION_RANGE", "BLOCK_INTERACTION_RANGE") + .change("PLAYER.ENTITY_INTERACTION_RANGE", "ENTITY_INTERACTION_RANGE") + .change("PLAYER.BLOCK_BREAK_SPEED", "BLOCK_BREAK_SPEED") + .change("PLAYER.MINING_EFFICIENCY", "MINING_EFFICIENCY") + .change("PLAYER.SNEAKING_SPEED", "SNEAKING_SPEED") + .change("PLAYER.SUBMERGED_MINING_SPEED", "SUBMERGED_MINING_SPEED") + .change("PLAYER.SWEEPING_DAMAGE_RATIO", "SWEEPING_DAMAGE_RATIO") + .change("ZOMBIE.SPAWN_REINFORCEMENTS", "SPAWN_REINFORCEMENTS") .build(); public static final BiFunction ATTRIBUTE_RENAME = ATTRIBUTE_DATA::getReplacement; diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/enums/EnumEvil.java b/src/main/java/org/bukkit/craftbukkit/legacy/enums/EnumEvil.java index 693b2bde32c8..657d377ee4fd 100644 --- a/src/main/java/org/bukkit/craftbukkit/legacy/enums/EnumEvil.java +++ b/src/main/java/org/bukkit/craftbukkit/legacy/enums/EnumEvil.java @@ -17,6 +17,7 @@ import java.util.stream.Collectors; import org.bukkit.NamespacedKey; import org.bukkit.Registry; +import org.bukkit.attribute.Attribute; import org.bukkit.block.banner.PatternType; import org.bukkit.craftbukkit.legacy.FieldRename; import org.bukkit.craftbukkit.legacy.reroute.DoNotReroute; @@ -44,6 +45,7 @@ public class EnumEvil { static { // Add Classes which got changed here + REGISTRIES.put(Attribute.class, new LegacyRegistryData(Registry.ATTRIBUTE, Attribute::valueOf)); REGISTRIES.put(Villager.Type.class, new LegacyRegistryData(Registry.VILLAGER_TYPE, Villager.Type::valueOf)); REGISTRIES.put(Villager.Profession.class, new LegacyRegistryData(Registry.VILLAGER_PROFESSION, Villager.Profession::valueOf)); REGISTRIES.put(Frog.Variant.class, new LegacyRegistryData(Registry.FROG_VARIANT, Frog.Variant::valueOf)); diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java index 7d1feb48925b..c51e7a939b52 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java +++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java @@ -87,7 +87,8 @@ public class Commodore { "org/bukkit/entity/Frog$Variant", "NOP", "org/bukkit/entity/Cat$Type", "NOP", "org/bukkit/map/MapCursor$Type", "NOP", - "org/bukkit/block/banner/PatternType", "NOP" + "org/bukkit/block/banner/PatternType", "NOP", + "org/bukkit/attribute/Attribute", "NOP" ); private final List reroutes = new ArrayList<>(); // only for testing diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java index aefbeeec0ec9..eda0a3dad7b4 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -51,7 +51,6 @@ import org.bukkit.craftbukkit.CraftFeatureFlag; import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftServer; -import org.bukkit.craftbukkit.attribute.CraftAttribute; import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.craftbukkit.damage.CraftDamageEffect; import org.bukkit.craftbukkit.damage.CraftDamageSourceBuilder; @@ -368,7 +367,7 @@ public String getTranslationKey(ItemStack itemStack) { @Override public String getTranslationKey(final Attribute attribute) { - return CraftAttribute.bukkitToMinecraft(attribute).getDescriptionId(); + return attribute.getTranslationKey(); } @Override diff --git a/src/test/java/org/bukkit/craftbukkit/attribute/AttributeTest.java b/src/test/java/org/bukkit/craftbukkit/attribute/AttributeTest.java deleted file mode 100644 index f90474f44331..000000000000 --- a/src/test/java/org/bukkit/craftbukkit/attribute/AttributeTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.bukkit.craftbukkit.attribute; - -import static org.junit.jupiter.api.Assertions.*; -import net.minecraft.core.Holder; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.world.entity.ai.attributes.AttributeBase; -import org.bukkit.attribute.Attribute; -import org.bukkit.support.environment.AllFeatures; -import org.junit.jupiter.api.Test; - -@AllFeatures -public class AttributeTest { - - @Test - public void testToBukkit() { - for (AttributeBase nms : BuiltInRegistries.ATTRIBUTE) { - Attribute bukkit = CraftAttribute.minecraftToBukkit(nms); - - assertNotNull(bukkit, nms.toString()); - } - } - - @Test - public void testToNMS() { - for (Attribute attribute : Attribute.values()) { - Holder nms = CraftAttribute.bukkitToMinecraftHolder(attribute); - - assertNotNull(nms, attribute.name()); - } - } -} diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java index 8926df659efe..840be1d4a5d1 100644 --- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java @@ -440,18 +440,18 @@ public void testEachExtraData() { public void testAttributeModifiers() { UUID sameUUID = UUID.randomUUID(); ItemMeta itemMeta = Bukkit.getItemFactory().getItemMeta(Material.DIAMOND_PICKAXE); - itemMeta.addAttributeModifier(Attribute.GENERIC_ATTACK_SPEED, new AttributeModifier(sameUUID, "Test Modifier", 10, AttributeModifier.Operation.ADD_NUMBER)); + itemMeta.addAttributeModifier(Attribute.ATTACK_SPEED, new AttributeModifier(sameUUID, "Test Modifier", 10, AttributeModifier.Operation.ADD_NUMBER)); ItemMeta equalMeta = Bukkit.getItemFactory().getItemMeta(Material.DIAMOND_PICKAXE); - equalMeta.addAttributeModifier(Attribute.GENERIC_ATTACK_SPEED, new AttributeModifier(sameUUID, "Test Modifier", 10, AttributeModifier.Operation.ADD_NUMBER)); + equalMeta.addAttributeModifier(Attribute.ATTACK_SPEED, new AttributeModifier(sameUUID, "Test Modifier", 10, AttributeModifier.Operation.ADD_NUMBER)); assertThat(itemMeta.equals(equalMeta), is(true)); ItemMeta itemMeta2 = Bukkit.getItemFactory().getItemMeta(Material.DIAMOND_PICKAXE); - itemMeta2.addAttributeModifier(Attribute.GENERIC_ATTACK_SPEED, new AttributeModifier(sameUUID, "Test Modifier", 10, AttributeModifier.Operation.ADD_NUMBER)); + itemMeta2.addAttributeModifier(Attribute.ATTACK_SPEED, new AttributeModifier(sameUUID, "Test Modifier", 10, AttributeModifier.Operation.ADD_NUMBER)); ItemMeta notEqualMeta2 = Bukkit.getItemFactory().getItemMeta(Material.DIAMOND_PICKAXE); - notEqualMeta2.addAttributeModifier(Attribute.GENERIC_ATTACK_SPEED, new AttributeModifier(sameUUID, "Test Modifier", 11, AttributeModifier.Operation.ADD_NUMBER)); + notEqualMeta2.addAttributeModifier(Attribute.ATTACK_SPEED, new AttributeModifier(sameUUID, "Test Modifier", 11, AttributeModifier.Operation.ADD_NUMBER)); assertThat(itemMeta2.equals(notEqualMeta2), is(false)); } diff --git a/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java b/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java index c237986a1083..6da72f19ed55 100644 --- a/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java +++ b/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java @@ -6,6 +6,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; import net.minecraft.world.effect.MobEffectList; +import net.minecraft.world.entity.ai.attributes.AttributeBase; import net.minecraft.world.entity.animal.CatVariant; import net.minecraft.world.entity.animal.FrogVariant; import net.minecraft.world.entity.animal.WolfVariant; @@ -18,11 +19,13 @@ import org.bukkit.GameEvent; import org.bukkit.JukeboxSong; import org.bukkit.MusicInstrument; +import org.bukkit.attribute.Attribute; import org.bukkit.block.BlockType; import org.bukkit.block.banner.PatternType; import org.bukkit.craftbukkit.CraftGameEvent; import org.bukkit.craftbukkit.CraftJukeboxSong; import org.bukkit.craftbukkit.CraftMusicInstrument; +import org.bukkit.craftbukkit.attribute.CraftAttribute; import org.bukkit.craftbukkit.block.CraftBlockType; import org.bukkit.craftbukkit.block.banner.CraftPatternType; import org.bukkit.craftbukkit.damage.CraftDamageType; @@ -63,6 +66,7 @@ public class RegistriesArgumentProvider implements ArgumentsProvider { static { // Order: Bukkit class, Minecraft Registry key, CraftBukkit class, Minecraft class + register(Attribute.class, Registries.ATTRIBUTE, CraftAttribute.class, AttributeBase.class); register(Enchantment.class, Registries.ENCHANTMENT, CraftEnchantment.class, net.minecraft.world.item.enchantment.Enchantment.class); register(GameEvent.class, Registries.GAME_EVENT, CraftGameEvent.class, net.minecraft.world.level.gameevent.GameEvent.class); register(MusicInstrument.class, Registries.INSTRUMENT, CraftMusicInstrument.class, Instrument.class);