minecraft-src/net/minecraft/resources/RegistryOps.java
2025-07-04 03:45:38 +03:00

128 lines
5.2 KiB
Java

package net.minecraft.resources;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.Dynamic;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.Lifecycle;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import net.minecraft.core.HolderGetter;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.HolderOwner;
import net.minecraft.core.Registry;
import net.minecraft.core.Holder.Reference;
import net.minecraft.util.ExtraCodecs;
public class RegistryOps<T> extends DelegatingOps<T> {
private final RegistryOps.RegistryInfoLookup lookupProvider;
public static <T> RegistryOps<T> create(DynamicOps<T> delegate, HolderLookup.Provider registries) {
return create(delegate, new RegistryOps.HolderLookupAdapter(registries));
}
public static <T> RegistryOps<T> create(DynamicOps<T> delegate, RegistryOps.RegistryInfoLookup lookupProvider) {
return new RegistryOps<>(delegate, lookupProvider);
}
public static <T> Dynamic<T> injectRegistryContext(Dynamic<T> dynamic, HolderLookup.Provider registries) {
return new Dynamic<>(registries.createSerializationContext(dynamic.getOps()), dynamic.getValue());
}
private RegistryOps(DynamicOps<T> delegate, RegistryOps.RegistryInfoLookup lookupProvider) {
super(delegate);
this.lookupProvider = lookupProvider;
}
public <U> RegistryOps<U> withParent(DynamicOps<U> ops) {
return (RegistryOps<U>)(ops == this.delegate ? this : new RegistryOps<>(ops, this.lookupProvider));
}
public <E> Optional<HolderOwner<E>> owner(ResourceKey<? extends Registry<? extends E>> registryKey) {
return this.lookupProvider.lookup(registryKey).map(RegistryOps.RegistryInfo::owner);
}
public <E> Optional<HolderGetter<E>> getter(ResourceKey<? extends Registry<? extends E>> registryKey) {
return this.lookupProvider.lookup(registryKey).map(RegistryOps.RegistryInfo::getter);
}
public boolean equals(Object object) {
if (this == object) {
return true;
} else if (object != null && this.getClass() == object.getClass()) {
RegistryOps<?> registryOps = (RegistryOps<?>)object;
return this.delegate.equals(registryOps.delegate) && this.lookupProvider.equals(registryOps.lookupProvider);
} else {
return false;
}
}
public int hashCode() {
return this.delegate.hashCode() * 31 + this.lookupProvider.hashCode();
}
public static <E, O> RecordCodecBuilder<O, HolderGetter<E>> retrieveGetter(ResourceKey<? extends Registry<? extends E>> registryOps) {
return ExtraCodecs.<HolderGetter<E>>retrieveContext(
dynamicOps -> dynamicOps instanceof RegistryOps<?> registryOpsx
? (DataResult)registryOpsx.lookupProvider
.lookup(registryOps)
.map(registryInfo -> DataResult.success(registryInfo.getter(), registryInfo.elementsLifecycle()))
.orElseGet(() -> DataResult.error(() -> "Unknown registry: " + registryOps))
: DataResult.error(() -> "Not a registry ops")
)
.forGetter(object -> null);
}
public static <E, O> RecordCodecBuilder<O, Reference<E>> retrieveElement(ResourceKey<E> key) {
ResourceKey<? extends Registry<E>> resourceKey = ResourceKey.createRegistryKey(key.registry());
return ExtraCodecs.<Reference<E>>retrieveContext(
dynamicOps -> dynamicOps instanceof RegistryOps<?> registryOps
? (DataResult)registryOps.lookupProvider
.lookup(resourceKey)
.flatMap(registryInfo -> registryInfo.getter().get(key))
.map(DataResult::success)
.orElseGet(() -> DataResult.error(() -> "Can't find value: " + key))
: DataResult.error(() -> "Not a registry ops")
)
.forGetter(object -> null);
}
static final class HolderLookupAdapter implements RegistryOps.RegistryInfoLookup {
private final HolderLookup.Provider lookupProvider;
private final Map<ResourceKey<? extends Registry<?>>, Optional<? extends RegistryOps.RegistryInfo<?>>> lookups = new ConcurrentHashMap();
public HolderLookupAdapter(HolderLookup.Provider lookupProvider) {
this.lookupProvider = lookupProvider;
}
@Override
public <E> Optional<RegistryOps.RegistryInfo<E>> lookup(ResourceKey<? extends Registry<? extends E>> registryKey) {
return (Optional<RegistryOps.RegistryInfo<E>>)this.lookups.computeIfAbsent(registryKey, this::createLookup);
}
private Optional<RegistryOps.RegistryInfo<Object>> createLookup(ResourceKey<? extends Registry<?>> registryKey) {
return this.lookupProvider.lookup(registryKey).map(RegistryOps.RegistryInfo::fromRegistryLookup);
}
public boolean equals(Object object) {
return this == object
? true
: object instanceof RegistryOps.HolderLookupAdapter holderLookupAdapter && this.lookupProvider.equals(holderLookupAdapter.lookupProvider);
}
public int hashCode() {
return this.lookupProvider.hashCode();
}
}
public record RegistryInfo<T>(HolderOwner<T> owner, HolderGetter<T> getter, Lifecycle elementsLifecycle) {
public static <T> RegistryOps.RegistryInfo<T> fromRegistryLookup(HolderLookup.RegistryLookup<T> registryLookup) {
return new RegistryOps.RegistryInfo<>(registryLookup, registryLookup, registryLookup.registryLifecycle());
}
}
public interface RegistryInfoLookup {
<T> Optional<RegistryOps.RegistryInfo<T>> lookup(ResourceKey<? extends Registry<? extends T>> registryKey);
}
}