#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;
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,10 +8,10 @@ import net.minecraft.world.entity.decoration.PaintingVariant;
import org.bukkit.Art;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
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;
@ -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.");
}
private final NamespacedKey key;
private final PaintingVariant paintingVariant;
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;
public CraftArt(NamespacedKey key, Holder<PaintingVariant> handle) {
super(key, handle, count++);
}
@Override
public int getBlockWidth() {
return paintingVariant.width();
return getHandle().width();
}
@Override
public int getBlockHeight() {
return paintingVariant.height();
return getHandle().height();
}
@Override
public int getId() {
return CraftRegistry.getMinecraftRegistry(Registries.PAINTING_VARIANT).getId(paintingVariant);
return CraftRegistry.getMinecraftRegistry(Registries.PAINTING_VARIANT).getId(getHandle());
}
@NotNull
@Override
public NamespacedKey getKey() {
return key;
}
@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();
return getKeyOrThrow();
}
}

View File

@ -1,15 +1,15 @@
package org.bukkit.craftbukkit;
import java.util.Locale;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.level.material.FluidType;
import org.bukkit.Fluid;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
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;
@ -21,74 +21,13 @@ public class CraftFluid implements Fluid, Handleable<FluidType> {
return CraftRegistry.bukkitToMinecraft(bukkit);
}
private final NamespacedKey key;
private final FluidType fluidType;
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;
public CraftFluid(NamespacedKey key, Holder<FluidType> handle) {
super(key, handle, count++);
}
@NotNull
@Override
public NamespacedKey getKey() {
return key;
}
@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();
return getKeyOrThrow();
}
}

View File

@ -1,11 +1,13 @@
package org.bukkit.craftbukkit;
import com.google.common.base.Preconditions;
import net.minecraft.core.registries.Registries;
import org.bukkit.GameEvent;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.Handleable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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
@Override
public NamespacedKey getKey() {
return key;
return getKeyOrThrow();
}
@Override
@ -58,4 +60,22 @@ public class CraftGameEvent extends GameEvent implements Handleable<net.minecraf
public String toString() {
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.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.craftbukkit.registry.CraftRegistryItem;
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) {
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.");
}
private final NamespacedKey key;
private final net.minecraft.world.item.JukeboxSong 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;
public CraftJukeboxSong(NamespacedKey key, Holder<net.minecraft.world.item.JukeboxSong> handle) {
super(key, handle);
}
@Override
@NotNull
public NamespacedKey getKey() {
return key;
return getKeyOrThrow();
}
@NotNull
@Override
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.HolderHandleable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class CraftMusicInstrument extends MusicInstrument implements HolderHandleable<Instrument> {
@ -92,11 +93,7 @@ public class CraftMusicInstrument extends MusicInstrument implements HolderHandl
@NotNull
@Override
public NamespacedKey getKey() {
if (key == null) {
throw new IllegalStateException("Music instrument is not registered.");
}
return key;
return getKeyOrThrow();
}
@Override
@ -129,4 +126,22 @@ public class CraftMusicInstrument extends MusicInstrument implements HolderHandl
public String toString() {
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) {
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) {
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) {
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) {
return new CraftRegistry<>(Enchantment.class, registryHolder.lookupOrThrow(Registries.ENCHANTMENT), wrap(CraftEnchantment::new), FieldRename.ENCHANTMENT_RENAME);
}
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) {
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);
}
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) {
return new CraftRegistry<>(PotionEffectType.class, registryHolder.lookupOrThrow(Registries.MOB_EFFECT), wrap(CraftPotionEffectType::new), FieldRename.NONE);
}
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) {
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);
}
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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;

View File

