package net.minecraft.core; import com.google.common.collect.ImmutableMap; import com.mojang.logging.LogUtils; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Map.Entry; import java.util.stream.Collectors; import java.util.stream.Stream; import net.minecraft.resources.ResourceKey; import org.slf4j.Logger; /** * The root level registry, essentially a registry of registries. It is also an access point, hence the name, for other dynamic registries. */ public interface RegistryAccess extends HolderLookup.Provider { Logger LOGGER = LogUtils.getLogger(); RegistryAccess.Frozen EMPTY = new RegistryAccess.ImmutableRegistryAccess(Map.of()).freeze(); @Override Optional> lookup(ResourceKey> registryKey); default Registry lookupOrThrow(ResourceKey> resourceKey) { return (Registry)this.lookup(resourceKey).orElseThrow(() -> new IllegalStateException("Missing registry: " + resourceKey)); } Stream> registries(); @Override default Stream>> listRegistryKeys() { return this.registries().map(registryEntry -> registryEntry.key); } static RegistryAccess.Frozen fromRegistryOfRegistries(Registry> registryOfRegistries) { return new RegistryAccess.Frozen() { @Override public Optional> lookup(ResourceKey> registryKey) { Registry> registry = (Registry>)registryOfRegistries; return registry.getOptional((ResourceKey>)registryKey); } @Override public Stream> registries() { return registryOfRegistries.entrySet().stream().map(RegistryAccess.RegistryEntry::fromMapEntry); } @Override public RegistryAccess.Frozen freeze() { return this; } }; } default RegistryAccess.Frozen freeze() { class FrozenAccess extends RegistryAccess.ImmutableRegistryAccess implements RegistryAccess.Frozen { protected FrozenAccess(final Stream> registries) { super(registries); } } return new FrozenAccess(this.registries().map(RegistryAccess.RegistryEntry::freeze)); } public interface Frozen extends RegistryAccess { } public static class ImmutableRegistryAccess implements RegistryAccess { private final Map>, ? extends Registry> registries; public ImmutableRegistryAccess(List> registries) { this.registries = (Map>, ? extends Registry>)registries.stream() .collect(Collectors.toUnmodifiableMap(Registry::key, registry -> registry)); } public ImmutableRegistryAccess(Map>, ? extends Registry> registries) { this.registries = Map.copyOf(registries); } public ImmutableRegistryAccess(Stream> registries) { this.registries = (Map>, ? extends Registry>)registries.collect( ImmutableMap.toImmutableMap(RegistryAccess.RegistryEntry::key, RegistryAccess.RegistryEntry::value) ); } @Override public Optional> lookup(ResourceKey> registryKey) { return Optional.ofNullable((Registry)this.registries.get(registryKey)).map(registry -> registry); } @Override public Stream> registries() { return this.registries.entrySet().stream().map(RegistryAccess.RegistryEntry::fromMapEntry); } } public record RegistryEntry(ResourceKey> key, Registry value) { private static > RegistryAccess.RegistryEntry fromMapEntry( Entry>, R> mapEntry ) { return fromUntyped((ResourceKey>)mapEntry.getKey(), (Registry)mapEntry.getValue()); } private static RegistryAccess.RegistryEntry fromUntyped(ResourceKey> key, Registry value) { return new RegistryAccess.RegistryEntry<>((ResourceKey>)key, (Registry)value); } private RegistryAccess.RegistryEntry freeze() { return new RegistryAccess.RegistryEntry<>(this.key, this.value.freeze()); } } }