#1519: Add RegistryAware to indicate better that not all registry items are registered

This commit is contained in:
DerFrZocker 2025-01-13 19:39:17 +11:00 committed by md_5
parent df01cf867a
commit 9973ccccfd
No known key found for this signature in database
GPG Key ID: E8E901AC7C617C11
27 changed files with 434 additions and 934 deletions

View File

@ -1,7 +1,6 @@
package org.bukkit.craftbukkit; package org.bukkit.craftbukkit;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import java.util.Locale;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry; import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
@ -9,10 +8,10 @@ import net.minecraft.world.entity.decoration.PaintingVariant;
import org.bukkit.Art; import org.bukkit.Art;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class CraftArt implements Art, Handleable<PaintingVariant> { public class CraftArt extends CraftOldEnumRegistryItem<Art, PaintingVariant> implements Art {
private static int count = 0; private static int count = 0;
@ -41,89 +40,28 @@ public class CraftArt implements Art, Handleable<PaintingVariant> {
+ ", this can happen if a plugin creates its own painting variant with out properly registering it."); + ", this can happen if a plugin creates its own painting variant with out properly registering it.");
} }
private final NamespacedKey key; public CraftArt(NamespacedKey key, Holder<PaintingVariant> handle) {
private final PaintingVariant paintingVariant; super(key, handle, count++);
private final String name;
private final int ordinal;
public CraftArt(NamespacedKey key, PaintingVariant paintingVariant) {
this.key = key;
this.paintingVariant = paintingVariant;
// 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 art specific values.
// Custom arts will return the key with namespace. For a plugin this should look than like a new art
// (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 PaintingVariant getHandle() {
return paintingVariant;
} }
@Override @Override
public int getBlockWidth() { public int getBlockWidth() {
return paintingVariant.width(); return getHandle().width();
} }
@Override @Override
public int getBlockHeight() { public int getBlockHeight() {
return paintingVariant.height(); return getHandle().height();
} }
@Override @Override
public int getId() { public int getId() {
return CraftRegistry.getMinecraftRegistry(Registries.PAINTING_VARIANT).getId(paintingVariant); return CraftRegistry.getMinecraftRegistry(Registries.PAINTING_VARIANT).getId(getHandle());
} }
@NotNull @NotNull
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
}
@Override
public int compareTo(@NotNull Art art) {
return ordinal - art.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 CraftArt otherArt)) {
return false;
}
return getKey().equals(otherArt.getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
} }
} }

View File

@ -1,15 +1,15 @@
package org.bukkit.craftbukkit; package org.bukkit.craftbukkit;
import java.util.Locale; import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.world.level.material.FluidType; import net.minecraft.world.level.material.FluidType;
import org.bukkit.Fluid; import org.bukkit.Fluid;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class CraftFluid implements Fluid, Handleable<FluidType> { public class CraftFluid extends CraftOldEnumRegistryItem<Fluid, FluidType> implements Fluid {
private static int count = 0; private static int count = 0;
@ -21,74 +21,13 @@ public class CraftFluid implements Fluid, Handleable<FluidType> {
return CraftRegistry.bukkitToMinecraft(bukkit); return CraftRegistry.bukkitToMinecraft(bukkit);
} }
private final NamespacedKey key; public CraftFluid(NamespacedKey key, Holder<FluidType> handle) {
private final FluidType fluidType; super(key, handle, count++);
private final String name;
private final int ordinal;
public CraftFluid(NamespacedKey key, FluidType fluidType) {
this.key = key;
this.fluidType = fluidType;
// 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 fluid specific values.
// Custom fluids will return the key with namespace. For a plugin this should look than like a new fluid
// (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 FluidType getHandle() {
return fluidType;
} }
@NotNull @NotNull
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
}
@Override
public int compareTo(@NotNull Fluid fluid) {
return ordinal - fluid.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 CraftFluid otherFluid)) {
return false;
}
return getKey().equals(otherFluid.getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
} }
} }

View File

@ -1,11 +1,13 @@
package org.bukkit.craftbukkit; package org.bukkit.craftbukkit;
import com.google.common.base.Preconditions;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import org.bukkit.GameEvent; import org.bukkit.GameEvent;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.util.Handleable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class CraftGameEvent extends GameEvent implements Handleable<net.minecraft.world.level.gameevent.GameEvent> { public class CraftGameEvent extends GameEvent implements Handleable<net.minecraft.world.level.gameevent.GameEvent> {
@ -33,7 +35,7 @@ public class CraftGameEvent extends GameEvent implements Handleable<net.minecraf
@NotNull @NotNull
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
} }
@Override @Override
@ -58,4 +60,22 @@ public class CraftGameEvent extends GameEvent implements Handleable<net.minecraf
public String toString() { public String toString() {
return "CraftGameEvent{key=" + key + "}"; return "CraftGameEvent{key=" + key + "}";
} }
@NotNull
@Override
public NamespacedKey getKeyOrThrow() {
Preconditions.checkState(isRegistered(), "Cannot get key of this registry item, because it is not registered. Use #isRegistered() before calling this method.");
return this.key;
}
@Nullable
@Override
public NamespacedKey getKeyOrNull() {
return this.key;
}
@Override
public boolean isRegistered() {
return this.key != null;
}
} }

View File

@ -8,10 +8,10 @@ import net.minecraft.network.chat.contents.TranslatableContents;
import org.bukkit.JukeboxSong; import org.bukkit.JukeboxSong;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.registry.CraftRegistryItem;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class CraftJukeboxSong implements JukeboxSong, Handleable<net.minecraft.world.item.JukeboxSong> { public class CraftJukeboxSong extends CraftRegistryItem<net.minecraft.world.item.JukeboxSong> implements JukeboxSong {
public static JukeboxSong minecraftToBukkit(net.minecraft.world.item.JukeboxSong minecraft) { public static JukeboxSong minecraftToBukkit(net.minecraft.world.item.JukeboxSong minecraft) {
return CraftRegistry.minecraftToBukkit(minecraft, Registries.JUKEBOX_SONG, Registry.JUKEBOX_SONG); return CraftRegistry.minecraftToBukkit(minecraft, Registries.JUKEBOX_SONG, Registry.JUKEBOX_SONG);
@ -38,28 +38,19 @@ public class CraftJukeboxSong implements JukeboxSong, Handleable<net.minecraft.w
+ ", this can happen if a plugin creates its own trim pattern without properly registering it."); + ", this can happen if a plugin creates its own trim pattern without properly registering it.");
} }
private final NamespacedKey key; public CraftJukeboxSong(NamespacedKey key, Holder<net.minecraft.world.item.JukeboxSong> handle) {
private final net.minecraft.world.item.JukeboxSong handle; super(key, handle);
public CraftJukeboxSong(NamespacedKey key, net.minecraft.world.item.JukeboxSong handle) {
this.key = key;
this.handle = handle;
}
@Override
public net.minecraft.world.item.JukeboxSong getHandle() {
return handle;
} }
@Override @Override
@NotNull @NotNull
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
} }
@NotNull @NotNull
@Override @Override
public String getTranslationKey() { public String getTranslationKey() {
return ((TranslatableContents) handle.description().getContents()).getKey(); return ((TranslatableContents) getHandle().description().getContents()).getKey();
} }
} }

View File

@ -16,6 +16,7 @@ import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.CraftNamespacedKey; import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.util.HolderHandleable; import org.bukkit.craftbukkit.util.HolderHandleable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class CraftMusicInstrument extends MusicInstrument implements HolderHandleable<Instrument> { public class CraftMusicInstrument extends MusicInstrument implements HolderHandleable<Instrument> {
@ -92,11 +93,7 @@ public class CraftMusicInstrument extends MusicInstrument implements HolderHandl
@NotNull @NotNull
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
if (key == null) { return getKeyOrThrow();
throw new IllegalStateException("Music instrument is not registered.");
}
return key;
} }
@Override @Override
@ -129,4 +126,22 @@ public class CraftMusicInstrument extends MusicInstrument implements HolderHandl
public String toString() { public String toString() {
return "CraftMusicInstrument{key=" + key + ", handle=" + handle + "}"; return "CraftMusicInstrument{key=" + key + ", handle=" + handle + "}";
} }
@NotNull
@Override
public NamespacedKey getKeyOrThrow() {
Preconditions.checkState(isRegistered(), "Cannot get key of this registry item, because it is not registered. Use #isRegistered() before calling this method.");
return this.key;
}
@Nullable
@Override
public NamespacedKey getKeyOrNull() {
return this.key;
}
@Override
public boolean isRegistered() {
return this.key != null;
}
} }