@ -1,7 +1,6 @@
package org.bukkit.craftbukkit;
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,10 +8,10 @@ import net.minecraft.sounds.SoundEffect;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.Sound;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
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;
@ -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.");
}
private final NamespacedKey key;
private final SoundEffect soundEffect;
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;
public CraftSound(NamespacedKey key, Holder<SoundEffect> handle) {
super(key, handle, count++);
}
@NotNull
@Override
public NamespacedKey getKey() {
return key;
}
@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();
return getKeyOrThrow();
}
}

View File

@ -11,11 +11,11 @@ import org.bukkit.Registry;
import org.bukkit.attribute.Attribute;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.legacy.FieldRename;
import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
import org.bukkit.craftbukkit.util.ApiVersion;
import org.bukkit.craftbukkit.util.Handleable;
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;
@ -63,80 +63,19 @@ public class CraftAttribute implements Attribute, Handleable<AttributeBase> {
return bukkit.getKey().toString();
}
private final NamespacedKey key;
private final AttributeBase attributeBase;
private final String name;
private final int ordinal;
public CraftAttribute(NamespacedKey key, AttributeBase attributeBase) {
this.key = key;
this.attributeBase = attributeBase;
// For backwards compatibility, minecraft values will stile return the uppercase name without the namespace,
// in case plugins use for example the name as key in a config file to receive attribute specific values.
// Custom attributes will return the key with namespace. For a plugin this should look than like a new attribute
// (which can always be added in new minecraft versions and the plugin should therefore handle it accordingly).
if (NamespacedKey.MINECRAFT.equals(key.getNamespace())) {
this.name = key.getKey().toUpperCase(Locale.ROOT);
} else {
this.name = key.toString();
}
this.ordinal = count++;
}
@Override
public AttributeBase getHandle() {
return attributeBase;
public CraftAttribute(NamespacedKey key, Holder<AttributeBase> handle) {
super(key, handle, count++);
}
@NotNull
@Override
public NamespacedKey getKey() {
return key;
return getKeyOrThrow();
}
@NotNull
@Override
public String getTranslationKey() {
return attributeBase.getDescriptionId();
}
@Override
public int compareTo(@NotNull Attribute attribute) {
return ordinal - attribute.ordinal();
}
@NotNull
@Override
public String name() {
return name;
}
@Override
public int ordinal() {
return ordinal;
}
@Override
public String toString() {
// For backwards compatibility
return name();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof CraftAttribute otherAttribute)) {
return false;
}
return getKey().equals(otherAttribute.getKey());
}
@Override
public int hashCode() {
return getKey().hashCode();
return getHandle().getDescriptionId();
}
}

View File

@ -1,6 +1,5 @@
package org.bukkit.craftbukkit.block;
import java.util.Locale;
import net.minecraft.core.Holder;
import net.minecraft.core.IRegistry;
import net.minecraft.core.registries.Registries;
@ -9,10 +8,10 @@ import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
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;
@ -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.");
}
private final NamespacedKey key;
private final BiomeBase biomeBase;
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;
public CraftBiome(NamespacedKey key, Holder<BiomeBase> handle) {
super(key, handle, count++);
}
@NotNull
@Override
public NamespacedKey getKey() {
return key;
}
@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();
return getKeyOrThrow();
}
}

View File

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

View File

