minecraft-src/net/minecraft/commands/arguments/ResourceArgument.java
2025-07-04 03:15:13 +03:00

136 lines
6.7 KiB
Java

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<T> implements ArgumentType<Reference<T>> {
private static final Collection<String> 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<? extends Registry<T>> registryKey;
private final HolderLookup<T> registryLookup;
public ResourceArgument(CommandBuildContext context, ResourceKey<? extends Registry<T>> registryKey) {
this.registryKey = registryKey;
this.registryLookup = context.lookupOrThrow(registryKey);
}
public static <T> ResourceArgument<T> resource(CommandBuildContext context, ResourceKey<? extends Registry<T>> registryKey) {
return new ResourceArgument<>(context, registryKey);
}
public static <T> Reference<T> getResource(CommandContext<CommandSourceStack> context, String argument, ResourceKey<Registry<T>> registryKey) throws CommandSyntaxException {
Reference<T> 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<Attribute> getAttribute(CommandContext<CommandSourceStack> context, String argument) throws CommandSyntaxException {
return getResource(context, argument, Registries.ATTRIBUTE);
}
public static Reference<ConfiguredFeature<?, ?>> getConfiguredFeature(CommandContext<CommandSourceStack> context, String argument) throws CommandSyntaxException {
return getResource(context, argument, Registries.CONFIGURED_FEATURE);
}
public static Reference<Structure> getStructure(CommandContext<CommandSourceStack> context, String argument) throws CommandSyntaxException {
return getResource(context, argument, Registries.STRUCTURE);
}
public static Reference<EntityType<?>> getEntityType(CommandContext<CommandSourceStack> context, String argument) throws CommandSyntaxException {
return getResource(context, argument, Registries.ENTITY_TYPE);
}
public static Reference<EntityType<?>> getSummonableEntityType(CommandContext<CommandSourceStack> context, String argument) throws CommandSyntaxException {
Reference<EntityType<?>> 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<MobEffect> getMobEffect(CommandContext<CommandSourceStack> context, String argument) throws CommandSyntaxException {
return getResource(context, argument, Registries.MOB_EFFECT);
}
public static Reference<Enchantment> getEnchantment(CommandContext<CommandSourceStack> context, String argument) throws CommandSyntaxException {
return getResource(context, argument, Registries.ENCHANTMENT);
}
public Reference<T> parse(StringReader builder) throws CommandSyntaxException {
ResourceLocation resourceLocation = ResourceLocation.read(builder);
ResourceKey<T> resourceKey = ResourceKey.create(this.registryKey, resourceLocation);
return (Reference<T>)this.registryLookup
.get(resourceKey)
.orElseThrow(() -> ERROR_UNKNOWN_RESOURCE.createWithContext(builder, resourceLocation, this.registryKey.location()));
}
@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> commandContext, SuggestionsBuilder suggestionsBuilder) {
return SharedSuggestionProvider.suggestResource(this.registryLookup.listElementIds().map(ResourceKey::location), suggestionsBuilder);
}
@Override
public Collection<String> getExamples() {
return EXAMPLES;
}
public static class Info<T> implements ArgumentTypeInfo<ResourceArgument<T>, ResourceArgument.Info<T>.Template> {
public void serializeToNetwork(ResourceArgument.Info<T>.Template template, FriendlyByteBuf friendlyByteBuf) {
friendlyByteBuf.writeResourceKey(template.registryKey);
}
public ResourceArgument.Info<T>.Template deserializeFromNetwork(FriendlyByteBuf friendlyByteBuf) {
return new net.minecraft.commands.arguments.ResourceArgument.Info.Template(this, friendlyByteBuf.readRegistryKey());
}
public void serializeToJson(ResourceArgument.Info<T>.Template template, JsonObject jsonObject) {
jsonObject.addProperty("registry", template.registryKey.location().toString());
}
public ResourceArgument.Info<T>.Template unpack(ResourceArgument<T> resourceArgument) {
return new net.minecraft.commands.arguments.ResourceArgument.Info.Template(this, resourceArgument.registryKey);
}
}
}