View File

@ -141,19 +141,19 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
*/ */
public static <B extends Keyed> Registry<?> createRegistry(Class<? super B> bukkitClass, IRegistryCustom registryHolder) { public static <B extends Keyed> Registry<?> createRegistry(Class<? super B> bukkitClass, IRegistryCustom registryHolder) {
if (bukkitClass == Art.class) { if (bukkitClass == Art.class) {
return new CraftRegistry<>(Art.class, registryHolder.lookupOrThrow(Registries.PAINTING_VARIANT), wrap(CraftArt::new), FieldRename.NONE); return new CraftRegistry<>(Art.class, registryHolder.lookupOrThrow(Registries.PAINTING_VARIANT), CraftArt::new, FieldRename.NONE);
} }
if (bukkitClass == Attribute.class) { if (bukkitClass == Attribute.class) {
return new CraftRegistry<>(Attribute.class, registryHolder.lookupOrThrow(Registries.ATTRIBUTE), wrap(CraftAttribute::new), FieldRename.ATTRIBUTE_RENAME); return new CraftRegistry<>(Attribute.class, registryHolder.lookupOrThrow(Registries.ATTRIBUTE), CraftAttribute::new, FieldRename.ATTRIBUTE_RENAME);
} }
if (bukkitClass == Biome.class) { if (bukkitClass == Biome.class) {
return new CraftRegistry<>(Biome.class, registryHolder.lookupOrThrow(Registries.BIOME), wrap(CraftBiome::new), FieldRename.BIOME_RENAME); return new CraftRegistry<>(Biome.class, registryHolder.lookupOrThrow(Registries.BIOME), CraftBiome::new, FieldRename.BIOME_RENAME);
} }
if (bukkitClass == Enchantment.class) { if (bukkitClass == Enchantment.class) {
return new CraftRegistry<>(Enchantment.class, registryHolder.lookupOrThrow(Registries.ENCHANTMENT), wrap(CraftEnchantment::new), FieldRename.ENCHANTMENT_RENAME); return new CraftRegistry<>(Enchantment.class, registryHolder.lookupOrThrow(Registries.ENCHANTMENT), wrap(CraftEnchantment::new), FieldRename.ENCHANTMENT_RENAME);
} }
if (bukkitClass == Fluid.class) { if (bukkitClass == Fluid.class) {
return new CraftRegistry<>(Fluid.class, registryHolder.lookupOrThrow(Registries.FLUID), wrap(CraftFluid::new), FieldRename.NONE); return new CraftRegistry<>(Fluid.class, registryHolder.lookupOrThrow(Registries.FLUID), CraftFluid::new, FieldRename.NONE);
} }
if (bukkitClass == GameEvent.class) { if (bukkitClass == GameEvent.class) {
return new CraftRegistry<>(GameEvent.class, registryHolder.lookupOrThrow(Registries.GAME_EVENT), wrap(CraftGameEvent::new), FieldRename.NONE); return new CraftRegistry<>(GameEvent.class, registryHolder.lookupOrThrow(Registries.GAME_EVENT), wrap(CraftGameEvent::new), FieldRename.NONE);
@ -162,13 +162,13 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
return new CraftRegistry<>(MusicInstrument.class, registryHolder.lookupOrThrow(Registries.INSTRUMENT), CraftMusicInstrument::new, FieldRename.NONE); return new CraftRegistry<>(MusicInstrument.class, registryHolder.lookupOrThrow(Registries.INSTRUMENT), CraftMusicInstrument::new, FieldRename.NONE);
} }
if (bukkitClass == MenuType.class) { if (bukkitClass == MenuType.class) {
return new CraftRegistry<>(MenuType.class, registryHolder.lookupOrThrow(Registries.MENU), wrap(CraftMenuType::new), FieldRename.NONE); return new CraftRegistry<>(MenuType.class, registryHolder.lookupOrThrow(Registries.MENU), CraftMenuType::new, FieldRename.NONE);
} }
if (bukkitClass == PotionEffectType.class) { if (bukkitClass == PotionEffectType.class) {
return new CraftRegistry<>(PotionEffectType.class, registryHolder.lookupOrThrow(Registries.MOB_EFFECT), wrap(CraftPotionEffectType::new), FieldRename.NONE); return new CraftRegistry<>(PotionEffectType.class, registryHolder.lookupOrThrow(Registries.MOB_EFFECT), wrap(CraftPotionEffectType::new), FieldRename.NONE);
} }
if (bukkitClass == Sound.class) { if (bukkitClass == Sound.class) {
return new CraftRegistry<>(Sound.class, registryHolder.lookupOrThrow(Registries.SOUND_EVENT), wrap(CraftSound::new), FieldRename.NONE); return new CraftRegistry<>(Sound.class, registryHolder.lookupOrThrow(Registries.SOUND_EVENT), CraftSound::new, FieldRename.NONE);
} }
if (bukkitClass == Structure.class) { if (bukkitClass == Structure.class) {
return new CraftRegistry<>(Structure.class, registryHolder.lookupOrThrow(Registries.STRUCTURE), wrap(CraftStructure::new), FieldRename.NONE); return new CraftRegistry<>(Structure.class, registryHolder.lookupOrThrow(Registries.STRUCTURE), wrap(CraftStructure::new), FieldRename.NONE);
@ -177,43 +177,43 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
return new CraftRegistry<>(StructureType.class, registryHolder.lookupOrThrow(Registries.STRUCTURE_TYPE), wrap(CraftStructureType::new), FieldRename.NONE); return new CraftRegistry<>(StructureType.class, registryHolder.lookupOrThrow(Registries.STRUCTURE_TYPE), wrap(CraftStructureType::new), FieldRename.NONE);
} }
if (bukkitClass == Villager.Type.class) { if (bukkitClass == Villager.Type.class) {
return new CraftRegistry<>(Villager.Type.class, registryHolder.lookupOrThrow(Registries.VILLAGER_TYPE), wrap(CraftVillager.CraftType::new), FieldRename.NONE); return new CraftRegistry<>(Villager.Type.class, registryHolder.lookupOrThrow(Registries.VILLAGER_TYPE), CraftVillager.CraftType::new, FieldRename.NONE);
} }
if (bukkitClass == Villager.Profession.class) { if (bukkitClass == Villager.Profession.class) {
return new CraftRegistry<>(Villager.Profession.class, registryHolder.lookupOrThrow(Registries.VILLAGER_PROFESSION), wrap(CraftVillager.CraftProfession::new), FieldRename.NONE); return new CraftRegistry<>(Villager.Profession.class, registryHolder.lookupOrThrow(Registries.VILLAGER_PROFESSION), CraftVillager.CraftProfession::new, FieldRename.NONE);
} }
if (bukkitClass == TrimMaterial.class) { if (bukkitClass == TrimMaterial.class) {
return new CraftRegistry<>(TrimMaterial.class, registryHolder.lookupOrThrow(Registries.TRIM_MATERIAL), wrap(CraftTrimMaterial::new), FieldRename.NONE); return new CraftRegistry<>(TrimMaterial.class, registryHolder.lookupOrThrow(Registries.TRIM_MATERIAL), CraftTrimMaterial::new, FieldRename.NONE);
} }
if (bukkitClass == TrimPattern.class) { if (bukkitClass == TrimPattern.class) {
return new CraftRegistry<>(TrimPattern.class, registryHolder.lookupOrThrow(Registries.TRIM_PATTERN), wrap(CraftTrimPattern::new), FieldRename.NONE); return new CraftRegistry<>(TrimPattern.class, registryHolder.lookupOrThrow(Registries.TRIM_PATTERN), CraftTrimPattern::new, FieldRename.NONE);
} }
if (bukkitClass == DamageType.class) { if (bukkitClass == DamageType.class) {
return new CraftRegistry<>(DamageType.class, registryHolder.lookupOrThrow(Registries.DAMAGE_TYPE), wrap(CraftDamageType::new), FieldRename.NONE); return new CraftRegistry<>(DamageType.class, registryHolder.lookupOrThrow(Registries.DAMAGE_TYPE), CraftDamageType::new, FieldRename.NONE);
} }
if (bukkitClass == JukeboxSong.class) { if (bukkitClass == JukeboxSong.class) {
return new CraftRegistry<>(JukeboxSong.class, registryHolder.lookupOrThrow(Registries.JUKEBOX_SONG), wrap(CraftJukeboxSong::new), FieldRename.NONE); return new CraftRegistry<>(JukeboxSong.class, registryHolder.lookupOrThrow(Registries.JUKEBOX_SONG), CraftJukeboxSong::new, FieldRename.NONE);
} }
if (bukkitClass == Wolf.Variant.class) { if (bukkitClass == Wolf.Variant.class) {
return new CraftRegistry<>(Wolf.Variant.class, registryHolder.lookupOrThrow(Registries.WOLF_VARIANT), wrap(CraftWolf.CraftVariant::new), FieldRename.NONE); return new CraftRegistry<>(Wolf.Variant.class, registryHolder.lookupOrThrow(Registries.WOLF_VARIANT), CraftWolf.CraftVariant::new, FieldRename.NONE);
} }
if (bukkitClass == BlockType.class) { if (bukkitClass == BlockType.class) {
return new CraftRegistry<>(BlockType.class, registryHolder.lookupOrThrow(Registries.BLOCK), wrap(CraftBlockType::new), FieldRename.NONE); return new CraftRegistry<>(BlockType.class, registryHolder.lookupOrThrow(Registries.BLOCK), CraftBlockType::new, FieldRename.NONE);
} }
if (bukkitClass == ItemType.class) { if (bukkitClass == ItemType.class) {
return new CraftRegistry<>(ItemType.class, registryHolder.lookupOrThrow(Registries.ITEM), wrap(CraftItemType::new), FieldRename.NONE); return new CraftRegistry<>(ItemType.class, registryHolder.lookupOrThrow(Registries.ITEM), CraftItemType::new, FieldRename.NONE);
} }
if (bukkitClass == Frog.Variant.class) { if (bukkitClass == Frog.Variant.class) {
return new CraftRegistry<>(Frog.Variant.class, registryHolder.lookupOrThrow(Registries.FROG_VARIANT), wrap(CraftFrog.CraftVariant::new), FieldRename.NONE); return new CraftRegistry<>(Frog.Variant.class, registryHolder.lookupOrThrow(Registries.FROG_VARIANT), CraftFrog.CraftVariant::new, FieldRename.NONE);
} }
if (bukkitClass == Cat.Type.class) { if (bukkitClass == Cat.Type.class) {
return new CraftRegistry<>(Cat.Type.class, registryHolder.lookupOrThrow(Registries.CAT_VARIANT), wrap(CraftCat.CraftType::new), FieldRename.NONE); return new CraftRegistry<>(Cat.Type.class, registryHolder.lookupOrThrow(Registries.CAT_VARIANT), CraftCat.CraftType::new, FieldRename.NONE);
} }
if (bukkitClass == MapCursor.Type.class) { if (bukkitClass == MapCursor.Type.class) {
return new CraftRegistry<>(MapCursor.Type.class, registryHolder.lookupOrThrow(Registries.MAP_DECORATION_TYPE), wrap(CraftMapCursor.CraftType::new), FieldRename.NONE); return new CraftRegistry<>(MapCursor.Type.class, registryHolder.lookupOrThrow(Registries.MAP_DECORATION_TYPE), CraftMapCursor.CraftType::new, FieldRename.NONE);
} }
if (bukkitClass == PatternType.class) { if (bukkitClass == PatternType.class) {
return new CraftRegistry<>(PatternType.class, registryHolder.lookupOrThrow(Registries.BANNER_PATTERN), wrap(CraftPatternType::new), FieldRename.NONE); return new CraftRegistry<>(PatternType.class, registryHolder.lookupOrThrow(Registries.BANNER_PATTERN), CraftPatternType::new, FieldRename.NONE);
} }
return null; return null;

View File

@ -1,7 +1,6 @@
package org.bukkit.craftbukkit; package org.bukkit.craftbukkit;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import java.util.Locale;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry; import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
@ -9,10 +8,10 @@ import net.minecraft.sounds.SoundEffect;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class CraftSound implements Sound, Handleable<SoundEffect> { public class CraftSound extends CraftOldEnumRegistryItem<Sound, SoundEffect> implements Sound {
private static int count = 0; private static int count = 0;
@ -37,74 +36,13 @@ public class CraftSound implements Sound, Handleable<SoundEffect> {
+ ", this can happen if a plugin creates its own sound effect with out properly registering it."); + ", this can happen if a plugin creates its own sound effect with out properly registering it.");
} }
private final NamespacedKey key; public CraftSound(NamespacedKey key, Holder<SoundEffect> handle) {
private final SoundEffect soundEffect; super(key, handle, count++);
private final String name;
private final int ordinal;
public CraftSound(NamespacedKey key, SoundEffect soundEffect) {
this.key = key;
this.soundEffect = soundEffect;
// 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 sound specific values.
// Custom sounds will return the key with namespace. For a plugin this should look than like a new sound
// (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).replace('.', '_');
} else {
this.name = key.toString();
}
this.ordinal = count++;
}
@Override
public SoundEffect getHandle() {
return soundEffect;
} }
@NotNull @NotNull
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
}
@Override
public int compareTo(@NotNull Sound sound) {
return ordinal - sound.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 CraftSound otherSound)) {
return false;
}
return getKey().equals(otherSound.getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
} }
} }

