diff --git a/paper-server/nms-patches/net/minecraft/world/inventory/ContainerEnchantTable.patch b/paper-server/nms-patches/net/minecraft/world/inventory/ContainerEnchantTable.patch index f606d687c8..56eb1c8523 100644 --- a/paper-server/nms-patches/net/minecraft/world/inventory/ContainerEnchantTable.patch +++ b/paper-server/nms-patches/net/minecraft/world/inventory/ContainerEnchantTable.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/world/inventory/ContainerEnchantTable.java +++ b/net/minecraft/world/inventory/ContainerEnchantTable.java -@@ -25,6 +25,21 @@ +@@ -25,6 +25,22 @@ import net.minecraft.world.level.block.BlockEnchantmentTable; import net.minecraft.world.level.block.Blocks; @@ -9,6 +9,7 @@ +import net.minecraft.world.item.enchantment.Enchantment; +import org.bukkit.Location; +import org.bukkit.NamespacedKey; ++import org.bukkit.craftbukkit.enchantments.CraftEnchantment; +import org.bukkit.craftbukkit.inventory.CraftInventoryEnchanting; +import org.bukkit.craftbukkit.inventory.CraftInventoryView; +import org.bukkit.craftbukkit.inventory.CraftItemStack; @@ -22,7 +23,7 @@ public class ContainerEnchantTable extends Container { static final MinecraftKey EMPTY_SLOT_LAPIS_LAZULI = new MinecraftKey("item/empty_slot_lapis_lazuli"); -@@ -35,6 +50,10 @@ +@@ -35,6 +51,10 @@ public final int[] costs; public final int[] enchantClue; public final int[] levelClue; @@ -33,7 +34,7 @@ public ContainerEnchantTable(int i, PlayerInventory playerinventory) { this(i, playerinventory, ContainerAccess.NULL); -@@ -48,6 +67,13 @@ +@@ -48,6 +68,13 @@ super.setChanged(); ContainerEnchantTable.this.slotsChanged(this); } @@ -47,7 +48,7 @@ }; this.random = RandomSource.create(); this.enchantmentSeed = ContainerProperty.standalone(); -@@ -55,13 +81,13 @@ +@@ -55,13 +82,13 @@ this.enchantClue = new int[]{-1, -1, -1}; this.levelClue = new int[]{-1, -1, -1}; this.access = containeraccess; @@ -63,7 +64,7 @@ @Override public boolean mayPlace(ItemStack itemstack) { return itemstack.is(Items.LAPIS_LAZULI); -@@ -95,6 +121,9 @@ +@@ -95,6 +122,9 @@ this.addDataSlot(ContainerProperty.shared(this.levelClue, 0)); this.addDataSlot(ContainerProperty.shared(this.levelClue, 1)); this.addDataSlot(ContainerProperty.shared(this.levelClue, 2)); @@ -73,7 +74,7 @@ } @Override -@@ -102,7 +131,7 @@ +@@ -102,7 +132,7 @@ if (iinventory == this.enchantSlots) { ItemStack itemstack = iinventory.getItem(0); @@ -82,7 +83,7 @@ this.access.execute((world, blockposition) -> { int i = 0; Iterator iterator = BlockEnchantmentTable.BOOKSHELF_OFFSETS.iterator(); -@@ -141,6 +170,41 @@ +@@ -141,6 +171,41 @@ } } @@ -90,7 +91,7 @@ + CraftItemStack item = CraftItemStack.asCraftMirror(itemstack); + org.bukkit.enchantments.EnchantmentOffer[] offers = new EnchantmentOffer[3]; + for (j = 0; j < 3; ++j) { -+ org.bukkit.enchantments.Enchantment enchantment = (this.enchantClue[j] >= 0) ? org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(BuiltInRegistries.ENCHANTMENT.byId(this.enchantClue[j])))) : null; ++ org.bukkit.enchantments.Enchantment enchantment = (this.enchantClue[j] >= 0) ? CraftEnchantment.minecraftToBukkit(Enchantment.byId(this.enchantClue[j])) : null; + offers[j] = (enchantment != null) ? new EnchantmentOffer(enchantment, this.levelClue[j], this.costs[j]) : null; + } + @@ -111,7 +112,7 @@ + EnchantmentOffer offer = event.getOffers()[j]; + if (offer != null) { + this.costs[j] = offer.getCost(); -+ this.enchantClue[j] = BuiltInRegistries.ENCHANTMENT.getId(BuiltInRegistries.ENCHANTMENT.get(CraftNamespacedKey.toMinecraft(offer.getEnchantment().getKey()))); ++ this.enchantClue[j] = BuiltInRegistries.ENCHANTMENT.getId(CraftEnchantment.bukkitToMinecraft(offer.getEnchantment())); + this.levelClue[j] = offer.getEnchantmentLevel(); + } else { + this.costs[j] = 0; @@ -124,7 +125,7 @@ this.broadcastChanges(); }); } else { -@@ -168,21 +232,46 @@ +@@ -168,21 +233,46 @@ ItemStack itemstack2 = itemstack; List list = this.getEnchantmentList(world.enabledFeatures(), itemstack, i, this.costs[i]); @@ -135,11 +136,11 @@ + // entityhuman.onEnchantmentPerformed(itemstack, j); // Moved down + Map enchants = new java.util.HashMap(); + for (WeightedRandomEnchant instance : list) { -+ enchants.put(org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(instance.enchantment))), instance.level); ++ enchants.put(CraftEnchantment.minecraftToBukkit(instance.enchantment), instance.level); + } + CraftItemStack item = CraftItemStack.asCraftMirror(itemstack2); + -+ org.bukkit.enchantments.Enchantment hintedEnchantment = org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(Enchantment.byId(enchantClue[i])))); ++ org.bukkit.enchantments.Enchantment hintedEnchantment = CraftEnchantment.minecraftToBukkit(Enchantment.byId(enchantClue[i])); + int hintedEnchantmentLevel = levelClue[i]; + EnchantItemEvent event = new EnchantItemEvent((Player) entityhuman.getBukkitEntity(), this.getBukkitView(), access.getLocation().getBlock(), item, this.costs[i], enchants, hintedEnchantment, hintedEnchantmentLevel, i); + world.getCraftServer().getPluginManager().callEvent(event); @@ -177,7 +178,7 @@ if (!entityhuman.hasInfiniteMaterials()) { itemstack1.shrink(j); if (itemstack1.isEmpty()) { -@@ -245,6 +334,7 @@ +@@ -245,6 +335,7 @@ @Override public boolean stillValid(EntityHuman entityhuman) { @@ -185,7 +186,7 @@ return stillValid(this.access, entityhuman, Blocks.ENCHANTING_TABLE); } -@@ -295,4 +385,17 @@ +@@ -295,4 +386,17 @@ return itemstack; } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMusicInstrument.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMusicInstrument.java index 7d1dc46fc5..b6d151d378 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMusicInstrument.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMusicInstrument.java @@ -38,6 +38,18 @@ public class CraftMusicInstrument extends MusicInstrument implements Handleable< + ", this can happen if a plugin creates its own instrument without properly registering it."); } + public static String bukkitToString(MusicInstrument bukkit) { + Preconditions.checkArgument(bukkit != null); + + return bukkit.getKey().toString(); + } + + public static MusicInstrument stringToBukkit(String string) { + Preconditions.checkArgument(string != null); + + return Registry.INSTRUMENT.get(NamespacedKey.fromString(string)); + } + private final NamespacedKey key; private final Instrument handle; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftParticle.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftParticle.java index 9a11517097..bf1c5d0504 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftParticle.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftParticle.java @@ -31,6 +31,7 @@ import org.bukkit.block.data.BlockData; import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.craftbukkit.entity.CraftEntity; import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.craftbukkit.legacy.FieldRename; import org.bukkit.craftbukkit.util.CraftLocation; import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.craftbukkit.util.CraftNamespacedKey; @@ -207,7 +208,7 @@ public abstract class CraftParticle implements Keyed { } public CraftParticleRegistry(IRegistry> minecraftRegistry) { - super(CraftParticle.class, minecraftRegistry, null); + super(CraftParticle.class, minecraftRegistry, null, FieldRename.PARTICLE_TYPE_RENAME); } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java index b6a1682aab..3ce32ab75e 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java @@ -16,7 +16,10 @@ import org.bukkit.GameEvent; import org.bukkit.Keyed; import org.bukkit.MusicInstrument; import org.bukkit.NamespacedKey; +import org.bukkit.Particle; import org.bukkit.Registry; +import org.bukkit.attribute.Attribute; +import org.bukkit.block.Biome; import org.bukkit.craftbukkit.damage.CraftDamageType; import org.bukkit.craftbukkit.enchantments.CraftEnchantment; import org.bukkit.craftbukkit.entity.CraftWolf; @@ -24,11 +27,14 @@ import org.bukkit.craftbukkit.generator.structure.CraftStructure; import org.bukkit.craftbukkit.generator.structure.CraftStructureType; import org.bukkit.craftbukkit.inventory.trim.CraftTrimMaterial; import org.bukkit.craftbukkit.inventory.trim.CraftTrimPattern; +import org.bukkit.craftbukkit.legacy.FieldRename; import org.bukkit.craftbukkit.potion.CraftPotionEffectType; +import org.bukkit.craftbukkit.util.ApiVersion; import org.bukkit.craftbukkit.util.CraftNamespacedKey; import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.damage.DamageType; import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.EntityType; import org.bukkit.entity.Wolf; import org.bukkit.generator.structure.Structure; import org.bukkit.generator.structure.StructureType; @@ -39,6 +45,7 @@ import org.jetbrains.annotations.NotNull; public class CraftRegistry implements Registry { + private static final BiFunction NONE = (namespacedKey, apiVersion) -> namespacedKey; private static IRegistryCustom registry; public static void setMinecraftRegistry(IRegistryCustom registry) { @@ -110,49 +117,83 @@ public class CraftRegistry implements Registry { */ public static Registry createRegistry(Class bukkitClass, IRegistryCustom registryHolder) { if (bukkitClass == Enchantment.class) { - return new CraftRegistry<>(Enchantment.class, registryHolder.registryOrThrow(Registries.ENCHANTMENT), CraftEnchantment::new); + return new CraftRegistry<>(Enchantment.class, registryHolder.registryOrThrow(Registries.ENCHANTMENT), CraftEnchantment::new, FieldRename.ENCHANTMENT_RENAME); } if (bukkitClass == GameEvent.class) { - return new CraftRegistry<>(GameEvent.class, registryHolder.registryOrThrow(Registries.GAME_EVENT), CraftGameEvent::new); + return new CraftRegistry<>(GameEvent.class, registryHolder.registryOrThrow(Registries.GAME_EVENT), CraftGameEvent::new, NONE); } if (bukkitClass == MusicInstrument.class) { - return new CraftRegistry<>(MusicInstrument.class, registryHolder.registryOrThrow(Registries.INSTRUMENT), CraftMusicInstrument::new); + return new CraftRegistry<>(MusicInstrument.class, registryHolder.registryOrThrow(Registries.INSTRUMENT), CraftMusicInstrument::new, NONE); } if (bukkitClass == PotionEffectType.class) { - return new CraftRegistry<>(PotionEffectType.class, registryHolder.registryOrThrow(Registries.MOB_EFFECT), CraftPotionEffectType::new); + return new CraftRegistry<>(PotionEffectType.class, registryHolder.registryOrThrow(Registries.MOB_EFFECT), CraftPotionEffectType::new, NONE); } if (bukkitClass == Structure.class) { - return new CraftRegistry<>(Structure.class, registryHolder.registryOrThrow(Registries.STRUCTURE), CraftStructure::new); + return new CraftRegistry<>(Structure.class, registryHolder.registryOrThrow(Registries.STRUCTURE), CraftStructure::new, NONE); } if (bukkitClass == StructureType.class) { - return new CraftRegistry<>(StructureType.class, BuiltInRegistries.STRUCTURE_TYPE, CraftStructureType::new); + return new CraftRegistry<>(StructureType.class, BuiltInRegistries.STRUCTURE_TYPE, CraftStructureType::new, NONE); } if (bukkitClass == TrimMaterial.class) { - return new CraftRegistry<>(TrimMaterial.class, registryHolder.registryOrThrow(Registries.TRIM_MATERIAL), CraftTrimMaterial::new); + return new CraftRegistry<>(TrimMaterial.class, registryHolder.registryOrThrow(Registries.TRIM_MATERIAL), CraftTrimMaterial::new, NONE); } if (bukkitClass == TrimPattern.class) { - return new CraftRegistry<>(TrimPattern.class, registryHolder.registryOrThrow(Registries.TRIM_PATTERN), CraftTrimPattern::new); + return new CraftRegistry<>(TrimPattern.class, registryHolder.registryOrThrow(Registries.TRIM_PATTERN), CraftTrimPattern::new, NONE); } if (bukkitClass == DamageType.class) { - return new CraftRegistry<>(DamageType.class, registryHolder.registryOrThrow(Registries.DAMAGE_TYPE), CraftDamageType::new); + return new CraftRegistry<>(DamageType.class, registryHolder.registryOrThrow(Registries.DAMAGE_TYPE), CraftDamageType::new, NONE); } if (bukkitClass == Wolf.Variant.class) { - return new CraftRegistry<>(Wolf.Variant.class, registryHolder.registryOrThrow(Registries.WOLF_VARIANT), CraftWolf.CraftVariant::new); + return new CraftRegistry<>(Wolf.Variant.class, registryHolder.registryOrThrow(Registries.WOLF_VARIANT), CraftWolf.CraftVariant::new, NONE); } return null; } + public static B get(Registry bukkit, NamespacedKey namespacedKey, ApiVersion apiVersion) { + if (bukkit instanceof CraftRegistry craft) { + return craft.get(namespacedKey, apiVersion); + } + + if (bukkit instanceof Registry.SimpleRegistry simple) { + Class bClass = simple.getType(); + + if (bClass == Biome.class) { + return bukkit.get(FieldRename.BIOME_RENAME.apply(namespacedKey, apiVersion)); + } + + if (bClass == EntityType.class) { + return bukkit.get(FieldRename.ENTITY_TYPE_RENAME.apply(namespacedKey, apiVersion)); + } + + 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); + } + private final Class bukkitClass; private final Map cache = new HashMap<>(); private final IRegistry minecraftRegistry; private final BiFunction minecraftToBukkit; + private final BiFunction updater; private boolean init; - public CraftRegistry(Class bukkitClass, IRegistry minecraftRegistry, BiFunction minecraftToBukkit) { + public CraftRegistry(Class bukkitClass, IRegistry minecraftRegistry, BiFunction minecraftToBukkit, BiFunction updater) { this.bukkitClass = bukkitClass; this.minecraftRegistry = minecraftRegistry; this.minecraftToBukkit = minecraftToBukkit; + this.updater = updater; + } + + public B get(NamespacedKey namespacedKey, ApiVersion apiVersion) { + return get(updater.apply(namespacedKey, apiVersion)); } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java b/paper-server/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java index 7724ed7478..fb4de996fb 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttribute.java @@ -1,6 +1,7 @@ package org.bukkit.craftbukkit.attribute; import com.google.common.base.Preconditions; +import java.util.Locale; import net.minecraft.core.Holder; import net.minecraft.core.IRegistry; import net.minecraft.core.registries.Registries; @@ -9,6 +10,8 @@ import org.bukkit.NamespacedKey; import org.bukkit.Registry; import org.bukkit.attribute.Attribute; import org.bukkit.craftbukkit.CraftRegistry; +import org.bukkit.craftbukkit.legacy.FieldRename; +import org.bukkit.craftbukkit.util.ApiVersion; import org.bukkit.craftbukkit.util.CraftNamespacedKey; public class CraftAttribute { @@ -28,10 +31,17 @@ public class CraftAttribute { return minecraftToBukkit(minecraft.value()); } - public static Attribute stringToBukkit(String bukkit) { - Preconditions.checkArgument(bukkit != null); + public static Attribute stringToBukkit(String string) { + Preconditions.checkArgument(string != null); - return Registry.ATTRIBUTE.get(NamespacedKey.fromString(bukkit)); + // We currently do not have any version-dependent remapping, so we can use current version + // First convert from when only the names where saved + string = FieldRename.convertAttributeName(ApiVersion.CURRENT, string); + string = string.toLowerCase(Locale.ROOT); + NamespacedKey key = NamespacedKey.fromString(string); + + // Now also convert from when keys where saved + return CraftRegistry.get(Registry.ATTRIBUTE, key, ApiVersion.CURRENT); } public static AttributeBase bukkitToMinecraft(Attribute bukkit) { @@ -53,4 +63,10 @@ public class CraftAttribute { throw new IllegalArgumentException("No Reference holder found for " + bukkit + ", this can happen if a plugin creates its own sound effect with out properly registering it."); } + + public static String bukkitToString(Attribute bukkit) { + Preconditions.checkArgument(bukkit != null); + + return bukkit.getKey().toString(); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java index 16309e8152..566a3630cc 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java @@ -143,13 +143,13 @@ public class CraftCreatureSpawner extends CraftBlockEntityState> type = EntityTypes.by(spawnData.getEntityToSpawn()); - return type.map(entityTypes -> EntityTypes.getKey(entityTypes).getPath()).orElse(null); + return type.map(CraftEntityType::minecraftToBukkit).map(CraftEntityType::bukkitToString).orElse(null); } @Override public void setCreatureTypeByName(String creatureType) { // Verify input - EntityType type = EntityType.fromName(creatureType); + EntityType type = CraftEntityType.stringToBukkit(creatureType); if (type == null) { setSpawnedType(null); return; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/paper-server/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java index 510a3aa361..d2101c4ff7 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java @@ -1,5 +1,7 @@ package org.bukkit.craftbukkit.enchantments; +import com.google.common.base.Preconditions; +import java.util.Locale; import net.minecraft.core.Holder; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; @@ -9,6 +11,8 @@ import org.bukkit.NamespacedKey; import org.bukkit.Registry; import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.craftbukkit.legacy.FieldRename; +import org.bukkit.craftbukkit.util.ApiVersion; import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.EnchantmentTarget; @@ -29,6 +33,25 @@ public class CraftEnchantment extends Enchantment implements Handleable enchantments = new LinkedHashMap(ench.size()); for (Map.Entry entry : ench.entrySet()) { - // Doctor older enchants - String enchantKey = entry.getKey().toString(); - if (enchantKey.equals("SWEEPING")) { - enchantKey = "SWEEPING_EDGE"; - } - - Enchantment enchantment = Enchantment.getByName(enchantKey); + Enchantment enchantment = CraftEnchantment.stringToBukkit(entry.getKey().toString()); if ((enchantment != null) && (entry.getValue() instanceof Integer)) { enchantments.put(enchantment, (Integer) entry.getValue()); } @@ -696,7 +689,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { continue; } AttributeModifier modifier = (AttributeModifier) o; - Attribute attribute = EnumUtils.getEnum(Attribute.class, attributeName.toUpperCase(Locale.ROOT)); + Attribute attribute = CraftAttribute.stringToBukkit(attributeName); if (attribute == null) { continue; } @@ -1520,7 +1513,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { List hideFlags = new ArrayList(); for (ItemFlag hideFlagEnum : getItemFlags()) { - hideFlags.add(hideFlagEnum.name()); + hideFlags.add(CraftItemFlag.bukkitToString(hideFlagEnum)); } if (!hideFlags.isEmpty()) { builder.put(HIDEFLAGS.BUKKIT, hideFlags); @@ -1620,7 +1613,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { ImmutableMap.Builder enchants = ImmutableMap.builder(); for (Map.Entry enchant : enchantments.entrySet()) { - enchants.put(enchant.getKey().getName(), enchant.getValue()); + enchants.put(CraftEnchantment.bukkitToString(enchant.getKey()), enchant.getValue()); } builder.put(key.BUKKIT, enchants.build()); @@ -1640,7 +1633,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { if (modCollection == null || modCollection.isEmpty()) { continue; } - mods.put(entry.getKey().name(), new ArrayList<>(modCollection)); + mods.put(CraftAttribute.bukkitToString(entry.getKey()), new ArrayList<>(modCollection)); } builder.put(key.BUKKIT, mods); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java index 71d44f7475..08c0e49044 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMusicInstrument.java @@ -8,8 +8,6 @@ import net.minecraft.core.component.DataComponents; import net.minecraft.world.item.Instrument; import org.bukkit.Material; import org.bukkit.MusicInstrument; -import org.bukkit.NamespacedKey; -import org.bukkit.Registry; import org.bukkit.configuration.serialization.DelegateDeserialization; import org.bukkit.craftbukkit.CraftMusicInstrument; import org.bukkit.inventory.meta.MusicInstrumentMeta; @@ -42,7 +40,7 @@ public class CraftMetaMusicInstrument extends CraftMetaItem implements MusicInst String instrumentString = SerializableMeta.getString(map, GOAT_HORN_INSTRUMENT.BUKKIT, true); if (instrumentString != null) { - this.instrument = Registry.INSTRUMENT.get(NamespacedKey.fromString(instrumentString)); + this.instrument = CraftMusicInstrument.stringToBukkit(instrumentString); } } @@ -110,7 +108,7 @@ public class CraftMetaMusicInstrument extends CraftMetaItem implements MusicInst super.serialize(builder); if (hasInstrument()) { - builder.put(GOAT_HORN_INSTRUMENT.BUKKIT, instrument.getKey().toString()); + builder.put(GOAT_HORN_INSTRUMENT.BUKKIT, CraftMusicInstrument.bukkitToString(instrument)); } return builder; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSpawnEgg.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSpawnEgg.java index a3218584b9..b799b65b8c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSpawnEgg.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSpawnEgg.java @@ -9,11 +9,11 @@ import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.resources.MinecraftKey; import net.minecraft.world.item.component.CustomData; import org.bukkit.Material; import org.bukkit.configuration.serialization.DelegateDeserialization; import org.bukkit.craftbukkit.entity.CraftEntitySnapshot; +import org.bukkit.craftbukkit.entity.CraftEntityType; import org.bukkit.craftbukkit.util.CraftLegacy; import org.bukkit.entity.EntitySnapshot; import org.bukkit.entity.EntityType; @@ -138,7 +138,7 @@ public class CraftMetaSpawnEgg extends CraftMetaItem implements SpawnEggMeta { String entityType = SerializableMeta.getString(map, ENTITY_ID.BUKKIT, true); if (entityType != null) { - this.spawnedType = EntityType.fromName(entityType); + this.spawnedType = CraftEntityType.stringToBukkit(entityType); } } @@ -155,7 +155,7 @@ public class CraftMetaSpawnEgg extends CraftMetaItem implements SpawnEggMeta { // Duplicated from constructor String entityType = SerializableMeta.getString(map, ENTITY_ID.BUKKIT, true); if (entityType != null) { - this.spawnedType = EntityType.fromName(entityType); + this.spawnedType = CraftEntityType.stringToBukkit(entityType); } } @@ -172,7 +172,7 @@ public class CraftMetaSpawnEgg extends CraftMetaItem implements SpawnEggMeta { // See if we can read a converted ID tag if (entityTag.contains(ENTITY_ID.NBT)) { - this.spawnedType = EntityType.fromName(new MinecraftKey(entityTag.getString(ENTITY_ID.NBT)).getPath()); + this.spawnedType = CraftEntityType.stringToBukkit(entityTag.getString(ENTITY_ID.NBT)); } } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java b/paper-server/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java index c35257b9bd..bec510c4e8 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java @@ -1,9 +1,14 @@ package org.bukkit.craftbukkit.legacy; +import java.util.function.BiFunction; +import org.bukkit.Keyed; +import org.bukkit.NamespacedKey; import org.bukkit.Particle; +import org.bukkit.Registry; import org.bukkit.attribute.Attribute; import org.bukkit.block.Biome; import org.bukkit.block.banner.PatternType; +import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.legacy.fieldrename.FieldRenameData; import org.bukkit.craftbukkit.legacy.reroute.DoNotReroute; import org.bukkit.craftbukkit.legacy.reroute.InjectPluginVersion; @@ -36,13 +41,23 @@ public class FieldRename { case "org/bukkit/MusicInstrument" -> convertMusicInstrumentName(apiVersion, from); case "org/bukkit/Particle" -> convertParticleName(apiVersion, from); case "org/bukkit/loot/LootTables" -> convertLootTablesName(apiVersion, from); - case "org/bukkit/attribute/Attribute" -> convertAttributeName(apiVersion, from); + case "org/bukkit/attribute/Attribute" -> convertAttributeName(apiVersion, from).replace('.', '_'); case "org/bukkit/map/MapCursor$Type" -> convertMapCursorTypeName(apiVersion, from); case "org/bukkit/inventory/ItemFlag" -> convertItemFlagName(apiVersion, from); default -> from; }; } + @RerouteStatic("java/lang/Enum") + public static > T valueOf(Class enumClass, String name, @InjectPluginVersion ApiVersion apiVersion) { + return Enum.valueOf(enumClass, rename(apiVersion, enumClass.getName().replace('.', '/'), name)); + } + + public static T get(Registry registry, NamespacedKey namespacedKey) { + // We don't have version-specific changes, so just use current, and don't inject a version + return CraftRegistry.get(registry, namespacedKey, ApiVersion.CURRENT); + } + // PatternType private static final FieldRenameData PATTERN_TYPE_DATA = FieldRenameData.Builder.newBuilder() .forVersionsBefore(ApiVersion.FIELD_NAME_PARITY) @@ -82,17 +97,20 @@ public class FieldRename { .change("DAMAGE_UNDEAD", "SMITE") .change("DAMAGE_ARTHROPODS", "BANE_OF_ARTHROPODS") .change("LOOT_BONUS_MOBS", "LOOTING") - .change("SWEEPING_EDGE", "SWEEPING") .change("DIG_SPEED", "EFFICIENCY") .change("DURABILITY", "UNBREAKING") .change("LOOT_BONUS_BLOCKS", "FORTUNE") .change("ARROW_DAMAGE", "POWER") .change("ARROW_KNOCKBACK", "PUNCH") .change("ARROW_FIRE", "FLAME") - .change("ARROW_INFINITY", "INFINITY") + .change("ARROW_INFINITE", "INFINITY") .change("LUCK", "LUCK_OF_THE_SEA") + .withKeyRename() + .change("SWEEPING", "SWEEPING_EDGE") .build(); + public static final BiFunction ENCHANTMENT_RENAME = ENCHANTMENT_DATA::getReplacement; + @DoNotReroute public static String convertEnchantmentName(ApiVersion version, String from) { return ENCHANTMENT_DATA.getReplacement(version, from); @@ -108,6 +126,7 @@ public class FieldRename { // Biome private static final FieldRenameData BIOME_DATA = FieldRenameData.Builder.newBuilder() .forAllVersions() + .withKeyRename() .change("NETHER", "NETHER_WASTES") .change("TALL_BIRCH_FOREST", "OLD_GROWTH_BIRCH_FOREST") .change("GIANT_TREE_TAIGA", "OLD_GROWTH_PINE_TAIGA") @@ -122,6 +141,8 @@ public class FieldRename { .change("WOODED_BADLANDS_PLATEAU", "WOODED_BADLANDS") .build(); + public static final BiFunction BIOME_RENAME = BIOME_DATA::getReplacement; + @DoNotReroute public static String convertBiomeName(ApiVersion version, String from) { return BIOME_DATA.getReplacement(version, from); @@ -134,23 +155,9 @@ public class FieldRename { return Biome.valueOf(convertBiomeName(ApiVersion.CURRENT, name)); } - // EntityType private static final FieldRenameData ENTITY_TYPE_DATA = FieldRenameData.Builder.newBuilder() .forAllVersions() - .change("XP_ORB", "EXPERIENCE_ORB") - .change("EYE_OF_ENDER_SIGNAL", "EYE_OF_ENDER") - .change("XP_BOTTLE", "EXPERIENCE_BOTTLE") - .change("FIREWORKS_ROCKET", "FIREWORK_ROCKET") - .change("EVOCATION_FANGS", "EVOKER_FANGS") - .change("EVOCATION_ILLAGER", "EVOKER") - .change("VINDICATION_ILLAGER", "VINDICATOR") - .change("ILLUSION_ILLAGER", "ILLUSIONER") - .change("COMMANDBLOCK_MINECART", "COMMAND_BLOCK_MINECART") - .change("SNOWMAN", "SNOW_GOLEM") - .change("VILLAGER_GOLEM", "IRON_GOLEM") - .change("ENDER_CRYSTAL", "END_CRYSTAL") - .change("ZOMBIE_PIGMAN", "ZOMBIFIED_PIGLIN") .change("PIG_ZOMBIE", "ZOMBIFIED_PIGLIN") .change("DROPPED_ITEM", "ITEM") .change("LEASH_HITCH", "LEASH_KNOT") @@ -167,11 +174,26 @@ public class FieldRename { .change("MINECART_MOB_SPAWNER", "SPAWNER_MINECART") .change("MUSHROOM_COW", "MOOSHROOM") .change("SNOWMAN", "SNOW_GOLEM") - .change("ENDER_CRYSTAL", "END_CRYSTAL") .change("FISHING_HOOK", "FISHING_BOBBER") .change("LIGHTNING", "LIGHTNING_BOLT") + .withKeyRename() + .change("XP_ORB", "EXPERIENCE_ORB") + .change("EYE_OF_ENDER_SIGNAL", "EYE_OF_ENDER") + .change("XP_BOTTLE", "EXPERIENCE_BOTTLE") + .change("FIREWORKS_ROCKET", "FIREWORK_ROCKET") + .change("EVOCATION_FANGS", "EVOKER_FANGS") + .change("EVOCATION_ILLAGER", "EVOKER") + .change("VINDICATION_ILLAGER", "VINDICATOR") + .change("ILLUSION_ILLAGER", "ILLUSIONER") + .change("COMMANDBLOCK_MINECART", "COMMAND_BLOCK_MINECART") + .change("SNOWMAN", "SNOW_GOLEM") + .change("VILLAGER_GOLEM", "IRON_GOLEM") + .change("ENDER_CRYSTAL", "END_CRYSTAL") + .change("ZOMBIE_PIGMAN", "ZOMBIFIED_PIGLIN") .build(); + public static final BiFunction ENTITY_TYPE_RENAME = ENTITY_TYPE_DATA::getReplacement; + @DoNotReroute public static String convertEntityTypeName(ApiVersion version, String from) { return ENTITY_TYPE_DATA.getReplacement(version, from); @@ -220,7 +242,6 @@ public class FieldRename { // PotionType private static final FieldRenameData POTION_TYPE_DATA = FieldRenameData.Builder.newBuilder() .forAllVersions() - .change("UNCRAFTABLE", "EMPTY") .change("JUMP", "LEAPING") .change("SPEED", "SWIFTNESS") .change("INSTANT_HEAL", "HEALING") @@ -292,8 +313,12 @@ public class FieldRename { .change("WATER_DROP", "RAIN") .change("MOB_APPEARANCE", "ELDER_GUARDIAN") .change("TOTEM", "TOTEM_OF_UNDYING") + .withKeyRename() + .change("GUST_EMITTER", "GUST_EMITTER_LARGE") .build(); + public static final BiFunction PARTICLE_TYPE_RENAME = PARTICLE_DATA::getReplacement; + @DoNotReroute public static String convertParticleName(ApiVersion version, String from) { return PARTICLE_DATA.getReplacement(version, from); @@ -327,9 +352,12 @@ public class FieldRename { // Attribute private static final FieldRenameData ATTRIBUTE_DATA = FieldRenameData.Builder.newBuilder() .forAllVersions() - .change("HORSE_JUMP_STRENGTH", "GENERIC_JUMP_STRENGTH") + .withKeyRename() + .change("HORSE.JUMP_STRENGTH", "GENERIC.JUMP_STRENGTH") .build(); + public static final BiFunction ATTRIBUTE_RENAME = ATTRIBUTE_DATA::getReplacement; + @DoNotReroute public static String convertAttributeName(ApiVersion version, String from) { return ATTRIBUTE_DATA.getReplacement(version, from); @@ -339,7 +367,7 @@ public class FieldRename { @RerouteStatic("org/bukkit/attribute/Attribute") public static Attribute valueOf_Attribute(String name) { // We don't have version-specific changes, so just use current, and don't inject a version - return Attribute.valueOf(convertAttributeName(ApiVersion.CURRENT, name)); + return Attribute.valueOf(convertAttributeName(ApiVersion.CURRENT, name).replace('.', '_')); } // MapCursor Type diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/legacy/fieldrename/FieldRenameData.java b/paper-server/src/main/java/org/bukkit/craftbukkit/legacy/fieldrename/FieldRenameData.java index c6922fd338..121c7efdd4 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/legacy/fieldrename/FieldRenameData.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/legacy/fieldrename/FieldRenameData.java @@ -5,9 +5,10 @@ import java.util.Locale; import java.util.Map; import java.util.NavigableMap; import java.util.TreeMap; +import org.bukkit.NamespacedKey; import org.bukkit.craftbukkit.util.ApiVersion; -public record FieldRenameData(NavigableMap> versionData, Map data) { +public record FieldRenameData(RenameData renameData, RenameData keyRenameData) { public String getReplacement(ApiVersion apiVersion, String from) { if (from == null) { @@ -15,24 +16,25 @@ public record FieldRenameData(NavigableMap> vers } from = from.toUpperCase(Locale.ROOT); - from = data.getOrDefault(from, from); + return renameData.getReplacement(apiVersion, from); + } - for (Map.Entry> entry : versionData.entrySet()) { - if (apiVersion.isNewerThanOrSameAs(entry.getKey())) { - continue; - } - - from = entry.getValue().getOrDefault(from, from); + public NamespacedKey getReplacement(NamespacedKey from, ApiVersion apiVersion) { + if (from == null) { + return null; } - return from; + return keyRenameData.getReplacement(apiVersion, from); } public static class Builder { private final Map data = new HashMap<>(); private final NavigableMap> versionData = new TreeMap<>(); + private final Map keyData = new HashMap<>(); + private final NavigableMap> versionKeyData = new TreeMap<>(); private ApiVersion currentVersion; + private boolean keyRename = false; public static Builder newBuilder() { return new Builder(); @@ -40,25 +42,58 @@ public record FieldRenameData(NavigableMap> vers public Builder forVersionsBefore(ApiVersion apiVersion) { this.currentVersion = apiVersion; + this.keyRename = false; return this; } public Builder forAllVersions() { this.currentVersion = null; + this.keyRename = false; + return this; + } + + public Builder withKeyRename() { + this.keyRename = true; return this; } public Builder change(String from, String to) { if (currentVersion != null) { - versionData.computeIfAbsent(currentVersion, d -> new HashMap<>()).put(from, to); + versionData.computeIfAbsent(currentVersion, d -> new HashMap<>()).put(from.replace('.', '_'), to); } else { - data.put(from, to); + data.put(from.replace('.', '_'), to); + } + + if (keyRename) { + NamespacedKey fromKey = NamespacedKey.minecraft(from.toLowerCase(Locale.ROOT)); + NamespacedKey toKey = NamespacedKey.minecraft(to.toLowerCase(Locale.ROOT)); + if (currentVersion != null) { + versionKeyData.computeIfAbsent(currentVersion, d -> new HashMap<>()).put(fromKey, toKey); + } else { + keyData.put(fromKey, toKey); + } } return this; } public FieldRenameData build() { - return new FieldRenameData(versionData, data); + return new FieldRenameData(new RenameData<>(versionData, data), new RenameData<>(versionKeyData, keyData)); + } + } + + private record RenameData(NavigableMap> versionData, Map data) { + public T getReplacement(ApiVersion apiVersion, T from) { + from = data.getOrDefault(from, from); + + for (Map.Entry> entry : versionData.entrySet()) { + if (apiVersion.isNewerThanOrSameAs(entry.getKey())) { + continue; + } + + from = entry.getValue().getOrDefault(from, from); + } + + return from; } } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionType.java b/paper-server/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionType.java index 3a63560d4d..29621d8eea 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionType.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionType.java @@ -3,6 +3,7 @@ package org.bukkit.craftbukkit.potion; import com.google.common.base.Preconditions; import com.google.common.base.Suppliers; import java.util.List; +import java.util.Locale; import java.util.function.Supplier; import net.minecraft.core.Holder; import net.minecraft.core.IRegistry; @@ -11,6 +12,8 @@ import net.minecraft.world.item.alchemy.PotionRegistry; import org.bukkit.NamespacedKey; import org.bukkit.Registry; 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.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -53,16 +56,23 @@ public class CraftPotionType implements PotionType.InternalPotionData { + ", this can happen if a plugin creates its own sound effect with out properly registering it."); } - public static String bukkitToString(PotionType potionType) { - Preconditions.checkArgument(potionType != null); + public static String bukkitToString(PotionType bukkit) { + Preconditions.checkArgument(bukkit != null); - return potionType.getKey().toString(); + return bukkit.getKey().toString(); } public static PotionType stringToBukkit(String string) { Preconditions.checkArgument(string != null); - return Registry.POTION.get(NamespacedKey.fromString(string)); + // We currently do not have any version-dependent remapping, so we can use current version + // First convert from when only the names where saved + string = FieldRename.convertPotionTypeName(ApiVersion.CURRENT, string); + string = string.toLowerCase(Locale.ROOT); + NamespacedKey key = NamespacedKey.fromString(string); + + // Now also convert from when keys where saved + return CraftRegistry.get(Registry.POTION, key, ApiVersion.CURRENT); } private final NamespacedKey key; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java index f63e3f9b6d..848bafdc8d 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -41,8 +41,10 @@ import net.minecraft.world.level.block.state.IBlockData; import net.minecraft.world.level.storage.SavedFile; import org.bukkit.Bukkit; import org.bukkit.FeatureFlag; +import org.bukkit.Keyed; import org.bukkit.Material; import org.bukkit.NamespacedKey; +import org.bukkit.Registry; import org.bukkit.UnsafeValues; import org.bukkit.advancement.Advancement; import org.bukkit.attribute.Attribute; @@ -58,10 +60,12 @@ import org.bukkit.craftbukkit.damage.CraftDamageEffect; import org.bukkit.craftbukkit.damage.CraftDamageSourceBuilder; import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.craftbukkit.legacy.CraftLegacy; +import org.bukkit.craftbukkit.legacy.FieldRename; import org.bukkit.craftbukkit.potion.CraftPotionType; import org.bukkit.damage.DamageEffect; import org.bukkit.damage.DamageSource; import org.bukkit.damage.DamageType; +import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.EntityType; import org.bukkit.inventory.CreativeCategory; import org.bukkit.inventory.EquipmentSlot; @@ -399,6 +403,21 @@ public final class CraftMagicNumbers implements UnsafeValues { return new CraftDamageSourceBuilder(damageType); } + @Override + public String get(Class aClass, String s) { + if (aClass == Enchantment.class) { + // We currently do not have any version-dependent remapping, so we can use current version + return FieldRename.convertEnchantmentName(ApiVersion.CURRENT, s); + } + return s; + } + + @Override + public B get(Registry registry, NamespacedKey namespacedKey) { + // We currently do not have any version-dependent remapping, so we can use current version + return CraftRegistry.get(registry, namespacedKey, ApiVersion.CURRENT); + } + /** * This helper class represents the different NBT Tags. *

diff --git a/paper-server/src/test/java/org/bukkit/registry/RegistryLoadOrderTest.java b/paper-server/src/test/java/org/bukkit/registry/RegistryLoadOrderTest.java index 3a6dbb370d..a09bea0479 100644 --- a/paper-server/src/test/java/org/bukkit/registry/RegistryLoadOrderTest.java +++ b/paper-server/src/test/java/org/bukkit/registry/RegistryLoadOrderTest.java @@ -58,7 +58,7 @@ public class RegistryLoadOrderTest extends AbstractTestingBase { minecraftRegistry.register(ResourceKey.create(resourceKey, MinecraftKey.tryBuild("bukkit", "test-two")), new MinecraftTestType(), new RegistrationInfo(Optional.empty(), Lifecycle.experimental())); minecraftRegistry.freeze(); - registry = new CraftRegistry<>(keyedClass, minecraftRegistry, minecraftToBukkit); + registry = new CraftRegistry<>(keyedClass, minecraftRegistry, minecraftToBukkit, (namespacedKey, apiVersion) -> namespacedKey); testClassNotLoaded(init.get()); Object testOne = registry.get(new NamespacedKey("bukkit", "test-one"));