package net.minecraft.core; import com.mojang.datafixers.DataFixUtils; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.DynamicOps; import com.mojang.serialization.Keyable; import com.mojang.serialization.Lifecycle; import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.Map.Entry; import java.util.stream.Stream; import java.util.stream.StreamSupport; import net.fabricmc.fabric.api.event.registry.FabricRegistry; import net.minecraft.core.component.DataComponentLookup; import net.minecraft.resources.Identifier; import net.minecraft.resources.ResourceKey; import net.minecraft.tags.TagKey; import net.minecraft.tags.TagLoader; import net.minecraft.util.ExtraCodecs; import net.minecraft.util.RandomSource; import org.jspecify.annotations.Nullable; public interface Registry extends IdMap, Keyable, HolderLookup.RegistryLookup, FabricRegistry { @Override ResourceKey> key(); default Codec byNameCodec() { return this.referenceHolderWithLifecycle().flatComapMap(Holder.Reference::value, value -> this.safeCastToReference(this.wrapAsHolder((T)value))); } default Codec> holderByNameCodec() { return this.referenceHolderWithLifecycle().flatComapMap(holder -> holder, this::safeCastToReference); } private Codec> referenceHolderWithLifecycle() { Codec> referenceCodec = Identifier.CODEC .comapFlatMap( name -> (DataResult)this.get(name).map(DataResult::success).orElseGet(() -> DataResult.error(() -> "Unknown registry key in " + this.key() + ": " + name)), holder -> holder.key().identifier() ); return ExtraCodecs.overrideLifecycle( referenceCodec, e -> (Lifecycle)this.registrationInfo(e.key()).map(RegistrationInfo::lifecycle).orElse(Lifecycle.experimental()) ); } private DataResult> safeCastToReference(final Holder holder) { return holder instanceof Holder.Reference reference ? DataResult.success(reference) : DataResult.error(() -> "Unregistered holder in " + this.key() + ": " + holder); } @Override default Stream keys(final DynamicOps ops) { return this.keySet().stream().map(k -> ops.createString(k.toString())); } @Nullable Identifier getKey(T thing); Optional> getResourceKey(T thing); @Override int getId(@Nullable T thing); @Nullable T getValue(@Nullable ResourceKey key); @Nullable T getValue(@Nullable Identifier key); Optional registrationInfo(ResourceKey element); default Optional getOptional(@Nullable final Identifier key) { return Optional.ofNullable(this.getValue(key)); } default Optional getOptional(@Nullable final ResourceKey key) { return Optional.ofNullable(this.getValue(key)); } Optional> getAny(); default T getValueOrThrow(final ResourceKey key) { T value = this.getValue(key); if (value == null) { throw new IllegalStateException("Missing key in " + this.key() + ": " + key); } else { return value; } } Set keySet(); Set, T>> entrySet(); Set> registryKeySet(); Optional> getRandom(RandomSource random); default Stream stream() { return StreamSupport.stream(this.spliterator(), false); } boolean containsKey(Identifier key); boolean containsKey(ResourceKey key); static T register(final Registry registry, final String name, final T value) { return register(registry, Identifier.parse(name), value); } static T register(final Registry registry, final Identifier location, final T value) { return register(registry, ResourceKey.create(registry.key(), location), value); } static T register(final Registry registry, final ResourceKey key, final T value) { ((WritableRegistry)registry).register(key, (V)value, RegistrationInfo.BUILT_IN); return value; } static Holder.Reference registerForHolder(final Registry registry, final ResourceKey key, final T value) { return ((WritableRegistry)registry).register(key, (R)value, RegistrationInfo.BUILT_IN); } static Holder.Reference registerForHolder(final Registry registry, final Identifier location, final T value) { return registerForHolder(registry, ResourceKey.create(registry.key(), location), value); } Registry freeze(); Holder.Reference createIntrusiveHolder(T value); Optional> get(int id); Optional> get(Identifier id); Holder wrapAsHolder(T value); default Iterable> getTagOrEmpty(final TagKey id) { return DataFixUtils.orElse(this.get(id), List.of()); } Stream> getTags(); default IdMap> asHolderIdMap() { return new IdMap>() { { Objects.requireNonNull(Registry.this); } public int getId(final Holder thing) { return Registry.this.getId(thing.value()); } @Nullable public Holder byId(final int id) { return (Holder)Registry.this.get(id).orElse(null); } @Override public int size() { return Registry.this.size(); } public Iterator> iterator() { return Registry.this.listElements().map(e -> e).iterator(); } }; } Registry.PendingTags prepareTagReload(TagLoader.LoadResult tags); DataComponentLookup componentLookup(); public interface PendingTags { ResourceKey> key(); HolderLookup.RegistryLookup lookup(); void apply(); int size(); } }