View File

@ -11,11 +11,11 @@ import org.bukkit.Registry;
import org.bukkit.attribute.Attribute; import org.bukkit.attribute.Attribute;
import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.legacy.FieldRename; import org.bukkit.craftbukkit.legacy.FieldRename;
import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
import org.bukkit.craftbukkit.util.ApiVersion; import org.bukkit.craftbukkit.util.ApiVersion;
import org.bukkit.craftbukkit.util.Handleable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class CraftAttribute implements Attribute, Handleable<AttributeBase> { public class CraftAttribute extends CraftOldEnumRegistryItem<Attribute, AttributeBase> implements Attribute {
private static int count = 0; private static int count = 0;
@ -63,80 +63,19 @@ public class CraftAttribute implements Attribute, Handleable<AttributeBase> {
return bukkit.getKey().toString(); return bukkit.getKey().toString();
} }
private final NamespacedKey key; public CraftAttribute(NamespacedKey key, Holder<AttributeBase> handle) {
private final AttributeBase attributeBase; super(key, handle, count++);
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 @NotNull
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
} }
@NotNull @NotNull
@Override @Override
public String getTranslationKey() { public String getTranslationKey() {
return attributeBase.getDescriptionId(); return getHandle().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();
} }
} }

View File

@ -1,6 +1,5 @@
package org.bukkit.craftbukkit.block; package org.bukkit.craftbukkit.block;
import java.util.Locale;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry; import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
@ -9,10 +8,10 @@ import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class CraftBiome implements Biome, Handleable<BiomeBase> { public class CraftBiome extends CraftOldEnumRegistryItem<Biome, BiomeBase> implements Biome {
private static int count = 0; private static int count = 0;
@ -47,74 +46,13 @@ public class CraftBiome implements Biome, Handleable<BiomeBase> {
+ ", this can happen if a plugin creates its own biome base with out properly registering it."); + ", this can happen if a plugin creates its own biome base with out properly registering it.");
} }
private final NamespacedKey key; public CraftBiome(NamespacedKey key, Holder<BiomeBase> handle) {
private final BiomeBase biomeBase; super(key, handle, count++);
private final String name;
private final int ordinal;
public CraftBiome(NamespacedKey key, BiomeBase biomeBase) {
this.key = key;
this.biomeBase = biomeBase;
// 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 biome specific values.
// Custom biomes will return the key with namespace. For a plugin this should look than like a new biome
// (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 BiomeBase getHandle() {
return biomeBase;
} }
@NotNull @NotNull
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
}
@Override
public int compareTo(@NotNull Biome biome) {
return ordinal - biome.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 CraftBiome otherBiome)) {
return false;
}
return getKey().equals(otherBiome.getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
} }
} }

View File

