package net.minecraft.resources; import com.google.common.collect.MapMaker; import com.mojang.serialization.Codec; import io.netty.buffer.ByteBuf; import java.util.Optional; import java.util.concurrent.ConcurrentMap; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.network.codec.StreamCodec; /** * An immutable key for a resource, in terms of the name of its parent registry and its location in that registry. *

* {@link net.minecraft.core.Registry} uses this to return resource keys for registry objects via {@link net.minecraft.core.Registry#getResourceKey(Object)}. It also uses this class to store its name, with the parent registry name set to {@code minecraft:root}. When used in this way it is usually referred to as a "registry key".

*

* @param The type of the resource represented by this {@code ResourceKey}, or the type of the registry if it is a registry key. * @see net.minecraft.resources.ResourceLocation */ public class ResourceKey { private static final ConcurrentMap> VALUES = new MapMaker().weakValues().makeMap(); /** * The name of the parent registry of the resource. */ private final ResourceLocation registryName; /** * The location of the resource within the registry. */ private final ResourceLocation location; public static Codec> codec(ResourceKey> registryKey) { return ResourceLocation.CODEC.xmap(resourceLocation -> create(registryKey, resourceLocation), ResourceKey::location); } public static StreamCodec> streamCodec(ResourceKey> registryKey) { return ResourceLocation.STREAM_CODEC.map(resourceLocation -> create(registryKey, resourceLocation), ResourceKey::location); } /** * Constructs a new {@code ResourceKey} for a resource with the specified {@code location} within the registry specified by the given {@code registryKey}. * * @return the created resource key. The registry name is set to the location of the specified {@code registryKey} and with the specified {@code location} as the location of the resource. */ public static ResourceKey create(ResourceKey> registryKey, ResourceLocation location) { return create(registryKey.location, location); } /** * @return the created registry key. The registry name is set to {@code minecraft:root} and the location the specified {@code registryName}. */ public static ResourceKey> createRegistryKey(ResourceLocation location) { return create(Registries.ROOT_REGISTRY_NAME, location); } private static ResourceKey create(ResourceLocation registryName, ResourceLocation location) { return (ResourceKey)VALUES.computeIfAbsent( new ResourceKey.InternKey(registryName, location), internKey -> new ResourceKey(internKey.registry, internKey.location) ); } private ResourceKey(ResourceLocation registryName, ResourceLocation location) { this.registryName = registryName; this.location = location; } public String toString() { return "ResourceKey[" + this.registryName + " / " + this.location + "]"; } /** * @return {@code true} if this resource key is a direct child of the specified {@code registryKey}. */ public boolean isFor(ResourceKey> registryKey) { return this.registryName.equals(registryKey.location()); } public Optional> cast(ResourceKey> registryKey) { return this.isFor(registryKey) ? Optional.of(this) : Optional.empty(); } public ResourceLocation location() { return this.location; } public ResourceLocation registry() { return this.registryName; } public ResourceKey> registryKey() { return createRegistryKey(this.registryName); } record InternKey(ResourceLocation registry, ResourceLocation location) { } }