@ -7,25 +7,16 @@ import net.minecraft.core.registries.Registries;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
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.DamageScaling;
import org.bukkit.damage.DamageType;
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;
private final net.minecraft.world.damagesource.DamageType damageType;
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;
public CraftDamageType(NamespacedKey key, Holder<net.minecraft.world.damagesource.DamageType> handle) {
super(key, handle);
}
@Override
@ -55,12 +46,7 @@ public class CraftDamageType implements DamageType, Handleable<net.minecraft.wor
@Override
public NamespacedKey getKey() {
return this.key;
}
@Override
public String toString() {
return "CraftDamageType{" + "key=" + this.getKey() + ",damageScaling=" + this.getDamageScaling() + ",damageEffect=" + this.getDamageEffect() + ",deathMessageType=" + this.getDeathMessageType() + ",exhaustion=" + this.getExhaustion() + "}";
return getKeyOrThrow();
}
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.EnchantmentWrapper;
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> {
@ -70,7 +72,7 @@ public class CraftEnchantment extends Enchantment implements Handleable<net.mine
@Override
public NamespacedKey getKey() {
return key;
return getKeyOrThrow();
}
@Override
@ -173,4 +175,22 @@ public class CraftEnchantment extends Enchantment implements Handleable<net.mine
public String toString() {
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;
import com.google.common.base.Preconditions;
import java.util.Locale;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.animal.CatVariant;
@ -12,7 +11,7 @@ import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
import org.bukkit.entity.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()));
}
public static class CraftType implements Type, Handleable<CatVariant> {
public static class CraftType extends CraftOldEnumRegistryItem<Type, CatVariant> implements Type {
private static int count = 0;
public static Type minecraftToBukkit(CatVariant minecraft) {
@ -72,73 +71,13 @@ public class CraftCat extends CraftTameableAnimal implements Cat {
return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.CAT_VARIANT);
}
private final NamespacedKey key;
private final CatVariant catVariant;
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;
public CraftType(NamespacedKey key, Holder<CatVariant> handle) {
super(key, handle, count++);
}
@Override
public NamespacedKey getKey() {
return key;
}
@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();
return getKeyOrThrow();
}
}
}

View File

@ -1,7 +1,6 @@
package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import java.util.Locale;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.animal.FrogVariant;
@ -10,7 +9,7 @@ import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
import org.bukkit.entity.Entity;
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));
}
public static class CraftVariant implements Variant, Handleable<FrogVariant> {
public static class CraftVariant extends CraftOldEnumRegistryItem<Variant, FrogVariant> implements Variant {
private static int count = 0;
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);
}
private final NamespacedKey key;
private final FrogVariant frogVariant;
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;
public CraftVariant(NamespacedKey key, Holder<FrogVariant> handle) {
super(key, handle, count++);
}
@Override
public NamespacedKey getKey() {
return key;
}
@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();
return getKeyOrThrow();
}
}
}

View File

@ -2,13 +2,13 @@ package org.bukkit.craftbukkit.entity;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import net.minecraft.core.BlockPosition;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.ai.gossip.ReputationType;
import net.minecraft.world.entity.monster.EntityZombie;
@ -23,6 +23,7 @@ import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.entity.Villager;
@ -208,7 +209,7 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
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;
public static Type minecraftToBukkit(VillagerType minecraft) {
@ -219,77 +220,17 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
return CraftRegistry.bukkitToMinecraft(bukkit);
}
private final NamespacedKey key;
private final VillagerType villagerType;
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;
public CraftType(NamespacedKey key, Holder<VillagerType> handle) {
super(key, handle, count++);
}
@Override
public NamespacedKey getKey() {
return key;
}
@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();
return getKeyOrThrow();
}
}
public static class CraftProfession implements Profession, Handleable<VillagerProfession> {
public static class CraftProfession extends CraftOldEnumRegistryItem<Profession, VillagerProfession> implements Profession {
private static int count = 0;
public static Profession minecraftToBukkit(VillagerProfession minecraft) {
@ -300,73 +241,13 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
return CraftRegistry.bukkitToMinecraft(bukkit);
}
private final NamespacedKey key;
private final VillagerProfession villagerProfession;
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;
public CraftProfession(NamespacedKey key, Holder<VillagerProfession> handle) {
super(key, handle, count++);
}
@Override
public NamespacedKey getKey() {
return key;
}
@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();
return getKeyOrThrow();
}
}

View File