@ -5,6 +5,7 @@ import java.lang.reflect.Method;
import java.util.Arrays; import java.util.Arrays;
import java.util.function.Consumer; import java.util.function.Consumer;
import net.minecraft.core.BlockPosition; import net.minecraft.core.BlockPosition;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.world.EnumHand; import net.minecraft.world.EnumHand;
import net.minecraft.world.entity.player.EntityHuman; import net.minecraft.world.entity.player.EntityHuman;
@ -28,15 +29,13 @@ import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.inventory.CraftItemType; import org.bukkit.craftbukkit.inventory.CraftItemType;
import org.bukkit.craftbukkit.registry.CraftRegistryItem;
import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.inventory.ItemType; import org.bukkit.inventory.ItemType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>, Handleable<Block> { public class CraftBlockType<B extends BlockData> extends CraftRegistryItem<Block> implements BlockType.Typed<B> {
private final NamespacedKey key;
private final Block block;
private final Class<B> blockDataClass; private final Class<B> blockDataClass;
private final boolean interactable; private final boolean interactable;
@ -90,16 +89,10 @@ public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>,
return hasMethod; return hasMethod;
} }
public CraftBlockType(NamespacedKey key, Block block) { public CraftBlockType(NamespacedKey key, Holder<Block> handle) {
this.key = key; super(key, handle);
this.block = block; this.blockDataClass = (Class<B>) CraftBlockData.fromData(getHandle().defaultBlockState()).getClass().getInterfaces()[0];
this.blockDataClass = (Class<B>) CraftBlockData.fromData(block.defaultBlockState()).getClass().getInterfaces()[0]; this.interactable = isInteractable(getHandle());
this.interactable = isInteractable(block);
}
@Override
public Block getHandle() {
return block;
} }
@NotNull @NotNull
@ -113,7 +106,7 @@ public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>,
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <Other extends BlockData> Typed<Other> typed(@NotNull Class<Other> blockDataType) { public <Other extends BlockData> Typed<Other> typed(@NotNull Class<Other> blockDataType) {
if (blockDataType.isAssignableFrom(this.blockDataClass)) return (Typed<Other>) this; if (blockDataType.isAssignableFrom(this.blockDataClass)) return (Typed<Other>) this;
throw new IllegalArgumentException("Cannot type block type " + this.key.toString() + " to blockdata type " + blockDataType.getSimpleName()); throw new IllegalArgumentException("Cannot type block type " + (isRegistered() ? getKeyOrThrow() : toString()) + " to blockdata type " + blockDataType.getSimpleName());
} }
@Override @Override
@ -122,7 +115,7 @@ public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>,
return true; return true;
} }
return block.asItem() != Items.AIR; return getHandle().asItem() != Items.AIR;
} }
@NotNull @NotNull
@ -132,8 +125,8 @@ public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>,
return ItemType.AIR; return ItemType.AIR;
} }
Item item = block.asItem(); Item item = getHandle().asItem();
Preconditions.checkArgument(item != Items.AIR, "The block type %s has no corresponding item type", getKey()); Preconditions.checkArgument(item != Items.AIR, "The block type %s has no corresponding item type", (isRegistered() ? getKeyOrThrow() : toString()));
return CraftItemType.minecraftToBukkitNew(item); return CraftItemType.minecraftToBukkitNew(item);
} }
@ -165,12 +158,12 @@ public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>,
@Override @Override
public boolean isSolid() { public boolean isSolid() {
return block.defaultBlockState().blocksMotion(); return getHandle().defaultBlockState().blocksMotion();
} }
@Override @Override
public boolean isAir() { public boolean isAir() {
return block.defaultBlockState().isAir(); return getHandle().defaultBlockState().isAir();
} }
@Override @Override
@ -181,22 +174,22 @@ public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>,
@Override @Override
public boolean isFlammable() { public boolean isFlammable() {
return block.defaultBlockState().ignitedByLava(); return getHandle().defaultBlockState().ignitedByLava();
} }
@Override @Override
public boolean isBurnable() { public boolean isBurnable() {
return ((BlockFire) Blocks.FIRE).igniteOdds.getOrDefault(block, 0) > 0; return ((BlockFire) Blocks.FIRE).igniteOdds.getOrDefault(getHandle(), 0) > 0;
} }
@Override @Override
public boolean isOccluding() { public boolean isOccluding() {
return block.defaultBlockState().isRedstoneConductor(BlockAccessAir.INSTANCE, BlockPosition.ZERO); return getHandle().defaultBlockState().isRedstoneConductor(BlockAccessAir.INSTANCE, BlockPosition.ZERO);
} }
@Override @Override
public boolean hasGravity() { public boolean hasGravity() {
return block instanceof Fallable; return getHandle() instanceof Fallable;
} }
@Override @Override
@ -206,32 +199,32 @@ public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>,
@Override @Override
public float getHardness() { public float getHardness() {
return block.defaultBlockState().destroySpeed; return getHandle().defaultBlockState().destroySpeed;
} }
@Override @Override
public float getBlastResistance() { public float getBlastResistance() {
return block.getExplosionResistance(); return getHandle().getExplosionResistance();
} }
@Override @Override
public float getSlipperiness() { public float getSlipperiness() {
return block.getFriction(); return getHandle().getFriction();
} }
@NotNull @NotNull
@Override @Override
public String getTranslationKey() { public String getTranslationKey() {
return block.getDescriptionId(); return getHandle().getDescriptionId();
} }
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
} }
@Override @Override
public Material asMaterial() { public Material asMaterial() {
return Registry.MATERIAL.get(this.key); return Registry.MATERIAL.get(getKeyOrThrow());
} }
} }

View File

@ -1,7 +1,6 @@
package org.bukkit.craftbukkit.block.banner; package org.bukkit.craftbukkit.block.banner;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import java.util.Locale;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry; import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
@ -10,9 +9,9 @@ import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.block.banner.PatternType; import org.bukkit.block.banner.PatternType;
import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
public class CraftPatternType implements PatternType, Handleable<EnumBannerPatternType> { public class CraftPatternType extends CraftOldEnumRegistryItem<PatternType, EnumBannerPatternType> implements PatternType {
private static int count = 0; private static int count = 0;
@ -41,73 +40,13 @@ public class CraftPatternType implements PatternType, Handleable<EnumBannerPatte
+ ", this can happen if a plugin creates its own banner pattern without properly registering it."); + ", this can happen if a plugin creates its own banner pattern without properly registering it.");
} }
private final NamespacedKey key; public CraftPatternType(NamespacedKey key, Holder<EnumBannerPatternType> handle) {
private final EnumBannerPatternType bannerPatternType; super(key, handle, count++);
private final String name;
private final int ordinal;
public CraftPatternType(NamespacedKey key, EnumBannerPatternType bannerPatternType) {
this.key = key;
this.bannerPatternType = bannerPatternType;
// 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 pattern type specific values.
// Custom pattern types will return the key with namespace. For a plugin this should look than like a new pattern type
// (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 EnumBannerPatternType getHandle() {
return bannerPatternType;
} }
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
}
@Override
public int compareTo(PatternType patternType) {
return ordinal - patternType.ordinal();
}
@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 CraftPatternType)) {
return false;
}
return getKey().equals(((PatternType) other).getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
} }
@Override @Override

View File

@ -7,25 +7,16 @@ import net.minecraft.core.registries.Registries;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.registry.CraftRegistryItem;
import org.bukkit.damage.DamageEffect; import org.bukkit.damage.DamageEffect;
import org.bukkit.damage.DamageScaling; import org.bukkit.damage.DamageScaling;
import org.bukkit.damage.DamageType; import org.bukkit.damage.DamageType;
import org.bukkit.damage.DeathMessageType; import org.bukkit.damage.DeathMessageType;
public class CraftDamageType implements DamageType, Handleable<net.minecraft.world.damagesource.DamageType> { public class CraftDamageType extends CraftRegistryItem<net.minecraft.world.damagesource.DamageType> implements DamageType {
private final NamespacedKey key; public CraftDamageType(NamespacedKey key, Holder<net.minecraft.world.damagesource.DamageType> handle) {
private final net.minecraft.world.damagesource.DamageType damageType; super(key, handle);
public CraftDamageType(NamespacedKey key, net.minecraft.world.damagesource.DamageType damageType) {
this.key = key;
this.damageType = damageType;
}
@Override
public net.minecraft.world.damagesource.DamageType getHandle() {
return this.damageType;
} }
@Override @Override
@ -55,12 +46,7 @@ public class CraftDamageType implements DamageType, Handleable<net.minecraft.wor
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return this.key; return getKeyOrThrow();
}
@Override
public String toString() {
return "CraftDamageType{" + "key=" + this.getKey() + ",damageScaling=" + this.getDamageScaling() + ",damageEffect=" + this.getDamageEffect() + ",deathMessageType=" + this.getDeathMessageType() + ",exhaustion=" + this.getExhaustion() + "}";
} }
public static DeathMessageType deathMessageTypeToBukkit(net.minecraft.world.damagesource.DeathMessageType deathMessageType) { public static DeathMessageType deathMessageTypeToBukkit(net.minecraft.world.damagesource.DeathMessageType deathMessageType) {

View File

@ -17,6 +17,8 @@ import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget; import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.enchantments.EnchantmentWrapper; import org.bukkit.enchantments.EnchantmentWrapper;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class CraftEnchantment extends Enchantment implements Handleable<net.minecraft.world.item.enchantment.Enchantment> { public class CraftEnchantment extends Enchantment implements Handleable<net.minecraft.world.item.enchantment.Enchantment> {
@ -70,7 +72,7 @@ public class CraftEnchantment extends Enchantment implements Handleable<net.mine
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
} }
@Override @Override
@ -173,4 +175,22 @@ public class CraftEnchantment extends Enchantment implements Handleable<net.mine
public String toString() { public String toString() {
return "CraftEnchantment[" + getKey() + "]"; return "CraftEnchantment[" + getKey() + "]";
} }
@NotNull
@Override
public NamespacedKey getKeyOrThrow() {
Preconditions.checkState(isRegistered(), "Cannot get key of this registry item, because it is not registered. Use #isRegistered() before calling this method.");
return this.key;
}
@Nullable
@Override
public NamespacedKey getKeyOrNull() {
return this.key;
}
@Override
public boolean isRegistered() {
return this.key != null;
}
} }

