Registry
Registries in Minecraft hold all sort of information - possible item or block types, enchantments, potion effects, … and more!
There are two types of registry arguments: resource
and resourceKey
.
The main difference between those arguments is the return value: The resource
argument returns the parsed value, whilst the resourceKey
only returns a TypedKey
, which
you can use to retrieve the value yourself.
Resource argument
Section titled “Resource argument”Just like any other argument, you can get a ArgumentType<T>
reference to it using ArgumentTypes.resource(RegistryKey<T>)
. A selection of possible registry keys can be
found below. They are accessed in a static context using the RegistryKey
interface.
Each entry in RegistryKey
returns a RegistryKey<T>
. The <T>
generic parameter here describes the return type. This means that if we were to retrieve
RegistryKey.ITEM
, the return type would be an ItemType
, since it is defined as follows:
public sealed interface RegistryKey<T> extends Keyed permits RegistryKeyImpl { // ... RegistryKey<ItemType> ITEM = RegistryKeyImpl.create("item"); // ...}
And really, there isn’t much more to it. For that exact reason, here is an example on the implementation of such an argument:
public static LiteralCommandNode<CommandSourceStack> enchantmentRegistry() { return Commands.literal("enchants-registry") .then(Commands.argument("enchantment", ArgumentTypes.resource(RegistryKey.ENCHANTMENT)) .executes(ctx -> { final Enchantment enchantment = ctx.getArgument("enchantment", Enchantment.class);
if (ctx.getSource().getExecutor() instanceof Player player) { final ItemStack stack = player.getInventory().getItemInMainHand(); stack.addUnsafeEnchantment(enchantment, 10); ctx.getSource().getSender().sendRichMessage("Enchanted <player>'s <item> with <enchantment>!", Placeholder.component("player", player.name()), Placeholder.component("item", Component.translatable(stack)), Placeholder.component("enchantment", enchantment.displayName(10)) ); return Command.SINGLE_SUCCESS; }
ctx.getSource().getSender().sendRichMessage("<red>This command requires a player!"); return Command.SINGLE_SUCCESS; })) .build();}
We define an enchantment
argument using a enchantment registry key resource and retrieve the value of that using ctx.getArgument("enchantment", Enchantment.class)
.
Finally, we enchant the item of the executing player’s hand with whatever enchantment the sender chose at level 10 and send a success message.
Here is how it looks in-game:
Resource key argument
Section titled “Resource key argument”For the client, there is barely any difference between the using ArgumentTypes.resource
or ArgumentTypes.resourceKey
. The only difference is that
using ArgumentTypes.resourceKey
does not provide error checking. We can visualize this using RegistryKey.ITEM
.
Here is the tab completion when using ArgumentTypes.resource(RegistryKey.ITEM)
:
And here is the tab completion when using ArgumentTypes.resourceKey(RegistryKey.ITEM)
:
The resource argument provides a much cleaner user experience, whilst the resourceKey
argument has one very important use case: You get the raw
TypedKey<T>
returned as an argument result. This object is particularly useful, as it provides all information required to be able to retrieve
a value from a registry yourself.
Direct code comparison
Section titled “Direct code comparison”Here is a simple code snipped on how one could use the RegistryKey.ITEM
registry with a resource
argument type:
Commands.argument("item", ArgumentTypes.resource(RegistryKey.ITEM)) .executes(ctx -> { final ItemType item = ctx.getArgument("item", ItemType.class);
if (ctx.getSource().getExecutor() instanceof Player player) { player.getInventory().addItem(item.createItemStack()); }
return Command.SINGLE_SUCCESS; });
Here is the same code, using a resourceKey
argument type. Instead of directly retrieving the argument using ctx.getArgument("item", TypedKey.class)
, we instead use the
RegistryArgumentExtractor
to retrieve our TypedKey<ItemType>
.
Commands.argument("item", ArgumentTypes.resourceKey(RegistryKey.ITEM)) .executes(ctx -> { final TypedKey<ItemType> itemKey = RegistryArgumentExtractor.getTypedKey(ctx, RegistryKey.ITEM, "item"); ItemType item = RegistryAccess.registryAccess().getRegistry(itemKey.registryKey()).get(itemKey.key());
if (item == null) { ctx.getSource().getSender().sendRichMessage("<red>Please provide a valid item!"); return Command.SINGLE_SUCCESS; }
if (ctx.getSource().getExecutor() instanceof Player player) { player.getInventory().addItem(item.createItemStack()); }
return Command.SINGLE_SUCCESS; })
Using a TypedKey
Section titled “Using a TypedKey”First, in order to get the correct registry, you can run RegistryAccess#getRegistry(RegistryKey)
. In order to get a RegistryAccess
, you can just use the static
RegistryAccess.registryAccess()
method. The RegistryKey
is retrieved using TypedKey#registryKey()
.
Now, in order to get the final value T
, you can run Registry#get(Key)
, where the key can be retrieved using TypedKey#key()
. This will return the backing instance
from that resource key or null, if no value has been found.
Use case over resource argument
Section titled “Use case over resource argument”The main use case for this argument type is the ability to store the key (the value returned to you by TypedKey#key
). If you want to be able to store the exact user
input and be able to retrieve the backed instance without much trouble, that is the way to do it.
Registry key previews
Section titled “Registry key previews”At the time of writing, the following RegistryKeys exist:
RegistryKeys Field | Return Value | Preview Video |
---|---|---|
ATTRIBUTE | Attribute | Attribute |
BANNER_PATTERN | PatternType | Banner Pattern |
BIOME | Biome | Biome |
BLOCK | BlockType | Block |
CAT_VARIANT | Cat.Type | Cat Variant |
DAMAGE_TYPE | DamageType | Damage Type |
DATA_COMPONENT_TYPE | DataComponentType | Data Component Type |
ENCHANTMENT | Enchantment | Enchantment |
ENTITY_TYPE | EntityType | Entity Type |
FLUID | Fluid | Fluid |
FROG_VARIANT | Frog.Variant | Frog Variant |
GAME_EVENT | GameEvent | Game Event |
INSTRUMENT | MusicInstrument | Instrument |
ITEM | ItemType | Item |
JUKEBOX_SONG | JukeboxSong | Jukebox Song |
MAP_DECORATION_TYPE | MapCursor.Type | Map Decoration Type |
MEMORY_MODULE_TYPE | MemoryKey<?> | Memory Module Type |
MENU | MenuType | Menu |
MOB_EFFECT | PotionEffectType | Mob effect |
PAINTING_VARIANT | Art | Painting variant |
PARTICLE_TYPE | Particle | Particle |
POTION | PotionType | Potion |
SOUND_EVENT | Sound | Sound |
STRUCTURE | Structure | Structure |
STRUCTURE_TYPE | StructureType | Structure Type |
TRIM_MATERIAL | TrimMaterial | Trim Material |
TRIM_PATTERN | TrimPattern | Trim Pattern |
VILLAGER_PROFESSION | Villager.Profession | Villager Profession |
VILLAGER_TYPE | Villager.Type | Villager Type |
WOLF_VARIANT | Wolf.Variant | Wolf Variant |
Attribute
Section titled “Attribute”Banner Pattern
Section titled “Banner Pattern”Cat variant
Section titled “Cat variant”Damage type
Section titled “Damage type”Enchantment
Section titled “Enchantment”Entity type
Section titled “Entity type”Data component type
Section titled “Data component type”Frog variant
Section titled “Frog variant”Game event
Section titled “Game event”Instrument
Section titled “Instrument”Jukebox Song
Section titled “Jukebox Song”Map decoration type
Section titled “Map decoration type”Memory module type
Section titled “Memory module type”Mob effect
Section titled “Mob effect”Painting variant
Section titled “Painting variant”Particle
Section titled “Particle”Potion
Section titled “Potion”Structure
Section titled “Structure”This argument kicks the client, so no preview for this one ¯\_(ツ)_/¯