@ -12,7 +12,7 @@ import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.craftbukkit.registry.CraftRegistryItem;
import org.bukkit.entity.Wolf;
public class CraftWolf extends CraftTameableAnimal implements Wolf {
@ -81,7 +81,7 @@ public class CraftWolf extends CraftTameableAnimal implements Wolf {
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) {
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.");
}
private final NamespacedKey key;
private final WolfVariant variant;
public CraftVariant(NamespacedKey key, WolfVariant variant) {
this.key = key;
this.variant = variant;
}
@Override
public WolfVariant getHandle() {
return variant;
public CraftVariant(NamespacedKey key, Holder<WolfVariant> handle) {
super(key, handle);
}
@Override
public NamespacedKey getKey() {
return key;
}
@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();
return getKeyOrThrow();
}
}
}

View File

@ -1,5 +1,6 @@
package org.bukkit.craftbukkit.generator.structure;
import com.google.common.base.Preconditions;
import com.google.common.base.Suppliers;
import java.util.function.Supplier;
import net.minecraft.core.registries.Registries;
@ -9,6 +10,8 @@ import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.generator.structure.Structure;
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> {
@ -42,6 +45,24 @@ public class CraftStructure extends Structure implements Handleable<net.minecraf
@Override
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;
import com.google.common.base.Preconditions;
import net.minecraft.core.registries.Registries;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable;
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<?>> {
@ -32,6 +35,24 @@ public class CraftStructureType extends StructureType implements Handleable<net.
@Override
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 java.util.function.Consumer;
import java.util.function.Supplier;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.Registries;
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.CraftAttributeInstance;
import org.bukkit.craftbukkit.block.CraftBlockType;
import org.bukkit.craftbukkit.registry.CraftRegistryItem;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.inventory.CreativeCategory;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
@ -36,10 +37,8 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
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;
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);
}
public CraftItemType(NamespacedKey key, Item item) {
this.key = key;
this.item = item;
public CraftItemType(NamespacedKey key, Holder<Item> handle) {
super(key, handle);
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) {
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
@ -109,11 +107,6 @@ public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Han
return itemStack;
}
@Override
public Item getHandle() {
return item;
}
public M getItemMeta(net.minecraft.world.item.ItemStack itemStack) {
return itemMetaData.get().fromItemStack().apply(itemStack);
}
@ -124,14 +117,14 @@ public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Han
@Override
public boolean hasBlockType() {
return item instanceof ItemBlock;
return getHandle() instanceof ItemBlock;
}
@NotNull
@Override
public BlockType getBlockType() {
if (!(item instanceof ItemBlock block)) {
throw new IllegalStateException("The item type " + getKey() + " has no corresponding block type");
if (!(getHandle() instanceof ItemBlock block)) {
throw new IllegalStateException("The item type " + (isRegistered() ? getKeyOrThrow() : toString()) + " has no corresponding block type");
}
return CraftBlockType.minecraftToBukkitNew(block.getBlock());
@ -152,43 +145,43 @@ public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Han
if (this == AIR) {
return 0;
}
return item.components().getOrDefault(DataComponents.MAX_STACK_SIZE, 64);
return getHandle().components().getOrDefault(DataComponents.MAX_STACK_SIZE, 64);
}
@Override
public short getMaxDurability() {
return item.components().getOrDefault(DataComponents.MAX_DAMAGE, 0).shortValue();
return getHandle().components().getOrDefault(DataComponents.MAX_DAMAGE, 0).shortValue();
}
@Override
public boolean isEdible() {
return item.components().has(DataComponents.FOOD);
return getHandle().components().has(DataComponents.FOOD);
}
@Override
public boolean isRecord() {
return item.components().has(DataComponents.JUKEBOX_PLAYABLE);
return getHandle().components().has(DataComponents.JUKEBOX_PLAYABLE);
}
@Override
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
public boolean isCompostable() {
return BlockComposter.COMPOSTABLES.containsKey(item);
return BlockComposter.COMPOSTABLES.containsKey(getHandle());
}
@Override
public float getCompostChance() {
Preconditions.checkArgument(isCompostable(), "The item type " + getKey() + " is not compostable");
return BlockComposter.COMPOSTABLES.getFloat(item);
Preconditions.checkArgument(isCompostable(), "The item type " + (isRegistered() ? getKeyOrThrow() : toString()) + " is not compostable");
return BlockComposter.COMPOSTABLES.getFloat(getHandle());
}
@Override
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());
}
@ -201,7 +194,7 @@ public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Han
public Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers(EquipmentSlot slot) {
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) -> {
Attribute attribute = CraftAttribute.minecraftToBukkit(key.value());
@ -225,16 +218,16 @@ public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Han
@NotNull
@Override
public String getTranslationKey() {
return item.getDescriptionId();
return getHandle().getDescriptionId();
}
@Override
public NamespacedKey getKey() {
return key;
return getKeyOrThrow();
}
@Override
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.craftbukkit.CraftRegistry;
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.inventory.InventoryView;
import org.bukkit.inventory.MenuType;
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;
public CraftMenuType(NamespacedKey key, Containers<?> handle) {
this.key = key;
this.handle = handle;
public CraftMenuType(NamespacedKey key, Holder<Containers<?>> handle) {
super(key, handle);
this.typeData = Suppliers.memoize(() -> CraftMenus.getMenuTypeData(this));
}
@Override
public Containers<?> getHandle() {
return this.handle;
}
@Override
public V create(final HumanEntity player, final String title) {
return builder().title(title).build(player);
@ -53,7 +45,7 @@ public class CraftMenuType<V extends InventoryView, B extends InventoryViewBuild
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
@ -63,7 +55,7 @@ public class CraftMenuType<V extends InventoryView, B extends InventoryViewBuild
@Override
public NamespacedKey getKey() {
return this.key;
return getKeyOrThrow();
}
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.Registry;
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.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) {
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.");
}
private final NamespacedKey key;
private final net.minecraft.world.item.equipment.trim.TrimMaterial 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;
public CraftTrimMaterial(NamespacedKey key, Holder<net.minecraft.world.item.equipment.trim.TrimMaterial> handle) {
super(key, handle);
}
@Override
@NotNull
public NamespacedKey getKey() {
return key;
return getKeyOrThrow();
}
@NotNull
@Override
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.Registry;
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.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) {
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.");
}
private final NamespacedKey key;
private final net.minecraft.world.item.equipment.trim.TrimPattern 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;
public CraftTrimPattern(NamespacedKey key, Holder<net.minecraft.world.item.equipment.trim.TrimPattern> handle) {
super(key, handle);
}
@Override
@NotNull
public NamespacedKey getKey() {
return key;
return getKeyOrThrow();
}
@NotNull
@Override
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;
import java.util.Locale;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.level.saveddata.maps.MapDecorationType;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.craftbukkit.registry.CraftOldEnumRegistryItem;
import org.bukkit.map.MapCursor;
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;
@ -32,73 +31,13 @@ public final class CraftMapCursor {
return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.MAP_DECORATION_TYPE);
}
private final NamespacedKey key;
private final MapDecorationType mapDecorationType;
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;
public CraftType(NamespacedKey key, Holder<MapDecorationType> handle) {
super(key, handle, count++);
}
@Override
public NamespacedKey getKey() {
return key;
}
@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();
return getKeyOrThrow();
}
@Override

View File

@ -1,5 +1,6 @@
package org.bukkit.craftbukkit.potion;
import com.google.common.base.Preconditions;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.effect.MobEffectList;
@ -12,6 +13,7 @@ import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionEffectTypeCategory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class CraftPotionEffectType extends PotionEffectType implements Handleable<MobEffectList> {
@ -49,7 +51,7 @@ public class CraftPotionEffectType extends PotionEffectType implements Handleabl
@NotNull
@Override
public NamespacedKey getKey() {
return key;
return getKeyOrThrow();
}
@Override
@ -151,4 +153,22 @@ public class CraftPotionEffectType extends PotionEffectType implements Handleabl
public String toString() {
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 + "}";
}
}