View File

@ -1,7 +1,6 @@
package org.bukkit.craftbukkit.entity; package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import java.util.Locale;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.animal.CatVariant; import net.minecraft.world.entity.animal.CatVariant;
@ -12,7 +11,7 @@ import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
import org.bukkit.entity.Cat; import org.bukkit.entity.Cat;
public class CraftCat extends CraftTameableAnimal implements Cat { public class CraftCat extends CraftTameableAnimal implements Cat {
@ -53,7 +52,7 @@ public class CraftCat extends CraftTameableAnimal implements Cat {
getHandle().setCollarColor(EnumColor.byId(color.getWoolData())); getHandle().setCollarColor(EnumColor.byId(color.getWoolData()));
} }
public static class CraftType implements Type, Handleable<CatVariant> { public static class CraftType extends CraftOldEnumRegistryItem<Type, CatVariant> implements Type {
private static int count = 0; private static int count = 0;
public static Type minecraftToBukkit(CatVariant minecraft) { public static Type minecraftToBukkit(CatVariant minecraft) {
@ -72,73 +71,13 @@ public class CraftCat extends CraftTameableAnimal implements Cat {
return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.CAT_VARIANT); return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.CAT_VARIANT);
} }
private final NamespacedKey key; public CraftType(NamespacedKey key, Holder<CatVariant> handle) {
private final CatVariant catVariant; super(key, handle, count++);
private final String name;
private final int ordinal;
public CraftType(NamespacedKey key, CatVariant catVariant) {
this.key = key;
this.catVariant = catVariant;
// For backwards compatibility, minecraft values will still return the uppercase name without the namespace,
// in case plugins use for example the name as key in a config file to receive type specific values.
// Custom types will return the key with namespace. For a plugin this should look than like a new type
// (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 CatVariant getHandle() {
return catVariant;
} }
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
}
@Override
public int compareTo(Type variant) {
return ordinal - variant.ordinal();
}
@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 CraftType)) {
return false;
}
return getKey().equals(((CraftType) other).getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
} }
} }
} }

View File

@ -1,7 +1,6 @@
package org.bukkit.craftbukkit.entity; package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import java.util.Locale;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.animal.FrogVariant; import net.minecraft.world.entity.animal.FrogVariant;
@ -10,7 +9,7 @@ import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
public class CraftFrog extends CraftAnimals implements org.bukkit.entity.Frog { public class CraftFrog extends CraftAnimals implements org.bukkit.entity.Frog {
@ -55,7 +54,7 @@ public class CraftFrog extends CraftAnimals implements org.bukkit.entity.Frog {
getHandle().setVariant(CraftVariant.bukkitToMinecraftHolder(variant)); getHandle().setVariant(CraftVariant.bukkitToMinecraftHolder(variant));
} }
public static class CraftVariant implements Variant, Handleable<FrogVariant> { public static class CraftVariant extends CraftOldEnumRegistryItem<Variant, FrogVariant> implements Variant {
private static int count = 0; private static int count = 0;
public static Variant minecraftToBukkit(FrogVariant minecraft) { public static Variant minecraftToBukkit(FrogVariant minecraft) {
@ -74,73 +73,13 @@ public class CraftFrog extends CraftAnimals implements org.bukkit.entity.Frog {
return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.FROG_VARIANT); return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.FROG_VARIANT);
} }
private final NamespacedKey key; public CraftVariant(NamespacedKey key, Holder<FrogVariant> handle) {
private final FrogVariant frogVariant; super(key, handle, count++);
private final String name;
private final int ordinal;
public CraftVariant(NamespacedKey key, FrogVariant frogVariant) {
this.key = key;
this.frogVariant = frogVariant;
// For backwards compatibility, minecraft values will still return the uppercase name without the namespace,
// in case plugins use for example the name as key in a config file to receive variant specific values.
// Custom variants will return the key with namespace. For a plugin this should look than like a new variant
// (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 FrogVariant getHandle() {
return frogVariant;
} }
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
}
@Override
public int compareTo(Variant variant) {
return ordinal - variant.ordinal();
}
@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 CraftVariant)) {
return false;
}
return getKey().equals(((Variant) other).getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
} }
} }
} }

View File

@ -2,13 +2,13 @@ package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import net.minecraft.core.BlockPosition; import net.minecraft.core.BlockPosition;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.ai.gossip.ReputationType; import net.minecraft.world.entity.ai.gossip.ReputationType;
import net.minecraft.world.entity.monster.EntityZombie; import net.minecraft.world.entity.monster.EntityZombie;
@ -23,6 +23,7 @@ import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
import org.bukkit.craftbukkit.util.CraftLocation; import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.entity.Villager; import org.bukkit.entity.Villager;
@ -208,7 +209,7 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
return getHandle().gossipDecayInterval; return getHandle().gossipDecayInterval;
} }
public static class CraftType implements Type, Handleable<VillagerType> { public static class CraftType extends CraftOldEnumRegistryItem<Type, VillagerType> implements Type {
private static int count = 0; private static int count = 0;
public static Type minecraftToBukkit(VillagerType minecraft) { public static Type minecraftToBukkit(VillagerType minecraft) {
@ -219,77 +220,17 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
return CraftRegistry.bukkitToMinecraft(bukkit); return CraftRegistry.bukkitToMinecraft(bukkit);
} }
private final NamespacedKey key; public CraftType(NamespacedKey key, Holder<VillagerType> handle) {
private final VillagerType villagerType; super(key, handle, count++);
private final String name;
private final int ordinal;
public CraftType(NamespacedKey key, VillagerType villagerType) {
this.key = key;
this.villagerType = villagerType;
// For backwards compatibility, minecraft values will still return the uppercase name without the namespace,
// in case plugins use for example the name as key in a config file to receive type specific values.
// Custom types will return the key with namespace. For a plugin this should look than like a new type
// (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 VillagerType getHandle() {
return villagerType;
} }
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
}
@Override
public int compareTo(Type type) {
return ordinal - type.ordinal();
}
@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 CraftType)) {
return false;
}
return getKey().equals(((Type) other).getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
} }
} }
public static class CraftProfession implements Profession, Handleable<VillagerProfession> { public static class CraftProfession extends CraftOldEnumRegistryItem<Profession, VillagerProfession> implements Profession {
private static int count = 0; private static int count = 0;
public static Profession minecraftToBukkit(VillagerProfession minecraft) { public static Profession minecraftToBukkit(VillagerProfession minecraft) {
@ -300,73 +241,13 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
return CraftRegistry.bukkitToMinecraft(bukkit); return CraftRegistry.bukkitToMinecraft(bukkit);
} }
private final NamespacedKey key; public CraftProfession(NamespacedKey key, Holder<VillagerProfession> handle) {
private final VillagerProfession villagerProfession; super(key, handle, count++);
private final String name;
private final int ordinal;
public CraftProfession(NamespacedKey key, VillagerProfession villagerProfession) {
this.key = key;
this.villagerProfession = villagerProfession;
// For backwards compatibility, minecraft values will still return the uppercase name without the namespace,
// in case plugins use for example the name as key in a config file to receive profession specific values.
// Custom professions will return the key with namespace. For a plugin this should look than like a new profession
// (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 VillagerProfession getHandle() {
return villagerProfession;
} }
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
}
@Override
public int compareTo(Profession profession) {
return ordinal - profession.ordinal();
}
@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 CraftProfession)) {
return false;
}
return getKey().equals(((Profession) other).getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
} }
} }

