package net.minecraft.commands.arguments; import com.google.gson.JsonObject; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; import com.mojang.brigadier.exceptions.Dynamic3CommandExceptionType; import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import java.util.Arrays; import java.util.Collection; import java.util.concurrent.CompletableFuture; import net.minecraft.commands.CommandBuildContext; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.SharedSuggestionProvider; import net.minecraft.commands.synchronization.ArgumentTypeInfo; import net.minecraft.core.HolderLookup; import net.minecraft.core.Registry; import net.minecraft.core.Holder.Reference; import net.minecraft.core.registries.Registries; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.level.levelgen.structure.Structure; public class ResourceArgument implements ArgumentType> { private static final Collection EXAMPLES = Arrays.asList("foo", "foo:bar", "012"); private static final DynamicCommandExceptionType ERROR_NOT_SUMMONABLE_ENTITY = new DynamicCommandExceptionType( object -> Component.translatableEscape("entity.not_summonable", object) ); public static final Dynamic2CommandExceptionType ERROR_UNKNOWN_RESOURCE = new Dynamic2CommandExceptionType( (object, object2) -> Component.translatableEscape("argument.resource.not_found", object, object2) ); public static final Dynamic3CommandExceptionType ERROR_INVALID_RESOURCE_TYPE = new Dynamic3CommandExceptionType( (object, object2, object3) -> Component.translatableEscape("argument.resource.invalid_type", object, object2, object3) ); final ResourceKey> registryKey; private final HolderLookup registryLookup; public ResourceArgument(CommandBuildContext context, ResourceKey> registryKey) { this.registryKey = registryKey; this.registryLookup = context.lookupOrThrow(registryKey); } public static ResourceArgument resource(CommandBuildContext context, ResourceKey> registryKey) { return new ResourceArgument<>(context, registryKey); } public static Reference getResource(CommandContext context, String argument, ResourceKey> registryKey) throws CommandSyntaxException { Reference reference = context.getArgument(argument, Reference.class); ResourceKey resourceKey = reference.key(); if (resourceKey.isFor(registryKey)) { return reference; } else { throw ERROR_INVALID_RESOURCE_TYPE.create(resourceKey.location(), resourceKey.registry(), registryKey.location()); } } public static Reference getAttribute(CommandContext context, String argument) throws CommandSyntaxException { return getResource(context, argument, Registries.ATTRIBUTE); } public static Reference> getConfiguredFeature(CommandContext context, String argument) throws CommandSyntaxException { return getResource(context, argument, Registries.CONFIGURED_FEATURE); } public static Reference getStructure(CommandContext context, String argument) throws CommandSyntaxException { return getResource(context, argument, Registries.STRUCTURE); } public static Reference> getEntityType(CommandContext context, String argument) throws CommandSyntaxException { return getResource(context, argument, Registries.ENTITY_TYPE); } public static Reference> getSummonableEntityType(CommandContext context, String argument) throws CommandSyntaxException { Reference> reference = getResource(context, argument, Registries.ENTITY_TYPE); if (!reference.value().canSummon()) { throw ERROR_NOT_SUMMONABLE_ENTITY.create(reference.key().location().toString()); } else { return reference; } } public static Reference getMobEffect(CommandContext context, String argument) throws CommandSyntaxException { return getResource(context, argument, Registries.MOB_EFFECT); } public static Reference getEnchantment(CommandContext context, String argument) throws CommandSyntaxException { return getResource(context, argument, Registries.ENCHANTMENT); } public Reference parse(StringReader builder) throws CommandSyntaxException { ResourceLocation resourceLocation = ResourceLocation.read(builder); ResourceKey resourceKey = ResourceKey.create(this.registryKey, resourceLocation); return (Reference)this.registryLookup .get(resourceKey) .orElseThrow(() -> ERROR_UNKNOWN_RESOURCE.createWithContext(builder, resourceLocation, this.registryKey.location())); } @Override public CompletableFuture listSuggestions(CommandContext commandContext, SuggestionsBuilder suggestionsBuilder) { return SharedSuggestionProvider.suggestResource(this.registryLookup.listElementIds().map(ResourceKey::location), suggestionsBuilder); } @Override public Collection getExamples() { return EXAMPLES; } public static class Info implements ArgumentTypeInfo, ResourceArgument.Info.Template> { public void serializeToNetwork(ResourceArgument.Info.Template template, FriendlyByteBuf friendlyByteBuf) { friendlyByteBuf.writeResourceKey(template.registryKey); } public ResourceArgument.Info.Template deserializeFromNetwork(FriendlyByteBuf friendlyByteBuf) { return new net.minecraft.commands.arguments.ResourceArgument.Info.Template(this, friendlyByteBuf.readRegistryKey()); } public void serializeToJson(ResourceArgument.Info.Template template, JsonObject jsonObject) { jsonObject.addProperty("registry", template.registryKey.location().toString()); } public ResourceArgument.Info.Template unpack(ResourceArgument resourceArgument) { return new net.minecraft.commands.arguments.ResourceArgument.Info.Template(this, resourceArgument.registryKey); } } }