Skip to main content

Registry Arguments

Registries in Minecraft hold all sort of information - possible item materials, block materials, enchantments, potion effects, ... and more! These arguments are particularly useful for retrieving type values.

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.

For more information on the resourceKey argument, check out its dedicated segment.

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 ResourceKeys interface.

Each entry in the ResourceKeys returns a RegistryKey<T>. The <T> generic parameter here describes the return type. This means that if we were to retrieve RegistryKeys.ITEM, since it is defined as follows:

RegistryKey.class
public sealed interface RegistryKey<T> extends Keyed permits RegistryKeyImpl {
// ...
RegistryKey<ItemType> ITEM = RegistryKeyImpl.create("item");
// ...
}

The return type of the retrieved value using ctx.getArgument(...) would be an ItemType.

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.translationKey())),
Placeholder.component("enchantment", enchantment.displayName(10))
);
}
else {
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:


warning

There are certain edge-cases, where this argument will cause a Network Protocol Error on the client, due to missing registries on the client. Basically, the only argument where this is the case right now is with the STRUCTURE registry key.

// Registering this command will cause client to not be able to connect to the server.
final LiteralCommandNode<CommandSourceStack> invalidRegistryArgument = Commands.literal("registry-structure")
.then(Commands.argument("value", ArgumentTypes.resource(RegistryKey.STRUCTURE)))
.build();

Due to this fact, it is advised to only use the STRUCTURE registry key argument with a resourceKey(...) argument type and parse the values yourself. More information on resource key arguments can be found by clicking here..


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 for when using ArgumentTypes.resource(RegistryKey.ITEM):


And here is the tab completion for when using ArgumenTypes.resourceKey(RegistryKey.ITEM):


The resource argument provides a much cleaner user experience, whilst the resourceKey argument has one very important usecase: 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.

tip

Unless you have a specific reason for using the resourceKey argument over the resource one, the resource argument is preferred due to the error checking and simple usability.

Direct code comparison

Here is a simple code snipped on how one could use the RegistryKey.ITEM registry with a resource argument type:

Item Resource
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:

Item Resource
Commands.argument("item", ArgumentTypes.resourceKey(RegistryKey.ITEM))
.executes(ctx -> {
final TypedKey<ItemType> itemKey = ctx.getArgument("value", TypedKey.class);
ItemType item = RegistryAccess.registryAccess().getRegistry(itemKey.registryKey()).get(itemKey.key());

if (item == null) {
ctx.getSource().getSender().sendRichMessage("<red>Please provide a valid item!");
return -1;
}

if (ctx.getSource().getExecutor() instanceof Player player) {
player.getInventory().addItem(item.createItemStack());
}

return Command.SINGLE_SUCCESS;
});

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.

Usecase over resource argument

The main usecase 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 throuble, that is the way to do it.

Registry Key Previews

At the time of writing, the following RegistryKeys exist:

RegistryKeys FieldReturn ValuePreview Video
ATTRIBUTEAttributeAttribute
BANNER_PATTERNPatternTypePattern Type
BIOMEBiomeBiome
BLOCKBlockTypeBlock Type
CAT_VARIANTCat.TypeCat Type
DAMAGE_TYPEDamageTypeDamage Type
DATA_COMPONENT_TYPEDataComponentTypeData Component Type
FLUIDFluidFluid
FROG_VARIANTFrog.VariantFrog Variant
GAME_EVENTGameEventGame Event
INSTRUMENTMusicInstrumentMusic Instrument
ITEMItemTypeItem Type
JUKEBOX_SONGJukeboxSongJukebox Song
MAP_DECORATION_TYPEMapCursor.TypeMap Cursor Type
MENUMenuTypeMenu Type
MOB_EFFECTPotionEffectTypePotion Effect Type
PAINTING_VARIANTArtArt
SOUND_EVENTSoundSound
STRUCTUREStructureStructure
STRUCTURE_TYPEStructureTypeStructure Type
VILLAGER_PROFESSIONVillager.ProfessionVillager Profession
VILLAGER_TYPEVillager.TypeVillager Type
WOLF_VARIANTWolf.VariantWolf Variant

Attribute

Pattern Type

Biome

Block Type

Cat Type

Damage Type

Data Component Type

Fluid

Frog Variant

Game Event

Music Instrument

Item Type

Jukebox Song

Map Cursor Type

Potion Effect Type

Art

Sound

Structure

This argument kicks the client, so no preview for this one ¯\_(ツ)_/¯

Structure Type

Villager Profession

Villager Type

Wolf Variant