View File

@ -12,7 +12,7 @@ import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.registry.CraftRegistryItem;
import org.bukkit.entity.Wolf; import org.bukkit.entity.Wolf;
public class CraftWolf extends CraftTameableAnimal implements Wolf { public class CraftWolf extends CraftTameableAnimal implements Wolf {
@ -81,7 +81,7 @@ public class CraftWolf extends CraftTameableAnimal implements Wolf {
getHandle().setVariant(CraftVariant.bukkitToMinecraftHolder(variant)); getHandle().setVariant(CraftVariant.bukkitToMinecraftHolder(variant));
} }
public static class CraftVariant implements Variant, Handleable<WolfVariant> { public static class CraftVariant extends CraftRegistryItem<WolfVariant> implements Variant {
public static Variant minecraftToBukkit(WolfVariant minecraft) { public static Variant minecraftToBukkit(WolfVariant minecraft) {
return CraftRegistry.minecraftToBukkit(minecraft, Registries.WOLF_VARIANT, Registry.WOLF_VARIANT); return CraftRegistry.minecraftToBukkit(minecraft, Registries.WOLF_VARIANT, Registry.WOLF_VARIANT);
@ -108,45 +108,13 @@ public class CraftWolf extends CraftTameableAnimal implements Wolf {
+ ", this can happen if a plugin creates its own wolf variant with out properly registering it."); + ", this can happen if a plugin creates its own wolf variant with out properly registering it.");
} }
private final NamespacedKey key; public CraftVariant(NamespacedKey key, Holder<WolfVariant> handle) {
private final WolfVariant variant; super(key, handle);
public CraftVariant(NamespacedKey key, WolfVariant variant) {
this.key = key;
this.variant = variant;
}
@Override
public WolfVariant getHandle() {
return variant;
} }
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
}
@Override
public String toString() {
return key.toString();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof CraftVariant otherVariant)) {
return false;
}
return getKey().equals(otherVariant.getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
} }
} }
} }

View File

@ -1,5 +1,6 @@
package org.bukkit.craftbukkit.generator.structure; package org.bukkit.craftbukkit.generator.structure;
import com.google.common.base.Preconditions;
import com.google.common.base.Suppliers; import com.google.common.base.Suppliers;
import java.util.function.Supplier; import java.util.function.Supplier;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
@ -9,6 +10,8 @@ import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.generator.structure.Structure; import org.bukkit.generator.structure.Structure;
import org.bukkit.generator.structure.StructureType; import org.bukkit.generator.structure.StructureType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class CraftStructure extends Structure implements Handleable<net.minecraft.world.level.levelgen.structure.Structure> { public class CraftStructure extends Structure implements Handleable<net.minecraft.world.level.levelgen.structure.Structure> {
@ -42,6 +45,24 @@ public class CraftStructure extends Structure implements Handleable<net.minecraf
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
}
@NotNull
@Override
public NamespacedKey getKeyOrThrow() {
Preconditions.checkState(isRegistered(), "Cannot get key of this registry item, because it is not registered. Use #isRegistered() before calling this method.");
return this.key;
}
@Nullable
@Override
public NamespacedKey getKeyOrNull() {
return this.key;
}
@Override
public boolean isRegistered() {
return this.key != null;
} }
} }

View File

@ -1,11 +1,14 @@
package org.bukkit.craftbukkit.generator.structure; package org.bukkit.craftbukkit.generator.structure;
import com.google.common.base.Preconditions;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.generator.structure.StructureType; import org.bukkit.generator.structure.StructureType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class CraftStructureType extends StructureType implements Handleable<net.minecraft.world.level.levelgen.structure.StructureType<?>> { public class CraftStructureType extends StructureType implements Handleable<net.minecraft.world.level.levelgen.structure.StructureType<?>> {
@ -32,6 +35,24 @@ public class CraftStructureType extends StructureType implements Handleable<net.
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
}
@NotNull
@Override
public NamespacedKey getKeyOrThrow() {
Preconditions.checkState(isRegistered(), "Cannot get key of this registry item, because it is not registered. Use #isRegistered() before calling this method.");
return this.key;
}
@Nullable
@Override
public NamespacedKey getKeyOrNull() {
return this.key;
}
@Override
public boolean isRegistered() {
return this.key != null;
} }
} }

View File

@ -6,6 +6,7 @@ import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponents; import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
@ -26,8 +27,8 @@ import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.attribute.CraftAttribute; import org.bukkit.craftbukkit.attribute.CraftAttribute;
import org.bukkit.craftbukkit.attribute.CraftAttributeInstance; import org.bukkit.craftbukkit.attribute.CraftAttributeInstance;
import org.bukkit.craftbukkit.block.CraftBlockType; import org.bukkit.craftbukkit.block.CraftBlockType;
import org.bukkit.craftbukkit.registry.CraftRegistryItem;
import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.inventory.CreativeCategory; import org.bukkit.inventory.CreativeCategory;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -36,10 +37,8 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Handleable<Item> { public class CraftItemType<M extends ItemMeta> extends CraftRegistryItem<Item> implements ItemType.Typed<M> {
private final NamespacedKey key;
private final Item item;
private final Supplier<CraftItemMetas.ItemMetaData<M>> itemMetaData; private final Supplier<CraftItemMetas.ItemMetaData<M>> itemMetaData;
public static Material minecraftToBukkit(Item item) { public static Material minecraftToBukkit(Item item) {
@ -58,9 +57,8 @@ public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Han
return CraftRegistry.bukkitToMinecraft(bukkit); return CraftRegistry.bukkitToMinecraft(bukkit);
} }
public CraftItemType(NamespacedKey key, Item item) { public CraftItemType(NamespacedKey key, Holder<Item> handle) {
this.key = key; super(key, handle);
this.item = item;
this.itemMetaData = Suppliers.memoize(() -> CraftItemMetas.getItemMetaData(this)); this.itemMetaData = Suppliers.memoize(() -> CraftItemMetas.getItemMetaData(this));
} }
@ -76,7 +74,7 @@ public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Han
public <Other extends ItemMeta> Typed<Other> typed(@NotNull final Class<Other> itemMetaType) { public <Other extends ItemMeta> Typed<Other> typed(@NotNull final Class<Other> itemMetaType) {
if (itemMetaType.isAssignableFrom(this.itemMetaData.get().metaClass())) return (Typed<Other>) this; if (itemMetaType.isAssignableFrom(this.itemMetaData.get().metaClass())) return (Typed<Other>) this;
throw new IllegalArgumentException("Cannot type item type " + this.key.toString() + " to meta type " + itemMetaType.getSimpleName()); throw new IllegalArgumentException("Cannot type item type " + (isRegistered() ? getKeyOrThrow() : toString()) + " to meta type " + itemMetaType.getSimpleName());
} }
@NotNull @NotNull
@ -109,11 +107,6 @@ public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Han
return itemStack; return itemStack;
} }
@Override
public Item getHandle() {
return item;
}
public M getItemMeta(net.minecraft.world.item.ItemStack itemStack) { public M getItemMeta(net.minecraft.world.item.ItemStack itemStack) {
return itemMetaData.get().fromItemStack().apply(itemStack); return itemMetaData.get().fromItemStack().apply(itemStack);
} }
@ -124,14 +117,14 @@ public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Han
@Override @Override
public boolean hasBlockType() { public boolean hasBlockType() {
return item instanceof ItemBlock; return getHandle() instanceof ItemBlock;
} }
@NotNull @NotNull
@Override @Override
public BlockType getBlockType() { public BlockType getBlockType() {
if (!(item instanceof ItemBlock block)) { if (!(getHandle() instanceof ItemBlock block)) {
throw new IllegalStateException("The item type " + getKey() + " has no corresponding block type"); throw new IllegalStateException("The item type " + (isRegistered() ? getKeyOrThrow() : toString()) + " has no corresponding block type");
} }
return CraftBlockType.minecraftToBukkitNew(block.getBlock()); return CraftBlockType.minecraftToBukkitNew(block.getBlock());
@ -152,43 +145,43 @@ public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Han
if (this == AIR) { if (this == AIR) {
return 0; return 0;
} }
return item.components().getOrDefault(DataComponents.MAX_STACK_SIZE, 64); return getHandle().components().getOrDefault(DataComponents.MAX_STACK_SIZE, 64);
} }
@Override @Override
public short getMaxDurability() { public short getMaxDurability() {
return item.components().getOrDefault(DataComponents.MAX_DAMAGE, 0).shortValue(); return getHandle().components().getOrDefault(DataComponents.MAX_DAMAGE, 0).shortValue();
} }
@Override @Override
public boolean isEdible() { public boolean isEdible() {
return item.components().has(DataComponents.FOOD); return getHandle().components().has(DataComponents.FOOD);
} }
@Override @Override
public boolean isRecord() { public boolean isRecord() {
return item.components().has(DataComponents.JUKEBOX_PLAYABLE); return getHandle().components().has(DataComponents.JUKEBOX_PLAYABLE);
} }
@Override @Override
public boolean isFuel() { public boolean isFuel() {
return MinecraftServer.getServer().fuelValues().isFuel(new net.minecraft.world.item.ItemStack(item)); return MinecraftServer.getServer().fuelValues().isFuel(new net.minecraft.world.item.ItemStack(getHandle()));
} }
@Override @Override
public boolean isCompostable() { public boolean isCompostable() {
return BlockComposter.COMPOSTABLES.containsKey(item); return BlockComposter.COMPOSTABLES.containsKey(getHandle());
} }
@Override @Override
public float getCompostChance() { public float getCompostChance() {
Preconditions.checkArgument(isCompostable(), "The item type " + getKey() + " is not compostable"); Preconditions.checkArgument(isCompostable(), "The item type " + (isRegistered() ? getKeyOrThrow() : toString()) + " is not compostable");
return BlockComposter.COMPOSTABLES.getFloat(item); return BlockComposter.COMPOSTABLES.getFloat(getHandle());
} }
@Override @Override
public ItemType getCraftingRemainingItem() { public ItemType getCraftingRemainingItem() {
net.minecraft.world.item.ItemStack expectedItem = item.getCraftingRemainder(); net.minecraft.world.item.ItemStack expectedItem = getHandle().getCraftingRemainder();
return expectedItem.isEmpty() ? null : minecraftToBukkitNew(expectedItem.getItem()); return expectedItem.isEmpty() ? null : minecraftToBukkitNew(expectedItem.getItem());
} }
@ -201,7 +194,7 @@ public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Han
public Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers(EquipmentSlot slot) { public Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers(EquipmentSlot slot) {
ImmutableMultimap.Builder<Attribute, AttributeModifier> defaultAttributes = ImmutableMultimap.builder(); ImmutableMultimap.Builder<Attribute, AttributeModifier> defaultAttributes = ImmutableMultimap.builder();
ItemAttributeModifiers nmsDefaultAttributes = item.components().getOrDefault(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY); ItemAttributeModifiers nmsDefaultAttributes = getHandle().components().getOrDefault(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY);
nmsDefaultAttributes.forEach(CraftEquipmentSlot.getNMS(slot), (key, value) -> { nmsDefaultAttributes.forEach(CraftEquipmentSlot.getNMS(slot), (key, value) -> {
Attribute attribute = CraftAttribute.minecraftToBukkit(key.value()); Attribute attribute = CraftAttribute.minecraftToBukkit(key.value());
@ -225,16 +218,16 @@ public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Han
@NotNull @NotNull
@Override @Override
public String getTranslationKey() { public String getTranslationKey() {
return item.getDescriptionId(); return getHandle().getDescriptionId();
} }
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
} }
@Override @Override
public Material asMaterial() { public Material asMaterial() {
return Registry.MATERIAL.get(this.key); return Registry.MATERIAL.get(getKeyOrThrow());
} }
} }

View File

@ -9,29 +9,21 @@ import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.inventory.util.CraftMenus; import org.bukkit.craftbukkit.inventory.util.CraftMenus;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.registry.CraftRegistryItem;
import org.bukkit.entity.HumanEntity; import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.MenuType; import org.bukkit.inventory.MenuType;
import org.bukkit.inventory.view.builder.InventoryViewBuilder; import org.bukkit.inventory.view.builder.InventoryViewBuilder;
public class CraftMenuType<V extends InventoryView, B extends InventoryViewBuilder<V>> implements MenuType.Typed<V, B>, Handleable<Containers<?>> { public class CraftMenuType<V extends InventoryView, B extends InventoryViewBuilder<V>> extends CraftRegistryItem<Containers<?>> implements MenuType.Typed<V, B> {
private final NamespacedKey key;
private final Containers<?> handle;
private final Supplier<CraftMenus.MenuTypeData<V, B>> typeData; private final Supplier<CraftMenus.MenuTypeData<V, B>> typeData;
public CraftMenuType(NamespacedKey key, Containers<?> handle) { public CraftMenuType(NamespacedKey key, Holder<Containers<?>> handle) {
this.key = key; super(key, handle);
this.handle = handle;
this.typeData = Suppliers.memoize(() -> CraftMenus.getMenuTypeData(this)); this.typeData = Suppliers.memoize(() -> CraftMenus.getMenuTypeData(this));
} }
@Override
public Containers<?> getHandle() {
return this.handle;
}
@Override @Override
public V create(final HumanEntity player, final String title) { public V create(final HumanEntity player, final String title) {
return builder().title(title).build(player); return builder().title(title).build(player);
@ -53,7 +45,7 @@ public class CraftMenuType<V extends InventoryView, B extends InventoryViewBuild
return (Typed<V, B>) this; return (Typed<V, B>) this;
} }
throw new IllegalArgumentException("Cannot type InventoryView " + this.key.toString() + " to InventoryView type " + clazz.getSimpleName()); throw new IllegalArgumentException("Cannot type InventoryView " + (isRegistered() ? getKeyOrThrow() : toString()) + " to InventoryView type " + clazz.getSimpleName());
} }
@Override @Override
@ -63,7 +55,7 @@ public class CraftMenuType<V extends InventoryView, B extends InventoryViewBuild
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return this.key; return getKeyOrThrow();
} }
public static Containers<?> bukkitToMinecraft(MenuType bukkit) { public static Containers<?> bukkitToMinecraft(MenuType bukkit) {

View File

@ -8,11 +8,11 @@ import net.minecraft.network.chat.contents.TranslatableContents;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.registry.CraftRegistryItem;
import org.bukkit.inventory.meta.trim.TrimMaterial; import org.bukkit.inventory.meta.trim.TrimMaterial;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class CraftTrimMaterial implements TrimMaterial, Handleable<net.minecraft.world.item.equipment.trim.TrimMaterial> { public class CraftTrimMaterial extends CraftRegistryItem<net.minecraft.world.item.equipment.trim.TrimMaterial> implements TrimMaterial {
public static TrimMaterial minecraftToBukkit(net.minecraft.world.item.equipment.trim.TrimMaterial minecraft) { public static TrimMaterial minecraftToBukkit(net.minecraft.world.item.equipment.trim.TrimMaterial minecraft) {
return CraftRegistry.minecraftToBukkit(minecraft, Registries.TRIM_MATERIAL, Registry.TRIM_MATERIAL); return CraftRegistry.minecraftToBukkit(minecraft, Registries.TRIM_MATERIAL, Registry.TRIM_MATERIAL);
@ -39,28 +39,19 @@ public class CraftTrimMaterial implements TrimMaterial, Handleable<net.minecraft
+ ", this can happen if a plugin creates its own trim material without properly registering it."); + ", this can happen if a plugin creates its own trim material without properly registering it.");
} }
private final NamespacedKey key; public CraftTrimMaterial(NamespacedKey key, Holder<net.minecraft.world.item.equipment.trim.TrimMaterial> handle) {
private final net.minecraft.world.item.equipment.trim.TrimMaterial handle; super(key, handle);
public CraftTrimMaterial(NamespacedKey key, net.minecraft.world.item.equipment.trim.TrimMaterial handle) {
this.key = key;
this.handle = handle;
}
@Override
public net.minecraft.world.item.equipment.trim.TrimMaterial getHandle() {
return handle;
} }
@Override @Override
@NotNull @NotNull
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
} }
@NotNull @NotNull
@Override @Override
public String getTranslationKey() { public String getTranslationKey() {
return ((TranslatableContents) handle.description().getContents()).getKey(); return ((TranslatableContents) getHandle().description().getContents()).getKey();
} }
} }

View File

@ -8,11 +8,11 @@ import net.minecraft.network.chat.contents.TranslatableContents;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.registry.CraftRegistryItem;
import org.bukkit.inventory.meta.trim.TrimPattern; import org.bukkit.inventory.meta.trim.TrimPattern;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class CraftTrimPattern implements TrimPattern, Handleable<net.minecraft.world.item.equipment.trim.TrimPattern> { public class CraftTrimPattern extends CraftRegistryItem<net.minecraft.world.item.equipment.trim.TrimPattern> implements TrimPattern {
public static TrimPattern minecraftToBukkit(net.minecraft.world.item.equipment.trim.TrimPattern minecraft) { public static TrimPattern minecraftToBukkit(net.minecraft.world.item.equipment.trim.TrimPattern minecraft) {
return CraftRegistry.minecraftToBukkit(minecraft, Registries.TRIM_PATTERN, Registry.TRIM_PATTERN); return CraftRegistry.minecraftToBukkit(minecraft, Registries.TRIM_PATTERN, Registry.TRIM_PATTERN);
@ -39,28 +39,19 @@ public class CraftTrimPattern implements TrimPattern, Handleable<net.minecraft.w
+ ", this can happen if a plugin creates its own trim pattern without properly registering it."); + ", this can happen if a plugin creates its own trim pattern without properly registering it.");
} }
private final NamespacedKey key; public CraftTrimPattern(NamespacedKey key, Holder<net.minecraft.world.item.equipment.trim.TrimPattern> handle) {
private final net.minecraft.world.item.equipment.trim.TrimPattern handle; super(key, handle);
public CraftTrimPattern(NamespacedKey key, net.minecraft.world.item.equipment.trim.TrimPattern handle) {
this.key = key;
this.handle = handle;
}
@Override
public net.minecraft.world.item.equipment.trim.TrimPattern getHandle() {
return handle;
} }
@Override @Override
@NotNull @NotNull
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
} }
@NotNull @NotNull
@Override @Override
public String getTranslationKey() { public String getTranslationKey() {
return ((TranslatableContents) handle.description().getContents()).getKey(); return ((TranslatableContents) getHandle().description().getContents()).getKey();
} }
} }

View File

@ -1,18 +1,17 @@
package org.bukkit.craftbukkit.map; package org.bukkit.craftbukkit.map;
import java.util.Locale;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.world.level.saveddata.maps.MapDecorationType; import net.minecraft.world.level.saveddata.maps.MapDecorationType;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Registry; import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
import org.bukkit.map.MapCursor; import org.bukkit.map.MapCursor;
public final class CraftMapCursor { public final class CraftMapCursor {
public static final class CraftType implements MapCursor.Type, Handleable<MapDecorationType> { public static final class CraftType extends CraftOldEnumRegistryItem<MapCursor.Type, MapDecorationType> implements MapCursor.Type {
private static int count = 0; private static int count = 0;
@ -32,73 +31,13 @@ public final class CraftMapCursor {
return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.MAP_DECORATION_TYPE); return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.MAP_DECORATION_TYPE);
} }
private final NamespacedKey key; public CraftType(NamespacedKey key, Holder<MapDecorationType> handle) {
private final MapDecorationType mapDecorationType; super(key, handle, count++);
private final String name;
private final int ordinal;
public CraftType(NamespacedKey key, MapDecorationType mapDecorationType) {
this.key = key;
this.mapDecorationType = mapDecorationType;
// For backwards compatibility, minecraft values will still return the uppercase name without the namespace,
// in case plugins use for example the name as key in a config file to receive type specific values.
// Custom types will return the key with namespace. For a plugin this should look than like a new type
// (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 MapDecorationType getHandle() {
return mapDecorationType;
} }
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
}
@Override
public int compareTo(MapCursor.Type type) {
return ordinal - type.ordinal();
}
@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 CraftType)) {
return false;
}
return getKey().equals(((MapCursor.Type) other).getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
} }
@Override @Override

View File

@ -1,5 +1,6 @@
package org.bukkit.craftbukkit.potion; package org.bukkit.craftbukkit.potion;
import com.google.common.base.Preconditions;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.world.effect.MobEffectList; import net.minecraft.world.effect.MobEffectList;
@ -12,6 +13,7 @@ import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionEffectTypeCategory; import org.bukkit.potion.PotionEffectTypeCategory;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class CraftPotionEffectType extends PotionEffectType implements Handleable<MobEffectList> { public class CraftPotionEffectType extends PotionEffectType implements Handleable<MobEffectList> {
@ -49,7 +51,7 @@ public class CraftPotionEffectType extends PotionEffectType implements Handleabl
@NotNull @NotNull
@Override @Override
public NamespacedKey getKey() { public NamespacedKey getKey() {
return key; return getKeyOrThrow();
} }
@Override @Override
@ -151,4 +153,22 @@ public class CraftPotionEffectType extends PotionEffectType implements Handleabl
public String toString() { public String toString() {
return "CraftPotionEffectType[" + getKey() + "]"; return "CraftPotionEffectType[" + getKey() + "]";
} }
@NotNull
@Override
public NamespacedKey getKeyOrThrow() {
Preconditions.checkState(isRegistered(), "Cannot get key of this registry item, because it is not registered. Use #isRegistered() before calling this method.");
return this.key;
}
@Nullable
@Override
public NamespacedKey getKeyOrNull() {
return this.key;
}
@Override
public boolean isRegistered() {
return this.key != null;
}
} }

View File

@ -0,0 +1,67 @@
package org.bukkit.craftbukkit.registry;
import com.google.common.base.Preconditions;
import java.util.Locale;
import net.minecraft.core.Holder;
import org.bukkit.NamespacedKey;
import org.bukkit.util.OldEnum;
import org.jetbrains.annotations.NotNull;
@Deprecated
public abstract class CraftOldEnumRegistryItem<T extends OldEnum<T>, M> extends CraftRegistryItem<M> implements OldEnum<T> {
private final int ordinal;
private final String name;
protected CraftOldEnumRegistryItem(NamespacedKey key, Holder<M> handle, int ordinal) {
super(key, handle);
this.ordinal = ordinal;
if (isRegistered()) {
// 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 registry item specific values.
// Custom registry items will return the key with namespace. For a plugin this should look than like a new registry item
// (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();
}
} else {
this.name = null;
}
}
@Override
public int compareTo(@NotNull T other) {
checkState();
return ordinal - other.ordinal();
}
@NotNull
@Override
public String name() {
checkState();
return this.name;
}
@Override
public int ordinal() {
checkState();
return this.ordinal;
}
@Override
public String toString() {
// For backwards compatibility
if (isRegistered()) {
return name();
}
return super.toString();
}
private void checkState() {
Preconditions.checkState(isRegistered(), "Cannot call method for this registry item, because it is not registered. Use #isRegistered() before calling this method.");
}
}

View File

@ -0,0 +1,82 @@
package org.bukkit.craftbukkit.registry;
import com.google.common.base.Preconditions;
import java.util.Objects;
import net.minecraft.core.Holder;
import org.bukkit.NamespacedKey;
import org.bukkit.craftbukkit.util.HolderHandleable;
import org.bukkit.registry.RegistryAware;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class CraftRegistryItem<M> implements RegistryAware, HolderHandleable<M> {
private final NamespacedKey key;
private final Holder<M> handle;
protected CraftRegistryItem(NamespacedKey key, Holder<M> handle) {
this.key = key;
this.handle = handle;
}
@Override
public Holder<M> getHandleHolder() {
return this.handle;
}
@Override
public M getHandle() {
return getHandleHolder().value();
}
@NotNull
@Override
public NamespacedKey getKeyOrThrow() {
Preconditions.checkState(isRegistered(), "Cannot get key of this registry item, because it is not registered. Use #isRegistered() before calling this method.");
return this.key;
}
@Nullable
@Override
public NamespacedKey getKeyOrNull() {
return this.key;
}
@Override
public boolean isRegistered() {
return this.key != null;
}
@Override
public int hashCode() {
if (isRegistered()) {
return getKeyOrThrow().hashCode();
}
return getHandle().hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
CraftRegistryItem<?> other = (CraftRegistryItem<?>) obj;
if (isRegistered() || other.isRegistered()) {
return Objects.equals(this.key, other.key);
}
return Objects.equals(getHandle(), other.getHandle());
}
@Override
public String toString() {
return getClass().getSimpleName() + "{key=" + this.key + ", handle=" + this.handle + "}";
}
}